|
|
@@ -1,284 +0,0 @@
|
|
|
-#!/bin/bash
|
|
|
-
|
|
|
-# UTXO归集脚本
|
|
|
-# 用于归集多个UTXO币到指定地址
|
|
|
-
|
|
|
-set -e # 遇到错误时退出
|
|
|
-
|
|
|
-# 默认配置
|
|
|
-DEFAULT_FEE=1
|
|
|
-DEFAULT_MASTER_PUBKEY="33zmSubiizyAVzeSfKbVtLMKifm5u6VaTt9wae5K4CT6h5PLXovecjYwxwDXuzfKVsuefe1wh2VJVHAh4nbA53zBiXKf2Nc3fN3sVmZpmPWneUYGbWcXKzhmN714DVbzaS9U"
|
|
|
-
|
|
|
-# 颜色输出
|
|
|
-RED='\033[0;31m'
|
|
|
-GREEN='\033[0;32m'
|
|
|
-YELLOW='\033[1;33m'
|
|
|
-BLUE='\033[0;34m'
|
|
|
-NC='\033[0m' # No Color
|
|
|
-
|
|
|
-# 打印带颜色的消息
|
|
|
-print_info() {
|
|
|
- echo -e "${BLUE}[INFO]${NC} $1"
|
|
|
-}
|
|
|
-
|
|
|
-print_success() {
|
|
|
- echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
|
-}
|
|
|
-
|
|
|
-print_warning() {
|
|
|
- echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
|
-}
|
|
|
-
|
|
|
-print_error() {
|
|
|
- echo -e "${RED}[ERROR]${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 " -n, --names NAMES 要归集的note名称,用逗号分隔"
|
|
|
- echo " -s, --scan-only 仅扫描余额,不执行归集"
|
|
|
- echo " -l, --list-only 仅列出notes,不执行归集"
|
|
|
- echo " -h, --help 显示此帮助信息"
|
|
|
- echo ""
|
|
|
- echo "示例:"
|
|
|
- echo " $0 --scan-only # 仅扫描余额"
|
|
|
- echo " $0 --list-only # 仅列出notes"
|
|
|
- echo " $0 --names \"note1,note2\" --fee 2 # 归集指定notes"
|
|
|
- echo " $0 --names \"note1,note2\" --recipient PUBKEY # 归集到指定地址"
|
|
|
-}
|
|
|
-
|
|
|
-# 解析命令行参数
|
|
|
-MASTER_PUBKEY="$DEFAULT_MASTER_PUBKEY"
|
|
|
-RECIPIENT=""
|
|
|
-FEE="$DEFAULT_FEE"
|
|
|
-NAMES=""
|
|
|
-SCAN_ONLY=false
|
|
|
-LIST_ONLY=false
|
|
|
-
|
|
|
-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
|
|
|
- ;;
|
|
|
- -n|--names)
|
|
|
- NAMES="$2"
|
|
|
- shift 2
|
|
|
- ;;
|
|
|
- -s|--scan-only)
|
|
|
- SCAN_ONLY=true
|
|
|
- shift
|
|
|
- ;;
|
|
|
- -l|--list-only)
|
|
|
- LIST_ONLY=true
|
|
|
- shift
|
|
|
- ;;
|
|
|
- -h|--help)
|
|
|
- show_help
|
|
|
- exit 0
|
|
|
- ;;
|
|
|
- *)
|
|
|
- print_error "未知参数: $1"
|
|
|
- show_help
|
|
|
- exit 1
|
|
|
- ;;
|
|
|
- esac
|
|
|
-done
|
|
|
-
|
|
|
-# 如果没有指定接收地址,使用主公钥
|
|
|
-if [[ -z "$RECIPIENT" ]]; then
|
|
|
- RECIPIENT="$MASTER_PUBKEY"
|
|
|
-fi
|
|
|
-
|
|
|
-print_info "开始UTXO归集流程..."
|
|
|
-print_info "主公钥: $MASTER_PUBKEY"
|
|
|
-print_info "接收地址: $RECIPIENT"
|
|
|
-print_info "手续费: $FEE nicks"
|
|
|
-
|
|
|
-# 步骤1: 扫描并更新本地UTXO余额
|
|
|
-print_info "步骤1: 扫描并更新本地UTXO余额..."
|
|
|
-if nockchain-wallet scan --master-pubkey "$MASTER_PUBKEY"; then
|
|
|
- print_success "UTXO余额扫描完成"
|
|
|
-else
|
|
|
- print_error "UTXO余额扫描失败"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-# 步骤2: 列出所有notes
|
|
|
-print_info "步骤2: 列出所有notes..."
|
|
|
-NOTES_OUTPUT=$(nockchain-wallet list-notes)
|
|
|
-if [[ $? -eq 0 ]]; then
|
|
|
- print_success "Notes列表获取成功"
|
|
|
- echo "$NOTES_OUTPUT"
|
|
|
-else
|
|
|
- print_error "获取notes列表失败"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-# 如果只是扫描或列出,则退出
|
|
|
-if [[ "$SCAN_ONLY" == true || "$LIST_ONLY" == true ]]; then
|
|
|
- print_success "操作完成"
|
|
|
- exit 0
|
|
|
-fi
|
|
|
-
|
|
|
-# 步骤3: 验证参数
|
|
|
-if [[ -z "$NAMES" ]]; then
|
|
|
- print_error "请指定要归集的note名称 (使用 --names 参数)"
|
|
|
- echo ""
|
|
|
- print_info "可用的notes:"
|
|
|
- echo "$NOTES_OUTPUT"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-# 步骤4: 解析note名称和余额
|
|
|
-print_info "步骤3: 解析note信息..."
|
|
|
-IFS=',' read -ra NOTE_ARRAY <<< "$NAMES"
|
|
|
-NOTE_COUNT=${#NOTE_ARRAY[@]}
|
|
|
-
|
|
|
-if [[ $NOTE_COUNT -lt 2 ]]; then
|
|
|
- print_error "归集需要至少2个notes"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-print_info "准备归集 $NOTE_COUNT 个notes: ${NOTE_ARRAY[*]}"
|
|
|
-
|
|
|
-# 从notes输出中提取余额信息
|
|
|
-declare -A NOTE_BALANCES
|
|
|
-
|
|
|
-# 使用更简单的方法提取Name和Assets
|
|
|
-NOTES_OUTPUT_CLEAN=$(echo "$NOTES_OUTPUT" | strings)
|
|
|
-ASSETS_LINES=$(echo "$NOTES_OUTPUT_CLEAN" | 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_CLEAN"
|
|
|
-
|
|
|
-# 将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[@]} -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
|
|
|
-
|
|
|
-# 构建NOTE_BALANCES关联数组
|
|
|
-for i in "${!NAMES_ARRAY[@]}"; do
|
|
|
- note_name="${NAMES_ARRAY[$i]}"
|
|
|
- balance="${ASSETS_ARRAY[$i]}"
|
|
|
- NOTE_BALANCES["$note_name"]="$balance"
|
|
|
- print_info "Note: $note_name, 余额: $balance nicks"
|
|
|
-done
|
|
|
-
|
|
|
-# 验证所有指定的notes都存在
|
|
|
-MISSING_NOTES=()
|
|
|
-for note in "${NOTE_ARRAY[@]}"; do
|
|
|
- if [[ -z "${NOTE_BALANCES[$note]}" ]]; then
|
|
|
- MISSING_NOTES+=("$note")
|
|
|
- fi
|
|
|
-done
|
|
|
-
|
|
|
-if [[ ${#MISSING_NOTES[@]} -gt 0 ]]; then
|
|
|
- print_error "以下notes不存在: ${MISSING_NOTES[*]}"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-# 步骤5: 计算总余额和构建参数
|
|
|
-print_info "步骤4: 计算归集参数..."
|
|
|
-
|
|
|
-# 构建names参数
|
|
|
-NAMES_PARAM=$(IFS=','; echo "${NOTE_ARRAY[*]}")
|
|
|
-
|
|
|
-# 构建recipients参数 (所有余额都发送到同一个地址)
|
|
|
-RECIPIENTS_PARAM=""
|
|
|
-GIFTS_PARAM=""
|
|
|
-TOTAL_BALANCE=0
|
|
|
-
|
|
|
-for i in "${!NOTE_ARRAY[@]}"; do
|
|
|
- note="${NOTE_ARRAY[$i]}"
|
|
|
- balance="${NOTE_BALANCES[$note]}"
|
|
|
- TOTAL_BALANCE=$((TOTAL_BALANCE + balance))
|
|
|
-
|
|
|
- if [[ -n "$RECIPIENTS_PARAM" ]]; then
|
|
|
- RECIPIENTS_PARAM+=","
|
|
|
- GIFTS_PARAM+=","
|
|
|
- fi
|
|
|
- RECIPIENTS_PARAM+="[1 $RECIPIENT]"
|
|
|
-
|
|
|
- # 如果是最后一个note,需要扣除手续费
|
|
|
- if [[ $i -eq $((${#NOTE_ARRAY[@]} - 1)) ]]; then
|
|
|
- if [[ $balance -lt $FEE ]]; then
|
|
|
- print_error "最后一个note '$note' 的余额 ($balance) 不足以支付手续费 ($FEE)"
|
|
|
- exit 1
|
|
|
- fi
|
|
|
- # 从最后一个note扣除手续费
|
|
|
- adjusted_balance=$((balance - FEE))
|
|
|
- GIFTS_PARAM+="$adjusted_balance"
|
|
|
- print_info "Note: $note, 余额: $balance nicks, 扣除手续费后: $adjusted_balance nicks"
|
|
|
- else
|
|
|
- GIFTS_PARAM+="$balance"
|
|
|
- print_info "Note: $note, 余额: $balance nicks"
|
|
|
- fi
|
|
|
-done
|
|
|
-
|
|
|
-print_info "总余额: $TOTAL_BALANCE nicks"
|
|
|
-print_info "手续费: $FEE nicks (从最后一个note扣除)"
|
|
|
-print_info "实际归集金额: $((TOTAL_BALANCE - FEE)) nicks"
|
|
|
-
|
|
|
-# 验证最后一个note的余额是否足够支付手续费
|
|
|
-LAST_NOTE="${NOTE_ARRAY[-1]}"
|
|
|
-LAST_NOTE_BALANCE="${NOTE_BALANCES[$LAST_NOTE]}"
|
|
|
-if [[ $LAST_NOTE_BALANCE -lt $FEE ]]; then
|
|
|
- print_error "最后一个note '$LAST_NOTE' 的余额 ($LAST_NOTE_BALANCE) 不足以支付手续费 ($FEE)"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-# 步骤6: 创建归集交易
|
|
|
-print_info "步骤5: 创建归集交易..."
|
|
|
-print_info "执行命令: nockchain-wallet create-tx --names \"$NAMES_PARAM\" --recipients \"$RECIPIENTS_PARAM\" --gifts \"$GIFTS_PARAM\" --fee $FEE"
|
|
|
-
|
|
|
-if nockchain-wallet create-tx --names "$NAMES_PARAM" --recipients "$RECIPIENTS_PARAM" --gifts "$GIFTS_PARAM" --fee "$FEE"; then
|
|
|
- print_success "归集交易创建成功!"
|
|
|
- print_success "归集了 $NOTE_COUNT 个notes,总金额: $TOTAL_BALANCE nicks"
|
|
|
- print_success "手续费: $FEE nicks"
|
|
|
- print_success "实际归集到地址: $RECIPIENT"
|
|
|
-else
|
|
|
- print_error "归集交易创建失败"
|
|
|
- exit 1
|
|
|
-fi
|
|
|
-
|
|
|
-print_success "UTXO归集流程完成!"
|