mcpField
S
sp3nd

sp3nd

github.com/starchild-ai-agentその他3086 回インストール6 日前に更新
リポジトリ

sp3nd について

SP3NDは、AIエージェントがAmazonやeBayの商品を購入し、Solana上のUSDCで支払うためのショッピングスキルです。登録、カート・注文作成、支払いトランザクションの構築と署名を扱います。

主な機能

  1. 01AmazonとeBayで商品を購入
  2. 02地域に応じてマーケットプレイスのドメインを選択
  3. 03カートと注文を作成
  4. 04USDCトランザクションを構築・署名
  5. 05注文の支払い状況を確認

活用シーン

  1. 01商品リンクからエージェントに注文させる
  2. 02配送地域に合わせたドメインを選ぶ
  3. 03Solana 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 エージェントが 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 ウォレット(mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v)
  • solders および solana Python パッケージ(pip install solders solana)
  • .env 内の SP3ND API 認証情報(以下のステップ 1 で取得)

ステップ 1: エージェントを登録する(初回のみ)

自己登録 — 承認待ちのキューはありません。認証情報は一度だけ表示されるので、すぐに保存してください。

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 の TLD を選択する

重要: 配送先の国に一致するマーケットプレイスの TLD を使用してください。TLD が誤っていると、注文の失敗や誤った価格設定につながります。

地域別の Amazon TLD
TLD対象国
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 TLD
TLD対象国
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. 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 エージェントには、Privy が管理する Solana ウォレットが組み込まれています。次の 2 つのツールを順番に使用してください:

ステップ 1 — ウォレットアドレスを取得する:

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

ステップ 2 — 構築前に USDC 残高を確認する:

wallet_sol_balance()  →  lists all SPL tokens including USDC

ステップ 3 — 未署名の tx に署名する:

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

ステップ 4 — Solana RPC 経由で直接ブロードキャストする:

⚠️ wallet_sol_transfer は使用しないでください — これはネイティブ SOL のみを扱い、SPL トークンには対応していません。USDC の送金では、署名済みの tx を 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 を検出し、注文を Paid としてマークします — 通常は 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 でオンチェーンから取得し、導出してはいけません
memo 命令の欠落SP3ND Order: <order_number> を付けた MemoSq4g... 命令を追加してください — これがないと USDC は着金しますが注文は未払いのままです
USDC に wallet_sol_transfer を使用動作しません — 生の tx を構築し、wallet_sol_sign_transaction を実行して、RPC 経由でブロードキャストしてください
国に対して誤った Amazon TLDステップ 2 の TLD 表を使用してください — 誤った TLD は注文失敗につながります
導出した ATA を使った未署名 txトレジャリーの実際の ATA は導出した ATA と異なります — 取得してください
注文に customer_email がない必須フィールドです — これがないと createPartnerOrder は 400 を返します
カートの有効期限カートは 30 分で失効します — 速やかに注文してください

手数料体系

  • プラットフォーム手数料: デフォルトで 0%
  • 支払い: Solana 上の USDC (6 桁、USD 金額に 1,000,000 を乗算)
  • Amazon: 対象商品は Prime 送料無料
  • eBay: 商品ごとの送料は出品者が設定

主要なアドレス

項目値
SP3ND トレジャリー2nkTRv3qxk7n2eYYjFAndReVXaV7sTF3Z9pNimvp5jcp
USDC mint (Solana)EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
x402 ファシリテーターhttps://facilitator.payai.network
サポート[email protected]

コメント