|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +set -euo pipefail |
| 4 | + |
| 5 | +GREEN='\033[0;32m' |
| 6 | +BLUE='\033[0;34m' |
| 7 | +YELLOW='\033[1;33m' |
| 8 | +RED='\033[0;31m' |
| 9 | +NC='\033[0m' |
| 10 | + |
| 11 | +echo -e "${BLUE}╔══════════════════════════════════════════════════════════╗${NC}" |
| 12 | +echo -e "${BLUE}║ Auto-Register Tide -> Auto Rebalance (Two-Terminal) ║${NC}" |
| 13 | +echo -e "${BLUE}╚══════════════════════════════════════════════════════════╝${NC}" |
| 14 | +echo "" |
| 15 | + |
| 16 | +# 0) Wait for emulator |
| 17 | +echo -e "${BLUE}Waiting for emulator (3569) to be ready...${NC}" |
| 18 | +for i in {1..30}; do |
| 19 | + if nc -z 127.0.0.1 3569; then |
| 20 | + echo -e "${GREEN}Emulator ready.${NC}" |
| 21 | + break |
| 22 | + fi |
| 23 | + sleep 1 |
| 24 | +done |
| 25 | +nc -z 127.0.0.1 3569 || { echo -e "${RED}Emulator not detected on port 3569${NC}"; exit 1; } |
| 26 | + |
| 27 | +# 1) Minimal idempotent setup |
| 28 | +echo -e "${BLUE}Granting FlowVaults beta to tidal...${NC}" |
| 29 | +flow transactions send cadence/transactions/flow-vaults/admin/grant_beta.cdc \ |
| 30 | + --network emulator \ |
| 31 | + --payer tidal --proposer tidal \ |
| 32 | + --authorizer tidal --authorizer tidal >/dev/null || true |
| 33 | + |
| 34 | +echo -e "${BLUE}Setting up SchedulerManager...${NC}" |
| 35 | +flow transactions send cadence/transactions/flow-vaults/setup_scheduler_manager.cdc \ |
| 36 | + --network emulator --signer tidal >/dev/null || true |
| 37 | + |
| 38 | +echo -e "${BLUE}Setting up Supervisor...${NC}" |
| 39 | +flow transactions send cadence/transactions/flow-vaults/setup_supervisor.cdc \ |
| 40 | + --network emulator --signer tidal >/dev/null || true |
| 41 | + |
| 42 | +# Capture initial block height |
| 43 | +START_HEIGHT=$(flow blocks get latest 2>/dev/null | grep -i -E 'Height|Block Height' | grep -oE '[0-9]+' | head -1) |
| 44 | +START_HEIGHT=${START_HEIGHT:-0} |
| 45 | + |
| 46 | +# 2) Schedule Supervisor once (soon) to seed first child jobs for newly created Tide |
| 47 | +FUTURE=$(python - <<'PY' |
| 48 | +import time; print(f"{time.time()+10:.1f}") |
| 49 | +PY |
| 50 | +) |
| 51 | +echo -e "${BLUE}Estimating fee for supervisor schedule at ${FUTURE}...${NC}" |
| 52 | +EST=$(flow scripts execute cadence/scripts/flow-vaults/estimate_rebalancing_cost.cdc --network emulator \ |
| 53 | + --args-json "[{\"type\":\"UFix64\",\"value\":\"$FUTURE\"},{\"type\":\"UInt8\",\"value\":\"1\"},{\"type\":\"UInt64\",\"value\":\"800\"}]" | grep -oE 'flowFee: [0-9]+\\.[0-9]+' | awk '{print $2}') |
| 54 | +FEE=$(python - <<PY |
| 55 | +f=float("$EST") if "$EST" else 0.00005 |
| 56 | +print(f"{f+0.00001:.8f}") |
| 57 | +PY |
| 58 | +) |
| 59 | +SUP_JSON="[\ |
| 60 | + {\"type\":\"UFix64\",\"value\":\"$FUTURE\"},\ |
| 61 | + {\"type\":\"UInt8\",\"value\":\"1\"},\ |
| 62 | + {\"type\":\"UInt64\",\"value\":\"800\"},\ |
| 63 | + {\"type\":\"UFix64\",\"value\":\"$FEE\"},\ |
| 64 | + {\"type\":\"UFix64\",\"value\":\"60.0\"},\ |
| 65 | + {\"type\":\"Bool\",\"value\":true},\ |
| 66 | + {\"type\":\"UFix64\",\"value\":\"300.0\"},\ |
| 67 | + {\"type\":\"Bool\",\"value\":false}\ |
| 68 | +]" |
| 69 | +echo -e "${BLUE}Scheduling Supervisor once...${NC}" |
| 70 | +flow transactions send cadence/transactions/flow-vaults/schedule_supervisor.cdc \ |
| 71 | + --network emulator --signer tidal --args-json "$SUP_JSON" >/dev/null |
| 72 | + |
| 73 | +# 3) Record existing tide IDs, then create a new tide (auto-register happens inside the transaction) |
| 74 | +echo -e "${BLUE}Fetching existing tide IDs...${NC}" |
| 75 | +BEFORE_IDS=$(flow scripts execute cadence/scripts/flow-vaults/get_tide_ids.cdc \ |
| 76 | + --network emulator \ |
| 77 | + --args-json '[{"type":"Address","value":"0x045a1763c93006ca"}]' | grep -oE '\[[^]]*\]' | tr -d '[] ' || true) |
| 78 | + |
| 79 | +echo -e "${BLUE}Creating a new tide (100 FLOW) - auto-register will run inside...${NC}" |
| 80 | +flow transactions send cadence/transactions/flow-vaults/create_tide.cdc \ |
| 81 | + --network emulator --signer tidal \ |
| 82 | + --args-json '[{"type":"String","value":"A.045a1763c93006ca.FlowVaultsStrategies.TracerStrategy"},{"type":"String","value":"A.0ae53cb6e3f42a79.FlowToken.Vault"},{"type":"UFix64","value":"100.0"}]' >/dev/null |
| 83 | + |
| 84 | +AFTER_IDS=$(flow scripts execute cadence/scripts/flow-vaults/get_tide_ids.cdc \ |
| 85 | + --network emulator \ |
| 86 | + --args-json '[{"type":"Address","value":"0x045a1763c93006ca"}]' | grep -oE '\[[^]]*\]' | tr -d '[] ' || true) |
| 87 | + |
| 88 | +# Determine new tide ID |
| 89 | +NEW_TIDE_ID="" |
| 90 | +for id in $(echo "$AFTER_IDS" | tr ',' ' '); do |
| 91 | + if ! echo "$BEFORE_IDS" | tr ',' ' ' | tr -s ' ' | grep -qw "$id"; then |
| 92 | + NEW_TIDE_ID="$id" |
| 93 | + break |
| 94 | + fi |
| 95 | +done |
| 96 | +if [[ -z "${NEW_TIDE_ID}" ]]; then |
| 97 | + # fallback: choose the max id |
| 98 | + NEW_TIDE_ID=$(echo "$AFTER_IDS" | tr ',' ' ' | xargs -n1 | sort -n | tail -1) |
| 99 | +fi |
| 100 | +echo -e "${GREEN}New Tide ID: ${NEW_TIDE_ID}${NC}" |
| 101 | +[[ -n "${NEW_TIDE_ID}" ]] || { echo -e "${RED}Could not determine new Tide ID.${NC}"; exit 1; } |
| 102 | + |
| 103 | +# 4) Initial metrics for the new tide |
| 104 | +echo -e "${BLUE}Initial metrics for tide ${NEW_TIDE_ID}:${NC}" |
| 105 | +INIT_BAL=$(flow scripts execute cadence/scripts/flow-vaults/get_auto_balancer_balance_by_id.cdc \ |
| 106 | + --network emulator --args-json "[{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]") |
| 107 | +INIT_VAL=$(flow scripts execute cadence/scripts/flow-vaults/get_auto_balancer_current_value_by_id.cdc \ |
| 108 | + --network emulator --args-json "[{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]") |
| 109 | +INIT_TBAL=$(flow scripts execute cadence/scripts/flow-vaults/get_tide_balance.cdc \ |
| 110 | + --network emulator --args-json "[{\"type\":\"Address\",\"value\":\"0x045a1763c93006ca\"},{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]") |
| 111 | +echo -e "${BLUE} bal=${INIT_BAL}${NC}" |
| 112 | +echo -e "${BLUE} val=${INIT_VAL}${NC}" |
| 113 | +echo -e "${BLUE} tideBal=${INIT_TBAL}${NC}" |
| 114 | + |
| 115 | +# 5) Price drift so that rebalance is needed |
| 116 | +echo -e "${BLUE}Changing FLOW & YIELD prices to induce drift...${NC}" |
| 117 | +flow transactions send cadence/transactions/mocks/oracle/set_price.cdc \ |
| 118 | + 'A.0ae53cb6e3f42a79.FlowToken.Vault' 1.8 --signer tidal >/dev/null |
| 119 | +flow transactions send cadence/transactions/mocks/oracle/set_price.cdc \ |
| 120 | + 'A.045a1763c93006ca.YieldToken.Vault' 1.5 --signer tidal >/dev/null |
| 121 | + |
| 122 | +# 6) Wait for Supervisor to run and seed the child schedule; then poll child scheduled tx |
| 123 | +echo -e "${BLUE}Waiting for Supervisor execution and child schedule...${NC}" |
| 124 | + |
| 125 | +SCHED_ID="" |
| 126 | +for i in {1..30}; do |
| 127 | + INFO=$(flow scripts execute cadence/scripts/flow-vaults/get_scheduled_rebalancing.cdc \ |
| 128 | + --network emulator \ |
| 129 | + --args-json "[{\"type\":\"Address\",\"value\":\"0x045a1763c93006ca\"},{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]" 2>/dev/null || true) |
| 130 | + SCHED_ID=$(echo "${INFO}" | awk -F'scheduledTransactionID: ' '/scheduledTransactionID: /{print $2}' | awk -F',' '{print $1}' | tr -cd '0-9') |
| 131 | + if [[ -n "${SCHED_ID}" ]]; then |
| 132 | + break |
| 133 | + fi |
| 134 | + sleep 1 |
| 135 | +done |
| 136 | + |
| 137 | +if [[ -z "${SCHED_ID}" ]]; then |
| 138 | + echo -e "${RED}Child schedule for tide ${NEW_TIDE_ID} was not created by Supervisor within timeout.${NC}" |
| 139 | + exit 1 |
| 140 | +fi |
| 141 | +echo -e "${GREEN}Child Scheduled Tx ID for tide ${NEW_TIDE_ID}: ${SCHED_ID}${NC}" |
| 142 | + |
| 143 | +# 7) Poll scheduled tx status to executed or nil, then verify on-chain proof and movement |
| 144 | +STATUS_NIL_OK=0 |
| 145 | +STATUS_RAW="" |
| 146 | +for i in {1..45}; do |
| 147 | + STATUS_RAW=$((flow scripts execute cadence/scripts/flow-vaults/get_scheduled_tx_status.cdc \ |
| 148 | + --network emulator \ |
| 149 | + --args-json "[{\"type\":\"UInt64\",\"value\":\"$SCHED_ID\"}]" 2>/dev/null | tr -d '\n' | grep -oE 'rawValue: [0-9]+' | awk '{print $2}') || true) |
| 150 | + if [[ -z "${STATUS_RAW}" ]]; then |
| 151 | + echo -e "${GREEN}Status: nil (likely removed after execution)${NC}" |
| 152 | + STATUS_NIL_OK=1 |
| 153 | + break |
| 154 | + fi |
| 155 | + echo -e "${BLUE}Status rawValue: ${STATUS_RAW}${NC}" |
| 156 | + if [[ "${STATUS_RAW}" == "2" ]]; then |
| 157 | + echo -e "${GREEN}Scheduled transaction executed.${NC}" |
| 158 | + break |
| 159 | + fi |
| 160 | + sleep 1 |
| 161 | +done |
| 162 | +
|
| 163 | +END_HEIGHT=$(flow blocks get latest 2>/dev/null | grep -i -E 'Height|Block Height' | grep -oE '[0-9]+' | head -1) |
| 164 | +END_HEIGHT=${END_HEIGHT:-$START_HEIGHT} |
| 165 | +EXEC_EVENTS_COUNT=$(flow events get A.f8d6e0586b0a20c7.FlowTransactionScheduler.Executed --start ${START_HEIGHT} --end ${END_HEIGHT} 2>/dev/null | grep -c "A.f8d6e0586b0a20c7.FlowTransactionScheduler.Executed" || true) |
| 166 | +
|
| 167 | +OC_RES=$(flow scripts execute cadence/scripts/flow-vaults/was_rebalancing_executed.cdc \ |
| 168 | + --network emulator \ |
| 169 | + --args-json "[{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"},{\"type\":\"UInt64\",\"value\":\"$SCHED_ID\"}]" 2>/dev/null | tr -d '\n') |
| 170 | +echo -e "${BLUE}On-chain executed proof for ${SCHED_ID}: ${OC_RES}${NC}" |
| 171 | +OC_OK=0; [[ "$OC_RES" =~ "Result: true" ]] && OC_OK=1 |
| 172 | +
|
| 173 | +if [[ "${STATUS_RAW:-}" != "2" && "${EXEC_EVENTS_COUNT:-0}" -eq 0 && "${STATUS_NIL_OK:-0}" -eq 0 && "${OC_OK:-0}" -eq 0 ]]; then |
| 174 | + echo -e "${RED}FAIL: No proof that scheduled tx executed (status/event/on-chain).${NC}" |
| 175 | + exit 1 |
| 176 | +fi |
| 177 | +
|
| 178 | +FINAL_BAL=$(flow scripts execute cadence/scripts/flow-vaults/get_auto_balancer_balance_by_id.cdc \ |
| 179 | + --network emulator --args-json "[{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]") |
| 180 | +FINAL_VAL=$(flow scripts execute cadence/scripts/flow-vaults/get_auto_balancer_current_value_by_id.cdc \ |
| 181 | + --network emulator --args-json "[{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]") |
| 182 | +FINAL_TBAL=$(flow scripts execute cadence/scripts/flow-vaults/get_tide_balance.cdc \ |
| 183 | + --network emulator --args-json "[{\"type\":\"Address\",\"value\":\"0x045a1763c93006ca\"},{\"type\":\"UInt64\",\"value\":\"$NEW_TIDE_ID\"}]") |
| 184 | +
|
| 185 | +extract_val() { printf "%s" "$1" | grep -oE 'Result: [^[:space:]]+' | awk '{print $2}'; } |
| 186 | +IB=$(extract_val "${INIT_BAL}"); FB=$(extract_val "${FINAL_BAL}") |
| 187 | +IV=$(extract_val "${INIT_VAL}"); FV=$(extract_val "${FINAL_VAL}") |
| 188 | +ITB=$(extract_val "${INIT_TBAL}"); FTB=$(extract_val "${FINAL_TBAL}") |
| 189 | +
|
| 190 | +REB_CNT=$(flow events get A.045a1763c93006ca.DeFiActions.Rebalanced --start ${START_HEIGHT} --end ${END_HEIGHT} 2>/dev/null | grep -c "A.045a1763c93006ca.DeFiActions.Rebalanced" || true) |
| 191 | +if [[ "${IB}" == "${FB}" && "${IV}" == "${FV}" && "${ITB}" == "${FTB}" && "${REB_CNT:-0}" -eq 0 ]]; then |
| 192 | + echo -e "${RED}FAIL: No asset movement detected after rebalance.${NC}" |
| 193 | + echo -e "${BLUE}Initial bal=${INIT_BAL} val=${INIT_VAL} tideBal=${INIT_TBAL}${NC}" |
| 194 | + echo -e "${BLUE}Final bal=${FINAL_BAL} val=${FINAL_VAL} tideBal=${FINAL_TBAL}${NC}" |
| 195 | + exit 1 |
| 196 | +fi |
| 197 | +
|
| 198 | +echo -e "${GREEN}PASS: Auto-register + Supervisor seeded first rebalance, and movement occurred for tide ${NEW_TIDE_ID}.${NC}" |
| 199 | +
|
| 200 | +
|
0 commit comments