tax rate, version and compose (#70)
resolves #67 Co-authored-by: johba <johba@harb.eth> Reviewed-on: https://codeberg.org/johba/harb/pulls/70
This commit is contained in:
parent
d8ca557eb6
commit
6cbb1781ce
40 changed files with 1243 additions and 213 deletions
|
|
@ -1,7 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/../kraiken-lib"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
cd "$REPO_ROOT/kraiken-lib"
|
||||
|
||||
if [[ ! -d node_modules || ! -x node_modules/.bin/tsc ]]; then
|
||||
if ! npm install --silent; then
|
||||
|
|
@ -9,6 +12,9 @@ if [[ ! -d node_modules || ! -x node_modules/.bin/tsc ]]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Ensure tax rate data mirrors onchain Stake.sol before compiling
|
||||
node "$SCRIPT_DIR/sync-tax-rates.mjs"
|
||||
|
||||
./node_modules/.bin/tsc
|
||||
|
||||
echo "kraiken-lib built"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,64 @@ start_stack() {
|
|||
./scripts/build-kraiken-lib.sh
|
||||
|
||||
echo "Starting stack..."
|
||||
podman-compose up -d
|
||||
# Start services in strict dependency order with explicit create+start
|
||||
# This avoids podman dependency graph issues
|
||||
|
||||
# Create all containers first (without starting)
|
||||
echo " Creating containers..."
|
||||
podman-compose up --no-start 2>&1 | grep -v "STEP\|Copying\|Writing\|Getting\|fetch\|Installing\|Executing" || true
|
||||
|
||||
# Phase 1: Start base services (no dependencies)
|
||||
echo " Starting anvil & postgres..."
|
||||
podman-compose start anvil postgres >/dev/null 2>&1
|
||||
|
||||
# Wait for base services to be healthy
|
||||
echo " Waiting for anvil & postgres..."
|
||||
for i in {1..30}; do
|
||||
anvil_healthy=$(podman healthcheck run harb_anvil_1 >/dev/null 2>&1 && echo "yes" || echo "no")
|
||||
postgres_healthy=$(podman healthcheck run harb_postgres_1 >/dev/null 2>&1 && echo "yes" || echo "no")
|
||||
if [[ "$anvil_healthy" == "yes" ]] && [[ "$postgres_healthy" == "yes" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Phase 2: Start bootstrap (depends on anvil & postgres healthy)
|
||||
echo " Starting bootstrap..."
|
||||
podman-compose start bootstrap >/dev/null 2>&1
|
||||
|
||||
# Wait for bootstrap to complete
|
||||
echo " Waiting for bootstrap..."
|
||||
for i in {1..60}; do
|
||||
bootstrap_status=$(podman inspect harb_bootstrap_1 --format='{{.State.Status}}')
|
||||
if [[ "$bootstrap_status" == "exited" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Phase 3: Start ponder (depends on bootstrap completed)
|
||||
echo " Starting ponder..."
|
||||
podman-compose start ponder >/dev/null 2>&1
|
||||
|
||||
# Wait for ponder to be healthy
|
||||
echo " Waiting for ponder..."
|
||||
for i in {1..60}; do
|
||||
ponder_healthy=$(podman healthcheck run harb_ponder_1 >/dev/null 2>&1 && echo "yes" || echo "no")
|
||||
if [[ "$ponder_healthy" == "yes" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Phase 4: Start frontend services (depend on ponder healthy)
|
||||
echo " Starting webapp, landing, txn-bot..."
|
||||
podman-compose start webapp landing txn-bot >/dev/null 2>&1
|
||||
|
||||
# Phase 5: Start caddy (depends on frontend services)
|
||||
sleep 5
|
||||
echo " Starting caddy..."
|
||||
podman-compose start caddy >/dev/null 2>&1
|
||||
|
||||
echo "Watching for kraiken-lib changes..."
|
||||
./scripts/watch-kraiken-lib.sh &
|
||||
|
|
|
|||
106
scripts/sync-tax-rates.mjs
Normal file
106
scripts/sync-tax-rates.mjs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Sync TAX_RATE options from the on-chain Stake contract to kraiken-lib.
|
||||
*
|
||||
* The Stake.sol contract defines the canonical TAX_RATES array in basis points (yearly percentage * 100).
|
||||
* This script parses that array and regenerates kraiken-lib/src/taxRates.ts so that all front-end consumers
|
||||
* share a single source of truth that mirrors the deployed contract.
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const stakeSourcePath = path.resolve(__dirname, '../onchain/src/Stake.sol');
|
||||
const taxRatesDestPath = path.resolve(__dirname, '../kraiken-lib/src/taxRates.ts');
|
||||
|
||||
const source = readFileSync(stakeSourcePath, 'utf8');
|
||||
|
||||
const match = source.match(/uint256\[]\s+public\s+TAX_RATES\s*=\s*\[([^\]]+)\]/m);
|
||||
if (!match) {
|
||||
throw new Error(`Unable to locate TAX_RATES array in ${stakeSourcePath}`);
|
||||
}
|
||||
|
||||
const rawValues = match[1]
|
||||
.split(',')
|
||||
.map(value => value.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
if (rawValues.length === 0) {
|
||||
throw new Error('TAX_RATES array is empty or failed to parse');
|
||||
}
|
||||
|
||||
const taxRateOptions = rawValues.map((value, index) => {
|
||||
const basisPoints = Number(value.replace(/_/g, ''));
|
||||
if (!Number.isFinite(basisPoints)) {
|
||||
throw new Error(`Invalid TAX_RATES entry "${value}" at index ${index}`);
|
||||
}
|
||||
|
||||
const yearlyPercent = basisPoints;
|
||||
const decimalRate = yearlyPercent / 100;
|
||||
const dailyPercent = yearlyPercent / 365;
|
||||
|
||||
return {
|
||||
index,
|
||||
year: yearlyPercent,
|
||||
daily: Number(dailyPercent.toFixed(5)),
|
||||
decimal: Number(decimalRate.toFixed(2)),
|
||||
};
|
||||
});
|
||||
|
||||
// Generate checksum for runtime validation
|
||||
import { createHash } from 'node:crypto';
|
||||
const taxRatesString = rawValues.join(',');
|
||||
const checksum = createHash('sha256').update(taxRatesString).digest('hex').slice(0, 16);
|
||||
|
||||
const fileHeader = `/**
|
||||
* AUTO-GENERATED FILE — DO NOT EDIT
|
||||
*
|
||||
* Generated by scripts/sync-tax-rates.mjs from onchain/src/Stake.sol.
|
||||
* Run \`node scripts/sync-tax-rates.mjs\` after modifying the contract TAX_RATES array.
|
||||
*/
|
||||
`;
|
||||
|
||||
const interfaceDef = `export interface TaxRateOption {
|
||||
index: number;
|
||||
year: number;
|
||||
daily: number;
|
||||
decimal: number;
|
||||
}
|
||||
`;
|
||||
|
||||
const optionLines = taxRateOptions
|
||||
.map(option => ` { index: ${option.index}, year: ${option.year}, daily: ${option.daily}, decimal: ${option.decimal} }`)
|
||||
.join(',\n');
|
||||
|
||||
const content = `${fileHeader}
|
||||
${interfaceDef}
|
||||
export const TAX_RATE_OPTIONS: TaxRateOption[] = [
|
||||
${optionLines}
|
||||
];
|
||||
|
||||
/**
|
||||
* Checksum of the contract TAX_RATES array (first 16 chars of SHA-256).
|
||||
* Used for runtime validation to ensure kraiken-lib is in sync with deployed contracts.
|
||||
*
|
||||
* To validate at runtime:
|
||||
* 1. Read TAX_RATES array from the Stake contract
|
||||
* 2. Compute checksum: sha256(values.join(',')).slice(0, 16)
|
||||
* 3. Compare with TAX_RATES_CHECKSUM
|
||||
*
|
||||
* If mismatch: Run \`node scripts/sync-tax-rates.mjs\` and rebuild kraiken-lib.
|
||||
*/
|
||||
export const TAX_RATES_CHECKSUM = '${checksum}';
|
||||
|
||||
/**
|
||||
* Array of raw year values (matches contract uint256[] TAX_RATES exactly).
|
||||
* Used for runtime validation without needing to parse options.
|
||||
*/
|
||||
export const TAX_RATES_RAW = [${rawValues.join(', ')}];
|
||||
`;
|
||||
|
||||
writeFileSync(taxRatesDestPath, content.trimStart() + '\n');
|
||||
Loading…
Add table
Add a link
Reference in a new issue