mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-25 06:01:11 +00:00
test(amm-ui): bootstrap deterministic test wallet in testnet setup
This commit is contained in:
@@ -8,27 +8,30 @@
|
||||
# AMM UI swap test (apps/amm/tests/swap.mjs) exercises; run it once to stand up
|
||||
# a swappable pool, then launch the UI / run the test.
|
||||
#
|
||||
# DETERMINISTIC TEST WALLET: by default the script bootstraps an ISOLATED wallet
|
||||
# (git-ignored, under this folder) by restoring it from a fixed BIP-39 mnemonic
|
||||
# and creating its accounts in a fixed order. The wallet's BIP-32 key tree makes
|
||||
# those account ids reproducible across machines, so the whole team gets the
|
||||
# same token/holding ids — and the script auto-writes apps/amm/amm-tokens.json
|
||||
# from them for the UI. It never touches your personal ~/.lee/wallet.
|
||||
#
|
||||
# Program IDs and all AMM PDAs (config, pool, vaults, LP, tick) are DERIVED at
|
||||
# runtime from the deployed binaries + the token definition accounts, so this
|
||||
# script stays correct even if you rebuild the guest binaries (new image id =>
|
||||
# new program id => new PDAs). Only the input accounts below are hand-picked.
|
||||
# new program id => new PDAs).
|
||||
#
|
||||
# TEST WALLET (isolated): by default this script points the wallet at a
|
||||
# dedicated, git-ignored home under this folder (apps/amm/tests/testnet/.wallet)
|
||||
# so it never touches your personal ~/.lee/wallet. Override with TEST_WALLET_HOME.
|
||||
#
|
||||
# Prerequisites (all managed by you, outside this script):
|
||||
# Prerequisites (managed by you, outside this script):
|
||||
# - `wallet` and `spel` on PATH (from the SPEL toolchain)
|
||||
# - a wallet initialized at TEST_WALLET_HOME, funded and synced, that OWNS the
|
||||
# account ids configured below (see "TEST ACCOUNTS" — these must be derived
|
||||
# from / created in the test wallet; see docs/testnet-runbook.md §2)
|
||||
# - a reachable, funded sequencer (set TEST_SEQUENCER_ADDR, or pre-configure
|
||||
# the wallet). Account creation is local, but deploys/mints need funds.
|
||||
# - `cargo` (to run the amm_pdas example)
|
||||
# - the guest .bin files already built (`make build-programs`)
|
||||
# - the IDL files under artifacts/ (`make idl`)
|
||||
#
|
||||
# Usage (from anywhere in the repo):
|
||||
# apps/amm/tests/testnet/setup-amm-testnet.sh
|
||||
# TEST_WALLET_HOME=/tmp/lez-test-wallet apps/amm/tests/testnet/setup-amm-testnet.sh
|
||||
# TEST_SEQUENCER_ADDR=http://127.0.0.1:8080 apps/amm/tests/testnet/setup-amm-testnet.sh
|
||||
# FORCE_BOOTSTRAP=1 ... # re-restore the test wallet (rewrites its storage)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
@@ -39,23 +42,31 @@ REPO_ROOT="${REPO_ROOT:-$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
###############################################################################
|
||||
# TEST WALLET — isolated from your personal wallet
|
||||
# TEST WALLET — isolated + deterministic
|
||||
###############################################################################
|
||||
|
||||
# Dedicated wallet home for tests. Kept out of git (see .gitignore). Exported
|
||||
# under both env var names so whichever the installed `wallet`/`spel` expects
|
||||
# is satisfied.
|
||||
# under both env var names so whichever the installed `wallet`/`spel` expects is
|
||||
# satisfied (the current wallet uses LEE_WALLET_HOME_DIR).
|
||||
TEST_WALLET_HOME="${TEST_WALLET_HOME:-$SCRIPT_DIR/.wallet}"
|
||||
export LEE_WALLET_HOME_DIR="$TEST_WALLET_HOME"
|
||||
export NSSA_WALLET_HOME_DIR="$TEST_WALLET_HOME"
|
||||
|
||||
# The deterministic test mnemonic. A wallet restored from this seed always
|
||||
# yields the same account ids, which is why the ids below can be pinned and
|
||||
# shared with the team. Keep in sync with the wallet at TEST_WALLET_HOME.
|
||||
# The deterministic test seed. A wallet restored from this mnemonic yields the
|
||||
# same account ids every time, which is why they can be shared/pinned.
|
||||
TEST_MNEMONIC="${TEST_MNEMONIC:-test test test test test test test test test test test junk}"
|
||||
TEST_WALLET_PASSWORD="${TEST_WALLET_PASSWORD:-test}"
|
||||
TEST_WALLET_DEPTH="${TEST_WALLET_DEPTH:-3}"
|
||||
# Optional: point the test wallet's config at your sequencer. Leave empty to use
|
||||
# whatever the wallet home is already configured with.
|
||||
TEST_SEQUENCER_ADDR="${TEST_SEQUENCER_ADDR:-}"
|
||||
|
||||
# Deterministic accounts, created in THIS fixed order after a fresh restore so
|
||||
# their ids are reproducible. Resolved to ids at runtime via `wallet account id`.
|
||||
ACCOUNT_LABELS=(token-a-def token-a-holding token-b-def token-b-holding lp-holding)
|
||||
|
||||
###############################################################################
|
||||
# CONFIG — edit these
|
||||
# CONFIG — non-account parameters (edit freely)
|
||||
###############################################################################
|
||||
|
||||
# --- Program binaries (docker release builds; image ids must match deployment) ---
|
||||
@@ -67,38 +78,20 @@ TWAP_BIN="programs/twap_oracle/methods/guest/target/riscv32im-risc0-zkvm-elf/doc
|
||||
TOKEN_IDL="artifacts/token-idl.json"
|
||||
AMM_IDL="artifacts/amm-idl.json"
|
||||
|
||||
# --- TEST ACCOUNTS (must be owned by the wallet at TEST_WALLET_HOME) ----------
|
||||
# These are the deterministic accounts the test suite relies on. See the
|
||||
# "Deterministic test accounts" note at the top of the file / the PR discussion:
|
||||
# once the test wallet is restored from TEST_MNEMONIC, capture the ids it derives
|
||||
# and pin them here so amm-tokens.json and swap.mjs can reference known accounts.
|
||||
|
||||
# --- Token A ---
|
||||
TOKEN_A_NAME="TOKEN A"
|
||||
TOKEN_A_SUPPLY="1000000000000000000000"
|
||||
TOKEN_A_DEF="6gQMF38wEDPEnUamLmNqN8opss5xvr9w55eddddMmpEK" # --definition-target-account
|
||||
TOKEN_A_HOLDING="EF6c3VtgzUzpxfEKpvR3ZxsCch8y5YqazmWQu6Bybvyq" # --holding-target-account
|
||||
TOKEN_A_MINT_AUTH="EF6c3VtgzUzpxfEKpvR3ZxsCch8y5YqazmWQu6Bybvyq"
|
||||
|
||||
# --- Token B ---
|
||||
TOKEN_B_NAME="TOKEN B"
|
||||
TOKEN_B_SUPPLY="1000000000000000000000"
|
||||
TOKEN_B_DEF="Hw65ZimauFtHtvmDvWb24aWi1E6uRCifdyEn46Ei8wAc"
|
||||
TOKEN_B_HOLDING="L3hr1xABT3gkSYR1Fztu2smyJ1ftXcivjM8LguMjAsp"
|
||||
TOKEN_B_MINT_AUTH="L3hr1xABT3gkSYR1Fztu2smyJ1ftXcivjM8LguMjAsp"
|
||||
|
||||
# --- AMM / pool inputs ---
|
||||
AMM_AUTHORITY="EF6c3VtgzUzpxfEKpvR3ZxsCch8y5YqazmWQu6Bybvyq"
|
||||
USER_HOLDING_A="$TOKEN_A_HOLDING"
|
||||
USER_HOLDING_B="$TOKEN_B_HOLDING"
|
||||
USER_HOLDING_LP="7taJs6YpzBcWc5jiZcnZ817nU1G5WnQtBHskbcMDUc6A"
|
||||
CLOCK_ACCOUNT="4BdcjoXkq786TMWcBGGHqcxeLYMZmn17rL4eM9ZyRWNU"
|
||||
# --- Token metadata ---
|
||||
TOKEN_A_NAME="TOKEN A"; TOKEN_A_SYMBOL="TKA"; TOKEN_A_SUPPLY="1000000000000000000000"; TOKEN_A_DECIMALS=18
|
||||
TOKEN_B_NAME="TOKEN B"; TOKEN_B_SYMBOL="TKB"; TOKEN_B_SUPPLY="1000000000000000000000"; TOKEN_B_DECIMALS=18
|
||||
|
||||
# --- Pool inputs ---
|
||||
CLOCK_ACCOUNT="4BdcjoXkq786TMWcBGGHqcxeLYMZmn17rL4eM9ZyRWNU" # canonical LEZ system clock
|
||||
POOL_TOKEN_A_AMOUNT="10000"
|
||||
POOL_TOKEN_B_AMOUNT="10000"
|
||||
POOL_FEES="1"
|
||||
POOL_DEADLINE="18446744073709551615"
|
||||
|
||||
# Where the UI token config is written (git-ignored; consumed via TOKENS_CONFIG).
|
||||
TOKENS_CONFIG_OUT="apps/amm/amm-tokens.json"
|
||||
|
||||
###############################################################################
|
||||
# Helpers
|
||||
###############################################################################
|
||||
@@ -136,9 +129,6 @@ run_tx() {
|
||||
die "command exited with status $rc — $desc"
|
||||
fi
|
||||
|
||||
# The confirmation line printed by spel is:
|
||||
# ✅ Transaction confirmed — included in a block.
|
||||
# Match on the two stable substrings to be robust to emoji/dash encoding.
|
||||
if grep -q "Transaction confirmed" "$tmp" && grep -q "included in a block" "$tmp"; then
|
||||
log "${GRN}✅ CONFIRMED — included in a block: ${desc}${RST}"
|
||||
rm -f "$tmp"
|
||||
@@ -148,7 +138,7 @@ run_tx() {
|
||||
rm -f "$tmp"
|
||||
if [ "$mode" = "soft" ]; then
|
||||
log "${YEL}⚠ no '✅ Transaction confirmed — included in a block.' marker for: ${desc}"
|
||||
log " (continuing — 'wallet deploy-program' may not print the spel marker; verify manually)${RST}"
|
||||
log " (continuing — some commands don't print the spel marker; verify manually)${RST}"
|
||||
return 0
|
||||
fi
|
||||
die "NOT CONFIRMED — expected '✅ Transaction confirmed — included in a block.' for: $desc"
|
||||
@@ -171,8 +161,47 @@ program_id() {
|
||||
printf '%s' "$pid"
|
||||
}
|
||||
|
||||
# Resolve a wallet account id (bare base58) from its label. Deterministic under
|
||||
# the test mnemonic. Returns non-zero if the label isn't registered yet.
|
||||
acct_id() {
|
||||
local label="$1" out
|
||||
out="$(wallet account id --account-id "$label" 2>/dev/null)" || return 1
|
||||
printf '%s' "$out" | grep -oE '[1-9A-HJ-NP-Za-km-z]{32,44}' | head -n1
|
||||
}
|
||||
|
||||
# Restore the isolated test wallet from the fixed mnemonic and register the
|
||||
# deterministic accounts. `restore-keys` REWRITES storage (safe here — it's a
|
||||
# throwaway test home). Idempotent: skips accounts that already resolve.
|
||||
bootstrap_test_wallet() {
|
||||
sec "Bootstrap deterministic test wallet"
|
||||
kv "wallet home" "$TEST_WALLET_HOME"
|
||||
mkdir -p "$TEST_WALLET_HOME"
|
||||
|
||||
if [ -n "$TEST_SEQUENCER_ADDR" ]; then
|
||||
log "${DIM}\$ wallet config set sequencer_addr $TEST_SEQUENCER_ADDR${RST}"
|
||||
wallet config set sequencer_addr "$TEST_SEQUENCER_ADDR" \
|
||||
|| log "${YEL}⚠ 'wallet config set sequencer_addr' failed — configure the wallet manually.${RST}"
|
||||
fi
|
||||
|
||||
# restore-keys reads the mnemonic then the password from stdin.
|
||||
log "${DIM}\$ printf '<mnemonic>\\n<password>\\n' | wallet restore-keys --depth $TEST_WALLET_DEPTH${RST}"
|
||||
printf '%s\n%s\n' "$TEST_MNEMONIC" "$TEST_WALLET_PASSWORD" \
|
||||
| wallet restore-keys --depth "$TEST_WALLET_DEPTH" \
|
||||
|| die "wallet restore-keys failed"
|
||||
|
||||
local label
|
||||
for label in "${ACCOUNT_LABELS[@]}"; do
|
||||
if acct_id "$label" >/dev/null 2>&1; then
|
||||
kv "exists" "$label"
|
||||
else
|
||||
log "${DIM}\$ wallet account new public --label $label${RST}"
|
||||
wallet account new public --label "$label" || die "failed to create account: $label"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# 0. Preflight
|
||||
# 0. Preflight + wallet bootstrap
|
||||
###############################################################################
|
||||
sec "Preflight"
|
||||
require_cmd wallet
|
||||
@@ -181,26 +210,47 @@ require_cmd cargo
|
||||
require_file "$TOKEN_BIN"; require_file "$AMM_BIN"; require_file "$TWAP_BIN"
|
||||
require_file "$TOKEN_IDL"; require_file "$AMM_IDL"
|
||||
kv "repo root" "$REPO_ROOT"
|
||||
kv "test wallet home" "$TEST_WALLET_HOME"
|
||||
if [ ! -d "$TEST_WALLET_HOME" ]; then
|
||||
die "test wallet home not found: $TEST_WALLET_HOME
|
||||
Initialize a wallet there from the test mnemonic, then create/pin the TEST
|
||||
ACCOUNTS above. See docs/testnet-runbook.md §2. Mnemonic:
|
||||
\"$TEST_MNEMONIC\""
|
||||
kv "token bin" "$TOKEN_BIN"; kv "amm bin" "$AMM_BIN"; kv "twap bin" "$TWAP_BIN"
|
||||
|
||||
if [ ! -d "$TEST_WALLET_HOME" ] || [ "${FORCE_BOOTSTRAP:-0}" = "1" ]; then
|
||||
bootstrap_test_wallet
|
||||
else
|
||||
kv "test wallet" "reusing $TEST_WALLET_HOME (FORCE_BOOTSTRAP=1 to re-restore)"
|
||||
fi
|
||||
kv "token bin" "$TOKEN_BIN"
|
||||
kv "amm bin" "$AMM_BIN"
|
||||
kv "twap bin" "$TWAP_BIN"
|
||||
|
||||
###############################################################################
|
||||
# 1. Deploy programs
|
||||
# 1. Resolve the deterministic test accounts
|
||||
###############################################################################
|
||||
sec "Resolve deterministic test accounts (from the test mnemonic)"
|
||||
TOKEN_A_DEF="$(acct_id token-a-def)" || die "token-a-def not registered — run with FORCE_BOOTSTRAP=1"
|
||||
TOKEN_A_HOLDING="$(acct_id token-a-holding)" || die "token-a-holding not registered"
|
||||
TOKEN_B_DEF="$(acct_id token-b-def)" || die "token-b-def not registered"
|
||||
TOKEN_B_HOLDING="$(acct_id token-b-holding)" || die "token-b-holding not registered"
|
||||
USER_HOLDING_LP="$(acct_id lp-holding)" || die "lp-holding not registered"
|
||||
for v in TOKEN_A_DEF TOKEN_A_HOLDING TOKEN_B_DEF TOKEN_B_HOLDING USER_HOLDING_LP; do
|
||||
[ -n "${!v}" ] || die "failed to resolve account id for $v"
|
||||
done
|
||||
|
||||
# Derived roles (the input holding signs; mint authority == holding; authority is the A holding).
|
||||
TOKEN_A_MINT_AUTH="$TOKEN_A_HOLDING"; TOKEN_B_MINT_AUTH="$TOKEN_B_HOLDING"
|
||||
AMM_AUTHORITY="$TOKEN_A_HOLDING"
|
||||
USER_HOLDING_A="$TOKEN_A_HOLDING"; USER_HOLDING_B="$TOKEN_B_HOLDING"
|
||||
|
||||
kv "token-a-def" "$TOKEN_A_DEF"
|
||||
kv "token-a-holding" "$TOKEN_A_HOLDING"
|
||||
kv "token-b-def" "$TOKEN_B_DEF"
|
||||
kv "token-b-holding" "$TOKEN_B_HOLDING"
|
||||
kv "lp-holding" "$USER_HOLDING_LP"
|
||||
|
||||
###############################################################################
|
||||
# 2. Deploy programs
|
||||
###############################################################################
|
||||
run_tx soft "deploy token program" -- wallet deploy-program "$TOKEN_BIN"
|
||||
run_tx soft "deploy amm program" -- wallet deploy-program "$AMM_BIN"
|
||||
run_tx soft "deploy twap_oracle program" -- wallet deploy-program "$TWAP_BIN"
|
||||
|
||||
###############################################################################
|
||||
# 2. Derive program IDs
|
||||
# 3. Derive program IDs
|
||||
###############################################################################
|
||||
sec "Program IDs (derived from the deployed binaries)"
|
||||
TOKEN_PID="$(program_id "$TOKEN_BIN")"; kv "token program id" "$TOKEN_PID"
|
||||
@@ -208,7 +258,7 @@ AMM_PID="$(program_id "$AMM_BIN")"; kv "amm program id" "$AMM_PID"
|
||||
TWAP_PID="$(program_id "$TWAP_BIN")"; kv "twap program id" "$TWAP_PID"
|
||||
|
||||
###############################################################################
|
||||
# 3. Create token definitions (mint supply to the holding accounts)
|
||||
# 4. Create token definitions (mint supply to the holding accounts)
|
||||
###############################################################################
|
||||
run_tx strict "create fungible definition: $TOKEN_A_NAME" -- \
|
||||
spel --idl "$TOKEN_IDL" --program "$TOKEN_BIN" -- new-fungible-definition \
|
||||
@@ -225,7 +275,7 @@ run_tx strict "create fungible definition: $TOKEN_B_NAME" -- \
|
||||
--mint-authority "$TOKEN_B_MINT_AUTH"
|
||||
|
||||
###############################################################################
|
||||
# 4. Verify token definitions & holdings
|
||||
# 5. Verify token definitions & holdings
|
||||
###############################################################################
|
||||
inspect "$TOKEN_IDL" "$TOKEN_A_DEF" "TokenDefinition"
|
||||
inspect "$TOKEN_IDL" "$TOKEN_A_HOLDING" "TokenHolding"
|
||||
@@ -233,7 +283,7 @@ inspect "$TOKEN_IDL" "$TOKEN_B_DEF" "TokenDefinition"
|
||||
inspect "$TOKEN_IDL" "$TOKEN_B_HOLDING" "TokenHolding"
|
||||
|
||||
###############################################################################
|
||||
# 5. Derive AMM PDAs from the program ids + token pair
|
||||
# 6. Derive AMM PDAs from the program ids + token pair
|
||||
###############################################################################
|
||||
sec "Deriving AMM PDAs (amm_pdas example)"
|
||||
log "${DIM}\$ cargo run -q -p amm_program --example amm_pdas -- $AMM_PID $TWAP_PID $TOKEN_A_DEF $TOKEN_B_DEF${RST}"
|
||||
@@ -262,13 +312,9 @@ kv "vault_b" "$VAULT_B"
|
||||
kv "pool_definition_lp" "$POOL_LP"
|
||||
kv "lp_lock_holding" "$LP_LOCK"
|
||||
kv "current_tick_account" "$TICK"
|
||||
kv "user_holding_a" "$USER_HOLDING_A"
|
||||
kv "user_holding_b" "$USER_HOLDING_B"
|
||||
kv "user_holding_lp" "$USER_HOLDING_LP"
|
||||
kv "clock" "$CLOCK_ACCOUNT"
|
||||
|
||||
###############################################################################
|
||||
# 6. Initialize the AMM
|
||||
# 7. Initialize the AMM
|
||||
###############################################################################
|
||||
run_tx strict "initialize AMM config" -- \
|
||||
spel --idl "$AMM_IDL" --program "$AMM_BIN" -- initialize \
|
||||
@@ -278,7 +324,7 @@ run_tx strict "initialize AMM config" -- \
|
||||
--authority "$AMM_AUTHORITY"
|
||||
|
||||
###############################################################################
|
||||
# 7. Create the pool (seed initial liquidity)
|
||||
# 8. Create the pool (seed initial liquidity)
|
||||
###############################################################################
|
||||
run_tx strict "create pool + seed liquidity" -- \
|
||||
spel --idl "$AMM_IDL" --program "$AMM_BIN" -- new-definition \
|
||||
@@ -299,16 +345,40 @@ run_tx strict "create pool + seed liquidity" -- \
|
||||
--deadline "$POOL_DEADLINE"
|
||||
|
||||
###############################################################################
|
||||
# 8. Verify the pool
|
||||
# 9. Verify the pool
|
||||
###############################################################################
|
||||
inspect "$AMM_IDL" "$POOL" "PoolDefinition"
|
||||
|
||||
###############################################################################
|
||||
# 10. Write the UI token config from the deterministic accounts
|
||||
###############################################################################
|
||||
sec "Write UI token config -> $TOKENS_CONFIG_OUT"
|
||||
cat > "$TOKENS_CONFIG_OUT" <<JSON
|
||||
[
|
||||
{
|
||||
"symbol": "$TOKEN_A_SYMBOL",
|
||||
"name": "$TOKEN_A_NAME",
|
||||
"definitionId": "$TOKEN_A_DEF",
|
||||
"holding": "$TOKEN_A_HOLDING",
|
||||
"decimals": $TOKEN_A_DECIMALS
|
||||
},
|
||||
{
|
||||
"symbol": "$TOKEN_B_SYMBOL",
|
||||
"name": "$TOKEN_B_NAME",
|
||||
"definitionId": "$TOKEN_B_DEF",
|
||||
"holding": "$TOKEN_B_HOLDING",
|
||||
"decimals": $TOKEN_B_DECIMALS
|
||||
}
|
||||
]
|
||||
JSON
|
||||
kv "wrote" "$TOKENS_CONFIG_OUT"
|
||||
|
||||
sec "Done"
|
||||
log "${GRN}✅ Setup complete.${RST}"
|
||||
kv "AMM program id" "$AMM_PID"
|
||||
kv "TWAP program id" "$TWAP_PID"
|
||||
kv "pool" "$POOL"
|
||||
log ""
|
||||
log "For the UI / swap test, set:"
|
||||
log " ${DIM}AMM_PROGRAM_BIN=$REPO_ROOT/$AMM_BIN${RST}"
|
||||
log " ${DIM}TOKENS_CONFIG (apps/amm/amm-tokens.json with def ids $TOKEN_A_DEF / $TOKEN_B_DEF)${RST}"
|
||||
log "Launch the UI / run the swap test with:"
|
||||
log " ${DIM}export LEE_WALLET_HOME_DIR=$TEST_WALLET_HOME${RST}"
|
||||
log " ${DIM}AMM_PROGRAM_BIN=$REPO_ROOT/$AMM_BIN TOKENS_CONFIG=$REPO_ROOT/$TOKENS_CONFIG_OUT nix run .#amm-ui${RST}"
|
||||
|
||||
Reference in New Issue
Block a user