mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-19 14:31:50 +02:00
docs(skills): note the Solana recipient token-account requirement
The exact-SVM client transfers to the associated token account it derives for payTo and does not create it. When that account is missing, settlement fails at simulation and the 402 returns transaction_simulation_failed, which reads like a client bug rather than a missing recipient account. Adds a pre-flight check plus the three ways to create the account, and notes that freshly provisioned and custodial wallets are the common case. Found while running the documented flow end to end on Solana devnet; confirmed against the upstream client scheme, which only derives the destination ATA. Not currently covered in the upstream docs. Mirrored across en, ja-JP, and zh-CN.
This commit is contained in:
@@ -162,6 +162,23 @@ const res = await fetchWithPayment("https://api.example.com/data", { method: "GE
|
||||
| Python(FastAPI、Flask) | PyPI の `x402` |
|
||||
| Go(Gin、Echo、`net/http`) | `github.com/x402-foundation/x402/go/v2` |
|
||||
|
||||
**Solana のセラー:`payTo` アドレスには先にトークンアカウントが必要。** exact-SVM クライアントは `payTo` から導出した*関連トークンアカウント*(ATA)に送金するが、それを作成はしない。そのアカウントが存在しないと決済はシミュレーション段階で失敗し、402 が `transaction_simulation_failed` を返す — クライアントのバグのように見えるが、実際は受取側アカウントの欠落である。本番投入前に確認すること:
|
||||
|
||||
```bash
|
||||
curl -s https://api.mainnet-beta.solana.com -X POST -H 'Content-Type: application/json' \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner",
|
||||
"params":["<PAYTO_ADDRESS>",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}' \
|
||||
| jq '.result.value | length' # 0 なら USDC アカウントなし — 支払い受付前に作成する
|
||||
```
|
||||
|
||||
次のいずれかで作成できる(作成者が少額のレントを負担し、支払者ではない):
|
||||
|
||||
- そのトークンを `payTo` に一度でも送金する — 送金側の転送でアカウントが作成される。
|
||||
- spl-token CLI で `spl-token create-account <MINT> --owner <PAYTO_ADDRESS>`。
|
||||
- コード上では `@solana-program/token` の `getCreateAssociatedTokenIdempotentInstruction` をプロビジョニングフローに追加する — 冪等版なので再実行しても安全。
|
||||
|
||||
これは新規プロビジョニングされたウォレットやカストディアルウォレットへの支払いで最も問題になりやすい。そうしたウォレットは対象アセットの ATA をまだ持っていないことが多い。
|
||||
|
||||
**発見。** x402 バザール拡張を実装するファシリテーターは `/discovery/resources` エンドポイントを公開する — CDP カタログは `https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources`、PayAI カタログは `https://facilitator.payai.network/discovery/resources` で照会できる。Solana で支払い可能なサービスには、Solana Foundation のキュレーションカタログである [pay.sh](https://pay.sh) もある。
|
||||
|
||||
## 例
|
||||
|
||||
@@ -162,6 +162,23 @@ const res = await fetchWithPayment("https://api.example.com/data", { method: "GE
|
||||
| Python(FastAPI、Flask) | PyPI 上的 `x402` |
|
||||
| Go(Gin、Echo、`net/http`) | `github.com/x402-foundation/x402/go/v2` |
|
||||
|
||||
**Solana 卖方:`payTo` 地址需要先有代币账户。** exact-SVM 客户端会转账到它为 `payTo` 推导出的*关联代币账户*(ATA),但不会创建它。如果该账户不存在,结算会在模拟阶段失败——402 返回 `transaction_simulation_failed`,看起来像客户端 bug,实际是收款方账户缺失。上线前请检查:
|
||||
|
||||
```bash
|
||||
curl -s https://api.mainnet-beta.solana.com -X POST -H 'Content-Type: application/json' \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner",
|
||||
"params":["<PAYTO_ADDRESS>",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}' \
|
||||
| jq '.result.value | length' # 0 表示没有 USDC 账户 —— 接受付款前先创建
|
||||
```
|
||||
|
||||
以下任一方式都能创建(由创建者支付少量租金,而非付款方):
|
||||
|
||||
- 向 `payTo` 转一次该代币的任意数量——发送方的转账会创建该账户。
|
||||
- 用 spl-token CLI:`spl-token create-account <MINT> --owner <PAYTO_ADDRESS>`。
|
||||
- 在代码中,将 `@solana-program/token` 的 `getCreateAssociatedTokenIdempotentInstruction` 加入你的开通流程——幂等版本可安全重复执行。
|
||||
|
||||
这个问题在向新开通的钱包或托管钱包付款时最容易出现,这类钱包往往还没有该资产的 ATA。
|
||||
|
||||
**发现。** 实现 x402 集市扩展的结算器会公开 `/discovery/resources` 端点——可在 `https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources` 查询 CDP 目录,在 `https://facilitator.payai.network/discovery/resources` 查询 PayAI 目录。对于 Solana 可付费服务,还有 Solana 基金会的精选目录 [pay.sh](https://pay.sh)。
|
||||
|
||||
## 示例
|
||||
|
||||
@@ -163,6 +163,23 @@ The wrapped client only pays challenges whose `network` matches a scheme you reg
|
||||
| Python (FastAPI, Flask) | `x402` on PyPI |
|
||||
| Go (Gin, Echo, `net/http`) | `github.com/x402-foundation/x402/go/v2` |
|
||||
|
||||
**Solana sellers: the `payTo` address needs a token account first.** The exact-SVM client transfers to the *associated token account* (ATA) it derives for `payTo` and does not create it. If that account does not exist, settlement fails at simulation — the 402 comes back with `transaction_simulation_failed`, which reads like a client bug but is a missing recipient account. Check before going live:
|
||||
|
||||
```bash
|
||||
curl -s https://api.mainnet-beta.solana.com -X POST -H 'Content-Type: application/json' \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner",
|
||||
"params":["<PAYTO_ADDRESS>",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}' \
|
||||
| jq '.result.value | length' # 0 means no USDC account — create it before accepting payments
|
||||
```
|
||||
|
||||
Any one of these creates it (whoever creates it pays the small rent, not the payer):
|
||||
|
||||
- Send any amount of that token to `payTo` once — the sender's transfer creates the account.
|
||||
- `spl-token create-account <MINT> --owner <PAYTO_ADDRESS>` with the spl-token CLI.
|
||||
- In code, add `getCreateAssociatedTokenIdempotentInstruction` from `@solana-program/token` to your provisioning flow — the idempotent variant is safe to re-run.
|
||||
|
||||
This bites hardest when payouts go to freshly provisioned or custodial wallets, which often have no ATA for the asset yet.
|
||||
|
||||
**Discovery.** Facilitators that implement the x402 bazaar extension expose a `/discovery/resources` endpoint — query the CDP catalog at `https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources` and the PayAI catalog at `https://facilitator.payai.network/discovery/resources`. For Solana-payable services there is also [pay.sh](https://pay.sh), the Solana Foundation's curated catalog.
|
||||
|
||||
## Examples
|
||||
|
||||
Reference in New Issue
Block a user