买入与卖出
发一个请求,拿回一笔未签名的交易,由你自己的脚本签名并发送。下面的脚本是完整的:填上私钥、代币地址和金额,直接运行。

一个接口覆盖 Robinhood 链上所有 Pons 代币,不管哪一代发的、现在在哪:
- Pons v2:内盘联合曲线上,毕业后在它的 Uniswap v4 池子里。
- Pons v1:发射进的那个 Uniswap V3 池子里。
- Robinhood 链上任何有 Uniswap 池子的代币:代币化股票(NVDA、TSLA、USDG……)和直接发进池子的代币。
你只传代币地址,API 自动判断。返回里的 protocol(PONS_V2 / PONS_V1 / UNISWAP)和 venue(pons_curve、uniswap_v4、uniswap_v3)会告诉你结果。
你需要什么
- Node.js 或 Python。
- 一个钱包私钥,里面有一点 Robinhood 链上的 ETH。
- 一个代币地址。从 ponsfamily.com 任意代币页面 或 实时发射 里拿一个。
示例
- JavaScript
- Python
const { Wallet } = require("ethers");
// ─── 改这三行 ────────────────────────────────────────
const PRIVATE_KEY = "0xYOUR_PRIVATE_KEY";
const TOKEN = "0xTHE_TOKEN_ADDRESS";
const AMOUNT = "0.01"; // 买入:要花的 ETH。卖出:"1000" 个代币,或 "100%"
const ACTION = "buy"; // "buy" 或 "sell"
const TO_ETH = true; // 卖出以 USDG/NVDA 等计价的代币时,
// 顺便把所得换回 ETH
const SLIPPAGE = 5; // 滑点百分比,允许价格对你不利的幅度
// ──────────────────────────────────────────────────────
async function main() {
const wallet = new Wallet(PRIVATE_KEY); // 只用来签名,不连任何节点
const res = await fetch("https://api.shrine.trade/rh/api/local-trade", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
action: ACTION,
token: TOKEN,
amount: AMOUNT,
toEth: TO_ETH,
slippage: SLIPPAGE,
from: wallet.address,
}),
});
const data = await res.json();
if (data.error) throw new Error(`${data.error}: ${data.message}`);
console.log("预计得到约", data.quote.expectedOutFormatted,
ACTION === "buy" ? "tokens" : data.quoteAsset.symbol);
if (data.quoteSwap) {
console.log("先用", data.quoteSwap.ethInMaxFormatted, "ETH 买入",
data.quoteSwap.quoteOutFormatted, data.quoteAsset.symbol);
}
// 本地签名,把签好的交易交给 API 广播:私钥不会离开这个脚本,
// 你也不需要自己的 RPC。
for (const tx of data.txs) {
const signed = await wallet.signTransaction({
to: tx.to, data: tx.data, value: BigInt(tx.value), gasLimit: BigInt(tx.gas),
maxFeePerGas: BigInt(tx.maxFeePerGas), maxPriorityFeePerGas: BigInt(tx.maxPriorityFeePerGas),
nonce: tx.nonce, chainId: tx.chainId, type: 2,
});
const sent = await (await fetch("https://api.shrine.trade/rh/api/send", {
method: "POST", headers: { "content-type": "application/json" },
body: JSON.stringify({ signedTx: signed }),
})).json();
if (sent.error) throw new Error(`${sent.error}: ${sent.message}`);
if (sent.status !== "landed") throw new Error(`${tx.description} ${sent.status}: ${sent.explorer}`);
console.log(tx.description + ": " + sent.explorer);
}
if (ACTION === "buy") {
console.log(`买入 ${data.name} (${data.symbol}) ${data.token} 花费 ${data.ethInFormatted ?? data.amountInFormatted} ETH`);
} else if (data.toEth) {
console.log(`卖出 ${data.amountInFormatted} ${data.name} (${data.symbol}) ${data.token} 得到 ${data.toEth.ethOutFormatted} ETH`);
} else {
console.log(`卖出 ${data.amountInFormatted} ${data.name} (${data.symbol}) ${data.token} 得到 ${data.quote.expectedOutFormatted} ${data.quoteAsset.symbol}`);
}
}
main();
保存为 trade.js,然后:
npm install ethers
node trade.js
import requests
from eth_account import Account
# ─── 改这三行 ────────────────────────────────────────
PRIVATE_KEY = "0xYOUR_PRIVATE_KEY"
TOKEN = "0xTHE_TOKEN_ADDRESS"
AMOUNT = "0.01" # 买入:要花的 ETH。卖出:"1000" 个代币,或 "100%"
ACTION = "buy" # "buy" 或 "sell"
TO_ETH = True # 卖出以 USDG/NVDA 等计价的代币时,顺便把所得换回 ETH
SLIPPAGE = 5 # 滑点百分比,允许价格对你不利的幅度
# ──────────────────────────────────────────────────────
account = Account.from_key(PRIVATE_KEY) # 只用来签名,不连任何节点
res = requests.post(
"https://api.shrine.trade/rh/api/local-trade",
json={"action": ACTION, "token": TOKEN, "amount": AMOUNT, "toEth": TO_ETH, "slippage": SLIPPAGE, "from": account.address},
)
data = res.json()
if "error" in data:
raise SystemExit(f"{data['error']}: {data['message']}")
unit = "tokens" if ACTION == "buy" else data["quoteAsset"]["symbol"]
print("预计得到约", data["quote"]["expectedOutFormatted"], unit)
for tx in data["txs"]:
signed = Account.sign_transaction(
{
"to": tx["to"],
"data": tx["data"],
"value": int(tx["value"]),
"gas": tx["gas"],
"maxFeePerGas": int(tx["maxFeePerGas"]),
"maxPriorityFeePerGas": int(tx["maxPriorityFeePerGas"]),
"nonce": tx["nonce"],
"chainId": tx["chainId"],
},
account.key,
)
sent = requests.post("https://api.shrine.trade/rh/api/send", json={"signedTx": "0x" + signed.raw_transaction.hex().removeprefix("0x")}).json()
if "error" in sent:
raise SystemExit(f"{sent['error']}: {sent['message']}")
if sent["status"] != "landed":
raise SystemExit(f"{tx['description']} {sent['status']}: {sent['explorer']}")
print(tx["description"] + ":", sent["explorer"])
if ACTION == "buy":
print(f"买入 {data['name']} ({data['symbol']}) {data['token']} 花费 {data.get('ethInFormatted', data['amountInFormatted'])} ETH")
elif data.get("toEth"):
print(f"卖出 {data['amountInFormatted']} {data['name']} ({data['symbol']}) {data['token']} 得到 {data['toEth']['ethOutFormatted']} ETH")
else:
print(f"卖出 {data['amountInFormatted']} {data['name']} ({data['symbol']}) {data['token']} 得到 {data['quote']['expectedOutFormatted']} {data['quoteAsset']['symbol']}")
保存为 trade.py,然后:
pip install eth-account requests
python trade.py
API 返回什么,脚本就按顺序发什么。通常是一笔交易;第一次卖出,或者买入以 USDG、NVDA 等资产计价的代币,前面可能多一笔一次性的授权。
交易有防夹子保护:Robinhood 链没有公开内存池,排序器排序之前没人能看到你的交易;链上 minOut 保证成交不会比滑点允许的更差。
Pons 有狙击保护,发射后约 3 秒内的买入会被征税。
卖出
把 ACTION 改成 "sell"。金额可以是代币数量,也可以是持仓的百分比:
AMOUNT | 卖出 |
|---|---|
"1000" | 1000 枚代币 |
"50%" | 一半余额 |
"100%" | 全部 |
以 USDG、NVDA 等计价的代币
很多 Pons 新币不是以 ETH 计价,而是 Robinhood 链上的某个代币化资产。脚本不用改:买入时 AMOUNT 永远是 ETH。对一个以 USDG 计价的代币,"0.001" 的意思是"花 0.001 ETH",API 算出对应多少 USDG(amountIn,单位见 quoteAsset)交给曲线或池子。钱包里已有足够 USDG 就直接用;不够的话交易序列会以一笔用 ETH 买入差额的兑换开头,quoteSwap 说明它的成本。返回里的 ethIn 是你要求花的 ETH。
卖出时得到的是那个资产。加上 toEth: true(脚本里的 TO_ETH)所得会再换成 ETH:毕业代币在同一笔交易里完成,内盘代币则追加一笔按保证最小值执行的兑换。返回里的 toEth 说明最终得到多少 ETH、经过哪些池子。
完整列表见 创建代币。
出错了怎么办
| 错误 | 怎么办 |
|---|---|
insufficient_funds | 往钱包充 ETH:交易金额,再加一点 Gas。 |
insufficient_balance | 卖出数量超过持仓。试试 "100%"。 |
token_not_found | 不是 Pons 代币。确认填的是代币,不是池子。 |
slippage_exceeded | 价格动了。调高 SLIPPAGE(百分比,默认 5)再试。 |
graduating | 代币正在迁移到 Uniswap 池子。等一分钟再试。 |
完整列表见 错误。
发送
POST https://api.shrine.trade/rh/api/send 接收一笔签好的交易,通过我们的 Robinhood 链节点广播,所以脚本完全不需要 RPC。它只转发本 API 构建的交易:Pons 和 Uniswap 买卖、发币、授权和领取,其他一律以 not_ours 拒绝。
| 字段 | ||
|---|---|---|
signedTx | 0x 十六进制 | 签好的交易,即 wallet.signTransaction 的返回值。 |
wait | 布尔,可选 | 默认 true:等待回执。false 则节点一接受就返回哈希。 |
{ "hash": "0x…", "status": "landed", "blockNumber": 55020118, "gasUsed": 119746, "explorer": "https://robinscan.io/tx/0x…" }
status 为 landed(已上链)、reverted(已回滚)或 pending(未等待,或 45 秒内未打包)。发币交易上链后还会带 token 和 curve,从工厂事件里读出。
请求与返回
POST https://api.shrine.trade/rh/api/local-trade
请求
| 字段 | ||
|---|---|---|
action | "buy" 或 "sell" | |
token | 地址 | Pons 代币。 |
amount | 十进制字符串 | 买入:要花的 ETH,与代币计价资产无关。卖出:代币数量("1000")或持仓百分比("50%"、"100%")。 |
from | 地址 | 你的钱包。 |
slippage | 数字,可选 | 百分比,默认 5。 |
toEth | 布尔,可选 | 仅卖出、且代币以 ERC-20 计价时:把所得再换成 ETH。 |
返回:一个真实的例子,用 0.001 ETH 买入一个以 RDDT 计价的代币:
{
"action": "buy",
"token": "0x77df8B452670deb3DA51B367CD58044422dcE4b0",
"name": "Honest Work",
"symbol": "HONEST",
"curve": "0x07365E838a3f62675b81b3438137824F4B03457e",
"phase": "NotGraduated",
"venue": "pons_curve",
"amountIn": "14171692423151839",
"amountInFormatted": "0.014171692423151839",
"quoteAsset": {
"address": "0x05b37Fb53A299a1b874A619e1c4C404D52C36F4C",
"symbol": "RDDT",
"decimals": 18,
"isNative": false
},
"quote": {
"expectedOut": "819167564794497226305697",
"expectedOutFormatted": "819167.564794497226305697",
"minOut": "778209186554772364990412",
"curveFeeBps": 100,
"creatorTaxBps": 0,
"snipeTaxBps": 0,
"shrineFeeBps": 50,
"slippagePct": 5.0
},
"ethIn": "1000000000000000",
"ethInFormatted": "0.001",
"txs": [
{
"to": "0x05b37Fb53A299a1b874A619e1c4C404D52C36F4C",
"data": "0x\u2026",
"value": "0",
"gas": 80000,
"maxFeePerGas": "580242501",
"maxPriorityFeePerGas": "1",
"nonce": 5,
"chainId": 4663,
"type": 2,
"description": "approve_quote"
},
{
"to": "0xEc20E594D28a17511264dc73a84cd4AA957B0ABc",
"data": "0x\u2026",
"value": "0",
"gas": 400000,
"maxFeePerGas": "580242501",
"maxPriorityFeePerGas": "1",
"nonce": 6,
"chainId": 4663,
"type": 2,
"description": "buy"
}
]
}
txs:按此顺序签名并发送。value、maxFeePerGas、maxPriorityFeePerGas是以 wei 计的十进制字符串,其余是数字。description标明每笔交易:buy、sell,一次性的approve/approve_quote(曲线)或approve_permit2/approve_router(Uniswap),buy_quote_with_eth(买入前的兑换),convert_to_eth(内盘卖出后的兑换)。name/symbol:代币自己的名称和符号,方便脚本记录交易了什么。protocol:PONS_V2或PONS_V1。venue:v2 代币在内盘时为pons_curve,毕业后为uniswap_v4,所有 v1 代币为uniswap_v3。请求在所有情况下都一样。v1 代币永远以 ETH 计价,所以toEth和计价资产兑换不适用。quoteAsset:交易的结算资产,ETH 或代币的计价资产。decimals不一定是 18。amountIn:曲线或池子收到的数量,以quoteAsset计。买入以 ERC-20 计价的代币时,ethIn是你要求的 ETH,amountIn是它买到的资产数量。quote.expectedOut:你应到手的数量;minOut已扣滑点并由链上强制执行。基础单位,*Formatted字段是可读数字。quote里的费用:curveFeeBps和creatorTaxBps是 Pons 的,shrineFeeBps是我们的(50 = 0.5%),snipeTaxBps是 Pons 此刻对你钱包的开盘税。quoteSwap:仅当钱包缺计价资产、前面加了一笔兑换时出现:买到的quoteOut、报价的ethIn、携带的ethInMax(未用完退回)、经过的池子route。toEth:仅当卖出带toEth: true时出现:扣除我们费用后的ethOut、链上强制的ethOutMin、经过的池子route。毕业代币在同一笔交易里完成,内盘代币追加一笔convert_to_eth。