mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-03 01:41:44 +00:00
Executable
+163
@@ -0,0 +1,163 @@
|
||||
#!/bin/sh
|
||||
|
||||
# cli-docgen.sh
|
||||
# A shell script to generate CLI documentation by walking the installed snrd binary.
|
||||
# This script assumes snrd is already installed and available in PATH.
|
||||
|
||||
set -e # Exit immediately if a command exits with a non-zero status.
|
||||
|
||||
# --- Default Values ---
|
||||
OUT_DIR="./docs/cli"
|
||||
|
||||
# --- Usage Function ---
|
||||
usage() {
|
||||
echo "Usage: $0 [--out <dir>] [--help]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --out <dir> Specify the output directory."
|
||||
echo " (Default: ./docs/cli)"
|
||||
echo " --help Display this help message."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- Argument Parsing ---
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--out)
|
||||
if [ -n "$2" ]; then
|
||||
OUT_DIR="$2"
|
||||
shift 2
|
||||
else
|
||||
echo "Error: --out requires a directory path." >&2
|
||||
usage
|
||||
fi
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown option '$1'" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- Main Logic ---
|
||||
|
||||
# Check if snrd binary is installed
|
||||
if ! command -v snrd >/dev/null 2>&1; then
|
||||
echo "Error: snrd binary not found in PATH." >&2
|
||||
echo "Please run 'make install' first to install the snrd binary." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create output directory
|
||||
echo "Creating output directory: $OUT_DIR"
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
# Clean existing files
|
||||
echo "Cleaning existing documentation..."
|
||||
rm -f "$OUT_DIR"/*.md
|
||||
|
||||
# Function to sanitize filename
|
||||
sanitize_filename() {
|
||||
echo "$1" | tr ' ' '_' | tr '/' '-' | tr -d '[](){}' | sed 's/^-//;s/-$//'
|
||||
}
|
||||
|
||||
# Generate main command documentation
|
||||
echo "Generating documentation for snrd..."
|
||||
|
||||
# Main snrd help
|
||||
snrd --help >"$OUT_DIR/snrd.md" 2>&1 || true
|
||||
echo "Generated: $OUT_DIR/snrd.md"
|
||||
|
||||
# Get list of main commands
|
||||
echo "Walking command tree..."
|
||||
|
||||
# Primary commands we want to document
|
||||
MAIN_COMMANDS="auth genesis help init keys migrate node prune query rollback status tendermint tx version"
|
||||
|
||||
# Generate documentation for each main command
|
||||
for cmd in $MAIN_COMMANDS; do
|
||||
echo "Processing: snrd $cmd"
|
||||
|
||||
# Generate main command doc
|
||||
filename=$(sanitize_filename "$cmd")
|
||||
snrd "$cmd" --help >"$OUT_DIR/snrd_${filename}.md" 2>&1 || true
|
||||
echo " Generated: $OUT_DIR/snrd_${filename}.md"
|
||||
|
||||
# Special handling for commonly used sub-commands
|
||||
case "$cmd" in
|
||||
"query")
|
||||
# Document query sub-modules
|
||||
QUERY_MODULES="account accounts auth bank consensus delegation did distribution dwn feegrant gov slashing staking svc tendermint tx"
|
||||
for module in $QUERY_MODULES; do
|
||||
echo " Processing: snrd query $module"
|
||||
filename=$(sanitize_filename "query_${module}")
|
||||
snrd query "$module" --help >"$OUT_DIR/snrd_${filename}.md" 2>&1 || true
|
||||
done
|
||||
;;
|
||||
"tx")
|
||||
# Document tx sub-modules
|
||||
TX_MODULES="bank consensus crisis did distribution dwn feegrant gov slashing staking svc"
|
||||
for module in $TX_MODULES; do
|
||||
echo " Processing: snrd tx $module"
|
||||
filename=$(sanitize_filename "tx_${module}")
|
||||
snrd tx "$module" --help >"$OUT_DIR/snrd_${filename}.md" 2>&1 || true
|
||||
done
|
||||
;;
|
||||
"keys")
|
||||
# Document keys sub-commands
|
||||
KEYS_COMMANDS="add delete export import list migrate parse show"
|
||||
for subcmd in $KEYS_COMMANDS; do
|
||||
echo " Processing: snrd keys $subcmd"
|
||||
filename=$(sanitize_filename "keys_${subcmd}")
|
||||
snrd keys "$subcmd" --help >"$OUT_DIR/snrd_${filename}.md" 2>&1 || true
|
||||
done
|
||||
;;
|
||||
"auth")
|
||||
# Document auth sub-commands
|
||||
AUTH_COMMANDS="register verify sign"
|
||||
for subcmd in $AUTH_COMMANDS; do
|
||||
echo " Processing: snrd auth $subcmd"
|
||||
filename=$(sanitize_filename "auth_${subcmd}")
|
||||
snrd auth "$subcmd" --help >"$OUT_DIR/snrd_${filename}.md" 2>&1 || true
|
||||
done
|
||||
;;
|
||||
"genesis")
|
||||
# Document genesis sub-commands
|
||||
GENESIS_COMMANDS="add-genesis-account collect-txs export gentx init migrate validate"
|
||||
for subcmd in $GENESIS_COMMANDS; do
|
||||
echo " Processing: snrd genesis $subcmd"
|
||||
filename=$(sanitize_filename "genesis_${subcmd}")
|
||||
snrd genesis "$subcmd" --help >"$OUT_DIR/snrd_${filename}.md" 2>&1 || true
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Generate index file with all commands
|
||||
echo "Generating index file..."
|
||||
cat >"$OUT_DIR/index.md" <<EOF
|
||||
# Sonr CLI Documentation
|
||||
|
||||
This documentation is auto-generated from the \`snrd\` binary.
|
||||
|
||||
## Main Commands
|
||||
|
||||
EOF
|
||||
|
||||
# Add links to all generated files
|
||||
for file in "$OUT_DIR"/snrd*.md; do
|
||||
if [ -f "$file" ]; then
|
||||
basename=$(basename "$file" .md)
|
||||
# Convert filename back to readable format
|
||||
readable_name=$(echo "$basename" | sed 's/snrd_//' | tr '_' ' ' | sed 's/-/ /g')
|
||||
echo "- [$readable_name](./$basename.md)" >>"$OUT_DIR/index.md"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Documentation generation complete!"
|
||||
echo "Files generated in: $OUT_DIR"
|
||||
echo "Total files: $(ls -1 "$OUT_DIR"/*.md 2>/dev/null | wc -l)"
|
||||
@@ -0,0 +1,58 @@
|
||||
const converter = require('swagger2openapi');
|
||||
const glob = require('glob');
|
||||
const fs = require('fs').promises;
|
||||
const yaml = require('yaml');
|
||||
|
||||
/**
|
||||
* Script to find and convert Swagger 2.0 YAML files to OpenAPI 3.0 in-place.
|
||||
*/
|
||||
async function convertAll() {
|
||||
// Define options for the swagger2openapi converter.
|
||||
// Set 'patch' to true to perform some cleanup and fixing operations.
|
||||
const options = { patch: true, warnOnly: true };
|
||||
|
||||
try {
|
||||
// 1. Find all files ending with .swagger.yaml in the target directory.
|
||||
const swaggerFiles = glob.sync('docs/static/openapi/*.swagger.yaml');
|
||||
|
||||
if (swaggerFiles.length === 0) {
|
||||
console.log(
|
||||
"Conversion script finished: No *.swagger.yaml files were found in 'docs/static/openapi/'."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Found ${swaggerFiles.length} Swagger file(s) to convert.`);
|
||||
|
||||
// 2. Create a list of conversion promises.
|
||||
const conversionPromises = swaggerFiles.map(async (filePath) => {
|
||||
try {
|
||||
console.log(`- Converting ${filePath}...`);
|
||||
|
||||
// 3. Convert the file. The result object contains the OpenAPI definition.
|
||||
const { openapi } = await converter.convertFile(filePath, options);
|
||||
|
||||
// 4. Serialize the resulting OpenAPI object back to a YAML string.
|
||||
const openapiYamlString = yaml.stringify(openapi);
|
||||
|
||||
// 5. Overwrite the original file with the new OpenAPI 3.0 content.
|
||||
await fs.writeFile(filePath, openapiYamlString, 'utf8');
|
||||
|
||||
console.log(` √ Successfully converted and overwritten ${filePath}`);
|
||||
} catch (err) {
|
||||
console.error(` × Failed to convert ${filePath}:`, err.message);
|
||||
}
|
||||
});
|
||||
|
||||
// 6. Wait for all file conversions to complete.
|
||||
await Promise.all(conversionPromises);
|
||||
|
||||
console.log('\nConversion process complete.');
|
||||
} catch (error) {
|
||||
console.error('\nAn unexpected error occurred:', error);
|
||||
process.exit(1); // Exit with an error code
|
||||
}
|
||||
}
|
||||
|
||||
// Run the conversion process.
|
||||
convertAll();
|
||||
Executable
+146
@@ -0,0 +1,146 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eux
|
||||
|
||||
# generate_vrf_key generates a VRF keypair and stores it securely
|
||||
generate_vrf_key() {
|
||||
local home_dir="$1"
|
||||
|
||||
if [[ -z "${home_dir}" ]]; then
|
||||
echo "Error: HOME_DIR parameter is required" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
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}"
|
||||
|
||||
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 "")
|
||||
|
||||
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
|
||||
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
|
||||
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"
|
||||
|
||||
echo "Output of gentx"
|
||||
cat "$CHAIN_DIR"/config/gentx/*.json | jq
|
||||
|
||||
echo "Running collect-gentxs"
|
||||
$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"
|
||||
fi
|
||||
Executable
+177
@@ -0,0 +1,177 @@
|
||||
#!/bin/bash
|
||||
# Cross-platform localnet script that works on all systems including Arch Linux
|
||||
# This script handles Docker permission issues and provides fallback to local binary
|
||||
|
||||
set -eu
|
||||
|
||||
# Color codes for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_color() {
|
||||
color=$1
|
||||
shift
|
||||
echo -e "${color}$@${NC}"
|
||||
}
|
||||
|
||||
# Detect OS
|
||||
detect_os() {
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
if [ -f /etc/arch-release ]; then
|
||||
echo "arch"
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
echo "debian"
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
echo "redhat"
|
||||
else
|
||||
echo "linux"
|
||||
fi
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
echo "macos"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if user is in docker group
|
||||
check_docker_access() {
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
# Try to run a simple docker command
|
||||
if docker info >/dev/null 2>&1; then
|
||||
return 0
|
||||
else
|
||||
# Check if it's a permission issue
|
||||
if groups | grep -q docker; then
|
||||
print_color "$YELLOW" "You're in the docker group but Docker daemon might not be running"
|
||||
return 1
|
||||
else
|
||||
print_color "$YELLOW" "You need to be in the docker group to use Docker without sudo"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if binary exists and is accessible
|
||||
check_binary() {
|
||||
local binary_name="${1:-snrd}"
|
||||
|
||||
# Check in build directory first
|
||||
if [ -x "./build/${binary_name}" ]; then
|
||||
echo "./build/${binary_name}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check in PATH
|
||||
if command -v "${binary_name}" >/dev/null 2>&1; then
|
||||
echo "$(which "${binary_name}")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Setup proper permissions for directories
|
||||
setup_permissions() {
|
||||
local home_dir="${1}"
|
||||
|
||||
# Ensure directory exists
|
||||
mkdir -p "${home_dir}"
|
||||
|
||||
# Set proper ownership if running as non-root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
# Make sure current user owns the directory
|
||||
if [ -w "${home_dir}" ]; then
|
||||
return 0
|
||||
else
|
||||
print_color "$YELLOW" "Setting up permissions for ${home_dir}..."
|
||||
# Try to take ownership (will fail if not owner)
|
||||
if ! chmod -R u+rwX "${home_dir}" 2>/dev/null; then
|
||||
print_color "$RED" "Cannot set permissions on ${home_dir}. You may need to remove it manually: sudo rm -rf ${home_dir}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
print_color "$BLUE" "=== Sonr Cross-Platform Localnet Setup ==="
|
||||
|
||||
# Detect OS
|
||||
OS=$(detect_os)
|
||||
print_color "$GREEN" "Detected OS: ${OS}"
|
||||
|
||||
# Set default values
|
||||
export CHAIN_ID=${CHAIN_ID:-"sonrtest_1-1"}
|
||||
export HOME_DIR=$(eval echo "${HOME_DIR:-"~/.sonr"}")
|
||||
export BINARY=${BINARY:-"snrd"}
|
||||
export BLOCK_TIME=${BLOCK_TIME:-"1000ms"}
|
||||
export CLEAN=${CLEAN:-"true"}
|
||||
|
||||
# Decision logic for execution method
|
||||
USE_METHOD=""
|
||||
BINARY_PATH=""
|
||||
|
||||
# 1. Check if FORCE_DOCKER is set
|
||||
if [[ "${FORCE_DOCKER:-false}" == "true" ]]; then
|
||||
if check_docker_access; then
|
||||
USE_METHOD="docker"
|
||||
print_color "$GREEN" "Using Docker (forced)"
|
||||
else
|
||||
print_color "$RED" "FORCE_DOCKER=true but Docker is not accessible"
|
||||
exit 1
|
||||
fi
|
||||
# 2. Check for local binary
|
||||
elif BINARY_PATH=$(check_binary "${BINARY}"); then
|
||||
USE_METHOD="local"
|
||||
print_color "$GREEN" "Using local binary: ${BINARY_PATH}"
|
||||
# 3. Try Docker as fallback
|
||||
elif check_docker_access; then
|
||||
USE_METHOD="docker"
|
||||
print_color "$YELLOW" "No local binary found, using Docker"
|
||||
else
|
||||
# No method available
|
||||
print_color "$RED" "Error: No execution method available!"
|
||||
print_color "$YELLOW" "Please either:"
|
||||
print_color "$YELLOW" " 1. Run 'make install' to build the binary"
|
||||
print_color "$YELLOW" " 2. Install Docker and ensure it's running"
|
||||
if [[ "${OS}" == "arch" ]]; then
|
||||
print_color "$YELLOW" " On Arch Linux: sudo pacman -S docker && sudo systemctl start docker"
|
||||
print_color "$YELLOW" " Add yourself to docker group: sudo usermod -aG docker $USER"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Setup permissions for home directory
|
||||
if ! setup_permissions "${HOME_DIR}"; then
|
||||
print_color "$RED" "Failed to setup permissions"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Export the method for test_node.sh to use
|
||||
if [[ "${USE_METHOD}" == "docker" ]]; then
|
||||
export FORCE_DOCKER=true
|
||||
else
|
||||
export FORCE_DOCKER=false
|
||||
# Add build directory to PATH if using local binary from build/
|
||||
if [[ "${BINARY_PATH}" == "./build/"* ]]; then
|
||||
export PATH="$(pwd)/build:${PATH}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run the actual test node script
|
||||
print_color "$BLUE" "Starting localnet with ${USE_METHOD} method..."
|
||||
bash scripts/test_node.sh
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
Executable
+331
@@ -0,0 +1,331 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
# clear
|
||||
|
||||
# Detect git state and determine appropriate comparison base
|
||||
git_comparison_base() {
|
||||
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Check for uncommitted changes (staged or unstaged)
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
# Development mode - compare against last commit
|
||||
echo "HEAD"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if we're on master/main branch
|
||||
if [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
||||
# On master - compare against last tag
|
||||
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
||||
if [[ -n "$last_tag" ]]; then
|
||||
echo "$last_tag"
|
||||
else
|
||||
# No tags exist, compare against first commit
|
||||
echo "$(git rev-list --max-parents=0 HEAD)"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
# On feature branch with clean state - compare against master
|
||||
echo "master"
|
||||
}
|
||||
|
||||
# Get current git context for display
|
||||
git_context() {
|
||||
local base=$(git_comparison_base)
|
||||
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
local has_changes=$(git status --porcelain | wc -l)
|
||||
|
||||
if [[ "$has_changes" -gt 0 ]]; then
|
||||
echo "Development mode: comparing against HEAD (last commit)"
|
||||
elif [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
||||
echo "Master branch: comparing against $base"
|
||||
else
|
||||
echo "Feature branch: comparing against master"
|
||||
fi
|
||||
}
|
||||
|
||||
changed_files() {
|
||||
local base=$(git_comparison_base)
|
||||
|
||||
if [[ "$base" == "HEAD" ]]; then
|
||||
# In development mode - show uncommitted changes
|
||||
git diff --name-only HEAD
|
||||
git diff --cached --name-only
|
||||
git ls-files --others --exclude-standard
|
||||
else
|
||||
# Compare against determined base
|
||||
git diff --name-only "$base" "$(git rev-parse HEAD)"
|
||||
fi | sort -u
|
||||
}
|
||||
|
||||
changed_scopes() {
|
||||
local changed_files=$(changed_files)
|
||||
local context=$(git_context)
|
||||
|
||||
echo "🔍 Changed Files by Scope"
|
||||
echo "========================="
|
||||
echo "📍 $context"
|
||||
echo ""
|
||||
|
||||
# Process each scope
|
||||
yq eval '.[] | @json' .github/scopes.yml | while IFS= read -r scope_obj; do
|
||||
local scope_name=$(echo "$scope_obj" | jq -r '.name')
|
||||
local patterns=$(echo "$scope_obj" | jq -r '.include[]' | sed 's|^\./||; s|/\*\*$||')
|
||||
local matched_files=""
|
||||
|
||||
# Find matching files for all patterns of this scope
|
||||
for pattern in $patterns; do
|
||||
while IFS= read -r file; do
|
||||
[[ -n "$file" ]] && [[ "$file" == "$pattern"* ]] && matched_files+="$file\n"
|
||||
done <<<"$changed_files"
|
||||
done
|
||||
|
||||
# Display if there are matches
|
||||
if [[ -n "$matched_files" ]]; then
|
||||
local unique_count=$(echo -e "$matched_files" | sort -u | grep -c '^' || echo 0)
|
||||
echo ""
|
||||
echo "📦 $scope_name [$unique_count files]"
|
||||
|
||||
# Group files by directory
|
||||
echo -e "$matched_files" | sort -u | while IFS= read -r file; do
|
||||
[[ -n "$file" ]] || continue
|
||||
|
||||
# Indent based on directory depth
|
||||
local depth=$(echo "$file" | tr -cd '/' | wc -c)
|
||||
local indent=""
|
||||
for ((i = 0; i < depth; i++)); do
|
||||
indent=" $indent"
|
||||
done
|
||||
|
||||
# Show just the filename with smart tree characters
|
||||
local basename=$(basename "$file")
|
||||
local dirname=$(dirname "$file")
|
||||
|
||||
if [[ "$dirname" != "." ]]; then
|
||||
echo " 📁 $dirname/"
|
||||
echo " └── $basename"
|
||||
else
|
||||
echo " └── $file"
|
||||
fi
|
||||
done | sort -u # Remove duplicate directory listings
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
success() {
|
||||
gum log --structured "$1" --prefix "✅" --prefix.foreground "#00ff00"
|
||||
}
|
||||
|
||||
error() {
|
||||
gum log --structured "$1" --prefix "❌" --prefix.foreground "#ff0000"
|
||||
}
|
||||
|
||||
info() {
|
||||
gum log --structured --prefix "📍" --prefix.foreground "#00ffff" "$1"
|
||||
}
|
||||
|
||||
header() {
|
||||
local title="$1"
|
||||
gum style --border-foreground 240 --border double --align center --padding "0 1" "$title"
|
||||
echo "" | gum format
|
||||
}
|
||||
|
||||
separator() {
|
||||
echo "---" | gum format
|
||||
}
|
||||
|
||||
list_item() {
|
||||
local item="$1"
|
||||
echo "- $item" | gum format
|
||||
}
|
||||
|
||||
devbox_run() {
|
||||
local command="$1"
|
||||
local action=$(echo "$command" | cut -f1 -d: | tr '[:upper:]' '[:lower:]')
|
||||
local scope=$(echo "$command" | cut -f2 -d: | tr '[:upper:]' '[:lower:]')
|
||||
local title="Executing devbox run $action:$scope..."
|
||||
gum spin --show-error --spinner meter --title "$title" -- devbox run "$command"
|
||||
success "$scope finished $action"
|
||||
}
|
||||
|
||||
install() {
|
||||
header "Install"
|
||||
gum spin --show-error --spinner pulse --title "Installing pnpm..." -- pnpm install --frozen-lockfile
|
||||
gum spin --show-error --spinner pulse --title "Installing Go..." -- go mod download
|
||||
info "pnpm(10.14.0)"
|
||||
info "go(1.24.7)"
|
||||
separator
|
||||
}
|
||||
|
||||
build_all() {
|
||||
header "Build"
|
||||
devbox_run "build:auth"
|
||||
devbox_run "build:dash"
|
||||
devbox_run "build:core"
|
||||
devbox_run "build:com"
|
||||
devbox_run "build:es"
|
||||
devbox_run "build:hway"
|
||||
devbox_run "build:motr"
|
||||
devbox_run "build:pkl"
|
||||
devbox_run "build:sdk"
|
||||
devbox_run "build:ui"
|
||||
devbox_run "build:vault"
|
||||
separator
|
||||
}
|
||||
|
||||
test_all() {
|
||||
header "Test"
|
||||
devbox_run "test:auth"
|
||||
devbox_run "test:dash"
|
||||
devbox_run "test:core"
|
||||
devbox_run "test:com"
|
||||
devbox_run "test:es"
|
||||
devbox_run "test:hway"
|
||||
devbox_run "test:motr"
|
||||
devbox_run "test:pkl"
|
||||
devbox_run "test:sdk"
|
||||
devbox_run "test:ui"
|
||||
devbox_run "test:vault"
|
||||
separator
|
||||
}
|
||||
|
||||
release_all() {
|
||||
header "Release"
|
||||
# devbox_run "release:auth"
|
||||
# devbox_run "release:dash"
|
||||
devbox_run "release:core"
|
||||
devbox_run "release:com"
|
||||
devbox_run "release:es"
|
||||
devbox_run "release:hway"
|
||||
devbox_run "release:motr"
|
||||
devbox_run "release:pkl"
|
||||
devbox_run "release:sdk"
|
||||
devbox_run "release:ui"
|
||||
devbox_run "release:vault"
|
||||
separator
|
||||
}
|
||||
|
||||
snapshot_all() {
|
||||
header "Snapshot"
|
||||
devbox_run "snapshot:core"
|
||||
devbox_run "snapshot:hway"
|
||||
devbox_run "snapshot:motr"
|
||||
devbox_run "snapshot:vault"
|
||||
separator
|
||||
}
|
||||
|
||||
test_scopes() {
|
||||
for scope in $(affected_scopes); do
|
||||
# Check if the test script exists in devbox.json
|
||||
if grep -q "\"test:$scope\":" devbox.json 2>/dev/null; then
|
||||
echo "Testing scope: $scope"
|
||||
devbox run "test:$scope"
|
||||
else
|
||||
echo "Skipping test for scope: $scope (no test script defined)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
build_scopes() {
|
||||
for scope in $(affected_scopes); do
|
||||
# Check if the build script exists in devbox.json
|
||||
if grep -q "\"build:$scope\":" devbox.json 2>/dev/null; then
|
||||
echo "Building scope: $scope"
|
||||
devbox run "build:$scope"
|
||||
else
|
||||
echo "Skipping build for scope: $scope (no build script defined)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
release_scopes() {
|
||||
for scope in $(affected_scopes); do
|
||||
# Check if the release script exists in devbox.json
|
||||
if grep -q "\"release:$scope\":" devbox.json 2>/dev/null; then
|
||||
echo "Releasing scope: $scope"
|
||||
devbox run "release:$scope"
|
||||
else
|
||||
echo "Skipping release for scope: $scope (no release script defined)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
snapshot_scopes() {
|
||||
for scope in $(affected_scopes); do
|
||||
# Check if the snapshot script exists in devbox.json
|
||||
if grep -q "\"snapshot:$scope\":" devbox.json 2>/dev/null; then
|
||||
echo "Creating snapshot for scope: $scope"
|
||||
devbox run "snapshot:$scope"
|
||||
else
|
||||
echo "Skipping snapshot for scope: $scope (no snapshot script defined)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
affected_scopes() {
|
||||
local verbose="${1:-false}"
|
||||
local changed_files=$(changed_files)
|
||||
|
||||
if [[ "$verbose" == "true" ]] || [[ "$verbose" == "-v" ]]; then
|
||||
echo "📍 $(git_context)" >&2
|
||||
echo "" >&2
|
||||
fi
|
||||
|
||||
yq eval -o=json '.[]' .github/scopes.yml | jq -r --arg files "$changed_files" '
|
||||
select(.include[] as $pattern |
|
||||
$files | split("\n")[] |
|
||||
startswith($pattern | sub("^\\./"; "") | sub("/\\*\\*$"; ""))
|
||||
) |
|
||||
.name
|
||||
' | sort -u
|
||||
}
|
||||
|
||||
main() {
|
||||
cmd="$1"
|
||||
shift || true # Allow shifting even if no more args
|
||||
|
||||
case "$cmd" in
|
||||
"build-all")
|
||||
build_all
|
||||
;;
|
||||
"test-all")
|
||||
test_all
|
||||
;;
|
||||
"release-all")
|
||||
release_all
|
||||
;;
|
||||
"snapshot-all")
|
||||
snapshot_all
|
||||
;;
|
||||
"build-scopes")
|
||||
build_scopes
|
||||
;;
|
||||
"test-scopes")
|
||||
test_scopes
|
||||
;;
|
||||
"release-scopes")
|
||||
release_scopes
|
||||
;;
|
||||
"snapshot-scopes")
|
||||
snapshot_scopes
|
||||
;;
|
||||
"install-pnpm")
|
||||
install_pnpm
|
||||
;;
|
||||
"install-go")
|
||||
install_go
|
||||
;;
|
||||
"install")
|
||||
install
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $cmd"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+336
@@ -0,0 +1,336 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
# Detect git state and determine appropriate comparison base
|
||||
git_comparison_base() {
|
||||
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Check for uncommitted changes (staged or unstaged)
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
# Development mode - compare against last commit
|
||||
echo "HEAD"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if we're on master/main branch
|
||||
if [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
||||
# On master - compare against last tag
|
||||
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
||||
if [[ -n "$last_tag" ]]; then
|
||||
echo "$last_tag"
|
||||
else
|
||||
# No tags exist, compare against first commit
|
||||
echo "$(git rev-list --max-parents=0 HEAD)"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
# On feature branch with clean state - compare against master
|
||||
echo "master"
|
||||
}
|
||||
|
||||
# Get development mode status
|
||||
is_development_mode() {
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
echo "true"
|
||||
else
|
||||
echo "false"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get current git context for display
|
||||
git_context() {
|
||||
local base=$(git_comparison_base)
|
||||
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
local has_changes=$(git status --porcelain | wc -l)
|
||||
|
||||
if [[ "$has_changes" -gt 0 ]]; then
|
||||
echo "Development mode: comparing against HEAD (last commit)"
|
||||
elif [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
||||
echo "Master branch: comparing against $base"
|
||||
else
|
||||
echo "Feature branch: comparing against master"
|
||||
fi
|
||||
}
|
||||
|
||||
default_branch() {
|
||||
# This function is kept for backward compatibility
|
||||
echo "master"
|
||||
}
|
||||
|
||||
changed_files() {
|
||||
local base=$(git_comparison_base)
|
||||
|
||||
if [[ "$base" == "HEAD" ]]; then
|
||||
# In development mode - show uncommitted changes
|
||||
git diff --name-only HEAD
|
||||
git diff --cached --name-only
|
||||
git ls-files --others --exclude-standard
|
||||
else
|
||||
# Compare against determined base
|
||||
git diff --name-only "$base" "$(git rev-parse HEAD)"
|
||||
fi | sort -u
|
||||
}
|
||||
|
||||
changed_scopes() {
|
||||
local changed_files=$(changed_files)
|
||||
local context=$(git_context)
|
||||
|
||||
echo "🔍 Changed Files by Scope"
|
||||
echo "========================="
|
||||
echo "📍 $context"
|
||||
echo ""
|
||||
|
||||
# Process each scope
|
||||
yq eval '.[] | @json' .github/scopes.yml | while IFS= read -r scope_obj; do
|
||||
local scope_name=$(echo "$scope_obj" | jq -r '.name')
|
||||
local patterns=$(echo "$scope_obj" | jq -r '.include[]' | sed 's|^\./||; s|/\*\*$||')
|
||||
local matched_files=""
|
||||
|
||||
# Find matching files for all patterns of this scope
|
||||
for pattern in $patterns; do
|
||||
while IFS= read -r file; do
|
||||
[[ -n "$file" ]] && [[ "$file" == "$pattern"* ]] && matched_files+="$file\n"
|
||||
done <<<"$changed_files"
|
||||
done
|
||||
|
||||
# Display if there are matches
|
||||
if [[ -n "$matched_files" ]]; then
|
||||
local unique_count=$(echo -e "$matched_files" | sort -u | grep -c '^' || echo 0)
|
||||
echo ""
|
||||
echo "📦 $scope_name [$unique_count files]"
|
||||
|
||||
# Group files by directory
|
||||
echo -e "$matched_files" | sort -u | while IFS= read -r file; do
|
||||
[[ -n "$file" ]] || continue
|
||||
|
||||
# Indent based on directory depth
|
||||
local depth=$(echo "$file" | tr -cd '/' | wc -c)
|
||||
local indent=""
|
||||
for ((i = 0; i < depth; i++)); do
|
||||
indent=" $indent"
|
||||
done
|
||||
|
||||
# Show just the filename with smart tree characters
|
||||
local basename=$(basename "$file")
|
||||
local dirname=$(dirname "$file")
|
||||
|
||||
if [[ "$dirname" != "." ]]; then
|
||||
echo " 📁 $dirname/"
|
||||
echo " └── $basename"
|
||||
else
|
||||
echo " └── $file"
|
||||
fi
|
||||
done | sort -u # Remove duplicate directory listings
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
changed_scopes_diff() {
|
||||
local changed_files=$(changed_files)
|
||||
local base_branch=$(default_branch)
|
||||
local max_lines="${1:-10}" # Max diff lines to show per file
|
||||
|
||||
echo "🔍 Changed Files with Diffs"
|
||||
echo "==========================="
|
||||
|
||||
# Process each scope
|
||||
yq eval '.[] | @json' .github/scopes.yml | while IFS= read -r scope_obj; do
|
||||
local scope_name=$(echo "$scope_obj" | jq -r '.name')
|
||||
local patterns=$(echo "$scope_obj" | jq -r '.include[]' | sed 's|^\./||; s|/\*\*$||')
|
||||
local matched_files=""
|
||||
|
||||
# Find matching files
|
||||
for pattern in $patterns; do
|
||||
while IFS= read -r file; do
|
||||
[[ -n "$file" ]] && [[ "$file" == "$pattern"* ]] && matched_files+="$file\n"
|
||||
done <<<"$changed_files"
|
||||
done
|
||||
|
||||
if [[ -n "$matched_files" ]]; then
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📦 $scope_name"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
echo -e "$matched_files" | sort -u | while IFS= read -r file; do
|
||||
[[ -n "$file" ]] || continue
|
||||
|
||||
echo ""
|
||||
echo "┌─ 📄 $file"
|
||||
echo "├─────────────────────────────────"
|
||||
|
||||
# Show the diff with context
|
||||
git diff --unified=2 "$base_branch...HEAD" -- "$file" |
|
||||
tail -n +5 |
|
||||
head -n "$max_lines" |
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
@@*)
|
||||
echo "│ $(tput setaf 6)$line$(tput sgr0)"
|
||||
;;
|
||||
+*)
|
||||
echo "│ $(tput setaf 2)$line$(tput sgr0)"
|
||||
;;
|
||||
-*)
|
||||
echo "│ $(tput setaf 1)$line$(tput sgr0)"
|
||||
;;
|
||||
*)
|
||||
echo "│ $line"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if diff was truncated
|
||||
local full_diff_lines=$(git diff "$base_branch...HEAD" -- "$file" | wc -l)
|
||||
if [[ $full_diff_lines -gt $max_lines ]]; then
|
||||
echo "│ ... ($(($full_diff_lines - $max_lines)) more lines)"
|
||||
fi
|
||||
|
||||
echo "└─────────────────────────────────"
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
affected_scopes() {
|
||||
local verbose="${1:-false}"
|
||||
local changed_files=$(changed_files)
|
||||
|
||||
if [[ "$verbose" == "true" ]] || [[ "$verbose" == "-v" ]]; then
|
||||
echo "📍 $(git_context)" >&2
|
||||
echo "" >&2
|
||||
fi
|
||||
|
||||
yq eval -o=json '.[]' .github/scopes.yml | jq -r --arg files "$changed_files" '
|
||||
select(.include[] as $pattern |
|
||||
$files | split("\n")[] |
|
||||
startswith($pattern | sub("^\\./"; "") | sub("/\\*\\*$"; ""))
|
||||
) |
|
||||
.name
|
||||
' | sort -u
|
||||
}
|
||||
|
||||
current_issue() {
|
||||
local branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
local feature_part=$(echo "$branch" | cut -f2 -d'/')
|
||||
local result=$(gh issue ls | rg -i "$feature_part" | cut -f1 | head -n1)
|
||||
if [[ -z "$result" ]]; then
|
||||
local middle_part=$(echo "$feature_part" | cut -f2 -d'-')
|
||||
if [[ -n "$middle_part" ]]; then
|
||||
result=$(gh issue ls | rg -i "$middle_part" | cut -f1 | head -n1)
|
||||
fi
|
||||
fi
|
||||
echo "$result"
|
||||
}
|
||||
|
||||
current_branch() {
|
||||
git rev-parse --abbrev-ref HEAD
|
||||
}
|
||||
|
||||
current_pr() {
|
||||
gh pr ls --json headRefName,number --jq '.[] | {number: .number, branch: .headRefName}' | rg "$(git rev-parse --abbrev-ref HEAD)" | jq '.number'
|
||||
}
|
||||
|
||||
current_milestone() {
|
||||
gh issue view "$(current_issue)" --json milestone --jq '.milestone'
|
||||
}
|
||||
|
||||
final_issue() {
|
||||
local issue_num=$(current_issue)
|
||||
|
||||
if [[ -z "$issue_num" ]]; then
|
||||
echo "false"
|
||||
return
|
||||
fi
|
||||
|
||||
# Get milestone details
|
||||
local milestone_data=$(gh issue view "$issue_num" --json milestone)
|
||||
local milestone_title=$(echo "$milestone_data" | jq -r '.milestone.title // empty')
|
||||
local milestone_number=$(echo "$milestone_data" | jq -r '.milestone.number // empty')
|
||||
|
||||
if [[ -z "$milestone_title" ]]; then
|
||||
echo "false"
|
||||
return
|
||||
fi
|
||||
|
||||
# Get all open issues in the milestone
|
||||
local open_issues=$(gh issue list --milestone "$milestone_title" --state open --json number,title)
|
||||
local open_count=$(echo "$open_issues" | jq 'length')
|
||||
|
||||
# Debug output (optional - remove if not needed)
|
||||
if [[ "${DEBUG:-}" == "true" ]]; then
|
||||
echo "Current issue: #$issue_num" >&2
|
||||
echo "Milestone: $milestone_title" >&2
|
||||
echo "Open issues in milestone: $open_count" >&2
|
||||
echo "$open_issues" | jq -r '.[] | "#\(.number): \(.title)"' >&2
|
||||
fi
|
||||
|
||||
# Return true only if exactly 1 issue remains
|
||||
[[ "$open_count" -eq 1 ]] && echo "true" || echo "false"
|
||||
}
|
||||
|
||||
# Validate that we're on the default branch (master/main)
|
||||
# Returns exit 1 if not on default branch - useful for pre-bump hooks
|
||||
validate_default_branch() {
|
||||
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
if [[ "$current_branch" == "master" ]] || [[ "$current_branch" == "main" ]]; then
|
||||
echo "✅ On default branch: $current_branch"
|
||||
return 0
|
||||
else
|
||||
echo "❌ Error: Not on default branch (master/main)"
|
||||
echo " Current branch: $current_branch"
|
||||
echo " Please switch to master/main before bumping versions"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
cmd="$1"
|
||||
shift || true # Allow shifting even if no more args
|
||||
|
||||
case "$cmd" in
|
||||
"git-context")
|
||||
echo "$(git_context)"
|
||||
;;
|
||||
"validate-default-branch")
|
||||
validate_default_branch
|
||||
exit $?
|
||||
;;
|
||||
"affected-scopes")
|
||||
echo "$(affected_scopes "$@")"
|
||||
;;
|
||||
"changed-files")
|
||||
echo "$(changed_files)"
|
||||
;;
|
||||
"changed-scopes")
|
||||
echo "$(changed_scopes)"
|
||||
;;
|
||||
"changed-scopes-diff")
|
||||
echo "$(changed_scopes_diff)"
|
||||
;;
|
||||
"current-branch")
|
||||
echo "$(current_branch)"
|
||||
;;
|
||||
"current-issue")
|
||||
echo "$(current_issue)"
|
||||
;;
|
||||
"current-milestone")
|
||||
echo "$(current_milestone)"
|
||||
;;
|
||||
"current-pr")
|
||||
echo "$(current_pr)"
|
||||
;;
|
||||
"final-issue")
|
||||
echo "$(final_issue)"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $cmd"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Get script directory and project root
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||||
|
||||
# Variables passed from commitizen
|
||||
IS_INITIAL=$CZ_POST_IS_INITIAL
|
||||
CURRENT_TAG=$CZ_POST_CURRENT_TAG_VERSION
|
||||
|
||||
# Check if we're not on release branch
|
||||
if [[ "$BRANCH" != "master" ]] && [[ "$BRANCH" != "main" ]]; then
|
||||
echo "❌ Error: Cannot bump versions on feature branch"
|
||||
echo " Please switch to master/main branch and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Cleanup function to discard CHANGELOG.md changes on failure
|
||||
cleanup_on_error() {
|
||||
local exit_code=$?
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
echo "❌ Error occurred during version bump (exit code: $exit_code)"
|
||||
|
||||
# Find all CHANGELOG.md files with changes
|
||||
local changed_changelogs=$(git diff --name-only | grep "CHANGELOG.md" || true)
|
||||
local staged_changelogs=$(git diff --cached --name-only | grep "CHANGELOG.md" || true)
|
||||
|
||||
# Discard unstaged changes
|
||||
if [[ -n "$changed_changelogs" ]]; then
|
||||
echo "🧹 Discarding local changes to CHANGELOG.md files..."
|
||||
while IFS= read -r file; do
|
||||
if [[ -n "$file" ]]; then
|
||||
echo " Reverting: $file"
|
||||
git checkout -- "$file" 2>/dev/null || true
|
||||
fi
|
||||
done <<< "$changed_changelogs"
|
||||
echo "✅ Unstaged CHANGELOG.md changes discarded"
|
||||
fi
|
||||
|
||||
# Discard staged changes
|
||||
if [[ -n "$staged_changelogs" ]]; then
|
||||
echo "🧹 Unstaging and discarding staged CHANGELOG.md files..."
|
||||
while IFS= read -r file; do
|
||||
if [[ -n "$file" ]]; then
|
||||
echo " Reverting: $file"
|
||||
git reset HEAD "$file" 2>/dev/null || true
|
||||
git checkout -- "$file" 2>/dev/null || true
|
||||
fi
|
||||
done <<< "$staged_changelogs"
|
||||
echo "✅ Staged CHANGELOG.md changes discarded"
|
||||
fi
|
||||
|
||||
if [[ -z "$changed_changelogs" ]] && [[ -z "$staged_changelogs" ]]; then
|
||||
echo "ℹ️ No CHANGELOG.md changes to discard"
|
||||
fi
|
||||
fi
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
# Set trap to cleanup on any error
|
||||
trap cleanup_on_error EXIT
|
||||
|
||||
# Get script directory and project root
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||||
NEW_TAG=$CZ_PRE_NEW_TAG_VERSION
|
||||
IS_NEW=$CZ_PRE_IS_INITIAL
|
||||
CHANGELOG=$CZ_PRE_CHANGELOG_FILE_NAME
|
||||
ORIGIN_TAGS=$(git tag -l)
|
||||
|
||||
# Check if we're not on release branch
|
||||
if [[ "$BRANCH" != "master" ]] && [[ "$BRANCH" != "main" ]]; then
|
||||
echo "❌ Error: Cannot bump versions on feature branch"
|
||||
echo " Please switch to master/main branch and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify next tag is not already present
|
||||
if echo "$ORIGIN_TAGS" | grep -q "$NEW_TAG"; then
|
||||
echo "❌ Error: Tag $NEW_TAG already exists"
|
||||
echo " Please choose a different tag name."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create CHANGELOG.md if it doesn't exist
|
||||
if [ ! -f "$CHANGELOG" ]; then
|
||||
echo "⚠️ Warning: CHANGELOG.md not found, creating new file."
|
||||
touch "$CHANGELOG"
|
||||
fi
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Get script directory and project root
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||||
|
||||
# Variables passed from commitizen
|
||||
IS_INITIAL=$CZ_POST_IS_INITIAL
|
||||
CURRENT_TAG=$CZ_POST_CURRENT_TAG_VERSION
|
||||
|
||||
# Check if we're not on release branch
|
||||
if [[ "$BRANCH" != "master" ]] && [[ "$BRANCH" != "main" ]]; then
|
||||
echo "❌ Error: Cannot bump versions on feature branch"
|
||||
echo " Please switch to master/main branch and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Get script directory and project root
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||||
|
||||
# Variables passed from commitizen
|
||||
IS_INITIAL=$CZ_POST_IS_INITIAL
|
||||
CURRENT_TAG=$CZ_POST_CURRENT_TAG_VERSION
|
||||
|
||||
# Check if we're not on release branch
|
||||
if [[ "$BRANCH" != "master" ]] && [[ "$BRANCH" != "main" ]]; then
|
||||
echo "❌ Error: Cannot bump versions on feature branch"
|
||||
echo " Please switch to master/main branch and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+254
-72
@@ -7,85 +7,267 @@ detect_platform() {
|
||||
OS=$(uname -s)
|
||||
ARCH=$(uname -m)
|
||||
|
||||
# Normalize OS names to match GitHub release naming
|
||||
case "${OS}" in
|
||||
Darwin) OS_NAME="darwin" ;;
|
||||
Linux) OS_NAME="linux" ;;
|
||||
MINGW* | MSYS* | CYGWIN*) OS_NAME="windows" ;;
|
||||
*)
|
||||
echo "Unsupported OS: ${OS}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Normalize architecture names
|
||||
case "${ARCH}" in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
aarch64 | arm64) ARCH="arm64" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to get latest release version
|
||||
get_latest_version() {
|
||||
LATEST_VERSION=$(curl -s https://api.github.com/repos/sonr-io/snrd/releases/latest | grep "tag_name" | cut -d '"' -f 4)
|
||||
LATEST_VERSION=${LATEST_VERSION#v} # Remove 'v' prefix
|
||||
}
|
||||
|
||||
# Function to install binaries to current directory
|
||||
install_tar() {
|
||||
local OS_NAME=$1
|
||||
echo "Installing Sonr for ${OS_NAME} (${ARCH})..."
|
||||
DOWNLOAD_URL="https://github.com/sonr-io/snrd/releases/download/v${LATEST_VERSION}/sonr_${LATEST_VERSION}_${OS_NAME}_${ARCH}.tar.gz"
|
||||
|
||||
# Download and extract
|
||||
echo "Downloading Sonr..."
|
||||
curl -L "${DOWNLOAD_URL}" -o sonr.tar.gz
|
||||
tar -xzf sonr.tar.gz
|
||||
rm sonr.tar.gz
|
||||
|
||||
chmod +x sonrd hway
|
||||
|
||||
echo "Binaries 'sonrd' and 'hway' have been extracted to the current directory"
|
||||
echo
|
||||
echo "To make them available system-wide, you can move them to /usr/local/bin with:"
|
||||
echo "sudo mv sonrd hway /usr/local/bin/"
|
||||
echo
|
||||
echo "Or move them to your personal bin directory with:"
|
||||
echo "mkdir -p ~/.local/bin"
|
||||
echo "mv sonrd hway ~/.local/bin/"
|
||||
echo "Then add ~/.local/bin to your PATH if it's not already there"
|
||||
}
|
||||
|
||||
# Function to install on Debian/Ubuntu
|
||||
install_debian() {
|
||||
echo "Installing Sonr for Debian/Ubuntu (${ARCH})..."
|
||||
SONRD_URL="https://github.com/sonr-io/snrd/releases/download/v${LATEST_VERSION}/sonrd_${LATEST_VERSION}_${ARCH}.deb"
|
||||
HWAY_URL="https://github.com/sonr-io/snrd/releases/download/v${LATEST_VERSION}/hway_${LATEST_VERSION}_${ARCH}.deb"
|
||||
|
||||
# Download packages
|
||||
TMP_DIR=$(mktemp -d)
|
||||
curl -L "${SONRD_URL}" -o "${TMP_DIR}/sonrd.deb"
|
||||
curl -L "${HWAY_URL}" -o "${TMP_DIR}/hway.deb"
|
||||
|
||||
# Install packages
|
||||
sudo dpkg -i "${TMP_DIR}/sonrd.deb"
|
||||
sudo dpkg -i "${TMP_DIR}/hway.deb"
|
||||
|
||||
# Cleanup
|
||||
rm -rf "${TMP_DIR}"
|
||||
|
||||
echo "Sonr has been installed system-wide"
|
||||
}
|
||||
|
||||
main() {
|
||||
detect_platform
|
||||
get_latest_version
|
||||
|
||||
case "${OS}" in
|
||||
Darwin)
|
||||
install_tar "Darwin"
|
||||
;;
|
||||
Linux)
|
||||
if [[ -f /etc/debian_version ]]; then
|
||||
install_debian
|
||||
else
|
||||
install_tar "Linux"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported operating system: ${OS}"
|
||||
echo "Unsupported architecture: ${ARCH}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main
|
||||
# Function to check if we can build locally
|
||||
can_build_locally() {
|
||||
# Check if we're in the sonr project directory
|
||||
if [[ -f "Makefile" ]] && [[ -f "go.mod" ]] && grep -q "module github.com/sonr-io/sonr" go.mod 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to build locally
|
||||
build_locally() {
|
||||
local INSTALL_DIR="$1"
|
||||
echo "Building Sonr locally..."
|
||||
|
||||
# Check if make and go are available
|
||||
if ! command -v make >/dev/null 2>&1; then
|
||||
echo "Error: make is required to build locally"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
echo "Error: Go is required to build locally"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build binaries
|
||||
echo "Building snrd..."
|
||||
make build || {
|
||||
echo "Error: Failed to build snrd"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Building motr..."
|
||||
make motr || {
|
||||
echo "Error: Failed to build motr"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Copy binaries to install directory
|
||||
cp build/snrd "${INSTALL_DIR}/" || {
|
||||
echo "Error: Failed to copy snrd"
|
||||
exit 1
|
||||
}
|
||||
cp build/motr.wasm "${INSTALL_DIR}/" || {
|
||||
echo "Error: Failed to copy motr.wasm"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Make binaries executable
|
||||
chmod +x "${INSTALL_DIR}/snrd"
|
||||
|
||||
echo "Binaries built and installed successfully to ${INSTALL_DIR}"
|
||||
}
|
||||
|
||||
# Function to get latest release version
|
||||
get_latest_version() {
|
||||
RELEASE_DATA=$(curl -s https://api.github.com/repos/sonr-io/sonr/releases/latest)
|
||||
|
||||
# Check if API returned an error (no releases available or private repo)
|
||||
if echo "${RELEASE_DATA}" | grep -q '"message": "Not Found"'; then
|
||||
if can_build_locally; then
|
||||
echo "No public releases found, building locally..."
|
||||
return 1
|
||||
else
|
||||
echo "Error: No releases found for sonr-io/sonr"
|
||||
echo "Please build and install from source:"
|
||||
echo " git clone https://github.com/sonr-io/sonr.git"
|
||||
echo " cd sonr"
|
||||
echo " ./scripts/install.sh"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
LATEST_VERSION=$(echo "${RELEASE_DATA}" | grep "tag_name" | cut -d '"' -f 4)
|
||||
if [[ -z "${LATEST_VERSION}" ]]; then
|
||||
echo "Error: Could not determine latest version"
|
||||
if can_build_locally; then
|
||||
echo "Falling back to local build..."
|
||||
return 1
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LATEST_VERSION=${LATEST_VERSION#v} # Remove 'v' prefix
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to install binaries
|
||||
install_binaries() {
|
||||
local INSTALL_DIR="${1:-$(pwd)}"
|
||||
|
||||
# Check if we have a version from releases
|
||||
if [[ -n "${LATEST_VERSION}" ]]; then
|
||||
echo "Installing Sonr v${LATEST_VERSION} for ${OS_NAME} (${ARCH}) to ${INSTALL_DIR}..."
|
||||
|
||||
# Use dl.sonr.io CDN for faster downloads
|
||||
BASE_URL="https://dl.sonr.io/v${LATEST_VERSION}"
|
||||
|
||||
# Download snrd binary
|
||||
echo "Downloading snrd..."
|
||||
if [[ ${OS_NAME} == "windows" ]]; then
|
||||
echo "Error: snrd does not support Windows"
|
||||
exit 1
|
||||
else
|
||||
if ! curl -L "${BASE_URL}/snrd_${OS_NAME}_${ARCH}" -o "${INSTALL_DIR}/snrd" -f; then
|
||||
echo "Warning: Failed to download from CDN, trying GitHub releases..."
|
||||
# Fallback to GitHub releases
|
||||
GITHUB_URL="https://github.com/sonr-io/sonr/releases/download/v${LATEST_VERSION}"
|
||||
if ! curl -L "${GITHUB_URL}/snrd_${OS_NAME}_${ARCH}" -o "${INSTALL_DIR}/snrd" -f; then
|
||||
echo "Error: Failed to download snrd binary from both CDN and GitHub"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Download motr.wasm (platform independent)
|
||||
echo "Downloading motr.wasm..."
|
||||
if ! curl -L "${BASE_URL}/motr.wasm" -o "${INSTALL_DIR}/motr.wasm" -f; then
|
||||
echo "Warning: Failed to download from CDN, trying GitHub releases..."
|
||||
# Fallback to GitHub releases
|
||||
GITHUB_URL="https://github.com/sonr-io/sonr/releases/download/v${LATEST_VERSION}"
|
||||
if ! curl -L "${GITHUB_URL}/motr.wasm" -o "${INSTALL_DIR}/motr.wasm" -f; then
|
||||
echo "Error: Failed to download motr.wasm from both CDN and GitHub"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make binaries executable
|
||||
chmod +x "${INSTALL_DIR}/snrd"
|
||||
|
||||
echo "Binaries installed successfully to ${INSTALL_DIR}"
|
||||
else
|
||||
# Fall back to local build
|
||||
build_locally "${INSTALL_DIR}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Available commands:"
|
||||
echo " snrd - Blockchain daemon"
|
||||
echo " motr.wasm - WebAssembly enclave"
|
||||
echo
|
||||
echo "Quick start:"
|
||||
echo " snrd --help # Show available commands"
|
||||
echo " snrd start # Start the blockchain node"
|
||||
}
|
||||
|
||||
# Function to install system-wide
|
||||
install_system() {
|
||||
if [[ ${EUID} -eq 0 ]]; then
|
||||
INSTALL_DIR="/usr/local/bin"
|
||||
else
|
||||
echo "Installing to /usr/local/bin requires sudo privileges..."
|
||||
sudo -v || {
|
||||
echo "Sudo access required for system-wide installation"
|
||||
exit 1
|
||||
}
|
||||
INSTALL_DIR="/usr/local/bin"
|
||||
|
||||
# Create temporary directory and install there first
|
||||
TMP_DIR=$(mktemp -d)
|
||||
install_binaries "${TMP_DIR}"
|
||||
|
||||
# Move to system directory with sudo
|
||||
sudo mv "${TMP_DIR}/"* "${INSTALL_DIR}/"
|
||||
rm -rf "${TMP_DIR}"
|
||||
|
||||
echo "Binaries installed system-wide to ${INSTALL_DIR}"
|
||||
return
|
||||
fi
|
||||
|
||||
install_binaries "${INSTALL_DIR}"
|
||||
}
|
||||
|
||||
# Function to install to user directory
|
||||
install_user() {
|
||||
USER_BIN_DIR="${HOME}/.local/bin"
|
||||
mkdir -p "${USER_BIN_DIR}"
|
||||
|
||||
install_binaries "${USER_BIN_DIR}"
|
||||
|
||||
# Check if user bin is in PATH
|
||||
if [[ ":${PATH}:" != *":${USER_BIN_DIR}:"* ]]; then
|
||||
echo
|
||||
echo "WARNING: ${USER_BIN_DIR} is not in your PATH"
|
||||
echo "Add the following line to your shell profile (~/.bashrc, ~/.zshrc, etc.):"
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"'
|
||||
echo
|
||||
echo "Then restart your terminal or run: source ~/.bashrc"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
detect_platform
|
||||
|
||||
# Try to get latest version from releases, but don't fail if not available
|
||||
if ! get_latest_version; then
|
||||
# get_latest_version returned 1, meaning no releases but we can build locally
|
||||
LATEST_VERSION=""
|
||||
fi
|
||||
|
||||
# Parse command line arguments
|
||||
case "${1-}" in
|
||||
--system | -s)
|
||||
install_system
|
||||
;;
|
||||
--user | -u)
|
||||
install_user
|
||||
;;
|
||||
--current | -c)
|
||||
install_binaries "$(pwd)"
|
||||
;;
|
||||
--help | -h)
|
||||
echo "Sonr Installation Script"
|
||||
echo
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --system, -s Install system-wide to /usr/local/bin (requires sudo)"
|
||||
echo " --user, -u Install to ~/.local/bin (user directory)"
|
||||
echo " --current, -c Install to current directory"
|
||||
echo " --help, -h Show this help message"
|
||||
echo
|
||||
echo "If no option is specified, defaults to --user installation"
|
||||
echo
|
||||
if can_build_locally; then
|
||||
echo "Note: No public releases found, will build from source"
|
||||
fi
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
# Default to user installation
|
||||
install_user
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Use --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
SOURCE=$1
|
||||
OUTPUT=$2
|
||||
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
cd $ROOT_DIR
|
||||
|
||||
mkdir -p $OUTPUT
|
||||
pkl eval package://pkg.pkl-lang.org/pkl-pantry/org.json_schema.contrib@1.0.0#/generate.pkl -m . -p source="$SOURCE" -p output="$OUTPUT"
|
||||
Regular → Executable
+21
-22
@@ -2,21 +2,20 @@
|
||||
|
||||
set -e
|
||||
|
||||
GO_MOD_PACKAGE="github.com/sonr-io/snrd"
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
GO_MOD_PACKAGE="github.com/sonr-io/sonr"
|
||||
|
||||
echo "Generating gogo proto code"
|
||||
cd proto
|
||||
proto_dirs=$(find . -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq)
|
||||
for dir in $proto_dirs; do
|
||||
for file in $(find "${dir}" -maxdepth 1 -name '*.proto'); do
|
||||
# this regex checks if a proto file has its go_package set to github.com/strangelove-ventures/poa/...
|
||||
# gogo proto files SHOULD ONLY be generated if this is false
|
||||
# we don't want gogo proto to run for proto files which are natively built for google.golang.org/protobuf
|
||||
if grep -q "option go_package" "$file" && grep -H -o -c "option go_package.*$GO_MOD_PACKAGE/api" "$file" | grep -q ':0$'; then
|
||||
buf generate --template buf.gen.gogo.yaml $file
|
||||
fi
|
||||
done
|
||||
for dir in ${proto_dirs}; do
|
||||
for file in $(find "${dir}" -maxdepth 1 -name '*.proto'); do
|
||||
# this regex checks if a proto file has its go_package set to github.com/strangelove-ventures/poa/...
|
||||
# gogo proto files SHOULD ONLY be generated if this is false
|
||||
# we don't want gogo proto to run for proto files which are natively built for google.golang.org/protobuf
|
||||
if grep -q "option go_package" "${file}" && grep -H -o -c "option go_package.*${GO_MOD_PACKAGE}/api" "${file}" | grep -q ':0$'; then
|
||||
buf generate --template buf.gen.gogo.yaml "${file}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "Generating pulsar proto code"
|
||||
@@ -24,28 +23,28 @@ buf generate --template buf.gen.pulsar.yaml
|
||||
|
||||
cd ..
|
||||
|
||||
cp -r $GO_MOD_PACKAGE/* ./
|
||||
cp -r "${GO_MOD_PACKAGE}"/* ./
|
||||
rm -rf github.com
|
||||
|
||||
# Copy files over for dep injection
|
||||
rm -rf api && mkdir api
|
||||
custom_modules=$(find . -name 'module' -type d -not -path "./proto/*" -not -path "./.cache/*")
|
||||
custom_modules=$(find . -name 'module' -type d -not -path "./proto/*" -not -path "./.cache/*" -not -path "./node_modules/*" -not -path "./packages/*")
|
||||
|
||||
# get the 1 up directory (so ./cosmos/mint/module becomes ./cosmos/mint)
|
||||
# remove the relative path starter from base namespaces. so ./cosmos/mint becomes cosmos/mint
|
||||
base_namespace=$(echo $custom_modules | sed -e 's|/module||g' | sed -e 's|\./||g')
|
||||
base_namespace=$(echo "${custom_modules}" | sed -e 's|/module||g' | sed -e 's|\./||g')
|
||||
|
||||
# echo "Base namespace: $base_namespace"
|
||||
for module in $base_namespace; do
|
||||
echo " [+] Moving: ./$module to ./api/$module"
|
||||
for module in ${base_namespace}; do
|
||||
echo " [+] Moving: ./${module} to ./api/${module}"
|
||||
|
||||
mkdir -p api/$module
|
||||
mkdir -p api/"${module}"
|
||||
|
||||
mv $module/* ./api/$module/
|
||||
mv "${module}"/* ./api/"${module}"/
|
||||
|
||||
# # incorrect reference to the module for coins
|
||||
find api/$module -type f -name '*.go' -exec sed -i -e 's|types "github.com/cosmos/cosmos-sdk/types"|types "cosmossdk.io/api/cosmos/base/v1beta1"|g' {} \;
|
||||
find api/$module -type f -name '*.go' -exec sed -i -e 's|types1 "github.com/cosmos/cosmos-sdk/x/bank/types"|types1 "cosmossdk.io/api/cosmos/bank/v1beta1"|g' {} \;
|
||||
# # incorrect reference to the module for coins
|
||||
find api/"${module}" -type f -name '*.go' -exec sed -i -e 's|types "github.com/cosmos/cosmos-sdk/types"|types "cosmossdk.io/api/cosmos/base/v1beta1"|g' {} \;
|
||||
find api/"${module}" -type f -name '*.go' -exec sed -i -e 's|types1 "github.com/cosmos/cosmos-sdk/x/bank/types"|types1 "cosmossdk.io/api/cosmos/bank/v1beta1"|g' {} \;
|
||||
|
||||
rm -rf $module
|
||||
rm -rf "${module}"
|
||||
done
|
||||
|
||||
Executable
+263
@@ -0,0 +1,263 @@
|
||||
#!/bin/bash
|
||||
# Setup script for running Sonr localnet on various systems
|
||||
# Supports: Arch Linux, Ubuntu/Debian, RedHat/Fedora, macOS
|
||||
|
||||
set -e
|
||||
|
||||
# Color codes
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
MAGENTA='\033[0;35m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_color() {
|
||||
color=$1
|
||||
shift
|
||||
echo -e "${color}$@${NC}"
|
||||
}
|
||||
|
||||
# Detect OS and distribution
|
||||
detect_os() {
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
if [ -f /etc/arch-release ]; then
|
||||
echo "arch"
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
echo "debian"
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
echo "redhat"
|
||||
elif [ -f /etc/alpine-release ]; then
|
||||
echo "alpine"
|
||||
else
|
||||
echo "linux"
|
||||
fi
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
echo "macos"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
# Install Docker on different systems
|
||||
install_docker() {
|
||||
local os=$1
|
||||
|
||||
print_color $BLUE "Installing Docker for ${os}..."
|
||||
|
||||
case $os in
|
||||
arch)
|
||||
print_color $YELLOW "Installing Docker on Arch Linux..."
|
||||
sudo pacman -Sy --noconfirm docker docker-compose
|
||||
sudo systemctl enable docker
|
||||
sudo systemctl start docker
|
||||
;;
|
||||
debian)
|
||||
print_color $YELLOW "Installing Docker on Debian/Ubuntu..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker.io docker-compose
|
||||
sudo systemctl enable docker
|
||||
sudo systemctl start docker
|
||||
;;
|
||||
redhat)
|
||||
print_color $YELLOW "Installing Docker on RedHat/Fedora..."
|
||||
sudo dnf install -y docker docker-compose
|
||||
sudo systemctl enable docker
|
||||
sudo systemctl start docker
|
||||
;;
|
||||
macos)
|
||||
print_color $YELLOW "Please install Docker Desktop from https://www.docker.com/products/docker-desktop"
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
print_color $RED "Unsupported OS for automatic Docker installation"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Add user to docker group
|
||||
sudo usermod -aG docker $USER
|
||||
print_color $GREEN "Docker installed. You may need to log out and back in for group changes to take effect."
|
||||
}
|
||||
|
||||
# Install Go if not present
|
||||
install_go() {
|
||||
if command -v go >/dev/null 2>&1; then
|
||||
print_color $GREEN "Go is already installed: $(go version)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_color $BLUE "Installing Go..."
|
||||
|
||||
local os=$(detect_os)
|
||||
local GO_VERSION="1.24.1"
|
||||
local ARCH=$(uname -m)
|
||||
|
||||
# Map architecture
|
||||
case $ARCH in
|
||||
x86_64)
|
||||
ARCH="amd64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
ARCH="arm64"
|
||||
;;
|
||||
*)
|
||||
print_color $RED "Unsupported architecture: $ARCH"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Determine OS for Go download
|
||||
local GO_OS=""
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
GO_OS="linux"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
GO_OS="darwin"
|
||||
else
|
||||
print_color $RED "Unsupported OS for Go installation"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Download and install Go
|
||||
local GO_TAR="go${GO_VERSION}.${GO_OS}-${ARCH}.tar.gz"
|
||||
wget "https://go.dev/dl/${GO_TAR}" -O /tmp/${GO_TAR}
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf /tmp/${GO_TAR}
|
||||
rm /tmp/${GO_TAR}
|
||||
|
||||
# Add to PATH
|
||||
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
|
||||
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.bashrc
|
||||
|
||||
# For zsh users
|
||||
if [ -f ~/.zshrc ]; then
|
||||
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrc
|
||||
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.zshrc
|
||||
fi
|
||||
|
||||
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
|
||||
|
||||
print_color $GREEN "Go ${GO_VERSION} installed successfully"
|
||||
}
|
||||
|
||||
# Install dependencies
|
||||
install_dependencies() {
|
||||
local os=$1
|
||||
|
||||
print_color $BLUE "Installing dependencies for ${os}..."
|
||||
|
||||
case $os in
|
||||
arch)
|
||||
sudo pacman -Sy --noconfirm base-devel git jq make gcc
|
||||
;;
|
||||
debian)
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential git jq make gcc
|
||||
;;
|
||||
redhat)
|
||||
sudo dnf groupinstall -y "Development Tools"
|
||||
sudo dnf install -y git jq make gcc
|
||||
;;
|
||||
macos)
|
||||
# Check for Homebrew
|
||||
if ! command -v brew >/dev/null 2>&1; then
|
||||
print_color $YELLOW "Installing Homebrew..."
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
fi
|
||||
brew install jq make gcc
|
||||
;;
|
||||
*)
|
||||
print_color $YELLOW "Please manually install: git, jq, make, gcc"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Setup function
|
||||
setup_environment() {
|
||||
local os=$(detect_os)
|
||||
|
||||
print_color $MAGENTA "=== Sonr Localnet Setup for ${os} ==="
|
||||
|
||||
# Install dependencies
|
||||
install_dependencies $os
|
||||
|
||||
# Install Go
|
||||
install_go
|
||||
|
||||
# Docker setup (optional)
|
||||
print_color $BLUE "Would you like to install/configure Docker? (y/n)"
|
||||
read -r response
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
print_color $GREEN "Docker is already installed"
|
||||
|
||||
# Check if user is in docker group
|
||||
if ! groups | grep -q docker; then
|
||||
print_color $YELLOW "Adding user to docker group..."
|
||||
sudo usermod -aG docker $USER
|
||||
print_color $YELLOW "You'll need to log out and back in for this to take effect"
|
||||
fi
|
||||
else
|
||||
install_docker $os
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build the binary
|
||||
print_color $BLUE "Building Sonr binary..."
|
||||
make install
|
||||
|
||||
# Create helpful aliases
|
||||
print_color $BLUE "Creating helpful aliases..."
|
||||
|
||||
cat >> ~/.bashrc << 'EOF'
|
||||
|
||||
# Sonr aliases
|
||||
alias sonr-localnet='cd $(pwd) && make localnet-x'
|
||||
alias sonr-status='curl -s http://localhost:26657/status | jq'
|
||||
alias sonr-logs='docker logs -f sonr-testnode 2>/dev/null || echo "No Docker container running"'
|
||||
alias sonr-stop='docker stop sonr-testnode 2>/dev/null || pkill -f snrd'
|
||||
EOF
|
||||
|
||||
if [ -f ~/.zshrc ]; then
|
||||
cat >> ~/.zshrc << 'EOF'
|
||||
|
||||
# Sonr aliases
|
||||
alias sonr-localnet='cd $(pwd) && make localnet-x'
|
||||
alias sonr-status='curl -s http://localhost:26657/status | jq'
|
||||
alias sonr-logs='docker logs -f sonr-testnode 2>/dev/null || echo "No Docker container running"'
|
||||
alias sonr-stop='docker stop sonr-testnode 2>/dev/null || pkill -f snrd'
|
||||
EOF
|
||||
fi
|
||||
|
||||
print_color $GREEN "=== Setup Complete ==="
|
||||
print_color $YELLOW "Next steps:"
|
||||
print_color $YELLOW "1. If Docker was installed, log out and back in for group changes"
|
||||
print_color $YELLOW "2. Run 'make localnet-x' to start the cross-platform localnet"
|
||||
print_color $YELLOW "3. Or use the aliases: sonr-localnet, sonr-status, sonr-logs, sonr-stop"
|
||||
|
||||
# OS-specific instructions
|
||||
case $os in
|
||||
arch)
|
||||
print_color $BLUE "\nArch Linux specific:"
|
||||
print_color $YELLOW "- If you prefer systemd service:"
|
||||
print_color $YELLOW " sudo cp etc/systemd/sonr.service /etc/systemd/system/sonr@${USER}.service"
|
||||
print_color $YELLOW " sudo systemctl daemon-reload"
|
||||
print_color $YELLOW " sudo systemctl enable sonr@${USER}"
|
||||
print_color $YELLOW " sudo systemctl start sonr@${USER}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "Makefile" ] || [ ! -d "cmd/snrd" ]; then
|
||||
print_color $RED "Error: This script must be run from the Sonr repository root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
setup_environment
|
||||
}
|
||||
|
||||
# Run main
|
||||
main "$@"
|
||||
Executable
+351
@@ -0,0 +1,351 @@
|
||||
#!/bin/bash
|
||||
# Starship E2E Testing Setup Script
|
||||
# This script manages the Starship deployment for E2E testing
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
STARSHIP_VERSION="${STARSHIP_VERSION:-v2.0.0}"
|
||||
STARSHIP_CONFIG="${STARSHIP_CONFIG:-chains/e2e-test.json}"
|
||||
NAMESPACE="${NAMESPACE:-starship}"
|
||||
TIMEOUT="${TIMEOUT:-300}"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Helper functions
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
# Check prerequisites
|
||||
check_prerequisites() {
|
||||
log_info "Checking prerequisites..."
|
||||
|
||||
# Check for kubectl
|
||||
if ! command -v kubectl &> /dev/null; then
|
||||
log_error "kubectl is required but not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker is required but not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for Starship CLI
|
||||
if ! command -v starship &> /dev/null; then
|
||||
log_warning "Starship CLI not found, installing..."
|
||||
install_starship
|
||||
fi
|
||||
|
||||
log_info "Prerequisites check completed"
|
||||
}
|
||||
|
||||
# Install Starship CLI
|
||||
install_starship() {
|
||||
log_info "Installing Starship CLI..."
|
||||
npm install -g @starship-ci/cli@${STARSHIP_VERSION}
|
||||
|
||||
if ! command -v starship &> /dev/null; then
|
||||
log_error "Failed to install Starship CLI"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Starship CLI installed successfully"
|
||||
}
|
||||
|
||||
# Build Docker image
|
||||
build_docker_image() {
|
||||
log_info "Building Sonr Docker image..."
|
||||
|
||||
# Build the image
|
||||
docker build -t sonr:local -f Dockerfile .
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Failed to build Docker image"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Docker image built successfully"
|
||||
}
|
||||
|
||||
# Start Starship network
|
||||
start_network() {
|
||||
log_info "Starting Starship network with config: ${STARSHIP_CONFIG}"
|
||||
|
||||
# Create namespace if it doesn't exist
|
||||
kubectl create namespace ${NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Start Starship
|
||||
starship start --config ${STARSHIP_CONFIG} --namespace ${NAMESPACE}
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Failed to start Starship network"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Starship network started"
|
||||
|
||||
# Wait for network to be ready
|
||||
wait_for_network
|
||||
}
|
||||
|
||||
# Stop Starship network
|
||||
stop_network() {
|
||||
log_info "Stopping Starship network..."
|
||||
|
||||
starship stop --namespace ${NAMESPACE}
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_warning "Failed to stop Starship network gracefully"
|
||||
fi
|
||||
|
||||
# Clean up namespace
|
||||
kubectl delete namespace ${NAMESPACE} --ignore-not-found=true
|
||||
|
||||
log_info "Starship network stopped"
|
||||
}
|
||||
|
||||
# Wait for network to be ready
|
||||
wait_for_network() {
|
||||
log_info "Waiting for network to be ready (timeout: ${TIMEOUT}s)..."
|
||||
|
||||
local start_time=$(date +%s)
|
||||
local current_time
|
||||
local elapsed
|
||||
|
||||
while true; do
|
||||
current_time=$(date +%s)
|
||||
elapsed=$((current_time - start_time))
|
||||
|
||||
if [ $elapsed -gt $TIMEOUT ]; then
|
||||
log_error "Timeout waiting for network to be ready"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if all pods are running
|
||||
local ready_pods=$(kubectl get pods -n ${NAMESPACE} --no-headers | grep -c "Running\|Completed" || true)
|
||||
local total_pods=$(kubectl get pods -n ${NAMESPACE} --no-headers | wc -l || true)
|
||||
|
||||
if [ "$ready_pods" -eq "$total_pods" ] && [ "$total_pods" -gt 0 ]; then
|
||||
log_info "All pods are ready ($ready_pods/$total_pods)"
|
||||
break
|
||||
fi
|
||||
|
||||
log_info "Waiting for pods to be ready ($ready_pods/$total_pods)..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Additional wait for services to be fully initialized
|
||||
log_info "Waiting for services to initialize..."
|
||||
sleep 10
|
||||
|
||||
# Verify chain connectivity
|
||||
verify_chain_connectivity
|
||||
}
|
||||
|
||||
# Verify chain connectivity
|
||||
verify_chain_connectivity() {
|
||||
log_info "Verifying chain connectivity..."
|
||||
|
||||
# Port-forward to access the chains
|
||||
kubectl port-forward -n ${NAMESPACE} service/sonr-1-validator 1317:1317 &
|
||||
local pf_pid=$!
|
||||
|
||||
sleep 5
|
||||
|
||||
# Check if chain is responding
|
||||
if curl -s http://localhost:1317/cosmos/base/tendermint/v1beta1/syncing | grep -q "syncing"; then
|
||||
log_info "Chain 1 is responding"
|
||||
else
|
||||
log_error "Chain 1 is not responding"
|
||||
kill $pf_pid 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
kill $pf_pid 2>/dev/null
|
||||
|
||||
# Check second chain
|
||||
kubectl port-forward -n ${NAMESPACE} service/sonr-2-validator 1318:1318 &
|
||||
pf_pid=$!
|
||||
|
||||
sleep 5
|
||||
|
||||
if curl -s http://localhost:1318/cosmos/base/tendermint/v1beta1/syncing | grep -q "syncing"; then
|
||||
log_info "Chain 2 is responding"
|
||||
else
|
||||
log_error "Chain 2 is not responding"
|
||||
kill $pf_pid 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
kill $pf_pid 2>/dev/null
|
||||
|
||||
log_info "Chain connectivity verified"
|
||||
}
|
||||
|
||||
# Get network info
|
||||
get_network_info() {
|
||||
log_info "Network Information:"
|
||||
echo "========================"
|
||||
|
||||
# Get pod status
|
||||
echo "Pods:"
|
||||
kubectl get pods -n ${NAMESPACE}
|
||||
echo ""
|
||||
|
||||
# Get services
|
||||
echo "Services:"
|
||||
kubectl get services -n ${NAMESPACE}
|
||||
echo ""
|
||||
|
||||
# Get endpoints
|
||||
echo "Endpoints:"
|
||||
echo "- Chain 1 REST: http://localhost:1317"
|
||||
echo "- Chain 1 RPC: http://localhost:26657"
|
||||
echo "- Chain 1 gRPC: localhost:9090"
|
||||
echo "- Chain 2 REST: http://localhost:1318"
|
||||
echo "- Chain 2 RPC: http://localhost:26658"
|
||||
echo "- Chain 2 gRPC: localhost:9091"
|
||||
echo "- Faucet: http://localhost:8000"
|
||||
echo "- Registry: http://localhost:8081"
|
||||
echo "- Explorer: http://localhost:8080"
|
||||
echo "========================"
|
||||
}
|
||||
|
||||
# Port forward for local access
|
||||
setup_port_forward() {
|
||||
log_info "Setting up port forwarding..."
|
||||
|
||||
# Chain 1
|
||||
kubectl port-forward -n ${NAMESPACE} service/sonr-1-validator 1317:1317 26657:26657 9090:9090 &
|
||||
|
||||
# Chain 2
|
||||
kubectl port-forward -n ${NAMESPACE} service/sonr-2-validator 1318:1318 26658:26658 9091:9091 &
|
||||
|
||||
# Faucet
|
||||
kubectl port-forward -n ${NAMESPACE} service/faucet 8000:8000 &
|
||||
|
||||
# Registry
|
||||
kubectl port-forward -n ${NAMESPACE} service/registry 8081:8081 &
|
||||
|
||||
# Explorer
|
||||
kubectl port-forward -n ${NAMESPACE} service/explorer 8080:8080 &
|
||||
|
||||
log_info "Port forwarding established"
|
||||
log_info "Press Ctrl+C to stop port forwarding and exit"
|
||||
|
||||
# Wait for interrupt
|
||||
trap "kill 0" EXIT
|
||||
wait
|
||||
}
|
||||
|
||||
# Run E2E tests
|
||||
run_e2e_tests() {
|
||||
log_info "Running E2E tests..."
|
||||
|
||||
# Set up port forwarding in background
|
||||
setup_port_forward &
|
||||
local pf_pid=$!
|
||||
|
||||
# Wait for port forwarding to be established
|
||||
sleep 5
|
||||
|
||||
# Run tests
|
||||
cd test/e2e
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
# Run specific test
|
||||
log_info "Running test: $1"
|
||||
go test -v -race -run "$1" ./...
|
||||
else
|
||||
# Run all tests
|
||||
log_info "Running all E2E tests"
|
||||
go test -v -race ./...
|
||||
fi
|
||||
|
||||
local test_result=$?
|
||||
|
||||
# Clean up port forwarding
|
||||
kill $pf_pid 2>/dev/null
|
||||
|
||||
if [ $test_result -eq 0 ]; then
|
||||
log_info "E2E tests passed successfully"
|
||||
else
|
||||
log_error "E2E tests failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main command handler
|
||||
case "${1:-}" in
|
||||
start)
|
||||
check_prerequisites
|
||||
build_docker_image
|
||||
start_network
|
||||
get_network_info
|
||||
;;
|
||||
stop)
|
||||
stop_network
|
||||
;;
|
||||
restart)
|
||||
stop_network
|
||||
sleep 5
|
||||
check_prerequisites
|
||||
build_docker_image
|
||||
start_network
|
||||
get_network_info
|
||||
;;
|
||||
status)
|
||||
get_network_info
|
||||
;;
|
||||
port-forward)
|
||||
setup_port_forward
|
||||
;;
|
||||
test)
|
||||
check_prerequisites
|
||||
build_docker_image
|
||||
start_network
|
||||
run_e2e_tests "${2:-}"
|
||||
stop_network
|
||||
;;
|
||||
test-only)
|
||||
run_e2e_tests "${2:-}"
|
||||
;;
|
||||
*)
|
||||
echo "Starship E2E Testing Manager"
|
||||
echo ""
|
||||
echo "Usage: $0 {start|stop|restart|status|port-forward|test|test-only} [test-name]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " start - Start Starship network for E2E testing"
|
||||
echo " stop - Stop Starship network"
|
||||
echo " restart - Restart Starship network"
|
||||
echo " status - Show network status and information"
|
||||
echo " port-forward - Set up port forwarding for local access"
|
||||
echo " test - Start network, run tests, then stop network"
|
||||
echo " test-only - Run tests against existing network"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 start # Start the network"
|
||||
echo " $0 test # Run all E2E tests"
|
||||
echo " $0 test TestBasicChain # Run specific test"
|
||||
echo " $0 test-only TestIBC # Run test against existing network"
|
||||
echo " $0 port-forward # Access network locally"
|
||||
echo " $0 stop # Stop the network"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Regular → Executable
+74
-74
@@ -10,7 +10,7 @@ set -eu
|
||||
export KEY="acc0"
|
||||
export KEY2="acc1"
|
||||
|
||||
export CHAIN_ID=${CHAIN_ID:-"localchain-1"}
|
||||
export CHAIN_ID=${CHAIN_ID:-"sonrtest_1-1"}
|
||||
export MONIKER="localvalidator"
|
||||
export KEYALGO="secp256k1"
|
||||
export KEYRING=${KEYRING:-"test"}
|
||||
@@ -34,119 +34,119 @@ app_toml="${HOME_DIR}/config/app.toml"
|
||||
genesis_json="${HOME_DIR}/config/genesis.json"
|
||||
|
||||
# if which binary does not exist, install it
|
||||
if [ -z $(which $BINARY) ]; then
|
||||
make install
|
||||
if [[ -z $(which "${BINARY}") ]]; then
|
||||
make install
|
||||
|
||||
if [ -z $(which $BINARY) ]; then
|
||||
echo "Ensure $BINARY is installed and in your PATH"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z $(which "${BINARY}") ]]; then
|
||||
echo "Ensure ${BINARY} is installed and in your PATH"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
command -v jq >/dev/null 2>&1 || {
|
||||
echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"
|
||||
exit 1
|
||||
echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set_config() {
|
||||
$BINARY config set client chain-id $CHAIN_ID
|
||||
$BINARY config set client keyring-backend $KEYRING
|
||||
${BINARY} config set client chain-id "${CHAIN_ID}"
|
||||
${BINARY} config set client keyring-backend "${KEYRING}"
|
||||
}
|
||||
set_config
|
||||
|
||||
from_scratch() {
|
||||
# Fresh install on current branch
|
||||
make install
|
||||
# Fresh install on current branch
|
||||
make install
|
||||
|
||||
# remove existing daemon files.
|
||||
if [ ${#HOME_DIR} -le 2 ]; then
|
||||
echo "HOME_DIR must be more than 2 characters long"
|
||||
return
|
||||
fi
|
||||
rm -rf $HOME_DIR && echo "Removed $HOME_DIR"
|
||||
# remove existing daemon files.
|
||||
if [[ ${#HOME_DIR} -le 2 ]]; then
|
||||
echo "HOME_DIR must be more than 2 characters long"
|
||||
return
|
||||
fi
|
||||
rm -rf "${HOME_DIR}" && echo "Removed ${HOME_DIR}"
|
||||
|
||||
# reset values if not set already after whipe
|
||||
set_config
|
||||
# reset values if not set already after whipe
|
||||
set_config
|
||||
|
||||
add_key() {
|
||||
key=$1
|
||||
mnemonic=$2
|
||||
echo $mnemonic | $BINARY keys add $key --home $HOME_DIR --keyring-backend $KEYRING --algo $KEYALGO --recover
|
||||
}
|
||||
add_key() {
|
||||
key=$1
|
||||
mnemonic=$2
|
||||
echo "${mnemonic}" | ${BINARY} keys add "${key}" --home "${HOME_DIR}" --keyring-backend "${KEYRING}" --algo "${KEYALGO}" --recover
|
||||
}
|
||||
|
||||
# cosmos1efd63aw40lxf3n4mhf7dzhjkr453axur6cpk92
|
||||
add_key $KEY "decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry"
|
||||
# cosmos1hj5fveer5cjtn4wd6wstzugjfdxzl0xpxvjjvr
|
||||
add_key $KEY2 "wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise"
|
||||
# cosmos1efd63aw40lxf3n4mhf7dzhjkr453axur6cpk92
|
||||
add_key "${KEY}" "decorate bright ozone fork gallery riot bus exhaust worth way bone indoor calm squirrel merry zero scheme cotton until shop any excess stage laundry"
|
||||
# cosmos1hj5fveer5cjtn4wd6wstzugjfdxzl0xpxvjjvr
|
||||
add_key "${KEY2}" "wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise"
|
||||
|
||||
$BINARY init $CHAIN_ID --chain-id $CHAIN_ID --overwrite --default-denom $DENOM --home $HOME_DIR
|
||||
${BINARY} init "${CHAIN_ID}" --chain-id "${CHAIN_ID}" --overwrite --default-denom "${DENOM}" --home "${HOME_DIR}"
|
||||
|
||||
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_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
|
||||
}
|
||||
|
||||
# === CORE MODULES ===
|
||||
# block
|
||||
update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"'
|
||||
# crisis
|
||||
update_test_genesis $(printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' $DENOM)
|
||||
# === CORE MODULES ===
|
||||
# block
|
||||
update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"'
|
||||
# crisis
|
||||
update_test_genesis $(printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' "${DENOM}")
|
||||
|
||||
# === 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'
|
||||
# === 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'
|
||||
|
||||
$BINARY keys list --keyring-backend $KEYRING --home $HOME_DIR
|
||||
${BINARY} keys list --keyring-backend "${KEYRING}" --home "${HOME_DIR}"
|
||||
|
||||
# Allocate genesis accounts
|
||||
$BINARY genesis add-genesis-account $KEY 10000000$DENOM,900test --keyring-backend $KEYRING --home $HOME_DIR --append
|
||||
$BINARY genesis add-genesis-account $KEY2 10000000$DENOM,800test --keyring-backend $KEYRING --home $HOME_DIR --append
|
||||
# Allocate genesis accounts
|
||||
${BINARY} genesis add-genesis-account "${KEY}" 10000000"${DENOM}",900test --keyring-backend "${KEYRING}" --home "${HOME_DIR}" --append
|
||||
${BINARY} genesis add-genesis-account "${KEY2}" 10000000"${DENOM}",800test --keyring-backend "${KEYRING}" --home "${HOME_DIR}" --append
|
||||
|
||||
# ICS provider genesis hack
|
||||
HACK_DIR=icshack-1 && echo $HACK_DIR
|
||||
rm -rf $HACK_DIR
|
||||
cp -r ${HOME_DIR} $HACK_DIR
|
||||
# ICS provider genesis hack
|
||||
HACK_DIR=icshack-1 && echo "${HACK_DIR}"
|
||||
rm -rf "${HACK_DIR}"
|
||||
cp -r "${HOME_DIR}" "${HACK_DIR}"
|
||||
|
||||
$BINARY add-consumer-section provider --home $HACK_DIR
|
||||
ccvjson=$(jq '.app_state["ccvconsumer"]' $HACK_DIR/config/genesis.json)
|
||||
echo $ccvjson
|
||||
jq '.app_state["ccvconsumer"] = '"$ccvjson" ${HACK_DIR}/config/genesis.json >json.tmp && mv json.tmp $genesis_json
|
||||
rm -rf $HACK_DIR
|
||||
${BINARY} add-consumer-section provider --home "${HACK_DIR}"
|
||||
ccvjson=$(jq '.app_state["ccvconsumer"]' "${HACK_DIR}"/config/genesis.json)
|
||||
echo "${ccvjson}"
|
||||
jq '.app_state["ccvconsumer"] = '"${ccvjson}" "${HACK_DIR}"/config/genesis.json >json.tmp && mv json.tmp "${genesis_json}"
|
||||
rm -rf "${HACK_DIR}"
|
||||
|
||||
update_test_genesis $(printf '.app_state["ccvconsumer"]["params"]["unbonding_period"]="%s"' "240s")
|
||||
update_test_genesis $(printf '.app_state["ccvconsumer"]["params"]["unbonding_period"]="%s"' "240s")
|
||||
}
|
||||
|
||||
# check if CLEAN is not set to false
|
||||
if [ "$CLEAN" != "false" ]; then
|
||||
echo "Starting from a clean state"
|
||||
from_scratch
|
||||
if [[ ${CLEAN} != "false" ]]; then
|
||||
echo "Starting from a clean state"
|
||||
from_scratch
|
||||
fi
|
||||
|
||||
# Opens the RPC endpoint to outside connections
|
||||
sed -i -e 's/laddr = "tcp:\/\/127.0.0.1:26657"/c\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
|
||||
sed -i -e 's/laddr = "tcp:\/\/127.0.0.1:26657"/c\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
|
||||
|
||||
# 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/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
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
# Rosetta Api
|
||||
sed -i -e 's/address = ":8080"/address = "0.0.0.0:'$ROSETTA'"/g' $HOME_DIR/config/app.toml
|
||||
sed -i -e 's/address = ":8080"/address = "0.0.0.0:'"${ROSETTA}"'"/g' "${HOME_DIR}"/config/app.toml
|
||||
|
||||
# Faster blocks
|
||||
sed -i -e 's/timeout_commit = "5s"/timeout_commit = "'$BLOCK_TIME'"/g' $HOME_DIR/config/config.toml
|
||||
sed -i -e 's/timeout_commit = "5s"/timeout_commit = "'"${BLOCK_TIME}"'"/g' "${HOME_DIR}"/config/config.toml
|
||||
|
||||
# Start the daemon in the background
|
||||
$BINARY start --pruning=nothing --minimum-gas-prices=0$DENOM --rpc.laddr="tcp://0.0.0.0:$RPC" --home $HOME_DIR
|
||||
${BINARY} start --pruning=nothing --minimum-gas-prices=0"${DENOM}" --rpc.laddr="tcp://0.0.0.0:${RPC}" --home "${HOME_DIR}"
|
||||
|
||||
Regular → Executable
+355
-102
@@ -2,25 +2,23 @@
|
||||
# Run this script to quickly install, setup, and run the current version of the network without docker.
|
||||
#
|
||||
# Examples:
|
||||
# CHAIN_ID="local-1" HOME_DIR="~/.core" BLOCK_TIME="1000ms" CLEAN=true sh scripts/test_node.sh
|
||||
# CHAIN_ID="local-2" HOME_DIR="~/.core" 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
|
||||
# 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
|
||||
|
||||
export KEY0_NAME=${KEY0_NAME:-"user0"}
|
||||
export KEY0_MNEMONIC=${KEY0_MNEMONIC:-"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 KEY1_NAME="user2"
|
||||
export KEY1_MNEMONIC=${KEY1_MNEMONIC:-"wealth flavor believe regret funny network recall kiss grape useless pepper cram hint member few certain unveil rather brick bargain curious require crowd raise"}
|
||||
set -eu
|
||||
|
||||
export TX_INDEX_INDEXER=${TX_INDEX_INDEXER:-"kv"}
|
||||
export TX_INDEX_PSQL_CONN=${TX_INDEX_PSQL_CONN:-""}
|
||||
export CHAIN_ID=${CHAIN_ID:-"sonr-testnet-1"}
|
||||
export MONIKER="florence"
|
||||
export KEYALGO="secp256k1"
|
||||
export KEY="acc0"
|
||||
export KEY2="acc1"
|
||||
|
||||
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:-sonrd}
|
||||
export BINARY=${BINARY:-snrd}
|
||||
export DENOM=${DENOM:-usnr}
|
||||
|
||||
export CLEAN=${CLEAN:-"true"}
|
||||
export CLEAN=${CLEAN:-"false"}
|
||||
export RPC=${RPC:-"26657"}
|
||||
export REST=${REST:-"1317"}
|
||||
export PROFF=${PROFF:-"6060"}
|
||||
@@ -28,138 +26,393 @@ 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"}
|
||||
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
# 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"}
|
||||
|
||||
# if which binary does not exist, exit
|
||||
if [ -z `which $BINARY` ]; then
|
||||
echo "Ensure $BINARY is installed and in your PATH"
|
||||
exit 1
|
||||
# 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
|
||||
# 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..."
|
||||
else
|
||||
echo "Binary ${BINARY} 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"
|
||||
USE_DOCKER=true
|
||||
else
|
||||
echo "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."
|
||||
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"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
alias BINARY="$BINARY --home=$HOME_DIR"
|
||||
# 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
|
||||
}
|
||||
|
||||
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; }
|
||||
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
|
||||
# Ensure the directory exists on the host
|
||||
mkdir -p "${HOME_DIR}"
|
||||
# Determine if we're in a TTY
|
||||
DOCKER_TTY_FLAG=""
|
||||
if [ -t 0 ]; then
|
||||
DOCKER_TTY_FLAG="-it"
|
||||
fi
|
||||
# Mount home directory to container's /root/.sonr
|
||||
docker run --rm ${DOCKER_TTY_FLAG} \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
onsonr/snrd:latest \
|
||||
snrd --home /root/.sonr "$@"
|
||||
else
|
||||
${BINARY} "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
set_config() {
|
||||
$BINARY config set client chain-id $CHAIN_ID
|
||||
$BINARY config set client keyring-backend $KEYRING
|
||||
run_binary config set client chain-id "${CHAIN_ID}"
|
||||
run_binary config set client keyring-backend "${KEYRING}"
|
||||
}
|
||||
set_config
|
||||
|
||||
from_scratch () {
|
||||
# Fresh install on current branch
|
||||
make install
|
||||
from_scratch() {
|
||||
# Fresh install on current branch (skip if using Docker or SKIP_INSTALL is true)
|
||||
if [[ "${USE_DOCKER}" == "false" ]] && [[ "${SKIP_INSTALL}" == "false" ]]; then
|
||||
make install
|
||||
fi
|
||||
|
||||
# remove existing daemon files.
|
||||
if [ ${#HOME_DIR} -le 2 ]; then
|
||||
echo "HOME_DIR must be more than 2 characters long"
|
||||
return
|
||||
fi
|
||||
rm -rf $HOME_DIR && echo "Removed $HOME_DIR"
|
||||
# remove existing daemon files.
|
||||
if [[ ${#HOME_DIR} -le 2 ]]; then
|
||||
echo "HOME_DIR must be more than 2 characters long"
|
||||
return
|
||||
fi
|
||||
rm -rf "${HOME_DIR}" && echo "Removed ${HOME_DIR}"
|
||||
|
||||
# reset values if not set already after whipe
|
||||
set_config
|
||||
# reset values if not set already after whipe
|
||||
set_config
|
||||
|
||||
add_key() {
|
||||
echo "Adding key: $1"
|
||||
key=$1
|
||||
mnemonic=$2
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
# idx1efd63aw40lxf3n4mhf7dzhjkr453axur9vjt6y
|
||||
echo "$KEY0_MNEMONIC" | BINARY keys add $KEY0_NAME --keyring-backend $KEYRING --algo $KEYALGO --recover
|
||||
echo "$KEY1_MNEMONIC" | BINARY keys add $KEY1_NAME --keyring-backend $KEYRING --algo $KEYALGO --recover
|
||||
# idx140fehngcrxvhdt84x729p3f0qmkmea8n570lrg
|
||||
add_key "${KEY}" "${SONR_MNEMONIC_1}"
|
||||
|
||||
# chain initial setup
|
||||
BINARY init $MONIKER --chain-id $CHAIN_ID --default-denom $DENOM
|
||||
# idx1r6yue0vuyj9m7xw78npspt9drq2tmtvgcrf7sr
|
||||
add_key "${KEY2}" "${SONR_MNEMONIC_2}"
|
||||
|
||||
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
|
||||
}
|
||||
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}"
|
||||
fi
|
||||
|
||||
# === CORE MODULES ===
|
||||
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
|
||||
}
|
||||
|
||||
# Block
|
||||
update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"'
|
||||
# === CORE MODULES ===
|
||||
|
||||
# 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"'
|
||||
# Block
|
||||
update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"'
|
||||
|
||||
# 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"'
|
||||
# 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"'
|
||||
|
||||
# mint
|
||||
update_test_genesis `printf '.app_state["mint"]["params"]["mint_denom"]="%s"' $DENOM`
|
||||
# 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
|
||||
|
||||
# crisis
|
||||
update_test_genesis `printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' $DENOM`
|
||||
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"'
|
||||
|
||||
# === CUSTOM MODULES ===
|
||||
# globalfee
|
||||
update_test_genesis `printf '.app_state["globalfee"]["params"]["minimum_gas_prices"]=[{"amount":"0.000000000000000000","denom":"%s"}]' $DENOM`
|
||||
# tokenfactory
|
||||
update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_fee"]=[]'
|
||||
update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_gas_consume"]=100000'
|
||||
# poa
|
||||
update_test_genesis '.app_state["poa"]["params"]["admins"]=["idx10d07y265gmmuvt4z0w9aw880jnsr700j9kqcfa"]'
|
||||
# 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"'
|
||||
|
||||
# Allocate genesis accounts
|
||||
BINARY genesis add-genesis-account $KEY0_NAME 10000000$DENOM,900snr --keyring-backend $KEYRING
|
||||
BINARY genesis add-genesis-account $KEY1_NAME 10000000$DENOM,800snr --keyring-backend $KEYRING
|
||||
# mint
|
||||
update_test_genesis $(printf '.app_state["mint"]["params"]["mint_denom"]="%s"' "${DENOM}")
|
||||
|
||||
# Sign genesis transaction
|
||||
BINARY genesis gentx $KEY0_NAME 1000000$DENOM --keyring-backend $KEYRING --chain-id $CHAIN_ID
|
||||
# crisis
|
||||
update_test_genesis $(printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' "${DENOM}")
|
||||
|
||||
BINARY genesis collect-gentxs
|
||||
## abci
|
||||
update_test_genesis '.consensus["params"]["abci"]["vote_extensions_enable_height"]="1"'
|
||||
|
||||
BINARY genesis validate-genesis
|
||||
err=$?
|
||||
if [ $err -ne 0 ]; then
|
||||
echo "Failed to validate genesis"
|
||||
return
|
||||
fi
|
||||
# === 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
|
||||
if [[ "${USE_DOCKER}" == "true" ]]; then
|
||||
docker run --rm \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
onsonr/snrd:latest \
|
||||
snrd --home /root/.sonr genesis add-genesis-account "${KEY}" "${BASE_GENESIS_ALLOCATIONS}" --keyring-backend "${KEYRING}" --append
|
||||
docker run --rm \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
onsonr/snrd:latest \
|
||||
snrd --home /root/.sonr genesis add-genesis-account "${KEY2}" "${BASE_GENESIS_ALLOCATIONS}" --keyring-backend "${KEYRING}" --append
|
||||
# Sign genesis transaction
|
||||
docker run --rm \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
onsonr/snrd:latest \
|
||||
snrd --home /root/.sonr genesis gentx "${KEY}" 1000000000000000000000"${DENOM}" --gas-prices 0"${DENOM}" --keyring-backend "${KEYRING}" --chain-id "${CHAIN_ID}"
|
||||
docker run --rm \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
onsonr/snrd:latest \
|
||||
snrd --home /root/.sonr genesis collect-gentxs
|
||||
docker run --rm \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
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
|
||||
# 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
|
||||
fi
|
||||
}
|
||||
|
||||
# check if CLEAN is not set to false
|
||||
if [ "$CLEAN" != "false" ]; then
|
||||
echo "Starting from a clean state"
|
||||
from_scratch
|
||||
if [[ ${CLEAN} != "false" ]]; then
|
||||
echo "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"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Starting node..."
|
||||
|
||||
# Tx Index
|
||||
if [ "$TX_INDEX_PSQL_CONN" != "" ]; then
|
||||
awk -v conn="$TX_INDEX_PSQL_CONN" '/^psql-conn = / {$0 = "psql-conn = \"" conn "\""} 1' $HOME_DIR/config/config.toml > temp && mv temp $HOME_DIR/config/config.toml
|
||||
fi
|
||||
|
||||
|
||||
# Opens the RPC endpoint to outside connections
|
||||
sed -i 's/laddr = "tcp:\/\/127.0.0.1:26657"/c\laddr = "tcp:\/\/0.0.0.0:'$RPC'"/g' $HOME_DIR/config/config.toml
|
||||
sed -i 's/cors_allowed_origins = \[\]/cors_allowed_origins = \["\*"\]/g' $HOME_DIR/config/config.toml
|
||||
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
|
||||
|
||||
# REST endpoint
|
||||
sed -i 's/address = "tcp:\/\/localhost:1317"/address = "tcp:\/\/0.0.0.0:'$REST'"/g' $HOME_DIR/config/app.toml
|
||||
sed -i 's/enable = false/enable = true/g' $HOME_DIR/config/app.toml
|
||||
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
|
||||
|
||||
# peer exchange
|
||||
sed -i 's/pprof_laddr = "localhost:6060"/pprof_laddr = "localhost:'$PROFF_LADDER'"/g' $HOME_DIR/config/config.toml
|
||||
sed -i 's/laddr = "tcp:\/\/0.0.0.0:26656"/laddr = "tcp:\/\/0.0.0.0:'$P2P'"/g' $HOME_DIR/config/config.toml
|
||||
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
|
||||
|
||||
# GRPC
|
||||
sed -i 's/address = "localhost:9090"/address = "0.0.0.0:'$GRPC'"/g' $HOME_DIR/config/app.toml
|
||||
sed -i 's/address = "localhost:9091"/address = "0.0.0.0:'$GRPC_WEB'"/g' $HOME_DIR/config/app.toml
|
||||
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
|
||||
|
||||
# Rosetta Api
|
||||
sed -i 's/address = ":8080"/address = "0.0.0.0:'$ROSETTA'"/g' $HOME_DIR/config/app.toml
|
||||
sed -i 's/indexer = "kv"/indexer = "'$TX_INDEX_INDEXER'"/g' $HOME_DIR/config/config.toml
|
||||
sed -i -e 's/address = ":8080"/address = "0.0.0.0:'"${ROSETTA}"'"/g' "${HOME_DIR}"/config/app.toml
|
||||
|
||||
# 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
|
||||
|
||||
# Start the node with 0 gas fees
|
||||
BINARY start --pruning=nothing --minimum-gas-prices=0$DENOM --rpc.laddr="tcp://0.0.0.0:$RPC" --grpc.address="0.0.0.0:$GRPC" --grpc-web.enable=true
|
||||
# Faster blocks
|
||||
sed -i -e 's/timeout_commit = "5s"/timeout_commit = "'"${BLOCK_TIME}"'"/g' "${HOME_DIR}"/config/config.toml
|
||||
|
||||
# Start the node (with or without Docker)
|
||||
if [[ "${USE_DOCKER}" == "true" ]]; then
|
||||
echo "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"
|
||||
elif [ -t 0 ]; then
|
||||
echo ""
|
||||
echo "Would you like to run the node in detached mode (background)? [y/N]"
|
||||
read -r -n 1 DETACH_RESPONSE
|
||||
echo ""
|
||||
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"
|
||||
else
|
||||
echo "Running in foreground mode. Use Ctrl+C to stop."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Determine if we're in a TTY (only for non-detached mode)
|
||||
DOCKER_TTY_FLAG=""
|
||||
if [ -t 0 ] && [ -z "$DETACHED_MODE" ]; then
|
||||
DOCKER_TTY_FLAG="-it"
|
||||
fi
|
||||
|
||||
docker run --rm ${DETACHED_MODE} ${DOCKER_TTY_FLAG} \
|
||||
-v "${HOME_DIR}:/root/.sonr" \
|
||||
--network host \
|
||||
--name sonr-testnode \
|
||||
onsonr/snrd:latest \
|
||||
snrd start --pruning=nothing --minimum-gas-prices=0"${DENOM}" --rpc.laddr="tcp://0.0.0.0:${RPC}" --home /root/.sonr --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}"
|
||||
|
||||
# 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 ""
|
||||
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}"
|
||||
fi
|
||||
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
|
||||
DENOM="${DENOM:=usnr}"
|
||||
CHAIN_BIN="${CHAIN_BIN:=snrd}"
|
||||
CHAIN_DIR="${CHAIN_DIR:=$HOME/.sonr}"
|
||||
|
||||
set -eux
|
||||
|
||||
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)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
GIT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
CONSTITUTION_FILE="${GIT_ROOT}/CONSTITUTION.md"
|
||||
|
||||
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
|
||||
|
||||
if [ "$(jq -r '.app_state.gov.params' "$CHAIN_DIR"/config/genesis.json)" == "null" ]; then
|
||||
gov_overrides_sdk_v46
|
||||
else
|
||||
gov_overrides_sdk_v47
|
||||
fi
|
||||
|
||||
$CHAIN_BIN tendermint show-node-id
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e # Exit on any error
|
||||
|
||||
# Function to compare version strings
|
||||
version_gt() {
|
||||
test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"
|
||||
}
|
||||
|
||||
# Install commitizen if not present
|
||||
if ! command -v cz &> /dev/null; then
|
||||
echo "Installing commitizen..."
|
||||
pip install --user commitizen
|
||||
fi
|
||||
|
||||
# Get all tags and sort them by version
|
||||
echo "Fetching all tags..."
|
||||
git fetch --tags --force
|
||||
TAGS=$(git tag -l "v*" | sort -V)
|
||||
LATEST_TAG=$(echo "$TAGS" | tail -n1)
|
||||
|
||||
if [ -z "$LATEST_TAG" ]; then
|
||||
echo "No tags found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Latest tag: $LATEST_TAG"
|
||||
|
||||
# Run commitizen to determine next version
|
||||
echo "Running commitizen bump --dry-run..."
|
||||
NEXT_VERSION=$(cz bump --dry-run --increment=patch 2>&1 | grep "tag to create: v" | cut -d "v" -f2)
|
||||
|
||||
if [ -z "$NEXT_VERSION" ]; then
|
||||
echo "Failed to determine next version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Next version determined by commitizen: v$NEXT_VERSION"
|
||||
|
||||
# Check if the next version already exists
|
||||
if echo "$TAGS" | grep -q "v$NEXT_VERSION"; then
|
||||
echo "ERROR: Version v$NEXT_VERSION already exists!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the next version is actually greater than the latest
|
||||
if ! version_gt "$NEXT_VERSION" "${LATEST_TAG#v}"; then
|
||||
echo "ERROR: Next version v$NEXT_VERSION is not greater than current version $LATEST_TAG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Version v$NEXT_VERSION is valid and does not exist yet"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user