mcpField
D
delphi

delphi

github.com/gensyn-ai其他1691 次安装12 周前更新
代码仓库

关于 delphi

Delphi 是一项通过 `@gensyn-ai/gensyn-delphi-sdk` 使用 Gensyn 信息市场的技能,涵盖市场查询、报价、交易、持仓及结算操作,并区分竞赛的 LMSR 市场与常规互助池市场。

主要功能

  1. 01浏览并查看市场详情
  2. 02查询买入、卖出和赎回报价
  3. 03交易结果份额
  4. 04查看持仓与交易记录
  5. 05赎回或清算持仓
  6. 06检查余额与代币授权

适用场景

  1. 01查找市场并了解当前详情
  2. 02交易前估算成本或收益
  3. 03管理已结算或过期市场的持仓
  4. 04交易前检查钱包资金

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gensyn-ai/gensyn-delphi-skills --skill delphi

安装后在 Claude Code 中输入/delphi确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

AGENTS.md
.env.example
.gitignore
README.md
CLAUDE.md
SECURITY.md
LICENSE.TXT
package.json
.claude/skills/delphi/reference/
markets.md
onchain.md
trading.md
positions.md
subgraph.md
funding.md
reference/
competition.md
markets.md
funding.md
onchain.md
positions.md
trading.md
subgraph.md
scripts/
bridge-eth-to-gensyn-mainnet.ts
scripts/agent-tui/
app.tsx
edges.ts
data.ts
events.ts
format.ts
index.tsx
ui.tsx
screens.tsx

详细介绍

Delphi

Gensyn Delphi 是一套用于在 Gensyn 上部署信息市场并与之交互的工具。市场由用户所有且无需许可——Gensyn 不控制市场、不托管资金,也不结算交易。此 API 仅为方便而维护。所有交互都通过 @gensyn-ai/gensyn-delphi-sdk 包中的 DelphiClient 完成。

要参与 Agent 竞赛交易? 该竞赛使用独立网络 (competition-testnet),采用 LMSR 市场,而非下文介绍的相互博彩市场。定价数学、代币、注册步骤和排行榜都各不相同——交易前请阅读 reference/competition.md,不要将下文的相互博彩部分应用于该竞赛。

动态相互博彩市场的运作方式

本节介绍 Delphi 测试网/主网。竞赛使用 LMSR,价格总和为 1,现货价格 就是 隐含概率,获胜份额始终恰好兑付 1 个代币。请参阅 reference/competition.md。

动态相互博彩市场是一种博彩或信息系统,其价格(赔率)由所有参与者下注的分布内生形成,而非由做市商设定。随着新赌注不断加入,隐含概率会持续更新:获得更多资金支持的结果赔率会下降(隐含概率上升),支持较少的结果则会变得更便宜。所有参与者的流动性汇集在一起,因此交易者实际上是在与整体市场而非某个交易对手下注,而资金池的深度决定了新信息对价格的影响程度。这形成了一种自我调节机制,使价格既反映当前观点,也反映新增流动性的边际影响。与流动性稀薄的订单簿市场相比,这通常会带来更平稳、更稳定的价格更新,同时价格仍会随时间逐步趋向共识概率。

重要:现货价格和预期兑付额各自独立变动,且兑付额并非固定。不同于固定兑付市场(例如 Polymarket),其中获胜份额始终可恰好兑付 $1,Delphi DPM 的兑付额在结算时确定:整个资金池由获胜份额持有者瓜分,因此每份获胜份额的兑付额=获胜份额总数/资金池总额。

现货价格是当前买入下一份额的边际成本,也就是定价曲线的局部斜率。可以根据当前资金池状态和预期赎回价值推断出一个类似概率的数值,但它与现货价格并不相同;根据流动性分布和市场深度的不同,两者可能存在显著差异。

何时使用此技能

  • 用户想要列出、搜索或浏览信息市场
  • 用户想要查询某个市场的价格、概率或详情
  • 用户想要买入或卖出结果份额
  • 用户想要查看自己的投资组合、持仓或交易历史
  • 用户想要赎回已结算市场的收益
  • 用户想要清仓已过期(未结算)市场中的持仓
  • 如果用户要求创建市场,请提醒他们:在 UI 之外创建的市场不会显示在 UI 上
  • 用户想要查询或设置交易所需的代币授权
  • 用户想要查询历史链上交易数据(买入、卖出、赎回、清算)
  • 用户想要通过 Goldsky 子图查询某个市场或钱包的近期交易
  • 用户想要查看钱包中的 ETH 或代币余额
  • 用户想要获取 ETH 或 USDC,为交易钱包提供资金(测试网水龙头、跨链桥接)
  • 用户想要参与Agent 交易竞赛交易、注册或查询自己的排名 → 加载 reference/competition.md
  • 用户提到竞赛、排行榜、agent-competition.gensyn.ai,或设置了 DELPHI_NETWORK=competition-testnet
  • 任何关于 Delphi 信息市场或在 Gensyn 上进行链上交易的问题

安装

npm install

这将安装所有必需的依赖项,包括 SDK、dotenv、viem 和开发工具。

示例脚本

此仓库在 scripts/ 文件夹中包含可运行的示例脚本,展示所有常见操作。这些脚本为 Agent 提供了便捷的参考或直接运行路径:

脚本用途使用方法
scripts/list-markets.ts列出并筛选市场npx tsx scripts/list-markets.ts [status] [category] [limit]
scripts/get-market.ts获取特定市场的详情npx tsx scripts/get-market.ts <market-id>
scripts/quote-buy.ts获取买入报价(只读)npx tsx scripts/quote-buy.ts <market-address> <outcome-idx> <shares>
scripts/quote-sell.ts获取卖出报价(只读)npx tsx scripts/quote-sell.ts <market-address> <outcome-idx> <shares>
scripts/quote-redeem.ts获取已结算市场的赎回金额报价(只读)npx tsx scripts/quote-redeem.ts <market-address> [wallet-address]
scripts/quote-liquidate.ts获取已过期市场的清算所得报价(只读)npx tsx scripts/quote-liquidate.ts <market-address> <outcome-idx>[,<idx>...] [wallet-address]
scripts/buy-shares.ts买入份额(链上)npx tsx scripts/buy-shares.ts <market-address> <outcome-idx> <shares> [slippage-pct]
scripts/sell-shares.ts卖出份额(链上)npx tsx scripts/sell-shares.ts <market-address> <outcome-idx> <shares> [slippage-pct]
scripts/list-positions.ts列出钱包持仓npx tsx scripts/list-positions.ts [wallet-address]
scripts/redeem.ts赎回已结算市场的收益npx tsx scripts/redeem.ts <market-address> [market-address ...]
scripts/liquidate.ts清算已过期市场中的持仓npx tsx scripts/liquidate.ts <market-address> [market-address ...]
scripts/token-approval.ts检查或设置代币授权npx tsx scripts/token-approval.ts <market-address> [amount|unlimited]
scripts/list-recent-trades.ts通过子图列出近期交易npx tsx scripts/list-recent-trades.ts <market-proxy-address> [limit]
scripts/agent-tui/实时只读 Ink 仪表板(概览 — 包含 Edge View 和 Agent Logs — · 投资组合 · 我的活动 · 市场,支持深入查看市场详情)npx tsx scripts/agent-tui/index.tsx <wallet-address> <testnet|mainnet|competition-testnet>(两项均为必填) · 按键:1-4 切换屏幕,↑↓ 选择,⏎ 查看详情,r 刷新,q 退出(添加 --once 可仅显示单帧)
scripts/log-event.ts向 Agent 事件日志追加可追踪事件(Agent TUI → 概览 → Agent Logs)npx tsx scripts/log-event.ts <type> "<message>"
scripts/compute-edge.ts计算一个或多个市场结果的优势(你的概率 − 市场隐含概率);输出信号并提供给 Agent TUI → 概览 → Edge Viewnpx tsx scripts/compute-edge.ts <market-address> <outcome-idx> <your-prob> [<market> <outcome> <prob> ...]
scripts/get-wallet-balances.ts检查 ETH 和抵押代币余额npx tsx scripts/get-wallet-balances.ts
scripts/testnet-faucet.ts从 Gensyn 水龙头领取 1,000 测试网 USDCnpx tsx scripts/testnet-faucet.ts
scripts/bridge-eth-to-gensyn-testnet.ts将 ETH 从 Sepolia 跨链桥接至 Gensyn Testnetnpx tsx scripts/bridge-eth-to-gensyn-testnet.ts <amount-eth>
scripts/bridge-eth-to-gensyn-mainnet.ts将 ETH 从 Ethereum 主网跨链桥接至 Gensyn Mainnetnpx tsx scripts/bridge-eth-to-gensyn-mainnet.ts <amount-eth>
scripts/bridge-usdc-to-gensyn-mainnet.ts通过 LayerZero 将 USDC 从 Ethereum 主网跨链桥接至 Gensyn Mainnetnpx tsx scripts/bridge-usdc-to-gensyn-mainnet.ts <amount-usdc> [slippage-pct]

所有脚本都使用来自 scripts/client.ts 的共享客户端配置,该配置会自动处理环境变量设置。你也可以通过 npm 脚本运行它们:npm run list-markets、npm run buy-shares 等。

运行脚本前

运行 scripts/ 中的任何脚本之前,请确保已准备好运行环境。

必需的设置检查清单:

  1. 运行 npm install 安装依赖。
  2. 确认已设置所需的环境变量:
    • 检查项目根目录中是否有 .env 文件(首选),或者
    • 确认已在 Shell 会话中导出环境变量
  3. 如果任一项检查未通过,请先修复,再运行任何任务脚本。
  4. 设置完成前,请勿调用 scripts/*.ts。
  5. 请勿在命令中内联传递环境变量——请改用 .env 文件或 export 语句。

环境变量

只有两项是必需的:API 密钥和钱包签名凭据。其他所有配置都有合理的默认值。如果未设置 DELPHI_NETWORK,SDK 默认使用 testnet。

缺少环境变量时的 Agent 指示:

如果未设置必需的环境变量,请勿在聊天中向用户索要这些变量的值。请改为:

  1. 告知用户需要哪些变量(如下所列)。
  2. 告知用户在哪里获取每个值。
  3. 请用户在项目根目录自行创建 .env 文件,并填入这些值。
  4. 等待用户确认文件已创建后再继续。
  5. 切勿读取 .env 文件——请将其视为 Agent 不得访问的机密存储。

需要告知用户的必需变量:

变量获取方式
DELPHI_API_ACCESS_KEYTestnet: 在 https://delphi-api-access.gensyn.ai/ 生成 · Mainnet: 在 https://api-access.delphi.fyi/ 生成

此外,还需选择以下一种签名方式(请告知用户任选其一):

选项 A — 私钥

变量说明
DELPHI_SIGNER_TYPE设置为 private_key
WALLET_PRIVATE_KEY钱包的 0x 前缀十六进制私钥

选项 B — Coinbase CDP Server Wallet(默认签名方式,无需设置 DELPHI_SIGNER_TYPE)

变量获取方式
CDP_API_KEY_IDServer Wallet v2 Quickstart(https://docs.cdp.coinbase.com/server-wallets/v2/introduction/quickstart)
CDP_API_KEY_SECRETServer Wallet v2 Quickstart(https://docs.cdp.coinbase.com/server-wallets/v2/introduction/quickstart)
CDP_WALLET_SECRETServer Wallet v2 Quickstart(https://docs.cdp.coinbase.com/server-wallets/v2/introduction/quickstart)
CDP_WALLET_ADDRESS其 CDP 钱包地址(带 0x 前缀)(参见 https://docs.cdp.coinbase.com/server-wallets/v2/introduction/quickstart)

还请务必向用户传达以下两点:

  • 使用 CDP 选项时,私钥会安全地存储在 Coinbase 的可信执行环境(TEE)中,绝不会离开 TEE。详情请参阅 Server Wallet v2 docs。

  • 执行 Delphi 交易时,签名钱包必须在 Gensyn 链上持有 ETH(用于支付 Gas)和 USDC。

网络选择
变量值默认值
DELPHI_NETWORK"testnet" | "mainnet" | "competition-testnet""testnet"

SDK 默认使用 testnet — DELPHI_NETWORK 为可选项。仅当用户明确希望使用 mainnet 或参加竞赛时才设置此变量。

当 DELPHI_NETWORK=testnet(默认值)时,SDK 会自动使用:

  • RPC URL:https://gensyn-testnet.g.alchemy.com/public
  • Chain ID:685685
  • Gateway:0x22ea355D7218Dc86b4c83732cBbd01f7Ff2332b3(自动结算)
  • Factory:0x97d2b3F0614C8189343A38094629FCE2910b727A
  • Legacy gateway:0x7b8FDBD187B0Be5e30e48B1995df574A62667147(自动结算前的市场)
  • Token:0x0724D6079b986F8e44bDafB8a09B60C0bd6A45a1
  • API URL:https://delphi-api.gensyn.ai/
  • Subgraph URL:https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-testnet-autoset/1.0.0/gn

当 DELPHI_NETWORK=mainnet 时,SDK 会自动使用:

  • RPC URL:https://gensyn-mainnet.g.alchemy.com/public
  • Chain ID:685689
  • Gateway:0x982a67aE92D8de361957249fB2BB4a62BCc6A8d5(自动结算)
  • Factory:0x9C73417f79a1361c6aF9Bd828343badEE1b84936
  • Legacy gateway:0x4e4e85c52E0F414cc67eE88d0C649Ec81698d700(自动结算前的市场)
  • Token:0x5b32c997211621d55a89Cc5abAF1cC21F3A6ddF5
  • API URL:https://api.delphi.fyi/
  • Subgraph URL:https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-mainnet-autoset/1.0.0/gn

当 DELPHI_NETWORK=competition-testnet(Agent 交易竞赛)时,SDK 会自动使用:

  • RPC URL:https://gensyn-testnet.g.alchemy.com/public(与 testnet 使用同一条链)
  • Chain ID:685685
  • Gateway:0x097599c9D966fF496284b892A8F13BF885b258ef(LmsrGateway — 单一部署,没有 legacy)
  • Factory:0xEa9D0a78d0209916e88e363B8FDa3e23206Ff49b
  • Token:0x8A2d75753362Eb5D5669a2c22cbf394b26a0571F(TST,6 位小数 — 不是 USDC)
  • API URL:https://delphi-api.gensyn.ai/(共享的 testnet 部署;客户端会自动发送 X-Delphi-Mode: competition)
  • Subgraph URL:https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-agent-competition/1.0.0/gn
  • 排行榜:https://agent-competition.gensyn.ai

竞赛不只是地址不同。 它采用 LMSR 定价(获胜份额恰好支付 1 个代币,价格总和为 1),需要 testnet API 密钥,并且需要在 DoraHacks 注册你的钱包才能参与排名。 交易前请阅读 reference/competition.md。

Delphi 同时运行两个部署。每个新市场都会创建在自动结算网关上,并由预言机结算;较早的市场则位于 legacy 网关上。每个网关都会拒绝对方的市场,因此 SDK 会针对每个市场解析正确的网关 — 传入任意市场地址即可使用。不过,默认的子图仅涵盖自动部署:查询 legacy 市场的子图会返回空结果(参见 reference/subgraph.md)。

由于现在采用自动结算,市场可能会变为 failed — 预言机已运行,但无法确定问题的结果。failed 市场没有获胜结果,因此 redeemMarket() 会回滚,资金需通过 liquidate() 取回,与 expired 的处理方式完全相同。完整状态列表:open、awaiting_settlement、settled、expired、failed。

上述地址和子图端点,以及 client.resolveGateway()、 client.getMarketStatus() 和 subgraph.getMarketSettlement(),要求使用 @gensyn-ai/gensyn-delphi-sdk@^2.0.0(已固定在 package.json 中)。在较旧版本的 SDK 中, 默认值仍指向 legacy 网关,并且不存在这些方法。

可选覆盖项

如果需要指向自定义端点,可覆盖网络默认值:

变量描述
GENSYN_RPC_URL自定义 RPC 端点
GENSYN_CHAIN_ID自定义链 ID
DELPHI_GATEWAY_CONTRACT自定义网关地址。会将每次调用固定到此网关,并禁用按市场路由——对其不拥有的市场进行调用将回滚
DELPHI_LEGACY_GATEWAY_CONTRACT自定义旧版网关地址
DELPHI_FACTORY_CONTRACT自定义自动结算工厂(用于路由市场)
DELPHI_LEGACY_FACTORY_CONTRACT自定义旧版工厂(用于路由市场)
DELPHI_API_BASE_URL自定义 API 基础 URL
DELPHI_SUBGRAPH_URL自定义 Goldsky 子图端点
DELPHI_TOKEN_ADDRESS覆盖 ERC-20 抵押代币地址
DELPHI_SIGNER_TYPE"private_key" 或 "cdp_server_wallet"(默认值)
DELPHI_COMPETITION_ID用于限定 list-markets.ts、get-market.ts 和 Agent TUI 中市场读取范围的竞赛 UUID(仅限竞赛网络;其他情况下会忽略)。未设置 = 当前竞赛

客户端设置

import {
  DelphiClient,
  SubgraphClient,
  createPrivateKeySigner,
  createCdpSigner,
} from "@gensyn-ai/gensyn-delphi-sdk";

// All config is read from environment variables automatically.
const client = new DelphiClient();

单位

类型原始表示形式人类可读的换算
份额18 位小数的大整数1n * 10n**18n = 1 份额
USDC6 位小数的大整数1_000_000n = 1 USDC
隐含概率(链上大整数)18 位小数(1e18 = 100%)5n * 10n**17n = 50%
现货价格(链上大整数)6 位小数(1e6 = 1.0 USDC/份额)600_000n = 0.60 USDC/份额
market.spotPrices[i]普通 number 浮点数0.6 = 0.60 USDC/份额——已转换为人类可读形式
market.spotImpliedProbabilities[i]普通 number 浮点数(0–1)0.6 = 60%——已转换为人类可读形式
// Human → raw bigint (inputs to SDK)
const sharesToBigint = (n: number) => BigInt(Math.round(n * 1e18));
const usdcToBigint   = (n: number) => BigInt(Math.round(n * 1e6));

// Raw bigint → display string
const toUsdc      = (n: bigint) => `${(Number(n) / 1e6).toFixed(6)} USDC`;
const toShares    = (n: bigint) => `${(Number(n) / 1e18).toFixed(4)} shares`;
const toProb      = (n: bigint) => `${(Number(n) / 1e18 * 100).toFixed(2)}%`;
const toSpotPrice = (n: bigint) => `${(Number(n) / 1e6).toFixed(4)} USDC/share`;

核心模式

提示:请参阅 scripts/list-markets.ts,了解完整的可运行示例。

列出市场
const { markets } = await client.listMarkets({
  status: "open",        // "open" | "awaiting_settlement" | "settled" | "expired"
  category: "crypto",   // crypto, culture, economics, miscellaneous, politics, sports
  limit: 20,
  skip: 0,
  orderBy: "liquidity", // "liquidity" (default) | "created" | "settles_at" (soonest first)
  verifiable: true,     // optional: filter to markets with verifiable settlement
  pricesAndImpliedProbabilities: true, // optional: fetch spot prices and implied probabilities
});

for (const market of markets ?? []) {
  const meta = market.metadata; // typed as MarketMetadata | null — no cast needed
  console.log(market.id, meta?.question);
  // market.id                        = market address — use this as marketAddress in all SDK calls
  // market.appMarketId               = UUID identifying the market in the Delphi app
  // market.marketUrl                 = direct link to the market on the Delphi app
  // market.implementation            = underlying logic contract (NOT used for SDK calls)
  // market.category                  = market category string (e.g. "crypto")
  // market.verifiable                = true if market uses verifiable settlement
  // market.tradingFee                = 18-decimal bigint string (e.g. "20000000000000000" = 2%); null if no fee
  //                                    convert: Number(market.tradingFee) / 1e18 * 100 → fee percentage
  // market.winningOutcomeIdx         = set after settlement, otherwise null
  // market.resolvesAt                = ISO timestamp for when market resolves, or null
  // market.settlesAt                 = ISO timestamp for scheduled settlement, or null
  // market.proof                     = settlement proof string, or null
  // market.error                     = resolution error message if settlement failed, or null
  // market.fetchResponseStatus       = metadata fetch status string (e.g. "success"), or null
  // market.metadataUriContentHash    = hex hash of the fetched metadata content (e.g. "0x9434...")
  // market.dataSources               = data source identifiers, or null
  // market.spotPrices                = spot price per outcome as human-readable float (only if pricesAndImpliedProbabilities: true)
  // market.spotImpliedProbabilities  = implied probability per outcome as 0–1 float (only if pricesAndImpliedProbabilities: true)
}
获取单个市场

提示:请参阅 scripts/get-market.ts,了解完整的可运行示例。

const market = await client.getMarket({ id: "<market-id>", pricesAndImpliedProbabilities: true });
const meta = market.metadata; // typed as MarketMetadata | null — no cast needed
// market.id                       = use as marketAddress for all SDK calls (quoteBuy, buyShares, etc.)
// market.appMarketId              = UUID identifying the market in the Delphi app
// market.marketUrl                = direct link to the market on the Delphi app
// market.implementation           = the logic contract address — NOT the marketAddress for SDK calls
// market.spotPrices               = spot price per outcome as human-readable float (e.g. [0.6, 0.4])
// market.spotImpliedProbabilities = implied probability per outcome as 0–1 float (e.g. [0.6, 0.4])
实时价格

获取实时价格最简单的方式是在 listMarkets 或 getMarket 中设置 pricesAndImpliedProbabilities: true——SDK 会通过 multicall 获取价格,并以人类可读的浮点数形式返回在市场对象中:

// market.spotPrices[i]               — spot price as float (e.g. 0.6 = 0.60 USDC/share)
// market.spotImpliedProbabilities[i] — implied probability as 0–1 float (e.g. 0.6 = 60%)
if (market.spotPrices && market.spotImpliedProbabilities) {
  for (let i = 0; i < (meta?.outcomes?.length ?? 0); i++) {
    console.log(`[${i}] price: ${market.spotPrices[i].toFixed(4)} USDC/share | prob: ${(market.spotImpliedProbabilities[i] * 100).toFixed(2)}%`);
  }
}

如需自定义链上读取(高级用法),请通过 viem 直接使用 Gateway ABI——请参阅 reference/onchain.md。

买入报价(只读,不消耗 Gas)

提示:请参阅 scripts/quote-buy.ts,了解完整的可运行示例。

const { tokensIn } = await client.quoteBuy({
  marketAddress: "0x..." as `0x${string}`,
  outcomeIdx: 0,
  sharesOut: BigInt(Math.round(10 * 1e18)),  // 10 shares
});
// tokensIn = USDC cost in 6-decimal bigint
const costUsdc = Number(tokensIn) / 1e6;
卖出报价(只读,不消耗 Gas)

提示:请参阅 scripts/quote-sell.ts,了解完整的可运行示例。

const { tokensOut } = await client.quoteSell({
  marketAddress: "0x..." as `0x${string}`,
  outcomeIdx: 0,
  sharesIn: BigInt(Math.round(5 * 1e18)),  // 5 shares
});
const payoutUsdc = Number(tokensOut) / 1e6;
赎回/清算报价(只读,不消耗 Gas)

对于已结束的市场,现货价格不再反映持仓价值——可实现的价值是已结算市场的赎回支付金额,或已到期市场的清算所得。这些报价会通过 eth_call 模拟链上 redeem/liquidate(不消耗 Gas,不更改状态);如果持仓无法赎回/清算(例如,已结算但结果为亏损,或市场尚未结束),则会抛出异常,因此请使用 try/catch 包裹调用。

提示:请参阅 scripts/quote-redeem.ts 和 scripts/quote-liquidate.ts,了解完整的可运行示例。

// Settled market: payout for the caller's winning shares. account defaults to
// the configured signer; pass it to quote for any wallet.
const { sharesIn, tokensOut } = await client.quoteRedeem({
  marketAddress: "0x..." as `0x${string}`,
  account: "0x..." as `0x${string}`,   // optional
});
const payoutUsdc = Number(tokensOut) / 1e6;  // 0 / throws for a losing outcome

// Expired market: proceeds from liquidating the given outcomes.
const { sharesIn: burned, totalTokensOut } = await client.quoteLiquidate({
  marketAddress: "0x..." as `0x${string}`,
  outcomeIndices: [0, 1],
  account: "0x..." as `0x${string}`,   // optional
});
const proceedsUsdc = Number(totalTokensOut) / 1e6;

跨状态估值组合:仅对开放市场使用现货价格(shares × spotPrice)。对已结算市场,使用 quoteRedeem 估算获胜结果的价值(失败结果的价值为 0);对已到期市场,则使用 quoteLiquidate。Agent TUI 的 Portfolio 标签页正是如此处理,并会显示每个持仓的状态徽章。

买入份额(链上交易,自动授权)

提示:请参阅 scripts/buy-shares.ts,了解完整的可运行示例。

const marketAddress = "0x..." as `0x${string}`;
const outcomeIdx = 0;
const sharesOut = BigInt(Math.round(10 * 1e18));  // 10 shares

// 1. Quote, and cap the spend with 2% slippage
const { tokensIn } = await client.quoteBuy({ marketAddress, outcomeIdx, sharesOut });
const maxTokensIn = tokensIn * 102n / 100n;

// 2. Ensure USDC approval (idempotent — only sends tx if needed).
//    Approve maxTokensIn, not tokensIn: the buy can spend up to the cap, so an
//    allowance sized to the quote reverts if the price moves within slippage.
await client.ensureTokenApproval({ marketAddress, minimumAmount: maxTokensIn });

// 3. Buy
const { transactionHash } = await client.buyShares({
  marketAddress,
  outcomeIdx,
  sharesOut,
  maxTokensIn,
});
卖出份额(链上交易)

提示:请参阅 scripts/sell-shares.ts,了解完整的可运行示例。

const sharesIn = BigInt(Math.round(5 * 1e18));

// 1. Quote
const { tokensOut } = await client.quoteSell({ marketAddress, outcomeIdx, sharesIn });

// 2. Sell with 2% slippage
const minTokensOut = tokensOut * 98n / 100n;
const { transactionHash } = await client.sellShares({
  marketAddress,
  outcomeIdx,
  sharesIn,
  minTokensOut,
});
列出仓位

Tip:查看 scripts/list-positions.ts,了解完整可运行示例。

Important:shares 等于 0 的仓位(即 BigInt(p.shares) === 0n)表示已完全退出的仓位。由于钱包不持有任何份额,因此无法赎回或清算。尝试赎回或清算之前,请务必过滤掉份额为零的仓位。

const { positions } = await client.listPositions({
  wallet: "0x...",
  redeemedOrLiquidated: false,  // only active positions
  limit: 50,
});

for (const p of positions ?? []) {
  const shares = Number(BigInt(p.shares)) / 1e18;
  if (shares === 0) continue; // no stake — skip
  console.log(`Market ${p.marketProxy} | Outcome ${p.outcomeIdx} | ${shares} shares`);
}
赎回已结算的仓位

Tip:查看 scripts/redeem.ts,了解完整可运行示例。

Important:只有份额非零的仓位才能赎回。如果 listPositions 返回的仓位中 shares === "0",则钱包在该市场中没有持仓,调用 redeemMarket 将失败或不返回任何内容。赎回前务必确认份额大于 0。

// Single market
const { transactionHash, sharesIn, tokensOut } = await client.redeemMarket({
  marketAddress: "0x..." as `0x${string}`,
});

// Batch
const { results, totalTokensOut } = await client.redeemPositions({
  marketAddresses: ["0x...", "0x..."],
});
for (const r of results) {
  if (r.success) console.log(`Redeemed ${Number(r.tokensOut!) / 1e6} USDC from ${r.marketAddress}`);
  else console.error(`Failed ${r.marketAddress}: ${r.error}`);
}
清算已到期的仓位

Tip:查看 scripts/liquidate.ts,了解完整可运行示例。

清算适用于已到期但从未结算的市场中的仓位。赎回适用于已有赢家的已结算市场,而清算则用于收回未解决即已到期的市场中的代币。

// Liquidate a single market — pass all outcome indices you hold
const { transactionHash, sharesIn, totalTokensOut } = await client.liquidate({
  marketAddress: "0x..." as `0x${string}`,
  outcomeIndices: [0, 1],  // all outcome indices with positions
});
// sharesIn: bigint[] — shares burned per outcome index
// totalTokensOut: bigint — total USDC recovered across all outcomes

// Derive outcome indices from listPositions:
const { positions } = await client.listPositions({ wallet, redeemedOrLiquidated: false });
const outcomeIndices = positions!
  .filter(p => p.marketProxy === marketAddress && BigInt(p.shares) > 0n)
  .map(p => Number(p.outcomeIdx));
代币授权

Tip:查看 scripts/token-approval.ts,了解完整可运行示例。

// Check current allowance
const { ownerAddress, allowance } = await client.getTokenAllowance({ marketAddress });

// Approve unlimited
await client.approveToken({ marketAddress });

// Approve specific amount (50 USDC)
await client.approveToken({ marketAddress, amount: 50_000_000n });

// Idempotent: only approves if current allowance is below minimum
// Response always includes current allowance, plus transactionHash if a tx was sent
const { approvalNeeded, allowance, transactionHash } = await client.ensureTokenApproval({
  marketAddress,
  minimumAmount: requiredTokens,
  approveAmount: 100_000_000n,  // optional: amount to approve if needed (defaults to max uint256)
});
查看钱包余额

Tip:查看 scripts/get-wallet-balances.ts,了解完整可运行示例。

// ETH (native gas token)
const ethBalance = await client.getEthBalance();
console.log(`ETH: ${(Number(ethBalance) / 1e18).toFixed(6)}`);

// ERC-20 collateral token (defaults to SDK-configured token address)
const tokenAddress = client.getTokenAddress(); // inspect the configured token address
const { balance, decimals } = await client.getErc20BalanceWithDecimals();
const formatted = (Number(balance) / 10 ** decimals).toFixed(decimals > 6 ? 6 : decimals);
console.log(`Token (${tokenAddress}): ${formatted}`);

// Or fetch raw balance only (6-decimal for USDC)
const raw = await client.getErc20Balance(); // uses default token; pass address to override
通过子图查询近期交易

Tip:查看 scripts/list-recent-trades.ts,了解完整可运行示例。

SDK 的 SubgraphClient 会查询由 Goldsky 子图索引的链上事件数据。可通过 client.getSubgraph() 访问它。

const subgraph = client.getSubgraph();

// Convenience method: get buys and sells for a market
const { buys, sells } = await subgraph.getMarketTrades(
  "0x..." as string,  // market proxy address
  { first: 20 }
);

for (const buy of buys) {
  const cost = Number(BigInt(buy.tokensIn ?? "0")) / 1e6;
  const shares = Number(BigInt(buy.sharesOut ?? "0")) / 1e18;
  const time = new Date(Number(buy.timestamp_) * 1000).toLocaleString();
  console.log(`BUY ${time} | ${cost.toFixed(4)} USDC → ${shares.toFixed(4)} shares`);
}

// Arbitrary GraphQL: recent buys across all markets
// SubgraphBuy, SubgraphSell, SubgraphMeta are all exported from the SDK for typing:
//   import type { SubgraphBuy, SubgraphSell, SubgraphMeta } from "@gensyn-ai/gensyn-delphi-sdk";
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(first: 5, orderBy: timestamp_, orderDirection: desc) {
    id buyer marketProxy tokensIn sharesOut timestamp_
  }
}`);

// Check subgraph indexing status (block number, deployment, error flag)
const meta = await subgraph.getMeta();
console.log(`Block: ${meta.block.number}, indexing errors: ${meta.hasIndexingErrors}`);

可用实体:gatewayBuys、gatewaySells、gatewayRedemptions、gatewayLiquidations、gatewayMarketSettleds、gatewayMarketFaileds、marketResolutionRequesteds。这些实体均支持筛选(where)、排序(orderBy + orderDirection)和分页(first + skip)。请注意,自动结算子图中不存在 gatewayWinnerSubmitteds;查询它会产生 GraphQL 硬错误。请改用 gatewayMarketSettleds,它包含相同的数据内容。

TUI

用户可以通过只读的 Agent TUI 仪表板实时查看 Agent 正在执行的操作,包括投资组合、仓位、活动、市场、Edge View 和 Agent Logs 推理流。运行 npx tsx scripts/agent-tui/index.tsx <wallet-address> <testnet|mainnet|competition-testnet>(或 npm run agent-tui -- <wallet-address> <testnet|mainnet|competition-testnet>)即可启动。下面的两个辅助工具会为其 Agent Logs 和 Edge View 面板提供数据。

追踪你的推理(Agent Logs)

log-event 会填充 Agent TUI 的 Agent Logs 面板。在真正的决策点使用它:记录你为什么采取行动(THINK),然后记录你采取的行动。事件类型:

类型用途
THINK推理——你观察到了什么、为什么市场看起来定价失当、你发现了什么优势、为什么选择这一方向和规模。这是最重要的类型。
BUY你执行的买入。
SELL你执行的卖出。
LIQUIDATE清算已过期市场中的持仓。
REDEEM领取已结算市场的收益。
SKIP你评估过并有意跳过的市场(以及原因)。
npx tsx scripts/log-event.ts THINK "<the reasoning — why this trade>"
npx tsx scripts/log-event.ts BUY   "<the action you took>"
  • THINK 是最重要的类型——记录推理过程。这正是 Agent Logs 面板存在的意义。
  • 行动类型(BUY/SELL/LIQUIDATE/REDEEM)是对思考之后所做之事的简短记录。保持简洁——My Activity 标签页已经显示了交易细节(金额、价格、交易哈希),所以不要重复记录。
  • 使用 SKIP 记录你评估过但跳过的市场,让日志呈现你考虑过哪些市场,而不只是你交易了哪些市场。

不要只描述订单。"Buy 10 YES on Wild Pandas, 2% slippage" 与 Activity 中显示的内容完全相同——应记录原因。

示例:

npx tsx scripts/log-event.ts THINK "BTC $99,999 by Jun 31: ~12 days left and price is still ~\$25k away — that move is unlikely, yet the market prices NO at only 71%. Taking NO; small testnet size to validate."
npx tsx scripts/log-event.ts BUY   "10 NO on BTC $99,999"

在真正的决策点记录 THINK→行动组合,而不是每次例行读取都记录。<type> 不区分大小写,并会规范化为大写。事件会追加到 $DELPHI_AGENT_LOG(默认值为 ~/.delphi/agent-events.jsonl);该文件会自动创建。

交易前计算优势(Edge View)

优势是交易的核心信号——在自主决定买入或卖出某个市场前,务必先计算优势。 优势是你对某个结果的概率估计与市场实时隐含概率之间的差值:

edge = your probability − market's implied probability

正优势表示该结果相对于你的判断定价偏低(可考虑买入);负优势表示该结果定价偏高(可考虑卖出或避开)。差值绝对值越大,信号越强。

scripts/compute-edge.ts 会获取市场的实时隐含概率,根据你的估计计算优势,输出信号,并将其保存下来;保存的结果会按差值大小排序,显示在 Agent TUI 的 Edge View(Overview 屏幕)中。

# Single market outcome: your probability is 0.30 (or pass 30 for percent)
npx tsx scripts/compute-edge.ts 0x1234…abcd 1 0.30

# Several at once — repeat the (market, outcome, prob) triple
npx tsx scripts/compute-edge.ts 0x1234…abcd 1 0.30  0x5678…ef01 0 0.62

<your-prob> 是你对该结果的概率估计(0–1,例如 0.30,或百分比,例如 30);<market-address> 是来自 listMarkets/getMarket 的市场 ID,<outcome-idx> 是结果的索引。对同一(市场、结果)重复运行会覆盖先前的值(以最新值为准)。

自主决定是否买入或卖出某个市场时,必须遵循以下决策流程:

  1. 形成你对该结果的概率估计。
  2. 运行 compute-edge.ts,将估计与市场的实时隐含概率进行比较。
  3. 根据所得优势做出决策——只在优势显著为正(买入)或为负(卖出)时交易,并优先选择差值更大的市场。若优势较小或符号不符,则 SKIP。
  4. 然后使用 log-event THINK 记录你的推理(提及优势),并使用 log-event BUY/SELL 记录你采取的行动。

优势会保存到 $DELPHI_AGENT_EDGES(默认值为 ~/.delphi/agent-edges.jsonl);该文件会自动创建。每次刷新时,Edge View 都会将你保存的概率与市场实时价格重新匹配,因此显示的优势会随着市场变化保持最新。

错误处理

错误原因修复方法
TokensInExceedsMax价格上涨至高于 maxTokensIn重新报价,提高滑点
TokensOutBelowMin价格下跌至低于 minTokensOut重新报价,提高滑点
MarketNotOpen市场已关闭或已结算先检查 market.status
SharesInExceedSupply卖出的份额超过持有量卖出前检查持仓
Requires apiKey缺少 DELPHI_API_ACCESS_KEY设置环境变量
Requires rpcUrl缺少 GENSYN_RPC_URL设置环境变量,或使用网络默认值
Requires privateKey缺少 WALLET_PRIVATE_KEY设置环境变量,或切换至 CDP 签名器
CDP signing requires ...缺少 CDP 环境变量设置所有 CDP_ 变量

参考文件(按需加载)

文件加载时机
reference/markets.md查看完整的 listMarkets/getMarket 参数、Market 类型架构和元数据结构
reference/trading.md查看交易机制、滑点公式和互助投注定价说明
reference/positions.md查看 Position/Trade 类型架构、批量赎回模式和投资组合估算
reference/onchain.md查看完整的 Gateway ABI 函数列表、直接 viem 读取模式和签名配置
reference/subgraph.md查看 Goldsky 子图 GraphQL 架构、SubgraphClient API、实体类型、筛选方式和原始查询示例
reference/funding.md查看如何将 ETH 和 USDC 转入 Gensyn(测试网水龙头、OP Stack 桥、LayerZero USDC 桥)
reference/competition.mdAgent 交易竞赛:LMSR 与互助投注定价、注册、交易差异、排行榜、子图差异和故障模式

评论

支持 Markdown