feeds について
Goldsky Feedsは、対応チェーン上のウォレット残高と送金をHTTPで取得するサービスです。独自のデータパイプラインを運用せずに標準化されたデータを必要とする利用者向けで、インデックス作成・正規化・価格付けはGoldskyが担います。
主な機能
- 01トークン残高と米ドル総額の取得
- 02新しい順での送金取得
- 03チェーン・トークン・方向による絞り込み
- 04結果のページネーション
- 05APIキーによるHTTPリクエスト認証
活用シーン
- 01ウォレットが現在保有する資産の確認
- 02ウォレットの入出金履歴の調査
- 03チェーンやトークンコントラクトによるデータ絞り込み
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ goldsky-io/ goldsky-agent --skill feedsインストール後、Claude Code で/feedsを入力して読み込まれたか確認します。
詳細
Goldsky Feeds
Feeds は HTTP 経由で、1 つのウォレットについて 1 つの質問に回答します。サポート対象のチェーン全体で、そのウォレットが保有しているもの、または送受信したものを、1 回のリクエストで確認できます。Goldsky が行をインデックス化、正規化し、価格を付与します。呼び出し側でパイプラインを実行する必要はありません。
同じホストと同じキーで、Polymarket とブロックヘッダーフィードも利用できます。これらは「このキーで利用できるその他のフィード」に記載されており、以下の規約には従いません。
CLI でキーを取得します(goldsky feeds key reveal)。フィード自体は通常の HTTP です。goldsky feeds の読み取りコマンドはありません。goldsky edge create でキーを作成しないでください。Edge の作成処理ではエンドポイント名 feeds が予約されているため、このコマンドは拒否されます。CLI のログイントークンは別の認証情報であり、これらのリクエストの認証には使えません。Feeds キーを表示しないでください。
このツールが適さない場合
- 行をユーザー自身のデータベースや Webhook に取り込む必要がある場合。これは Turbo パイプラインです(
/turbo-builder、/datasets)。Feeds はシンクにストリーミングしません。ストリーミングはまだ提供されていません(https://docs.goldsky.com/feeds/streaming)。 - 質問が Turbo のデータセット名またはチェーンプレフィックスに関する場合。これは
/datasetsです。プレフィックスは異なります。Feeds ではpolygonとarbitrum_one、Turbo ではmaticとarbitrumです。 - 質問が JSON-RPC に関する場合。これは
/edge、または現在のプロバイダーを使い続けたい場合は/boostです。
キー
プロジェクトごとに Feeds キーは 1 つで、すべてのフィードでそのキーを使用します。CLI で取得してください。ユーザーをダッシュボードに誘導せず、goldsky edge create も実行しないでください。
goldsky feeds key reveal
export GOLDSKY_FEEDS_API_KEY="$(cat "$HOME/.goldsky/feeds-api-key")"
reveal は、プロジェクトにキーがない場合は作成し、すでにある場合は既存のキーを取得して、~/.goldsky/feeds-api-key に書き込みます(モード 600)。キーが表示されることも、ローテーションされることもないため、再実行しても安全です。そのファイルを cat してチャットに貼り付けたり、キーをほかの場所に書き込んだりしないでください。
成功すると、Created Feeds API key and saved it to ~/.goldsky/feeds-api-key または Saved existing Feeds API key to ~/.goldsky/feeds-api-key と表示されます。代わりに一般的なヘルプが表示された場合、CLI のバージョンは 13.17.0 より古いです(古い CLI はこの場合も終了コード 0 を返すため、終了コードではなく出力を確認してください)。/auth-setup を実行して、固定バージョンをインストールしてください。--token は渡さないでください。401 はログインしていないことを示します。まず /auth-setup を使ってください。403 は、ユーザーがプロジェクトの Editor ではないことを示します。409 は、Edge エンドポイント名 feeds が存在し、それが Feeds キーではないことを示します。そのエンドポイントを先に削除する必要があります。
ユーザーから依頼されない限り、キーをローテーションしないでください。ローテーションすると、現在のキーは直ちに無効になります。
キーは x-api-key ヘッダーで送信してください。?key= と Authorization: Bearer も受け付けられますが、キーが URL ログに残らないよう、ヘッダーを優先してください。キーがない場合は、401 ではなく x402 の支払い要求本文を含む 402 が返ります。これはフィードをリクエストごとの支払いでも提供しているためです。キーが指定されていても誤っている場合は 401 です。そのため、402 が返った場合はヘッダーが届いていません。キーが不正だと判断する前に、GOLDSKY_FEEDS_API_KEY が設定されていることを確認してください。
呼び出し
curl -sS -H "x-api-key: $GOLDSKY_FEEDS_API_KEY" \
"https://edge.goldsky.com/data/feeds/wallets/balances?address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
curl -sS -H "x-api-key: $GOLDSKY_FEEDS_API_KEY" \
"https://edge.goldsky.com/data/feeds/wallets/transfers?address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
Balances は、ネイティブ資産を含む、ウォレットが保有する各トークンの最新残高と total_value_usd を返します。Transfers は、そのウォレットの移動を新しい順に返します。direction は address を基準にした in または out です。
クイックスタートに記載されていないパラメーターやレスポンスフィールドを使う前に、https://edge.goldsky.com/data/openapi.json を確認してください。このドキュメントが仕様です。ガイドは https://docs.goldsky.com/feeds/quickstart、概要は https://docs.goldsky.com/feeds です。
ClickHouse の上流で障害が発生した場合、どちらのフィードも 502 を返すことがあります。また、一部のチェーンでネイティブ残高を取得できない場合、Balances は 503 を返すことがあります。503 の場合、error.chains にチェーン名が示され、Retry-After が設定されます。これは部分的な障害なので、ウォレットが空だと報告せず、再試行してください。
address は必須で、ウォレットを 1 つだけ指定します。EVM アドレスは 0x の後に 40 桁の 16 進数が続く形式です。base58 形式の Solana アドレスは検証を通過しますが、まだ対応するチェーンがないため、data が空の 200 を返します。200 以外の本文はエラーであり、ウォレットが空であることを意味しません。
パラメーター
リクエストが拒否された場合は、OpenAPI 仕様を再確認してください。これらは URL のクエリパラメーターです。チェーンのセットは chains パラメーターで指定します。
chainsを省略すると、サポートされているすべてのチェーンが対象になります。正規スラッグをカンマ区切りで指定してください。matic、arbitrum、mainnetは、それぞれpolygon、arbitrum_one、ethereumのエイリアスです。大文字と小文字は区別されず、-は_として解釈されます。それ以外の表記は 400 を返します。token_symbolはシンボルに一致するため、2 つのコントラクトが両方とも一致することがあります。たとえばusdcは、複数のチェーンでネイティブコントラクトとブリッジされたコントラクトの両方を返します。トークンを特定のコントラクトに限定するにはtoken_addressを使用してください。最大 100 個までカンマ区切りで指定できます。残高では、ゼロアドレスを指定すると、対象範囲内のすべてのチェーンのネイティブ資産が選択されます。include_unknown_priceのデフォルトは false で、Goldsky に価格 ソース がないトークンは除外されます。ただし、これはすべての行に価格が付くことを保証するものではありません。デフォルトでは、価格を取得できるトークンの行でもprice_usdとvalue_usdが null のまま返されることがあります。すべての行で価格が null の場合に対応してください。include_historicalのデフォルトは false です。残高で true に設定すると、残高がゼロの行も取得できます。これには、完全に売却したトークンや、ウォレットが保有していないネイティブ資産も含まれます。あるウォレットでは、行数が 373 件から 517 件になりました。「このウォレットがこれまでに X を保有したことがあるか」を調べる場合は必要ですが、「現在の価値はいくらか」を調べる場合は不要です。min_value_usdは、指定した USD 価値を下回る行と、価格がない行を除外します。total_value_usdにも適用されます。- トランスファーでは、
fromとtoはblock_timestampに対する RFC 3339 形式の包含範囲です。from_blockとto_blockは、ブロック番号をチェーン間で比較できないため、チェーンを 1 つだけ指定する必要があります。チェーンを 1 つに限定しない場合は 400 ではなく 422CONFLICTING_FILTERSが返されます。transfer_typeはnative、erc20、またはその両方をカンマ区切りで指定します。NFT の種類(erc721、erc1155)を指定すると 400 が返されます。splは受け付けられ、空のdataとともに 200 を返します。まだ Solana チェーンが提供されていないためです。この空のページは、EVM チェーン上でフィルターに一致するものがなかったことを意味し、ウォレットが空であることを意味するわけではありません。directionはinまたはoutです。 page_sizeのデフォルトは 100 で、最大値は 1000 です。より大きな値を指定すると拒否されずに 1000 へ切り詰められるため、リクエストした件数が適用されたと決めつけず、pagination.page_sizeを確認してください。次のページを取得するには、前のレスポンスのpagination.next_page_tokenをpage_tokenに設定します。トークンが有効なのは、それを生成したフィルターに対してのみです。各ページは個別に課金されるリクエストです(https://docs.goldsky.com/pricing/summary#feeds)。ユーザーがその範囲を求めていない限り、全履歴をたどらないでください。
この API キーで利用できるその他のフィード
/polymarket/activity、/polymarket/positions、/polymarket/balances、/blocks/{chain}、/blocks/{chain}/head は、同じホストと同じ API キーで提供されています。Polymarket に関する質問のたびにパイプラインを構築する必要はありません。行をユーザー自身のデータベースに保存する必要がある場合にのみ、/turbo-builder を利用してください。呼び出し方は同じで、x-api-key ヘッダーを指定します。呼び出す前に OpenAPI 仕様を確認してください。以下の 3 つの規約はすべて異なります。
- ページネーションには
page_sizeとpage_tokenではなくlimitとcursorを使います。 次のカーソルはトップレベルのnext_cursorで、pagination.next_page_tokenではありません。page_sizeは受け付けられますが、無視されるため、2 行を要求するつもりで送ったリクエストでもデフォルトの 100 行が返り、そのすべてに課金されます。返された内容を確認してください。 - チェーン名の表記はウォレットフィードの表記とは異なります。
/blocksは 21 のチェーンを提供し、Polygon はmaticと表記します。polygon、mainnet、およびarbitrumのあらゆる表記は、ここでは 400 エラーになります。ウォレットフィードは 7 つのチェーンを提供し、Polygon はpolygonと表記され、maticは別名としてのみ使えます。一方で使えるスラッグが、もう一方でも使えるとは限りません。 - エラーは常に
{"error":{"code","message"}}形式のエンベロープで返るとは限りません。 これらのパスでクエリ文字列が不正な場合、素の文字列(Failed to deserialize query string: ...)が返されるため、.error.messageを読み取ると null になります。レスポンス本文の形式ではなく、ステータスコードに基づいて分岐してください。 - 数値のスケーリングはパスごとに異なります。
/polymarket/activityは、JSON 数値をすでに小数形式で返します(price: 0.65、amount_shares: 84.615385、amount_usdc: 55.0で、amount_usdc / amount_shares == priceです)。/polymarket/positionsと/polymarket/balancesは、1e6 を単位とする生の整数値を文字列で返します。そのため、avg_price: "100000"は 0.10 ドル、amount: "12120000000"は 12120 株を意味します。ユーザーに表示する前に、どちらも 1e6 で割ってください。positions.amountとbalances.balanceは同じスケールですが、同じ数量ではなく、ここでサンプリングした行の半数では値が一致しませんでした。amountは取引から算出したネットポジションで、balanceは実際に保有している条件付きトークンの残高です。分割、統合、償還、通常の転送は、約定がなくてもトークンを移動させます。質問に答える方を選び、もう一方で代用しないでください。 /polymarket/activityは、選択性の低いスキャンを拒否します。address、token_id、300000 ブロック以下の範囲で開始点と終了点を指定したブロック期間、604800 秒以下の範囲で開始点と終了点を指定した時間期間のいずれかを指定するか、フィルターなしでlimitを 100 以下にする必要があります。それ以外の場合は、400MISSING_SELECTIVE_FILTERが返されます。- 仕様で警告が付いている値が 3 つあります。
activity.feeの基準値は、ソースデータ内の一部の maker/taker の組み合わせで一貫していません。positions.last_updated_atはパイプラインの upsert 時刻であり、ブロック時刻ではないため、異なるblock_numberの行でも同じ値になる場合があります。並べ替えにはblock_numberを使ってください。balances.as_of_blockは、そのブロック時点の状態を再構築したものではなく、挿入順に基づく、そのブロック以前で最新の残高です。
レスポンスに基づくコードの作成
- 残高は各トークンの最新数量であり、履歴ではありません。同じブロック内に複数の転送がある場合、残高行は 1 つにまとめられます。移動の再構築には転送フィードを使ってください。
- 転送オブジェクトには ID がありません。
block_numberやblock_timestampを含む主キーを作成しないでください。リオーグを乗り越えたトランザクションは、異なるブロックフィールドで再び返されるためです。また、1 つのトランザクションが転送を 1 回だけ出力するとは限りません。 price_usdとamount_usdはリクエストの処理時に計算されます。同じ転送を後から読み取ると、異なる USD 値が表示される場合があります。