Feat/add networks (#1303)

* No commit suggestions generated

* No commit suggestions generated

* No commit suggestions generated
This commit is contained in:
Prad Nukala
2025-10-12 11:23:20 -04:00
committed by GitHub
parent 40eadc995e
commit ebfa2b062a
97 changed files with 3979 additions and 16119 deletions
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
set -euxo pipefail
mkdir -p /tmp/chains $UPGRADE_DIR
echo "Fetching code from tag"
mkdir -p /tmp/chains/$CHAIN_NAME
cd /tmp/chains/$CHAIN_NAME
if [[ $CODE_TAG =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "Trying to fetch code from commit hash"
curl -LO $CODE_REPO/archive/$CODE_TAG.zip
unzip $CODE_TAG.zip
code_dir=${CODE_REPO##*/}-${CODE_TAG}
elif [[ $CODE_TAG = v* ]]; then
echo "Trying to fetch code from tag with 'v' prefix"
curl -LO $CODE_REPO/archive/refs/tags/$CODE_TAG.zip
unzip $CODE_TAG.zip
code_dir=${CODE_REPO##*/}-${CODE_TAG#"v"}
else
echo "Trying to fetch code from tag or branch"
if curl -fsLO $CODE_REPO/archive/refs/tags/$CODE_TAG.zip; then
unzip $CODE_TAG.zip
code_dir=${CODE_REPO##*/}-$CODE_TAG
elif curl -fsLO $CODE_REPO/archive/refs/heads/$CODE_TAG.zip; then
unzip $(echo $CODE_TAG | rev | cut -d "/" -f 1 | rev).zip
code_dir=${CODE_REPO##*/}-${CODE_TAG/\//-}
else
echo "Tag or branch '$CODE_TAG' not found"
exit 1
fi
fi
echo "Fetch wasmvm if needed"
cd /tmp/chains/$CHAIN_NAME/$code_dir
WASM_VERSION=$(cat go.mod | grep -oe "github.com/CosmWasm/wasmvm v[0-9.]*" | cut -d ' ' -f 2)
if [[ WASM_VERSION != "" ]]; then
mkdir -p /tmp/chains/libwasmvm_muslc
cd /tmp/chains/libwasmvm_muslc
curl -LO https://github.com/CosmWasm/wasmvm/releases/download/$WASM_VERSION/libwasmvm_muslc.x86_64.a
cp libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.a
fi
echo "Build chain binary"
cd /tmp/chains/$CHAIN_NAME/$code_dir
CGO_ENABLED=1 BUILD_TAGS="muslc linkstatic" LINK_STATICALLY=true LEDGER_ENABLED=false make install
echo "Copy created binary to the upgrade directories"
if [[ $UPGRADE_NAME == "genesis" ]]; then
mkdir -p $UPGRADE_DIR/genesis/bin
cp $GOBIN/$CHAIN_BIN $UPGRADE_DIR/genesis/bin
else
mkdir -p $UPGRADE_DIR/upgrades/$UPGRADE_NAME/bin
cp $GOBIN/$CHAIN_BIN $UPGRADE_DIR/upgrades/$UPGRADE_NAME/bin
fi
echo "Cleanup"
rm -rf /tmp/chains/$CHAIN_NAME
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
# chain-rpc-ready.sh - Check if a CometBFT or Tendermint RPC service is ready
# Usage: chain-rpc-ready.sh [RPC_URL]
set -euo pipefail
RPC_URL=${1:-"http://localhost:26657"}
echo 1>&2 "Checking if $RPC_URL is ready..."
# Check if the RPC URL is reachable,
json=$(curl -s --connect-timeout 2 "$RPC_URL/status")
# and the bootstrap block state has been validated,
if [ "$(echo "$json" | jq -r '.result.sync_info | (.earliest_block_height < .latest_block_height)')" != true ]; then
echo 1>&2 "$RPC_URL is not ready: bootstrap block state has not been validated"
exit 1
fi
# and the node is not catching up.
if [ "$(echo "$json" | jq -r .result.sync_info.catching_up)" != false ]; then
echo 1>&2 "$RPC_URL is not ready: node is catching up"
exit 1
fi
echo "$json" | jq -r .result
exit 0
+93 -125
View File
@@ -1,146 +1,114 @@
#!/bin/bash
set -eux
# scripts/create-genesis.sh - Create genesis file for Sonr network
# generate_vrf_key generates a VRF keypair and stores it securely
generate_vrf_key() {
local home_dir="$1"
set -euo pipefail
if [[ -z "${home_dir}" ]]; then
echo "Error: HOME_DIR parameter is required" >&2
return 1
fi
# Source helper libraries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/env.sh"
source "${SCRIPT_DIR}/lib/keys.sh"
source "${SCRIPT_DIR}/lib/genesis.sh"
local genesis_file="${home_dir}/config/genesis.json"
if [[ ! -f "${genesis_file}" ]]; then
echo "Error: Genesis file not found at ${genesis_file}" >&2
return 1
fi
local chain_id
chain_id=$(jq -r '.chain_id' "${genesis_file}" 2>/dev/null)
if [[ -z "${chain_id}" || "${chain_id}" == "null" ]]; then
echo "Error: Failed to extract chain-id from genesis file" >&2
return 1
fi
echo "Generating VRF keypair for network: ${chain_id}"
local entropy_seed
entropy_seed=$(echo -n "${chain_id}" | sha256sum | cut -d' ' -f1)
local seed_part1="${entropy_seed}"
local seed_part2
seed_part2=$(echo -n "${entropy_seed}" | sha256sum | cut -d' ' -f1)
local vrf_key_hex="${seed_part1}${seed_part2}"
if [[ ${#vrf_key_hex} -ne 128 ]]; then
echo "Error: Generated VRF key has incorrect size: ${#vrf_key_hex}" >&2
return 1
fi
local vrf_key_path="${home_dir}/vrf_secret.key"
mkdir -p "${home_dir}"
echo -n "${vrf_key_hex}" | xxd -r -p > "${vrf_key_path}"
chmod 0600 "${vrf_key_path}"
local file_size
file_size=$(wc -c < "${vrf_key_path}")
if [[ ${file_size} -ne 64 ]]; then
echo "Error: VRF key file has incorrect size: ${file_size} bytes" >&2
rm -f "${vrf_key_path}"
return 1
fi
echo "✓ VRF keypair generated for network: ${chain_id}"
echo "✓ VRF secret key stored securely: ${vrf_key_path}"
return 0
}
DENOM="${DENOM:=usnr}"
# Match init-testnet.sh allocation: 100000000000000000000000000snr = 100000000000000000000000000000000usnr
COINS="${COINS:=100000000000000000000000000000000$DENOM,100000000000000000000000000snr}"
CHAIN_ID="${CHAIN_ID:=sonrtest_1-1}"
CHAIN_BIN="${CHAIN_BIN:=snrd}"
CHAIN_DIR="${CHAIN_DIR:=$HOME/.sonr}"
KEYS_CONFIG="${KEYS_CONFIG:=configs/keys.json}"
# Initialize environment
init_env
# Set defaults for genesis creation
FAUCET_ENABLED="${FAUCET_ENABLED:=true}"
NUM_VALIDATORS="${NUM_VALIDATORS:=1}"
NUM_RELAYERS="${NUM_RELAYERS:=0}"
# check if the binary has genesis subcommand or not, if not, set CHAIN_GENESIS_CMD to empty
CHAIN_GENESIS_CMD=$($CHAIN_BIN 2>&1 | grep -q "genesis-related subcommands" && echo "genesis" || echo "")
# Match init-testnet.sh allocation: 100000000000000000000000000snr = 100000000000000000000000000000000usnr
BASE_COINS="${BASE_COINS:=100000000000000000000000000000000${DENOM},100000000000000000000000000snr}"
VALIDATOR_AMOUNT="1000000000000000000000000000${DENOM}"
jq -r ".genesis[0].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN init "$CHAIN_ID" --chain-id "$CHAIN_ID" --default-denom "$DENOM" --recover
# Add genesis keys to the keyring and self delegate initial coins
echo "Adding key...." $(jq -r ".genesis[0].name" "$KEYS_CONFIG")
jq -r ".genesis[0].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN keys add $(jq -r ".genesis[0].name" "$KEYS_CONFIG") --recover --keyring-backend="test"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" add-genesis-account $($CHAIN_BIN keys show -a $(jq -r .genesis[0].name "$KEYS_CONFIG") --keyring-backend="test") "$COINS" --keyring-backend="test"
# Add faucet key to the keyring and self delegate initial coins
echo "Adding key...." $(jq -r ".faucet[0].name" "$KEYS_CONFIG")
jq -r ".faucet[0].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN keys add $(jq -r ".faucet[0].name" "$KEYS_CONFIG") --recover --keyring-backend="test"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" add-genesis-account $($CHAIN_BIN keys show -a $(jq -r .faucet[0].name "$KEYS_CONFIG") --keyring-backend="test") "$COINS" --keyring-backend="test"
# Add test keys to the keyring and self delegate initial coins
echo "Adding key...." $(jq -r ".keys[0].name" "$KEYS_CONFIG")
jq -r ".keys[0].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN keys add $(jq -r ".keys[0].name" "$KEYS_CONFIG") --recover --keyring-backend="test"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" add-genesis-account $($CHAIN_BIN keys show -a $(jq -r .keys[0].name "$KEYS_CONFIG") --keyring-backend="test") "$COINS" --keyring-backend="test"
if [[ $FAUCET_ENABLED == "false" && $NUM_RELAYERS -gt "-1" ]]; then
## Add relayers keys and delegate tokens
for i in $(seq 0 "$NUM_RELAYERS"); do
# Add relayer key and delegate tokens
RELAYER_KEY_NAME="$(jq -r ".relayers[$i].name" "$KEYS_CONFIG")"
echo "Adding relayer key.... $RELAYER_KEY_NAME"
jq -r ".relayers[$i].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN keys add "$RELAYER_KEY_NAME" --recover --keyring-backend="test"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" add-genesis-account $($CHAIN_BIN keys show -a "$RELAYER_KEY_NAME" --keyring-backend="test") "$COINS" --keyring-backend="test"
# Add relayer-cli key and delegate tokens
RELAYER_CLI_KEY_NAME="$(jq -r ".relayers_cli[$i].name" "$KEYS_CONFIG")"
echo "Adding relayer-cli key.... $RELAYER_CLI_KEY_NAME"
jq -r ".relayers_cli[$i].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN keys add "$RELAYER_CLI_KEY_NAME" --recover --keyring-backend="test"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" add-genesis-account $($CHAIN_BIN keys show -a "$RELAYER_CLI_KEY_NAME" --keyring-backend="test") "$COINS" --keyring-backend="test"
done
# Check if binary has genesis subcommand
CHAIN_GENESIS_CMD=""
if $CHAIN_BIN 2>&1 | grep -q "genesis-related subcommands"; then
CHAIN_GENESIS_CMD="genesis"
fi
## if faucet not enabled then add validator and relayer with index as keys and into gentx
if [[ $FAUCET_ENABLED == "false" && $NUM_VALIDATORS -gt "1" ]]; then
## Add validators key and delegate tokens
for i in $(seq 0 "$NUM_VALIDATORS"); do
VAL_KEY_NAME="$(jq -r '.validators[0].name' "$KEYS_CONFIG")-$i"
echo "Adding validator key.... $VAL_KEY_NAME"
jq -r ".validators[0].mnemonic" "$KEYS_CONFIG" | $CHAIN_BIN keys add "$VAL_KEY_NAME" --index "$i" --recover --keyring-backend="test"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" add-genesis-account $($CHAIN_BIN keys show -a "$VAL_KEY_NAME" --keyring-backend="test") "$COINS" --keyring-backend="test"
done
log_info "Creating genesis for Sonr network: $CHAIN_ID"
# Initialize chain
local genesis_mnemonic
genesis_mnemonic=$(jq -r ".genesis[0].mnemonic" "$KEYS_CONFIG")
echo "$genesis_mnemonic" | $CHAIN_BIN init "$CHAIN_ID" --chain-id "$CHAIN_ID" --default-denom "$DENOM" --recover
# Add genesis accounts
log_info "Adding genesis accounts..."
# Genesis key
local genesis_key_name
genesis_key_name=$(jq -r ".genesis[0].name" "$KEYS_CONFIG")
import_mnemonic "$genesis_key_name" "$genesis_mnemonic"
fund_key "$genesis_key_name" "$BASE_COINS"
# Faucet key
local faucet_key_name
faucet_key_name=$(jq -r ".faucet[0].name" "$KEYS_CONFIG")
local faucet_mnemonic
faucet_mnemonic=$(jq -r ".faucet[0].mnemonic" "$KEYS_CONFIG")
import_mnemonic "$faucet_key_name" "$faucet_mnemonic"
fund_key "$faucet_key_name" "$BASE_COINS"
# Test key
local test_key_name
test_key_name=$(jq -r ".keys[0].name" "$KEYS_CONFIG")
local test_mnemonic
test_mnemonic=$(jq -r ".keys[0].mnemonic" "$KEYS_CONFIG")
import_mnemonic "$test_key_name" "$test_mnemonic"
fund_key "$test_key_name" "$BASE_COINS"
# Add relayer keys if faucet is disabled
if [[ "$FAUCET_ENABLED" == "false" && "$NUM_RELAYERS" -gt 0 ]]; then
for i in $(seq 0 "$NUM_RELAYERS"); do
local relayer_key_name
relayer_key_name=$(jq -r ".relayers[$i].name" "$KEYS_CONFIG")
local relayer_mnemonic
relayer_mnemonic=$(jq -r ".relayers[$i].mnemonic" "$KEYS_CONFIG")
import_mnemonic "$relayer_key_name" "$relayer_mnemonic"
fund_key "$relayer_key_name" "$BASE_COINS"
local relayer_cli_key_name
relayer_cli_key_name=$(jq -r ".relayers_cli[$i].name" "$KEYS_CONFIG")
local relayer_cli_mnemonic
relayer_cli_mnemonic=$(jq -r ".relayers_cli[$i].mnemonic" "$KEYS_CONFIG")
import_mnemonic "$relayer_cli_key_name" "$relayer_cli_mnemonic"
fund_key "$relayer_cli_key_name" "$BASE_COINS"
done
fi
echo "Creating gentx..."
COIN=$(echo "$COINS" | cut -d ',' -f1)
# Use full validator amount to meet minimum delegation requirement (274890886240)
# Match the working init-testnet.sh: 1000000000000000000000snr = 1000000000000000000000000000usnr
VALIDATOR_AMOUNT="1000000000000000000000000000$DENOM"
$CHAIN_BIN "$CHAIN_GENESIS_CMD" gentx $(jq -r ".genesis[0].name" "$KEYS_CONFIG") "$VALIDATOR_AMOUNT" --keyring-backend="test" --chain-id "$CHAIN_ID" --gas-prices="0$DENOM"
# Add additional validator keys if needed
if [[ "$FAUCET_ENABLED" == "false" && "$NUM_VALIDATORS" -gt 1 ]]; then
for i in $(seq 1 "$NUM_VALIDATORS"); do
local val_key_name="${genesis_key_name}-${i}"
local val_mnemonic
val_mnemonic=$(jq -r ".validators[0].mnemonic" "$KEYS_CONFIG")
import_mnemonic "$val_key_name" "$val_mnemonic"
fund_key "$val_key_name" "$BASE_COINS"
done
fi
echo "Output of gentx"
cat "$CHAIN_DIR"/config/gentx/*.json | jq
# Create genesis transaction
log_info "Creating genesis transaction..."
$CHAIN_BIN "$CHAIN_GENESIS_CMD" gentx "$genesis_key_name" "$VALIDATOR_AMOUNT" \
--keyring-backend "$KEYRING_BACKEND" \
--chain-id "$CHAIN_ID" \
--gas-prices "0${DENOM}"
echo "Running collect-gentxs"
log_info "Genesis transaction output:"
cat "$CHAIN_DIR/config/gentx"/*.json | jq
# Collect genesis transactions
log_info "Collecting genesis transactions..."
$CHAIN_BIN "$CHAIN_GENESIS_CMD" collect-gentxs
ls "$CHAIN_DIR"/config
# Generate VRF keypair
echo ""
echo "Generating VRF keypair..."
if ! generate_vrf_key "${CHAIN_DIR}"; then
echo "Warning: VRF key generation failed, but continuing..."
echo "Note: Multi-validator encryption features may not work without VRF keys"
log_info "Generating VRF keypair..."
if ! generate_vrf_key "$CHAIN_DIR"; then
log_warn "VRF key generation failed, but continuing..."
log_warn "Note: Multi-validator encryption features may not work without VRF keys"
fi
log_success "Genesis creation completed"
+84
View File
@@ -0,0 +1,84 @@
#!/bin/bash
# scripts/create-ics.sh - Create ICS proposal for Sonr network
set -euo pipefail
# Source helper libraries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/env.sh"
source "${SCRIPT_DIR}/lib/keys.sh"
source "${SCRIPT_DIR}/lib/tx.sh"
# Initialize environment
init_env
# Set defaults for ICS setup
KEY_NAME="${KEY_NAME:-ics-setup}"
STAKE_AMOUNT="10000000${DENOM}"
MAX_RETRIES="${MAX_RETRIES:-3}"
RETRY_INTERVAL="${RETRY_INTERVAL:-30}"
# Validate required parameters
if [[ -z "${PROPOSAL_FILE:-}" ]]; then
log_error "PROPOSAL_FILE environment variable is required"
exit 1
fi
ensure_file "$PROPOSAL_FILE"
log_info "Setting up ICS proposal with key '$KEY_NAME'"
# Import key from keys config if available
if [[ -f "${KEYS_CONFIG:-}" ]]; then
local key_mnemonic
key_mnemonic=$(jq -r ".keys[0].mnemonic" "$KEYS_CONFIG" 2>/dev/null || echo "")
if [[ -n "$key_mnemonic" && "$key_mnemonic" != "null" ]]; then
import_mnemonic "$KEY_NAME" "$key_mnemonic"
else
log_warn "No valid mnemonic found in $KEYS_CONFIG, using existing key or create one manually"
fi
else
log_warn "KEYS_CONFIG not set, ensure key '$KEY_NAME' exists"
fi
# Ensure key exists
ensure_key "$KEY_NAME"
# Get validator address and stake tokens
local validator_address
validator_address=$(get_validator_address)
stake_tokens "$KEY_NAME" "$validator_address" "$STAKE_AMOUNT"
# Determine proposal command (legacy vs new)
local submit_cmd="submit-proposal"
if $CHAIN_BIN tx gov --help 2>/dev/null | grep -q "submit-legacy-proposal"; then
submit_cmd="submit-legacy-proposal"
fi
log_info "Using proposal command: $submit_cmd"
# Submit proposal
local tx_hash
tx_hash=$(submit_proposal "$KEY_NAME" "$PROPOSAL_FILE" "consumer-addition")
# Extract proposal ID from transaction
local proposal_id
proposal_id=$(query_chain tx "$tx_hash" | jq -r '.logs[0].events[] | select(.type=="submit_proposal").attributes[] | select(.key=="proposal_id").value // empty')
if [[ -z "$proposal_id" || "$proposal_id" == "null" ]]; then
log_error "Failed to extract proposal ID from transaction"
exit 1
fi
log_info "Proposal ID: $proposal_id"
# Vote on proposal
vote_proposal "$KEY_NAME" "$proposal_id" "yes"
# Wait for proposal to pass
wait_for_proposal "$proposal_id" "$MAX_RETRIES" "$RETRY_INTERVAL"
log_success "ICS proposal setup completed successfully"
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
# scripts/create-validator.sh - Create a validator for Sonr network
set -euo pipefail
# Source helper libraries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/env.sh"
source "${SCRIPT_DIR}/lib/keys.sh"
source "${SCRIPT_DIR}/lib/tx.sh"
# Initialize environment
init_env
# Ensure chain directory exists
ensure_chain_dir
# Set defaults for validator creation
VAL_NAME="${VAL_NAME:-$CHAIN_ID-validator}"
VALIDATOR_AMOUNT="5000000000${DENOM}"
log_info "Creating validator '$VAL_NAME' for Sonr network"
# Wait for node to sync
wait_for_sync 10
# Get Cosmos SDK version to determine validator creation format
set +e
cosmos_sdk_version=$($CHAIN_BIN version --long | sed -n 's/cosmos_sdk_version: \(.*\)/\1/p')
set -e
log_info "Cosmos SDK version: $cosmos_sdk_version"
# Create validator based on SDK version
if [[ "$cosmos_sdk_version" > "v0.50.0" ]]; then
log_info "Using Cosmos SDK v0.50+ validator creation format"
# Create validator JSON for v0.50+
local validator_json
validator_json=$(cat <<EOF
{
"pubkey": "$($CHAIN_BIN tendermint show-validator $NODE_ARGS)",
"amount": "$VALIDATOR_AMOUNT",
"moniker": "$VAL_NAME",
"commission-rate": "0.1",
"commission-max-rate": "0.2",
"commission-max-change-rate": "0.01",
"min-self-delegation": "1000000"
}
EOF
)
echo "$validator_json" > /tmp/validator.json
# Submit validator creation transaction
submit_tx "$VAL_NAME" staking create-validator /tmp/validator.json
rm -f /tmp/validator.json
else
log_info "Using legacy validator creation format"
# Check if min-self-delegation parameter is supported
local args=""
if $CHAIN_BIN tx staking create-validator --help 2>/dev/null | grep -q "min-self-delegation"; then
args="--min-self-delegation=1000000"
fi
# Submit validator creation transaction with legacy format
submit_tx "$VAL_NAME" staking create-validator \
--pubkey="$($CHAIN_BIN tendermint show-validator $NODE_ARGS)" \
--moniker "$VAL_NAME" \
--amount "$VALIDATOR_AMOUNT" \
--commission-rate="0.10" \
--commission-max-rate="0.20" \
--commission-max-change-rate="0.01" \
$args
fi
log_success "Validator '$VAL_NAME' created successfully"
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
REGISTRY_URL="$1"
CHAIN_1="$2"
CHAIN_2="$3"
set -eux
function connection_id() {
CONNECTION_ID=$(curl -s $REGISTRY_URL/ibc/$CHAIN_1/$CHAIN_2 | jq -r ".chain_1.connection_id")
echo $CONNECTION_ID
}
echo "Try to get connection id, if failed, wait for 2 seconds and try again"
max_tries=20
while [[ max_tries -gt 0 ]]
do
id=$(connection_id)
if [[ -n "$id" ]]; then
echo "Found connection id: $id"
exit 0
fi
echo "Failed to get connection id. Sleeping for 2 secs. Tries left $max_tries"
((max_tries--))
sleep 10
done
+121
View File
@@ -0,0 +1,121 @@
# Sonr Script Library
This directory contains modular helper scripts for Sonr blockchain operations. These helpers provide reusable functions for common tasks like environment setup, configuration management, key handling, and transaction operations.
## Library Structure
### `env.sh` - Environment Management
Centralizes default environment variables and provides utility functions for logging, validation, and system checks.
**Key Functions:**
- `init_env()` - Initialize environment with required tools and cleanup
- `log_info()`, `log_warn()`, `log_error()`, `log_success()` - Colored logging
- `require_cmd()`, `ensure_file()`, `ensure_binary()` - Validation helpers
- `is_docker()` - Check if running in Docker container
**Environment Variables:**
- `DENOM=usnr` - Default denomination
- `CHAIN_BIN=snrd` - Binary name
- `CHAIN_DIR=~/.sonr` - Chain data directory
- `CHAIN_ID=sonrtest_1-1` - Default chain ID
### `jq_patch.sh` - JSON Operations
Provides safe JSON patching operations using `jq` with temporary files and validation.
**Key Functions:**
- `patch_json(file, jq_expr)` - Apply jq expression to file
- `set_json_string()`, `set_json_number()`, `set_json_bool()` - Type-safe setters
- `json_path_exists()`, `get_json_value()` - Query helpers
- `validate_json()` - JSON validation
### `config.sh` - Configuration Management
Handles TOML configuration files for Cosmos SDK nodes using `crudini` or `sed` fallbacks.
**Key Functions:**
- `configure_node()` - Complete node configuration with ports and settings
- `enable_rpc()`, `enable_rest()`, `enable_grpc()` - Enable services
- `set_consensus_timeouts()`, `set_min_gas_prices()` - Parameter setters
- `set_toml_value()` - Generic TOML value setter
### `keys.sh` - Key Management
Provides functions for importing, managing, and using cryptographic keys.
**Key Functions:**
- `import_mnemonic()` - Import key from mnemonic phrase
- `ensure_key()`, `get_key_address()` - Key validation and retrieval
- `fund_key()`, `delegate_to_validator()` - Account operations
- `wait_for_sync()` - Node synchronization waiting
### `tx.sh` - Transaction Operations
Handles blockchain transactions with error handling and retry logic.
**Key Functions:**
- `submit_tx()` - Submit transaction with gas and error handling
- `query_chain()` - Query blockchain state
- `submit_proposal()`, `vote_proposal()` - Governance operations
- `stake_tokens()`, `get_balance()` - Staking operations
### `genesis.sh` - Genesis File Operations
Specialized functions for genesis file creation and modification.
**Key Functions:**
- `generate_vrf_key()` - Generate VRF keypair for network
- `update_genesis_params()` - Apply Sonr-specific genesis parameters
- `add_constitution()` - Add constitution to governance
- `validate_genesis()` - Genesis file validation
## Usage Examples
### Basic Environment Setup
```bash
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/env.sh"
source "${SCRIPT_DIR}/lib/config.sh"
init_env
ensure_chain_dir
configure_node "$CHAIN_DIR" --rpc-port 26657 --rest-port 1317
```
### Key Management
```bash
#!/bin/bash
source "scripts/lib/keys.sh"
import_mnemonic "mykey" "word1 word2 word3..." "eth_secp256k1"
fund_key "mykey" "1000000usnr"
```
### Genesis Creation
```bash
#!/bin/bash
source "scripts/lib/genesis.sh"
update_genesis_params
add_constitution
generate_vrf_key "$CHAIN_DIR"
```
## Integration Guidelines
1. **Always source required libraries** at the top of scripts
2. **Call `init_env()`** early to set up logging and validation
3. **Use consistent error handling** with the provided logging functions
4. **Validate inputs** using `ensure_*` functions before operations
5. **Handle Docker vs local execution** in wrapper functions
6. **Use descriptive log messages** for user feedback
## Error Handling
All functions use consistent error handling:
- Functions return 0 on success, 1 on failure
- Use `log_error()` for user-visible errors
- Use `log_warn()` for non-fatal issues
- Cleanup temporary files automatically via `trap`
## Docker Compatibility
All functions support both local and Docker execution modes:
- Use `is_docker()` to detect environment
- Use `run_binary()` wrapper for command execution
- Mount volumes correctly for Docker containers
- Handle TTY and interactive mode appropriately
+341
View File
@@ -0,0 +1,341 @@
#!/bin/bash
# scripts/lib/config.sh - Configuration file utilities for TOML and other formats
set -euo pipefail
# Source environment and JSON helpers
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/env.sh"
source "${SCRIPT_DIR}/jq_patch.sh"
# Check if crudini is available for TOML operations
CRUDINI_AVAILABLE=false
if command -v crudini >/dev/null 2>&1; then
CRUDINI_AVAILABLE=true
fi
# Set TOML value using crudini if available, fallback to sed
# Usage: set_toml_value <file> <section> <key> <value>
set_toml_value() {
local file="$1"
local section="$2"
local key="$3"
local value="$4"
ensure_file "$file"
if [[ "$CRUDINI_AVAILABLE" == "true" ]]; then
if crudini --set "$file" "$section" "$key" "$value" 2>/dev/null; then
log_success "Set $section.$key = $value in $file"
return 0
fi
fi
# Fallback to sed for simple cases
log_warn "Using sed fallback for TOML update (install crudini for better support)"
# Escape special characters in value
local escaped_value
escaped_value=$(printf '%s\n' "$value" | sed 's/[[\.*^$()+?{|]/\\&/g')
# Try to find and replace the line
if sed -i "s|^\s*$key\s*=.*|$key = \"$escaped_value\"|g" "$file"; then
log_success "Set $key = $value in $file (using sed)"
return 0
fi
log_error "Failed to set $section.$key in $file"
return 1
}
# Enable RPC server
# Usage: enable_rpc <config_file> [port]
enable_rpc() {
local config_file="$1"
local port="${2:-26657}"
ensure_file "$config_file"
log_info "Enabling RPC server on port $port"
# Update laddr
set_toml_value "$config_file" "" "laddr" "tcp://0.0.0.0:$port"
# Enable CORS
set_toml_value "$config_file" "" "cors_allowed_origins" '["*"]'
}
# Enable REST API server
# Usage: enable_rest <app_config_file> [port]
enable_rest() {
local app_config_file="$1"
local port="${2:-1317}"
ensure_file "$app_config_file"
log_info "Enabling REST API server on port $port"
# Update address
set_toml_value "$app_config_file" "api" "address" "tcp://0.0.0.0:$port"
# Enable API
set_toml_value "$app_config_file" "api" "enable" "true"
# Enable unsafe CORS
set_toml_value "$app_config_file" "api" "enabled-unsafe-cors" "true"
}
# Enable gRPC server
# Usage: enable_grpc <app_config_file> [port]
enable_grpc() {
local app_config_file="$1"
local port="${2:-9090}"
ensure_file "$app_config_file"
log_info "Enabling gRPC server on port $port"
# Update address
set_toml_value "$app_config_file" "grpc" "address" "0.0.0.0:$port"
}
# Enable gRPC-Web server
# Usage: enable_grpc_web <app_config_file> [port]
enable_grpc_web() {
local app_config_file="$1"
local port="${2:-9091}"
ensure_file "$app_config_file"
log_info "Enabling gRPC-Web server on port $port"
# Update address
set_toml_value "$app_config_file" "grpc-web" "address" "0.0.0.0:$port"
}
# Enable JSON-RPC
# Usage: enable_json_rpc <app_config_file> [port] [ws_port]
enable_json_rpc() {
local app_config_file="$1"
local port="${2:-8545}"
local ws_port="${3:-8546}"
ensure_file "$app_config_file"
log_info "Enabling JSON-RPC on port $port (WebSocket: $ws_port)"
# Enable JSON-RPC
set_toml_value "$app_config_file" "json-rpc" "enable" "true"
# Set address
set_toml_value "$app_config_file" "json-rpc" "address" "0.0.0.0:$port"
# Set WebSocket address
set_toml_value "$app_config_file" "json-rpc" "ws-address" "0.0.0.0:$ws_port"
# Enable APIs
set_toml_value "$app_config_file" "json-rpc" "api" "eth,txpool,personal,net,debug,web3"
}
# Enable Rosetta API
# Usage: enable_rosetta <app_config_file> [port]
enable_rosetta() {
local app_config_file="$1"
local port="${2:-8080}"
ensure_file "$app_config_file"
log_info "Enabling Rosetta API on port $port"
# Update address
set_toml_value "$app_config_file" "rosetta" "address" "0.0.0.0:$port"
}
# Set consensus timeouts
# Usage: set_consensus_timeouts <config_file> [propose] [prevote] [precommit] [commit]
set_consensus_timeouts() {
local config_file="$1"
local timeout_propose="${2:-5s}"
local timeout_prevote="${3:-1s}"
local timeout_precommit="${4:-1s}"
local timeout_commit="${5:-5s}"
ensure_file "$config_file"
log_info "Setting consensus timeouts: propose=$timeout_propose, prevote=$timeout_prevote, precommit=$timeout_precommit, commit=$timeout_commit"
set_toml_value "$config_file" "consensus" "timeout_propose" "$timeout_propose"
set_toml_value "$config_file" "consensus" "timeout_prevote" "$timeout_prevote"
set_toml_value "$config_file" "consensus" "timeout_precommit" "$timeout_precommit"
set_toml_value "$config_file" "consensus" "timeout_commit" "$timeout_commit"
}
# Set pruning strategy
# Usage: set_pruning <app_config_file> [strategy]
set_pruning() {
local app_config_file="$1"
local strategy="${2:-default}"
ensure_file "$app_config_file"
log_info "Setting pruning strategy to $strategy"
set_toml_value "$app_config_file" "pruning" "strategy" "$strategy"
}
# Set minimum gas prices
# Usage: set_min_gas_prices <app_config_file> [price]
set_min_gas_prices() {
local app_config_file="$1"
local price="${2:-0${DENOM}}"
ensure_file "$app_config_file"
log_info "Setting minimum gas prices to $price"
set_toml_value "$app_config_file" "minimum-gas-prices" "minimum-gas-prices" "$price"
}
# Enable metrics
# Usage: enable_metrics <config_file> [retention_time]
enable_metrics() {
local config_file="$1"
local retention_time="${2:-3600}"
ensure_file "$config_file"
log_info "Enabling metrics with retention time ${retention_time}s"
# Enable prometheus in config.toml
set_toml_value "$config_file" "instrumentation" "prometheus" "true"
# Set retention time in app.toml
if [[ -f "$config_file" ]]; then
set_toml_value "$config_file" "telemetry" "prometheus-retention-time" "$retention_time"
fi
}
# Set keyring backend
# Usage: set_keyring_backend <client_config_file> [backend]
set_keyring_backend() {
local client_config_file="$1"
local backend="${2:-test}"
ensure_file "$client_config_file"
log_info "Setting keyring backend to $backend"
set_toml_value "$client_config_file" "keyring-backend" "keyring-backend" "$backend"
}
# Set chain ID in client config
# Usage: set_client_chain_id <client_config_file> [chain_id]
set_client_chain_id() {
local client_config_file="$1"
local chain_id="${2:-$CHAIN_ID}"
ensure_file "$client_config_file"
log_info "Setting client chain ID to $chain_id"
set_toml_value "$client_config_file" "chain-id" "chain-id" "$chain_id"
}
# Set client output format
# Usage: set_client_output <client_config_file> [format]
set_client_output() {
local client_config_file="$1"
local format="${2:-json}"
ensure_file "$client_config_file"
log_info "Setting client output format to $format"
set_toml_value "$client_config_file" "output" "output" "$format"
}
# Configure full node settings
# Usage: configure_node <config_dir> [options...]
configure_node() {
local config_dir="$1"
shift
ensure_chain_dir
local config_toml="$config_dir/config/config.toml"
local app_toml="$config_dir/config/app.toml"
local client_toml="$config_dir/config/client.toml"
log_info "Configuring node in $config_dir"
# Apply configurations based on arguments
while [[ $# -gt 0 ]]; do
case $1 in
--rpc-port)
enable_rpc "$config_toml" "$2"
shift 2
;;
--rest-port)
enable_rest "$app_toml" "$2"
shift 2
;;
--grpc-port)
enable_grpc "$app_toml" "$2"
shift 2
;;
--grpc-web-port)
enable_grpc_web "$app_toml" "$2"
shift 2
;;
--json-rpc-port)
enable_json_rpc "$app_toml" "$2" "$3"
shift 3
;;
--rosetta-port)
enable_rosetta "$app_toml" "$2"
shift 2
;;
--consensus-timeouts)
set_consensus_timeouts "$config_toml" "$2" "$3" "$4" "$5"
shift 5
;;
--pruning)
set_pruning "$app_toml" "$2"
shift 2
;;
--min-gas-prices)
set_min_gas_prices "$app_toml" "$2"
shift 2
;;
--metrics)
enable_metrics "$config_toml" "$2"
shift 2
;;
--keyring-backend)
set_keyring_backend "$client_toml" "$2"
shift 2
;;
--chain-id)
set_client_chain_id "$client_toml" "$2"
shift 2
;;
--output-format)
set_client_output "$client_toml" "$2"
shift 2
;;
*)
log_error "Unknown configuration option: $1"
return 1
;;
esac
done
log_success "Node configuration completed"
}
# Export functions
export -f set_toml_value enable_rpc enable_rest enable_grpc enable_grpc_web
export -f enable_json_rpc enable_rosetta set_consensus_timeouts set_pruning
export -f set_min_gas_prices enable_metrics set_keyring_backend set_client_chain_id
export -f set_client_output configure_node
+141
View File
@@ -0,0 +1,141 @@
#!/bin/bash
# scripts/lib/env.sh - Environment defaults and utility functions for Sonr scripts
set -euo pipefail
# Default environment variables for Sonr
export DENOM="${DENOM:=usnr}"
export CHAIN_BIN="${CHAIN_BIN:=snrd}"
export CHAIN_DIR="${CHAIN_DIR:=$HOME/.sonr}"
export CHAIN_ID="${CHAIN_ID:=sonrtest_1-1}"
export KEYRING_BACKEND="${KEYRING_BACKEND:=test}"
export NODE_URL="${NODE_URL:=http://0.0.0.0:26657}"
export GAS="${GAS:=auto}"
export GAS_ADJUSTMENT="${GAS_ADJUSTMENT:=1.5}"
# Colors for logging
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $*"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $*"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $*"
}
# Utility functions
require_cmd() {
local cmd="$1"
if ! command -v "$cmd" >/dev/null 2>&1; then
log_error "Required command '$cmd' not found. Please install it."
exit 1
fi
}
join_path() {
local base="$1"
local path="$2"
echo "$base/$path" | sed 's#//#/#g'
}
# Check if running in Docker
is_docker() {
[[ -f /.dockerenv ]] || [[ -n "${DOCKER_CONTAINER:-}" ]]
}
# Get absolute path
abs_path() {
local path="$1"
if [[ -d "$path" ]]; then
cd "$path" && pwd
else
cd "$(dirname "$path")" && echo "$(pwd)/$(basename "$path")"
fi
}
# Validate chain directory exists
ensure_chain_dir() {
if [[ ! -d "$CHAIN_DIR" ]]; then
log_error "Chain directory does not exist: $CHAIN_DIR"
exit 1
fi
}
# Validate binary exists
ensure_binary() {
if ! command -v "$CHAIN_BIN" >/dev/null 2>&1; then
log_error "Binary '$CHAIN_BIN' not found in PATH"
exit 1
fi
}
# Check if file exists
ensure_file() {
local file="$1"
if [[ ! -f "$file" ]]; then
log_error "Required file not found: $file"
exit 1
fi
}
# Retry function for operations that might fail
retry() {
local max_attempts="$1"
local delay="$2"
local cmd="$3"
shift 3
local attempt=1
while [[ $attempt -le $max_attempts ]]; do
log_info "Attempt $attempt/$max_attempts: $cmd $*"
if "$cmd" "$@"; then
return 0
fi
if [[ $attempt -lt $max_attempts ]]; then
log_warn "Command failed, retrying in ${delay}s..."
sleep "$delay"
fi
((attempt++))
done
log_error "Command failed after $max_attempts attempts: $cmd $*"
return 1
}
# Initialize environment
init_env() {
require_cmd jq
ensure_binary
# Set up cleanup trap
trap cleanup EXIT
log_info "Environment initialized for Sonr chain: $CHAIN_ID"
}
cleanup() {
# Remove temporary files if they exist
rm -f /tmp/genesis.json /tmp/config.toml /tmp/app.toml /tmp/client.toml
}
# Export functions for use in other scripts
export -f log_info log_warn log_error log_success
export -f require_cmd join_path is_docker abs_path
export -f ensure_chain_dir ensure_binary ensure_file
export -f retry init_env cleanup
+210
View File
@@ -0,0 +1,210 @@
#!/bin/bash
# scripts/lib/genesis.sh - Genesis file utilities for Sonr scripts
set -euo pipefail
# Source environment and JSON helpers
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/env.sh"
source "${SCRIPT_DIR}/jq_patch.sh"
# Generate VRF keypair for the network
# Usage: generate_vrf_key [chain_dir]
generate_vrf_key() {
local chain_dir="${1:-$CHAIN_DIR}"
ensure_chain_dir
local genesis_file="$chain_dir/config/genesis.json"
ensure_file "$genesis_file"
local chain_id
chain_id=$(get_json_value "$genesis_file" '.chain_id')
if [[ -z "$chain_id" || "$chain_id" == "null" ]]; then
log_error "Failed to extract chain-id from genesis file"
return 1
fi
log_info "Generating VRF keypair for network: $chain_id"
# Create deterministic entropy from chain-id using SHA256
local entropy_seed
entropy_seed=$(echo -n "$chain_id" | sha256sum | cut -d' ' -f1)
# Generate 64 bytes of deterministic randomness
local seed_part1="$entropy_seed"
local seed_part2
seed_part2=$(echo -n "$entropy_seed" | sha256sum | cut -d' ' -f1)
# Combine to create 64 bytes of hex data
local vrf_key_hex="${seed_part1}${seed_part2}"
# Ensure we have exactly 128 hex characters (64 bytes)
if [[ ${#vrf_key_hex} -ne 128 ]]; then
log_error "Generated VRF key has incorrect size: ${#vrf_key_hex}"
return 1
fi
# Path to store VRF secret key
local vrf_key_path="$chain_dir/vrf_secret.key"
# Ensure directory exists
mkdir -p "$chain_dir"
# Convert hex to binary and write to file
echo -n "$vrf_key_hex" | xxd -r -p > "$vrf_key_path"
# Set restrictive permissions (owner read/write only)
chmod 0600 "$vrf_key_path"
# Validate file was created with correct size (64 bytes)
local file_size
file_size=$(wc -c < "$vrf_key_path")
if [[ $file_size -ne 64 ]]; then
log_error "VRF key file has incorrect size: ${file_size} bytes"
rm -f "$vrf_key_path"
return 1
fi
log_success "VRF keypair generated for network: $chain_id"
log_success "VRF secret key stored securely: $vrf_key_path"
return 0
}
# Update genesis with Sonr-specific parameters
# Usage: update_genesis_params [genesis_file]
update_genesis_params() {
local genesis_file="${1:-$CHAIN_DIR/config/genesis.json}"
ensure_file "$genesis_file"
log_info "Updating genesis parameters for Sonr"
# Update stake denomination
set_json_string "$genesis_file" 'app_state.staking.params.bond_denom' "$DENOM"
# Update mint denomination
set_json_string "$genesis_file" 'app_state.mint.params.mint_denom' "$DENOM"
# Update crisis fee
set_json_object "$genesis_file" 'app_state.crisis.constant_fee' "{\"denom\":\"$DENOM\",\"amount\":\"1000\"}"
# Update minimum commission rate
set_json_string "$genesis_file" 'app_state.staking.params.min_commission_rate' "0.050000000000000000"
# Update block max gas
set_json_string "$genesis_file" 'consensus.params.block.max_gas' "100000000000"
# Update unbonding time
set_json_string "$genesis_file" 'app_state.staking.params.unbonding_time' "300s"
# Update downtime jail duration
set_json_string "$genesis_file" 'app_state.slashing.params.downtime_jail_duration' "60s"
# Update governance parameters for SDK v0.47+
if json_path_exists "$genesis_file" '.app_state.gov.params'; then
set_json_string "$genesis_file" 'app_state.gov.params.max_deposit_period' "30s"
set_json_string "$genesis_file" 'app_state.gov.params.min_deposit[0].amount' "10"
set_json_string "$genesis_file" 'app_state.gov.params.voting_period' "30s"
set_json_string "$genesis_file" 'app_state.gov.params.quorum' "0.000000000000000000"
set_json_string "$genesis_file" 'app_state.gov.params.threshold' "0.000000000000000000"
set_json_string "$genesis_file" 'app_state.gov.params.veto_threshold' "0.000000000000000000"
fi
# Update EVM parameters if present
if json_path_exists "$genesis_file" '.app_state.evm'; then
set_json_string "$genesis_file" 'app_state.evm.params.evm_denom' "$DENOM"
set_json_object "$genesis_file" 'app_state.evm.params.active_static_precompiles' '["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805"]'
fi
# Update ERC20 parameters if present
if json_path_exists "$genesis_file" '.app_state.erc20'; then
set_json_object "$genesis_file" 'app_state.erc20.params.native_precompiles' '["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]'
set_json_object "$genesis_file" 'app_state.erc20.token_pairs' '[{"contract_owner":1,"erc20_address":"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE","denom":"'"$DENOM"'","enabled":true}]'
fi
# Update feemarket parameters if present
if json_path_exists "$genesis_file" '.app_state.feemarket'; then
set_json_bool "$genesis_file" 'app_state.feemarket.params.no_base_fee' true
set_json_string "$genesis_file" 'app_state.feemarket.params.base_fee' "0.000000000000000000"
fi
# Update tokenfactory parameters if present
if json_path_exists "$genesis_file" '.app_state.tokenfactory'; then
set_json_object "$genesis_file" 'app_state.tokenfactory.params.denom_creation_fee' '[]'
set_json_number "$genesis_file" 'app_state.tokenfactory.params.denom_creation_gas_consume' 100000
fi
# Update ABCI parameters if present
if json_path_exists "$genesis_file" '.consensus.params.abci'; then
set_json_string "$genesis_file" 'consensus.params.abci.vote_extensions_enable_height' "1"
fi
log_success "Genesis parameters updated for Sonr"
}
# Add constitution to governance if CONSTITUTION.md exists
# Usage: add_constitution [genesis_file] [constitution_file]
add_constitution() {
local genesis_file="${1:-$CHAIN_DIR/config/genesis.json}"
local constitution_file="${2:-CONSTITUTION.md}"
ensure_file "$genesis_file"
# Look for CONSTITUTION.md in the git root directory
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local git_root
git_root="$(cd "${script_dir}/.." && pwd)"
local constitution_path="$git_root/$constitution_file"
if [[ ! -f "$constitution_path" ]]; then
log_warn "Constitution file not found: $constitution_path"
return 0
fi
log_info "Adding constitution from: $constitution_path"
local constitution_content
constitution_content=$(cat "$constitution_path" | jq -Rs .)
set_json_object "$genesis_file" 'app_state.gov.constitution' "$constitution_content"
log_success "Constitution added to governance"
}
# Validate genesis file
# Usage: validate_genesis [genesis_file]
validate_genesis() {
local genesis_file="${1:-$CHAIN_DIR/config/genesis.json}"
ensure_file "$genesis_file"
log_info "Validating genesis file..."
# Validate JSON
validate_json "$genesis_file"
# Check required fields
local chain_id
chain_id=$(get_json_value "$genesis_file" '.chain_id')
if [[ -z "$chain_id" || "$chain_id" == "null" ]]; then
log_error "Genesis file missing chain_id"
return 1
fi
# Check app_state exists
if ! json_path_exists "$genesis_file" '.app_state'; then
log_error "Genesis file missing app_state"
return 1
fi
log_success "Genesis file validation passed"
}
# Export functions
export -f generate_vrf_key update_genesis_params add_constitution validate_genesis
+154
View File
@@ -0,0 +1,154 @@
#!/bin/bash
# scripts/lib/jq_patch.sh - JSON patching utilities for genesis and config files
set -euo pipefail
# Source environment helpers
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/env.sh"
# Patch JSON file with jq expression and save to temp file then move back
# Usage: patch_json <file> <jq_expression>
patch_json() {
local file="$1"
local jq_expr="$2"
ensure_file "$file"
log_info "Patching $file with: $jq_expr"
# Create temp file in same directory to avoid cross-filesystem issues
local temp_file
temp_file="$(dirname "$file")/.tmp.$(basename "$file").$$"
if ! jq -r "$jq_expr" "$file" > "$temp_file" 2>/dev/null; then
rm -f "$temp_file"
log_error "Failed to patch JSON file: $file"
return 1
fi
mv "$temp_file" "$file"
log_success "Successfully patched $file"
}
# Ensure array contains specific value
# Usage: ensure_array_contains <file> <path> <value>
ensure_array_contains() {
local file="$1"
local path="$2"
local value="$3"
ensure_file "$file"
local current_value
current_value=$(jq -r "$path // []" "$file")
# Check if value already exists
if [[ "$current_value" == *"\"$value\""* ]]; then
log_info "Value '$value' already exists in $path"
return 0
fi
# Add value to array
local jq_expr
jq_expr=".${path} += [\"$value\"]"
patch_json "$file" "$jq_expr"
}
# Set string value at path
# Usage: set_json_string <file> <path> <value>
set_json_string() {
local file="$1"
local path="$2"
local value="$3"
local jq_expr
jq_expr=".${path} = \"$value\""
patch_json "$file" "$jq_expr"
}
# Set numeric value at path
# Usage: set_json_number <file> <path> <value>
set_json_number() {
local file="$1"
local path="$2"
local value="$3"
local jq_expr
jq_expr=".${path} = $value"
patch_json "$file" "$jq_expr"
}
# Set boolean value at path
# Usage: set_json_bool <file> <path> <value>
set_json_bool() {
local file="$1"
local path="$2"
local value="$3"
local jq_expr
jq_expr=".${path} = $value"
patch_json "$file" "$jq_expr"
}
# Set object value at path
# Usage: set_json_object <file> <path> <json_object>
set_json_object() {
local file="$1"
local path="$2"
local json_object="$3"
local jq_expr
jq_expr=".${path} = $json_object"
patch_json "$file" "$jq_expr"
}
# Check if path exists and is not null
# Usage: json_path_exists <file> <path>
json_path_exists() {
local file="$1"
local path="$2"
ensure_file "$file"
local result
result=$(jq -r "$path // empty" "$file" 2>/dev/null)
[[ -n "$result" && "$result" != "null" ]]
}
# Get value at path
# Usage: get_json_value <file> <path>
get_json_value() {
local file="$1"
local path="$2"
ensure_file "$file"
jq -r "$path" "$file"
}
# Validate JSON file
# Usage: validate_json <file>
validate_json() {
local file="$1"
ensure_file "$file"
if ! jq empty "$file" >/dev/null 2>&1; then
log_error "Invalid JSON in file: $file"
return 1
fi
log_success "JSON validation passed for $file"
}
# Export functions
export -f patch_json ensure_array_contains set_json_string set_json_number
export -f set_json_bool set_json_object json_path_exists get_json_value validate_json
+211
View File
@@ -0,0 +1,211 @@
#!/bin/bash
# scripts/lib/keys.sh - Key management utilities for Sonr scripts
set -euo pipefail
# Source environment helpers
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/env.sh"
# Import mnemonic and add key to keyring
# Usage: import_mnemonic <key_name> <mnemonic> [algo]
import_mnemonic() {
local key_name="$1"
local mnemonic="$2"
local algo="${3:-eth_secp256k1}"
log_info "Importing key '$key_name'"
if [[ -z "$mnemonic" ]]; then
log_error "Mnemonic cannot be empty"
return 1
fi
# Use Docker wrapper if needed
if is_docker; then
echo "$mnemonic" | $CHAIN_BIN keys add "$key_name" \
--keyring-backend "$KEYRING_BACKEND" \
--algo "$algo" \
--recover
else
echo "$mnemonic" | $CHAIN_BIN keys add "$key_name" \
--keyring-backend "$KEYRING_BACKEND" \
--algo "$algo" \
--home "$CHAIN_DIR" \
--recover
fi
log_success "Key '$key_name' imported successfully"
}
# Ensure key exists in keyring
# Usage: ensure_key <key_name>
ensure_key() {
local key_name="$1"
if ! $CHAIN_BIN keys show "$key_name" \
--keyring-backend "$KEYRING_BACKEND" \
--home "$CHAIN_DIR" \
--output json >/dev/null 2>&1; then
log_error "Key '$key_name' not found in keyring"
return 1
fi
log_info "Key '$key_name' exists in keyring"
}
# Get key address
# Usage: get_key_address <key_name>
get_key_address() {
local key_name="$1"
ensure_key "$key_name"
local address
address=$($CHAIN_BIN keys show "$key_name" \
--keyring-backend "$KEYRING_BACKEND" \
--home "$CHAIN_DIR" \
--output json | jq -r '.address')
if [[ -z "$address" || "$address" == "null" ]]; then
log_error "Failed to get address for key '$key_name'"
return 1
fi
echo "$address"
}
# Fund key with tokens from genesis
# Usage: fund_key <key_name> <amount>
fund_key() {
local key_name="$1"
local amount="$2"
ensure_key "$key_name"
local address
address=$(get_key_address "$key_name")
log_info "Funding key '$key_name' ($address) with $amount"
if is_docker; then
$CHAIN_BIN genesis add-genesis-account "$address" "$amount" \
--keyring-backend "$KEYRING_BACKEND"
else
$CHAIN_BIN genesis add-genesis-account "$address" "$amount" \
--keyring-backend "$KEYRING_BACKEND" \
--home "$CHAIN_DIR"
fi
log_success "Funded key '$key_name' with $amount"
}
# Delegate tokens to validator
# Usage: delegate_to_validator <delegator_key> <validator_address> <amount>
delegate_to_validator() {
local delegator_key="$1"
local validator_address="$2"
local amount="$3"
ensure_key "$delegator_key"
log_info "Delegating $amount from '$delegator_key' to validator $validator_address"
$CHAIN_BIN tx staking delegate "$validator_address" "$amount" \
--from "$delegator_key" \
--chain-id "$CHAIN_ID" \
--node "$NODE_URL" \
--keyring-backend "$KEYRING_BACKEND" \
--gas "$GAS" \
--gas-adjustment "$GAS_ADJUSTMENT" \
--yes
log_success "Delegation completed"
}
# Create validator with key
# Usage: create_validator <key_name> <moniker> <amount> [options...]
create_validator() {
local key_name="$1"
local moniker="$2"
local amount="$3"
shift 3
ensure_key "$key_name"
local validator_address
validator_address=$(get_key_address "$key_name")
log_info "Creating validator '$moniker' with key '$key_name'"
# Build validator JSON
local validator_json
validator_json=$(cat <<EOF
{
"pubkey": "$($CHAIN_BIN tendermint show-validator)",
"amount": "$amount",
"moniker": "$moniker",
"commission-rate": "0.1",
"commission-max-rate": "0.2",
"commission-max-change-rate": "0.01",
"min-self-delegation": "1000000"
}
EOF
)
echo "$validator_json" > /tmp/validator.json
$CHAIN_BIN tx staking create-validator /tmp/validator.json \
--from "$key_name" \
--chain-id "$CHAIN_ID" \
--node "$NODE_URL" \
--keyring-backend "$KEYRING_BACKEND" \
--gas "$GAS" \
--gas-adjustment "$GAS_ADJUSTMENT" \
--yes
rm -f /tmp/validator.json
log_success "Validator '$moniker' created successfully"
}
# Wait for node to sync
# Usage: wait_for_sync [max_tries]
wait_for_sync() {
local max_tries="${1:-10}"
log_info "Waiting for node to sync..."
local tries=0
while [[ $tries -lt $max_tries ]]; do
if $CHAIN_BIN status \
--node "$NODE_URL" \
--output json 2>/dev/null | jq -e '.SyncInfo.catching_up == false' >/dev/null 2>&1; then
log_success "Node is synced"
return 0
fi
log_info "Still syncing... ($((tries + 1))/$max_tries)"
sleep 30
((tries++))
done
log_error "Node failed to sync after $max_tries attempts"
return 1
}
# List keys in keyring
# Usage: list_keys
list_keys() {
$CHAIN_BIN keys list \
--keyring-backend "$KEYRING_BACKEND" \
--home "$CHAIN_DIR" \
--output json | jq
}
# Export functions
export -f import_mnemonic ensure_key get_key_address fund_key
export -f delegate_to_validator create_validator wait_for_sync list_keys
+228
View File
@@ -0,0 +1,228 @@
#!/bin/bash
# scripts/lib/tx.sh - Transaction utilities for Sonr scripts
set -euo pipefail
# Source environment and key helpers
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/env.sh"
source "${SCRIPT_DIR}/keys.sh"
# Submit transaction with automatic gas and error handling
# Usage: submit_tx <from_key> <command...>
submit_tx() {
local from_key="$1"
shift
ensure_key "$from_key"
log_info "Submitting transaction from '$from_key': $*"
local tx_result
tx_result=$($CHAIN_BIN tx "$@" \
--from "$from_key" \
--chain-id "$CHAIN_ID" \
--node "$NODE_URL" \
--keyring-backend "$KEYRING_BACKEND" \
--gas "$GAS" \
--gas-adjustment "$GAS_ADJUSTMENT" \
--output json \
--yes 2>&1)
# Check for transaction hash
local tx_hash
tx_hash=$(echo "$tx_result" | jq -r '.txhash // empty')
if [[ -n "$tx_hash" && "$tx_hash" != "null" ]]; then
log_success "Transaction submitted: $tx_hash"
# Wait for confirmation
sleep 5
# Query transaction result
local tx_query
tx_query=$($CHAIN_BIN query tx "$tx_hash" \
--node "$NODE_URL" \
--output json 2>/dev/null)
local tx_code
tx_code=$(echo "$tx_query" | jq -r '.code // 0')
if [[ "$tx_code" == "0" ]]; then
log_success "Transaction confirmed successfully"
echo "$tx_hash"
return 0
else
local tx_log
tx_log=$(echo "$tx_query" | jq -r '.raw_log // "Unknown error"')
log_error "Transaction failed (code $tx_code): $tx_log"
return 1
fi
else
log_error "Transaction submission failed: $tx_result"
return 1
fi
}
# Query with error handling
# Usage: query_chain <command...>
query_chain() {
log_info "Querying chain: $*"
local result
result=$($CHAIN_BIN query "$@" \
--node "$NODE_URL" \
--output json 2>/dev/null)
if [[ -z "$result" || "$result" == "null" ]]; then
log_error "Query failed or returned null"
return 1
fi
echo "$result"
}
# Get validator address (first available)
# Usage: get_validator_address
get_validator_address() {
log_info "Getting validator address..."
local validators
validators=$(query_chain staking validators)
local validator_address
validator_address=$(echo "$validators" | jq -r '.validators[0].operator_address // empty')
if [[ -z "$validator_address" || "$validator_address" == "null" ]]; then
log_error "No validators found"
return 1
fi
log_success "Using validator: $validator_address"
echo "$validator_address"
}
# Submit governance proposal
# Usage: submit_proposal <from_key> <proposal_file> [proposal_type]
submit_proposal() {
local from_key="$1"
local proposal_file="$2"
local proposal_type="${3:-}"
ensure_file "$proposal_file"
ensure_key "$from_key"
log_info "Submitting governance proposal from '$from_key'"
local submit_cmd="submit-proposal"
if [[ -n "$proposal_type" ]]; then
submit_cmd="$submit_cmd $proposal_type"
fi
# Check if legacy proposal command is needed
if ! $CHAIN_BIN tx gov submit-proposal --help 2>/dev/null | grep -q "submit-proposal"; then
submit_cmd="submit-legacy-proposal"
fi
submit_tx "$from_key" gov "$submit_cmd" "$proposal_file"
}
# Vote on governance proposal
# Usage: vote_proposal <from_key> <proposal_id> <vote_option>
vote_proposal() {
local from_key="$1"
local proposal_id="$2"
local vote_option="${3:-yes}"
ensure_key "$from_key"
log_info "Voting '$vote_option' on proposal $proposal_id from '$from_key'"
submit_tx "$from_key" gov vote "$proposal_id" "$vote_option"
}
# Wait for proposal to pass
# Usage: wait_for_proposal <proposal_id> [max_tries] [interval]
wait_for_proposal() {
local proposal_id="$1"
local max_tries="${2:-3}"
local interval="${3:-30}"
log_info "Waiting for proposal $proposal_id to pass..."
local tries=0
while [[ $tries -lt $max_tries ]]; do
local status
status=$(query_chain gov proposal "$proposal_id" | jq -r '.status // "unknown"')
case "$status" in
"PROPOSAL_STATUS_PASSED")
log_success "Proposal $proposal_id has passed"
return 0
;;
"PROPOSAL_STATUS_REJECTED")
log_error "Proposal $proposal_id was rejected"
return 1
;;
"PROPOSAL_STATUS_FAILED")
log_error "Proposal $proposal_id failed"
return 1
;;
*)
log_info "Proposal status: $status ($((tries + 1))/$max_tries)"
sleep "$interval"
((tries++))
;;
esac
done
log_error "Proposal $proposal_id did not pass after $max_tries attempts"
return 1
}
# Stake tokens to validator
# Usage: stake_tokens <from_key> <validator_address> <amount>
stake_tokens() {
local from_key="$1"
local validator_address="$2"
local amount="$3"
ensure_key "$from_key"
log_info "Staking $amount from '$from_key' to $validator_address"
submit_tx "$from_key" staking delegate "$validator_address" "$amount"
}
# Query account balance
# Usage: get_balance <address> [denom]
get_balance() {
local address="$1"
local denom="${2:-$DENOM}"
log_info "Getting balance for $address (denom: $denom)"
local balance
balance=$(query_chain bank balances "$address" | jq -r ".balances[] | select(.denom == \"$denom\") | .amount // \"0\"")
echo "$balance"
}
# Send tokens
# Usage: send_tokens <from_key> <to_address> <amount>
send_tokens() {
local from_key="$1"
local to_address="$2"
local amount="$3"
ensure_key "$from_key"
log_info "Sending $amount from '$from_key' to $to_address"
submit_tx "$from_key" bank send "$from_key" "$to_address" "$amount"
}
# Export functions
export -f submit_tx query_chain get_validator_address submit_proposal
export -f vote_proposal wait_for_proposal stake_tokens get_balance send_tokens
+123 -257
View File
@@ -5,156 +5,76 @@
# CHAIN_ID="localchain_9000-1" HOME_DIR="~/.sonr" BLOCK_TIME="1000ms" CLEAN=true sh scripts/test_node.sh
# CHAIN_ID="localchain_9000-2" HOME_DIR="~/.sonr" CLEAN=true RPC=36657 REST=2317 PROFF=6061 P2P=36656 GRPC=8090 GRPC_WEB=8091 ROSETTA=8081 BLOCK_TIME="500ms" sh scripts/test_node.sh
set -eu
set -euo pipefail
export KEY="acc0"
export KEY2="acc1"
# Source helper libraries
# Get the directory of this script reliably
SCRIPT_DIR="/usr/local/lib/sonr-scripts"
source "${SCRIPT_DIR}/env.sh"
source "${SCRIPT_DIR}/config.sh"
source "${SCRIPT_DIR}/keys.sh"
source "${SCRIPT_DIR}/genesis.sh"
export CHAIN_ID=${CHAIN_ID:-"sonrtest_1-1"}
export MONIKER="localvalidator"
export KEYALGO="eth_secp256k1"
export KEYRING=${KEYRING:-"test"}
export HOME_DIR=$(eval echo "${HOME_DIR:-"~/.sonr"}")
export BINARY=${BINARY:-snrd}
export DENOM=${DENOM:-usnr}
# Initialize environment
init_env
export CLEAN=${CLEAN:-"false"}
export RPC=${RPC:-"26657"}
export REST=${REST:-"1317"}
export PROFF=${PROFF:-"6060"}
export P2P=${P2P:-"26656"}
export GRPC=${GRPC:-"9090"}
export GRPC_WEB=${GRPC_WEB:-"9091"}
export ROSETTA=${ROSETTA:-"8080"}
export JSON_RPC=${JSON_RPC:-"8545"}
export JSON_RPC_WS=${JSON_RPC_WS:-"8546"}
export BLOCK_TIME=${BLOCK_TIME:-"5s"}
# Set defaults for test node
export KEY="${KEY:-acc0}"
export KEY2="${KEY2:-acc1}"
export MONIKER="${MONIKER:-localvalidator}"
export KEYALGO="${KEYALGO:-eth_secp256k1}"
# Configurable Mnemomics
export SONR_MNEMONIC_1=${SONR_MNEMONIC_1:-"decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry"}
export SONR_MNEMONIC_2=${SONR_MNEMONIC_2:-"wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise"}
# Configurable ports
export RPC="${RPC:-26657}"
export REST="${REST:-1317}"
export PROFF="${PROFF:-6060}"
export P2P="${P2P:-26656}"
export GRPC="${GRPC:-9090}"
export GRPC_WEB="${GRPC_WEB:-9091}"
export ROSETTA="${ROSETTA:-8080}"
export JSON_RPC="${JSON_RPC:-8545}"
export JSON_RPC_WS="${JSON_RPC_WS:-8546}"
export BLOCK_TIME="${BLOCK_TIME:-5s}"
# Configurable mnemonics
export SONR_MNEMONIC_1="${SONR_MNEMONIC_1:-decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry}"
export SONR_MNEMONIC_2="${SONR_MNEMONIC_2:-wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise}"
# Docker and installation options
export FORCE_DOCKER="${FORCE_DOCKER:-false}"
export SKIP_INSTALL="${SKIP_INSTALL:-false}"
export CLEAN="${CLEAN:-false}"
export DOCKER_DETACHED="${DOCKER_DETACHED:-false}"
# Check if binary exists, if not use Docker (or force Docker if requested)
export FORCE_DOCKER=${FORCE_DOCKER:-"false"}
export SKIP_INSTALL=${SKIP_INSTALL:-"false"}
USE_DOCKER=false
if [[ "${FORCE_DOCKER}" == "true" ]] || [[ -z $(which "${BINARY}") ]]; then
if [[ "${FORCE_DOCKER}" == "true" ]] || ! command -v "$CHAIN_BIN" >/dev/null 2>&1; then
# Check if Docker is available and use it
if command -v docker >/dev/null 2>&1; then
if [[ "${FORCE_DOCKER}" == "true" ]]; then
echo "Force Docker mode enabled, using Docker image onsonr/snrd:latest..."
log_info "Force Docker mode enabled, using Docker image onsonr/snrd:latest"
else
echo "Binary ${BINARY} not found locally, checking for Docker image onsonr/snrd:latest..."
log_info "Binary $CHAIN_BIN not found locally, checking for Docker image onsonr/snrd:latest"
fi
if docker image inspect onsonr/snrd:latest >/dev/null 2>&1; then
echo "Using Docker image onsonr/snrd:latest"
log_info "Using Docker image onsonr/snrd:latest"
USE_DOCKER=true
else
echo "Docker image onsonr/snrd:latest not found. Pulling image..."
log_info "Docker image onsonr/snrd:latest not found. Pulling image..."
docker pull onsonr/snrd:latest || {
echo "Failed to pull onsonr/snrd:latest. Please ensure Docker is running and you have internet access."
log_error "Failed to pull onsonr/snrd:latest. Please ensure Docker is running and you have internet access."
exit 1
}
USE_DOCKER=true
fi
else
echo "Binary ${BINARY} not found. Please either:"
echo " 1. Install ${BINARY} with 'make install'"
echo " 2. Install Docker to use the containerized version"
log_error "Binary $CHAIN_BIN not found. Please either:"
log_error " 1. Install $CHAIN_BIN with 'make install'"
log_error " 2. Install Docker to use the containerized version"
exit 1
fi
fi
# Final check if not using Docker
if [[ "${USE_DOCKER}" == "false" ]]; then
command -v "${BINARY}" >/dev/null 2>&1 || {
echo >&2 "${BINARY} command not found. Ensure this is setup / properly installed in your GOPATH (make install)."
exit 1
}
fi
command -v jq >/dev/null 2>&1 || {
echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"
exit 1
}
# generate_vrf_key generates a VRF keypair and stores it securely
# Mirrors the Go implementation in app/commands/enhance_init.go
generate_vrf_key() {
local home_dir="$1"
local use_docker="${2:-false}"
# Validate parameters
if [[ -z "${home_dir}" ]]; then
echo "Error: HOME_DIR parameter is required" >&2
return 1
fi
# Path to genesis file
local genesis_file="${home_dir}/config/genesis.json"
# Check if genesis file exists
if [[ ! -f "${genesis_file}" ]]; then
echo "Error: Genesis file not found at ${genesis_file}" >&2
return 1
fi
# Extract chain-id from genesis file
local chain_id
chain_id=$(jq -r '.chain_id' "${genesis_file}" 2>/dev/null)
if [[ -z "${chain_id}" || "${chain_id}" == "null" ]]; then
echo "Error: Failed to extract chain-id from genesis file" >&2
return 1
fi
echo "Generating VRF keypair for network: ${chain_id}"
# Create deterministic entropy from chain-id using SHA256
local entropy_seed
entropy_seed=$(echo -n "${chain_id}" | sha256sum | cut -d' ' -f1)
# Generate 64 bytes of deterministic randomness
local seed_part1="${entropy_seed}"
local seed_part2
seed_part2=$(echo -n "${entropy_seed}" | sha256sum | cut -d' ' -f1)
# Combine to create 64 bytes of hex data
local vrf_key_hex="${seed_part1}${seed_part2}"
# Ensure we have exactly 128 hex characters (64 bytes)
if [[ ${#vrf_key_hex} -ne 128 ]]; then
echo "Error: Generated VRF key has incorrect size: ${#vrf_key_hex}" >&2
return 1
fi
# Path to store VRF secret key
local vrf_key_path="${home_dir}/vrf_secret.key"
# Ensure directory exists
mkdir -p "${home_dir}"
# Convert hex to binary and write to file
echo -n "${vrf_key_hex}" | xxd -r -p > "${vrf_key_path}"
# Set restrictive permissions (owner read/write only)
chmod 0600 "${vrf_key_path}"
# Validate file was created with correct size (64 bytes)
local file_size
file_size=$(wc -c < "${vrf_key_path}")
if [[ ${file_size} -ne 64 ]]; then
echo "Error: VRF key file has incorrect size: ${file_size} bytes" >&2
rm -f "${vrf_key_path}"
return 1
fi
echo "✓ VRF keypair generated for network: ${chain_id}"
echo "✓ VRF secret key stored securely: ${vrf_key_path}"
return 0
}
# Create wrapper function for binary execution
run_binary() {
if [[ "${USE_DOCKER}" == "true" ]]; then
@@ -172,10 +92,11 @@ run_binary() {
onsonr/snrd:latest \
snrd --home /root/.sonr "$@"
else
${BINARY} "$@"
${CHAIN_BIN} "$@"
fi
}
# Set client configuration
set_config() {
run_binary config set client chain-id "${CHAIN_ID}"
run_binary config set client keyring-backend "${KEYRING}"
@@ -185,100 +106,49 @@ set_config
from_scratch() {
# Fresh install on current branch (skip if using Docker or SKIP_INSTALL is true)
if [[ "${USE_DOCKER}" == "false" ]] && [[ "${SKIP_INSTALL}" == "false" ]]; then
log_info "Installing $CHAIN_BIN..."
make install
fi
# remove existing daemon files.
# Remove existing daemon files
if [[ ${#HOME_DIR} -le 2 ]]; then
echo "HOME_DIR must be more than 2 characters long"
return
log_error "HOME_DIR must be more than 2 characters long"
return 1
fi
rm -rf "${HOME_DIR}" && echo "Removed ${HOME_DIR}"
rm -rf "${HOME_DIR}"
log_info "Removed existing chain directory: ${HOME_DIR}"
# reset values if not set already after whipe
# Reset configuration
set_config
add_key() {
key=$1
mnemonic=$2
if [[ "${USE_DOCKER}" == "true" ]]; then
# For Docker, we need to pass the mnemonic differently
mkdir -p "${HOME_DIR}"
echo "${mnemonic}" | docker run --rm -i \
-v "${HOME_DIR}:/root/.sonr" \
--network host \
onsonr/snrd:latest \
snrd --home /root/.sonr keys add "${key}" --keyring-backend "${KEYRING}" --algo "${KEYALGO}" --recover
else
echo "${mnemonic}" | ${BINARY} keys add "${key}" --keyring-backend "${KEYRING}" --algo "${KEYALGO}" --home "${HOME_DIR}" --recover
fi
}
# idx140fehngcrxvhdt84x729p3f0qmkmea8n570lrg
add_key "${KEY}" "${SONR_MNEMONIC_1}"
# idx1r6yue0vuyj9m7xw78npspt9drq2tmtvgcrf7sr
add_key "${KEY2}" "${SONR_MNEMONIC_2}"
# Add test keys
log_info "Adding test keys..."
import_mnemonic "${KEY}" "${SONR_MNEMONIC_1}" "$KEYALGO"
import_mnemonic "${KEY2}" "${SONR_MNEMONIC_2}" "$KEYALGO"
# Initialize chain
log_info "Initializing chain with moniker: $MONIKER"
if [[ "${USE_DOCKER}" == "true" ]]; then
# For Docker init, we need to handle it specially
docker run --rm \
-v "${HOME_DIR}:/root/.sonr" \
--network host \
onsonr/snrd:latest \
snrd --home /root/.sonr init "${MONIKER}" --chain-id "${CHAIN_ID}" --default-denom "${DENOM}"
else
${BINARY} init "${MONIKER}" --chain-id "${CHAIN_ID}" --default-denom "${DENOM}" --home "${HOME_DIR}"
${CHAIN_BIN} init "${MONIKER}" --chain-id "${CHAIN_ID}" --default-denom "${DENOM}" --home "${HOME_DIR}"
fi
update_test_genesis() {
cat "${HOME_DIR}"/config/genesis.json | jq "$1" >"${HOME_DIR}"/config/tmp_genesis.json && mv "${HOME_DIR}"/config/tmp_genesis.json "${HOME_DIR}"/config/genesis.json
}
# Update genesis parameters
log_info "Updating genesis parameters..."
update_genesis_params
# === CORE MODULES ===
# Add constitution if available
add_constitution
# Block
update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"'
# Set up genesis accounts and transactions
local BASE_GENESIS_ALLOCATIONS="100000000000000000000000000${DENOM},100000000test"
# Gov
update_test_genesis $(printf '.app_state["gov"]["params"]["min_deposit"]=[{"denom":"%s","amount":"1000000"}]' "${DENOM}")
update_test_genesis '.app_state["gov"]["params"]["voting_period"]="30s"'
update_test_genesis '.app_state["gov"]["params"]["expedited_voting_period"]="15s"'
# Add CONSTITUTION.md to governance if it exists
if [ -f "CONSTITUTION.md" ]; then
CONSTITUTION_CONTENT=$(cat CONSTITUTION.md | jq -Rs .)
update_test_genesis ".app_state[\"gov\"][\"constitution\"]=$CONSTITUTION_CONTENT"
fi
update_test_genesis $(printf '.app_state["evm"]["params"]["evm_denom"]="%s"' "${DENOM}")
update_test_genesis '.app_state["evm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805"]'
update_test_genesis '.app_state["erc20"]["params"]["native_precompiles"]=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' # https://eips.ethereum.org/EIPS/eip-7528
update_test_genesis $(printf '.app_state["erc20"]["token_pairs"]=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"%s",enabled:true}]' "${DENOM}")
update_test_genesis '.app_state["feemarket"]["params"]["no_base_fee"]=true'
update_test_genesis '.app_state["feemarket"]["params"]["base_fee"]="0.000000000000000000"'
# staking
update_test_genesis $(printf '.app_state["staking"]["params"]["bond_denom"]="%s"' "${DENOM}")
update_test_genesis '.app_state["staking"]["params"]["min_commission_rate"]="0.050000000000000000"'
# mint
update_test_genesis $(printf '.app_state["mint"]["params"]["mint_denom"]="%s"' "${DENOM}")
# crisis
update_test_genesis $(printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' "${DENOM}")
## abci
update_test_genesis '.consensus["params"]["abci"]["vote_extensions_enable_height"]="1"'
# === CUSTOM MODULES ===
# tokenfactory
update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_fee"]=[]'
update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_gas_consume"]=100000'
BASE_GENESIS_ALLOCATIONS="100000000000000000000000000${DENOM},100000000test"
# Allocate genesis accounts
log_info "Adding genesis accounts..."
if [[ "${USE_DOCKER}" == "true" ]]; then
docker run --rm \
-v "${HOME_DIR}:/root/.sonr" \
@@ -307,85 +177,78 @@ from_scratch() {
onsonr/snrd:latest \
snrd --home /root/.sonr genesis validate-genesis
else
${BINARY} genesis add-genesis-account "${KEY}" "${BASE_GENESIS_ALLOCATIONS}" --keyring-backend "${KEYRING}" --home "${HOME_DIR}" --append
${BINARY} genesis add-genesis-account "${KEY2}" "${BASE_GENESIS_ALLOCATIONS}" --keyring-backend "${KEYRING}" --home "${HOME_DIR}" --append
${CHAIN_BIN} genesis add-genesis-account "${KEY}" "${BASE_GENESIS_ALLOCATIONS}" --keyring-backend "${KEYRING}" --home "${HOME_DIR}" --append
${CHAIN_BIN} genesis add-genesis-account "${KEY2}" "${BASE_GENESIS_ALLOCATIONS}" --keyring-backend "${KEYRING}" --home "${HOME_DIR}" --append
# Sign genesis transaction
${BINARY} genesis gentx "${KEY}" 1000000000000000000000"${DENOM}" --gas-prices 0"${DENOM}" --keyring-backend "${KEYRING}" --chain-id "${CHAIN_ID}" --home "${HOME_DIR}"
${BINARY} genesis collect-gentxs --home "${HOME_DIR}"
${BINARY} genesis validate-genesis --home "${HOME_DIR}"
fi
err=$?
if [[ ${err} -ne 0 ]]; then
echo "Failed to validate genesis"
return
${CHAIN_BIN} genesis gentx "${KEY}" 1000000000000000000000"${DENOM}" --gas-prices 0"${DENOM}" --keyring-backend "${KEYRING}" --chain-id "${CHAIN_ID}" --home "${HOME_DIR}"
${CHAIN_BIN} genesis collect-gentxs --home "${HOME_DIR}"
${CHAIN_BIN} genesis validate-genesis --home "${HOME_DIR}"
fi
log_success "Genesis setup completed"
}
# check if CLEAN is not set to false
# Check if CLEAN is not set to false
if [[ ${CLEAN} != "false" ]]; then
echo "Starting from a clean state"
log_info "Starting from a clean state"
from_scratch
# Generate VRF keypair (must be done after genesis file is created)
echo ""
echo "Generating VRF keypair..."
if ! generate_vrf_key "${HOME_DIR}" "${USE_DOCKER}"; then
echo "Warning: VRF key generation failed, but continuing..."
echo "Note: Multi-validator encryption features may not work without VRF keys"
log_info "Generating VRF keypair..."
if ! generate_vrf_key "${HOME_DIR}"; then
log_warn "VRF key generation failed, but continuing..."
log_warn "Note: Multi-validator encryption features may not work without VRF keys"
fi
fi
echo "Starting node..."
log_info "Configuring node ports and settings..."
# Opens the RPC endpoint to outside connections
sed -i -e 's/laddr = "tcp:\/\/127.0.0.1:26657"/laddr = "tcp:\/\/0.0.0.0:'"${RPC}"'"/g' "${HOME_DIR}"/config/config.toml
sed -i -e 's/cors_allowed_origins = \[\]/cors_allowed_origins = \["*"\]/g' "${HOME_DIR}"/config/config.toml
# Configure node with all the specified ports and settings
configure_node "$HOME_DIR" \
--rpc-port "$RPC" \
--rest-port "$REST" \
--grpc-port "$GRPC" \
--grpc-web-port "$GRPC_WEB" \
--json-rpc-port "$JSON_RPC" \
--rosetta-port "$ROSETTA" \
--min-gas-prices "0${DENOM}" \
--pruning nothing
# REST endpoint
sed -i -e 's/address = "tcp:\/\/localhost:1317"/address = "tcp:\/\/0.0.0.0:'"${REST}"'"/g' "${HOME_DIR}"/config/app.toml
sed -i -e 's/enable = false/enable = true/g' "${HOME_DIR}"/config/app.toml
sed -i -e 's/enabled-unsafe-cors = false/enabled-unsafe-cors = true/g' "${HOME_DIR}"/config/app.toml
# Set consensus timeouts
set_consensus_timeouts "$HOME_DIR/config/config.toml" "5s" "1s" "1s" "$BLOCK_TIME"
# peer exchange
sed -i -e 's/pprof_laddr = "localhost:6060"/pprof_laddr = "localhost:'"${PROFF}"'"/g' "${HOME_DIR}"/config/config.toml
sed -i -e 's/laddr = "tcp:\/\/0.0.0.0:26656"/laddr = "tcp:\/\/0.0.0.0:'"${P2P}"'"/g' "${HOME_DIR}"/config/config.toml
# Enable CORS for RPC
set_toml_value "$HOME_DIR/config/config.toml" "" "cors_allowed_origins" '["*"]'
# GRPC
sed -i -e 's/address = "localhost:9090"/address = "0.0.0.0:'"${GRPC}"'"/g' "${HOME_DIR}"/config/app.toml
sed -i -e 's/address = "localhost:9091"/address = "0.0.0.0:'"${GRPC_WEB}"'"/g' "${HOME_DIR}"/config/app.toml
# Set pprof address
set_toml_value "$HOME_DIR/config/config.toml" "" "pprof_laddr" "localhost:${PROFF}"
# Rosetta Api
sed -i -e 's/address = ":8080"/address = "0.0.0.0:'"${ROSETTA}"'"/g' "${HOME_DIR}"/config/app.toml
# Set P2P address
set_toml_value "$HOME_DIR/config/config.toml" "p2p" "laddr" "tcp://0.0.0.0:${P2P}"
# JSON-RPC
sed -i -e '/\[json-rpc\]/,/^\[/ s/enable = false/enable = true/' "${HOME_DIR}"/config/app.toml
sed -i -e '/\[json-rpc\]/,/^\[/ s/address = "127.0.0.1:8545"/address = "0.0.0.0:'"${JSON_RPC}"'"/' "${HOME_DIR}"/config/app.toml
sed -i -e '/\[json-rpc\]/,/^\[/ s/ws-address = "127.0.0.1:8546"/ws-address = "0.0.0.0:'"${JSON_RPC_WS}"'"/' "${HOME_DIR}"/config/app.toml
# Faster blocks
sed -i -e 's/timeout_commit = "5s"/timeout_commit = "'"${BLOCK_TIME}"'"/g' "${HOME_DIR}"/config/config.toml
log_info "Starting node..."
# Start the node (with or without Docker)
if [[ "${USE_DOCKER}" == "true" ]]; then
echo "Starting node using Docker..."
log_info "Starting node using Docker..."
# Check for detached mode via environment variable or prompt
DETACHED_MODE=""
if [[ "${DOCKER_DETACHED}" == "true" ]]; then
DETACHED_MODE="-d"
echo "Running in detached mode. Use 'docker logs -f sonr-testnode' to view logs."
echo "Stop with: docker stop sonr-testnode"
log_info "Running in detached mode. Use 'docker logs -f sonr-testnode' to view logs."
log_info "Stop with: docker stop sonr-testnode"
elif [ -t 0 ]; then
echo ""
echo "Would you like to run the node in detached mode (background)? [y/N]"
log_info ""
log_info "Would you like to run the node in detached mode (background)? [y/N]"
read -r -n 1 DETACH_RESPONSE
echo ""
log_info ""
if [[ "$DETACH_RESPONSE" =~ ^[Yy]$ ]]; then
DETACHED_MODE="-d"
echo "Running in detached mode. Use 'docker logs -f sonr-testnode' to view logs."
echo "Stop with: docker stop sonr-testnode"
log_info "Running in detached mode. Use 'docker logs -f sonr-testnode' to view logs."
log_info "Stop with: docker stop sonr-testnode"
else
echo "Running in foreground mode. Use Ctrl+C to stop."
log_info "Running in foreground mode. Use Ctrl+C to stop."
fi
fi
@@ -404,15 +267,18 @@ if [[ "${USE_DOCKER}" == "true" ]]; then
# If running detached, show status
if [ -n "$DETACHED_MODE" ]; then
echo ""
echo "Node started in background"
echo ""
echo "Useful commands:"
echo " View logs: docker logs -f sonr-testnode"
echo " Stop node: docker stop sonr-testnode"
echo " Node status: curl http://localhost:${RPC}/status | jq '.result.sync_info'"
echo ""
log_info ""
log_success "Node started in background"
log_info ""
log_info "Useful commands:"
log_info " View logs: docker logs -f sonr-testnode"
log_info " Stop node: docker stop sonr-testnode"
log_info " Node status: curl http://localhost:${RPC}/status | jq '.result.sync_info'"
log_info ""
fi
else
${BINARY} start --pruning=nothing --minimum-gas-prices=0"${DENOM}" --rpc.laddr="tcp://0.0.0.0:${RPC}" --home "${HOME_DIR}" --json-rpc.api=eth,txpool,personal,net,debug,web3 --json-rpc.address="0.0.0.0:${JSON_RPC}" --json-rpc.ws-address="0.0.0.0:${JSON_RPC_WS}" --chain-id="${CHAIN_ID}"
log_info "Starting node locally..."
${CHAIN_BIN} start --pruning=nothing --minimum-gas-prices=0"${DENOM}" --rpc.laddr="tcp://0.0.0.0:${RPC}" --home "${HOME_DIR}" --json-rpc.api=eth,txpool,personal,net,debug,web3 --json-rpc.address="0.0.0.0:${JSON_RPC}" --json-rpc.ws-address="0.0.0.0:${JSON_RPC_WS}" --chain-id="${CHAIN_ID}"
fi
log_success "Node startup completed"
+84
View File
@@ -0,0 +1,84 @@
#!/bin/bash
# scripts/testnet-setup.sh - Initialize Sonr testnet nodes for Docker deployment
set -euo pipefail
# Source helper libraries
SCRIPT_DIR="/usr/local/lib/sonr-scripts"
source "${SCRIPT_DIR}/env.sh"
source "${SCRIPT_DIR}/config.sh"
source "${SCRIPT_DIR}/keys.sh"
source "${SCRIPT_DIR}/genesis.sh"
# Initialize environment
init_env
# Set defaults for testnet
NODE_TYPE="${NODE_TYPE:-validator}" # validator, sentry
MONIKER="${MONIKER:-validator}"
VALIDATOR_NAME="${VALIDATOR_NAME:-$MONIKER}"
CHAIN_ID="${CHAIN_ID:-sonrtest_1-1}"
HOME_DIR="${HOME_DIR:-/root/.sonr}"
log_info "Setting up Sonr testnet node: $NODE_TYPE ($VALIDATOR_NAME)"
# Ensure chain directory exists
ensure_chain_dir
# Update genesis parameters
log_info "Updating genesis parameters..."
update_genesis_params
# Add constitution if available
add_constitution
# Configure node
log_info "Configuring node..."
configure_node "$CHAIN_DIR" \
--rpc-port 26657 \
--rest-port 1317 \
--grpc-port 9090 \
--grpc-web-port 9091 \
--json-rpc-port 8545 8546 \
--rosetta-port 8080 \
--min-gas-prices "0${DENOM}" \
--pruning nothing \
--keyring-backend "$KEYRING_BACKEND" \
--chain-id "$CHAIN_ID" \
--output-format json
# Set consensus timeouts for faster blocks
set_consensus_timeouts "$CHAIN_DIR/config/config.toml" "5s" "1s" "1s" "1s"
# Enable CORS for RPC
set_toml_value "$CHAIN_DIR/config/config.toml" "" "cors_allowed_origins" '["*"]'
# Set pprof address
set_toml_value "$CHAIN_DIR/config/config.toml" "" "pprof_laddr" "localhost:6060"
# Set P2P address
set_toml_value "$CHAIN_DIR/config/config.toml" "p2p" "laddr" "tcp://0.0.0.0:26656"
# Generate VRF keypair
log_info "Generating VRF keypair..."
if ! generate_vrf_key "$CHAIN_DIR"; then
log_warn "VRF key generation failed, but continuing..."
log_warn "Note: Multi-validator encryption features may not work without VRF keys"
fi
# Create validator if this is a validator node
if [[ "$NODE_TYPE" == "validator" ]]; then
log_info "Creating validator..."
# Wait for node to sync (in case it's connecting to other nodes)
if [[ "${WAIT_FOR_SYNC:-false}" == "true" ]]; then
wait_for_sync 10
fi
# Create validator (this would need proper key setup)
log_info "Validator creation requires manual key setup and gentx creation"
log_info "Run: snrd genesis gentx <validator-key> <amount> --chain-id $CHAIN_ID"
fi
log_success "Testnet setup completed for $NODE_TYPE node: $VALIDATOR_NAME"
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
ADDRESS="$1"
DENOM="$2"
FAUCET_URL="$3"
FAUCET_ENABLED="$4"
set -eux
function transfer_token() {
status_code=$(curl --header "Content-Type: application/json" \
--request POST --write-out %{http_code} --silent --output /dev/null \
--data '{"denom":"'"$DENOM"'","address":"'"$ADDRESS"'"}' \
$FAUCET_URL)
echo $status_code
}
if [[ $FAUCET_ENABLED == "false" ]];
then
echo "Faucet not enabled... skipping transfer token from faucet"
exit 0
fi
echo "Try to send tokens, if failed, wait for 5 seconds and try again"
max_tries=5
while [[ max_tries -gt 0 ]]
do
status_code=$(transfer_token)
if [[ "$status_code" -eq 200 ]]; then
echo "Successfully sent tokens"
exit 0
fi
echo "Failed to send tokens. Sleeping for 2 secs. Tries left $max_tries"
((max_tries--))
sleep 2
done
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
# scripts/update-config.sh - Update configuration files for Sonr node
set -euo pipefail
# Source helper libraries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib/env.sh"
source "${SCRIPT_DIR}/lib/config.sh"
# Initialize environment
init_env
# Ensure chain directory exists
ensure_chain_dir
log_info "Updating configuration files for Sonr node"
# Configure node with standard settings
configure_node "$CHAIN_DIR" \
--rpc-port 26657 \
--rest-port 1317 \
--grpc-port 9090 \
--grpc-web-port 9091 \
--json-rpc-port 8545 8546 \
--rosetta-port 8080 \
--min-gas-prices "0${DENOM}" \
--pruning default \
--keyring-backend "$KEYRING_BACKEND" \
--chain-id "$CHAIN_ID" \
--output-format json
# Enable metrics if requested
if [[ "${METRICS:-false}" == "true" ]]; then
enable_metrics "$CHAIN_DIR/config/config.toml" 3600
fi
# Set consensus timeouts if provided
if [[ -n "${TIMEOUT_PROPOSE:-}" ]]; then
set_consensus_timeouts "$CHAIN_DIR/config/config.toml" \
"$TIMEOUT_PROPOSE" \
"${TIMEOUT_PREVOTE:-1s}" \
"${TIMEOUT_PRECOMMIT:-1s}" \
"${TIMEOUT_COMMIT:-5s}"
fi
log_success "Configuration update completed"
+23 -121
View File
@@ -1,130 +1,32 @@
#!/bin/bash
DENOM="${DENOM:=usnr}"
CHAIN_BIN="${CHAIN_BIN:=snrd}"
CHAIN_DIR="${CHAIN_DIR:=$HOME/.sonr}"
# scripts/update-genesis.sh - Update genesis.json with Sonr-specific parameters
set -eux
set -euo pipefail
ls "$CHAIN_DIR"/config
echo "Update genesis.json file with updated local params"
sed -i -e "s/\"stake\"/\"$DENOM\"/g" "$CHAIN_DIR"/config/genesis.json
sed -i "s/\"time_iota_ms\": \".*\"/\"time_iota_ms\": \"$TIME_IOTA_MS\"/" "$CHAIN_DIR"/config/genesis.json
echo "Update max gas param"
jq -r '.consensus.params.block.max_gas |= "100000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
echo "Update staking unbonding time and slashing jail time"
jq -r '.app_state.staking.params.unbonding_time |= "300s"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.slashing.params.downtime_jail_duration |= "60s"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
# overrides for older sdk versions, before 0.47
function gov_overrides_sdk_v46() {
jq -r '.app_state.gov.deposit_params.max_deposit_period |= "30s"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.deposit_params.min_deposit[0].amount |= "10"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.voting_params.voting_period |= "30s"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.tally_params.quorum |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.tally_params.threshold |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.tally_params.veto_threshold |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
}
# overrides for newer sdk versions, post 0.47
function gov_overrides_sdk_v47() {
jq -r '.app_state.gov.params.max_deposit_period |= "30s"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.params.min_deposit[0].amount |= "10"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.params.voting_period |= "30s"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.params.quorum |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.params.threshold |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.gov.params.veto_threshold |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
}
# EVM and feemarket configuration
if [ "$(jq -r '.app_state.evm' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r ".app_state.evm.params.evm_denom |= \"$DENOM\"" "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.evm.params.active_static_precompiles |= ["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805"]' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
if [ "$(jq -r '.app_state.erc20' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r '.app_state.erc20.params.native_precompiles |= ["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r ".app_state.erc20.token_pairs |= [{\"contract_owner\":1,\"erc20_address\":\"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\",\"denom\":\"$DENOM\",\"enabled\":true}]" "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
if [ "$(jq -r '.app_state.feemarket.params' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r '.app_state.feemarket.params.no_base_fee |= true' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.feemarket.params.base_fee |= "0.000000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
# Staking and mint configuration
if [ "$(jq -r '.app_state.staking' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r ".app_state.staking.params.bond_denom |= \"$DENOM\"" "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.staking.params.min_commission_rate |= "0.050000000000000000"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
if [ "$(jq -r '.app_state.mint' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r ".app_state.mint.params.mint_denom |= \"$DENOM\"" "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
if [ "$(jq -r '.app_state.crisis' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r ".app_state.crisis.constant_fee |= {\"denom\":\"$DENOM\",\"amount\":\"1000\"}" "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
# Token factory configuration
if [ "$(jq -r '.app_state.tokenfactory' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r '.app_state.tokenfactory.params.denom_creation_fee |= []' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
jq -r '.app_state.tokenfactory.params.denom_creation_gas_consume |= 100000' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
# ABCI configuration
if [ "$(jq -r '.consensus.params.abci' "$CHAIN_DIR"/config/genesis.json)" != "null" ]; then
jq -r '.consensus.params.abci.vote_extensions_enable_height |= "1"' "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
# Add CONSTITUTION.md to governance if it exists
# Look for CONSTITUTION.md in the git root directory (parent of scripts directory)
# Source helper libraries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GIT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
CONSTITUTION_FILE="${GIT_ROOT}/CONSTITUTION.md"
source "${SCRIPT_DIR}/lib/env.sh"
source "${SCRIPT_DIR}/lib/genesis.sh"
if [ -f "$CONSTITUTION_FILE" ]; then
echo "Adding CONSTITUTION.md to governance module from: $CONSTITUTION_FILE"
CONSTITUTION_CONTENT=$(cat "$CONSTITUTION_FILE" | jq -Rs .)
jq -r ".app_state.gov.constitution = $CONSTITUTION_CONTENT" "$CHAIN_DIR"/config/genesis.json >/tmp/genesis.json
mv /tmp/genesis.json "$CHAIN_DIR"/config/genesis.json
fi
# Initialize environment
init_env
if [ "$(jq -r '.app_state.gov.params' "$CHAIN_DIR"/config/genesis.json)" == "null" ]; then
gov_overrides_sdk_v46
else
gov_overrides_sdk_v47
fi
# Ensure chain directory exists
ensure_chain_dir
log_info "Updating genesis.json file with Sonr parameters"
# Update genesis parameters using helper functions
update_genesis_params
# Add constitution if available
add_constitution
# Validate genesis file
validate_genesis
# Show node ID
$CHAIN_BIN tendermint show-node-id
log_success "Genesis update completed"