- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains - Omit embedded publish git dirs and empty placeholders from index Made-with: Cursor
165 lines
4.8 KiB
Bash
165 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
|
|
# shellcheck source=/dev/null
|
|
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh"
|
|
|
|
require_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || {
|
|
echo "[fail] missing required command: $1" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
require_cmd cast
|
|
require_cmd curl
|
|
require_cmd jq
|
|
require_cmd python3
|
|
|
|
RPC_URL="${RPC_URL_138:-https://rpc-http-pub.d-bis.org}"
|
|
BASE_URL="${BASE_URL:-https://explorer.d-bis.org/token-aggregation}"
|
|
PRIVATE_KEY="${PRIVATE_KEY:-}"
|
|
if [[ -z "${PRIVATE_KEY}" ]]; then
|
|
echo "[fail] PRIVATE_KEY is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SIGNER="$(cast wallet address --private-key "${PRIVATE_KEY}")"
|
|
USDT="${USDT_ADDRESS_138:-0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1}"
|
|
WETH="${WETH9_ADDRESS_138:-0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2}"
|
|
ROUTER="${ENHANCED_SWAP_ROUTER_V2_ADDRESS:-0xF1c93F54A5C2fc0d7766Ccb0Ad8f157DFB4C99Ce}"
|
|
APPROVE_TOTAL_RAW="${APPROVE_TOTAL_RAW:-2000000000}" # 2,000 USDT
|
|
if (( $# > 0 )); then
|
|
SIZES_USD=("$@")
|
|
else
|
|
SIZES_USD=(10 50 100 250 500 1000)
|
|
fi
|
|
|
|
bal_of() {
|
|
cast call "$1" 'balanceOf(address)(uint256)' "$SIGNER" --rpc-url "$RPC_URL" | awk '{print $1}'
|
|
}
|
|
|
|
fmt_amount() {
|
|
python3 - "$1" "$2" <<'PY'
|
|
from decimal import Decimal
|
|
import sys
|
|
raw = Decimal(sys.argv[1])
|
|
decimals = Decimal(10) ** Decimal(sys.argv[2])
|
|
print(raw / decimals)
|
|
PY
|
|
}
|
|
|
|
ensure_allowance() {
|
|
local current
|
|
current="$(cast call "$USDT" 'allowance(address,address)(uint256)' "$SIGNER" "$ROUTER" --rpc-url "$RPC_URL" | awk '{print $1}')"
|
|
if [[ "$current" =~ ^[0-9]+$ ]] && (( current >= APPROVE_TOTAL_RAW )); then
|
|
echo "[ok] router allowance already sufficient: $current"
|
|
return
|
|
fi
|
|
|
|
echo "[info] approving router for ${APPROVE_TOTAL_RAW} raw USDT"
|
|
cast send "$USDT" \
|
|
'approve(address,uint256)' \
|
|
"$ROUTER" "$APPROVE_TOTAL_RAW" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--legacy \
|
|
--json | jq -r '.transactionHash'
|
|
}
|
|
|
|
build_plan() {
|
|
local amount_in_raw="$1"
|
|
curl -fsS \
|
|
-H 'content-type: application/json' \
|
|
-X POST \
|
|
--data "{\"sourceChainId\":138,\"tokenIn\":\"${USDT}\",\"tokenOut\":\"${WETH}\",\"amountIn\":\"${amount_in_raw}\"}" \
|
|
"${BASE_URL}/api/v2/routes/internal-execution-plan"
|
|
}
|
|
|
|
run_swap() {
|
|
local usd="$1"
|
|
local amount_in_raw=$(( usd * 1000000 ))
|
|
local plan provider contract calldata estimated min_out pre_usdt pre_weth tx_hash status post_usdt post_weth actual_usdt actual_weth
|
|
|
|
echo
|
|
echo "== ${usd} USDT -> WETH =="
|
|
|
|
plan="$(build_plan "$amount_in_raw")"
|
|
provider="$(printf '%s\n' "$plan" | jq -r '.plannerResponse.legs[0].provider // .plannerResponse.routePlan.legs[0].provider // "unknown"')"
|
|
contract="$(printf '%s\n' "$plan" | jq -r '.execution.contractAddress // .execution.target')"
|
|
calldata="$(printf '%s\n' "$plan" | jq -r '.execution.encodedCalldata')"
|
|
estimated="$(printf '%s\n' "$plan" | jq -r '.plannerResponse.estimatedAmountOut')"
|
|
min_out="$(printf '%s\n' "$plan" | jq -r '.plannerResponse.minAmountOut')"
|
|
|
|
[[ -n "$contract" && "$contract" != "null" ]] || {
|
|
echo "[fail] planner did not return contract address" >&2
|
|
exit 1
|
|
}
|
|
[[ -n "$calldata" && "$calldata" != "null" ]] || {
|
|
echo "[fail] planner did not return executable calldata" >&2
|
|
exit 1
|
|
}
|
|
|
|
pre_usdt="$(bal_of "$USDT")"
|
|
pre_weth="$(bal_of "$WETH")"
|
|
|
|
tx_hash="$(
|
|
cast send "$contract" \
|
|
"$calldata" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--legacy \
|
|
--json | jq -r '.transactionHash'
|
|
)"
|
|
|
|
status="$(cast receipt "$tx_hash" --rpc-url "$RPC_URL" --json | jq -r '.status')"
|
|
if [[ "$status" != "1" && "$status" != "0x1" ]]; then
|
|
echo "[fail] tx reverted: $tx_hash" >&2
|
|
exit 1
|
|
fi
|
|
|
|
post_usdt="$(bal_of "$USDT")"
|
|
post_weth="$(bal_of "$WETH")"
|
|
actual_usdt=$(( pre_usdt - post_usdt ))
|
|
actual_weth=$(( post_weth - pre_weth ))
|
|
|
|
jq -n \
|
|
--arg usd "$usd" \
|
|
--arg provider "$provider" \
|
|
--arg contract "$contract" \
|
|
--arg tx_hash "$tx_hash" \
|
|
--arg amount_in_raw "$amount_in_raw" \
|
|
--arg estimated "$estimated" \
|
|
--arg min_out "$min_out" \
|
|
--arg actual_usdt "$actual_usdt" \
|
|
--arg actual_weth "$actual_weth" \
|
|
--arg actual_usdt_fmt "$(fmt_amount "$actual_usdt" 6)" \
|
|
--arg actual_weth_fmt "$(fmt_amount "$actual_weth" 18)" \
|
|
'{
|
|
usdNotional: ($usd | tonumber),
|
|
provider: $provider,
|
|
contract: $contract,
|
|
txHash: $tx_hash,
|
|
amountInRaw: $amount_in_raw,
|
|
estimatedAmountOutRaw: $estimated,
|
|
minAmountOutRaw: $min_out,
|
|
actualAmountInRaw: $actual_usdt,
|
|
actualAmountOutRaw: $actual_weth,
|
|
actualAmountIn: $actual_usdt_fmt,
|
|
actualAmountOut: $actual_weth_fmt
|
|
}'
|
|
}
|
|
|
|
echo "Signer: ${SIGNER}"
|
|
echo "RPC: ${RPC_URL}"
|
|
echo "Base: ${BASE_URL}"
|
|
|
|
ensure_allowance
|
|
|
|
for usd in "${SIZES_USD[@]}"; do
|
|
run_swap "$usd"
|
|
done
|