mcpField
S
sp3nd

sp3nd

github.com/starchild-ai-agent其他3086 次安装6 天前更新
代码仓库

关于 sp3nd

SP3ND 是供 AI Agent 使用的购物技能,可在 Amazon 和 eBay 选购商品并以 Solana 上的 USDC 付款。文档涵盖注册、购物车和订单创建,以及构建并签名支付交易的流程。

主要功能

  1. 01在 Amazon 和 eBay 选购商品
  2. 02按地区选择商城域名
  3. 03创建购物车和订单
  4. 04构建并签名 USDC 交易
  5. 05查询订单支付状态

适用场景

  1. 01让 Agent 按指定商品链接下单
  2. 02根据收货地区选用商城域名
  3. 03使用 Solana USDC 支付购物订单
  4. 04轮询确认订单付款

安装

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

$npx skills add https://github.com/starchild-ai-agent/official-skills --skill sp3nd

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

详细介绍

SP3ND — 使用 Solana 上的 USDC 自主在 Amazon/eBay 购物

SP3ND 可让 AI Agent 使用 Solana 上的 USDC 在 Amazon 和 eBay 购买真实商品。无需 KYC、无需账户、平台费率为 0%,符合条件的 Amazon 商品可享受免费 Prime 配送。

完整 API 文档: https://sp3nd.shop/partner-api/docs SKILL.md: https://sp3nd.shop/skill.md 基础 URL: https://us-central1-sp3nddotshop-prod.cloudfunctions.net


前置条件

  • 持有 USDC 余额的 Solana 钱包(铸币地址:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v)
  • solders 和 solana Python 包(pip install solders solana)
  • .env 中的 SP3ND API 凭据(通过下方步骤 1 获取)

步骤 1:注册 Agent(仅需一次)

自助注册,无需排队审批。凭据只会显示一次;请立即保存。

import urllib.request, json

BASE_URL = "https://us-central1-sp3nddotshop-prod.cloudfunctions.net"
wallet_pubkey = "<your Solana wallet pubkey>"

payload = json.dumps({
    "agent_name": "My Agent",
    "solana_public_key": wallet_pubkey,
    "contact_email": "[email protected]",
    "description": "Autonomous shopping agent"
}).encode()

req = urllib.request.Request(
    f"{BASE_URL}/registerAgent",
    data=payload,
    headers={"Content-Type": "application/json"},
    method="POST"
)
with urllib.request.urlopen(req, timeout=15) as r:
    d = json.loads(r.read())
    print(d["api_key"], d["api_secret"])  # save both to .env

保存到 .env:

SP3ND_API_KEY=sp3nd_...
SP3ND_API_SECRET=sp3nd_sec_...

步骤 2:选择正确的 Amazon/eBay 顶级域名

重要: 使用与配送国家/地区对应的市场顶级域名。顶级域名错误会导致订单失败或价格错误。

各地区的 Amazon 顶级域名
顶级域名覆盖国家/地区
amazon.comUS,以及默认回退选项
amazon.co.ukGB、IE
amazon.deDE、AT、CH 以及欧洲大部分地区
amazon.frFR
amazon.itIT
amazon.esES
amazon.nlNL、BE
amazon.plPL
amazon.seSE
amazon.com.trTR
amazon.co.jpJP
amazon.com.auAU、NZ
amazon.inIN
amazon.sgSG、MY、TH、VN、ID、PH、MM、BN、KH、LA
amazon.aeAE、OM、BH、KW、QA、JO、IQ、LB
amazon.saSA、YE
amazon.egEG
amazon.com.brBR
amazon.com.mxMX
amazon.caCA
各地区的 eBay 顶级域名
顶级域名国家/地区
ebay.comUS(默认)
ebay.co.ukGB
ebay.deDE、AT、CH
ebay.frFR
ebay.itIT
ebay.esES
ebay.com.auAU
ebay.caCA

步骤 3:创建购物车

API_KEY    = os.environ["SP3ND_API_KEY"]
API_SECRET = os.environ["SP3ND_API_SECRET"]
HEADERS    = {"Content-Type": "application/json", "X-API-Key": API_KEY, "X-API-Secret": API_SECRET}

payload = json.dumps({
    "items": [{"product_url": "https://www.amazon.sg/dp/ASIN", "quantity": 1}]
}).encode()

req = urllib.request.Request(f"{BASE_URL}/createPartnerCart", data=payload, headers=HEADERS, method="POST")
with urllib.request.urlopen(req, timeout=20) as r:
    cart = json.loads(r.read())
    cart_id = cart["cart"]["cart_id"]
    total   = cart["cart"]["total_amount"]  # in USD = USDC amount needed

步骤 4:创建订单

payload = json.dumps({
    "cart_id": cart_id,
    "customer_email": "[email protected]",   # required
    "shipping_address": {
        "name":          "Full Name",
        "address_line1": "Street address",
        "address_line2": "Unit/suburb",    # optional
        "city":          "City",
        "state":         "State/province",
        "zip":           "Postal code",
        "country":       "ISO 2-letter code (e.g. MY, US, GB)",
        "phone":         "+1234567890"
    }
}).encode()

req = urllib.request.Request(f"{BASE_URL}/createPartnerOrder", data=payload, headers=HEADERS, method="POST")
with urllib.request.urlopen(req, timeout=20) as r:
    order = json.loads(r.read())
    order_id     = order["order"]["order_id"]
    order_number = order["order"]["order_number"]
    total_amount = order["order"]["total_amount"]

步骤 5:构建并签署支付交易

这是比较棘手的部分。 SP3ND 使用 x402 v2 协议。调用 payAgentOrder 时会返回带有支付要求的 HTTP 402。你必须:

  1. 在链上查找财库的实际 USDC 代币账户(ATA)——不要推导,直接获取
  2. 构建一笔包含两条指令的交易:USDC transferChecked,以及内容为 SP3ND Order: <order_number> 的 Memo
  3. Memo 为必填项——没有它,SP3ND 的 webhook 就无法将支付与订单匹配
  4. 直接通过 Solana RPC 签署并广播
import base64, struct, urllib.request, json
from solders.pubkey import Pubkey
from solders.hash import Hash
from solders.message import Message
from solders.transaction import Transaction
from solders.instruction import Instruction, AccountMeta
from solana.rpc.api import Client

USDC_MINT   = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
TOKEN_PROG  = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
MEMO_PROG   = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
TREASURY    = "2nkTRv3qxk7n2eYYjFAndReVXaV7sTF3Z9pNimvp5jcp"
RPC_URL     = "https://api.mainnet-beta.solana.com"

def get_treasury_ata():
    """Fetch SP3ND treasury's actual USDC ATA on-chain. Do NOT derive — fetch."""
    payload = json.dumps({
        "jsonrpc": "2.0", "id": 1,
        "method": "getTokenAccountsByOwner",
        "params": [TREASURY, {"mint": USDC_MINT}, {"encoding": "jsonParsed"}]
    }).encode()
    req = urllib.request.Request(RPC_URL, data=payload, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=10) as r:
        d = json.loads(r.read())
        return d["result"]["value"][0]["pubkey"]

def build_unsigned_tx(wallet_pubkey, our_ata, treasury_ata, amount_usdc_units, order_number):
    """Build unsigned tx: transferChecked + memo. amount_usdc_units = USDC * 1_000_000."""
    client = Client(RPC_URL)
    bh = client.get_latest_blockhash().value.blockhash

    wallet_pk  = Pubkey.from_string(wallet_pubkey)
    src        = Pubkey.from_string(our_ata)
    dst        = Pubkey.from_string(treasury_ata)
    mint       = Pubkey.from_string(USDC_MINT)
    token_prog = Pubkey.from_string(TOKEN_PROG)
    memo_prog  = Pubkey.from_string(MEMO_PROG)

    # Instruction 1: transferChecked (discriminator=12, u64 amount, u8 decimals=6)
    ix_transfer = Instruction(
        program_id=token_prog,
        accounts=[
            AccountMeta(pubkey=src,       is_signer=False, is_writable=True),
            AccountMeta(pubkey=mint,      is_signer=False, is_writable=False),
            AccountMeta(pubkey=dst,       is_signer=False, is_writable=True),
            AccountMeta(pubkey=wallet_pk, is_signer=True,  is_writable=False),
        ],
        data=bytes([12]) + struct.pack("<Q", amount_usdc_units) + bytes([6])
    )

    # Instruction 2: Memo — required for SP3ND webhook to match payment to order
    ix_memo = Instruction(
        program_id=memo_prog,
        accounts=[AccountMeta(pubkey=wallet_pk, is_signer=True, is_writable=False)],
        data=f"SP3ND Order: {order_number}".encode("utf-8")
    )

    msg = Message.new_with_blockhash([ix_transfer, ix_memo], wallet_pk, Hash.from_string(str(bh)))
    tx  = Transaction.new_unsigned(msg)
    return base64.b64encode(bytes(tx)).decode()
签署并广播(Starchild Privy 钱包)

Starchild Agent 内置由 Privy 管理的 Solana 钱包。按顺序使用以下两个工具:

步骤 1 — 获取钱包地址:

wallet_info()  →  returns solana address (e.g. C4ffoATXA5j3UdyvP4UQ3vMuQ547G18bG2QqhSs5bDvb)

步骤 2 — 构建交易前检查 USDC 余额:

wallet_sol_balance()  →  lists all SPL tokens including USDC

步骤 3 — 签署未签名的交易:

wallet_sol_sign_transaction(transaction=unsigned_b64)
→ returns { signed_transaction: "<base64>" }

步骤 4 — 直接通过 Solana RPC 广播:

⚠️ 不要使用 wallet_sol_transfer——它只能处理原生 SOL,不能处理 SPL 代币。转账 USDC 时,必须自行通过 Solana RPC 广播已签名的交易。

signed_b64 = "<signed_transaction from tool above>"

payload = json.dumps({
    "jsonrpc": "2.0", "id": 1,
    "method": "sendTransaction",
    "params": [signed_b64, {"encoding": "base64", "preflightCommitment": "confirmed"}]
}).encode()
req = urllib.request.Request(RPC_URL, data=payload, headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=30) as r:
    d = json.loads(r.read())
    tx_sig = d["result"]  # transaction signature
    print(f"https://solscan.io/tx/{tx_sig}")

查找你的 USDC 代币账户(our_ata):

# Fetch your own USDC ATA on-chain — same pattern as treasury ATA lookup
payload = json.dumps({
    "jsonrpc": "2.0", "id": 1,
    "method": "getTokenAccountsByOwner",
    "params": [wallet_pubkey, {"mint": USDC_MINT}, {"encoding": "jsonParsed"}]
}).encode()
req = urllib.request.Request(RPC_URL, data=payload, headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=10) as r:
    d = json.loads(r.read())
    our_ata = d["result"]["value"][0]["pubkey"]
    balance = d["result"]["value"][0]["account"]["data"]["parsed"]["info"]["tokenAmount"]["uiAmount"]

步骤 6:确认订单已付款

每隔约 5 秒轮询一次 getPartnerOrders。SP3ND 的 Helius webhook 会检测链上的 USDC 和 memo,并将订单标记为已付款——通常在 60 秒内完成。

import time

for _ in range(24):  # up to ~2 minutes
    req = urllib.request.Request(f"{BASE_URL}/getPartnerOrders", headers=HEADERS)
    with urllib.request.urlopen(req, timeout=15) as r:
        orders = json.loads(r.read())["orders"]
    order = next((o for o in orders if o["order_number"] == order_number), None)
    if order and order["status"] == "Paid":
        print("Order paid:", order["order_number"])
        break
    time.sleep(5)

常见问题

问题解决方法
金库 ATA 错误始终通过 getTokenAccountsByOwner 获取链上数据,切勿自行推导
缺少备注指令添加 MemoSq4g... 指令,并附上 SP3ND Order: <order_number> —— 缺少此指令时,USDC 虽会到账,但订单仍显示未付款
使用 wallet_sol_transfer 转账 USDC无法使用——构建原始交易,再调用 wallet_sol_sign_transaction,然后通过 RPC 广播
国家对应的 Amazon 顶级域名错误使用步骤 2 中的顶级域名表——顶级域名错误会导致订单失败
使用派生 ATA 的未签名交易金库的实际 ATA 与派生 ATA 不同——请获取实际 ATA
订单中缺少 customer_email此字段为必填项——缺少时,createPartnerOrder 会返回 400
购物车过期购物车会在 30 分钟后过期——请及时下单

费用结构

  • 平台费用:默认 0%
  • 付款方式:Solana 上的 USDC(6 位小数,美元金额乘以 1,000,000)
  • Amazon:符合条件的商品可享受 Prime 免费配送
  • eBay:每件商品的配送费由卖家设定

关键地址

项目值
SP3ND 金库2nkTRv3qxk7n2eYYjFAndReVXaV7sTF3Z9pNimvp5jcp
USDC mint(Solana)EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
x402 中介服务https://facilitator.payai.network
支持邮箱[email protected]

评论

支持 Markdown