├── .gitattributes ├── x ├── jwk │ ├── types │ │ ├── types.go │ │ ├── errors.go │ │ ├── keys.go │ │ ├── key_audience.go │ │ ├── codec.go │ │ ├── keys_test.go │ │ ├── genesis.go │ │ ├── genesis_test.go │ │ └── params.go │ ├── keeper │ │ ├── query.go │ │ ├── msg_server.go │ │ ├── query_params.go │ │ ├── migrations.go │ │ ├── params.go │ │ ├── keeper.go │ │ ├── query_audience.go │ │ ├── vulnerability_test.go │ │ └── audience_test.go │ ├── migrations │ │ └── v1 │ │ │ ├── migration.go │ │ │ └── migration_test.go │ ├── client │ │ └── cli │ │ │ ├── query_params.go │ │ │ ├── query.go │ │ │ ├── tx.go │ │ │ ├── util.go │ │ │ └── query_validate_jwt.go │ └── genesis.go ├── globalfee │ ├── alias.go │ ├── types │ │ ├── keys.go │ │ ├── keys_test.go │ │ ├── genesis.go │ │ └── types_test.go │ ├── README.md │ ├── keeper │ │ ├── migrations.go │ │ └── migrations_test.go │ ├── ante │ │ ├── expected_keepers.go │ │ └── ante_test.go │ ├── client │ │ └── cli │ │ │ └── query.go │ ├── migrations │ │ └── v2 │ │ │ └── migration.go │ ├── querier.go │ └── querier_test.go ├── xion │ ├── types │ │ ├── keys.go │ │ ├── errors.go │ │ ├── codec_test.go │ │ ├── errors_test.go │ │ ├── genesis.go │ │ ├── keys_test.go │ │ ├── expected_keepers.go │ │ └── codec.go │ ├── client │ │ └── cli │ │ │ ├── query.go │ │ │ ├── suite_test.go │ │ │ ├── query_platform_fee.go │ │ │ └── query_webauthn.go │ └── keeper │ │ └── genesis.go ├── mint │ └── types │ │ ├── keys.go │ │ ├── msgs.go │ │ ├── codec.go │ │ ├── expected_keepers.go │ │ ├── codec_test.go │ │ ├── params_legacy.go │ │ ├── genesis.go │ │ └── params_legacy_test.go └── feeabs │ └── types │ ├── events.go │ ├── errors.go │ ├── genesis.go │ ├── epoch.go │ ├── keys.go │ ├── events_test.go │ ├── codec_test.go │ ├── ibc.go │ └── errors_test.go ├── benchmarks ├── testdata │ ├── version.txt │ ├── cw20_base.wasm │ ├── cw1_whitelist.wasm │ └── download_releases.sh └── cw20_test.go ├── buf.lock ├── .go.work ├── contrib ├── relayer-tests │ ├── .gitignore │ ├── configs │ │ └── wasmd │ │ │ ├── chains │ │ │ ├── ibc-0.json │ │ │ └── ibc-1.json │ │ │ └── paths │ │ │ └── demo.json │ ├── README.md │ ├── test_ibc_transfer.sh │ └── init_two_chainz_relayer.sh ├── local │ ├── start_node.sh │ ├── README.md │ ├── 01-accounts.sh │ ├── 03-grpc-queries.sh │ └── setup_wasmd.sh ├── devtools │ └── README.md └── prometheus │ ├── prometheus.yaml │ └── README.md ├── .husky └── hooks │ └── pre-commit ├── client └── docs │ ├── docs.go │ └── static │ └── index.html ├── e2e_tests ├── testdata │ ├── contracts │ │ ├── zkemail.wasm │ │ ├── user_map.wasm │ │ ├── xion-account.wasm │ │ ├── tokenfactory_core.wasm │ │ ├── treasury-aarch64.wasm │ │ ├── account_updatable-aarch64.wasm │ │ ├── account_updatable-aarch64-previous.wasm │ │ └── account-wasm-updatable-event-aarch64.wasm │ ├── keys │ │ ├── public.json │ │ ├── jwtRS256.key.pub │ │ ├── zkproof.json │ │ └── vkey.json │ └── unsigned_msgs │ │ ├── bank_send_unsigned.json │ │ └── config.json ├── .gitignore ├── configuredChains.yaml └── app │ └── upgrade_test.go ├── .dockerignore ├── buf.work.yaml ├── indexer ├── errors.go ├── config.go ├── authz_decode_test.go ├── noop_service.go └── multi_raw.go ├── chains.yaml ├── proto ├── buf.gen.gogo.yaml ├── xion │ ├── jwk │ │ └── v1 │ │ │ ├── params.proto │ │ │ ├── genesis.proto │ │ │ └── audience.proto │ ├── mint │ │ └── v1 │ │ │ ├── genesis.proto │ │ │ ├── event.proto │ │ │ ├── tx.proto │ │ │ ├── mint.proto │ │ │ └── query.proto │ ├── feeabs │ │ └── v1beta1 │ │ │ ├── genesis.proto │ │ │ ├── params.proto │ │ │ └── proposal.proto │ ├── v1 │ │ ├── genesis.proto │ │ └── feegrant.proto │ └── globalfee │ │ └── v1 │ │ ├── query.proto │ │ └── genesis.proto ├── buf.gen.openapi.yaml ├── buf.yaml ├── buf.gen.pulsar.yaml └── buf.lock ├── scripts ├── README.md └── release-info.sh ├── .goreleaser └── integration.yaml ├── cmd └── xiond │ └── main.go ├── app ├── params │ ├── encoding.go │ ├── doc.go │ ├── proto.go │ ├── proto_test.go │ └── weights.go ├── genesis.go ├── xionapp.go ├── encoding.go ├── config.go ├── config_test.go └── v25_upgrade │ └── migrator.go ├── wasmbindings ├── wasm.go ├── test_utils.go ├── grpc_plugin.go ├── query_plugin.go └── whitelist_all_test.go ├── .github ├── workflows │ ├── trigger-assets.yaml │ ├── golangci-lint.yaml │ ├── tests.yaml │ ├── trigger-chain-registry.yaml │ ├── build-test.yaml │ ├── update-swagger.yaml │ ├── binaries-darwin.yaml │ ├── binaries-linux.yaml │ ├── trigger-homebrew.yaml │ ├── docker-scout.yaml │ ├── publish-release.yaml │ ├── trigger-types.yaml │ ├── heighliner-alt.yaml │ ├── build-release-info.yaml │ ├── build-release.yaml │ └── create-release.yaml └── CODEOWNERS ├── .gitignore ├── .coveragerc ├── .codecov.yml ├── make └── lint.mk └── .golangci.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /x/jwk/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | -------------------------------------------------------------------------------- /benchmarks/testdata/version.txt: -------------------------------------------------------------------------------- 1 | v0.10.0-soon4 2 | -------------------------------------------------------------------------------- /buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | -------------------------------------------------------------------------------- /.go.work: -------------------------------------------------------------------------------- 1 | go 1.25 2 | 3 | use ( 4 | . 5 | ./e2e_tests 6 | ) 7 | -------------------------------------------------------------------------------- /contrib/relayer-tests/.gitignore: -------------------------------------------------------------------------------- 1 | # Testing 2 | .relayer 3 | data 4 | -------------------------------------------------------------------------------- /.husky/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make format && make lint && make test-cover -------------------------------------------------------------------------------- /client/docs/docs.go: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import "embed" 4 | 5 | //go:embed static 6 | var Docs embed.FS 7 | -------------------------------------------------------------------------------- /benchmarks/testdata/cw20_base.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/benchmarks/testdata/cw20_base.wasm -------------------------------------------------------------------------------- /benchmarks/testdata/cw1_whitelist.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/benchmarks/testdata/cw1_whitelist.wasm -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/zkemail.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/zkemail.wasm -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/user_map.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/user_map.wasm -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/xion-account.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/xion-account.wasm -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Folders we don't want to copy to Docker daemon in `docker build . -t cosmwasm/xiond:latest` 2 | .github/ 3 | .vscode/ 4 | devnet/ 5 | -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/tokenfactory_core.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/tokenfactory_core.wasm -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/treasury-aarch64.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/treasury-aarch64.wasm -------------------------------------------------------------------------------- /x/jwk/keeper/query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/burnt-labs/xion/x/jwk/types" 5 | ) 6 | 7 | var _ types.QueryServer = Keeper{} 8 | -------------------------------------------------------------------------------- /buf.work.yaml: -------------------------------------------------------------------------------- 1 | # This workspace file points to the roots found in your 2 | # previous "buf.yaml" configuration. 3 | version: v1 4 | directories: 5 | - proto 6 | -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/account_updatable-aarch64.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/account_updatable-aarch64.wasm -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/account_updatable-aarch64-previous.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/account_updatable-aarch64-previous.wasm -------------------------------------------------------------------------------- /e2e_tests/testdata/contracts/account-wasm-updatable-event-aarch64.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burnt-labs/xion/HEAD/e2e_tests/testdata/contracts/account-wasm-updatable-event-aarch64.wasm -------------------------------------------------------------------------------- /contrib/local/start_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | wasmd start --rpc.laddr tcp://0.0.0.0:26657 --log_level=info --trace #remove trace flag if you don't wantg the stack trace to be printed 5 | -------------------------------------------------------------------------------- /indexer/errors.go: -------------------------------------------------------------------------------- 1 | package indexer 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrGrantNotFound = errors.New("grant not found") 7 | ErrAllowanceNotFound = errors.New("allowance not found") 8 | ) 9 | -------------------------------------------------------------------------------- /e2e_tests/testdata/keys/public.json: -------------------------------------------------------------------------------- 1 | [ 2 | "17159366307350401517208657413587014704131356894001302493847352957889395820464", 3 | "6632353713085157925504008443078919716322386156160602218536961028046468237192" 4 | ] -------------------------------------------------------------------------------- /x/globalfee/alias.go: -------------------------------------------------------------------------------- 1 | package globalfee 2 | 3 | import ( 4 | "github.com/burnt-labs/xion/x/globalfee/types" 5 | ) 6 | 7 | const ( 8 | ModuleName = types.ModuleName 9 | 10 | StoreKey = ModuleName 11 | ) 12 | -------------------------------------------------------------------------------- /contrib/relayer-tests/configs/wasmd/chains/ibc-0.json: -------------------------------------------------------------------------------- 1 | {"key":"testkey","chain-id":"ibc-0","rpc-addr":"http://localhost:26657","account-prefix":"wasm","gas-adjustment":1.5,"gas-prices":"0.025stake","trusting-period":"336h"} 2 | -------------------------------------------------------------------------------- /contrib/relayer-tests/configs/wasmd/chains/ibc-1.json: -------------------------------------------------------------------------------- 1 | {"key":"testkey","chain-id":"ibc-1","rpc-addr":"http://localhost:26557","account-prefix":"wasm","gas-adjustment":1.5,"gas-prices":"0.025stake", "trusting-period":"336h"} 2 | -------------------------------------------------------------------------------- /x/globalfee/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is the name of the this module 5 | ModuleName = "globalfee" 6 | 7 | StoreKey = ModuleName 8 | 9 | QuerierRoute = ModuleName 10 | ) 11 | -------------------------------------------------------------------------------- /x/jwk/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DONTCOVER 4 | 5 | import ( 6 | errorsmod "cosmossdk.io/errors" 7 | ) 8 | 9 | // x/jwk module sentinel errors 10 | var ( 11 | ErrInvalidJWK = errorsmod.Register(ModuleName, 1100, "invalid jwk") 12 | ) 13 | -------------------------------------------------------------------------------- /contrib/devtools/README.md: -------------------------------------------------------------------------------- 1 | ## Contributors 2 | 3 | Thanks to the entire Cosmos SDK team and the contributors who put their efforts into making simulation testing 4 | easier to implement. 🤗 5 | 6 | https://github.com/cosmos/cosmos-sdk/blob/master/contrib/devtools/Makefile -------------------------------------------------------------------------------- /chains.yaml: -------------------------------------------------------------------------------- 1 | # Xion 2 | - name: xion 3 | github-organization: burnt-labs 4 | github-repo: xion 5 | dockerfile: cosmos 6 | pre-build: 7 | apk add --no-cache binutils-gold 8 | build-target: make install 9 | binaries: 10 | - /go/bin/xiond 11 | build-env: 12 | - BUILD_TAGS=muslc 13 | -------------------------------------------------------------------------------- /contrib/relayer-tests/configs/wasmd/paths/demo.json: -------------------------------------------------------------------------------- 1 | {"src":{"chain-id":"ibc-0","client-id":"","connection-id":"","channel-id":"","port-id":"transfer","order":"unordered","version":"ics20-1"},"dst":{"chain-id":"ibc-1","client-id":"","connection-id":"","channel-id":"","port-id":"transfer","order":"unordered","version":"ics20-1"},"strategy":{"type":"naive"}} 2 | -------------------------------------------------------------------------------- /proto/buf.gen.gogo.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: gocosmos 4 | out: .. 5 | opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/feegrant/v1beta1/feegrant.proto=cosmossdk.io/x/feegrant 6 | - name: grpc-gateway 7 | out: .. 8 | opt: logtostderr=true,allow_colon_final_segments=true 9 | 10 | -------------------------------------------------------------------------------- /contrib/prometheus/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s # By default, scrape targets every 15 seconds. 3 | evaluation_interval: 15s # By default, scrape targets every 15 seconds. 4 | rule_files: 5 | 6 | scrape_configs: 7 | - job_name: xiond 8 | 9 | scrape_interval: 5s 10 | static_configs: 11 | - targets: ['host.docker.internal:26660'] -------------------------------------------------------------------------------- /x/jwk/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName defines the module name 5 | ModuleName = "jwk" 6 | 7 | // StoreKey defines the primary module store key 8 | StoreKey = ModuleName 9 | 10 | // RouterKey defines the module's message routing key 11 | RouterKey = ModuleName 12 | ) 13 | 14 | func KeyPrefix(p string) []byte { 15 | return []byte(p) 16 | } 17 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # Scripts 2 | 3 | These scripts are copied from the [Cosmos-SDK](https://github.com/cosmos/cosmos-sdk/tree/v0.42.1/scripts) repository 4 | with minor modifications. All credits and big thanks go to the original authors. 5 | 6 | Please note that a custom [fork](github.com/regen-network/protobuf) by the Regen network team is used. 7 | See [`go.mod`](../go.mod) for version. 8 | -------------------------------------------------------------------------------- /x/jwk/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/burnt-labs/xion/x/jwk/types" 5 | ) 6 | 7 | type msgServer struct { 8 | Keeper 9 | } 10 | 11 | // NewMsgServerImpl returns an implementation of the MsgServer interface 12 | // for the provided Keeper. 13 | func NewMsgServerImpl(keeper Keeper) types.MsgServer { 14 | return &msgServer{Keeper: keeper} 15 | } 16 | 17 | var _ types.MsgServer = msgServer{} 18 | -------------------------------------------------------------------------------- /.goreleaser/integration.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | project_name: tests 4 | 5 | # Docs: https://goreleaser.com/customization/build/ 6 | builds: 7 | - id: tests 8 | goos: 9 | - linux 10 | - darwin 11 | goarch: 12 | - arm64 13 | - amd64 14 | command: test 15 | dir: e2e_tests 16 | binary: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}" 17 | no_unique_dist_dir: true 18 | no_main_check: true 19 | -------------------------------------------------------------------------------- /x/globalfee/README.md: -------------------------------------------------------------------------------- 1 | # Global fee module 2 | 3 | The Global fee module is based on [Gaia's implementation](https://github.com/cosmos/gaia). Which is supplied by the great folks at [TGrade](https://github.com/confio/tgrade) 👋, with minor modifications. All credits and big thanks go to the original authors. 4 | 5 | More information about Cosmoshub fee system please check [here](https://github.com/cosmos/gaia/blob/v17.3.0/docs/docs/modules/globalfee.md). 6 | -------------------------------------------------------------------------------- /cmd/xiond/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "cosmossdk.io/log" 7 | 8 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 9 | 10 | "github.com/burnt-labs/xion/app" 11 | ) 12 | 13 | func main() { 14 | rootCmd, _ := NewRootCmd() 15 | 16 | if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { 17 | log.NewLogger(rootCmd.OutOrStderr()).Error("failure when running app", "err", err) 18 | os.Exit(1) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /e2e_tests/.gitignore: -------------------------------------------------------------------------------- 1 | # OS artifacts 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | 6 | # Test binaries and executables 7 | *.test 8 | *.out 9 | e2e_tests 10 | e2e_tests.test 11 | 12 | # Coverage reports 13 | coverage.txt 14 | coverage*.out 15 | coverage*.html 16 | profile.out 17 | 18 | # Test data and artifacts 19 | *.log 20 | xion-data/ 21 | .testnode/ 22 | 23 | # Temporary files 24 | tmp/ 25 | temp/ 26 | *.tmp 27 | 28 | # Go workspace files (if any) 29 | go.work 30 | go.work.sum 31 | 32 | *TEST_COVERAGE.md 33 | -------------------------------------------------------------------------------- /x/xion/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | var ( 4 | PlatformPercentageKey = []byte{0x00} 5 | PlatformMinimumKey = []byte{0x01} 6 | ) 7 | 8 | const ( 9 | // ModuleName is the module name constant used in many places 10 | ModuleName = "xion" 11 | 12 | // StoreKey is the store key string for oracle 13 | StoreKey = ModuleName 14 | 15 | // RouterKey is the message route for oracle 16 | RouterKey = ModuleName 17 | 18 | // QuerierRoute is the querier route for oracle 19 | QuerierRoute = ModuleName 20 | ) 21 | -------------------------------------------------------------------------------- /x/mint/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | var ( 4 | // MinterKey is the key to use for the keeper store. 5 | MinterKey = []byte{0x00} 6 | ParamsKey = []byte{0x01} 7 | ) 8 | 9 | const ( 10 | // module name 11 | ModuleName = "mint" 12 | 13 | // StoreKey is the default store key for mint 14 | StoreKey = ModuleName 15 | 16 | // Query endpoints supported by the minting querier 17 | QueryParameters = "parameters" 18 | QueryInflation = "inflation" 19 | QueryAnnualProvisions = "annual_provisions" 20 | ) 21 | -------------------------------------------------------------------------------- /x/globalfee/types/keys_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestModuleConstants(t *testing.T) { 10 | require.Equal(t, "globalfee", ModuleName) 11 | require.Equal(t, "globalfee", StoreKey) 12 | require.Equal(t, "globalfee", QuerierRoute) 13 | } 14 | 15 | func TestConstantsAreConsistent(t *testing.T) { 16 | // Ensure all constants are consistent with each other 17 | require.Equal(t, ModuleName, StoreKey) 18 | require.Equal(t, ModuleName, QuerierRoute) 19 | } 20 | -------------------------------------------------------------------------------- /benchmarks/testdata/download_releases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | command -v shellcheck > /dev/null && shellcheck "$0" 4 | 5 | if [ $# -ne 1 ]; then 6 | echo "Usage: ./download_releases.sh RELEASE_TAG" 7 | exit 1 8 | fi 9 | 10 | tag="$1" 11 | 12 | for contract in cw20_base cw1_whitelist; do 13 | url="https://github.com/CosmWasm/cw-plus/releases/download/$tag/${contract}.wasm" 14 | echo "Downloading $url ..." 15 | wget -O "${contract}.wasm" "$url" 16 | done 17 | 18 | rm -f version.txt 19 | echo "$tag" >version.txt -------------------------------------------------------------------------------- /proto/xion/jwk/v1/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.jwk.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/burnt-labs/xion/x/jwk/types"; 7 | 8 | // Params defines the parameters for the module. 9 | message Params { 10 | // Time offset in nanoseconds for JWT validation 11 | uint64 time_offset = 1 [ (gogoproto.moretags) = "yaml:\"time_offset\"" ]; 12 | // Gas required to deploy a new project/audience 13 | uint64 deployment_gas = 2 14 | [ (gogoproto.moretags) = "yaml:\"deployment_gas\"" ]; 15 | } 16 | -------------------------------------------------------------------------------- /proto/xion/jwk/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package xion.jwk.v1; 4 | 5 | import "gogoproto/gogo.proto"; 6 | import "xion/jwk/v1/params.proto"; 7 | import "xion/jwk/v1/audience.proto"; 8 | 9 | option go_package = "github.com/burnt-labs/xion/x/jwk/types"; 10 | 11 | // GenesisState defines the jwk module's genesis state. 12 | message GenesisState { 13 | // The module parameters 14 | Params params = 1 [ (gogoproto.nullable) = false ]; 15 | // List of all audiences 16 | repeated Audience audience_list = 2 [ (gogoproto.nullable) = false ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/params/encoding.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/client" 5 | "github.com/cosmos/cosmos-sdk/codec" 6 | "github.com/cosmos/cosmos-sdk/codec/types" 7 | ) 8 | 9 | // EncodingConfig specifies the concrete encoding types to use for a given app. 10 | // This is provided for compatibility between protobuf and amino implementations. 11 | type EncodingConfig struct { 12 | InterfaceRegistry types.InterfaceRegistry 13 | Codec codec.Codec 14 | TxConfig client.TxConfig 15 | Amino *codec.LegacyAmino 16 | } 17 | -------------------------------------------------------------------------------- /wasmbindings/wasm.go: -------------------------------------------------------------------------------- 1 | package wasmbinding 2 | 3 | import ( 4 | wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | ) 9 | 10 | func RegisterStargateQueries(queryRouter baseapp.GRPCQueryRouter, codec codec.Codec) []wasmkeeper.Option { 11 | queryPluginOpt := wasmkeeper.WithQueryPlugins(&wasmkeeper.QueryPlugins{ 12 | Stargate: StargateQuerier(queryRouter, codec), 13 | Grpc: GrpcQuerier(queryRouter), 14 | }) 15 | 16 | return []wasmkeeper.Option{ 17 | queryPluginOpt, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /proto/xion/jwk/v1/audience.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.jwk.v1; 3 | 4 | option go_package = "github.com/burnt-labs/xion/x/jwk/types"; 5 | 6 | // Audience represents a JWT audience configuration 7 | message Audience { 8 | // The audience identifier 9 | string aud = 1; 10 | // The public key associated with this audience 11 | string key = 2; 12 | // The admin address for this audience 13 | string admin = 3; 14 | } 15 | 16 | // AudienceClaim represents a claim for an audience 17 | message AudienceClaim { 18 | // The signer of the audience claim 19 | string signer = 1; 20 | } -------------------------------------------------------------------------------- /contrib/local/README.md: -------------------------------------------------------------------------------- 1 | # Dev scripts 2 | For manual testing. Works on my box(*) ... 3 | 4 | 5 | *) OSX 6 | 7 | ``` 8 | make install 9 | cd contrib/local 10 | rm -rf /tmp/trash 11 | HOME=/tmp/trash bash setup_wasmd.sh 12 | HOME=/tmp/trash bash start_node.sh 13 | ``` 14 | 15 | Next shell: 16 | 17 | ``` 18 | cd contrib/local 19 | ./01-accounts.sh 20 | ./02-contracts.sh 21 | ``` 22 | 23 | ## Shell script development 24 | 25 | [Use `shellcheck`](https://www.shellcheck.net/) to avoid common mistakes in shell scripts. 26 | [Use `shfmt`](https://github.com/mvdan/sh) to ensure a consistent code formatting. 27 | -------------------------------------------------------------------------------- /x/feeabs/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | EventTypeTimeout = "timeout" 5 | EventTypePacket = "receive_feechain_verification_packet" 6 | EventTypeEpochEnd = "epoch_end" // TODO: need to clean up (not use) 7 | EventTypeEpochStart = "epoch_start" 8 | AttributeKeyAckSuccess = "success" 9 | AttributeKeyAck = "acknowledgement" 10 | AttributeKeyAckError = "ack_error" 11 | AttributeEpochNumber = "epoch_number" 12 | AttributeEpochStartTime = "start_time" 13 | AttributeKeyFailureType = "failure_type" 14 | AttributeKeyPacket = "packet" 15 | ) 16 | -------------------------------------------------------------------------------- /benchmarks/cw20_test.go: -------------------------------------------------------------------------------- 1 | package benchmarks 2 | 3 | type cw20InitMsg struct { 4 | Name string `json:"name"` 5 | Symbol string `json:"symbol"` 6 | Decimals uint8 `json:"decimals"` 7 | InitialBalances []balance `json:"initial_balances"` 8 | } 9 | 10 | type balance struct { 11 | Address string `json:"address"` 12 | Amount uint64 `json:"amount,string"` 13 | } 14 | 15 | type cw20ExecMsg struct { 16 | Transfer *transferMsg `json:"transfer,omitempty"` 17 | } 18 | 19 | type transferMsg struct { 20 | Recipient string `json:"recipient"` 21 | Amount uint64 `json:"amount,string"` 22 | } 23 | -------------------------------------------------------------------------------- /contrib/relayer-tests/README.md: -------------------------------------------------------------------------------- 1 | # Relayer tests 2 | 3 | These scripts helps to test go-relayer with two local wasmd chains. \ 4 | Make sure you run below scripts under `wasmd/contrib/relayer-tests` directory. 5 | 6 | - `./init_two_chainz_relayer.sh` will spin two chains and runs 7 | - `./one_chain.sh` will spin a single chain. This script used by the one above 8 | - `./test_ibc_transfer.sh` will setup a path between chains and send tokens between chains. 9 | 10 | ## Thank you 11 | The setup scripts here are taken from [cosmos/relayer](https://github.com/cosmos/relayer) 12 | Thank your relayer team for these scripts. 13 | 14 | 15 | -------------------------------------------------------------------------------- /x/jwk/keeper/query_params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | 11 | "github.com/burnt-labs/xion/x/jwk/types" 12 | ) 13 | 14 | func (k Keeper) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 15 | if req == nil { 16 | return nil, status.Error(codes.InvalidArgument, "invalid request") 17 | } 18 | ctx := sdk.UnwrapSDKContext(goCtx) 19 | 20 | params := k.GetParams(ctx) 21 | 22 | return &types.QueryParamsResponse{Params: params}, nil 23 | } 24 | -------------------------------------------------------------------------------- /contrib/relayer-tests/test_ibc_transfer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Ensure relayer is installed 6 | if ! [ -x "$(which rly)" ]; then 7 | echo "Error: rly is not installed." >&2 8 | exit 1 9 | fi 10 | 11 | rly tx link demo -d 12 | 13 | rly tx transfer ibc-0 ibc-1 1000000test $(rly chains address ibc-1) 14 | 15 | sleep 2 16 | 17 | EXPECTED_BALANCE="100000000000test" 18 | CHAIN_1_BALANCE=$(rly q bal ibc-1) 19 | 20 | if [[ "$CHAIN_1_BALANCE" == *"$EXPECTED_BALANCE" ]]; then 21 | echo "Token not sent correctly" 22 | echo "$EXPECTED_BALANCE not found in $CHAIN_1_BALANCE" 23 | exit 1 24 | fi 25 | 26 | echo "IBC transfer executed successfully" 27 | -------------------------------------------------------------------------------- /proto/buf.gen.openapi.yaml: -------------------------------------------------------------------------------- 1 | # buf.gen.docs.yaml - For documentation generation 2 | # This replaces the gen_swagger function from the shell script 3 | # Generates OpenAPI docs from query.proto and service.proto files 4 | version: v2 5 | plugins: 6 | - protoc_builtin: openapiv2 7 | out: . 8 | opt: logtostderr=true,fqn_for_openapi_name=true,simple_operation_ids=true 9 | # Include all query and service proto files 10 | strategy: all 11 | inputs: 12 | - directory: . 13 | exclude_paths: 14 | - "**/packet-forward-middleware/**" 15 | - "**/regen-network/protobuf/**" 16 | - "**/poa/genesis.proto" 17 | - "**/tokenfactory/v1beta1/**" 18 | -------------------------------------------------------------------------------- /proto/xion/mint/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.mint.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "xion/mint/v1/mint.proto"; 6 | import "amino/amino.proto"; 7 | 8 | option go_package = "github.com/burnt-labs/xion/x/mint/types"; 9 | 10 | // GenesisState defines the mint module's genesis state. 11 | message GenesisState { 12 | // minter is a space for holding current inflation information. 13 | Minter minter = 1 14 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 15 | 16 | // params defines all the parameters of the module. 17 | Params params = 2 18 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 19 | } 20 | -------------------------------------------------------------------------------- /app/params/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package params defines the simulation parameters in the gaia. 3 | 4 | It contains the default weights used for each transaction used on the module's 5 | simulation. These weights define the chance for a transaction to be simulated at 6 | any gived operation. 7 | 8 | You can replace the default values for the weights by providing a params.json 9 | file with the weights defined for each of the transaction operations: 10 | 11 | { 12 | "op_weight_msg_send": 60, 13 | "op_weight_msg_delegate": 100, 14 | } 15 | 16 | In the example above, the `MsgSend` has 60% chance to be simulated, while the 17 | `MsgDelegate` will always be simulated. 18 | */ 19 | package params 20 | -------------------------------------------------------------------------------- /x/jwk/keeper/migrations.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 6 | 7 | v1 "github.com/burnt-labs/xion/x/jwk/migrations/v1" 8 | ) 9 | 10 | // Migrator is a struct for handling in-place store migrations. 11 | type Migrator struct { 12 | jwkSubspace paramtypes.Subspace 13 | } 14 | 15 | // NewMigrator returns a new Migrator. 16 | func NewMigrator(jwkSubspace paramtypes.Subspace) Migrator { 17 | return Migrator{jwkSubspace} 18 | } 19 | 20 | // Migrate1To2 migrates from version 1 to 2 21 | func (m Migrator) Migrate1To2(ctx sdk.Context) error { 22 | return v1.MigrateStore(ctx, m.jwkSubspace) 23 | } 24 | -------------------------------------------------------------------------------- /contrib/local/01-accounts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | 4 | BASE_ACCOUNT=$(wasmd keys show validator -a --keyring-backend=test) 5 | wasmd q account "$BASE_ACCOUNT" -o json | jq 6 | 7 | echo "## Add new account" 8 | wasmd keys add fred --keyring-backend=test 9 | 10 | echo "## Check balance" 11 | NEW_ACCOUNT=$(wasmd keys show fred -a --keyring-backend=test) 12 | wasmd q bank balances "$NEW_ACCOUNT" -o json || true 13 | 14 | echo "## Transfer tokens" 15 | wasmd tx bank send validator "$NEW_ACCOUNT" 1ustake --gas 1000000 -y --chain-id=testing --node=http://localhost:26657 -b sync -o json --keyring-backend=test | jq 16 | 17 | echo "## Check balance again" 18 | wasmd q bank balances "$NEW_ACCOUNT" -o json | jq 19 | -------------------------------------------------------------------------------- /app/params/proto.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/cosmos/cosmos-sdk/codec/types" 6 | "github.com/cosmos/cosmos-sdk/x/auth/tx" 7 | ) 8 | 9 | // MakeEncodingConfig creates an EncodingConfig for an amino based test configuration. 10 | func MakeEncodingConfig() EncodingConfig { 11 | amino := codec.NewLegacyAmino() 12 | interfaceRegistry := types.NewInterfaceRegistry() 13 | marshaler := codec.NewProtoCodec(interfaceRegistry) 14 | txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes) 15 | 16 | return EncodingConfig{ 17 | InterfaceRegistry: interfaceRegistry, 18 | Codec: marshaler, 19 | TxConfig: txCfg, 20 | Amino: amino, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /proto/buf.yaml: -------------------------------------------------------------------------------- 1 | # This module represents buf.build/cosmos/cosmos-sdk 2 | version: v1 3 | name: buf.build/burnt-labs/xion 4 | 5 | deps: 6 | - buf.build/cosmos/cosmos-sdk 7 | - buf.build/cosmos/cosmos-proto 8 | - buf.build/cosmos/gogo-proto 9 | - buf.build/googleapis/googleapis 10 | - buf.build/tendermint/tendermint 11 | - buf.build/protocolbuffers/wellknowntypes 12 | - buf.build/burnt-labs/abstractaccount 13 | - buf.build/burnt-labs/tokenfactory 14 | breaking: 15 | use: 16 | - FILE 17 | lint: 18 | use: 19 | - STANDARD 20 | - COMMENTS 21 | - FILE_LOWER_SNAKE_CASE 22 | except: 23 | #- UNARY_RPC 24 | # - COMMENT_FIELD 25 | - SERVICE_SUFFIX 26 | # - PACKAGE_VERSION_SUFFIX 27 | - RPC_REQUEST_STANDARD_NAME 28 | -------------------------------------------------------------------------------- /x/globalfee/keeper/migrations.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 6 | 7 | v2 "github.com/burnt-labs/xion/x/globalfee/migrations/v2" 8 | ) 9 | 10 | // Migrator is a struct for handling in-place store migrations. 11 | type Migrator struct { 12 | globalfeeSubspace paramtypes.Subspace 13 | } 14 | 15 | // NewMigrator returns a new Migrator. 16 | func NewMigrator(globalfeeSubspace paramtypes.Subspace) Migrator { 17 | return Migrator{globalfeeSubspace: globalfeeSubspace} 18 | } 19 | 20 | // Migrate1to2 migrates from version 1 to 2. 21 | func (m Migrator) Migrate1to2(ctx sdk.Context) error { 22 | return v2.MigrateStore(ctx, m.globalfeeSubspace) 23 | } 24 | -------------------------------------------------------------------------------- /e2e_tests/testdata/keys/jwtRS256.key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCiWDtMXdpqL7BHgdMN7mhH5ZGESx1be747cgkeXQGIeSZHgwuyQcb0fOK9aheyWhQGcEysU3E4fTHlw0wjTuiLg95FsfJKKiBFb0Jc+Mlo2VOL6lP8iAoWzIk1ewvLOudqMuQNtBTqlGweY14vSEA5S/jyu1e/xVVZY3yiQl6EPar03ssegUA6YhQQ+D9VMdO3wr/87714xko3h4yOH/j6zFFfo1c9I9PztdGWsrgZnilR2nzorS04UuHA7hSPQmQw18jzZ5VnW0BsOWqN3yMWcBvx9abzC11pM1sv8ABeZsOGzDAk7KvDx8BFkiGtdJ0oFZrp7iTuwvBMjL447yxp5ueUBGyMay3tkLObDkoKbZy0RWXeFiEfDJe78Dms5uUytXcfQbtap4owIxVInXWyyuWyZ9WE0jC7VCW3kZiY9NMmIKAZQZHFmSAPI7KMU0eCVillqYIbIn2jKh+y6QQaioxDpbOMWL+GNVqnNeLsuL5DQ6MSikhRQMOB5SuCNsZjR6IcjqwDPmGhoPRCNz17ceTr7LtVwoJMIBqdk6UlXS8mQcH3wsEuH2oChVR6L9VosV7Yhx9WWsv/jdpeWweGv9JRBjmkc+VQxtCKET/nt2k9GHfWoNf/DrJ7x2KWeI/wmakoza4jCcnTHuF8njlBrSgseasaXNj3CL5EY/RhSQ== mv@invidia-2.local 2 | -------------------------------------------------------------------------------- /proto/xion/feeabs/v1beta1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.feeabs.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "xion/feeabs/v1beta1/params.proto"; 6 | import "xion/feeabs/v1beta1/epoch.proto"; 7 | 8 | option go_package = "github.com/burnt-labs/xion/x/feeabs/types"; 9 | 10 | // GenesisState defines the feeabs module's genesis state. 11 | message GenesisState { 12 | // params defines the parameters for the feeabs module 13 | Params params = 1 [ 14 | (gogoproto.moretags) = "yaml:\"params\"", 15 | (gogoproto.nullable) = false 16 | ]; 17 | // epochs defines the list of epoch information 18 | repeated EpochInfo epochs = 2 [ (gogoproto.nullable) = false ]; 19 | // port_id defines the IBC port identifier 20 | string port_id = 3; 21 | } 22 | -------------------------------------------------------------------------------- /proto/xion/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.v1; 3 | 4 | import "cosmos/base/v1beta1/coin.proto"; 5 | import "gogoproto/gogo.proto"; 6 | 7 | option go_package = "github.com/burnt-labs/xion/x/xion/types"; 8 | 9 | // GenesisState defines the xion module's genesis state 10 | message GenesisState { 11 | // The percentage fee taken by the platform 12 | uint32 platform_percentage = 1; 13 | // Minimum amounts required for platform operations 14 | repeated cosmos.base.v1beta1.Coin platform_minimums = 2 [ 15 | (gogoproto.nullable) = false, 16 | (gogoproto.jsontag) = "platform_minimums,omitempty", 17 | (gogoproto.moretags) = "yaml:\"platform_minimums\"", 18 | (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /proto/xion/feeabs/v1beta1/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.feeabs.v1beta1; 3 | 4 | option go_package = "github.com/burnt-labs/xion/x/feeabs/types"; 5 | 6 | // Params defines the parameters for the feeabs module. 7 | message Params { 8 | // native ibced in osmosis 9 | string native_ibced_in_osmosis = 1; 10 | 11 | // osmosis query TWAP path 12 | string osmosis_query_twap_path = 2; 13 | 14 | // chain name for ibc path unwinding 15 | string chain_name = 3; 16 | 17 | // transfer channel for cross chain swap with osmosis 18 | string ibc_transfer_channel = 4; 19 | 20 | // query twap price icq channel with osmosis 21 | string ibc_query_icq_channel = 5; 22 | 23 | // osmosis crosschain swap contract address 24 | string osmosis_crosschain_swap_address = 6; 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/trigger-assets.yaml: -------------------------------------------------------------------------------- 1 | name: Trigger Assets 2 | 3 | on: 4 | workflow_call: # is called from the create-release workflow 5 | workflow_dispatch: # manual trigger 6 | 7 | jobs: 8 | trigger-assets: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Trigger xion-assets workflow 12 | uses: peter-evans/repository-dispatch@v2 13 | with: 14 | token: ${{ secrets.REPO_DISPATCH_TOKEN }} 15 | repository: burnt-labs/xion-assets 16 | event-type: xion-assets-release-trigger # NOTICE: must match the trigger in xion-assets workflow 17 | client-payload: | 18 | { 19 | "tag_name": "${{ github.event.release.tag_name }}", 20 | "release_name": "${{ github.event.release.name }}" 21 | } 22 | 23 | -------------------------------------------------------------------------------- /x/globalfee/ante/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/cosmos/cosmos-sdk/x/auth/types" 6 | ) 7 | 8 | // AccountKeeper defines the contract needed for AccountKeeper related APIs. 9 | // Interface provides support to use non-sdk AccountKeeper for AnteHandler's decorators. 10 | type AccountKeeper interface { 11 | GetParams(ctx sdk.Context) (params types.Params) 12 | GetAccount(ctx sdk.Context, addr sdk.AccAddress) sdk.AccountI 13 | SetAccount(ctx sdk.Context, acc sdk.AccountI) 14 | GetModuleAddress(moduleName string) sdk.AccAddress 15 | } 16 | 17 | // FeegrantKeeper defines the expected feegrant keeper. 18 | type FeegrantKeeper interface { 19 | UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error 20 | } 21 | -------------------------------------------------------------------------------- /x/xion/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import errorsmod "cosmossdk.io/errors" 4 | 5 | // Codes for general xion errors 6 | const ( 7 | DefaultCodespace = ModuleName 8 | ) 9 | 10 | var ( 11 | ErrNoAllowedContracts = errorsmod.Register(DefaultCodespace, 2, "no contract addresses specified") 12 | ErrNoValidAllowances = errorsmod.Register(DefaultCodespace, 3, "none of the allowances accepted the msg") 13 | ErrInconsistentExpiry = errorsmod.Register(DefaultCodespace, 4, "multi allowances must all expire together") 14 | ErrMinimumNotMet = errorsmod.Register(DefaultCodespace, 5, "minimum send amount not met") 15 | ErrNoValidWebAuth = errorsmod.Register(DefaultCodespace, 6, "Web auth is not valid") 16 | ErrWebAuthDataTooLarge = errorsmod.Register(DefaultCodespace, 7, "WebAuth data exceeds maximum allowed size") 17 | ) 18 | -------------------------------------------------------------------------------- /.github/workflows/golangci-lint.yaml: -------------------------------------------------------------------------------- 1 | name: GoLangCI Lint 2 | 3 | # reusable workflow, do not add triggers 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | golangci: 13 | name: main 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Check out code 17 | uses: actions/checkout@v5 18 | 19 | - name: Set Go Version 20 | id: go-version 21 | run: echo "version=$(sed -En 's/^go (.*)$/\1/p' go.mod)" >> $GITHUB_OUTPUT 22 | 23 | - uses: actions/setup-go@v5 24 | with: 25 | go-version: ${{ steps.go-version.outputs.version }} 26 | 27 | - name: golangci-lint-xiond 28 | uses: golangci/golangci-lint-action@v8 29 | with: 30 | version: v2.6.1 31 | args: --timeout=10m --tests=false 32 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | 3 | # reusable workflow, do not add triggers 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v5 13 | 14 | - uses: technote-space/get-diff-action@v6 15 | with: 16 | PATTERNS: | 17 | **/**.go 18 | go.mod 19 | go.sum 20 | 21 | - name: Prepare Environment 22 | run: | 23 | sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod | tee -a $GITHUB_ENV 24 | 25 | - name: Set up Go 26 | uses: actions/setup-go@v5 27 | with: 28 | go-version: ${{ env.GO_VERSION }} 29 | 30 | - name: Build 31 | run: go build -v ./... 32 | 33 | - name: Test 34 | run: make test-cover 35 | -------------------------------------------------------------------------------- /.github/workflows/trigger-chain-registry.yaml: -------------------------------------------------------------------------------- 1 | name: Trigger Chain Registry Update 2 | 3 | on: 4 | workflow_call: # is called from the publish-release workflow 5 | workflow_dispatch: # manual trigger 6 | 7 | jobs: 8 | trigger-chain-registry: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Trigger chain-registry workflow 12 | uses: peter-evans/repository-dispatch@v2 13 | with: 14 | token: ${{ secrets.REPO_DISPATCH_TOKEN }} 15 | repository: burnt-labs/chain-registry 16 | event-type: chain-registry-update-trigger # NOTICE: must match the trigger in chain-registry workflow 17 | client-payload: | 18 | { 19 | "tag_name": "${{ github.event.release.tag_name }}", 20 | "release_name": "${{ github.event.release.name }}" 21 | } 22 | 23 | -------------------------------------------------------------------------------- /x/jwk/migrations/v1/migration.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 8 | 9 | "github.com/burnt-labs/xion/x/jwk/types" 10 | ) 11 | 12 | // MigrateStore performs in-place params migrations of 13 | // TimeOffset and DeploymentGas 14 | // 15 | // this should correct a previous migration 16 | func MigrateStore(ctx sdk.Context, jwkSubspace paramtypes.Subspace) error { 17 | ctx.Logger().Info("Running Migration to v3") 18 | defaultParams := types.DefaultParams() 19 | 20 | if !jwkSubspace.HasKeyTable() { 21 | jwkSubspace = jwkSubspace.WithKeyTable(types.ParamKeyTable()) 22 | } 23 | ctx.Logger().Info(fmt.Sprintf("setting default params to: %+v\n", defaultParams)) 24 | jwkSubspace.SetParamSet(ctx, &defaultParams) 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /x/jwk/types/key_audience.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "encoding/binary" 4 | 5 | var _ binary.ByteOrder 6 | 7 | const ( 8 | // AudienceKeyPrefix is the prefix to retrieve all Audience 9 | AudienceKeyPrefix = "Audience/value/" 10 | 11 | // AudienceClaimKeyPrefix is the prefix for audience claims 12 | AudienceClaimKeyPrefix = "AudienceClaim/value/" 13 | ) 14 | 15 | // AudienceKey returns the store key to retrieve an Audience from the index fields 16 | func AudienceKey( 17 | aud string, 18 | ) []byte { 19 | var key []byte 20 | 21 | audBytes := []byte(aud) 22 | key = append(key, audBytes...) 23 | key = append(key, []byte("/")...) 24 | 25 | return key 26 | } 27 | 28 | func AudienceClaimKey(hash []byte) []byte { 29 | var key []byte 30 | 31 | key = append(key, hash...) 32 | key = append(key, []byte("/")...) 33 | 34 | return key 35 | } 36 | -------------------------------------------------------------------------------- /e2e_tests/testdata/unsigned_msgs/bank_send_unsigned.json: -------------------------------------------------------------------------------- 1 | { 2 | "body": { 3 | "messages": [ 4 | { 5 | "@type": "/cosmos.bank.v1beta1.MsgSend", 6 | "from_address": "xion1e2fuwe3uhq8zd9nkkk876nawrwdulgv460vzg7", 7 | "to_address": "xion1qaf2xflx5j3agtlvqk5vhjpeuhl6g45hxshwqj", 8 | "amount": [ 9 | { 10 | "denom": "uxion", 11 | "amount": "100000" 12 | } 13 | ] 14 | } 15 | ], 16 | "memo": "", 17 | "timeout_height": "0", 18 | "extension_options": [], 19 | "non_critical_extension_options": [] 20 | }, 21 | "auth_info": { 22 | "signer_infos": [], 23 | "fee": { 24 | "amount": [], 25 | "gas_limit": "200000", 26 | "payer": "", 27 | "granter": "" 28 | }, 29 | "tip": null 30 | }, 31 | "signatures": [] 32 | } 33 | -------------------------------------------------------------------------------- /x/jwk/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/burnt-labs/xion/x/jwk/types" 7 | ) 8 | 9 | // GetParams get all parameters as types.Params 10 | func (k Keeper) GetParams(ctx sdk.Context) types.Params { 11 | return types.NewParams(k.GetTimeOffset(ctx), k.GetDeploymentGas(ctx)) 12 | } 13 | 14 | // SetParams set the params 15 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { 16 | k.paramspace.SetParamSet(ctx, ¶ms) 17 | } 18 | 19 | func (k Keeper) GetTimeOffset(ctx sdk.Context) uint64 { 20 | var to uint64 21 | k.paramspace.Get(ctx, types.ParamStoreKeyTimeOffset, &to) 22 | return to 23 | } 24 | 25 | func (k Keeper) GetDeploymentGas(ctx sdk.Context) uint64 { 26 | var dg uint64 27 | k.paramspace.Get(ctx, types.ParamStoreKeyDeploymentGas, &dg) 28 | return dg 29 | } 30 | -------------------------------------------------------------------------------- /app/genesis.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/types/module" 8 | ) 9 | 10 | // GenesisState of the blockchain is represented here as a map of raw json 11 | // messages key'd by a identifier string. 12 | // The identifier is used to determine which module genesis information belongs 13 | // to so it may be appropriately routed during init chain. 14 | // Within this application default genesis information is retrieved from 15 | // the ModuleBasicManager which populates json from each BasicModule 16 | // object provided to it during init. 17 | type GenesisState map[string]json.RawMessage 18 | 19 | // NewDefaultGenesisState generates the default state for the application. 20 | func NewDefaultGenesisState(cdc codec.JSONCodec, manager module.BasicManager) GenesisState { 21 | return manager.DefaultGenesis(cdc) 22 | } 23 | -------------------------------------------------------------------------------- /app/params/proto_test.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestMakeEncodingConfig(t *testing.T) { 10 | config := MakeEncodingConfig() 11 | 12 | require.NotNil(t, config) 13 | require.NotNil(t, config.InterfaceRegistry) 14 | require.NotNil(t, config.Codec) 15 | require.NotNil(t, config.TxConfig) 16 | require.NotNil(t, config.Amino) 17 | 18 | // Test that the interface registry is properly initialized 19 | require.IsType(t, config.InterfaceRegistry, config.InterfaceRegistry) 20 | 21 | // Test that the codec is properly initialized 22 | require.IsType(t, config.Codec, config.Codec) 23 | 24 | // Test that the tx config is properly initialized 25 | require.IsType(t, config.TxConfig, config.TxConfig) 26 | 27 | // Test that the amino codec is properly initialized 28 | require.IsType(t, config.Amino, config.Amino) 29 | } 30 | -------------------------------------------------------------------------------- /client/docs/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | XION API 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /x/jwk/client/cli/query_params.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | 9 | "github.com/burnt-labs/xion/x/jwk/types" 10 | ) 11 | 12 | func CmdQueryParams() *cobra.Command { 13 | cmd := &cobra.Command{ 14 | Use: "params", 15 | Short: "shows the parameters of the module", 16 | Args: cobra.NoArgs, 17 | RunE: func(cmd *cobra.Command, _ []string) error { 18 | clientCtx, err := client.GetClientQueryContext(cmd) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | queryClient := types.NewQueryClient(clientCtx) 24 | 25 | res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) 26 | if err != nil { 27 | return err 28 | } 29 | 30 | return clientCtx.PrintProto(res) 31 | }, 32 | } 33 | 34 | flags.AddQueryFlagsToCmd(cmd) 35 | 36 | return cmd 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | *.swl 6 | *.swm 7 | *.swn 8 | .vscode 9 | .idea 10 | 11 | # Build 12 | vendor 13 | build 14 | tools/bin/* 15 | examples/build/* 16 | docs/_build 17 | docs/tutorial 18 | dist 19 | tools-stamp 20 | docs/node_modules 21 | client/docs/node_modules/ 22 | client/docs/tmp-swagger-gen/ 23 | devnet/.xiond 24 | devnet/.shared 25 | 26 | # Data - ideally these don't exist 27 | baseapp/data/* 28 | client/lcd/keys/* 29 | mytestnet 30 | 31 | # Testing 32 | coverage.txt 33 | coverage*out 34 | coverage*html 35 | profile.out 36 | xion-data 37 | 38 | # Vagrant 39 | .vagrant/ 40 | *.box 41 | *.log 42 | vagrant 43 | 44 | # IDE 45 | .idea/ 46 | *.iml 47 | 48 | # Graphviz 49 | dependency-graph.png 50 | 51 | # Latex 52 | *.aux 53 | *.out 54 | *.synctex.gz 55 | contract_tests/* 56 | 57 | # Go 58 | go.work 59 | go.work.sum 60 | /integration_tests/integration_tests.test 61 | release 62 | .testnode/ 63 | -------------------------------------------------------------------------------- /e2e_tests/configuredChains.yaml: -------------------------------------------------------------------------------- 1 | ## NOTICE: This file gets embedded into interchaintest binary. 2 | ## Set the environment variable: IBCTEST_CONFIGURED_CHAINS to a path 3 | ## to use custom versions of this file 4 | 5 | osmosis: 6 | name: osmosis 7 | type: cosmos 8 | bin: osmosisd 9 | bech32-prefix: osmo 10 | denom: uosmo 11 | gas-prices: 0.0025uosmo 12 | gas-adjustment: 1.3 13 | trusting-period: 336h 14 | images: 15 | - repository: ghcr.io/strangelove-ventures/heighliner/osmosis 16 | version: v28.0.0 17 | uid-gid: 1025:1025 18 | no-host-mount: false 19 | 20 | xion: 21 | name: xion 22 | type: cosmos 23 | bin: xiond 24 | bech32-prefix: xion 25 | denom: uxion 26 | gas-prices: 0.0uxion 27 | gas-adjustment: 1.3 28 | trusting-period: 336h 29 | images: 30 | - repository: ghcr.io/burnt-labs/xion/heighliner 31 | version: v20.0.0 32 | uid-gid: 1025:1025 33 | no-host-mount: false 34 | -------------------------------------------------------------------------------- /proto/xion/globalfee/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.globalfee.v1; 3 | 4 | import "xion/globalfee/v1/genesis.proto"; 5 | import "gogoproto/gogo.proto"; 6 | import "google/api/annotations.proto"; 7 | 8 | option go_package = "github.com/burnt-labs/xion/x/globalfee/types"; 9 | 10 | // Query defines the gRPC querier service. 11 | service Query { 12 | // Params queries the parameters of the module 13 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 14 | option (google.api.http).get = "/xion/globalfee/v1/params"; 15 | } 16 | } 17 | 18 | // QueryMinimumGasPricesRequest is the request type for the 19 | // Query/MinimumGasPrices RPC method. 20 | message QueryParamsRequest {} 21 | 22 | // QueryMinimumGasPricesResponse is the response type for the 23 | // Query/MinimumGasPrices RPC method. 24 | message QueryParamsResponse { 25 | // The global fee parameters 26 | Params params = 1 [ (gogoproto.nullable) = false ]; 27 | } -------------------------------------------------------------------------------- /x/xion/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | 10 | "github.com/burnt-labs/xion/x/xion/types" 11 | ) 12 | 13 | // GetQueryCmd returns the cli query commands for this module 14 | func GetQueryCmd() *cobra.Command { 15 | // Group jwk queries under a subcommand 16 | cmd := &cobra.Command{ 17 | Use: types.ModuleName, 18 | Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), 19 | DisableFlagParsing: true, 20 | SuggestionsMinimumDistance: 2, 21 | RunE: client.ValidateCmd, 22 | } 23 | 24 | cmd.AddCommand(CmdWebAuthNVerifyRegister()) 25 | cmd.AddCommand(CmdWebAuthNVerifyAuthenticate()) 26 | cmd.AddCommand(CmdPlatformPercentage()) 27 | cmd.AddCommand(CmdPlatformMinimum()) 28 | 29 | // this line is used by starport scaffolding # 1 30 | 31 | return cmd 32 | } 33 | -------------------------------------------------------------------------------- /x/feeabs/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdkerrors "cosmossdk.io/errors" 5 | ) 6 | 7 | var ( 8 | ErrInvalidExchangeRate = sdkerrors.Register(ModuleName, 1, "invalid exchange rate") 9 | ErrInvalidIBCFees = sdkerrors.Register(ModuleName, 2, "invalid ibc fees") 10 | ErrHostZoneConfigNotFound = sdkerrors.Register(ModuleName, 3, "host zone config not found") 11 | ErrDuplicateHostZoneConfig = sdkerrors.Register(ModuleName, 4, "duplicate host zone config") 12 | ErrNotEnoughFundInModuleAddress = sdkerrors.Register(ModuleName, 5, "not have funding yet") 13 | ErrUnsupportedDenom = sdkerrors.Register(ModuleName, 6, "unsupported denom") 14 | ErrHostZoneFrozen = sdkerrors.Register(ModuleName, 7, "host zone is frozen") 15 | ErrHostZoneOutdated = sdkerrors.Register(ModuleName, 8, "host zone is outdated") 16 | 17 | ErrInvalidSigner = sdkerrors.Register(ModuleName, 9, "invalid signer") 18 | ) 19 | -------------------------------------------------------------------------------- /x/mint/types/msgs.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | var _ sdk.Msg = &MsgUpdateParams{} 10 | 11 | // GetSignBytes implements the LegacyMsg interface. 12 | func (m MsgUpdateParams) GetSignBytes() []byte { 13 | return sdk.MustSortJSON(amino.MustMarshalJSON(&m)) 14 | } 15 | 16 | // GetSigners returns the expected signers for a MsgUpdateParams message. 17 | func (m *MsgUpdateParams) GetSigners() []sdk.AccAddress { 18 | addr, _ := sdk.AccAddressFromBech32(m.Authority) 19 | return []sdk.AccAddress{addr} 20 | } 21 | 22 | // ValidateBasic does a sanity check on the provided data. 23 | func (m *MsgUpdateParams) ValidateBasic() error { 24 | if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil { 25 | return errorsmod.Wrap(err, "invalid authority address") 26 | } 27 | 28 | if err := m.Params.Validate(); err != nil { 29 | return err 30 | } 31 | 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /x/jwk/genesis.go: -------------------------------------------------------------------------------- 1 | package jwk 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/burnt-labs/xion/x/jwk/keeper" 7 | "github.com/burnt-labs/xion/x/jwk/types" 8 | ) 9 | 10 | // InitGenesis initializes the module's state from a provided genesis state. 11 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { 12 | // Set all the audience 13 | for _, elem := range genState.AudienceList { 14 | k.SetAudience(ctx, elem) 15 | } 16 | // this line is used by starport scaffolding # genesis/module/init 17 | k.SetParams(ctx, genState.Params) 18 | } 19 | 20 | // ExportGenesis returns the module's exported genesis 21 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 22 | genesis := types.DefaultGenesis() 23 | genesis.Params = k.GetParams(ctx) 24 | 25 | genesis.AudienceList = k.GetAllAudience(ctx) 26 | // this line is used by starport scaffolding # genesis/module/export 27 | 28 | return genesis 29 | } 30 | -------------------------------------------------------------------------------- /e2e_tests/testdata/keys/zkproof.json: -------------------------------------------------------------------------------- 1 | { 2 | "pi_a": [ 3 | "12507447113723412003224186427502020795233065601694475948353916367458023917378", 4 | "11647492317411203501005000400445357960526164678860073240934539412172539662393", 5 | "1" 6 | ], 7 | "pi_b": [ 8 | [ 9 | "7940549314384105696029058996970477222250722318473222306365757709950316328622", 10 | "3871803822315737814507990678305738946962434293488010314614673049872361357824" 11 | ], 12 | [ 13 | "9321628147268837332826685691496619976214340529626890605901530205644891157623", 14 | "11055633623863522550839292215199250102681676923294542571845856636912478215249" 15 | ], 16 | [ 17 | "1", 18 | "0" 19 | ] 20 | ], 21 | "pi_c": [ 22 | "14657074421768515835858985917578621239565328965402854179356218448654860572889", 23 | "13279404639268614726451606952231465882641365149672841924541768399025661321311", 24 | "1" 25 | ], 26 | "protocol": "groth16", 27 | "curve": "bn128" 28 | } -------------------------------------------------------------------------------- /contrib/local/03-grpc-queries.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | 4 | DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" 5 | 6 | echo "-----------------------" 7 | 8 | echo "### List all codes" 9 | RESP=$(grpcurl -plaintext localhost:9090 cosmwasm.wasm.v1.Query/Codes) 10 | echo "$RESP" | jq 11 | 12 | CODE_ID=$(echo "$RESP" | jq -r '.codeInfos[-1].codeId') 13 | echo "### List contracts by code" 14 | RESP=$(grpcurl -plaintext -d "{\"codeId\": $CODE_ID}" localhost:9090 cosmwasm.wasm.v1.Query/ContractsByCode) 15 | echo "$RESP" | jq 16 | 17 | echo "### Show history for contract" 18 | CONTRACT=$(echo "$RESP" | jq -r ".contracts[-1]") 19 | grpcurl -plaintext -d "{\"address\": \"$CONTRACT\"}" localhost:9090 cosmwasm.wasm.v1.Query/ContractHistory | jq 20 | 21 | echo "### Show contract state" 22 | grpcurl -plaintext -d "{\"address\": \"$CONTRACT\"}" localhost:9090 cosmwasm.wasm.v1.Query/AllContractState | jq 23 | 24 | echo "Empty state due to 'burner' contract cleanup" 25 | -------------------------------------------------------------------------------- /indexer/config.go: -------------------------------------------------------------------------------- 1 | package indexer 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cast" 7 | 8 | servertypes "github.com/cosmos/cosmos-sdk/server/types" 9 | ) 10 | 11 | // Config defines the indexer configuration. 12 | type Config struct { 13 | Enabled bool `mapstructure:"enabled" json:"enabled"` 14 | } 15 | 16 | func DefaultConfig() Config { 17 | return Config{ 18 | Enabled: false, 19 | } 20 | } 21 | 22 | // DefaultConfigTemplate returns the default TOML snippet for the indexer configuration. 23 | func DefaultConfigTemplate() string { 24 | return ConfigTemplate(DefaultConfig()) 25 | } 26 | 27 | // ConfigTemplate returns the TOML snippet for the indexer configuration. 28 | func ConfigTemplate(c Config) string { 29 | return fmt.Sprintf(` 30 | [indexer] 31 | enabled = %t 32 | `, c.Enabled) 33 | } 34 | 35 | func NewConfigFromOptions(opts servertypes.AppOptions) Config { 36 | enabled := cast.ToBool(opts.Get("indexer.enabled")) 37 | return Config{ 38 | Enabled: enabled, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /e2e_tests/testdata/unsigned_msgs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "grant_config": [ 3 | { 4 | "msg_type_url": "/cosmos.bank.v1.MsgSend", 5 | "grant_config": { 6 | "description": "Bank grant", 7 | "authorization": { 8 | "type_url": "/cosmos.authz.v1.GenericAuthorization", 9 | "value": "CgRQYXk=" 10 | }, 11 | "optional": true 12 | } 13 | }, 14 | { 15 | "msg_type_url": "/cosmos.staking.v1.MsgDelegate", 16 | "grant_config": { 17 | "description": "Staking grant", 18 | "authorization": { 19 | "type_url": "/cosmos.authz.v1.GenericAuthorization", 20 | "value": "CgREZWxlZ2F0ZQ==" 21 | }, 22 | "optional": false 23 | } 24 | } 25 | ], 26 | "fee_config": { 27 | "description": "Fee allowance for user1", 28 | "allowance": { 29 | "type_url": "/cosmos.feegrant.v1.BasicAllowance", 30 | "value": "CgQICAI=" 31 | }, 32 | "expiration": 1715151235 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /x/xion/types/codec_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | "github.com/cosmos/cosmos-sdk/codec/types" 10 | 11 | xionTypes "github.com/burnt-labs/xion/x/xion/types" 12 | ) 13 | 14 | func TestRegisterLegacyAminoCodec(t *testing.T) { 15 | cdc := codec.NewLegacyAmino() 16 | 17 | // Should not panic 18 | require.NotPanics(t, func() { 19 | xionTypes.RegisterLegacyAminoCodec(cdc) 20 | }) 21 | } 22 | 23 | func TestRegisterInterfaces(t *testing.T) { 24 | registry := types.NewInterfaceRegistry() 25 | 26 | // Should not panic 27 | require.NotPanics(t, func() { 28 | xionTypes.RegisterInterfaces(registry) 29 | }) 30 | 31 | // Test that some interfaces are registered 32 | require.NotNil(t, registry) 33 | } 34 | 35 | func TestCodecInit(t *testing.T) { 36 | // Test that init function runs without panic 37 | // This is implicitly tested by importing the package 38 | require.True(t, true) 39 | } 40 | -------------------------------------------------------------------------------- /x/jwk/keeper/keeper.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "fmt" 5 | 6 | "cosmossdk.io/log" 7 | storetypes "cosmossdk.io/store/types" 8 | 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 12 | 13 | "github.com/burnt-labs/xion/x/jwk/types" 14 | ) 15 | 16 | type ( 17 | Keeper struct { 18 | cdc codec.BinaryCodec 19 | storeKey storetypes.StoreKey 20 | paramspace paramtypes.Subspace 21 | } 22 | ) 23 | 24 | func NewKeeper( 25 | cdc codec.BinaryCodec, 26 | storeKey storetypes.StoreKey, 27 | ps paramtypes.Subspace, 28 | ) Keeper { 29 | // set KeyTable if it has not already been set 30 | if !ps.HasKeyTable() { 31 | ps = ps.WithKeyTable(types.ParamKeyTable()) 32 | } 33 | 34 | return Keeper{ 35 | cdc: cdc, 36 | storeKey: storeKey, 37 | paramspace: ps, 38 | } 39 | } 40 | 41 | func (k Keeper) Logger(ctx sdk.Context) log.Logger { 42 | return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) 43 | } 44 | -------------------------------------------------------------------------------- /x/jwk/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | 10 | "github.com/burnt-labs/xion/x/jwk/types" 11 | ) 12 | 13 | // GetQueryCmd returns the cli query commands for this module 14 | func GetQueryCmd() *cobra.Command { 15 | // Group jwk queries under a subcommand 16 | cmd := &cobra.Command{ 17 | Use: types.ModuleName, 18 | Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), 19 | DisableFlagParsing: true, 20 | SuggestionsMinimumDistance: 2, 21 | RunE: client.ValidateCmd, 22 | } 23 | 24 | cmd.AddCommand(CmdQueryParams()) 25 | cmd.AddCommand(CmdListAudience()) 26 | cmd.AddCommand(CmdShowAudience()) 27 | cmd.AddCommand(CmdShowAudienceClaim()) 28 | cmd.AddCommand(CmdValidateJWT()) 29 | 30 | // utils, not sure where best to put this 31 | cmd.AddCommand(CmdConvertPemToJSON()) 32 | 33 | // this line is used by starport scaffolding # 1 34 | 35 | return cmd 36 | } 37 | -------------------------------------------------------------------------------- /x/jwk/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/types/msgservice" 8 | ) 9 | 10 | func RegisterCodec(cdc *codec.LegacyAmino) { 11 | cdc.RegisterConcrete(&MsgCreateAudience{}, "jwk/CreateAudience", nil) 12 | cdc.RegisterConcrete(&MsgUpdateAudience{}, "jwk/UpdateAudience", nil) 13 | cdc.RegisterConcrete(&MsgDeleteAudience{}, "jwk/DeleteAudience", nil) 14 | // this line is used by starport scaffolding # 2 15 | } 16 | 17 | func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 18 | registry.RegisterImplementations((*sdk.Msg)(nil), 19 | &MsgCreateAudience{}, 20 | &MsgUpdateAudience{}, 21 | &MsgDeleteAudience{}, 22 | ) 23 | // this line is used by starport scaffolding # 3 24 | 25 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 26 | } 27 | 28 | var ( 29 | Amino = codec.NewLegacyAmino() 30 | ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) 31 | ) 32 | -------------------------------------------------------------------------------- /x/feeabs/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "fmt" 4 | 5 | // DefaultGenesis returns the incentive module's default genesis state. 6 | func DefaultGenesis() *GenesisState { 7 | return &GenesisState{ 8 | Params: Params{ 9 | OsmosisQueryTwapPath: DefaultOsmosisQueryTwapPath, 10 | NativeIbcedInOsmosis: "ibc/C053D637CCA2A2BA030E2C5EE1B28A16F71CCB0E45E8BE52766DC1B241B77878", 11 | ChainName: DefaultChainName, 12 | }, 13 | Epochs: []EpochInfo{NewGenesisEpochInfo(DefaultQueryEpochIdentifier, DefaultQueryPeriod), NewGenesisEpochInfo(DefaultSwapEpochIdentifier, DefaultSwapPeriod)}, 14 | PortId: IBCPortID, 15 | } 16 | } 17 | 18 | // Validate performs basic genesis state validation, returning an error upon any failure. 19 | func (gs GenesisState) Validate() error { 20 | err := gs.Params.Validate() 21 | if err != nil { 22 | return fmt.Errorf("invalid params %s", err) 23 | } 24 | 25 | // Validate epochs genesis 26 | for _, epoch := range gs.Epochs { 27 | err := epoch.Validate() 28 | if err != nil { 29 | return err 30 | } 31 | } 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /x/jwk/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | 11 | // "github.com/cosmos/cosmos-sdk/client/flags" 12 | "github.com/burnt-labs/xion/x/jwk/types" 13 | ) 14 | 15 | var DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds()) 16 | 17 | // GetTxCmd returns the transaction commands for this module 18 | func GetTxCmd() *cobra.Command { 19 | cmd := &cobra.Command{ 20 | Use: types.ModuleName, 21 | Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), 22 | DisableFlagParsing: true, 23 | SuggestionsMinimumDistance: 2, 24 | RunE: client.ValidateCmd, 25 | } 26 | 27 | cmd.AddCommand(CmdCreateAudienceClaim()) 28 | cmd.AddCommand(CmdCreateAudience()) 29 | cmd.AddCommand(CmdUpdateAudience()) 30 | cmd.AddCommand(CmdDeleteAudience()) 31 | cmd.AddCommand(CmdDeleteAudienceClaim()) 32 | // this line is used by starport scaffolding # 1 33 | 34 | return cmd 35 | } 36 | -------------------------------------------------------------------------------- /app/xionapp.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gorilla/mux" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | 10 | "github.com/burnt-labs/xion/client/docs" 11 | ) 12 | 13 | // RegisterSwaggerAPI registers swagger route with API Server 14 | func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router, swaggerEnabled bool) error { 15 | if swaggerEnabled { 16 | docsServer := http.FileServer(http.FS(docs.Docs)) 17 | rtr.Handle("/static", docsServer) 18 | rtr.Handle("/static/", docsServer) 19 | rtr.Handle("/static/swagger.json", docsServer) 20 | rtr.Handle("/static/openapi.json", docsServer) 21 | 22 | rtr.PathPrefix("/static").Handler(http.StripPrefix("/static/", docsServer)) 23 | rtr.PathPrefix("/static/").Handler(http.StripPrefix("/static/", docsServer)) 24 | 25 | rtr.Handle("/", http.RedirectHandler("/static/", http.StatusMovedPermanently)) 26 | rtr.Handle("/swagger", http.RedirectHandler("/static/", http.StatusMovedPermanently)) 27 | rtr.Handle("/swagger/", http.RedirectHandler("/static/", http.StatusMovedPermanently)) 28 | } 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /x/xion/keeper/genesis.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "encoding/binary" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/burnt-labs/xion/x/xion/types" 9 | ) 10 | 11 | // InitGenesis initializes the bank module's state from a given genesis state. 12 | func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { 13 | k.OverwritePlatformPercentage(ctx, genState.PlatformPercentage) 14 | err := k.OverwritePlatformMinimum(ctx, genState.PlatformMinimums) 15 | if err != nil { 16 | panic(err) 17 | } 18 | } 19 | 20 | // ExportGenesis returns the bank module's genesis state. 21 | func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { 22 | bz := ctx.KVStore(k.storeKey).Get(types.PlatformPercentageKey) 23 | // Read as uint64 (8 bytes) since that's how it's stored, then convert to uint32 24 | platformPercentage := uint32(binary.BigEndian.Uint64(bz)) 25 | 26 | platformMinimums, err := k.GetPlatformMinimums(ctx) 27 | if err != nil { 28 | panic(err) 29 | } 30 | rv := types.NewGenesisState(platformPercentage, platformMinimums) 31 | return rv 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/build-test.yaml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | pull_request: 7 | branches: 8 | - main 9 | - release/* 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | lint: 17 | name: Golang CI Lint 18 | uses: burnt-labs/xion/.github/workflows/golangci-lint.yaml@workflows/main 19 | secrets: inherit 20 | 21 | update-swagger: 22 | name: Update Swagger 23 | uses: burnt-labs/xion/.github/workflows/update-swagger.yaml@workflows/main 24 | secrets: inherit 25 | 26 | unit-tests: 27 | name: Go Unit Tests 28 | uses: burnt-labs/xion/.github/workflows/tests.yaml@workflows/main 29 | secrets: inherit 30 | 31 | build-docker: 32 | name: Build Docker Images 33 | uses: burnt-labs/xion/.github/workflows/docker-build.yaml@workflows/main 34 | secrets: inherit 35 | 36 | e2e-tests: 37 | name: E2E tests 38 | needs: 39 | - build-docker 40 | uses: burnt-labs/xion/.github/workflows/e2e-tests.yaml@workflows/main 41 | secrets: inherit 42 | -------------------------------------------------------------------------------- /x/xion/types/errors_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/burnt-labs/xion/x/xion/types" 9 | ) 10 | 11 | func TestErrors(t *testing.T) { 12 | // Test that error constants are properly defined 13 | require.NotNil(t, types.ErrNoAllowedContracts) 14 | require.NotNil(t, types.ErrNoValidAllowances) 15 | require.NotNil(t, types.ErrInconsistentExpiry) 16 | require.NotNil(t, types.ErrMinimumNotMet) 17 | require.NotNil(t, types.ErrNoValidWebAuth) 18 | 19 | // Test error messages 20 | require.Contains(t, types.ErrNoAllowedContracts.Error(), "no contract addresses specified") 21 | require.Contains(t, types.ErrNoValidAllowances.Error(), "none of the allowances accepted the msg") 22 | require.Contains(t, types.ErrInconsistentExpiry.Error(), "multi allowances must all expire together") 23 | require.Contains(t, types.ErrMinimumNotMet.Error(), "minimum send amount not met") 24 | require.Contains(t, types.ErrNoValidWebAuth.Error(), "Web auth is not valid") 25 | 26 | // Test codespace 27 | require.Equal(t, types.ModuleName, types.DefaultCodespace) 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/update-swagger.yaml: -------------------------------------------------------------------------------- 1 | name: Update Swagger 2 | 3 | # runs on push to any branch 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | main: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | 14 | steps: 15 | - name: Check out code 16 | uses: actions/checkout@v5 17 | 18 | - name: Generate Swagger 19 | env: 20 | DOCKER_IMAGE: ghcr.io/cosmos/proto-builder:0.15.0 21 | run: | 22 | # runs as runner:docker (1001:121) 23 | chmod -R o+wX client 24 | make proto-gen-swagger 25 | chmod -R o-w client/* 26 | 27 | # Need to sort out using signed commits to use 28 | # - name: Commit if Changed 29 | # uses: stefanzweifel/git-auto-commit-action@v5 30 | # with: 31 | # commit_message: Update swagger 32 | 33 | - name: Fail on changed 34 | run: | 35 | if [[ -n "$(git status --porcelain)" ]]; then 36 | git status --porcelain 1>&2 37 | echo 'Please run `make proto-gen-swagger`' 1>&2 38 | exit 1 39 | fi 40 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | # Coverage configuration for Xion project 2 | # Format: INI-style configuration file 3 | 4 | [run] 5 | # Coverage threshold percentage (can be overridden via COVERAGE_THRESHOLD env var) 6 | threshold = 70 7 | 8 | [exclude] 9 | # Patterns to ignore in low coverage reporting 10 | # Format: file_path:pattern (grep -v compatible) 11 | 12 | # CLI commands with complex manual testing 13 | github.com/burnt-labs/xion/x/xion/client/cli/tx.go:.*NewSignCmd 14 | 15 | # WebAuthn verification (requires hardware/browser) 16 | github.com/burnt-labs/xion/x/xion/keeper/grpc_query.go:.*WebAuthNVerifyRegister 17 | 18 | # Staking inflation mint function 19 | github.com/burnt-labs/xion/x/xion/keeper/mint.go:.*StakedInflationMintFn 20 | 21 | # Indexer CLI reindex command (requires full chain context) 22 | github.com/burnt-labs/xion/indexer/client/cli/indexer.go:.*ReIndex 23 | 24 | # Wasm keeper metadata retrieval (requires full keeper setup for success path) 25 | # Error path is tested; success path needs integration test with real keeper 26 | github.com/burnt-labs/xion/app/keepers/wasm_keeper.go:.*GetXionContractMetadata 27 | 28 | github.com/burnt-labs/xion/app/v25_upgrade 29 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # # Specify a default Code Owner for all files with a wildcard: 2 | # * @default-owner 3 | 4 | # # Specify multiple Code Owners to a specific file: 5 | # README.md @doc-team @tech-lead 6 | 7 | # # Specify a Code Owner to all files with a specific extension: 8 | # *.rb @ruby-owner 9 | 10 | # # Specify Code Owners with usernames or email addresses: 11 | # LICENSE @legal janedoe@gitlab.com 12 | 13 | # # Use group names to match groups and nested groups: 14 | # README @group @group/with-nested/subgroup 15 | 16 | # # Specify a Code Owner to a directory and all its contents: 17 | # /docs/ @all-docs 18 | # /docs/* @root-docs 19 | # /docs/**/*.md @markdown-docs # Match specific file types in any subdirectory 20 | # /db/**/index.md @index-docs # Match a specific file name in any subdirectory 21 | 22 | # # Use a section to group related rules: 23 | # [Documentation] 24 | # ee/docs @docs 25 | # docs @docs 26 | 27 | # # Assign a role as a Code Owner: 28 | # /config/ @@maintainer 29 | 30 | * @burnt-labs/Burnt_Engineering/Burnt_Protocol 31 | 32 | .github/ @burnt-labs/Burnt_DevOps 33 | .goreleaser @burnt-labs/Burnt_DevOps 34 | Dockerfile @burnt-labs/Burnt_DevOps -------------------------------------------------------------------------------- /wasmbindings/test_utils.go: -------------------------------------------------------------------------------- 1 | package wasmbinding 2 | 3 | import ( 4 | "crypto/rsa" 5 | "os" 6 | 7 | "github.com/lestrrat-go/jwx/v2/jwk" 8 | ) 9 | 10 | func SetupKeys() (*rsa.PrivateKey, error) { 11 | // CreateAudience 12 | privateKeyBz, err := os.ReadFile("./keys/jwtRS256.key") 13 | if err != nil { 14 | return nil, err 15 | } 16 | jwKey, err := jwk.ParseKey(privateKeyBz, jwk.WithPEM(true)) 17 | if err != nil { 18 | return nil, err 19 | } 20 | var privateKey rsa.PrivateKey 21 | err = jwKey.Raw(&privateKey) 22 | if err != nil { 23 | return nil, err 24 | } 25 | return &privateKey, nil 26 | } 27 | 28 | func SetupPublicKeys(rsaFile ...string) (*rsa.PrivateKey, jwk.Key, error) { 29 | // CreateAudience 30 | if rsaFile[0] == "" { 31 | rsaFile[0] = "./keys/jwtRS256.key" 32 | } 33 | privateKeyBz, err := os.ReadFile(rsaFile[0]) 34 | if err != nil { 35 | return nil, nil, err 36 | } 37 | jwKey, err := jwk.ParseKey(privateKeyBz, jwk.WithPEM(true)) 38 | if err != nil { 39 | return nil, nil, err 40 | } 41 | 42 | var privateKey rsa.PrivateKey 43 | err = jwKey.Raw(&privateKey) 44 | if err != nil { 45 | return nil, nil, err 46 | } 47 | 48 | return &privateKey, jwKey, nil 49 | } 50 | -------------------------------------------------------------------------------- /app/encoding.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "testing" 5 | 6 | wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" 7 | 8 | dbm "github.com/cosmos/cosmos-db" 9 | 10 | "cosmossdk.io/log" 11 | 12 | simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 13 | 14 | "github.com/burnt-labs/xion/app/params" 15 | ) 16 | 17 | // MakeEncodingConfig creates a new EncodingConfig with all modules registered 18 | func MakeEncodingConfig(t testing.TB) params.EncodingConfig { 19 | // we "pre"-instantiate the application for getting the injected/configured encoding configuration 20 | // note, this is not necessary when using app wiring, as depinject can be directly used (see root_v2.go) 21 | tempApp := NewWasmApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, simtestutil.NewAppOptionsWithFlagHome(t.TempDir()), []wasmkeeper.Option{}) 22 | return makeEncodingConfig(tempApp) 23 | } 24 | 25 | func makeEncodingConfig(tempApp *WasmApp) params.EncodingConfig { 26 | encodingConfig := params.EncodingConfig{ 27 | InterfaceRegistry: tempApp.InterfaceRegistry(), 28 | Codec: tempApp.AppCodec(), 29 | TxConfig: tempApp.TxConfig(), 30 | Amino: tempApp.LegacyAmino(), 31 | } 32 | return encodingConfig 33 | } 34 | -------------------------------------------------------------------------------- /x/globalfee/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | ) 10 | 11 | // NewGenesisState - Create a new genesis state 12 | func NewGenesisState(params Params) *GenesisState { 13 | return &GenesisState{ 14 | Params: params, 15 | } 16 | } 17 | 18 | // DefaultGenesisState - Return a default genesis state 19 | func DefaultGenesisState() *GenesisState { 20 | return NewGenesisState(DefaultParams()) 21 | } 22 | 23 | // GetGenesisStateFromAppState returns x/auth GenesisState given raw application 24 | // genesis state. 25 | func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) *GenesisState { 26 | var genesisState GenesisState 27 | 28 | if appState[ModuleName] != nil { 29 | cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) 30 | } else { 31 | // Return default genesis state when module state is not present 32 | return DefaultGenesisState() 33 | } 34 | 35 | return &genesisState 36 | } 37 | 38 | func ValidateGenesis(data GenesisState) error { 39 | if err := data.Params.ValidateBasic(); err != nil { 40 | return errorsmod.Wrap(err, "globalfee params") 41 | } 42 | 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /x/jwk/client/cli/util.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | 7 | "github.com/lestrrat-go/jwx/v2/jwk" 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/cosmos/cosmos-sdk/client" 11 | "github.com/cosmos/cosmos-sdk/client/flags" 12 | ) 13 | 14 | func CmdConvertPemToJSON() *cobra.Command { 15 | cmd := &cobra.Command{ 16 | Use: "convert-pem [file] [alg | optional]", 17 | Short: "Convert PEM to JSON", 18 | Args: cobra.RangeArgs(1, 2), 19 | RunE: func(cmd *cobra.Command, args []string) (err error) { 20 | publicKeyBz, err := os.ReadFile(args[0]) 21 | if err != nil { 22 | return err 23 | } 24 | publicKey, err := jwk.ParseKey(publicKeyBz, jwk.WithPEM(true)) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | if len(args) == 2 { 30 | err = publicKey.Set("alg", args[1]) 31 | if err != nil { 32 | return err 33 | } 34 | } 35 | 36 | publicKeyJSON, err := json.Marshal(publicKey) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | clientCtx, err := client.GetClientQueryContext(cmd) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | return clientCtx.PrintBytes(publicKeyJSON) 47 | }, 48 | } 49 | 50 | flags.AddQueryFlagsToCmd(cmd) 51 | 52 | return cmd 53 | } 54 | -------------------------------------------------------------------------------- /x/jwk/client/cli/query_validate_jwt.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | 12 | "github.com/burnt-labs/xion/x/jwk/types" 13 | ) 14 | 15 | var _ = strconv.Itoa(0) 16 | 17 | func CmdValidateJWT() *cobra.Command { 18 | cmd := &cobra.Command{ 19 | Use: "validate-jwt [aud] [sub] [sig-bytes]", 20 | Short: "Query ValidateJWT", 21 | Args: cobra.ExactArgs(3), 22 | RunE: func(cmd *cobra.Command, args []string) (err error) { 23 | reqAud := args[0] 24 | reqSub := args[1] 25 | reqSigBytes := args[2] 26 | 27 | clientCtx, err := client.GetClientQueryContext(cmd) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | queryClient := types.NewQueryClient(clientCtx) 33 | 34 | params := &types.QueryValidateJWTRequest{ 35 | Aud: reqAud, 36 | Sub: reqSub, 37 | SigBytes: reqSigBytes, 38 | } 39 | 40 | fmt.Printf("request: %s", params) 41 | 42 | res, err := queryClient.ValidateJWT(cmd.Context(), params) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | return clientCtx.PrintProto(res) 48 | }, 49 | } 50 | 51 | flags.AddQueryFlagsToCmd(cmd) 52 | 53 | return cmd 54 | } 55 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | # 2 | # This codecov.yml is the default configuration for 3 | # all repositories on Codecov. You may adjust the settings 4 | # below in your own codecov.yml in your repository. 5 | # 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 70...100 10 | 11 | status: 12 | # Learn more at https://docs.codecov.io/docs/commit-status 13 | project: 14 | default: 15 | threshold: 1% # allow this much decrease on project 16 | app: 17 | target: 70% 18 | flags: 19 | - app 20 | modules: 21 | target: 70% 22 | flags: 23 | - modules 24 | client: 25 | flags: 26 | - client 27 | changes: false 28 | 29 | comment: 30 | layout: "reach, diff, files" 31 | behavior: default # update if exists else create new 32 | require_changes: true 33 | 34 | flags: 35 | app: 36 | paths: 37 | - "app/" 38 | modules: 39 | paths: 40 | - "x/" 41 | - "!x/**/client/" # ignore client package 42 | client: 43 | paths: 44 | - "x/**/client/" 45 | 46 | ignore: 47 | - "cmd/" 48 | - "contrib/" 49 | - "docs/" 50 | - "docker/" 51 | - "scripts/" 52 | - "*.md" 53 | - "*.rst" 54 | - "x/**/*.pb.go" 55 | - "x/**/*.pb.gw.go" 56 | - "x/**/test_common.go" 57 | - "x/**/testdata/" 58 | -------------------------------------------------------------------------------- /x/jwk/types/keys_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestModuleConstants(t *testing.T) { 10 | require.Equal(t, "jwk", ModuleName) 11 | require.Equal(t, "jwk", StoreKey) 12 | require.Equal(t, "jwk", RouterKey) 13 | } 14 | 15 | func TestConstantsAreConsistent(t *testing.T) { 16 | // Ensure all constants are consistent with each other 17 | require.Equal(t, ModuleName, StoreKey) 18 | require.Equal(t, ModuleName, RouterKey) 19 | } 20 | 21 | func TestKeyPrefix(t *testing.T) { 22 | tests := []struct { 23 | name string 24 | prefix string 25 | expected []byte 26 | }{ 27 | { 28 | name: "empty string", 29 | prefix: "", 30 | expected: []byte(""), 31 | }, 32 | { 33 | name: "simple prefix", 34 | prefix: "test", 35 | expected: []byte("test"), 36 | }, 37 | { 38 | name: "prefix with slash", 39 | prefix: "audience/", 40 | expected: []byte("audience/"), 41 | }, 42 | { 43 | name: "complex prefix", 44 | prefix: "audience/claim/", 45 | expected: []byte("audience/claim/"), 46 | }, 47 | } 48 | 49 | for _, tt := range tests { 50 | t.Run(tt.name, func(t *testing.T) { 51 | result := KeyPrefix(tt.prefix) 52 | require.Equal(t, tt.expected, result) 53 | }) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /wasmbindings/grpc_plugin.go: -------------------------------------------------------------------------------- 1 | package wasmbinding 2 | 3 | import ( 4 | "fmt" 5 | 6 | wasmvmtypes "github.com/CosmWasm/wasmvm/v3/types" 7 | 8 | abci "github.com/cometbft/cometbft/abci/types" 9 | 10 | "github.com/cosmos/gogoproto/proto" 11 | 12 | "github.com/cosmos/cosmos-sdk/baseapp" 13 | sdk "github.com/cosmos/cosmos-sdk/types" 14 | ) 15 | 16 | func GrpcQuerier(queryRouter baseapp.GRPCQueryRouter) func(ctx sdk.Context, request *wasmvmtypes.GrpcQuery) (proto.Message, error) { 17 | return func(ctx sdk.Context, request *wasmvmtypes.GrpcQuery) (proto.Message, error) { 18 | protoResponse, err := GetWhitelistedQuery(request.Path) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | route := queryRouter.Route(request.Path) 24 | if route == nil { 25 | return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("No route to query '%s'", request.Path)} 26 | } 27 | 28 | res, err := route(ctx, &abci.RequestQuery{ 29 | Data: request.Data, 30 | Path: request.Path, 31 | }) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | if res.Value == nil { 37 | return nil, fmt.Errorf("res returned from abci query route is nil") 38 | } 39 | err = proto.Unmarshal(res.Value, protoResponse) 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | return protoResponse, nil 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /x/globalfee/ante/ante_test.go: -------------------------------------------------------------------------------- 1 | package ante 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "cosmossdk.io/math" 9 | 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | // Test utility functions 14 | func TestUtilityFunctions(t *testing.T) { 15 | // Test MaxCoins function 16 | coins1 := sdk.DecCoins{sdk.NewDecCoinFromDec("uxion", math.LegacyNewDecWithPrec(1, 3))} 17 | coins2 := sdk.DecCoins{sdk.NewDecCoinFromDec("uxion", math.LegacyNewDecWithPrec(2, 3))} 18 | result := MaxCoins(coins1, coins2) 19 | expected := sdk.DecCoins{sdk.NewDecCoinFromDec("uxion", math.LegacyNewDecWithPrec(2, 3))} 20 | require.Equal(t, expected, result) 21 | 22 | // Test IsAllGT function 23 | require.True(t, IsAllGT(coins2, coins1)) 24 | require.False(t, IsAllGT(coins1, coins2)) 25 | require.False(t, IsAllGT(coins1, coins1)) 26 | 27 | // Test DenomsSubsetOf function 28 | require.True(t, DenomsSubsetOf(coins1, coins1)) 29 | subset := sdk.DecCoins{sdk.NewDecCoinFromDec("uxion", math.LegacyNewDecWithPrec(1, 3))} 30 | superset := sdk.DecCoins{ 31 | sdk.NewDecCoinFromDec("uxion", math.LegacyNewDecWithPrec(1, 3)), 32 | sdk.NewDecCoinFromDec("stake", math.LegacyNewDecWithPrec(1, 3)), 33 | }.Sort() // Ensure coins are sorted 34 | require.True(t, DenomsSubsetOf(subset, superset)) 35 | require.False(t, DenomsSubsetOf(superset, subset)) 36 | } 37 | -------------------------------------------------------------------------------- /.github/workflows/binaries-darwin.yaml: -------------------------------------------------------------------------------- 1 | name: Build Darwin Binaries 2 | 3 | # reusable workflow, do not add triggers 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-binaries: 10 | name: Build xiond-${{ matrix.os }}-${{ matrix.arch }} 11 | runs-on: 'ubuntu-latest' 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: 17 | - darwin 18 | arch: 19 | - amd64 20 | - arm64 21 | 22 | steps: 23 | - name: Check Out Code 24 | uses: actions/checkout@v5 25 | with: 26 | fetch-depth: 0 27 | 28 | - name: Set Go Version 29 | run: sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod >> $GITHUB_ENV 30 | 31 | - name: Set up Go 32 | uses: actions/setup-go@v5 33 | with: 34 | go-version: ${{ env.GO_VERSION }} 35 | 36 | - name: Build darwin Binary 37 | env: 38 | GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} 39 | run: | 40 | make build-${{ matrix.os }}-${{ matrix.arch }} 41 | 42 | - name: Upload Binary 43 | uses: actions/upload-artifact@v4 44 | with: 45 | name: xiond-${{ matrix.os }}-${{ matrix.arch }} 46 | path: dist/**/xiond-${{ matrix.os }}-${{ matrix.arch }} 47 | retention-days: 3 48 | if-no-files-found: error 49 | -------------------------------------------------------------------------------- /x/jwk/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | errorsmod "cosmossdk.io/errors" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 10 | ) 11 | 12 | // DefaultIndex is the default global index 13 | const DefaultIndex uint64 = 1 14 | 15 | // DefaultGenesis returns the default genesis state 16 | func DefaultGenesis() *GenesisState { 17 | return &GenesisState{ 18 | AudienceList: []Audience{}, 19 | // this line is used by starport scaffolding # genesis/types/default 20 | Params: DefaultParams(), 21 | } 22 | } 23 | 24 | // Validate performs basic genesis state validation returning an error upon any 25 | // failure. 26 | func (gs GenesisState) Validate() error { 27 | // Check for duplicated index in audience 28 | audienceIndexMap := make(map[string]struct{}) 29 | 30 | for _, elem := range gs.AudienceList { 31 | _, err := sdk.AccAddressFromBech32(elem.Admin) 32 | if err != nil { 33 | return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid admin address (%s)", err) 34 | } 35 | 36 | index := string(AudienceKey(elem.Aud)) 37 | if _, ok := audienceIndexMap[index]; ok { 38 | return fmt.Errorf("duplicated index for audience") 39 | } 40 | audienceIndexMap[index] = struct{}{} 41 | } 42 | // this line is used by starport scaffolding # genesis/types/validate 43 | 44 | return gs.Params.Validate() 45 | } 46 | -------------------------------------------------------------------------------- /x/xion/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | // Validate performs basic validation of supply genesis data returning an 12 | // error for any failed validation criteria. 13 | func (gs GenesisState) Validate() error { 14 | if gs.PlatformPercentage > 10000 { 15 | return errors.New("unable to set platform percentage to greater than 100%") 16 | } 17 | 18 | return nil 19 | } 20 | 21 | // NewGenesisState creates a new genesis state. 22 | func NewGenesisState(platformPercentage uint32, platformMinimums types.Coins) *GenesisState { 23 | rv := &GenesisState{ 24 | PlatformPercentage: platformPercentage, 25 | PlatformMinimums: platformMinimums, 26 | } 27 | return rv 28 | } 29 | 30 | // DefaultGenesisState returns a default bank module genesis state. 31 | func DefaultGenesisState() *GenesisState { 32 | return NewGenesisState(0, types.Coins{}) 33 | } 34 | 35 | // GetGenesisStateFromAppState returns x/bank GenesisState given raw application 36 | // genesis state. 37 | func GetGenesisStateFromAppState(cdc codec.JSONCodec, appState map[string]json.RawMessage) *GenesisState { 38 | var genesisState GenesisState 39 | 40 | if appState[ModuleName] != nil { 41 | cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) 42 | } 43 | 44 | return &genesisState 45 | } 46 | -------------------------------------------------------------------------------- /x/mint/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | "github.com/cosmos/cosmos-sdk/codec/legacy" 6 | "github.com/cosmos/cosmos-sdk/codec/types" 7 | cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | "github.com/cosmos/cosmos-sdk/types/msgservice" 10 | ) 11 | 12 | var amino = codec.NewLegacyAmino() 13 | 14 | func init() { 15 | RegisterLegacyAminoCodec(amino) 16 | cryptocodec.RegisterCrypto(amino) 17 | sdk.RegisterLegacyAminoCodec(amino) 18 | 19 | // Register all Amino interfaces and concrete types on the authz and gov Amino codec 20 | // so that this can later be used to properly serialize MsgGrant and MsgExec 21 | // instances. 22 | 23 | // RegisterLegacyAminoCodec(groupcodec.Amino) 24 | } 25 | 26 | // RegisterLegacyAminoCodec registers concrete types on the LegacyAmino codec 27 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 28 | cdc.RegisterConcrete(Params{}, "xion/x/mint/Params", nil) 29 | legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "xion/x/mint/MsgUpdateParams") 30 | } 31 | 32 | // RegisterInterfaces registers the interfaces types with the interface registry. 33 | func RegisterInterfaces(registry types.InterfaceRegistry) { 34 | registry.RegisterImplementations( 35 | (*sdk.Msg)(nil), 36 | &MsgUpdateParams{}, 37 | ) 38 | 39 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 40 | } 41 | -------------------------------------------------------------------------------- /.github/workflows/binaries-linux.yaml: -------------------------------------------------------------------------------- 1 | name: Build Linux Binaries 2 | 3 | # reusable workflow, do not add triggers 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-binaries: 10 | name: Build xiond-${{ matrix.os }}-${{ matrix.arch }} 11 | runs-on: ${{ matrix.arch == 'arm64' && format('github-{0}', matrix.arch) || 'ubuntu-latest' }} 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | os: 17 | - linux 18 | arch: 19 | - amd64 20 | - arm64 21 | 22 | steps: 23 | - name: Check Out Code 24 | uses: actions/checkout@v5 25 | with: 26 | fetch-depth: 0 27 | 28 | - name: Set Go Version 29 | run: sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod >> $GITHUB_ENV 30 | 31 | - name: Set up Go 32 | uses: actions/setup-go@v5 33 | with: 34 | go-version: ${{ env.GO_VERSION }} 35 | 36 | - name: Build Linux Binary 37 | env: 38 | GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} 39 | run: | 40 | make build-${{ matrix.os }}-${{ matrix.arch }} 41 | 42 | - name: Upload Binary 43 | uses: actions/upload-artifact@v4 44 | with: 45 | name: xiond-${{ matrix.os }}-${{ matrix.arch }} 46 | path: dist/**/xiond-${{ matrix.os }}-${{ matrix.arch }} 47 | retention-days: 3 48 | if-no-files-found: error 49 | -------------------------------------------------------------------------------- /x/xion/types/keys_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/burnt-labs/xion/x/xion/types" 9 | ) 10 | 11 | func TestKeys(t *testing.T) { 12 | // Test PlatformPercentageKey 13 | require.NotNil(t, types.PlatformPercentageKey) 14 | require.Equal(t, []byte{0x00}, types.PlatformPercentageKey) 15 | 16 | // Test PlatformMinimumKey 17 | require.NotNil(t, types.PlatformMinimumKey) 18 | require.Equal(t, []byte{0x01}, types.PlatformMinimumKey) 19 | } 20 | 21 | func TestConstants(t *testing.T) { 22 | // Test ModuleName 23 | require.Equal(t, "xion", types.ModuleName) 24 | 25 | // Test StoreKey 26 | require.Equal(t, types.ModuleName, types.StoreKey) 27 | require.Equal(t, "xion", types.StoreKey) 28 | 29 | // Test RouterKey 30 | require.Equal(t, types.ModuleName, types.RouterKey) 31 | require.Equal(t, "xion", types.RouterKey) 32 | 33 | // Test QuerierRoute 34 | require.Equal(t, types.ModuleName, types.QuerierRoute) 35 | require.Equal(t, "xion", types.QuerierRoute) 36 | 37 | // Test all constants are consistent 38 | require.Equal(t, types.ModuleName, types.StoreKey) 39 | require.Equal(t, types.ModuleName, types.RouterKey) 40 | require.Equal(t, types.ModuleName, types.QuerierRoute) 41 | } 42 | 43 | func TestKeyUniqueness(t *testing.T) { 44 | // Ensure keys are unique 45 | require.NotEqual(t, types.PlatformPercentageKey, types.PlatformMinimumKey) 46 | } 47 | -------------------------------------------------------------------------------- /make/lint.mk: -------------------------------------------------------------------------------- 1 | # Linting and formatting targets 2 | 3 | # Install formatting tools 4 | format-tools: 5 | go install mvdan.cc/gofumpt@v0.4.0 6 | go install github.com/client9/misspell/cmd/misspell@v0.3.4 7 | go install golang.org/x/tools/cmd/goimports@latest 8 | 9 | # Lint Go code 10 | lint: format-tools 11 | golangci-lint run --tests=false 12 | find . -name '*.go' -type f -not -path "./api/*" -not -path "*.git*" -not -path "*_test.go" -not -path "*.pb.go" -not -path "*.pb.gw.go" | xargs gofumpt -d 13 | 14 | # Format Go code 15 | format: format-tools 16 | golangci-lint run --fix 17 | find . -name '*.go' -type f -not -path "./api/*" -not -path "*.git*" -not -path "*.pb.go" -not -path "*.pb.gw.go" | xargs gofumpt -w 18 | find . -name '*.go' -type f -not -path "./api/*" -not -path "*.git*" -not -path "*.pb.go" -not -path "*.pb.gw.go" | xargs misspell -w 19 | find . -name '*.go' -type f -not -path "./api/*" -not -path "*.git*" -not -path "*.pb.go" -not -path "*.pb.gw.go" | xargs goimports -w -local github.com/burnt-labs/xiond 20 | 21 | # Help targets for lint module 22 | help-lint-brief: 23 | @echo " lint Lint and format code" 24 | 25 | help-lint: 26 | @echo "Linting targets:" 27 | @echo " lint Lint Go code" 28 | @echo " format Format Go code" 29 | @echo " format-tools Install formatting tools" 30 | @echo "" 31 | 32 | .PHONY: format-tools lint format help-lint help-lint-brief 33 | -------------------------------------------------------------------------------- /x/mint/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types // noalias 2 | 3 | import ( 4 | "context" 5 | 6 | "cosmossdk.io/math" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | // StakingKeeper defines the expected staking keeper 12 | type StakingKeeper interface { 13 | StakingTokenSupply(ctx context.Context) (math.Int, error) 14 | TotalBondedTokens(ctx context.Context) (math.Int, error) 15 | BondedRatio(ctx context.Context) (math.LegacyDec, error) 16 | } 17 | 18 | // AccountKeeper defines the contract required for account APIs. 19 | type AccountKeeper interface { 20 | GetModuleAddress(name string) sdk.AccAddress 21 | 22 | // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 23 | SetModuleAccount(context.Context, sdk.ModuleAccountI) 24 | GetModuleAccount(ctx context.Context, moduleName string) sdk.ModuleAccountI 25 | } 26 | 27 | // BankKeeper defines the contract needed to be fulfilled for banking and supply 28 | // dependencies. 29 | type BankKeeper interface { 30 | SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error 31 | SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt sdk.Coins) error 32 | MintCoins(ctx context.Context, name string, amt sdk.Coins) error 33 | GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin 34 | BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error 35 | } 36 | -------------------------------------------------------------------------------- /x/globalfee/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | 9 | "github.com/burnt-labs/xion/x/globalfee/types" 10 | ) 11 | 12 | func GetQueryCmd() *cobra.Command { 13 | queryCmd := &cobra.Command{ 14 | Use: types.ModuleName, 15 | Short: "Querying commands for the global fee module", 16 | DisableFlagParsing: true, 17 | SuggestionsMinimumDistance: 2, 18 | RunE: client.ValidateCmd, 19 | } 20 | queryCmd.AddCommand( 21 | GetCmdShowGlobalFeeParams(), 22 | ) 23 | return queryCmd 24 | } 25 | 26 | func GetCmdShowGlobalFeeParams() *cobra.Command { 27 | cmd := &cobra.Command{ 28 | Use: "params", 29 | Short: "Show globalfee params", 30 | Long: "Show globalfee requirement: minimum_gas_prices, bypass_min_fee_msg_types, max_total_bypass_minFee_msg_gas_usage", 31 | Args: cobra.ExactArgs(0), 32 | RunE: func(cmd *cobra.Command, _ []string) error { 33 | clientCtx, err := client.GetClientQueryContext(cmd) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | queryClient := types.NewQueryClient(clientCtx) 39 | res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) 40 | if err != nil { 41 | return err 42 | } 43 | return clientCtx.PrintProto(&res.Params) 44 | }, 45 | } 46 | flags.AddQueryFlagsToCmd(cmd) 47 | return cmd 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/trigger-homebrew.yaml: -------------------------------------------------------------------------------- 1 | name: Trigger Homebrew 2 | 3 | on: 4 | workflow_call: # is called from the create-release workflow 5 | workflow_dispatch: # manual trigger 6 | 7 | jobs: 8 | trigger-homebrew: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Trigger homebrew-xion workflow 12 | uses: peter-evans/repository-dispatch@v2 13 | with: 14 | token: ${{ secrets.REPO_DISPATCH_TOKEN }} 15 | repository: burnt-labs/homebrew-xion 16 | event-type: homebrew-release-trigger # NOTICE: must match the trigger in homebrew-xion workflow 17 | # -client-payload logic description- 18 | # Checks if it's a pre-release: github.event.release.prerelease == true - if the release is marked as a pre-release, it sets release_type to 'prerelease' 19 | # If not a pre-release, checks for latest release: github.event.release.prerelease == false && github.event.release.draft == false && github.event.release.make_latest == 'true' - ensures it's not a pre-release, not a draft, and is marked as the latest release 20 | # Sets latest tag: If all the above conditions are true, it sets release_type to 'latest' 21 | # Fallback to published: If none of the above conditions are met, it sets release_type to 'published' 22 | client-payload: | 23 | { 24 | "tag_name": "${{ github.event.release.tag_name }}", 25 | "release_name": "${{ github.event.release.name }}" 26 | } 27 | -------------------------------------------------------------------------------- /contrib/local/setup_wasmd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | 4 | PASSWORD=${PASSWORD:-1234567890} 5 | STAKE=${STAKE_TOKEN:-ustake} 6 | FEE=${FEE_TOKEN:-ucosm} 7 | CHAIN_ID=${CHAIN_ID:-testing} 8 | MONIKER=${MONIKER:-node001} 9 | 10 | wasmd init --chain-id "$CHAIN_ID" "$MONIKER" 11 | # staking/governance token is hardcoded in config, change this 12 | ## OSX requires: -i. 13 | sed -i. "s/\"stake\"/\"$STAKE\"/" "$HOME"/.wasmd/config/genesis.json 14 | if ! wasmd keys show validator --keyring-backend=test; then 15 | ( 16 | echo "$PASSWORD" 17 | echo "$PASSWORD" 18 | ) | wasmd keys add validator --keyring-backend=test 19 | fi 20 | # hardcode the validator account for this instance 21 | echo "$PASSWORD" | wasmd genesis add-genesis-account validator "1000000000$STAKE,1000000000$FEE" --keyring-backend=test 22 | # (optionally) add a few more genesis accounts 23 | for addr in "$@"; do 24 | echo "$addr" 25 | wasmd genesis add-genesis-account "$addr" "1000000000$STAKE,1000000000$FEE" --keyring-backend=test 26 | done 27 | # submit a genesis validator tx 28 | ## Workraround for https://github.com/cosmos/cosmos-sdk/issues/8251 29 | ( 30 | echo "$PASSWORD" 31 | echo "$PASSWORD" 32 | echo "$PASSWORD" 33 | ) | wasmd genesis gentx validator "250000000$STAKE" --chain-id="$CHAIN_ID" --amount="250000000$STAKE" --keyring-backend=test 34 | ## should be: 35 | # (echo "$PASSWORD"; echo "$PASSWORD"; echo "$PASSWORD") | xiond gentx validator "250000000$STAKE" --chain-id="$CHAIN_ID" 36 | wasmd genesis collect-gentxs 37 | -------------------------------------------------------------------------------- /contrib/prometheus/README.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | Enable prometheus metrics in wasmd: 3 | 4 | * Edit `$HOME/config/app.toml` 5 | ```toml 6 | [telemetry] 7 | 8 | # Enabled enables the application telemetry functionality. When enabled, 9 | # an in-memory sink is also enabled by default. Operators may also enabled 10 | # other sinks such as Prometheus. 11 | enabled =true 12 | # ... 13 | 14 | # PrometheusRetentionTime, when positive, enables a Prometheus metrics sink. 15 | prometheus-retention-time = 15 16 | ``` 17 | 18 | `retention-time` must be >0 (see prometheus scrape config) 19 | 20 | 21 | * Edit `$HOME/config/config.toml` 22 | ```toml 23 | [instrumentation] 24 | 25 | # When true, Prometheus metrics are served under /metrics on 26 | # PrometheusListenAddr. 27 | # Check out the documentation for the list of available metrics. 28 | prometheus = true 29 | ``` 30 | 31 | Test manually at: 32 | `http://localhost:1317/metrics?format=prometheus` 33 | 34 | Note the `format` parameter in the request for the endpoint: 35 | 36 | 37 | # Local testing 38 | ## Run Prometheus 39 | ```sh 40 | # port 9090 is used by xiond already 41 | docker run -it -v $(pwd)/contrib/prometheus:/prometheus -p9091:9090 prom/prometheus --config.file=/prometheus/prometheus.yaml 42 | ``` 43 | * Open [console](http://localhost:9091) and find `wasm_`service metrics 44 | 45 | ## Run Grafana 46 | 47 | ```shell 48 | docker run -it -p 3000:3000 grafana/grafana 49 | ``` 50 | * Add Prometheus data source 51 | `http://host.docker.internal:9091` 52 | ### Labels 53 | * `wasm_contract_create` = nanosec -------------------------------------------------------------------------------- /proto/xion/mint/v1/event.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.mint.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos_proto/cosmos.proto"; 6 | 7 | option go_package = "github.com/burnt-labs/xion/x/mint/types"; 8 | 9 | // MintIncentiveTokens defines an event emitted on each block from the mint 10 | // module EndBlocker 11 | message MintIncentiveTokens { 12 | // The ratio of bonded tokens to total supply 13 | string bonded_ratio = 1 [ 14 | (cosmos_proto.scalar) = "cosmos.Dec", 15 | (gogoproto.moretags) = "yaml:\"bonded_ratio\"", 16 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 17 | (gogoproto.nullable) = false 18 | ]; 19 | // The current inflation rate 20 | string inflation = 2 [ 21 | (cosmos_proto.scalar) = "cosmos.Dec", 22 | (gogoproto.moretags) = "yaml:\"inflation\"", 23 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 24 | (gogoproto.nullable) = false 25 | ]; 26 | // The total annual provisions for minting 27 | string annual_provisions = 3 [ 28 | (gogoproto.moretags) = "yaml:\"annual_provisions\"", 29 | (cosmos_proto.scalar) = "cosmos.Dec", 30 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 31 | (gogoproto.nullable) = false 32 | ]; 33 | // The amount of tokens needed for incentives 34 | uint64 needed_amount = 4; 35 | // The amount of tokens collected for incentives 36 | uint64 collected_amount = 5; 37 | // The amount of tokens minted 38 | uint64 minted_amount = 6; 39 | // The amount of tokens burned 40 | uint64 burned_amount = 7; 41 | } -------------------------------------------------------------------------------- /x/globalfee/migrations/v2/migration.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 6 | 7 | "github.com/burnt-labs/xion/x/globalfee/types" 8 | ) 9 | 10 | // MigrateStore performs in-place params migrations of 11 | // BypassMinFeeMsgTypes and MaxTotalBypassMinFeeMsgGasUsage 12 | // from app.toml to globalfee params. 13 | // The migration includes: 14 | // Add bypass-min-fee-msg-types params that are set 15 | // ["/ibc.core.channel.v1.MsgRecvPacket", 16 | // "/ibc.core.channel.v1.MsgAcknowledgement", 17 | // "/ibc.core.client.v1.MsgUpdateClient", 18 | // "/ibc.core.channel.v1.MsgTimeout", 19 | // "/ibc.core.channel.v1.MsgTimeoutOnClose"] as default and 20 | // add MaxTotalBypassMinFeeMsgGasUsage that is set 1_000_000 as default. 21 | func MigrateStore(ctx sdk.Context, globalfeeSubspace paramtypes.Subspace) error { 22 | if !globalfeeSubspace.HasKeyTable() { 23 | globalfeeSubspace = globalfeeSubspace.WithKeyTable(types.ParamKeyTable()) 24 | } 25 | 26 | var oldGlobalMinGasPrices sdk.DecCoins 27 | globalfeeSubspace.Get(ctx, types.ParamStoreKeyMinGasPrices, &oldGlobalMinGasPrices) 28 | defaultParams := types.DefaultParams() 29 | params := types.Params{ 30 | MinimumGasPrices: oldGlobalMinGasPrices, 31 | BypassMinFeeMsgTypes: defaultParams.BypassMinFeeMsgTypes, 32 | MaxTotalBypassMinFeeMsgGasUsage: defaultParams.MaxTotalBypassMinFeeMsgGasUsage, 33 | } 34 | 35 | globalfeeSubspace.SetParamSet(ctx, ¶ms) 36 | 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /app/config.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" 5 | 6 | serverconfig "github.com/cosmos/cosmos-sdk/server/config" 7 | 8 | "github.com/burnt-labs/xion/indexer" 9 | ) 10 | 11 | // CustomConfig defines a custom app.toml configuration file 12 | // that contains default wasm configuration and 13 | // indexer configuration 14 | type CustomConfig struct { 15 | serverconfig.Config 16 | Wasm wasmtypes.NodeConfig `mapstructure:"wasm" json:"wasm"` 17 | Indexer indexer.Config `mapstructure:"config" json:"config"` 18 | } 19 | 20 | func CustomconfigTemplate(config wasmtypes.NodeConfig) string { 21 | return serverconfig.DefaultConfigTemplate + wasmtypes.ConfigTemplate(config) + indexer.DefaultConfigTemplate() 22 | } 23 | 24 | func DefaultConfig() (string, any) { 25 | // Default SDK config params 26 | serverConfig := serverconfig.DefaultConfig() 27 | serverConfig.MinGasPrices = "0uxion" 28 | 29 | // Default x/wasm configuration 30 | wasmConfig := wasmtypes.DefaultNodeConfig() 31 | simulationLimit := uint64(50_000_00) 32 | wasmConfig.SimulationGasLimit = &simulationLimit // 50M Gas 33 | wasmConfig.SmartQueryGasLimit = 50_000_00 // 50M Gas 34 | wasmConfig.MemoryCacheSize = 1024 // 1GB memory caache 35 | 36 | // Default Indexer Params 37 | indexerConfig := indexer.DefaultConfig() 38 | customConfig := CustomConfig{ 39 | Config: *serverConfig, 40 | Wasm: wasmConfig, 41 | Indexer: indexerConfig, 42 | } 43 | 44 | return CustomconfigTemplate(wasmConfig), customConfig 45 | } 46 | -------------------------------------------------------------------------------- /x/mint/types/codec_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | "github.com/cosmos/cosmos-sdk/codec/types" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | func TestRegisterLegacyAminoCodec(t *testing.T) { 14 | cdc := codec.NewLegacyAmino() 15 | 16 | // Test that RegisterLegacyAminoCodec doesn't panic 17 | require.NotPanics(t, func() { 18 | RegisterLegacyAminoCodec(cdc) 19 | }) 20 | 21 | // Test that Params can be marshaled/unmarshaled 22 | params := DefaultParams() 23 | 24 | // Test marshaling 25 | bz, err := cdc.MarshalJSON(params) 26 | require.NoError(t, err) 27 | require.NotEmpty(t, bz) 28 | 29 | // Test unmarshaling 30 | var unmarshaled Params 31 | err = cdc.UnmarshalJSON(bz, &unmarshaled) 32 | require.NoError(t, err) 33 | require.Equal(t, params, unmarshaled) 34 | } 35 | 36 | func TestRegisterInterfaces(t *testing.T) { 37 | registry := types.NewInterfaceRegistry() 38 | 39 | // Test that RegisterInterfaces doesn't panic 40 | require.NotPanics(t, func() { 41 | RegisterInterfaces(registry) 42 | }) 43 | 44 | // Test that MsgUpdateParams is registered as sdk.Msg 45 | msg := &MsgUpdateParams{} 46 | require.Implements(t, (*sdk.Msg)(nil), msg) 47 | 48 | // Test that we can pack/unpack the message 49 | any, err := types.NewAnyWithValue(msg) 50 | require.NoError(t, err) 51 | 52 | var unpacked sdk.Msg 53 | err = registry.UnpackAny(any, &unpacked) 54 | require.NoError(t, err) 55 | require.Equal(t, msg, unpacked) 56 | } 57 | -------------------------------------------------------------------------------- /x/xion/client/cli/suite_test.go: -------------------------------------------------------------------------------- 1 | package cli_test 2 | 3 | import ( 4 | "io" 5 | "testing" 6 | 7 | "github.com/CosmWasm/wasmd/x/wasm" 8 | "github.com/stretchr/testify/suite" 9 | 10 | rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" 11 | 12 | feegrant "cosmossdk.io/x/feegrant/module" 13 | 14 | "github.com/cosmos/cosmos-sdk/client" 15 | "github.com/cosmos/cosmos-sdk/crypto/keyring" 16 | clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" 17 | testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" 18 | authz "github.com/cosmos/cosmos-sdk/x/authz/module" 19 | "github.com/cosmos/cosmos-sdk/x/bank" 20 | "github.com/cosmos/cosmos-sdk/x/gov" 21 | "github.com/cosmos/cosmos-sdk/x/staking" 22 | ) 23 | 24 | type CLITestSuite struct { 25 | suite.Suite 26 | 27 | kr keyring.Keyring 28 | encCfg testutilmod.TestEncodingConfig 29 | baseCtx client.Context 30 | } 31 | 32 | func TestMigrateTestSuite(t *testing.T) { 33 | suite.Run(t, new(CLITestSuite)) 34 | } 35 | 36 | func (s *CLITestSuite) SetupSuite() { 37 | s.encCfg = testutilmod.MakeTestEncodingConfig(bank.AppModuleBasic{}, feegrant.AppModuleBasic{}, authz.AppModuleBasic{}, staking.AppModuleBasic{}, gov.AppModuleBasic{}, wasm.AppModuleBasic{}) 38 | s.kr = keyring.NewInMemory(s.encCfg.Codec) 39 | s.baseCtx = client.Context{}. 40 | WithKeyring(s.kr). 41 | WithTxConfig(s.encCfg.TxConfig). 42 | WithCodec(s.encCfg.Codec). 43 | WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}). 44 | WithAccountRetriever(client.MockAccountRetriever{}). 45 | WithOutput(io.Discard) 46 | } 47 | -------------------------------------------------------------------------------- /indexer/authz_decode_test.go: -------------------------------------------------------------------------------- 1 | package indexer 2 | 3 | import ( 4 | "testing" 5 | 6 | "cosmossdk.io/collections" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | func TestAuthzDecode(t *testing.T) { 12 | // This test creates a proper collections-encoded key and verifies it can be decoded 13 | granter := sdk.AccAddress([]byte("granter_address_____")) 14 | grantee := sdk.AccAddress([]byte("grantee_address_____")) 15 | msgType := "/cosmos.bank.v1beta1.MsgSend" 16 | 17 | // Encode using collections codec 18 | codec := collections.TripleKeyCodec(sdk.AccAddressKey, sdk.AccAddressKey, collections.StringKey) 19 | triple := collections.Join3(granter, grantee, msgType) 20 | size := codec.Size(triple) 21 | buf := make([]byte, size) 22 | _, err := codec.Encode(buf, triple) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | // Add prefix 28 | key := append([]byte{0x01}, buf...) 29 | 30 | // Decode using our function 31 | decodedGranter, decodedGrantee, decodedMsgType := parseGrantStoreKey(key) 32 | 33 | if decodedGranter.String() != granter.String() { 34 | t.Errorf("granter mismatch: got %s, want %s", decodedGranter.String(), granter.String()) 35 | } 36 | if decodedGrantee.String() != grantee.String() { 37 | t.Errorf("grantee mismatch: got %s, want %s", decodedGrantee.String(), grantee.String()) 38 | } 39 | if decodedMsgType != msgType { 40 | t.Errorf("msgType mismatch: got %q (len=%d), want %q (len=%d)", decodedMsgType, len(decodedMsgType), msgType, len(msgType)) 41 | t.Logf("Key hex: %x", key) 42 | t.Logf("Buf hex: %x", buf) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /proto/xion/mint/v1/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.mint.v1; 3 | 4 | option go_package = "github.com/burnt-labs/xion/x/mint/types"; 5 | 6 | import "cosmos/msg/v1/msg.proto"; 7 | import "amino/amino.proto"; 8 | import "xion/mint/v1/mint.proto"; 9 | import "gogoproto/gogo.proto"; 10 | import "cosmos_proto/cosmos.proto"; 11 | 12 | // Msg defines the x/mint Msg service. 13 | service Msg { 14 | option (cosmos.msg.v1.service) = true; 15 | 16 | // UpdateParams defines a governance operation for updating the x/mint module 17 | // parameters. The authority is defaults to the x/gov module account. 18 | // 19 | // Since: cosmos-sdk 0.47 20 | rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); 21 | } 22 | 23 | // MsgUpdateParams is the Msg/UpdateParams request type. 24 | // 25 | // Since: cosmos-sdk 0.47 26 | message MsgUpdateParams { 27 | option (cosmos.msg.v1.signer) = "authority"; 28 | option (amino.name) = "xion/x/mint/MsgUpdateParams"; 29 | 30 | // authority is the address that controls the module (defaults to x/gov unless 31 | // overwritten). 32 | string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 33 | 34 | // params defines the x/mint parameters to update. 35 | // 36 | // NOTE: All parameters must be supplied. 37 | Params params = 2 38 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 39 | } 40 | 41 | // MsgUpdateParamsResponse defines the response structure for executing a 42 | // MsgUpdateParams message. 43 | // 44 | // Since: cosmos-sdk 0.47 45 | message MsgUpdateParamsResponse {} 46 | -------------------------------------------------------------------------------- /.github/workflows/docker-scout.yaml: -------------------------------------------------------------------------------- 1 | name: Docker Scout 2 | 3 | # reusable workflow, do not add triggers 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | docker-scout: 10 | name: main 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | pull-requests: write 15 | 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | os: 20 | - linux 21 | arch: 22 | - amd64 23 | - arm64 24 | 25 | steps: 26 | - name: Login to Docker Hub 27 | uses: docker/login-action@v3 28 | with: 29 | username: ${{ secrets.DOCKER_HUB_USERNAME }} 30 | password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} 31 | 32 | - name: Prepare environment 33 | run: | 34 | echo "DOCKER_FN=docker/${{ matrix.os }}/${{ matrix.arch }}.tar" | tr '/' '-' | tee -a $GITHUB_ENV 35 | 36 | - name: Download images 37 | uses: actions/download-artifact@v4 38 | with: 39 | path: ${{ runner.temp }} 40 | pattern: ${{ env.DOCKER_FN }} 41 | merge-multiple: true 42 | 43 | - name: Load images 44 | working-directory: ${{ runner.temp }} 45 | run: | 46 | ls -la 47 | docker load < ${{ env.DOCKER_FN }} 48 | 49 | - name: Run Docker Scout 50 | uses: docker/scout-action@v1 51 | with: 52 | command: cves 53 | only-fixed: true 54 | platform: ${{ matrix.os }}/${{ matrix.arch }} 55 | image: xion:${{ matrix.os }}-${{ matrix.arch }} 56 | -------------------------------------------------------------------------------- /x/feeabs/types/epoch.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | ) 7 | 8 | const ( 9 | DefaultSwapPeriod = time.Minute * 2 10 | DefaultQueryPeriod = time.Minute * 1 11 | DefaultSwapEpochIdentifier = "swap" 12 | DefaultQueryEpochIdentifier = "query" 13 | // assume that query period is after 1 minute, thus a maximum of 32 minutes is enough 14 | // todo: should be a parameter 15 | // 1, 2, 4, 8, 16, 32 16 | ExponentialMaxJump = 32 17 | // after 4 jump, a connection is considered outdated 18 | ExponentialOutdatedJump = 4 19 | ) 20 | 21 | func KeyPrefix(p string) []byte { 22 | return []byte(p) 23 | } 24 | 25 | // Validate also validates epoch info. 26 | func (epoch EpochInfo) Validate() error { 27 | if epoch.Identifier == "" { 28 | return errors.New("epoch identifier should NOT be empty") 29 | } 30 | if epoch.Duration == 0 { 31 | return errors.New("epoch duration should NOT be 0") 32 | } 33 | if epoch.CurrentEpoch < 0 { 34 | return errors.New("epoch CurrentEpoch must be non-negative") 35 | } 36 | if epoch.CurrentEpochStartHeight < 0 { 37 | return errors.New("epoch CurrentEpoch must be non-negative") 38 | } 39 | return nil 40 | } 41 | 42 | func NewGenesisEpochInfo(identifier string, duration time.Duration) EpochInfo { 43 | return EpochInfo{ 44 | Identifier: identifier, 45 | StartTime: time.Time{}, 46 | Duration: duration, 47 | CurrentEpoch: 0, 48 | CurrentEpochStartHeight: 0, 49 | CurrentEpochStartTime: time.Time{}, 50 | EpochCountingStarted: false, 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.github/workflows/publish-release.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Release 2 | 3 | on: 4 | workflow_call: # is called from the create-release workflow 5 | workflow_dispatch: # manual trigger 6 | release: # triggered by release event 7 | types: [released] 8 | # Notice: 9 | # ref: https://docs.github.com/en/webhooks/webhook-events-and-payloads#release 10 | # - "published" type is happening when the release is marked as "latest" 11 | # - "released" type is happening when a release was published, or a pre-release was changed to a release. 12 | # - "prereleased" type is happening when a release was created and identified as a pre-release. A pre-release is a release that is not ready for production and may be unstable. 13 | 14 | concurrency: # With concurrency control: Only the latest workflow run executes, previous runs get cancelled 15 | group: ${{ github.workflow }}-${{ github.ref }} 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | trigger-types: 20 | name: Trigger Types 21 | uses: burnt-labs/xion/.github/workflows/trigger-types.yaml@workflows/main 22 | secrets: inherit 23 | trigger-assets: 24 | name: Trigger Assets 25 | uses: burnt-labs/xion/.github/workflows/trigger-assets.yaml@workflows/main 26 | secrets: inherit 27 | trigger-homebrew: 28 | name: Trigger Homebrew 29 | uses: burnt-labs/xion/.github/workflows/trigger-homebrew.yaml@workflows/main 30 | secrets: inherit 31 | trigger-chain-registry: 32 | name: Trigger Chain Registry 33 | uses: burnt-labs/xion/.github/workflows/trigger-chain-registry.yaml@workflows/main 34 | secrets: inherit -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | run: 3 | tests: true 4 | linters: 5 | default: none 6 | enable: 7 | - bodyclose 8 | - copyloopvar 9 | - dogsled 10 | - errcheck 11 | - gocritic 12 | - gosec 13 | - govet 14 | - ineffassign 15 | - misspell 16 | - nakedret 17 | - revive 18 | - staticcheck 19 | - unconvert 20 | - unparam 21 | - unused 22 | settings: 23 | gocritic: 24 | disabled-checks: 25 | - appendAssign 26 | gosec: 27 | excludes: 28 | - G404 29 | - G115 30 | revive: 31 | rules: 32 | - name: "var-naming" 33 | disabled: true 34 | severity: "warning" 35 | arguments: [] 36 | exclusions: 37 | generated: lax 38 | presets: 39 | - comments 40 | - common-false-positives 41 | - legacy 42 | - std-error-handling 43 | paths: 44 | - third_party$ 45 | - builtin$ 46 | - examples$ 47 | issues: 48 | max-issues-per-linter: 0 49 | max-same-issues: 0 50 | formatters: 51 | enable: 52 | - gci 53 | - gofumpt 54 | settings: 55 | gci: 56 | sections: 57 | - standard 58 | - default 59 | - blank 60 | - dot 61 | - prefix(github.com/cometbft/cometbft) 62 | - prefix(github.com/cosmos) 63 | - prefix(cosmossdk.io) 64 | - prefix(github.com/cosmos/cosmos-sdk) 65 | - prefix(github.com/burnt-labs/xion) 66 | custom-order: true 67 | exclusions: 68 | generated: lax 69 | paths: 70 | - third_party$ 71 | - builtin$ 72 | - examples$ 73 | -------------------------------------------------------------------------------- /proto/buf.gen.pulsar.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | 3 | managed: 4 | enabled: true 5 | override: 6 | - file_option: go_package_prefix 7 | value: github.com/burnt-labs/xion/api 8 | - file_option: go_package_prefix 9 | module: buf.build/cosmos/gogo-proto 10 | value: github.com/cosmos/gogoproto 11 | - file_option: go_package_prefix 12 | module: buf.build/cosmos/cosmos-proto 13 | value: github.com/cosmos/cosmos-proto 14 | - file_option: go_package 15 | module: buf.build/cosmos/cosmos-proto 16 | path: cosmos_proto/cosmos.proto 17 | value: github.com/cosmos/cosmos-proto 18 | - file_option: go_package_prefix 19 | module: buf.build/cosmos/cosmos-sdk 20 | value: cosmossdk.io/api 21 | - file_option: go_package 22 | module: buf.build/googleapis/googleapis 23 | path: google/api/annotations.proto 24 | value: google.golang.org/genproto/googleapis/api/annotations 25 | - file_option: go_package 26 | module: buf.build/googleapis/googleapis 27 | path: google/api/http.proto 28 | value: google.golang.org/genproto/googleapis/api/annotations 29 | - file_option: go_package 30 | module: buf.build/tendermint/tendermint 31 | path: tendermint/abci/types.proto 32 | value: github.com/cometbft/cometbft/abci/types 33 | 34 | 35 | plugins: 36 | - local: protoc-gen-go-pulsar 37 | out: ../api 38 | opt: paths=source_relative 39 | - local: protoc-gen-go-grpc 40 | out: ../api 41 | opt: paths=source_relative 42 | - local: protoc-gen-go-cosmos-orm 43 | out: ../api 44 | opt: paths=source_relative 45 | -------------------------------------------------------------------------------- /x/mint/types/params_legacy.go: -------------------------------------------------------------------------------- 1 | /* 2 | NOTE: Usage of x/params to manage parameters is deprecated in favor of x/gov 3 | controlled execution of MsgUpdateParams messages. These types remains solely 4 | for migration purposes and will be removed in a future release. 5 | */ 6 | package types 7 | 8 | import ( 9 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 10 | ) 11 | 12 | // Parameter store keys 13 | var ( 14 | KeyMintDenom = []byte("MintDenom") 15 | KeyInflationRateChange = []byte("InflationRateChange") 16 | KeyInflationMax = []byte("InflationMax") 17 | KeyInflationMin = []byte("InflationMin") 18 | KeyGoalBonded = []byte("GoalBonded") 19 | KeyBlocksPerYear = []byte("BlocksPerYear") 20 | ) 21 | 22 | // Deprecated: ParamTable for minting module. 23 | func ParamKeyTable() paramtypes.KeyTable { 24 | return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) 25 | } 26 | 27 | // Implements params.ParamSet 28 | // 29 | // Deprecated. 30 | func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { 31 | return paramtypes.ParamSetPairs{ 32 | paramtypes.NewParamSetPair(KeyMintDenom, &p.MintDenom, validateMintDenom), 33 | paramtypes.NewParamSetPair(KeyInflationRateChange, &p.InflationRateChange, validateInflationRateChange), 34 | paramtypes.NewParamSetPair(KeyInflationMax, &p.InflationMax, validateInflationMax), 35 | paramtypes.NewParamSetPair(KeyInflationMin, &p.InflationMin, validateInflationMin), 36 | paramtypes.NewParamSetPair(KeyGoalBonded, &p.GoalBonded, validateGoalBonded), 37 | paramtypes.NewParamSetPair(KeyBlocksPerYear, &p.BlocksPerYear, validateBlocksPerYear), 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /x/xion/client/cli/query_platform_fee.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | 9 | "github.com/burnt-labs/xion/x/xion/types" 10 | ) 11 | 12 | func CmdPlatformPercentage() *cobra.Command { 13 | cmd := &cobra.Command{ 14 | Use: "platform-percentage", 15 | Short: "Get Platform Percentage", 16 | RunE: func(cmd *cobra.Command, _ []string) error { 17 | clientCtx, err := client.GetClientQueryContext(cmd) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | queryClient := types.NewQueryClient(clientCtx) 23 | 24 | params := &types.QueryPlatformPercentageRequest{} 25 | 26 | res, err := queryClient.PlatformPercentage(cmd.Context(), params) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | return clientCtx.PrintProto(res) 32 | }, 33 | } 34 | 35 | flags.AddQueryFlagsToCmd(cmd) 36 | 37 | return cmd 38 | } 39 | 40 | func CmdPlatformMinimum() *cobra.Command { 41 | cmd := &cobra.Command{ 42 | Use: "platform-minimum", 43 | Short: "Get Platform Minimum", 44 | RunE: func(cmd *cobra.Command, _ []string) error { 45 | clientCtx, err := client.GetClientQueryContext(cmd) 46 | if err != nil { 47 | return err 48 | } 49 | 50 | queryClient := types.NewQueryClient(clientCtx) 51 | 52 | params := &types.QueryPlatformMinimumRequest{} 53 | 54 | res, err := queryClient.PlatformMinimum(cmd.Context(), params) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | return clientCtx.PrintProto(res) 60 | }, 61 | } 62 | 63 | flags.AddQueryFlagsToCmd(cmd) 64 | 65 | return cmd 66 | } 67 | -------------------------------------------------------------------------------- /x/mint/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "cosmossdk.io/math" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // InflationCalculationFn defines the function required to calculate inflation rate during 10 | // BeginBlock. It receives the minter and params stored in the keeper, along with the current 11 | // bondedRatio and returns the newly calculated inflation rate. 12 | // It can be used to specify a custom inflation calculation logic, instead of relying on the 13 | // default logic provided by the sdk. 14 | type InflationCalculationFn func(ctx sdk.Context, minter Minter, params Params, bondedRatio math.LegacyDec) math.LegacyDec 15 | 16 | // DefaultInflationCalculationFn is the default function used to calculate inflation. 17 | func DefaultInflationCalculationFn(_ sdk.Context, minter Minter, params Params, bondedRatio math.LegacyDec) math.LegacyDec { 18 | return minter.NextInflationRate(params, bondedRatio) 19 | } 20 | 21 | // NewGenesisState creates a new GenesisState object 22 | func NewGenesisState(minter Minter, params Params) *GenesisState { 23 | return &GenesisState{ 24 | Minter: minter, 25 | Params: params, 26 | } 27 | } 28 | 29 | // DefaultGenesisState creates a default GenesisState object 30 | func DefaultGenesisState() *GenesisState { 31 | return &GenesisState{ 32 | Minter: DefaultInitialMinter(), 33 | Params: DefaultParams(), 34 | } 35 | } 36 | 37 | // ValidateGenesis validates the provided genesis state to ensure the 38 | // expected invariants holds. 39 | func ValidateGenesis(data GenesisState) error { 40 | if err := data.Params.Validate(); err != nil { 41 | return err 42 | } 43 | 44 | return ValidateMinter(data.Minter) 45 | } 46 | -------------------------------------------------------------------------------- /indexer/noop_service.go: -------------------------------------------------------------------------------- 1 | package indexer 2 | 3 | import ( 4 | "context" 5 | 6 | abci "github.com/cometbft/cometbft/abci/types" 7 | 8 | "cosmossdk.io/log" 9 | storetypes "cosmossdk.io/store/types" 10 | 11 | "github.com/cosmos/cosmos-sdk/types/module" 12 | ) 13 | 14 | // NoOpStreamService is a no-operation implementation of the StreamService 15 | // Used when the indexer cannot be initialized but we want the node to continue 16 | type NoOpStreamService struct { 17 | log log.Logger 18 | } 19 | 20 | // NewNoOpStreamService creates a new no-op stream service 21 | func NewNoOpStreamService(logger log.Logger) *NoOpStreamService { 22 | return &NoOpStreamService{ 23 | log: logger.With("module", "indexer", "mode", "noop"), 24 | } 25 | } 26 | 27 | // ListenFinalizeBlock implements ABCIListener - no-op 28 | func (n *NoOpStreamService) ListenFinalizeBlock(ctx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error { 29 | // No-op: just return nil to allow consensus to continue 30 | return nil 31 | } 32 | 33 | // ListenCommit implements ABCIListener - no-op 34 | func (n *NoOpStreamService) ListenCommit(ctx context.Context, res abci.ResponseCommit, changeSet []*storetypes.StoreKVPair) error { 35 | // No-op: just return nil to allow consensus to continue 36 | return nil 37 | } 38 | 39 | // Close implements io.Closer - no-op 40 | func (n *NoOpStreamService) Close() error { 41 | n.log.Info("Closing no-op indexer service") 42 | return nil 43 | } 44 | 45 | // RegisterServices implements the required interface - no-op 46 | func (n *NoOpStreamService) RegisterServices(configurator module.Configurator) error { 47 | n.log.Info("No-op indexer: skipping service registration") 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/trigger-types.yaml: -------------------------------------------------------------------------------- 1 | name: Trigger Types 2 | 3 | on: 4 | workflow_call: # is called from the create-release workflow 5 | workflow_dispatch: # manual trigger 6 | 7 | jobs: 8 | trigger-types: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Trigger xion-types workflow 12 | uses: peter-evans/repository-dispatch@v2 13 | with: 14 | token: ${{ secrets.REPO_DISPATCH_TOKEN }} 15 | repository: burnt-labs/xion-types 16 | event-type: xion-types-release-trigger # NOTICE: must match the trigger in xion-types workflow 17 | # -client-payload logic description- 18 | # Checks if it's a pre-release: github.event.release.prerelease == true - if the release is marked as a pre-release, it sets release_type to 'prerelease' 19 | # If not a pre-release, checks for latest release: github.event.release.prerelease == false && github.event.release.draft == false && github.event.release.make_latest == 'true' - ensures it's not a pre-release, not a draft, and is marked as the latest release 20 | # Sets latest tag: If all the above conditions are true, it sets release_type to 'latest' 21 | # Fallback to published: If none of the above conditions are met, it sets release_type to 'published' 22 | client-payload: | 23 | { 24 | "release_type": "${{ github.event.release.prerelease == true && 'prerelease' || (github.event.release.prerelease == false && github.event.release.draft == false && github.event.release.make_latest == 'true' && 'latest' || 'published') }}", 25 | "tag_name": "${{ github.event.release.tag_name }}", 26 | "release_name": "${{ github.event.release.name }}" 27 | } 28 | -------------------------------------------------------------------------------- /proto/xion/globalfee/v1/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.globalfee.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "cosmos/base/v1beta1/coin.proto"; 6 | 7 | option go_package = "github.com/burnt-labs/xion/x/globalfee/types"; 8 | 9 | // GenesisState - initial state of module 10 | message GenesisState { 11 | // Params of this module 12 | Params params = 1 [ 13 | (gogoproto.nullable) = false, 14 | (gogoproto.jsontag) = "params,omitempty" 15 | ]; 16 | } 17 | 18 | // Params defines the set of module parameters. 19 | message Params { 20 | // minimum_gas_prices stores the minimum gas price(s) for all TX on the chain. 21 | // When multiple coins are defined then they are accepted alternatively. 22 | // The list must be sorted by denoms asc. No duplicate denoms or zero amount 23 | // values allowed. For more information see 24 | // https://docs.cosmos.network/main/modules/auth#concepts 25 | repeated cosmos.base.v1beta1.DecCoin minimum_gas_prices = 1 [ 26 | (gogoproto.nullable) = false, 27 | (gogoproto.jsontag) = "minimum_gas_prices,omitempty", 28 | (gogoproto.moretags) = "yaml:\"minimum_gas_prices\"", 29 | (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins" 30 | ]; 31 | 32 | // bypass_min_fee_msg_types defines a list of message type urls 33 | // that are free of fee charge. 34 | repeated string bypass_min_fee_msg_types = 2 [ 35 | (gogoproto.jsontag) = "bypass_min_fee_msg_types,omitempty", 36 | (gogoproto.moretags) = "yaml:\"bypass_min_fee_msg_types\"" 37 | ]; 38 | 39 | // max_total_bypass_min_fee_msg_gas_usage defines the total maximum gas usage 40 | // allowed for a transaction containing only messages of types in 41 | // bypass_min_fee_msg_types to bypass fee charge. 42 | uint64 max_total_bypass_min_fee_msg_gas_usage = 3; 43 | } 44 | -------------------------------------------------------------------------------- /x/globalfee/querier.go: -------------------------------------------------------------------------------- 1 | package globalfee 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | "github.com/burnt-labs/xion/x/globalfee/types" 10 | ) 11 | 12 | var _ types.QueryServer = &GrpcQuerier{} 13 | 14 | // ParamSource is a read only subset of paramtypes.Subspace 15 | type ParamSource interface { 16 | Get(ctx sdk.Context, key []byte, ptr interface{}) 17 | Has(ctx sdk.Context, key []byte) bool 18 | } 19 | 20 | type GrpcQuerier struct { 21 | paramSource ParamSource 22 | } 23 | 24 | func NewGrpcQuerier(paramSource ParamSource) GrpcQuerier { 25 | return GrpcQuerier{paramSource: paramSource} 26 | } 27 | 28 | // MinimumGasPrices return minimum gas prices 29 | func (g GrpcQuerier) Params(stdCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 30 | if req == nil { 31 | return nil, fmt.Errorf("invalid request") 32 | } 33 | 34 | var minGasPrices sdk.DecCoins 35 | var bypassMinFeeMsgTypes []string 36 | var maxTotalBypassMinFeeMsgGasUsage uint64 37 | ctx := sdk.UnwrapSDKContext(stdCtx) 38 | 39 | if g.paramSource.Has(ctx, types.ParamStoreKeyMinGasPrices) { 40 | g.paramSource.Get(ctx, types.ParamStoreKeyMinGasPrices, &minGasPrices) 41 | } 42 | if g.paramSource.Has(ctx, types.ParamStoreKeyBypassMinFeeMsgTypes) { 43 | g.paramSource.Get(ctx, types.ParamStoreKeyBypassMinFeeMsgTypes, &bypassMinFeeMsgTypes) 44 | } 45 | if g.paramSource.Has(ctx, types.ParamStoreKeyMaxTotalBypassMinFeeMsgGasUsage) { 46 | g.paramSource.Get(ctx, types.ParamStoreKeyMaxTotalBypassMinFeeMsgGasUsage, &maxTotalBypassMinFeeMsgGasUsage) 47 | } 48 | 49 | return &types.QueryParamsResponse{ 50 | Params: types.Params{ 51 | MinimumGasPrices: minGasPrices, 52 | BypassMinFeeMsgTypes: bypassMinFeeMsgTypes, 53 | MaxTotalBypassMinFeeMsgGasUsage: maxTotalBypassMinFeeMsgGasUsage, 54 | }, 55 | }, nil 56 | } 57 | -------------------------------------------------------------------------------- /x/feeabs/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // Module name store the name of the module 5 | ModuleName = "feeabs" 6 | 7 | // StoreKey is the string store representation 8 | StoreKey = ModuleName 9 | 10 | // RouterKey is the msg router key for the feeabs module 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute defines the module's query routing key 14 | QuerierRoute = ModuleName 15 | 16 | // MemStoreKey defines the in-memory store key 17 | MemStoreKey = "mem_feeabs" 18 | 19 | // Contract: Coin denoms cannot contain this character 20 | KeySeparator = "|" 21 | ) 22 | 23 | type ( 24 | ByPassMsgKey struct{} 25 | ByPassExceedMaxGasUsageKey struct{} 26 | GlobalFeeKey struct{} 27 | ) 28 | 29 | var ( 30 | StoreExponentialBackoff = []byte{0x10} // sub store that records the next block to send an ibc query or cross - chain swap 31 | 32 | OsmosisTwapExchangeRate = []byte{0x01} // Key for the exchange rate of osmosis (to native token) 33 | KeyChannelID = []byte{0x02} // Key for IBC channel to osmosis 34 | KeyHostChainConfigByFeeAbs = []byte{0x03} // Key for IBC channel to osmosis 35 | KeyHostChainConfigByOsmosis = []byte{0x04} // Key for IBC channel to osmosis 36 | KeyPrefixEpoch = []byte{0x05} // KeyPrefixEpoch defines prefix key for storing epochs. 37 | KeyTokenDenomPair = []byte{0x06} // Key store token denom pair on feeabs and osmosis 38 | ) 39 | 40 | func GetKeyHostZoneConfigByFeeabsIBCDenom(feeabsIbcDenom string) []byte { 41 | return append(KeyHostChainConfigByFeeAbs, []byte(feeabsIbcDenom)...) 42 | } 43 | 44 | func GetKeyHostZoneConfigByOsmosisIBCDenom(osmosisIbcDenom string) []byte { 45 | return append(KeyHostChainConfigByOsmosis, []byte(osmosisIbcDenom)...) 46 | } 47 | 48 | func GetKeyTwapExchangeRate(ibcDenom string) []byte { 49 | return append(OsmosisTwapExchangeRate, []byte(ibcDenom)...) 50 | } 51 | -------------------------------------------------------------------------------- /e2e_tests/app/upgrade_test.go: -------------------------------------------------------------------------------- 1 | package e2e_app 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | 7 | "github.com/burnt-labs/xion/e2e_tests/testlib" 8 | "github.com/cosmos/interchaintest/v10/ibc" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestAppUpgradeNetwork(t *testing.T) { 13 | t.Parallel() 14 | 15 | // Get the "from" image (current version in repo) 16 | xionFromImage, err := testlib.GetGHCRPackageNameCurrentRepo() 17 | require.NoError(t, err) 18 | 19 | // Get the "to" from (local image) which is where we want to upgrade from 20 | xionFromImageParts := strings.SplitN(xionFromImage, ":", 2) 21 | require.GreaterOrEqual(t, len(xionFromImageParts), 2, "xionFromImage should have repository:tag format") 22 | 23 | // Get the "to" image (local image) which is where we want to upgrade to 24 | xionToImageParts, err := testlib.GetXionImageTagComponents() 25 | require.NoError(t, err) 26 | require.GreaterOrEqual(t, len(xionToImageParts), 2, "xionToImage should have repository:tag format") 27 | 28 | xionToRepo := xionToImageParts[0] 29 | xionToVersion := xionToImageParts[1] 30 | 31 | // Use "recent" as upgrade name for local builds, otherwise use version-based name 32 | upgradeName := "recent" 33 | if xionToVersion != "local" { 34 | // For non-local builds, use version as upgrade name (e.g., "v20") 35 | upgradeName = xionToVersion 36 | } 37 | 38 | chainSpec := testlib.XionChainSpec(3, 1) 39 | chainSpec.Version = xionFromImageParts[1] 40 | chainSpec.ChainConfig.Images = []ibc.DockerImage{ 41 | { 42 | Repository: xionFromImageParts[0], 43 | Version: xionFromImageParts[1], 44 | UIDGID: "1025:1025", 45 | }, 46 | } 47 | 48 | // Build chain starting with the "from" image 49 | xion := testlib.BuildXionChainWithSpec(t, chainSpec) 50 | 51 | // Upgrade from current version in repo to local image 52 | testlib.CosmosChainUpgradeTest(t, xion, xionToRepo, xionToVersion, upgradeName) 53 | } 54 | -------------------------------------------------------------------------------- /indexer/multi_raw.go: -------------------------------------------------------------------------------- 1 | package indexer 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | "unsafe" 7 | 8 | "cosmossdk.io/collections" 9 | "cosmossdk.io/collections/indexes" 10 | ) 11 | 12 | // MultiIterateRaw provides IterateRaw functionality for Multi indexes. 13 | // 14 | // Background: 15 | // The Multi index type is missing the IterateRaw() method that other index types 16 | // (Unique, ReversePair) provide. The underlying refKeys field (a KeySet) already has 17 | // IterateRaw(), but it's not exposed through the Multi type's public API. 18 | // 19 | // This helper uses reflection to access the private refKeys field and call its 20 | // IterateRaw() method. This is safe because: 21 | // 1. We're only calling a public method (IterateRaw) on the accessed field 22 | // 2. We're not modifying any state or violating type safety 23 | // 3. The performance impact is negligible (reflection only happens once per iteration) 24 | func MultiIterateRaw[ReferenceKey, PrimaryKey, Value any]( 25 | ctx context.Context, 26 | multi *indexes.Multi[ReferenceKey, PrimaryKey, Value], 27 | start, end []byte, 28 | order collections.Order, 29 | ) (collections.Iterator[collections.Pair[ReferenceKey, PrimaryKey], collections.NoValue], error) { 30 | // Access the private refKeys field via reflection 31 | // The Multi struct has: refKeys collections.KeySet[collections.Pair[ReferenceKey, PrimaryKey]] 32 | v := reflect.ValueOf(multi).Elem() 33 | refKeysField := v.FieldByName("refKeys") 34 | 35 | // Make the unexported field accessible and extract the KeySet 36 | // This is equivalent to: return multi.refKeys.IterateRaw(ctx, start, end, order) 37 | refKeys := reflect.NewAt( 38 | refKeysField.Type(), 39 | unsafe.Pointer(refKeysField.UnsafeAddr()), 40 | ).Elem().Interface().(collections.KeySet[collections.Pair[ReferenceKey, PrimaryKey]]) 41 | 42 | // Call the public IterateRaw method on the KeySet 43 | return refKeys.IterateRaw(ctx, start, end, order) 44 | } 45 | -------------------------------------------------------------------------------- /x/feeabs/types/events_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestEventConstants(t *testing.T) { 10 | // Test all event type constants 11 | require.Equal(t, "timeout", EventTypeTimeout) 12 | require.Equal(t, "receive_feechain_verification_packet", EventTypePacket) 13 | require.Equal(t, "epoch_end", EventTypeEpochEnd) 14 | require.Equal(t, "epoch_start", EventTypeEpochStart) 15 | 16 | // Test all attribute key constants 17 | require.Equal(t, "success", AttributeKeyAckSuccess) 18 | require.Equal(t, "acknowledgement", AttributeKeyAck) 19 | require.Equal(t, "ack_error", AttributeKeyAckError) 20 | require.Equal(t, "epoch_number", AttributeEpochNumber) 21 | require.Equal(t, "start_time", AttributeEpochStartTime) 22 | require.Equal(t, "failure_type", AttributeKeyFailureType) 23 | require.Equal(t, "packet", AttributeKeyPacket) 24 | } 25 | 26 | func TestEventConstantsUniqueness(t *testing.T) { 27 | // Collect all event constants to ensure they're unique 28 | eventTypes := []string{ 29 | EventTypeTimeout, 30 | EventTypePacket, 31 | EventTypeEpochEnd, 32 | EventTypeEpochStart, 33 | } 34 | 35 | attributeKeys := []string{ 36 | AttributeKeyAckSuccess, 37 | AttributeKeyAck, 38 | AttributeKeyAckError, 39 | AttributeEpochNumber, 40 | AttributeEpochStartTime, 41 | AttributeKeyFailureType, 42 | AttributeKeyPacket, 43 | } 44 | 45 | // Check that event types are unique 46 | for i := 0; i < len(eventTypes); i++ { 47 | for j := i + 1; j < len(eventTypes); j++ { 48 | require.NotEqual(t, eventTypes[i], eventTypes[j], 49 | "Event types should be unique") 50 | } 51 | } 52 | 53 | // Check that attribute keys are unique 54 | for i := 0; i < len(attributeKeys); i++ { 55 | for j := i + 1; j < len(attributeKeys); j++ { 56 | require.NotEqual(t, attributeKeys[i], attributeKeys[j], 57 | "Attribute keys should be unique") 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/heighliner-alt.yaml: -------------------------------------------------------------------------------- 1 | name: Heighliner Action Build 2 | 3 | # reusable workflow, do not add triggers 4 | on: 5 | workflow_dispatch: 6 | 7 | env: 8 | GHCR: ghcr.io/${{ github.repository }} 9 | PLATFORMS: linux/amd64 10 | 11 | jobs: 12 | build-heighliner: 13 | name: main 14 | runs-on: ubuntu-latest 15 | permissions: 16 | id-token: write 17 | contents: read 18 | packages: write 19 | pull-requests: write 20 | 21 | steps: 22 | - name: Login to GitHub Container Registry 23 | uses: docker/login-action@v3 24 | with: 25 | registry: ghcr.io 26 | username: ${{ github.repository_owner }} 27 | password: ${{ secrets.GITHUB_TOKEN }} 28 | 29 | - name: Set up docker buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Metadata for heighliner 33 | id: meta-heighliner 34 | uses: docker/metadata-action@v5 35 | with: 36 | images: | 37 | ${{ env.GHCR }}/heighliner 38 | tags: | 39 | type=sha 40 | type=semver,pattern={{version}},enable=${{ github.event_name == 'push' }} 41 | type=raw,value=latest,enable={{is_default_branch}} 42 | 43 | - name: Build Heighliner image 44 | id: heighliner 45 | uses: burnt-labs/heighliner-action@v1.0.0-alpha10 46 | with: 47 | local: true 48 | tag: ${{ steps.meta-heighliner.outputs.tags }} 49 | chain: xion 50 | dockerfile: import 51 | platform: ${{ env.PLATFORMS }} 52 | binaries: '["/usr/bin/xiond"]' 53 | build-env: "[\"BUILD_TAGS=muslc\", \"BASE_IMAGE=${{ env.GHCR }}/xion\", \"VERSION=${{ fromJSON(steps.meta-heighliner.outputs.json).labels['org.opencontainers.image.version'] }}\"]" 54 | 55 | - name: Push Heighliner image 56 | run: | 57 | docker push ghcr.io/burnt-labs/xion/${{ steps.heighliner.outputs.tag }} 58 | -------------------------------------------------------------------------------- /x/globalfee/keeper/migrations_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "cosmossdk.io/math" 9 | storetypes "cosmossdk.io/store/types" 10 | 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 13 | "github.com/cosmos/cosmos-sdk/testutil" 14 | sdk "github.com/cosmos/cosmos-sdk/types" 15 | paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" 16 | 17 | "github.com/burnt-labs/xion/x/globalfee/keeper" 18 | "github.com/burnt-labs/xion/x/globalfee/types" 19 | ) 20 | 21 | func TestNewMigrator(t *testing.T) { 22 | // Create a test subspace 23 | storeKey := storetypes.NewKVStoreKey(paramstypes.StoreKey) 24 | tkey := storetypes.NewTransientStoreKey(paramstypes.TStoreKey) 25 | 26 | subspace := paramstypes.NewSubspace( 27 | codec.NewProtoCodec(codectypes.NewInterfaceRegistry()), 28 | codec.NewLegacyAmino(), 29 | storeKey, 30 | tkey, 31 | types.ModuleName, 32 | ).WithKeyTable(types.ParamKeyTable()) 33 | 34 | migrator := keeper.NewMigrator(subspace) 35 | require.NotNil(t, migrator) 36 | } 37 | 38 | func TestMigrate1to2(t *testing.T) { 39 | // Create a test subspace 40 | storeKey := storetypes.NewKVStoreKey(paramstypes.StoreKey) 41 | tkey := storetypes.NewTransientStoreKey(paramstypes.TStoreKey) 42 | ctx := testutil.DefaultContextWithDB(t, storeKey, tkey) 43 | 44 | subspace := paramstypes.NewSubspace( 45 | codec.NewProtoCodec(codectypes.NewInterfaceRegistry()), 46 | codec.NewLegacyAmino(), 47 | storeKey, 48 | tkey, 49 | types.ModuleName, 50 | ).WithKeyTable(types.ParamKeyTable()) 51 | 52 | // Set up initial params for migration 53 | initialParams := sdk.DecCoins{sdk.NewDecCoin("stake", math.NewInt(1000))} 54 | subspace.Set(ctx.Ctx, types.ParamStoreKeyMinGasPrices, &initialParams) 55 | 56 | migrator := keeper.NewMigrator(subspace) 57 | 58 | // Test that the migration function can be called 59 | err := migrator.Migrate1to2(ctx.Ctx) 60 | require.NoError(t, err) 61 | } 62 | -------------------------------------------------------------------------------- /proto/xion/mint/v1/mint.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.mint.v1; 3 | 4 | option go_package = "github.com/burnt-labs/xion/x/mint/types"; 5 | 6 | import "gogoproto/gogo.proto"; 7 | import "cosmos_proto/cosmos.proto"; 8 | import "amino/amino.proto"; 9 | 10 | // Minter represents the minting state. 11 | message Minter { 12 | // current annual inflation rate 13 | string inflation = 1 [ 14 | (cosmos_proto.scalar) = "cosmos.Dec", 15 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 16 | (gogoproto.nullable) = false 17 | ]; 18 | // current annual expected provisions 19 | string annual_provisions = 2 [ 20 | (cosmos_proto.scalar) = "cosmos.Dec", 21 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 22 | (gogoproto.nullable) = false 23 | ]; 24 | } 25 | 26 | // Params defines the parameters for the x/mint module. 27 | message Params { 28 | option (gogoproto.goproto_stringer) = false; 29 | option (amino.name) = "xion/x/mint/Params"; 30 | 31 | // type of coin to mint 32 | string mint_denom = 1; 33 | // maximum annual change in inflation rate 34 | string inflation_rate_change = 2 [ 35 | (cosmos_proto.scalar) = "cosmos.Dec", 36 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 37 | (gogoproto.nullable) = false 38 | ]; 39 | // maximum inflation rate 40 | string inflation_max = 3 [ 41 | (cosmos_proto.scalar) = "cosmos.Dec", 42 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 43 | (gogoproto.nullable) = false 44 | ]; 45 | // minimum inflation rate 46 | string inflation_min = 4 [ 47 | (cosmos_proto.scalar) = "cosmos.Dec", 48 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 49 | (gogoproto.nullable) = false 50 | ]; 51 | // goal of percent bonded atoms 52 | string goal_bonded = 5 [ 53 | (cosmos_proto.scalar) = "cosmos.Dec", 54 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 55 | (gogoproto.nullable) = false 56 | ]; 57 | // expected blocks per year 58 | uint64 blocks_per_year = 6; 59 | } 60 | -------------------------------------------------------------------------------- /.github/workflows/build-release-info.yaml: -------------------------------------------------------------------------------- 1 | name: Build Release Info 2 | # Run for new release tags only 3 | 4 | on: 5 | workflow_call: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-release-info: 10 | runs-on: ubuntu-latest 11 | env: 12 | GH_TOKEN: ${{ github.token }} 13 | 14 | steps: 15 | - name: checkout 16 | uses: actions/checkout@v5 17 | 18 | - name: Prepare environment 19 | run: mkdir -p release 20 | 21 | - name: Download artifacts 22 | uses: actions/download-artifact@v4 23 | with: 24 | path: release 25 | pattern: xiond-* 26 | merge-multiple: true 27 | 28 | - name: Create version.json 29 | working-directory: release 30 | run: | 31 | set -Eeuo pipefail 32 | upgrade_name=$(echo $GITHUB_REF_NAME | cut -d. -f1) 33 | jq -s '.[0] * (.[1] // {})' <(go mod edit -json | jq --arg name $upgrade_name '{ 34 | name: $name, 35 | tag: "${{ github.ref_name }}", 36 | height: 0, 37 | proposal: 0, 38 | go_version: .Go, 39 | cosmos_sdk_version: (.Require[] | select(.Path == "github.com/cosmos/cosmos-sdk") | .Version), 40 | cosmwasm_enabled: (.Require[] | select(.Path == "github.com/CosmWasm/wasmd") != null), 41 | cosmwasm_version: (.Require[] | select(.Path == "github.com/CosmWasm/wasmd") | .Version), 42 | ibc_go_version: (.Require[] | select(.Path == "github.com/cosmos/ibc-go/v10") | .Version), 43 | consensus: { 44 | type: "cometbft", 45 | version: (.Require[] | select(.Path == "github.com/cometbft/cometbft") | .Version) 46 | } 47 | }') binaries.json | tee version.json 48 | 49 | - name: Upload version.json files 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: version.json 53 | path: release/version.json 54 | retention-days: 3 55 | if-no-files-found: error 56 | -------------------------------------------------------------------------------- /app/params/weights.go: -------------------------------------------------------------------------------- 1 | package params 2 | 3 | // Default simulation operation weights for messages and gov proposals 4 | const ( 5 | DefaultWeightMsgSend int = 100 6 | DefaultWeightMsgMultiSend int = 10 7 | DefaultWeightMsgSetWithdrawAddress int = 50 8 | DefaultWeightMsgWithdrawDelegationReward int = 50 9 | DefaultWeightMsgWithdrawValidatorCommission int = 50 10 | DefaultWeightMsgFundCommunityPool int = 50 11 | DefaultWeightMsgDeposit int = 100 12 | DefaultWeightMsgVote int = 67 13 | DefaultWeightMsgUnjail int = 100 14 | DefaultWeightMsgCreateValidator int = 100 15 | DefaultWeightMsgEditValidator int = 5 16 | DefaultWeightMsgDelegate int = 100 17 | DefaultWeightMsgUndelegate int = 100 18 | DefaultWeightMsgBeginRedelegate int = 100 19 | 20 | DefaultWeightCommunitySpendProposal int = 5 21 | DefaultWeightTextProposal int = 5 22 | DefaultWeightParamChangeProposal int = 5 23 | 24 | DefaultWeightMsgStoreCode int = 50 25 | DefaultWeightMsgInstantiateContract int = 100 26 | DefaultWeightMsgExecuteContract int = 100 27 | DefaultWeightMsgUpdateAdmin int = 25 28 | DefaultWeightMsgClearAdmin int = 10 29 | DefaultWeightMsgMigrateContract int = 50 30 | 31 | DefaultWeightStoreCodeProposal int = 5 32 | DefaultWeightInstantiateContractProposal int = 5 33 | DefaultWeightUpdateAdminProposal int = 5 34 | DefaultWeightExecuteContractProposal int = 5 35 | DefaultWeightClearAdminProposal int = 5 36 | DefaultWeightMigrateContractProposal int = 5 37 | DefaultWeightSudoContractProposal int = 5 38 | DefaultWeightPinCodesProposal int = 5 39 | DefaultWeightUnpinCodesProposal int = 5 40 | DefaultWeightUpdateInstantiateConfigProposal int = 5 41 | DefaultWeightStoreAndInstantiateContractProposal int = 5 42 | ) 43 | -------------------------------------------------------------------------------- /x/jwk/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 9 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 10 | 11 | "github.com/burnt-labs/xion/x/jwk/types" 12 | ) 13 | 14 | func TestGenesisState_Validate(t *testing.T) { 15 | tests := []struct { 16 | desc string 17 | genState *types.GenesisState 18 | valid bool 19 | }{ 20 | { 21 | desc: "default is valid", 22 | genState: types.DefaultGenesis(), 23 | valid: true, 24 | }, 25 | { 26 | desc: "valid genesis state", 27 | genState: &types.GenesisState{ 28 | Params: types.DefaultParams(), 29 | AudienceList: []types.Audience{ 30 | { 31 | Aud: "0", 32 | Admin: authtypes.NewModuleAddress(govtypes.ModuleName).String(), 33 | }, 34 | { 35 | Aud: "1", 36 | Admin: authtypes.NewModuleAddress(govtypes.ModuleName).String(), 37 | }, 38 | }, 39 | // this line is used by starport scaffolding # types/genesis/validField 40 | }, 41 | valid: true, 42 | }, 43 | { 44 | desc: "duplicated audience", 45 | genState: &types.GenesisState{ 46 | AudienceList: []types.Audience{ 47 | { 48 | Aud: "0", 49 | Admin: authtypes.NewModuleAddress(govtypes.ModuleName).String(), 50 | }, 51 | { 52 | Aud: "0", 53 | Admin: authtypes.NewModuleAddress(govtypes.ModuleName).String(), 54 | }, 55 | }, 56 | }, 57 | valid: false, 58 | }, 59 | { 60 | desc: "invalid admin address", 61 | genState: &types.GenesisState{ 62 | AudienceList: []types.Audience{ 63 | { 64 | Aud: "test-audience", 65 | Admin: "invalid-address", 66 | }, 67 | }, 68 | }, 69 | valid: false, 70 | }, 71 | // this line is used by starport scaffolding # types/genesis/testcase 72 | } 73 | for _, tc := range tests { 74 | t.Run(tc.desc, func(t *testing.T) { 75 | err := tc.genState.Validate() 76 | if tc.valid { 77 | require.NoError(t, err) 78 | } else { 79 | require.Error(t, err) 80 | } 81 | }) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /x/feeabs/types/codec_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | "github.com/cosmos/cosmos-sdk/codec/types" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | func TestRegisterCodec(t *testing.T) { 14 | cdc := codec.NewLegacyAmino() 15 | 16 | // This should not panic 17 | require.NotPanics(t, func() { 18 | RegisterCodec(cdc) 19 | }) 20 | } 21 | 22 | func TestRegisterInterfaces(t *testing.T) { 23 | registry := types.NewInterfaceRegistry() 24 | 25 | // This should not panic 26 | require.NotPanics(t, func() { 27 | RegisterInterfaces(registry) 28 | }) 29 | 30 | // Just verify that the function runs without panic 31 | // The actual interface registration testing is complex and would require 32 | // a full setup with proper protobuf message registration 33 | } 34 | 35 | func TestAminoCodec(t *testing.T) { 36 | // Test that the amino codec is properly initialized 37 | require.NotNil(t, amino) 38 | 39 | // Test encoding/decoding a message 40 | // nolint: goconst 41 | validAddr := "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh" 42 | senderAddr, err := sdk.AccAddressFromBech32(validAddr) 43 | require.NoError(t, err) 44 | 45 | msg := NewMsgSendQueryIbcDenomTWAP(senderAddr) 46 | 47 | // Should be able to marshal and unmarshal 48 | bz, err := amino.MarshalJSON(msg) 49 | require.NoError(t, err) 50 | require.NotEmpty(t, bz) 51 | 52 | var decoded MsgSendQueryIbcDenomTWAP 53 | err = amino.UnmarshalJSON(bz, &decoded) 54 | require.NoError(t, err) 55 | require.Equal(t, msg.Sender, decoded.Sender) 56 | } 57 | 58 | func TestInit(t *testing.T) { 59 | // The init function should have been called during package initialization 60 | // We can test that amino codec is properly set up 61 | require.NotNil(t, amino) 62 | 63 | // Test that we can encode a basic SDK message 64 | // nolint: goconst 65 | validAddr := "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh" 66 | senderAddr, err := sdk.AccAddressFromBech32(validAddr) 67 | require.NoError(t, err) 68 | 69 | msg := NewMsgSendQueryIbcDenomTWAP(senderAddr) 70 | bz := msg.GetSignBytes() 71 | require.NotEmpty(t, bz) 72 | } 73 | -------------------------------------------------------------------------------- /scripts/release-info.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | if [ -n "${DEBUG:-}" ]; then 5 | set -x 6 | fi 7 | 8 | # Get the directory of this script, used to source other scripts 9 | : ${scripts_dir:="$(realpath $(dirname $0))"} 10 | : ${base_dir:="$(dirname $scripts_dir)"} 11 | : ${release_dir:="$base_dir/release"} 12 | 13 | # set binaries file 14 | binaries_json=${release_dir}/binaries.json 15 | 16 | # set ref name if not set 17 | : ${GITHUB_REF_NAME:=$(git describe --tags)} 18 | 19 | upgrade_name=$(echo $GITHUB_REF_NAME | cut -d. -f1) 20 | 21 | binaries=$( 22 | find "$release_dir" -name 'xiond_*.tar.gz' ! -name 'xiond_*darwin_all.tar.gz' | sort 23 | ) 24 | 25 | binaries_list=$( 26 | for file in ${binaries[@]}; do 27 | platform=$(basename "$file" ".tar.gz" | cut -d_ -f3- | sed -E 's/^rc[0-9]*-//g; s/_/\//g') 28 | checksum=$(sha256sum "$file" | awk '{ print $1 }') 29 | echo "\"$platform\": \"https://github.com/burnt-labs/xion/releases/download/${GITHUB_REF_NAME}/$(basename "$file")?checksum=sha256:$checksum"\" 30 | done 31 | ) 32 | 33 | echo "{\"binaries\": {$(paste -s -d "," <(echo "${binaries_list[@]}"))}}" | jq . > ${binaries_json} 34 | 35 | go mod edit -json | 36 | jq --rawfile binaries "$binaries_json" --arg name "$upgrade_name" --arg tag "$GITHUB_REF_NAME" '{ 37 | name: $name, 38 | tag: $tag, 39 | recommended_version: $tag, 40 | language: { 41 | type: "go", 42 | version: ("v" + (.Go | split(".") | first + "." + (.[1] // ""))) 43 | }, 44 | binaries: ($binaries | fromjson).binaries, 45 | sdk: { 46 | type: "cosmos", 47 | version: (.Require[] | select(.Path == "github.com/cosmos/cosmos-sdk") | .Version) 48 | }, 49 | consensus: { 50 | type: "cometbft", 51 | version: (.Require[] | select(.Path == "github.com/cometbft/cometbft") | .Version) 52 | }, 53 | cosmwasm: { 54 | version: (.Require[] | select(.Path == "github.com/CosmWasm/wasmd") | .Version), 55 | enabled: (.Require[] | select(.Path == "github.com/CosmWasm/wasmd") != null) 56 | }, 57 | ibc: { 58 | type: "go", 59 | version: (.Require[] | select(.Path == "github.com/cosmos/ibc-go/v8") | .Version) 60 | } 61 | }' | tee "$release_dir/version.json" 62 | -------------------------------------------------------------------------------- /proto/xion/v1/feegrant.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/protobuf/any.proto"; 6 | import "cosmos_proto/cosmos.proto"; 7 | import "amino/amino.proto"; 8 | 9 | option go_package = "github.com/burnt-labs/xion/x/xion/types"; 10 | 11 | // AuthzAllowance creates allowance only authz message for a specific grantee 12 | message AuthzAllowance { 13 | option (gogoproto.goproto_getters) = false; 14 | option (cosmos_proto.implements_interface) = 15 | "cosmos.feegrant.v1beta1.FeeAllowanceI"; 16 | option (amino.name) = "xion/AuthzAllowance"; 17 | 18 | // allowance can be any of basic and periodic fee allowance. 19 | google.protobuf.Any allowance = 1 20 | [ (cosmos_proto.accepts_interface) = 21 | "cosmos.feegrant.v1beta1.FeeAllowanceI" ]; 22 | 23 | // The address that can use this authorization-based allowance 24 | string authz_grantee = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 25 | } 26 | 27 | // ContractsAllowance creates allowance only for specific contracts 28 | message ContractsAllowance { 29 | option (gogoproto.goproto_getters) = false; 30 | option (cosmos_proto.implements_interface) = 31 | "cosmos.feegrant.v1beta1.FeeAllowanceI"; 32 | option (amino.name) = "xion/ContractsAllowance"; 33 | 34 | // allowance can be any allowance interface type. 35 | google.protobuf.Any allowance = 1 36 | [ (cosmos_proto.accepts_interface) = 37 | "cosmos.feegrant.v1beta1.FeeAllowanceI" ]; 38 | 39 | // List of contract addresses that this allowance applies to 40 | repeated string contract_addresses = 2 41 | [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; 42 | } 43 | 44 | // MultiAnyAllowance creates an allowance that pays if any of the internal 45 | // allowances are met 46 | message MultiAnyAllowance { 47 | option (gogoproto.goproto_getters) = false; 48 | option (cosmos_proto.implements_interface) = 49 | "cosmos.feegrant.v1beta1.FeeAllowanceI"; 50 | option (amino.name) = "xion/MultiAnyAllowance"; 51 | 52 | // allowance can be any allowance interface type. 53 | repeated google.protobuf.Any allowances = 1 54 | [ (cosmos_proto.accepts_interface) = 55 | "cosmos.feegrant.v1beta1.FeeAllowanceI" ]; 56 | } 57 | -------------------------------------------------------------------------------- /wasmbindings/query_plugin.go: -------------------------------------------------------------------------------- 1 | package wasmbinding 2 | 3 | import ( 4 | "fmt" 5 | 6 | wasmvmtypes "github.com/CosmWasm/wasmvm/v3/types" 7 | 8 | abci "github.com/cometbft/cometbft/abci/types" 9 | 10 | "github.com/cosmos/gogoproto/proto" 11 | 12 | "github.com/cosmos/cosmos-sdk/baseapp" 13 | "github.com/cosmos/cosmos-sdk/codec" 14 | sdk "github.com/cosmos/cosmos-sdk/types" 15 | ) 16 | 17 | // StargateQuerier dispatches whitelisted stargate queries 18 | func StargateQuerier(queryRouter baseapp.GRPCQueryRouter, cdc codec.Codec) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) { 19 | return func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) { 20 | protoResponseType, err := GetWhitelistedQuery(request.Path) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | route := queryRouter.Route(request.Path) 26 | if route == nil { 27 | return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("No route to query '%s'", request.Path)} 28 | } 29 | 30 | res, err := route(ctx, &abci.RequestQuery{ 31 | Data: request.Data, 32 | Path: request.Path, 33 | }) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | if res.Value == nil { 39 | return nil, fmt.Errorf("res returned from abci query route is nil") 40 | } 41 | 42 | bz, err := ConvertProtoToJSONMarshal(protoResponseType, res.Value, cdc) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | return bz, nil 48 | } 49 | } 50 | 51 | // ConvertProtoToJsonMarshal unmarshals the given bytes into a proto message and then marshals it to json. 52 | // This is done so that clients calling stargate queries do not need to define their own proto unmarshalers, 53 | // being able to use response directly by json marshalling, which is supported in cosmwasm. 54 | func ConvertProtoToJSONMarshal(protoResponseType proto.Message, bz []byte, cdc codec.Codec) ([]byte, error) { 55 | // unmarshal binary into stargate response data structure 56 | err := cdc.Unmarshal(bz, protoResponseType) 57 | if err != nil { 58 | return nil, wasmvmtypes.Unknown{} 59 | } 60 | 61 | bz, err = cdc.MarshalJSON(protoResponseType) 62 | if err != nil { 63 | return nil, wasmvmtypes.Unknown{} 64 | } 65 | 66 | protoResponseType.Reset() 67 | 68 | return bz, nil 69 | } 70 | -------------------------------------------------------------------------------- /contrib/relayer-tests/init_two_chainz_relayer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # init_two_chainz_relayer creates two xiond chains and configures the relayer 3 | 4 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 5 | WASMD_DATA="$(pwd)/data" 6 | RELAYER_CONF="$(pwd)/.relayer" 7 | 8 | # Ensure relayer is installed 9 | if ! [ -x "$(which rly)" ]; then 10 | echo "Error: wasmd is not installed. Try running 'make build-wasmd'" >&2 11 | exit 1 12 | fi 13 | 14 | # Ensure xiond is installed 15 | if ! [ -x "$(which xiond)" ]; then 16 | echo "Error: wasmd is not installed. Try running 'make build-wasmd'" >&2 17 | exit 1 18 | fi 19 | 20 | # Display software version for testers 21 | echo "WASMD VERSION INFO:" 22 | xiond version --long 23 | 24 | # Ensure jq is installed 25 | if [[ ! -x "$(which jq)" ]]; then 26 | echo "jq (a tool for parsing json in the command line) is required..." 27 | echo "https://stedolan.github.io/jq/download/" 28 | exit 1 29 | fi 30 | 31 | # Delete data from old runs 32 | rm -rf $WASMD_DATA &> /dev/null 33 | rm -rf $RELAYER_CONF &> /dev/null 34 | 35 | # Stop existing xiond processes 36 | killall xiond &> /dev/null 37 | 38 | set -e 39 | 40 | chainid0=ibc-0 41 | chainid1=ibc-1 42 | 43 | echo "Generating wasmd configurations..." 44 | mkdir -p $WASMD_DATA && cd $WASMD_DATA && cd ../ 45 | ./one_chain.sh xiond $chainid0 ./data 26657 26656 6060 9090 46 | ./one_chain.sh xiond $chainid1 ./data 26557 26556 6061 9091 47 | 48 | [ -f $WASMD_DATA/$chainid0.log ] && echo "$chainid0 initialized. Watch file $WASMD_DATA/$chainid0.log to see its execution." 49 | [ -f $WASMD_DATA/$chainid1.log ] && echo "$chainid1 initialized. Watch file $WASMD_DATA/$chainid1.log to see its execution." 50 | 51 | 52 | echo "Generating rly configurations..." 53 | rly config init 54 | rly config add-chains configs/xiond/chains 55 | rly config add-paths configs/xiond/paths 56 | 57 | SEED0=$(jq -r '.mnemonic' $WASMD_DATA/ibc-0/key_seed.json) 58 | SEED1=$(jq -r '.mnemonic' $WASMD_DATA/ibc-1/key_seed.json) 59 | echo "Key $(rly keys restore ibc-0 testkey "$SEED0") imported from ibc-0 to relayer..." 60 | echo "Key $(rly keys restore ibc-1 testkey "$SEED1") imported from ibc-1 to relayer..." 61 | echo "Creating light clients..." 62 | sleep 3 63 | rly light init ibc-0 -f 64 | rly light init ibc-1 -f 65 | -------------------------------------------------------------------------------- /proto/xion/feeabs/v1beta1/proposal.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.feeabs.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/burnt-labs/xion/x/feeabs/types"; 7 | 8 | // HostChainFeeAbsStatus represents the status of a host chain fee abstraction 9 | // configuration 10 | enum HostChainFeeAbsStatus { 11 | // HOST_CHAIN_FEE_ABS_STATUS_UNSPECIFIED indicates an unspecified status 12 | HOST_CHAIN_FEE_ABS_STATUS_UNSPECIFIED = 0; 13 | // HOST_CHAIN_FEE_ABS_STATUS_UPDATED indicates the configuration is up to date 14 | HOST_CHAIN_FEE_ABS_STATUS_UPDATED = 1; 15 | // HOST_CHAIN_FEE_ABS_STATUS_OUTDATED indicates the configuration is outdated 16 | HOST_CHAIN_FEE_ABS_STATUS_OUTDATED = 2; 17 | // HOST_CHAIN_FEE_ABS_STATUS_FROZEN indicates the configuration is frozen 18 | HOST_CHAIN_FEE_ABS_STATUS_FROZEN = 3; 19 | } 20 | 21 | // HostChainFeeAbsConfig 22 | message HostChainFeeAbsConfig { 23 | // ibc token is allowed to be used as fee token 24 | string ibc_denom = 1 [ (gogoproto.moretags) = "yaml:\"allowed_token\"" ]; 25 | // token_in in cross_chain swap contract. 26 | string osmosis_pool_token_denom_in = 2; 27 | // pool id 28 | uint64 pool_id = 3; 29 | // Host chain fee abstraction connection status 30 | HostChainFeeAbsStatus status = 4; 31 | } 32 | 33 | // AddHostZoneProposal 34 | message AddHostZoneProposal { 35 | option (gogoproto.goproto_getters) = false; 36 | // the title of the proposal 37 | string title = 1; 38 | // the description of the proposal 39 | string description = 2; 40 | // the host chain config 41 | HostChainFeeAbsConfig host_chain_config = 3; 42 | } 43 | 44 | // DeleteHostZoneProposal 45 | message DeleteHostZoneProposal { 46 | option (gogoproto.goproto_getters) = false; 47 | // the title of the proposal 48 | string title = 1; 49 | // the description of the proposal 50 | string description = 2; 51 | // the ibc denom of this token 52 | string ibc_denom = 3; 53 | } 54 | 55 | // SetHostZoneProposal 56 | message SetHostZoneProposal { 57 | option (gogoproto.goproto_getters) = false; 58 | // the title of the proposal 59 | string title = 1; 60 | // the description of the proposal 61 | string description = 2; 62 | // the host chain config 63 | HostChainFeeAbsConfig host_chain_config = 3; 64 | } 65 | -------------------------------------------------------------------------------- /wasmbindings/whitelist_all_test.go: -------------------------------------------------------------------------------- 1 | package wasmbinding 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // TestAllWhitelistedPathsEnsured iterates every path we add in init() and ensures 8 | // GetWhitelistedQuery returns a non-nil proto.Message without error. 9 | func TestAllWhitelistedPathsEnsured(t *testing.T) { 10 | paths := []string{ 11 | "/cosmos.auth.v1beta1.Query/Account", 12 | "/cosmos.auth.v1beta1.Query/Params", 13 | "/cosmos.auth.v1beta1.Query/ModuleAccounts", 14 | "/cosmos.authz.v1beta1.Query/Grants", 15 | "/cosmos.bank.v1beta1.Query/Balance", 16 | "/cosmos.bank.v1beta1.Query/DenomMetadata", 17 | "/cosmos.bank.v1beta1.Query/DenomsMetadata", 18 | "/cosmos.bank.v1beta1.Query/Params", 19 | "/cosmos.bank.v1beta1.Query/SupplyOf", 20 | "/cosmos.distribution.v1beta1.Query/Params", 21 | "/cosmos.distribution.v1beta1.Query/DelegatorWithdrawAddress", 22 | "/cosmos.distribution.v1beta1.Query/ValidatorCommission", 23 | "/cosmos.feegrant.v1beta1.Query/Allowance", 24 | "/cosmos.feegrant.v1beta1.Query/AllowancesByGranter", 25 | "/cosmos.gov.v1beta1.Query/Deposit", 26 | "/cosmos.gov.v1beta1.Query/Params", 27 | "/cosmos.gov.v1beta1.Query/Vote", 28 | "/cosmos.slashing.v1beta1.Query/Params", 29 | "/cosmos.slashing.v1beta1.Query/SigningInfo", 30 | "/cosmos.staking.v1beta1.Query/Delegation", 31 | "/cosmos.staking.v1beta1.Query/Params", 32 | "/cosmos.staking.v1beta1.Query/Validator", 33 | "/xion.v1.Query/WebAuthNVerifyRegister", 34 | "/xion.v1.Query/WebAuthNVerifyAuthenticate", 35 | "/xion.jwk.v1.Query/AudienceAll", 36 | "/xion.jwk.v1.Query/Audience", 37 | "/xion.jwk.v1.Query/Params", 38 | "/xion.jwk.v1.Query/ValidateJWT", 39 | } 40 | 41 | seen := make(map[string]struct{}, len(paths)) 42 | for _, p := range paths { 43 | if _, dup := seen[p]; dup { 44 | // guard against accidental duplicates in test slice 45 | continue 46 | } 47 | seen[p] = struct{}{} 48 | msg, err := GetWhitelistedQuery(p) 49 | if err != nil { 50 | // fail fast with specific path context 51 | t.Fatalf("expected path %s to be whitelisted, got err: %v", p, err) 52 | } 53 | if msg == nil { 54 | t.Fatalf("expected non-nil proto message for path %s", p) 55 | } 56 | } 57 | 58 | if len(seen) != len(paths) { 59 | t.Fatalf("deduplicated path count mismatch: expected %d got %d", len(paths), len(seen)) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /proto/buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: burnt-labs 6 | repository: abstractaccount 7 | commit: 9db2c5638029409d90d27cafad584745 8 | digest: shake256:9cb480d93cbd8c4665f2964e95415f2792935d557680180cfc8536eb8f8f944618411b1f06d633610afa36b47985afaaf9a805e4102d33a6c1a9370384505a48 9 | - remote: buf.build 10 | owner: burnt-labs 11 | repository: tokenfactory 12 | commit: 5e4d38acf183470b9e6490c6f0bc8847 13 | digest: shake256:19708e05dc669c995751b17cfb291aa6d3c58f4d1b5cec511eca8f4d52c4fc40d092ec9dc5565da33344c1094fd866e58aead5932534753264fc6b2a34f3227e 14 | - remote: buf.build 15 | owner: cosmos 16 | repository: cosmos-proto 17 | commit: 04467658e59e44bbb22fe568206e1f70 18 | digest: shake256:73a640bd60e0c523b0f8237ff34eab67c45a38b64bbbde1d80224819d272dbf316ac183526bd245f994af6608b025f5130483d0133c5edd385531326b5990466 19 | - remote: buf.build 20 | owner: cosmos 21 | repository: cosmos-sdk 22 | commit: 650cd9ad7f7a468e8e19975269958658 23 | digest: shake256:c2c1e67ed8efa7f5c6af7a2fc02a6c257dc78fe86911cbf4d3dd379710bf475565ffe2ae4f65221888373d515caa31be68b720897cccec6e0c6a1a91ff0b5227 24 | - remote: buf.build 25 | owner: cosmos 26 | repository: gogo-proto 27 | commit: 88ef6483f90f478fb938c37dde52ece3 28 | digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba 29 | - remote: buf.build 30 | owner: googleapis 31 | repository: googleapis 32 | commit: 61b203b9a9164be9a834f58c37be6f62 33 | digest: shake256:e619113001d6e284ee8a92b1561e5d4ea89a47b28bf0410815cb2fa23914df8be9f1a6a98dcf069f5bc2d829a2cfb1ac614863be45cd4f8a5ad8606c5f200224 34 | - remote: buf.build 35 | owner: protocolbuffers 36 | repository: wellknowntypes 37 | commit: a4aee59cf3714106961b09d99b349cd1 38 | digest: shake256:7e2aa4fb37e2be8dc8a4bcbebaec00635abbcc7333df40ba6412a666335f66c5c0705ce4cc5c207e728412ac3d81850545f90e8535da66712a17ab42923be6bd 39 | - remote: buf.build 40 | owner: tendermint 41 | repository: tendermint 42 | commit: 33ed361a90514289beabf3189e1d7665 43 | digest: shake256:038267e06294714fd883610626554b04a127b576b4e253befb4206cb72d5d3c1eeccacd4b9ec8e3fb891f7c14e1cb0f770c077d2989638995b0a61c85afedb1d 44 | -------------------------------------------------------------------------------- /x/jwk/types/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | errorsmod "cosmossdk.io/errors" 5 | 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 8 | ) 9 | 10 | var _ paramtypes.ParamSet = (*Params)(nil) 11 | 12 | var ( 13 | ParamStoreKeyTimeOffset = []byte("TimeOffset") 14 | ParamStoreKeyDeploymentGas = []byte("DeploymentGas") 15 | ) 16 | 17 | // ParamKeyTable the param key table for launch module 18 | func ParamKeyTable() paramtypes.KeyTable { 19 | return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) 20 | } 21 | 22 | // NewParams creates a new Params instance 23 | func NewParams(timeOffset, deploymentGas uint64) Params { 24 | return Params{ 25 | TimeOffset: timeOffset, 26 | DeploymentGas: deploymentGas, 27 | } 28 | } 29 | 30 | // DefaultParams returns a default set of parameters 31 | func DefaultParams() Params { 32 | deploymentGas := uint64(10_000) 33 | timeOffset := uint64(30 * 1000) // default to 30 seconds 34 | 35 | return NewParams(timeOffset, deploymentGas) 36 | } 37 | 38 | // ParamSetPairs get the params.ParamSet 39 | func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { 40 | return paramtypes.ParamSetPairs{ 41 | paramtypes.NewParamSetPair(ParamStoreKeyDeploymentGas, &p.DeploymentGas, validateDeploymentGas), 42 | paramtypes.NewParamSetPair(ParamStoreKeyTimeOffset, &p.TimeOffset, validateTimeOffset), 43 | } 44 | } 45 | 46 | func validateDeploymentGas(i interface{}) error { 47 | v, ok := i.(uint64) 48 | if !ok { 49 | return errorsmod.Wrapf(sdkerrors.ErrInvalidType, "type: %T, expected uint64", i) 50 | } 51 | 52 | if v == 0 { 53 | return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "deployment gas must be positive") 54 | } 55 | 56 | return nil 57 | } 58 | 59 | func validateTimeOffset(i interface{}) error { 60 | v, ok := i.(uint64) 61 | if !ok { 62 | return errorsmod.Wrapf(sdkerrors.ErrInvalidType, "type: %T, expected uint64", i) 63 | } 64 | 65 | if v == 0 { 66 | return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "time offset must be positive") 67 | } 68 | 69 | return nil 70 | } 71 | 72 | // Validate validates the set of params 73 | func (p Params) Validate() error { 74 | if err := validateDeploymentGas(p.DeploymentGas); err != nil { 75 | return err 76 | } 77 | 78 | return validateTimeOffset(p.TimeOffset) 79 | } 80 | -------------------------------------------------------------------------------- /x/xion/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types // noalias 2 | 3 | import ( 4 | "context" 5 | 6 | aatypes "github.com/burnt-labs/abstract-account/x/abstractaccount/types" 7 | 8 | "cosmossdk.io/math" 9 | 10 | sdktypes "github.com/cosmos/cosmos-sdk/types" 11 | banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 12 | ) 13 | 14 | // BankKeeper defines the contract needed to be fulfilled for banking and supply 15 | // dependencies. 16 | type BankKeeper interface { 17 | SendCoinsFromModuleToAccount( 18 | ctx context.Context, 19 | senderModule string, 20 | recipientAddr sdktypes.AccAddress, 21 | amt sdktypes.Coins, 22 | ) error 23 | SendCoinsFromModuleToModule( 24 | ctx context.Context, 25 | senderModule, 26 | recipientModule string, 27 | amt sdktypes.Coins, 28 | ) error 29 | SendCoinsFromAccountToModule( 30 | ctx context.Context, 31 | senderAddr sdktypes.AccAddress, 32 | recipientModule string, 33 | amt sdktypes.Coins, 34 | ) error 35 | IsSendEnabledCoins(ctx context.Context, coins ...sdktypes.Coin) error 36 | BlockedAddr(addr sdktypes.AccAddress) bool 37 | SendCoins(ctx context.Context, fromAddr sdktypes.AccAddress, toAddr sdktypes.AccAddress, amt sdktypes.Coins) error 38 | InputOutputCoins(ctx context.Context, input banktypes.Input, outputs []banktypes.Output) error 39 | GetBalance(ctx context.Context, addr sdktypes.AccAddress, denom string) sdktypes.Coin 40 | BurnCoins(ctx context.Context, moduleName string, amt sdktypes.Coins) error 41 | } 42 | 43 | type AccountKeeper interface { 44 | GetModuleAccount(ctx context.Context, moduleName string) sdktypes.ModuleAccountI 45 | } 46 | 47 | type WasmKeeper interface { 48 | Migrate(ctx sdktypes.Context, contractAddress, caller sdktypes.AccAddress, newCodeID uint64, msg []byte) ([]byte, error) 49 | IterateContractsByCode(ctx sdktypes.Context, codeID uint64, cb func(address sdktypes.AccAddress) bool) 50 | PinCode(ctx sdktypes.Context, codeID uint64) error 51 | UnpinCode(ctx sdktypes.Context, codeID uint64) error 52 | } 53 | 54 | type AbstractAccountKeeper interface { 55 | GetParams(ctx sdktypes.Context) (*aatypes.Params, error) 56 | SetParams(ctx sdktypes.Context, params *aatypes.Params) error 57 | } 58 | 59 | type StakingKeeper interface { 60 | TotalBondedTokens(ctx context.Context) (math.Int, error) 61 | BondedRatio(ctx context.Context) (math.LegacyDec, error) 62 | } 63 | -------------------------------------------------------------------------------- /app/config_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | 7 | wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" 8 | "github.com/stretchr/testify/require" 9 | 10 | "github.com/burnt-labs/xion/indexer" 11 | ) 12 | 13 | func TestCustomconfigTemplate(t *testing.T) { 14 | // Create a default wasm config 15 | wasmConfig := wasmtypes.DefaultNodeConfig() 16 | 17 | // Test the template generation 18 | template := CustomconfigTemplate(wasmConfig) 19 | 20 | // Verify template is not empty 21 | require.NotEmpty(t, template) 22 | 23 | // Verify it contains wasm configuration markers 24 | require.Contains(t, template, "wasm", "Template should contain wasm configuration") 25 | 26 | // Verify it's a valid template with expected sections 27 | require.True(t, strings.Contains(template, "[") && strings.Contains(template, "]"), 28 | "Template should contain TOML sections") 29 | } 30 | 31 | func TestDefaultConfig(t *testing.T) { 32 | // Call DefaultConfig 33 | template, configInterface := DefaultConfig() 34 | 35 | // Verify template is returned 36 | require.NotEmpty(t, template) 37 | require.NotNil(t, configInterface) 38 | 39 | // Type assert to CustomConfig 40 | customConfig, ok := configInterface.(CustomConfig) 41 | require.True(t, ok, "Config should be of type CustomConfig") 42 | 43 | // Verify MinGasPrices is set correctly 44 | require.Equal(t, "0uxion", customConfig.MinGasPrices) 45 | 46 | // Verify Wasm config is set 47 | require.NotNil(t, customConfig.Wasm) 48 | require.NotNil(t, customConfig.Wasm.SimulationGasLimit) 49 | require.Equal(t, uint64(50_000_00), *customConfig.Wasm.SimulationGasLimit) 50 | require.Equal(t, uint64(50_000_00), customConfig.Wasm.SmartQueryGasLimit) 51 | require.Equal(t, uint32(1024), customConfig.Wasm.MemoryCacheSize) 52 | 53 | // Verify Indexer config is set 54 | require.NotNil(t, customConfig.Indexer) 55 | expectedIndexerConfig := indexer.DefaultConfig() 56 | require.Equal(t, expectedIndexerConfig.Enabled, customConfig.Indexer.Enabled) 57 | 58 | // Verify template contains wasm configuration 59 | require.Contains(t, template, "wasm") 60 | } 61 | 62 | func TestCustomConfig(t *testing.T) { 63 | // Test that CustomConfig struct can be created 64 | config := CustomConfig{ 65 | Indexer: indexer.Config{ 66 | Enabled: true, 67 | }, 68 | } 69 | 70 | require.True(t, config.Indexer.Enabled) 71 | } 72 | -------------------------------------------------------------------------------- /x/xion/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "cosmossdk.io/x/feegrant" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | "github.com/cosmos/cosmos-sdk/codec/legacy" 8 | "github.com/cosmos/cosmos-sdk/codec/types" 9 | cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | "github.com/cosmos/cosmos-sdk/types/msgservice" 12 | 13 | feeabstypes "github.com/burnt-labs/xion/x/feeabs/types" 14 | xionMintTypes "github.com/burnt-labs/xion/x/mint/types" 15 | ) 16 | 17 | // RegisterLegacyAminoCodec registers the necessary x/bank interfaces and concrete types 18 | // on the provided LegacyAmino codec. These types are used for Amino JSON serialization. 19 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 20 | legacy.RegisterAminoMsg(cdc, &MsgSend{}, "xion/MsgSend") 21 | legacy.RegisterAminoMsg(cdc, &MsgMultiSend{}, "xion/MsgMultiSend") 22 | legacy.RegisterAminoMsg(cdc, &MsgSetPlatformPercentage{}, "xion/MsgSetPlatformPercentage") 23 | legacy.RegisterAminoMsg(cdc, &MsgSetPlatformMinimum{}, "xion/MsgSetPlatformMinimum") 24 | legacy.RegisterAminoMsg(cdc, &xionMintTypes.MsgUpdateParams{}, "xion/x/mint/MsgUpdateParams") 25 | 26 | cdc.RegisterConcrete(&AuthzAllowance{}, "xion/AuthzAllowance", nil) 27 | cdc.RegisterConcrete(&ContractsAllowance{}, "xion/ContractsAllowance", nil) 28 | cdc.RegisterConcrete(&MultiAnyAllowance{}, "xion/MultiAnyAllowance", nil) 29 | cdc.RegisterConcrete(xionMintTypes.Params{}, "xion/x/mint/Params", nil) 30 | } 31 | 32 | func RegisterInterfaces(registry types.InterfaceRegistry) { 33 | registry.RegisterImplementations((*sdk.Msg)(nil), 34 | &MsgSend{}, 35 | &MsgMultiSend{}, 36 | &MsgSetPlatformPercentage{}, 37 | &MsgSetPlatformMinimum{}, 38 | &xionMintTypes.MsgUpdateParams{}, 39 | ) 40 | 41 | registry.RegisterInterface( 42 | "cosmos.feegrant.v1beta1.FeeAllowanceI", 43 | (*feegrant.FeeAllowanceI)(nil), 44 | &AuthzAllowance{}, 45 | &ContractsAllowance{}, 46 | &MultiAnyAllowance{}, 47 | ) 48 | 49 | // Register feeabs interfaces for reading historical proposals 50 | feeabstypes.RegisterInterfaces(registry) 51 | 52 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 53 | } 54 | 55 | var amino = codec.NewLegacyAmino() 56 | 57 | func init() { 58 | RegisterLegacyAminoCodec(amino) 59 | cryptocodec.RegisterCrypto(amino) 60 | sdk.RegisterLegacyAminoCodec(amino) 61 | } 62 | -------------------------------------------------------------------------------- /x/xion/client/cli/query_webauthn.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | 9 | "github.com/burnt-labs/xion/x/xion/types" 10 | ) 11 | 12 | func CmdWebAuthNVerifyRegister() *cobra.Command { 13 | cmd := &cobra.Command{ 14 | Use: "webauthn-register [addr] [challenge] [rp] [data]", 15 | Short: "Test Webauthn Registration", 16 | Args: cobra.ExactArgs(4), 17 | RunE: func(cmd *cobra.Command, args []string) error { 18 | reqAddr := args[0] 19 | reqChallenge := args[1] 20 | reqRP := args[2] 21 | reqData := []byte(args[3]) 22 | 23 | clientCtx, err := client.GetClientQueryContext(cmd) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | queryClient := types.NewQueryClient(clientCtx) 29 | 30 | params := &types.QueryWebAuthNVerifyRegisterRequest{ 31 | Addr: reqAddr, 32 | Challenge: reqChallenge, 33 | Rp: reqRP, 34 | Data: reqData, 35 | } 36 | 37 | res, err := queryClient.WebAuthNVerifyRegister(cmd.Context(), params) 38 | if err != nil { 39 | return err 40 | } 41 | 42 | return clientCtx.PrintProto(res) 43 | }, 44 | } 45 | 46 | flags.AddQueryFlagsToCmd(cmd) 47 | 48 | return cmd 49 | } 50 | 51 | func CmdWebAuthNVerifyAuthenticate() *cobra.Command { 52 | cmd := &cobra.Command{ 53 | Use: "webauthn-authenticate [addr] [challenge] [rp] [credential] [data]", 54 | Short: "Test Webauthn Authentication", 55 | Args: cobra.ExactArgs(5), 56 | RunE: func(cmd *cobra.Command, args []string) error { 57 | reqAddr := args[0] 58 | reqChallenge := args[1] 59 | reqRP := args[2] 60 | reqCredential := []byte(args[3]) 61 | reqData := []byte(args[4]) 62 | 63 | clientCtx, err := client.GetClientQueryContext(cmd) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | queryClient := types.NewQueryClient(clientCtx) 69 | 70 | params := &types.QueryWebAuthNVerifyAuthenticateRequest{ 71 | Addr: reqAddr, 72 | Challenge: reqChallenge, 73 | Rp: reqRP, 74 | Credential: reqCredential, 75 | Data: reqData, 76 | } 77 | 78 | res, err := queryClient.WebAuthNVerifyAuthenticate(cmd.Context(), params) 79 | if err != nil { 80 | return err 81 | } 82 | 83 | return clientCtx.PrintProto(res) 84 | }, 85 | } 86 | 87 | flags.AddQueryFlagsToCmd(cmd) 88 | 89 | return cmd 90 | } 91 | -------------------------------------------------------------------------------- /.github/workflows/build-release.yaml: -------------------------------------------------------------------------------- 1 | name: Build Release 2 | # Run for new release tags only 3 | # superceded by goreleaser.yaml 4 | 5 | on: 6 | workflow_call: 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build-release: 11 | runs-on: ubuntu-latest 12 | env: 13 | GH_TOKEN: ${{ github.token }} 14 | 15 | steps: 16 | - name: Create release directory 17 | run: mkdir -p release 18 | 19 | - name: Build Changelog 20 | id: changelog 21 | uses: mikepenz/release-changelog-builder-action@v4 22 | with: 23 | token: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | - name: Output Changelog 26 | run: echo "${{steps.changelog.outputs.changelog}}" 27 | 28 | - name: Create release for ${{ github.ref_name }} 29 | id: update-release 30 | uses: ncipollo/release-action@v1 31 | with: 32 | name: Release ${{ github.ref_name }} 33 | allowUpdates: true 34 | body: ${{ steps.changelog.outputs.changelog }} 35 | draft: false 36 | generateReleaseNotes: true 37 | prerelease: true 38 | removeArtifacts: false # important, true will remove src archives 39 | tag: ${{ github.ref_name }} 40 | token: ${{ secrets.GITHUB_TOKEN }} 41 | updateOnlyUnreleased: true 42 | 43 | - name: Download release archives 44 | working-directory: release 45 | run: | 46 | gh release download ${{ github.ref_name }} \ 47 | --repo=${{ github.repository }} \ 48 | --archive=tar.gz 49 | gh release download ${{ github.ref_name }} \ 50 | --repo=${{ github.repository }} \ 51 | --archive=zip 52 | ls 53 | 54 | - name: Download artifacts 55 | uses: actions/download-artifact@v4 56 | with: 57 | path: release 58 | pattern: xiond-* 59 | merge-multiple: true 60 | 61 | - name: Create checksums 62 | working-directory: release 63 | run: | 64 | sha256sum * | tee checksum.txt 65 | 66 | - name: Remove release archives 67 | working-directory: release 68 | run: | 69 | rm -f *.zip *.tar.gz 70 | ls 71 | 72 | - name: Upload release assets 73 | working-directory: release 74 | run: | 75 | gh release upload ${{ github.ref_name }} * \ 76 | --repo ${{ github.repository }} \ 77 | --clobber 78 | -------------------------------------------------------------------------------- /x/globalfee/querier_test.go: -------------------------------------------------------------------------------- 1 | package globalfee_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | storetypes "cosmossdk.io/store/types" 9 | 10 | "github.com/cosmos/cosmos-sdk/codec" 11 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 12 | "github.com/cosmos/cosmos-sdk/testutil" 13 | paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" 14 | 15 | "github.com/burnt-labs/xion/x/globalfee" 16 | "github.com/burnt-labs/xion/x/globalfee/types" 17 | ) 18 | 19 | func TestNewGrpcQuerier(t *testing.T) { 20 | // Create a test subspace 21 | storeKey := storetypes.NewKVStoreKey(paramstypes.StoreKey) 22 | tkey := storetypes.NewTransientStoreKey(paramstypes.TStoreKey) 23 | 24 | subspace := paramstypes.NewSubspace( 25 | codec.NewProtoCodec(codectypes.NewInterfaceRegistry()), 26 | codec.NewLegacyAmino(), 27 | storeKey, 28 | tkey, 29 | types.ModuleName, 30 | ).WithKeyTable(types.ParamKeyTable()) 31 | 32 | querier := globalfee.NewGrpcQuerier(subspace) 33 | require.NotNil(t, querier) 34 | } 35 | 36 | func TestGrpcQuerierParams(t *testing.T) { 37 | // Create a test subspace 38 | storeKey := storetypes.NewKVStoreKey(paramstypes.StoreKey) 39 | tkey := storetypes.NewTransientStoreKey(paramstypes.TStoreKey) 40 | ctx := testutil.DefaultContextWithDB(t, storeKey, tkey) 41 | 42 | subspace := paramstypes.NewSubspace( 43 | codec.NewProtoCodec(codectypes.NewInterfaceRegistry()), 44 | codec.NewLegacyAmino(), 45 | storeKey, 46 | tkey, 47 | types.ModuleName, 48 | ).WithKeyTable(types.ParamKeyTable()) 49 | 50 | // Set default params 51 | params := types.DefaultParams() 52 | subspace.SetParamSet(ctx.Ctx, ¶ms) 53 | 54 | querier := globalfee.NewGrpcQuerier(subspace) 55 | 56 | // Test Params query 57 | req := &types.QueryParamsRequest{} 58 | resp, err := querier.Params(ctx.Ctx, req) 59 | require.NoError(t, err) 60 | require.NotNil(t, resp) 61 | 62 | // Compare individual fields - MinimumGasPrices can be either empty slice or nil 63 | require.True(t, (len(params.MinimumGasPrices) == 0 && len(resp.Params.MinimumGasPrices) == 0), 64 | "MinimumGasPrices should both be empty") 65 | require.Equal(t, params.BypassMinFeeMsgTypes, resp.Params.BypassMinFeeMsgTypes) 66 | require.Equal(t, params.MaxTotalBypassMinFeeMsgGasUsage, resp.Params.MaxTotalBypassMinFeeMsgGasUsage) 67 | 68 | // Test Params query with nil request 69 | resp, err = querier.Params(ctx.Ctx, nil) 70 | require.Error(t, err) 71 | require.Nil(t, resp) 72 | } 73 | -------------------------------------------------------------------------------- /x/feeabs/types/ibc.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "time" 5 | 6 | abci "github.com/cometbft/cometbft/abci/types" 7 | 8 | codec "github.com/cosmos/cosmos-sdk/codec" 9 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | const ( 14 | // IBCPortID is the default port id that profiles module binds to. 15 | IBCPortID = "feeabs" 16 | ) 17 | 18 | var ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) 19 | 20 | // IBCPortKey defines the key to store the port ID in store. 21 | var ( 22 | IBCPortKey = []byte{0x01} 23 | FeePoolAddressKey = []byte{0x02} 24 | ) 25 | 26 | // NewQueryArithmeticTwapToNowRequest create new packet for ibc. 27 | func NewQueryArithmeticTwapToNowRequest( 28 | poolID uint64, 29 | baseDenom string, 30 | quoteDenom string, 31 | startTime time.Time, 32 | ) QueryArithmeticTwapToNowRequest { 33 | return QueryArithmeticTwapToNowRequest{ 34 | PoolId: poolID, 35 | BaseAsset: baseDenom, 36 | QuoteAsset: quoteDenom, 37 | StartTime: startTime, 38 | } 39 | } 40 | 41 | func (p QueryArithmeticTwapToNowRequest) GetBytes() []byte { 42 | return ModuleCdc.MustMarshal(&p) 43 | } 44 | 45 | func SerializeCosmosQuery(reqs []abci.RequestQuery) (bz []byte, err error) { 46 | q := &CosmosQuery{ 47 | Requests: reqs, 48 | } 49 | return ModuleCdc.Marshal(q) 50 | } 51 | 52 | func DeserializeCosmosQuery(bz []byte) (reqs []abci.RequestQuery, err error) { 53 | var q CosmosQuery 54 | err = ModuleCdc.Unmarshal(bz, &q) 55 | return q.Requests, err 56 | } 57 | 58 | func SerializeCosmosResponse(resps []abci.ResponseQuery) (bz []byte, err error) { 59 | r := &CosmosResponse{ 60 | Responses: resps, 61 | } 62 | return ModuleCdc.Marshal(r) 63 | } 64 | 65 | func DeserializeCosmosResponse(bz []byte) (resps []abci.ResponseQuery, err error) { 66 | var r CosmosResponse 67 | err = ModuleCdc.Unmarshal(bz, &r) 68 | return r.Responses, err 69 | } 70 | 71 | func NewInterchainQueryRequest(path string, data []byte) InterchainQueryRequest { 72 | return InterchainQueryRequest{ 73 | Data: data, 74 | Path: path, 75 | } 76 | } 77 | 78 | func NewInterchainQueryPacketData(data []byte, memo string) InterchainQueryPacketData { 79 | return InterchainQueryPacketData{ 80 | Data: data, 81 | Memo: memo, 82 | } 83 | } 84 | 85 | // GetBytes returns the JSON marshalled interchain query packet data. 86 | func (p InterchainQueryPacketData) GetBytes() []byte { 87 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&p)) 88 | } 89 | -------------------------------------------------------------------------------- /x/jwk/keeper/query_audience.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | 9 | "cosmossdk.io/store/prefix" 10 | 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | "github.com/cosmos/cosmos-sdk/types/query" 13 | 14 | "github.com/burnt-labs/xion/x/jwk/types" 15 | ) 16 | 17 | func (k Keeper) AudienceAll(goCtx context.Context, req *types.QueryAudienceAllRequest) (*types.QueryAudienceAllResponse, error) { 18 | if req == nil { 19 | return nil, status.Error(codes.InvalidArgument, "invalid request") 20 | } 21 | 22 | if req.Pagination != nil && req.Pagination.Limit > 100 { 23 | return nil, status.Error(codes.ResourceExhausted, "requests audience page size >100, too large") 24 | } 25 | 26 | var audiences []types.Audience 27 | ctx := sdk.UnwrapSDKContext(goCtx) 28 | 29 | store := ctx.KVStore(k.storeKey) 30 | audienceStore := prefix.NewStore(store, types.KeyPrefix(types.AudienceKeyPrefix)) 31 | 32 | pageRes, err := query.Paginate(audienceStore, req.Pagination, func(_ []byte, value []byte) error { 33 | var audience types.Audience 34 | if err := k.cdc.Unmarshal(value, &audience); err != nil { 35 | return err 36 | } 37 | 38 | audiences = append(audiences, audience) 39 | return nil 40 | }) 41 | if err != nil { 42 | return nil, status.Error(codes.Internal, err.Error()) 43 | } 44 | 45 | return &types.QueryAudienceAllResponse{Audience: audiences, Pagination: pageRes}, nil 46 | } 47 | 48 | func (k Keeper) Audience(goCtx context.Context, req *types.QueryAudienceRequest) (*types.QueryAudienceResponse, error) { 49 | if req == nil { 50 | return nil, status.Error(codes.InvalidArgument, "invalid request") 51 | } 52 | ctx := sdk.UnwrapSDKContext(goCtx) 53 | 54 | val, found := k.GetAudience( 55 | ctx, 56 | req.Aud, 57 | ) 58 | if !found { 59 | return nil, status.Error(codes.NotFound, "not found") 60 | } 61 | 62 | return &types.QueryAudienceResponse{Audience: val}, nil 63 | } 64 | 65 | func (k Keeper) AudienceClaim(goCtx context.Context, req *types.QueryAudienceClaimRequest) (*types.QueryAudienceClaimResponse, error) { 66 | if req == nil { 67 | return nil, status.Error(codes.InvalidArgument, "invalid request") 68 | } 69 | ctx := sdk.UnwrapSDKContext(goCtx) 70 | 71 | val, found := k.GetAudienceClaim( 72 | ctx, 73 | req.Hash, 74 | ) 75 | if !found { 76 | return nil, status.Error(codes.NotFound, "not found") 77 | } 78 | 79 | return &types.QueryAudienceClaimResponse{Claim: &val}, nil 80 | } 81 | -------------------------------------------------------------------------------- /x/jwk/migrations/v1/migration_test.go: -------------------------------------------------------------------------------- 1 | package v1_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | storetypes "cosmossdk.io/store/types" 9 | 10 | "github.com/cosmos/cosmos-sdk/codec" 11 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 12 | "github.com/cosmos/cosmos-sdk/testutil" 13 | paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" 14 | 15 | v1migration "github.com/burnt-labs/xion/x/jwk/migrations/v1" 16 | "github.com/burnt-labs/xion/x/jwk/types" 17 | ) 18 | 19 | func TestMigrateStore(t *testing.T) { 20 | storeKey := storetypes.NewKVStoreKey(types.StoreKey) 21 | tkey := storetypes.NewTransientStoreKey(paramstypes.TStoreKey) 22 | ctx := testutil.DefaultContextWithDB(t, storeKey, tkey) 23 | cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) 24 | 25 | // Test case 1: Create param subspace WITHOUT key table first 26 | paramStore := paramstypes.NewSubspace( 27 | cdc, 28 | codec.NewLegacyAmino(), 29 | storeKey, 30 | tkey, 31 | types.ModuleName, 32 | ) 33 | // Don't call WithKeyTable here to test the HasKeyTable() branch 34 | 35 | // Test MigrateStore - this should exercise the key table creation branch 36 | err := v1migration.MigrateStore(ctx.Ctx, paramStore) 37 | require.NoError(t, err) 38 | 39 | // Verify params were set correctly 40 | // After MigrateStore, the paramStore now has a key table, so we can use it directly 41 | var params types.Params 42 | paramStore.GetParamSet(ctx.Ctx, ¶ms) 43 | require.Equal(t, uint64(10_000), params.DeploymentGas) 44 | require.Equal(t, uint64(30_000), params.TimeOffset) 45 | 46 | // Test case 2: Create a fresh param subspace with key table already set 47 | storeKey2 := storetypes.NewKVStoreKey(types.StoreKey + "2") 48 | tkey2 := storetypes.NewTransientStoreKey(paramstypes.TStoreKey + "2") 49 | ctx2 := testutil.DefaultContextWithDB(t, storeKey2, tkey2) 50 | 51 | paramStoreWithKeyTable := paramstypes.NewSubspace( 52 | cdc, 53 | codec.NewLegacyAmino(), 54 | storeKey2, 55 | tkey2, 56 | types.ModuleName, 57 | ).WithKeyTable(types.ParamKeyTable()) 58 | 59 | // Test MigrateStore with key table already present 60 | err = v1migration.MigrateStore(ctx2.Ctx, paramStoreWithKeyTable) 61 | require.NoError(t, err) 62 | 63 | // Verify params were set correctly 64 | var params2 types.Params 65 | paramStoreWithKeyTable.GetParamSet(ctx2.Ctx, ¶ms2) 66 | require.Equal(t, uint64(10_000), params2.DeploymentGas) 67 | require.Equal(t, uint64(30_000), params2.TimeOffset) 68 | } 69 | -------------------------------------------------------------------------------- /proto/xion/mint/v1/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package xion.mint.v1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "xion/mint/v1/mint.proto"; 7 | import "amino/amino.proto"; 8 | 9 | option go_package = "github.com/burnt-labs/xion/x/mint/types"; 10 | 11 | // Query provides defines the gRPC querier service. 12 | service Query { 13 | // Params returns the total set of minting parameters. 14 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 15 | option (google.api.http).get = "/xion/mint/v1/params"; 16 | } 17 | 18 | // Inflation returns the current minting inflation value. 19 | rpc Inflation(QueryInflationRequest) returns (QueryInflationResponse) { 20 | option (google.api.http).get = "/xion/mint/v1/inflation"; 21 | } 22 | 23 | // AnnualProvisions current minting annual provisions value. 24 | rpc AnnualProvisions(QueryAnnualProvisionsRequest) 25 | returns (QueryAnnualProvisionsResponse) { 26 | option (google.api.http).get = "/xion/mint/v1/annual_provisions"; 27 | } 28 | } 29 | 30 | // QueryParamsRequest is the request type for the Query/Params RPC method. 31 | message QueryParamsRequest {} 32 | 33 | // QueryParamsResponse is the response type for the Query/Params RPC method. 34 | message QueryParamsResponse { 35 | // params defines the parameters of the module. 36 | Params params = 1 37 | [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; 38 | } 39 | 40 | // QueryInflationRequest is the request type for the Query/Inflation RPC method. 41 | message QueryInflationRequest {} 42 | 43 | // QueryInflationResponse is the response type for the Query/Inflation RPC 44 | // method. 45 | message QueryInflationResponse { 46 | // inflation is the current minting inflation value. 47 | bytes inflation = 1 [ 48 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 49 | (gogoproto.nullable) = false, 50 | (amino.dont_omitempty) = true 51 | ]; 52 | } 53 | 54 | // QueryAnnualProvisionsRequest is the request type for the 55 | // Query/AnnualProvisions RPC method. 56 | message QueryAnnualProvisionsRequest {} 57 | 58 | // QueryAnnualProvisionsResponse is the response type for the 59 | // Query/AnnualProvisions RPC method. 60 | message QueryAnnualProvisionsResponse { 61 | // annual_provisions is the current minting annual provisions value. 62 | bytes annual_provisions = 1 [ 63 | (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", 64 | (gogoproto.nullable) = false, 65 | (amino.dont_omitempty) = true 66 | ]; 67 | } 68 | -------------------------------------------------------------------------------- /e2e_tests/testdata/keys/vkey.json: -------------------------------------------------------------------------------- 1 | { 2 | "vk_alpha_1": [ 3 | "20491192805390485299153009773594534940189261866228447918068658471970481763042", 4 | "9383485363053290200918347156157836566562967994039712273449902621266178545958", 5 | "1" 6 | ], 7 | "vk_beta_2": [ 8 | [ 9 | "6375614351688725206403948262868962793625744043794305715222011528459656738731", 10 | "4252822878758300859123897981450591353533073413197771768651442665752259397132" 11 | ], 12 | [ 13 | "10505242626370262277552901082094356697409835680220590971873171140371331206856", 14 | "21847035105528745403288232691147584728191162732299865338377159692350059136679" 15 | ], 16 | [ 17 | "1", 18 | "0" 19 | ] 20 | ], 21 | "vk_gamma_2": [ 22 | [ 23 | "10857046999023057135944570762232829481370756359578518086990519993285655852781", 24 | "11559732032986387107991004021392285783925812861821192530917403151452391805634" 25 | ], 26 | [ 27 | "8495653923123431417604973247489272438418190587263600148770280649306958101930", 28 | "4082367875863433681332203403145435568316851327593401208105741076214120093531" 29 | ], 30 | [ 31 | "1", 32 | "0" 33 | ] 34 | ], 35 | "vk_delta_2": [ 36 | [ 37 | "5681006164308251953002113925585490159382365459900616695069738099616221007440", 38 | "1784372532023285234788112912605016418785853082678430162841833688972404754526" 39 | ], 40 | [ 41 | "13207372700374951217972734305987984211299541953272195804403019294285015432230", 42 | "11208098815931498258566335953255768915781024568431472973003740351242145274882" 43 | ], 44 | [ 45 | "1", 46 | "0" 47 | ] 48 | ], 49 | "IC": [ 50 | [ 51 | "13552796159321500446542092333925789627221763995917057705025024736845721942353", 52 | "9680985285040230751644495893215382676081535876363553660374115588862060487034", 53 | "1" 54 | ], 55 | [ 56 | "15254776772610533327488814281931287665893943177977310168056722368281728618662", 57 | "14367657701249547918513675533091286383358185662869887316466813062142674499260", 58 | "1" 59 | ], 60 | [ 61 | "14866859177758635030079226341862601112983487838511690567895574030672212441676", 62 | "1131454229353397332841644166317603239984551930044689440752008341203688834298", 63 | "1" 64 | ], 65 | [ 66 | "14452902482828558270298374737705658351270788428019585241026901331368858527948", 67 | "19097997774606523527158529552645961257150189357357601035078111643953385171384", 68 | "1" 69 | ] 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /x/jwk/keeper/vulnerability_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "crypto/sha256" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | jwkMsgServer "github.com/burnt-labs/xion/x/jwk/keeper" 10 | jwktypes "github.com/burnt-labs/xion/x/jwk/types" 11 | ) 12 | 13 | func TestAudienceDuplicateVulnerability(t *testing.T) { 14 | k, ctx := setupKeeper(t) 15 | admin := "cosmos1e2fuwe3uhq8zd9nkkk876nawrwdulgv4cxkq74" 16 | 17 | msgServer := jwkMsgServer.NewMsgServerImpl(k) 18 | 19 | // Create audience claim 20 | sum := sha256.Sum256([]byte("test-aud")) 21 | _, err := msgServer.CreateAudienceClaim(ctx, &jwktypes.MsgCreateAudienceClaim{ 22 | Admin: admin, 23 | AudHash: sum[:], 24 | }) 25 | require.NoError(t, err) 26 | 27 | // Create initial audience 28 | _, err = msgServer.CreateAudience(ctx, &jwktypes.MsgCreateAudience{ 29 | Admin: admin, 30 | Aud: "test-aud", 31 | Key: "initial-key", 32 | }) 33 | require.NoError(t, err) 34 | 35 | // Check initial state 36 | allAudiences := k.GetAllAudience(ctx) 37 | require.Len(t, allAudiences, 1, "Should have exactly 1 audience initially") 38 | 39 | initialAudience, found := k.GetAudience(ctx, "test-aud") 40 | require.True(t, found, "Initial audience should exist") 41 | require.Equal(t, "initial-key", initialAudience.Key, "Initial key should match") 42 | 43 | // Try to update with only Key change - this is where the vulnerability is claimed to be 44 | _, err = msgServer.UpdateAudience(ctx, &jwktypes.MsgUpdateAudience{ 45 | Admin: admin, 46 | NewAdmin: admin, // Keep same admin 47 | Aud: "test-aud", 48 | Key: "updated-key", 49 | NewAud: "", // Empty NewAud - this is the key part of the vulnerability claim 50 | }) 51 | require.NoError(t, err) 52 | 53 | // Check final state - this is where we test if duplicates were created 54 | allAudiences = k.GetAllAudience(ctx) 55 | require.Len(t, allAudiences, 1, "Should still have exactly 1 audience after update - NO DUPLICATES!") 56 | 57 | // Check if we can retrieve the audience and if it was properly updated 58 | audience, found := k.GetAudience(ctx, "test-aud") 59 | require.True(t, found, "Audience should still exist after update") 60 | require.Equal(t, "updated-key", audience.Key, "Key should be updated") 61 | require.Equal(t, admin, audience.Admin, "Admin should remain the same") 62 | require.Equal(t, "test-aud", audience.Aud, "Aud should remain the same") 63 | 64 | t.Logf("Test completed successfully. No duplicates were created.") 65 | t.Logf("Final audience count: %d", len(allAudiences)) 66 | t.Logf("Final audience: Aud=%s, Admin=%s, Key=%s", audience.Aud, audience.Admin, audience.Key) 67 | } 68 | -------------------------------------------------------------------------------- /x/globalfee/types/types_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 11 | 12 | "github.com/burnt-labs/xion/x/globalfee/types" 13 | ) 14 | 15 | func TestGlobalFeeGenesis(t *testing.T) { 16 | // Test DefaultGenesisState 17 | defaultGenesis := types.DefaultGenesisState() 18 | require.NotNil(t, defaultGenesis) 19 | require.Equal(t, types.DefaultParams(), defaultGenesis.Params) 20 | 21 | // Test NewGenesisState 22 | params := types.DefaultParams() 23 | genesis := types.NewGenesisState(params) 24 | require.NotNil(t, genesis) 25 | require.Equal(t, params, genesis.Params) 26 | 27 | // Test GetGenesisStateFromAppState 28 | appState := map[string]interface{}{ 29 | types.ModuleName: map[string]interface{}{ 30 | "params": map[string]interface{}{ 31 | "minimum_gas_prices": []interface{}{}, 32 | "bypass_min_fee_msg_types": []interface{}{}, 33 | "max_total_bypass_min_fee_msg_gas_usage": uint64(1000000), 34 | }, 35 | }, 36 | } 37 | 38 | cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) 39 | appStateBytes := make(map[string]json.RawMessage) 40 | for k, v := range appState { 41 | if b, err := json.Marshal(v); err == nil { 42 | appStateBytes[k] = b 43 | } 44 | } 45 | genesisState := types.GetGenesisStateFromAppState(cdc, appStateBytes) 46 | require.NotNil(t, genesisState) 47 | 48 | // Test ValidateGenesis 49 | err := types.ValidateGenesis(*defaultGenesis) 50 | require.NoError(t, err) 51 | } 52 | 53 | func TestGlobalFeeParams(t *testing.T) { 54 | // Test DefaultParams 55 | params := types.DefaultParams() 56 | require.NotNil(t, params) 57 | require.NotNil(t, params.MinimumGasPrices) 58 | require.NotNil(t, params.BypassMinFeeMsgTypes) 59 | require.Equal(t, uint64(1_000_000), params.MaxTotalBypassMinFeeMsgGasUsage) 60 | 61 | // Test ParamKeyTable 62 | keyTable := types.ParamKeyTable() 63 | require.NotNil(t, keyTable) 64 | 65 | // Test ValidateBasic 66 | err := params.ValidateBasic() 67 | require.NoError(t, err) 68 | 69 | // Test ParamSetPairs 70 | pairs := params.ParamSetPairs() 71 | require.NotNil(t, pairs) 72 | require.Len(t, pairs, 3) // MinimumGasPrices, BypassMinFeeMsgTypes, MaxTotalBypassMinFeeMsgGasUsage 73 | } 74 | 75 | func TestGlobalFeeCodec(t *testing.T) { 76 | // Test codec instantiation 77 | amino := codec.NewLegacyAmino() 78 | require.NotNil(t, amino) 79 | 80 | // Test interface registry 81 | registry := codectypes.NewInterfaceRegistry() 82 | require.NotNil(t, registry) 83 | } 84 | -------------------------------------------------------------------------------- /.github/workflows/create-release.yaml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | # Run for new release tags only 3 | 4 | on: 5 | workflow_dispatch: 6 | push: 7 | tags: 8 | - 'v[0-9]+\.[0-9]+\.[0-9]+' 9 | - 'v[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+' 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | lint: 17 | name: Golang CI Lint 18 | uses: burnt-labs/xion/.github/workflows/golangci-lint.yaml@workflows/main 19 | secrets: inherit 20 | 21 | update-swagger: 22 | name: Update Swagger 23 | uses: burnt-labs/xion/.github/workflows/update-swagger.yaml@workflows/main 24 | secrets: inherit 25 | 26 | unit-tests: 27 | name: Go Unit Tests 28 | uses: burnt-labs/xion/.github/workflows/tests.yaml@workflows/main 29 | secrets: inherit 30 | 31 | build-darwin: 32 | name: Build Binaries 33 | uses: burnt-labs/xion/.github/workflows/binaries-darwin.yaml@workflows/main 34 | secrets: inherit 35 | 36 | build-linux: 37 | name: Build Binaries 38 | uses: burnt-labs/xion/.github/workflows/binaries-linux.yaml@workflows/main 39 | secrets: inherit 40 | 41 | build-docker: 42 | name: Build Docker Images 43 | needs: build-linux 44 | uses: burnt-labs/xion/.github/workflows/docker-build.yaml@workflows/main 45 | secrets: inherit 46 | 47 | push-docker: 48 | name: Push Docker Images 49 | needs: build-docker 50 | uses: burnt-labs/xion/.github/workflows/docker-push.yaml@workflows/main 51 | secrets: inherit 52 | 53 | push-heighliner: 54 | name: Push Heighliner Images 55 | needs: build-docker 56 | uses: burnt-labs/xion/.github/workflows/heighliner-push.yaml@workflows/main 57 | secrets: inherit 58 | 59 | docker-scout: 60 | name: Docker Scout 61 | needs: build-docker 62 | uses: burnt-labs/xion/.github/workflows/docker-scout.yaml@workflows/main 63 | secrets: inherit 64 | 65 | e2e-tests: 66 | name: E2E tests 67 | needs: 68 | - build-docker 69 | uses: burnt-labs/xion/.github/workflows/e2e-tests.yaml@workflows/main 70 | secrets: inherit 71 | 72 | build-release: 73 | name: Build Release 74 | needs: 75 | - build-linux 76 | - lint 77 | - update-swagger 78 | - unit-tests 79 | - build-darwin 80 | - docker-scout 81 | - e2e-tests 82 | uses: burnt-labs/xion/.github/workflows/exec-goreleaser.yaml@workflows/main 83 | secrets: inherit 84 | 85 | verify-installers: 86 | name: Verify Package Installers 87 | needs: build-release 88 | uses: burnt-labs/xion/.github/workflows/verify-installers.yaml@workflows/main 89 | secrets: inherit 90 | -------------------------------------------------------------------------------- /x/feeabs/types/errors_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | sdkerrors "cosmossdk.io/errors" 9 | ) 10 | 11 | func TestErrors(t *testing.T) { 12 | // Test all error variables to ensure they are properly defined 13 | errorTests := []struct { 14 | name string 15 | err error 16 | code uint32 17 | codespace string 18 | message string 19 | }{ 20 | { 21 | name: "ErrInvalidExchangeRate", 22 | err: ErrInvalidExchangeRate, 23 | code: 1, 24 | codespace: ModuleName, 25 | message: "invalid exchange rate", 26 | }, 27 | { 28 | name: "ErrInvalidIBCFees", 29 | err: ErrInvalidIBCFees, 30 | code: 2, 31 | codespace: ModuleName, 32 | message: "invalid ibc fees", 33 | }, 34 | { 35 | name: "ErrHostZoneConfigNotFound", 36 | err: ErrHostZoneConfigNotFound, 37 | code: 3, 38 | codespace: ModuleName, 39 | message: "host zone config not found", 40 | }, 41 | { 42 | name: "ErrDuplicateHostZoneConfig", 43 | err: ErrDuplicateHostZoneConfig, 44 | code: 4, 45 | codespace: ModuleName, 46 | message: "duplicate host zone config", 47 | }, 48 | { 49 | name: "ErrNotEnoughFundInModuleAddress", 50 | err: ErrNotEnoughFundInModuleAddress, 51 | code: 5, 52 | codespace: ModuleName, 53 | message: "not have funding yet", 54 | }, 55 | { 56 | name: "ErrUnsupportedDenom", 57 | err: ErrUnsupportedDenom, 58 | code: 6, 59 | codespace: ModuleName, 60 | message: "unsupported denom", 61 | }, 62 | { 63 | name: "ErrHostZoneFrozen", 64 | err: ErrHostZoneFrozen, 65 | code: 7, 66 | codespace: ModuleName, 67 | message: "host zone is frozen", 68 | }, 69 | { 70 | name: "ErrHostZoneOutdated", 71 | err: ErrHostZoneOutdated, 72 | code: 8, 73 | codespace: ModuleName, 74 | message: "host zone is outdated", 75 | }, 76 | { 77 | name: "ErrInvalidSigner", 78 | err: ErrInvalidSigner, 79 | code: 9, 80 | codespace: ModuleName, 81 | message: "invalid signer", 82 | }, 83 | } 84 | 85 | for _, tt := range errorTests { 86 | t.Run(tt.name, func(t *testing.T) { 87 | require.NotNil(t, tt.err) 88 | 89 | // Test that it's a properly registered error 90 | sdkErr, ok := tt.err.(*sdkerrors.Error) 91 | require.True(t, ok, "error should be of type *sdkerrors.Error") 92 | 93 | require.Equal(t, tt.code, sdkErr.ABCICode()) 94 | require.Equal(t, tt.codespace, sdkErr.Codespace()) 95 | require.Contains(t, sdkErr.Error(), tt.message) 96 | }) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /x/jwk/keeper/audience_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 9 | govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" 10 | 11 | "github.com/burnt-labs/xion/x/jwk/types" 12 | ) 13 | 14 | func TestAudienceOperations(t *testing.T) { 15 | k, ctx := setupKeeper(t) 16 | 17 | // Test audience creation 18 | admin := authtypes.NewModuleAddress(govtypes.ModuleName).String() 19 | audience := types.Audience{ 20 | Aud: "test-audience", 21 | Admin: admin, 22 | Key: "test-key", 23 | } 24 | 25 | // Test SetAudience 26 | k.SetAudience(ctx, audience) 27 | 28 | // Test GetAudience 29 | retrievedAudience, found := k.GetAudience(ctx, "test-audience") 30 | require.True(t, found) 31 | require.Equal(t, audience, retrievedAudience) 32 | 33 | // Test GetAudience with non-existent audience 34 | _, found = k.GetAudience(ctx, "non-existent") 35 | require.False(t, found) 36 | 37 | // Test GetAllAudience 38 | allAudiences := k.GetAllAudience(ctx) 39 | require.Len(t, allAudiences, 1) 40 | require.Equal(t, audience, allAudiences[0]) 41 | 42 | // Add another audience 43 | audience2 := types.Audience{ 44 | Aud: "test-audience-2", 45 | Admin: admin, 46 | Key: "test-key-2", 47 | } 48 | k.SetAudience(ctx, audience2) 49 | 50 | // Verify we now have 2 audiences 51 | allAudiences = k.GetAllAudience(ctx) 52 | require.Len(t, allAudiences, 2) 53 | 54 | // Test RemoveAudience 55 | k.RemoveAudience(ctx, "test-audience") 56 | 57 | // Verify audience was removed 58 | _, found = k.GetAudience(ctx, "test-audience") 59 | require.False(t, found) 60 | 61 | // Verify we now have 1 audience 62 | allAudiences = k.GetAllAudience(ctx) 63 | require.Len(t, allAudiences, 1) 64 | require.Equal(t, audience2, allAudiences[0]) 65 | } 66 | 67 | func TestAudienceClaimOperations(t *testing.T) { 68 | k, ctx := setupKeeper(t) 69 | 70 | // Test audience claim creation 71 | claim := []byte("test-claim-hash") 72 | signer := authtypes.NewModuleAddress(govtypes.ModuleName) 73 | 74 | // Test SetAudienceClaim 75 | k.SetAudienceClaim(ctx, claim, signer) 76 | 77 | // Test GetAudienceClaim 78 | retrievedClaim, found := k.GetAudienceClaim(ctx, claim) 79 | require.True(t, found) 80 | require.Equal(t, signer.String(), retrievedClaim.Signer) 81 | 82 | // Test GetAudienceClaim with non-existent claim 83 | _, found = k.GetAudienceClaim(ctx, []byte("non-existent")) 84 | require.False(t, found) 85 | 86 | // Test RemoveAudienceClaim 87 | k.RemoveAudienceClaim(ctx, claim) 88 | 89 | // Verify claim was removed 90 | _, found = k.GetAudienceClaim(ctx, claim) 91 | require.False(t, found) 92 | } 93 | -------------------------------------------------------------------------------- /app/v25_upgrade/migrator.go: -------------------------------------------------------------------------------- 1 | package v25_upgrade 2 | 3 | import ( 4 | "fmt" 5 | 6 | wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" 7 | "github.com/gogo/protobuf/proto" 8 | 9 | storetypes "cosmossdk.io/store/types" 10 | 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | ) 13 | 14 | // MigrateContracts fixes corrupted contracts that cannot unmarshal 15 | // This is called from the v25 upgrade handler 16 | func MigrateContracts(ctx sdk.Context, storeKey storetypes.StoreKey) error { 17 | logger := ctx.Logger() 18 | logger.Info("v25: starting contract migration") 19 | 20 | store := ctx.KVStore(storeKey) 21 | 22 | var totalContracts int 23 | var fixedContracts int 24 | var skippedContracts int 25 | var failedContracts int 26 | 27 | prefix := []byte{ContractKeyPrefix} 28 | iterator := storetypes.KVStorePrefixIterator(store, prefix) 29 | defer iterator.Close() 30 | 31 | for ; iterator.Valid(); iterator.Next() { 32 | totalContracts++ 33 | 34 | key := iterator.Key() 35 | data := iterator.Value() 36 | 37 | // Get address for logging 38 | addressBytes := key[len(prefix):] 39 | address := sdk.AccAddress(addressBytes).String() 40 | 41 | // Try to unmarshal - if it succeeds, skip it (already working) 42 | var contractInfo wasmtypes.ContractInfo 43 | unmarshalErr := proto.Unmarshal(data, &contractInfo) 44 | 45 | if unmarshalErr == nil { 46 | // Contract is already working - skip it 47 | skippedContracts++ 48 | if totalContracts%1000 == 0 { 49 | logger.Info("v25 migration progress", 50 | "processed", totalContracts, 51 | "fixed", fixedContracts, 52 | "skipped", skippedContracts) 53 | } 54 | continue 55 | } 56 | 57 | // Contract fails to unmarshal - needs fixing 58 | // Use the FixContract function from fixer.go 59 | result := FixContract(address, data) 60 | 61 | if !result.FixSucceeded || !result.UnmarshalAfter { 62 | logger.Error("v25: failed to fix contract", 63 | "address", address, 64 | "original_state", result.OriginalState, 65 | "error", result.Error) 66 | failedContracts++ 67 | continue 68 | } 69 | 70 | // Write the fixed data 71 | store.Set(key, result.FixedData) 72 | fixedContracts++ 73 | 74 | if fixedContracts%100 == 0 { 75 | logger.Info("v25 migration progress", 76 | "processed", totalContracts, 77 | "fixed", fixedContracts, 78 | "skipped", skippedContracts) 79 | } 80 | } 81 | 82 | logger.Info("v25 migration complete", 83 | "total", totalContracts, 84 | "fixed", fixedContracts, 85 | "skipped", skippedContracts, 86 | "failed", failedContracts) 87 | 88 | if failedContracts > 0 { 89 | return fmt.Errorf("failed to fix %d contracts", failedContracts) 90 | } 91 | 92 | return nil 93 | } 94 | -------------------------------------------------------------------------------- /x/mint/types/params_legacy_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | 8 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 9 | ) 10 | 11 | func TestParamKeyTable(t *testing.T) { 12 | table := ParamKeyTable() 13 | require.NotNil(t, table) 14 | 15 | // We can't directly access the internal structure, but we can test that it doesn't panic 16 | require.NotPanics(t, func() { 17 | ParamKeyTable() 18 | }) 19 | } 20 | 21 | func TestParamSetPairs(t *testing.T) { 22 | params := DefaultParams() 23 | pairs := params.ParamSetPairs() 24 | 25 | require.Len(t, pairs, 6) 26 | 27 | // Check that all expected parameter keys are present 28 | expectedKeys := [][]byte{ 29 | KeyMintDenom, 30 | KeyInflationRateChange, 31 | KeyInflationMax, 32 | KeyInflationMin, 33 | KeyGoalBonded, 34 | KeyBlocksPerYear, 35 | } 36 | 37 | pairKeys := make([][]byte, len(pairs)) 38 | for i, pair := range pairs { 39 | pairKeys[i] = pair.Key 40 | } 41 | 42 | for _, expectedKey := range expectedKeys { 43 | found := false 44 | for _, pairKey := range pairKeys { 45 | if string(expectedKey) == string(pairKey) { 46 | found = true 47 | break 48 | } 49 | } 50 | require.True(t, found, "Expected key %s not found in param set pairs", string(expectedKey)) 51 | } 52 | } 53 | 54 | func TestParamSetPairsValidation(t *testing.T) { 55 | params := DefaultParams() 56 | pairs := params.ParamSetPairs() 57 | 58 | // Test that each pair has a validation function 59 | for _, pair := range pairs { 60 | require.NotNil(t, pair.ValidatorFn, "Validation function should not be nil for key %s", string(pair.Key)) 61 | 62 | // Test that validation functions work with default values 63 | switch string(pair.Key) { 64 | case string(KeyMintDenom): 65 | err := pair.ValidatorFn(params.MintDenom) 66 | require.NoError(t, err) 67 | case string(KeyInflationRateChange): 68 | err := pair.ValidatorFn(params.InflationRateChange) 69 | require.NoError(t, err) 70 | case string(KeyInflationMax): 71 | err := pair.ValidatorFn(params.InflationMax) 72 | require.NoError(t, err) 73 | case string(KeyInflationMin): 74 | err := pair.ValidatorFn(params.InflationMin) 75 | require.NoError(t, err) 76 | case string(KeyGoalBonded): 77 | err := pair.ValidatorFn(params.GoalBonded) 78 | require.NoError(t, err) 79 | case string(KeyBlocksPerYear): 80 | err := pair.ValidatorFn(params.BlocksPerYear) 81 | require.NoError(t, err) 82 | } 83 | } 84 | } 85 | 86 | func TestParamSetImplementation(t *testing.T) { 87 | params := &Params{} 88 | 89 | // Test that Params implements paramtypes.ParamSet 90 | require.Implements(t, (*paramtypes.ParamSet)(nil), params) 91 | } 92 | --------------------------------------------------------------------------------