#!/bin/bash # 快速UTXO归集脚本 # 简化版本,用于快速归集所有notes到指定地址 set -e # 默认配置 DEFAULT_FEE=1 DEFAULT_MASTER_PUBKEY="33zmSubiizyAVzeSfKbVtLMKifm5u6VaTt9wae5K4CT6h5PLXovecjYwxwDXuzfKVsuefe1wh2VJVHAh4nbA53zBiXKf2Nc3fN3sVmZpmPWneUYGbWcXKzhmN714DVbzaS9U" # 颜色输出 GREEN='\033[0;32m' BLUE='\033[0;34m' NC='\033[0m' print_info() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } # 显示帮助 show_help() { echo "快速UTXO归集脚本" echo "" echo "用法: $0 [选项]" echo "" echo "选项:" echo " -m, --master-pubkey PUBKEY 主公钥地址 (默认: $DEFAULT_MASTER_PUBKEY)" echo " -r, --recipient PUBKEY 接收地址 (默认: 使用主公钥)" echo " -f, --fee FEE 手续费 (默认: $DEFAULT_FEE nicks)" echo " -h, --help 显示帮助" echo "" echo "示例:" echo " $0 # 归集所有notes到主公钥地址" echo " $0 --fee 2 # 使用2 nicks手续费" echo " $0 --recipient PUBKEY # 归集到指定地址" } # 解析参数 MASTER_PUBKEY="$DEFAULT_MASTER_PUBKEY" RECIPIENT="" FEE="$DEFAULT_FEE" while [[ $# -gt 0 ]]; do case $1 in -m|--master-pubkey) MASTER_PUBKEY="$2" shift 2 ;; -r|--recipient) RECIPIENT="$2" shift 2 ;; -f|--fee) FEE="$2" shift 2 ;; -h|--help) show_help exit 0 ;; *) echo "未知参数: $1" show_help exit 1 ;; esac done if [[ -z "$RECIPIENT" ]]; then RECIPIENT="$MASTER_PUBKEY" fi print_info "开始快速归集流程..." # 1. 扫描余额 print_info "扫描UTXO余额..." nockchain-wallet scan --master-pubkey "$MASTER_PUBKEY" # 2. 获取所有notes print_info "获取notes列表..." NOTES_OUTPUT=$(nockchain-wallet list-notes 2>&1 | strings) # 3. 解析notes并构建参数 NAMES="" RECIPIENTS="" GIFTS="" TOTAL_BALANCE=0 NOTE_COUNT=0 # 提取Name和Assets信息 # Name字段是跨行的,需要特殊处理,并保持完整的方括号格式 ASSETS_LINES=$(echo "$NOTES_OUTPUT" | grep "Assets:" | sed 's/.*Assets: \([0-9]*\).*/\1/') # 手动构建完整的note名称 NAMES_LINES="" while IFS= read -r line; do if [[ $line =~ Name: ]]; then # 提取前缀部分 (去掉 "- Name: [" 和行末的换行) prefix=$(echo "$line" | sed 's/^- Name: \[\(.*\)$/\1/' | sed 's/[[:space:]]*$//') # 读取下一行获取后缀部分 read -r next_line # 去掉后缀末尾的 "]" suffix=$(echo "$next_line" | sed 's/\]$//') # 构建完整的note名称: [prefix suffix] full_name="[$prefix $suffix]" NAMES_LINES+="$full_name"$'\n' fi done <<< "$NOTES_OUTPUT" # 将Name和Assets转换为数组(使用 mapfile 避免 set -e 下的 read -d 错误) mapfile -t NAMES_ARRAY < <(printf '%s\n' "$NAMES_LINES") mapfile -t ASSETS_ARRAY < <(printf '%s\n' "$ASSETS_LINES") if [[ ${#NAMES_ARRAY[@]} -eq 0 || ${#ASSETS_ARRAY[@]} -eq 0 ]]; then print_info "没有找到可归集的notes" exit 0 fi # 确保Name和Assets数组长度一致;不一致则截断至最短并给出警告 if [[ ${#NAMES_ARRAY[@]} -ne ${#ASSETS_ARRAY[@]} ]]; then min_len=${#NAMES_ARRAY[@]} if [[ ${#ASSETS_ARRAY[@]} -lt $min_len ]]; then min_len=${#ASSETS_ARRAY[@]} fi print_info "Name与Assets数量不一致,按最短长度 $min_len 截断继续" NAMES_ARRAY=("${NAMES_ARRAY[@]:0:$min_len}") ASSETS_ARRAY=("${ASSETS_ARRAY[@]:0:$min_len}") fi # 构建参数 for i in "${!NAMES_ARRAY[@]}"; do note_name="${NAMES_ARRAY[$i]}" balance="${ASSETS_ARRAY[$i]}" if [[ -n "$NAMES" ]]; then NAMES+="," RECIPIENTS+="," GIFTS+="," fi NAMES+="$note_name" RECIPIENTS+="[1 $RECIPIENT]" # 如果是最后一个note,需要扣除手续费 if [[ $i -eq $((${#NAMES_ARRAY[@]} - 1)) ]]; then if [[ $balance -lt $FEE ]]; then print_error "最后一个note '$note_name' 的余额 ($balance) 不足以支付手续费 ($FEE)" exit 1 fi # 从最后一个note扣除手续费 adjusted_balance=$((balance - FEE)) GIFTS+="$adjusted_balance" print_info "Note: $note_name, 余额: $balance nicks, 扣除手续费后: $adjusted_balance nicks" else GIFTS+="$balance" print_info "Note: $note_name, 余额: $balance nicks" fi TOTAL_BALANCE=$((TOTAL_BALANCE + balance)) NOTE_COUNT=$((NOTE_COUNT + 1)) done if [[ $NOTE_COUNT -eq 0 ]]; then print_info "没有找到可归集的notes" exit 0 fi print_info "找到 $NOTE_COUNT 个notes,总余额: $TOTAL_BALANCE nicks" # 4. 创建归集交易 print_info "创建归集交易..." print_info "归集到地址: $RECIPIENT" print_info "手续费: $FEE nicks" nockchain-wallet create-tx --names "$NAMES" --recipients "$RECIPIENTS" --gifts "$GIFTS" --fee "$FEE" print_success "归集完成!归集了 $NOTE_COUNT 个notes,总金额: $TOTAL_BALANCE nicks"