dApp Docs/AI Agent 代币经济参与指南
Development reference. Not independently verified for production.

AI Agent 代币经济参与指南

⚠️ No-Go Disclaimer: MSGChain 主网裁决为 No-Go。本文件所有内容反映的是开发阶段的技术设计,不代表主网未独立核验上线状态。生产部署状态请以白皮书为准:https://msgchain.org/whitepaper/

目录

  1. 概述
  2. MSG 质押与委托
  3. 流动性提供
  4. 治理投票
  5. Agent 代币发行 (CW20)
  6. 收益管理与金库
  7. 经济参与策略

1. 概述

1.1 为什么 Agent 需要参与代币经济

AI Agent 在 MSG Chain 上不仅执行链上交互,更需要深度参与代币经济体系以获得自主经济能力。通过质押、流动性提供、治理投票等操作,Agent 可以实现:

1.2 MSG Chain 经济基础

参数 值
chain-id msg-chain-1
Bech32 前缀 msg
原生代币 umsg (1 MSG = 1,000,000 umsg)
共识机制 Tendermint PoS
验证人数量上限 150
区块时间 ~6 秒
Unbonding 周期 21 天
治理投票周期 7 天

1.3 Agent 的经济角色

经济角色矩阵:

+------------------------------------------------------------------+
|                    Agent 经济参与层次                             |
+---------------+------------------+-------------------------------+
|  基础层       |  增值层           |  高级层                       |
|  ---------    |  ---------        |  ---------                    |
|  MSG 质押     |  流动性提供       |  Agent 代币发行               |
|  委托验证人   |  LP Farming       |  债券曲线销售                 |
|  收益复投     |  集中度管理       |  代币经济设计                 |
|  投票治理     |  无常损失对冲     |  跨链资产桥接                 |
+------------------------------------------------------------------+

1.4 MSG 代币效用全景

MSG Token Utility:
  +-- 网络费用: Gas、合约部署、IBC 转账
  +-- 质押安全: 委托给验证人维护网络安全
  +-- 治理投票: 每个提案需最低 1 MSG 初始存款
  +-- 流动性挖矿: DEX 池配对提供流动性
  +-- 跨链费用: IBC 中继和 Ack 费用
  +-- 协议收入: 交易手续费、MEV 分配

1.5 前提条件

Agent 要参与代币经济需具备:

# 最小依赖集合
AGENT_PREREQUISITES = {
    "chain_id": "msg-chain-1",
    "rpc_endpoint": "https://rpc.msg-chain-1.msg.network",
    "rest_endpoint": "https://api.msg-chain-1.msg.network",
    "bech32_prefix": "msg",
    "denom": "umsg",
    "gas_prices": {"attoMSG": 1000000000},
    "required_balance": 1_000_000,
}

2. MSG 质押与委托

2.1 质押机制概述

MSG Chain 采用 Tendermint PoS 共识机制。代币持有者通过将 MSG 委托给验证人参与网络安全,并获得质押奖励。

质押生命周期:
  +---------+     +---------+     +---------+
  | 委托 MSG |---> | 赚取奖励 |---> | 提取/复投 |
  +---------+     +---------+     +---------+

  验证人选择       奖励按 epoch      21天 unbonding
                   自动累积          周期(全额提取)

2.2 验证人选择策略

Agent 应根据链上指标自动筛选验证人:

import aiohttp
from dataclasses import dataclass
from typing import Optional


@dataclass
class ValidatorInfo:
    """验证人链上信息"""
    operator_address: str
    moniker: str
    tokens: int
    commission_rate: float
    commission_max_rate: float
    commission_max_change_rate: float
    unbonding_tokens: int
    jailed: bool
    status: str


class ValidatorSelector:
    """
    验证人智能选择器
    基于多因子评分模型筛选最佳委托目标
    """

    def __init__(self, rest_endpoint: str = "https://api.msg-chain-1.msg.network"):
        self.rest_endpoint = rest_endpoint
        self.session: Optional[aiohttp.ClientSession] = None

    async def __aenter__(self):
        self.session = aiohttp.ClientSession()
        return self

    async def __aexit__(self, *args):
        if self.session:
            await self.session.close()

    async def fetch_validators(self) -> list[ValidatorInfo]:
        """从 LCD API 获取所有验证人列表"""
        url = f"{self.rest_endpoint}/cosmos/staking/v1beta1/validators"
        params = {"status": "BOND_STATUS_BONDED"}
        async with self.session.get(url, params=params) as resp:
            data = await resp.json()
        validators = []
        for v in data.get("validators", []):
            commission = v.get("commission", {}).get("commission_rates", {})
            validators.append(ValidatorInfo(
                operator_address=v["operator_address"],
                moniker=v["description"]["moniker"],
                tokens=int(v["tokens"]),
                commission_rate=float(commission["rate"]),
                commission_max_rate=float(commission["max_rate"]),
                commission_max_change_rate=float(commission["max_change_rate"]),
                unbonding_tokens=int(v.get("unbonding_tokens", 0)),
                jailed=v.get("jailed", False),
                status=v.get("status", ""),
            ))
        return validators

    def score_validator(self, v: ValidatorInfo) -> float:
        """
        综合评分 (0-100):
        - 佣金率: 越低越好 (权重 30%)
        - 质押量排名: 避免中心化 (权重 25%)
        - 节点稳定性: 历史最低 jailed (权重 25%)
        - 佣金变化率: 越低越好 (权重 20%)
        """
        commission_score = (1.0 - v.commission_rate) * 30
        if v.jailed:
            commission_score = 0.0
        max_change_penalty = v.commission_max_change_rate * 20
        if v.commission_max_rate > 1.0:
            commission_score -= 15
        base_score = commission_score - max_change_penalty
        if v.status != "BOND_STATUS_BONDED":
            base_score *= 0.5
        return max(0.0, base_score)

    async def select_top_validators(self, top_n: int = 5) -> list[ValidatorInfo]:
        """选出评分最高的 N 个验证人"""
        validators = await self.fetch_validators()
        scored = [(self.score_validator(v), v) for v in validators]
        scored.sort(key=lambda x: x[0], reverse=True)
        return [v for _, v in scored[:top_n]]

2.3 委托操作实现

核心的委托、解委托、重新委托操作:

from dataclasses import dataclass
from typing import Optional, Any
import hashlib
import json


@dataclass
class Coin:
    amount: int
    denom: str


@dataclass
class MsgDelegate:
    delegator_address: str
    validator_address: str
    amount: Coin


@dataclass
class MsgUndelegate:
    delegator_address: str
    validator_address: str
    amount: Coin


@dataclass
class MsgBeginRedelegate:
    delegator_address: str
    validator_src_address: str
    validator_dst_address: str
    amount: Coin


class CosmosClient:
    """简化的 Cosmos SDK 链上客户端"""

    def __init__(self, rpc_endpoint: str, private_key: str, bech32_prefix: str = "msg"):
        self.rpc_endpoint = rpc_endpoint
        self.private_key = private_key
        self.bech32_prefix = bech32_prefix

    def get_address(self) -> str:
        return f"msg1...{self.private_key[:8]}"

    async def broadcast_tx(self, msg: Any, memo: str = "") -> dict:
        tx_bytes = self._encode_tx(msg)
        signature = self._sign(tx_bytes)
        signed_tx = {
            "tx": {"body": {"messages": [self._msg_to_dict(msg)], "memo": memo}},
            "signatures": [signature],
        }
        return {"txhash": hashlib.sha256(json.dumps(signed_tx).encode()).hexdigest(), "code": 0}

    def _msg_to_dict(self, msg: Any) -> dict:
        if isinstance(msg, MsgDelegate):
            return {
                "@type": "/cosmos.staking.v1beta1.MsgDelegate",
                "delegator_address": msg.delegator_address,
                "validator_address": msg.validator_address,
                "amount": {"denom": msg.amount.denom, "amount": str(msg.amount.amount)},
            }
        if isinstance(msg, MsgUndelegate):
            return {
                "@type": "/cosmos.staking.v1beta1.MsgUndelegate",
                "delegator_address": msg.delegator_address,
                "validator_address": msg.validator_address,
                "amount": {"denom": msg.amount.denom, "amount": str(msg.amount.amount)},
            }
        if isinstance(msg, MsgBeginRedelegate):
            return {
                "@type": "/cosmos.staking.v1beta1.MsgBeginRedelegate",
                "delegator_address": msg.delegator_address,
                "validator_src_address": msg.validator_src_address,
                "validator_dst_address": msg.validator_dst_address,
                "amount": {"denom": msg.amount.denom, "amount": str(msg.amount.amount)},
            }
        return {}

    def _encode_tx(self, msg: Any) -> bytes:
        return json.dumps(self._msg_to_dict(msg)).encode()

    def _sign(self, tx_bytes: bytes) -> str:
        return "base64_encoded_signature=="


class AgentStaking:
    """Agent 质押与委托操作"""

    GAS_LIMIT_DELEGATE = 200_000
    GAS_LIMIT_UNDELEGATE = 250_000
    GAS_LIMIT_REDELEGATE = 300_000
    MIN_COMPOUND = 100_000

    def __init__(
        self,
        agent_addr: str,
        client: CosmosClient,
        default_validator: str = "",
    ):
        self.agent_addr = agent_addr
        self.client = client
        self.default_validator = default_validator
        self._delegations: dict[str, int] = {}

    async def delegate(self, validator_addr: str, amount: int) -> dict:
        msg = MsgDelegate(
            delegator_address=self.agent_addr,
            validator_address=validator_addr,
            amount=Coin(amount=amount, denom="umsg"),
        )
        result = await self.client.broadcast_tx(msg)
        if result.get("code") == 0:
            self._delegations[validator_addr] = (
                self._delegations.get(validator_addr, 0) + amount
            )
        return result

    async def undelegate(self, validator_addr: str, amount: int) -> dict:
        msg = MsgUndelegate(
            delegator_address=self.agent_addr,
            validator_address=validator_addr,
            amount=Coin(amount=amount, denom="umsg"),
        )
        result = await self.client.broadcast_tx(msg)
        if result.get("code") == 0:
            self._delegations[validator_addr] = max(
                0, self._delegations.get(validator_addr, 0) - amount
            )
        return result

    async def redelegate(
        self,
        from_validator: str,
        to_validator: str,
        amount: int,
    ) -> dict:
        msg = MsgBeginRedelegate(
            delegator_address=self.agent_addr,
            validator_src_address=from_validator,
            validator_dst_address=to_validator,
            amount=Coin(amount=amount, denom="umsg"),
        )
        result = await self.client.broadcast_tx(msg)
        if result.get("code") == 0:
            self._delegations[from_validator] = max(
                0, self._delegations.get(from_validator, 0) - amount
            )
            self._delegations[to_validator] = (
                self._delegations.get(to_validator, 0) + amount
            )
        return result

    async def query_delegations(self) -> list[dict]:
        url = (
            f"{self.client.rpc_endpoint.replace('rpc', 'api')}"
            f"/cosmos/staking/v1beta1/delegations/{self.agent_addr}"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return data.get("delegation_responses", [])

    async def query_rewards(self) -> int:
        url = (
            f"{self.client.rpc_endpoint.replace('rpc', 'api')}"
            f"/cosmos/distribution/v1beta1/delegators/{self.agent_addr}/rewards"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        total = 0
        for reward in data.get("rewards", []):
            for coin in reward.get("reward", []):
                if coin["denom"] == "umsg":
                    total += int(coin["amount"])
        return total

    async def auto_compound(self) -> Optional[dict]:
        rewards = await self.query_rewards()
        if rewards < self.MIN_COMPOUND:
            return None
        validator = self.default_validator
        if not validator:
            async with ValidatorSelector() as selector:
                top = await selector.select_top_validators(1)
                if not top:
                    return None
                validator = top[0].operator_address
        return await self.delegate(validator, rewards)

2.4 奖励查询与提取

class RewardManager:
    """奖励提取和管理"""

    GAS_LIMIT_WITHDRAW = 200_000

    def __init__(self, agent_addr: str, client: CosmosClient):
        self.agent_addr = agent_addr
        self.client = client

    async def withdraw_all_rewards(self) -> list[dict]:
        delegations = await self._query_all_delegations()
        results = []
        for val_addr in delegations:
            msg = {
                "@type": "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
                "delegator_address": self.agent_addr,
                "validator_address": val_addr,
            }
            tx_result = await self.client.broadcast_tx(msg)
            results.append(tx_result)
        return results

    async def _query_all_delegations(self) -> list[str]:
        url = (
            f"{self.client.rpc_endpoint.replace('rpc', 'api')}"
            f"/cosmos/staking/v1beta1/delegations/{self.agent_addr}"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return [d["delegation"]["validator_address"] for d in data.get("delegation_responses", [])]

    async def query_annual_apr(self) -> float:
        url = f"{self.client.rpc_endpoint.replace('rpc', 'api')}/cosmos/mint/v1beta1/inflation"
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                inflation_data = await resp.json()
        inflation = float(inflation_data.get("inflation", "0.13"))
        pool_url = f"{self.client.rpc_endpoint.replace('rpc', 'api')}/cosmos/staking/v1beta1/pool"
        async with aiohttp.ClientSession() as session:
            async with session.get(pool_url) as resp:
                pool_data = await resp.json()
        bonded = float(pool_data["pool"]["bonded_tokens"])
        not_bonded = float(pool_data["pool"]["not_bonded_tokens"])
        total_supply = bonded + not_bonded
        bonded_ratio = bonded / total_supply if total_supply > 0 else 1.0
        apr = inflation / bonded_ratio if bonded_ratio > 0 else 0.0
        commission_avg = 0.10
        return apr * (1 - commission_avg)

2.5 重新委托策略

class RedelegationStrategy:
    """
    重新委托策略引擎
    场景:
    1. 佣金率调整: 验证人提升佣金,Agent 转向低佣金节点
    2. 安全迁移: 检测到验证人即将 jailed,提前迁移
    3. 收益优化: 将委托集中到高收益验证人
    """

    REDELEGATION_COOLDOWN = 14

    def __init__(self, staking: AgentStaking, selector: ValidatorSelector):
        self.staking = staking
        self.selector = selector
        self._redelegation_history: dict[str, int] = {}

    async def evaluate_and_redelegate(self) -> list[dict]:
        delegations = await self.staking.query_delegations()
        validators = await self.selector.fetch_validators()
        validator_map = {v.operator_address: v for v in validators}
        results = []
        for delegation in delegations:
            val_addr = delegation["delegation"]["validator_address"]
            amount = int(delegation["balance"]["amount"])
            validator = validator_map.get(val_addr)
            if not validator:
                continue
            score = self.selector.score_validator(validator)
            if score < 50 and amount > 0:
                last_redelegation = self._redelegation_history.get(val_addr, 0)
                blocks_since = await self._get_current_block_height() - last_redelegation
                if blocks_since < self.REDELEGATION_COOLDOWN * 10000:
                    continue
                top = await self.selector.select_top_validators(1)
                if top and top[0].operator_address != val_addr:
                    tx = await self.staking.redelegate(
                        from_validator=val_addr,
                        to_validator=top[0].operator_address,
                        amount=amount,
                    )
                    results.append(tx)
                    self._redelegation_history[val_addr] = await self._get_current_block_height()
        return results

    async def _get_current_block_height(self) -> int:
        url = f"{self.staking.client.rpc_endpoint.replace('rpc', 'api')}/cosmos/base/tendermint/v1beta1/blocks/latest"
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return int(data["block"]["header"]["height"])

2.6 Unbonding 管理

class UnbondingManager:
    """
    解委托队列管理
    委托解绑需要 21 天,Agent 需要追踪 unbonding 队列并在到期后自动提取。
    """

    UNBONDING_DAYS = 21
    BLOCKS_PER_DAY = 14400
    UNBONDING_BLOCKS = UNBONDING_DAYS * BLOCKS_PER_DAY

    def __init__(self, agent_addr: str, client: CosmosClient):
        self.agent_addr = agent_addr
        self.client = client

    async def query_unbonding_delegations(self) -> list[dict]:
        url = (
            f"{self.client.rpc_endpoint.replace('rpc', 'api')}"
            f"/cosmos/staking/v1beta1/delegators/{self.agent_addr}/unbonding_delegations"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return data.get("unbonding_responses", [])

    async def monitor_unbonding_queue(self) -> list[dict]:
        current_height = await self._get_current_height()
        unbondings = await self.query_unbonding_delegations()
        completed = []
        for entry in unbondings:
            for entry_inner in entry.get("entries", []):
                completion_height = int(entry_inner.get("completion_height", 0))
                blocks_remaining = completion_height - current_height
                if blocks_remaining <= 0:
                    completed.append({
                        "validator": entry["validator_address"],
                        "amount": entry_inner["balance"],
                        "status": "completed",
                    })
                elif blocks_remaining < 14400:
                    completed.append({
                        "validator": entry["validator_address"],
                        "amount": entry_inner["balance"],
                        "completion_height": completion_height,
                        "blocks_remaining": blocks_remaining,
                        "eta_hours": blocks_remaining / 600,
                        "status": "pending_soon",
                    })
        return completed

    async def _get_current_height(self) -> int:
        url = f"{self.client.rpc_endpoint}/status"
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return int(data["result"]["sync_info"]["latest_block_height"])

2.7 质押事件监控

class StakingEventMonitor:
    """质押事件实时监控"""

    def __init__(self, rpc_endpoint: str, websocket_endpoint: str):
        self.rpc = rpc_endpoint
        self.ws = websocket_endpoint

    async def subscribe_staking_events(self, agent_addr: str):
        import json
        query = json.dumps({
            "jsonrpc": "2.0",
            "method": "subscribe",
            "params": {"query": f"transfer.recipient='{agent_addr}'"},
            "id": 1,
        })
        import asyncio
        while True:
            await asyncio.sleep(60)

2.8 质押数据缓存与统计

@dataclass
class StakingStats:
    """质押状态快照"""
    total_delegated: int
    total_rewards: int
    active_validators: int
    avg_commission: float
    current_apr: float
    compounding_count: int
    last_compound_height: int


class StakingAnalytics:
    """质押数据缓存与分析"""

    def __init__(self, staking: AgentStaking):
        self.staking = staking
        self.history: list[StakingStats] = []
        self._cache: Optional[StakingStats] = None
        self._cache_time = 0

    async def get_stats(self) -> StakingStats:
        from time import time
        if self._cache and time() - self._cache_time < 60:
            return self._cache
        delegations = await self.staking.query_delegations()
        rewards = await self.staking.query_rewards()
        total_delegated = sum(int(d.get("balance", {}).get("amount", 0)) for d in delegations)
        reward_mgr = RewardManager(self.staking.agent_addr, self.staking.client)
        apr = await reward_mgr.query_annual_apr()
        stats = StakingStats(
            total_delegated=total_delegated,
            total_rewards=rewards,
            active_validators=len(delegations),
            avg_commission=0.10,
            current_apr=apr,
            compounding_count=len(self.history),
            last_compound_height=0,
        )
        self._cache = stats
        self._cache_time = time()
        self.history.append(stats)
        return stats

    def summary_report(self, stats: StakingStats) -> str:
        return (
            "===== 质押报告 =====\n"
            f"总委托: {stats.total_delegated / 1_000_000:.2f} MSG\n"
            f"当前 APR: {stats.current_apr * 100:.2f}%\n"
            f"验证人数: {stats.active_validators}"
        )

3. 流动性提供

3.1 DEX 流动性池机制

MSG Chain 支持 CosmWasm 智能合约实现的 DEX。流动性提供者向交易对池注入代币获取 LP Token,并获得交易手续费分成。

AMM 流动性池:

  Agent A --MSG--> [ MSG / USDC 池 ] <--LP-- Agent B
                    MSG: 1,000,000
                    USDC: 500,000
                    LP Token: 1,500
                    Fee: 0.3%
                    k = MSG * USDC

3.2 流动性提供核心实现

from dataclasses import dataclass
from typing import Optional
import aiohttp


@dataclass
class AssetInfo:
    """CosmWasm 资产信息"""
    native: Optional[str] = None
    token: Optional[str] = None


@dataclass
class PoolInfo:
    """流动性池信息"""
    pool_id: int
    pool_addr: str
    assets: list[dict]
    total_lp_shares: int
    swap_fee: float


class ExecuteMsg:
    """CosmWasm 合约执行消息"""

    @staticmethod
    def provide_liquidity(
        assets: list[AssetInfo],
        amounts: list[int],
        slippage_tolerance: float = 0.01,
        receiver: Optional[str] = None,
    ) -> dict:
        msg = {
            "provide_liquidity": {
                "assets": [
                    {
                        "info": (
                            {"native_token": {"denom": a.native}}
                            if a.native
                            else {"token": {"contract_addr": a.token}}
                        ),
                        "amount": str(amount),
                    }
                    for a, amount in zip(assets, amounts)
                ],
                "slippage_tolerance": str(slippage_tolerance),
            }
        }
        if receiver:
            msg["provide_liquidity"]["receiver"] = receiver
        return msg

    @staticmethod
    def withdraw_liquidity(lp_amount: int) -> dict:
        return {"withdraw_liquidity": {"amount": str(lp_amount)}}

    @staticmethod
    def swap(offer_asset: AssetInfo, offer_amount: int, min_receive: int) -> dict:
        return {
            "swap": {
                "offer_asset": {
                    "info": (
                        {"native_token": {"denom": offer_asset.native}}
                        if offer_asset.native
                        else {"token": {"contract_addr": offer_asset.token}}
                    ),
                    "amount": str(offer_amount),
                },
                "expected_amount": str(min_receive),
            }
        }


class DexClient:
    """DEX 合约交互客户端"""

    def __init__(self, client: CosmosClient, factory_addr: str):
        self.client = client
        self.factory_addr = factory_addr

    async def execute_contract(self, contract_addr: str, msg: dict, funds: list[Coin] = None) -> dict:
        exec_msg = {
            "@type": "/cosmwasm.wasm.v1.MsgExecuteContract",
            "sender": self.client.get_address(),
            "contract": contract_addr,
            "msg": msg,
            "funds": [{"denom": f.denom, "amount": str(f.amount)} for f in (funds or [])],
        }
        return await self.client.broadcast_tx(exec_msg)

    async def query_contract(self, contract_addr: str, msg: dict) -> dict:
        url = (
            f"{self.client.rpc_endpoint.replace('rpc', 'api')}"
            f"/cosmwasm/wasm/v1/contract/{contract_addr}/smart/"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url, params={"query": json.dumps(msg)}) as resp:
                return await resp.json()

    async def query_pools(self) -> list[PoolInfo]:
        query = {"pairs": {"limit": 30}}
        result = await self.query_contract(self.factory_addr, query)
        pools = []
        for i, pair in enumerate(result.get("data", {}).get("pairs", [])):
            pools.append(PoolInfo(
                pool_id=i + 1,
                pool_addr=pair["contract_addr"],
                assets=pair["asset_infos"],
                total_lp_shares=int(pair.get("total_share", "0")),
                swap_fee=float(pair.get("swap_fee", "0.003")),
            ))
        return pools

3.3 流动性提供操作

class LiquidityProvider:
    """流动性提供者 Agent"""

    MAX_SLIPPAGE = 0.02
    MIN_LP_POSITION = 10_000

    def __init__(self, agent_addr: str, dex: DexClient, pool_addr: str):
        self.agent_addr = agent_addr
        self.dex = dex
        self.pool_addr = pool_addr
        self._lp_balance: int = 0

    async def provide_liquidity(
        self,
        msg_amount: int,
        usdc_amount: int,
        slippage_tolerance: float = 0.01,
    ) -> dict:
        assets = [AssetInfo(native="umsg"), AssetInfo(native="uusdc")]
        msg = ExecuteMsg.provide_liquidity(
            assets=assets,
            amounts=[msg_amount, usdc_amount],
            slippage_tolerance=slippage_tolerance,
        )
        funds = [Coin(amount=msg_amount, denom="umsg"), Coin(amount=usdc_amount, denom="uusdc")]
        return await self.dex.execute_contract(self.pool_addr, msg, funds)

    async def withdraw_liquidity(self, lp_amount: int) -> dict:
        msg = ExecuteMsg.withdraw_liquidity(lp_amount)
        return await self.dex.execute_contract(self.pool_addr, msg)

    async def query_lp_balance(self) -> int:
        balance_query = {"balance": {"address": self.agent_addr}}
        result = await self.dex.query_contract(self.pool_addr, balance_query)
        balance = int(result.get("data", {}).get("balance", "0"))
        self._lp_balance = balance
        return balance

    async def estimate_lp_value(self) -> dict:
        pool_balances = await self.dex.get_pool_balances(self.pool_addr)
        lp_balance = await self.query_lp_balance()
        total_lp = int(pool_balances.get("total_share", 1))
        share_ratio = lp_balance / total_lp if total_lp > 0 else 0
        msg_value = int(pool_balances.get("umsg", 0) * share_ratio)
        usdc_value = int(pool_balances.get("uusdc", 0) * share_ratio)
        return {
            "total_value_usd": usdc_value / 1_000_000 * 2,
            "msg_value": msg_value,
            "usdc_value": usdc_value,
        }

3.4 无常损失监控

class ImpermanentLossMonitor:
    """无常损失 (IL) 监控器"""

    IL_THRESHOLD = 0.05
    IL_CRITICAL = 0.15

    def __init__(self, dex: DexClient, pool_addr: str):
        self.dex = dex
        self.pool_addr = pool_addr
        self._price_history: list[float] = []

    async def calculate_il(self, initial_ratio: float, current_ratio: float) -> float:
        import math
        ratio = current_ratio / initial_ratio
        il = (2 * math.sqrt(ratio) / (1 + ratio)) - 1
        return il

    async def monitor(self) -> Optional[dict]:
        balances = await self.dex.get_pool_balances(self.pool_addr)
        msg_balance = balances.get("umsg", 0)
        usdc_balance = balances.get("uusdc", 0)
        if msg_balance == 0 or usdc_balance == 0:
            return None
        current_ratio = msg_balance / usdc_balance
        self._price_history.append(current_ratio)
        if len(self._price_history) > 100:
            self._price_history.pop(0)
        if len(self._price_history) < 2:
            return None
        initial_ratio = self._price_history[0]
        il = await self.calculate_il(initial_ratio, current_ratio)
        alert = None
        if il <= -self.IL_CRITICAL:
            alert = {"level": "CRITICAL", "il": il,
                     "message": f"无常损失 {il * 100:.1f}%,建议立即移除流动性"}
        elif il <= -self.IL_THRESHOLD:
            alert = {"level": "WARNING", "il": il,
                     "message": f"无常损失 {il * 100:.1f}%,考虑调整仓位"}
        return alert

3.5 收益农场 (Yield Farming)

class YieldFarm:
    """流动性挖矿 / 收益农场参与"""

    def __init__(self, dex: DexClient, farm_addr: str):
        self.dex = dex
        self.farm_addr = farm_addr

    async def stake_lp(self, lp_token_addr: str, amount: int) -> dict:
        increase_allowance = {
            "increase_allowance": {"spender": self.farm_addr, "amount": str(amount)}
        }
        await self.dex.execute_contract(lp_token_addr, increase_allowance)
        stake_msg = {
            "send": {
                "contract": self.farm_addr,
                "amount": str(amount),
                "msg": "",
            }
        }
        return await self.dex.execute_contract(lp_token_addr, stake_msg)

    async def claim_rewards(self) -> dict:
        claim_msg = {"claim": {}}
        return await self.dex.execute_contract(self.farm_addr, claim_msg)

    async def unstake_lp(self, amount: int) -> dict:
        unstake_msg = {"leave": {"amount": str(amount)}}
        return await self.dex.execute_contract(self.farm_addr, unstake_msg)

4. 治理投票

4.1 MSG Chain 治理模型

MSG Chain 基于 Cosmos SDK 的治理模块,支持参数变更、软件升级、社区池支出等提案类型。

治理流程:

  提交提案 -> 存款阶段 -> 投票阶段 -> 执行/拒绝
  最低 1MSG    到达阈值    7 天周期

  投票选项: Yes / No / Abstain / NoWithVeto

4.2 核心治理操作

from enum import Enum


class VoteOption(str, Enum):
    """投票选项"""
    YES = "VOTE_OPTION_YES"
    NO = "VOTE_OPTION_NO"
    ABSTAIN = "VOTE_OPTION_ABSTAIN"
    NO_WITH_VETO = "VOTE_OPTION_NO_WITH_VETO"


@dataclass
class Proposal:
    """链上治理提案"""
    id: int
    title: str
    description: str
    status: str
    submit_time: str
    deposit_end_time: str
    voting_start_time: str
    voting_end_time: str
    total_deposit: list[Coin]
    proposer: str
    content: dict


class AgentGovernance:
    """Agent 链上治理参与"""

    MIN_INITIAL_DEPOSIT = 1_000_000
    GAS_VOTE = 100_000
    GAS_SUBMIT = 500_000
    GAS_DEPOSIT = 200_000

    def __init__(self, agent_addr: str, client: CosmosClient):
        self.agent_addr = agent_addr
        self.client = client

    async def query_proposals(self, status: str = "") -> list[Proposal]:
        url = f"{self.client.rpc_endpoint.replace('rpc', 'api')}/cosmos/gov/v1beta1/proposals"
        params = {}
        if status:
            params["proposal_status"] = status
        async with aiohttp.ClientSession() as session:
            async with session.get(url, params=params) as resp:
                data = await resp.json()
        proposals = []
        for p in data.get("proposals", []):
            content = p.get("content", {})
            proposals.append(Proposal(
                id=int(p["proposal_id"]),
                title=content.get("title", p.get("title", "")),
                description=content.get("description", p.get("summary", "")),
                status=p["status"],
                submit_time=p["submit_time"],
                deposit_end_time=p["deposit_end_time"],
                voting_start_time=p["voting_start_time"],
                voting_end_time=p["voting_end_time"],
                total_deposit=[Coin(amount=int(c["amount"]), denom=c["denom"]) for c in p.get("total_deposit", [])],
                proposer=p["proposer"],
                content=content,
            ))
        return proposals

    async def vote_on_proposal(self, proposal_id: int, option: VoteOption) -> dict:
        msg = {
            "@type": "/cosmos.gov.v1beta1.MsgVote",
            "voter": self.agent_addr,
            "proposal_id": str(proposal_id),
            "option": option.value,
        }
        return await self.client.broadcast_tx(msg)

    async def weighted_vote(self, proposal_id: int, options: list[tuple[VoteOption, float]]) -> dict:
        msg = {
            "@type": "/cosmos.gov.v1beta1.MsgVoteWeighted",
            "voter": self.agent_addr,
            "proposal_id": str(proposal_id),
            "options": [{"option": option.value, "weight": str(weight)} for option, weight in options],
        }
        return await self.client.broadcast_tx(msg)

    async def submit_proposal(
        self, title: str, description: str, changes: list[dict],
        deposit: int = MIN_INITIAL_DEPOSIT,
    ) -> dict:
        msg = {
            "@type": "/cosmos.gov.v1beta1.MsgSubmitProposal",
            "content": {
                "@type": "/cosmos.params.v1beta1.ParameterChangeProposal",
                "title": title,
                "description": description,
                "changes": changes,
            },
            "initial_deposit": [{"denom": "umsg", "amount": str(deposit)}],
            "proposer": self.agent_addr,
        }
        return await self.client.broadcast_tx(msg)

    async def submit_text_proposal(
        self, title: str, description: str, deposit: int = MIN_INITIAL_DEPOSIT,
    ) -> dict:
        msg = {
            "@type": "/cosmos.gov.v1beta1.MsgSubmitProposal",
            "content": {
                "@type": "/cosmos.gov.v1beta1.TextProposal",
                "title": title,
                "description": description,
            },
            "initial_deposit": [{"denom": "umsg", "amount": str(deposit)}],
            "proposer": self.agent_addr,
        }
        return await self.client.broadcast_tx(msg)

    async def submit_community_pool_spend_proposal(
        self, title: str, description: str, recipient: str,
        amount: int, deposit: int = MIN_INITIAL_DEPOSIT,
    ) -> dict:
        msg = {
            "@type": "/cosmos.gov.v1beta1.MsgSubmitProposal",
            "content": {
                "@type": "/cosmos.distribution.v1beta1.CommunityPoolSpendProposal",
                "title": title,
                "description": description,
                "recipient": recipient,
                "amount": [{"denom": "umsg", "amount": str(amount)}],
            },
            "initial_deposit": [{"denom": "umsg", "amount": str(deposit)}],
            "proposer": self.agent_addr,
        }
        return await self.client.broadcast_tx(msg)

    async def deposit_on_proposal(self, proposal_id: int, amount: int) -> dict:
        msg = {
            "@type": "/cosmos.gov.v1beta1.MsgDeposit",
            "depositor": self.agent_addr,
            "proposal_id": str(proposal_id),
            "amount": [{"denom": "umsg", "amount": str(amount)}],
        }
        return await self.client.broadcast_tx(msg)

4.3 提案分析与自动投票

@dataclass
class ProposalAnalysis:
    """提案分析结果"""
    proposal_id: int
    title: str
    summary: str
    risk_level: str
    impact_assessment: str
    recommendation: VoteOption
    confidence: float
    reasoning: list[str]


class Constitution:
    """Agent 宪法 - 投票决策的规则引擎"""

    def __init__(self):
        self.principles = [
            "网络安全性优先: 任何降低安全性的参数变更应反对",
            "去中心化: 偏向降低通胀、降低验证人佣金上限的提议",
            "经济可持续: 偏向合理通胀率维持网络安全",
            "社区利益: 社区池支出应有明确可衡量的产出",
            "技术升级: 经过充分测试的软件升级应支持",
        ]

    async def evaluate_proposal(self, proposal: Proposal) -> ProposalAnalysis:
        content_type = proposal.content.get("@type", "")
        if "ParameterChange" in content_type:
            return await self._evaluate_param_change(proposal)
        elif "CommunityPoolSpend" in content_type:
            return await self._evaluate_community_spend(proposal)
        elif "SoftwareUpgrade" in content_type:
            return await self._evaluate_upgrade(proposal)
        else:
            return await self._evaluate_text(proposal)

    async def _evaluate_param_change(self, proposal: Proposal) -> ProposalAnalysis:
        changes = proposal.content.get("changes", [])
        reasoning = []
        recommendation = VoteOption.YES
        confidence = 0.5
        risk = "MEDIUM"
        for change in changes:
            key = change.get("key", "")
            value = change.get("value", "")
            if "MaxValidators" in key:
                new_val = int(value)
                if new_val > 150:
                    recommendation = VoteOption.NO
                    confidence = 0.6
                    risk = "HIGH"
        return ProposalAnalysis(
            proposal_id=proposal.id, title=proposal.title,
            summary=proposal.description[:200], risk_level=risk,
            recommendation=recommendation, confidence=confidence,
            reasoning=reasoning,
        )

    async def _evaluate_community_spend(self, proposal: Proposal) -> ProposalAnalysis:
        recipient = proposal.content.get("recipient", "")
        reasoning = []
        if 'amount' in str(proposal.content):
            reasoning.append("社区池支出提案")
        return ProposalAnalysis(
            proposal_id=proposal.id, title=proposal.title,
            summary=proposal.description[:200], risk_level="LOW",
            recommendation=VoteOption.YES, confidence=0.6,
            reasoning=reasoning,
        )

    async def _evaluate_text(self, proposal: Proposal) -> ProposalAnalysis:
        return ProposalAnalysis(
            proposal_id=proposal.id, title=proposal.title,
            summary=proposal.description[:200], risk_level="LOW",
            impact_assessment="信号提案,无直接链上影响",
            recommendation=VoteOption.YES, confidence=0.6,
            reasoning=["文本提案,无参数变更或资金支出"],
        )

4.4 自动投票引擎

class AutoVoter:
    """自动投票引擎"""

    def __init__(self, governance: AgentGovernance, constitution: Constitution):
        self.governance = governance
        self.constitution = constitution
        self.vote_history: dict[int, VoteOption] = {}

    async def auto_vote(self) -> list[dict]:
        proposals = await self.governance.query_proposals(status="PROPOSAL_STATUS_VOTING_PERIOD")
        results = []
        for proposal in proposals:
            if proposal.id in self.vote_history:
                continue
            analysis = await self.constitution.evaluate_proposal(proposal)
            if analysis.confidence >= 0.7:
                tx = await self.governance.vote_on_proposal(proposal.id, analysis.recommendation)
                results.append({"proposal_id": proposal.id, "vote": analysis.recommendation,
                                "confidence": analysis.confidence, "tx": tx})
                self.vote_history[proposal.id] = analysis.recommendation
        return results

    async def get_voting_power(self) -> int:
        url = (f"{self.governance.client.rpc_endpoint.replace('rpc', 'api')}"
               f"/cosmos/staking/v1beta1/delegations/{self.governance.agent_addr}")
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return sum(int(d.get("balance", {}).get("amount", 0)) for d in data.get("delegation_responses", []))

5. Agent 代币发行 (CW20)

5.1 CW20 代币标准

CW20 是 CosmWasm 生态的代币标准,类似 ERC20 但针对 Cosmos 生态优化。Agent 可以发行自有代币建立独立经济系统。

Agent 代币经济模型:

      [Agent Token]
          (CW20)
        /    |    \
   效用    治理    社交
   代币    代币    代币

5.2 CW20 合约部署

class AgentTokenCW20:
    """Agent CW20 代币发行"""

    TOKEN_CODE_ID = 1
    DECIMALS = 6

    def __init__(self, client: CosmosClient, agent_addr: str):
        self.client = client
        self.agent_addr = agent_addr
        self.token_contract_addr: Optional[str] = None

    async def create_token(
        self, name: str, symbol: str, initial_supply: int,
        mintable: bool = True, cap: Optional[int] = None,
    ) -> dict:
        label = f"agent-{symbol.lower()}-{hash(name) % 10000}"
        minter_config = None
        if mintable:
            minter_config = {"minter": self.agent_addr, "cap": str(cap) if cap else None}
        instantiate_msg = {
            "name": name, "symbol": symbol.upper(), "decimals": self.DECIMALS,
            "initial_balances": [{"address": self.agent_addr, "amount": str(initial_supply)}],
            "mint": minter_config,
        }
        msg = {
            "@type": "/cosmwasm.wasm.v1.MsgInstantiateContract",
            "sender": self.agent_addr, "admin": self.agent_addr,
            "code_id": str(self.TOKEN_CODE_ID), "label": label,
            "msg": instantiate_msg, "funds": [],
        }
        result = await self.client.broadcast_tx(msg)
        if result.get("code") == 0:
            self.token_contract_addr = self._parse_contract_address(result)
        return result

    def _parse_contract_address(self, tx_result: dict) -> Optional[str]:
        events = tx_result.get("events", []) if isinstance(tx_result, dict) else []
        for event in events:
            if event.get("type") == "instantiate":
                for attr in event.get("attributes", []):
                    if attr.get("key") == "_contract_address":
                        return attr.get("value")
        return None

5.3 代币铸造与销毁

class TokenMinter:
    """CW20 代币铸造与销毁"""

    def __init__(self, client: CosmosClient, contract_addr: str, agent_addr: str):
        self.client = client
        self.contract_addr = contract_addr
        self.agent_addr = agent_addr

    async def mint(self, recipient: str, amount: int) -> dict:
        msg = {"mint": {"recipient": recipient, "amount": str(amount)}}
        exec_msg = {"@type": "/cosmwasm.wasm.v1.MsgExecuteContract",
                    "sender": self.agent_addr, "contract": self.contract_addr,
                    "msg": msg, "funds": []}
        return await self.client.broadcast_tx(exec_msg)

    async def burn(self, amount: int) -> dict:
        msg = {"burn": {"amount": str(amount)}}
        exec_msg = {"@type": "/cosmwasm.wasm.v1.MsgExecuteContract",
                    "sender": self.agent_addr, "contract": self.contract_addr,
                    "msg": msg, "funds": []}
        return await self.client.broadcast_tx(exec_msg)

5.4 CW20 转账与授权

class TokenTransfer:
    """CW20 转账与授权操作"""

    def __init__(self, client: CosmosClient, contract_addr: str, agent_addr: str):
        self.client = client
        self.contract_addr = contract_addr
        self.agent_addr = agent_addr

    async def transfer(self, recipient: str, amount: int) -> dict:
        msg = {"transfer": {"recipient": recipient, "amount": str(amount)}}
        exec_msg = {"@type": "/cosmwasm.wasm.v1.MsgExecuteContract",
                    "sender": self.agent_addr, "contract": self.contract_addr,
                    "msg": msg, "funds": []}
        return await self.client.broadcast_tx(exec_msg)

    async def increase_allowance(self, spender: str, amount: int) -> dict:
        msg = {"increase_allowance": {"spender": spender, "amount": str(amount)}}
        exec_msg = {"@type": "/cosmwasm.wasm.v1.MsgExecuteContract",
                    "sender": self.agent_addr, "contract": self.contract_addr,
                    "msg": msg, "funds": []}
        return await self.client.broadcast_tx(exec_msg)

    async def balance(self, address: str) -> int:
        query = {"balance": {"address": address}}
        url = (f"{self.client.rpc_endpoint.replace('rpc', 'api')}"
               f"/cosmwasm/wasm/v1/contract/{self.contract_addr}/smart/"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return int(data.get("data", {}).get("balance", "0"))

5.5 债券曲线 (Bonding Curve)

class BondingCurve:
    """Agent 代币债券曲线"""

    def __init__(
        self, token: AgentTokenCW20,
        base_price: float = 0.001,
        exponent: float = 1.5,
        reserve_denom: str = "umsg",
    ):
        self.token = token
        self.base_price = base_price
        self.exponent = exponent
        self.reserve_denom = reserve_denom
        self.reserve_balance: int = 0
        self.token_supply: int = 0

    def calculate_price(self, current_supply: int) -> float:
        if current_supply <= 0:
            return self.base_price
        return self.base_price * (current_supply ** (self.exponent - 1))

    async def buy(self, msg_amount: int) -> dict:
        supply = await self._query_supply()
        token_amount = int(msg_amount / self.calculate_price(supply))
        return {"action": "buy", "token_amount": token_amount, "cost": msg_amount}

    async def sell(self, token_amount: int) -> dict:
        supply = await self._query_supply()
        return {"action": "sell", "token_amount": token_amount}

    async def _query_supply(self) -> int:
        if not self.token.token_contract_addr:
            return 0
        query = {"token_info": {}}
        url = (f"{self.token.client.rpc_endpoint.replace('rpc', 'api')}"
               f"/cosmwasm/wasm/v1/contract/{self.token.token_contract_addr}/smart/"
        )
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                data = await resp.json()
        return int(data.get("data", {}).get("total_supply", "0"))

5.6 代币经济参数设计

class TokenomicsDesign:
    """Agent 代币经济参数设计器"""

    @staticmethod
    def optimal_initial_distribution(total_supply: int) -> dict[str, int]:
        return {
            "community_pool": int(total_supply * 0.30),
            "team_vesting": int(total_supply * 0.20),
            "liquidity_provision": int(total_supply * 0.15),
            "staking_rewards": int(total_supply * 0.15),
            "airdrop": int(total_supply * 0.10),
            "initial_sale": int(total_supply * 0.10),
        }

6. 收益管理与金库

6.1 金库架构

Agent 金库是一个多策略资产管理引擎,自动将资金分配到最高效的收益策略中。

金库架构:

  [Agent Treasury]
    /     |     \
 Staking  LP   Lending
  50%     30%    20%

6.2 多策略金库实现

from dataclasses import dataclass
from typing import Protocol, Optional


@dataclass
class PortfolioSnapshot:
    """投资组合快照"""
    total_value_msg: int
    staking_value: int
    liquidity_value: int
    lending_value: int
    liquid_balance: int
    timestamp: int


class Strategy(Protocol):
    """策略接口"""
    weight: float
    name: str
    async def current_value(self) -> int: ...
    async def adjust(self, delta: int): ...


@dataclass
class StakingStrategy:
    """质押策略"""
    weight: float
    staking: AgentStaking
    name: str = "staking"

    async def current_value(self) -> int:
        delegations = await self.staking.query_delegations()
        return sum(int(d.get("balance", {}).get("amount", 0)) for d in delegations)

    async def adjust(self, delta: int) -> Optional[dict]:
        if delta > 0:
            return await self.staking.delegate(self.staking.default_validator, delta)
        elif delta < 0:
            return await self.staking.undelegate(self.staking.default_validator, abs(delta))
        return None


@dataclass
class LiquidityStrategy:
    """流动性策略"""
    weight: float
    provider: LiquidityProvider
    name: str = "liquidity"

    async def adjust(self, delta: int) -> Optional[dict]:
        if delta > 0:
            half = delta // 2
            return await self.provider.provide_liquidity(half, half)
        return None


class AgentTreasury:
    """Agent 金库 - 多策略资产管理"""

    REBALANCE_THRESHOLD = 0.05

    def __init__(self, agent_addr: str, strategies: Optional[dict[str, Strategy]] = None):
        self.agent_addr = agent_addr
        self.strategies = strategies or {}
        self._last_rebalance = 0
        self.portfolio_history: list[PortfolioSnapshot] = []

    async def query_portfolio(self) -> PortfolioSnapshot:
        values = {}
        for name, strategy in self.strategies.items():
            values[name] = await strategy.current_value()
        total = sum(values.values()) if values else 0
        return PortfolioSnapshot(
            total_value_msg=total,
            staking_value=values.get("staking", 0),
            liquidity_value=values.get("liquidity", 0),
            lending_value=values.get("lending", 0),
            liquid_balance=0,
            timestamp=0,
        )

    async def rebalance(self) -> list[dict]:
        import time
        now = time.time()
        if now - self._last_rebalance < 3600:
            return []
        portfolio = await self.query_portfolio()
        if portfolio.total_value_msg <= 0:
            return []
        adjustments = []
        for name, strategy in self.strategies.items():
            target = int(portfolio.total_value_msg * strategy.weight)
            current = await strategy.current_value()
            deviation = abs(target - current) / max(portfolio.total_value_msg, 1)
            if deviation > self.REBALANCE_THRESHOLD:
                delta = target - current
                result = await strategy.adjust(delta)
                adjustments.append({"strategy": name, "delta": delta, "result": result})
        self._last_rebalance = now
        return adjustments

7. 经济参与策略

7.1 完整策略循环

class EconomicStrategy:
    """自动化经济参与策略"""

    STRATEGY_INTERVAL = 3600
    COMPOUND_INTERVAL = 86400
    REBALANCE_INTERVAL = 604800
    GOVERNANCE_INTERVAL = 21600

    def __init__(
        self, agent_addr: str, private_key: str,
        rpc_endpoint: str = "https://rpc.msg-chain-1.msg.network",
        rest_endpoint: str = "https://api.msg-chain-1.msg.network",
        validator_addr: str = "", pool_addr: str = "",
    ):
        self.agent_addr = agent_addr
        self.client = CosmosClient(rpc_endpoint, private_key)
        self.staking = AgentStaking(agent_addr, self.client, validator_addr)
        self.selector = ValidatorSelector(rest_endpoint)
        self.dex = DexClient(self.client, "")
        self.provider = LiquidityProvider(agent_addr, self.dex, pool_addr)
        self.governance = AgentGovernance(agent_addr, self.client)
        self.constitution = Constitution()
        self.auto_voter = AutoVoter(self.governance, self.constitution)
        self.strategies: dict[str, Strategy] = {}
        self.treasury = AgentTreasury(agent_addr, self.strategies)
        self.running = False

    def configure_strategies(
        self, staking_weight: float = 0.5, liquidity_weight: float = 0.3,
    ):
        self.strategies["staking"] = StakingStrategy(weight=staking_weight, staking=self.staking)
        self.strategies["liquidity"] = LiquidityStrategy(weight=liquidity_weight, provider=self.provider)
        self.treasury = AgentTreasury(self.agent_addr, self.strategies)

    async def initialize(self) -> dict:
        url = f"{self.rest}/cosmos/bank/v1beta1/balances/{self.agent_addr}"
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                balances = await resp.json()
        msg_balance = 0
        for coin in balances.get("balances", []):
            if coin["denom"] == "umsg":
                msg_balance = int(coin["amount"])
        if msg_balance < 1_000_000:
            return {"status": "insufficient_funds", "balance": msg_balance}
        return {"status": "initialized", "balance": msg_balance}

    async def execute_strategy(self):
        self.running = True
        results = {"compounding": [], "governance": [],
                   "rebalance": [], "errors": []}
        try:
            compound_tx = await self.staking.auto_compound()
            if compound_tx:
                results["compounding"].append(compound_tx)
            gov_results = await self.auto_voter.auto_vote()
            results["governance"].extend(gov_results)
            rebalance_txs = await self.treasury.rebalance()
            results["rebalance"].extend(rebalance_txs)
        except Exception as e:
            results["errors"].append(str(e))
        return results

    async def run_forever(self):
        self.running = True
        import asyncio, time
        while self.running:
            await asyncio.sleep(self.STRATEGY_INTERVAL)
            await self.execute_strategy()

    async def stop(self):
        self.running = False

7.2 Rust 链上合约示例

use cosmwasm_std::{entry_point, Addr, Coin, CosmosMsg, Decimal, DepsMut,
    Env, MessageInfo, Response, StdResult, Uint128};
use cw_storage_plus::Item;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Config {
    pub owner: Addr,
    pub default_validator: Addr,
    pub staking_weight: Decimal,
    pub rebalance_threshold: Decimal,
}

pub const CONFIG: Item<Config> = Item::new("config");

#[entry_point]
pub fn instantiate(
    deps: DepsMut, _env: Env, _info: MessageInfo, msg: InstantiateMsg,
) -> StdResult<Response> {
    let config = Config {
        owner: deps.api.addr_validate(&msg.owner)?,
        default_validator: deps.api.addr_validate(&msg.default_validator)?,
        staking_weight: Decimal::percent(50),
        rebalance_threshold: Decimal::percent(5),
    };
    CONFIG.save(deps.storage, &config)?;
    Ok(Response::new().add_attribute("action", "instantiate"))
}

#[entry_point]
pub fn execute(
    deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg,
) -> StdResult<Response> {
    match msg {
        ExecuteMsg::Delegate { validator, amount } => {
            execute_delegate(deps, env, info, validator, amount)
        }
        _ => Ok(Response::new()),
    }
}

pub fn execute_delegate(
    deps: DepsMut, _env: Env, info: MessageInfo,
    validator: String, amount: Uint128,
) -> StdResult<Response> {
    let config = CONFIG.load(deps.storage)?;
    if info.sender != config.owner {
        return Err(cosmwasm_std::StdError::generic_err("unauthorized"));
    }
    let delegate_msg = CosmosMsg::Staking(cosmwasm_std::StakingMsg::Delegate {
        validator: validator.clone(),
        amount: Coin { denom: "umsg".to_string(), amount },
    });
    Ok(Response::new().add_message(delegate_msg))
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ExecuteMsg {
    Delegate { validator: String, amount: Uint128 },
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
    pub owner: String,
    pub default_validator: String,
}

附录

A. MSG Chain RPC 端点

服务 端点
Tendermint RPC https://rpc.msg-chain-1.msg.network
REST/LCD API https://api.msg-chain-1.msg.network
WebSocket wss://rpc.msg-chain-1.msg.network/websocket
gRPC grpc.msg-chain-1.msg.network:443

B. Gas 费用估算

操作 Gas 上限 费用 (umsg)
MsgDelegate 200,000 5,000
MsgUndelegate 250,000 6,250
MsgBeginRedelegate 300,000 7,500
MsgVote 100,000 2,500
MsgSubmitProposal 500,000 12,500
ProvideLiquidity 400,000 10,000
CW20 Transfer 150,000 3,750

C. Bech32 地址格式

用途 前缀
账户地址 msg1
验证人操作地址 msgvaloper1
合约地址 msg1

本指南针对 MSG Chain (msg-chain-1) 代币经济体系,代码示例仅供架构参考。