compose-reference について
Goldsky Compose アプリを構築する開発者やエージェント向けのリファレンススキルです。マニフェスト、CLI、タスク API、ウォレット、コントラクトの手順と、サンドボックスのインポート制約をまとめています。
主な機能
- 01compose.yaml のスキーマとトリガー
- 02CLI コマンドとフラグ
- 03TaskContext とウォレットのリファレンス
- 04コントラクトのコード生成とデプロイ
- 05サンドボックスのインポートとネットワーク規則
活用シーン
- 01compose.yaml の記述前にフィールドを確認
- 02アプリのライフサイクル操作のフラグを検索
- 03ウォレットやコントラクトのデプロイ手順を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ goldsky-io/ goldsky-agent --skill compose-referenceインストール後、Claude Code で/compose-referenceを入力して読み込まれたか確認します。
詳細
Goldsky Compose リファレンス
compose.yaml マニフェスト、goldsky compose CLI の全機能、TaskContext API、ウォレット、ガスのスポンサー提供、コントラクトのコード生成、ダッシュボード、料金に関するリファレンスです。対話型のビルドフローには /compose を、デバッグには /compose-doctor を使用してください。
これは Compose スキルファミリーのリファレンスレイヤーです。最初に読み込む
/composeには一般的なビルドルールと概念が記載されています。テンプレートスキル(/compose-bitcoin-oracle、/compose-vrf、/compose-dividend-distribution、/compose-compliance-oracle)には、アプリのソース例が記載されています。具体的なフィールド、フラグ、マニフェストの構造、API シグネチャを確認するときは、このスキルを読み込んでください。また、形状を記憶から組み立てるのではなく、compose.yamlやタスクファイルを書く前に必ず読み込んでください。
デプロイする前に、必ずマニフェストを検証してください。
goldsky compose startを使うと、スキーマエラーをすばやく検出できます。
サンドボックスのインポートルール — これを誤ると、タスクのバンドルに失敗するか、実行時にクラッシュします。 インポートしてはならないものが2つあります。Compose のランタイム機能と EVM SDK です。
env、fetch、callTask、logEvent、evm(ウォレット、チェーン、コントラクト、decodeEventLog)、collectionはすべて、注入されるcontext引数から利用できます。@goldsky/compose-evm(または類似の)パッケージは存在しません。チェーンにはviemをインポートせず、context.evm.chains.<name>を介してアクセスしてください。それ以外にインポートできるものは、アプリにpackage.jsonがあるかどうかによって異なります。
package.jsonがない(bitcoin-oracle などの Deno スタイルのアプリ):composeモジュール(型の場合はimport type { TaskContext } from "compose")と、同じプロジェクト内のファイル(./lib/utils、../contracts/Foo)のみインポートしてください。それ以外の名前だけのインポートは、バンドラーによって拒否されます。package.jsonがある(viem/@ethersproject/walletを使用する copy-trader や、gillを使用する solana などの esbuild でバンドルされるアプリ): そこに宣言された npm 依存関係はバンドルされ、ローカル/純粋な処理(暗号、署名、エンコード)にインポートして使用できます。制約となるのはネットワークです。Compose タスクは独自のアウトバウンドソケットを持たないサンドボックスで実行されるため、実行時に独自の HTTP 通信を行うパッケージ(axios、node-fetch、SDK に組み込まれた HTTP クライアント)は失敗します。すべてのネットワーク呼び出しをcontext.fetch経由にし、SDK の純粋なユーティリティのみを使用してください。つまり、ひな形にした例に合わせてください。
package.jsonが含まれている場合は、その npm インポートを維持してください。含まれていない場合は、新たに導入しないでください。
クイックリファレンス
よく参照する項目:
- マニフェストのトップレベル/タスク/トリガーフィールド → compose.yaml マニフェスト
- CLI フラグ → CLI コマンド
- TaskContext の構造、IWallet、Collection → TaskContext API
- スマートウォレットと BYO EOA、ガススポンサー提供のデフォルト設定 → ウォレット — 詳細
- コントラクトのコード生成ワークフロー → コントラクトのコード生成
--jsonの出力形式 → CLI JSON スキーマ- ダッシュボード URL → ダッシュボード
compose.yaml マニフェスト
トップレベルのフィールド
| フィールド | 型 | 必須 | 備考 |
|---|---|---|---|
name | 文字列 | はい | /^[a-zA-Z0-9]([a-zA-Z0-9_\-]*[a-zA-Z0-9])?$/。英字または数字で始まり、英字または数字で終わります。英字、数字、アンダースコア、ハイフンを使用できます。大文字と先頭の数字も使用できます。プラットフォームではさらに、既存のアプリ名と正規化後(小文字化し、[-_]+ を - に変換)の名前が一致する場合、409 エラーで拒否されるため、my-app、My_App、my__app は共存できません |
api_version | 文字列 | デプロイ時のみ | semver(例:0.1.0)、または stable/preview/canary(internal-* で始まる値も受け付けます) |
tasks | 配列 | はい | 空でないこと |
secrets | 文字列[] | いいえ | 名前のみ。値は compose secret set で設定します |
env | { local?, cloud? } | いいえ | env の有効な子要素は local と cloud のみです。それぞれ context.env にフラット化される Record<string, string> です。env.MY_VAR のように env の直下に変数名を指定すると拒否され、「有効なキーではありません」というエラーになります。アプリごとの固定値はここではなく、タスクファイルに記述してください。 |
タスクのフィールド
| フィールド | 型 | 必須 | 備考 |
|---|---|---|---|
name | 文字列 | はい | /^[a-zA-Z0-9][a-zA-Z0-9_.\-]*$/。英字または数字で始まります。英字、数字、アンダースコア、ハイフン、ドットを使用できます。先頭のアンダースコアは使用できなくなりました(_internal_task は拒否されます) |
path | 文字列 | はい | .ts タスクファイルへの相対パス |
triggers | 配列 | はい | 1 つ以上。各タイプにつき最大 1 つ |
retry_config | オブジェクト | いいえ | { max_attempts, initial_interval_ms, backoff_factor }。設定する場合は 3 つすべてが必須です。マニフェストバリデーターは、name、path、retry_config、triggers 以外のフィールドを含むタスクを拒否します |
トリガーのタイプ
cron
- type: cron
expression: "*/15 * * * *" # 5-field cron
http
- type: http
authentication: auth_token # or "none"
ip_whitelist: ["1.2.3.4", "10.0.0.0/8"] # optional, IPv4/IPv6/CIDR
onchain_event
- type: onchain_event
network: polygon_amoy # snake_case required
contract: "0xYourContractAddress" # 0x + 40 hex
events:
- "Transfer(address,address,uint256)" # viem signature strings, optional
dataset_version: "..." # optional
マニフェストの全体例
name: my-app
api_version: stable
secrets:
- COINGECKO_API_KEY
- ORACLE_SIGNER_KEY
env:
cloud:
LOG_LEVEL: info
local:
LOG_LEVEL: debug
tasks:
- name: update_oracle
path: src/tasks/update-oracle.ts
retry_config:
max_attempts: 3
initial_interval_ms: 1000
backoff_factor: 2
triggers:
- type: cron
expression: "*/5 * * * *"
- name: manual_trigger
path: src/tasks/manual-trigger.ts
triggers:
- type: http
authentication: auth_token
CLI コマンド
すべてのコマンドで -t/--token と --api-server を指定できます。-n/--name フラグでアプリを名前から選択します(指定がない場合は -m/--manifest、次に ./compose.yaml を使用します)。トークンの優先順位は --token > GOLDSKY_API_TOKEN 環境変数 > ~/.goldsky/auth_token(goldsky login によって書き込まれます)です。いずれも指定されていない場合、CLI は「Please run goldsky login, set GOLDSKY_API_TOKEN, or pass --token to the command.」というエラーを返します。
非対話モードでのガード。 名前を指定しない
init、api_versionのメジャーバージョンが一致しない状態でのdeploy(--forceが必要です。メッセージは「Refusing to deploy with a major api_version mismatch in non-interactive mode. Pass --force to override.」)、および-fを指定しないclean(「Use --force for non-interactive cleanup.」)は、非 TTY 環境ではすべて中止されます。エージェントは常に非 TTY 環境で実行されます。
ライフサイクル
| コマンド | 目的 | 主なフラグ |
|---|---|---|
compose init | 新しいアプリのひな形を作成 | [name](TTY があり、名前が指定されていない場合にのみプロンプトを表示します) |
compose start | ローカルで実行します(dev コマンドはありません) | --fork-chains、--cloud、--impersonate、-p/--port |
compose deploy | クラウドにバンドルしてアップロードします | -m、-t、-f(バージョン互換性の確認プロンプトをスキップします(ターミナルで実行していない場合、メジャーバージョンが一致しない状態でデプロイするには必須です))、--sync-env、--json |
compose status | ランタイムのステータスを表示します | -n、--json |
compose list | すべてのアプリを一覧表示します | --json |
compose history | アプリのデプロイ履歴を表示します | -n、--limit(デフォルトは 20、サーバー側の上限は 100)、--offset(デフォルトは 0)、--include-failures、--json |
compose pause | 一時停止します | -n、--json |
compose resume | 再開します | -n、--json |
compose delete | 削除します(確認のために文字列を入力します。CI では --force を使用します) | -n、--force、--delete-database、--json |
compose logs | ログを表示/追跡します | -f、--tail(デフォルトは 100)、--level、--search、--since、--max-lines、--timeout <duration>、--json |
compose clean | ローカルの .compose/stage.db を消去します | -f、-c/--config <config> |
compose update [version] | compose バイナリを再ダウンロードします | [version](stable/preview/semver)、--preview |
compose callTask <task_name> <payload> | JSON ペイロードでタスクを呼び出します。デフォルトではデプロイ済みのアプリを対象とします | --env <local|cloud>(デフォルトは cloud)、-p/--port <port>(ローカルを指定します。明示的に --env cloud を指定している場合に --port を指定するとエラーになります)、-n、-m、-t、--api-server、--json |
callTask --env local のローカルポート解決順序:--port フラグ > .compose/.port > 4000。接続拒否、不明なタスク名、古いポートファイルは、それぞれ異なるメッセージを表示し、終了コード 1 で終了します(コードは CONNECTION_REFUSED、TASK_NOT_FOUND、INVALID_RESPONSE、INVALID_PAYLOAD、INVALID_ENV、INVALID_FLAGS)。
シークレット
| コマンド | 目的 |
|---|---|
compose secret set <SECRET_NAME> --value <value> [-n <app>] [--env local|cloud] [--redeploy] | シークレットを設定します(名前は位置引数です。-n = アプリ) |
compose secret delete <secret_name> [-n <app>] [--env local|cloud] | 削除します |
compose secret list [-n <app>] | 一覧表示します(--env フラグはありません) |
compose deploy --sync-env | デプロイ時に .env の内容をすべてクラウドにアップロードします(secret sync はありません) |
ウォレット
| コマンド | 目的 |
|---|---|
compose wallet create <wallet_name> [-n <app>] [--env local|cloud] [--json] | 管理対象ウォレットを作成し、アドレスを出力します(名前は位置引数です。-n = アプリ) |
compose wallet list [-n <app>] [--env local|cloud] [--json] | テーブル:name、address、type(privy / private_key / tevm)、created_at |
コード生成
compose codegen — src/contracts/*.json の ABI をすべて解析し、.compose/generated/index.ts と .compose/types.d.ts を書き込みます。compose init、compose start の実行時、およびデプロイ時に自動で実行されます。
コントラクト
CLI から直接コントラクトをコンパイルしてデプロイするか、書き込み呼び出しを送信できます。Foundry は不要です(deployContract が solc をバンドルしています)。0.8.0 で追加されました。forge 形式の複数引数/配列コンストラクター構文には ≥ 0.8.1 が必要です。古いバージョンをお使いの場合は、goldsky compose update を実行してください。
compose deployContract <file.sol> — CLI 内でコンパイルし、アプリの Compose ウォレットを通じて CREATE2 プロキシ経由でデプロイします。forge 形式の複数引数/配列コンストラクター構文には ≥ 0.8.1 が必要です。
| フラグ | 目的 |
|---|---|
--chain-id <id> | 対象チェーン(必須)。例:Base Sepolia 84532、Base 8453、Polygon 137、Polygon Amoy 80002、Arbitrum 42161、Optimism 10。 |
--constructor-args <tokens...> | forge 形式:パラメーターごとにトークンを 1 つずつ、スペース区切りで指定します。配列は "[a,b]"、タプルは "(a,b)"、入れ子も使用できます。負の値は " -5"(先頭にスペースを付けて引用符で囲みます)。コンパイル済み ABI に基づいて型変換されます。 |
--wallet <name> | デプロイに使用するアプリのウォレット(既定値は default)。コントラクトがそのウォレットを承認する必要がある場合は、タスクコードで使用する evm.wallet({ name }) と一致させてください。 |
--verify | ブロックエクスプローラーでコントラクトを検証します。 |
--force | コンストラクター内の msg.sender ガードを回避します(送信元はウォレットではなく CREATE2 プロキシです)。 |
-m / -t | マニフェストのパス/プロジェクトトークン(Lifecycle を参照)。 |
--api-server | API サーバーの URL(グローバルフラグ)。 |
--json | JSON 出力(CLI JSON Schemas を参照)。 |
アプリのディレクトリから実行してください。アプリ名を読み取るために compose.yaml が参照されます。アプリ名とプロジェクト ID から決定論的な CREATE2 ソルトが生成されます。ガスがスポンサーされるチェーン(Base 8453、Base Sepolia 84532)では、資金を入れたキーも RPC URL も不要です。deployContract はクラウドの Alchemy バンドラー経由で実行されます。このバンドラーは Ethereum、Sepolia、Polygon、Polygon Amoy、Arbitrum、Arbitrum Sepolia、Optimism、Optimism Sepolia、Base、Base Sepolia(チェーン ID:1、11155111、137、80002、42161、421614、10、11155420、8453、84532)に対応しています。この一覧にないチェーンでは No Alchemy bundler URL for chain <id> エラーでデプロイが失敗するため、その場合は forge create による代替方法を使用してください(コンストラクター引数は同じです。ABI は自分で src/contracts/ に用意してください)。マルチプロバイダー対応の範囲は FOU-991 で管理されています。ランタイムのタスクガススポンサー(Gas Sponsorship を参照)は、このデプロイエンドポイントより多くのチェーンに対応しています。
ウォレットのライフサイクル。 wallet create と wallet list は、アプリをデプロイする前でも動作するようになりました(deployContract/writeContract と同様に、必要に応じてホスト型ストアをプロビジョニングします)。wallet create はデプロイ前のウォレットアドレスを返します。コンストラクター内でウォレットを認可するには、wallet create <name> → deployContract --constructor-args <address> → タスクにアドレスを設定 → compose deploy の順に実行します。
CREATE2 の衝突。 同じアプリから同じコントラクトソースとコンストラクター引数で再デプロイすると、CREATE2 の衝突が発生します。プラットフォームは HTTP 400 CONTRACT_ALREADY_DEPLOYED を返し、CLI は終了コード 1 で「このコントラクトはこのアプリですでにデプロイされています。同じコントラクト+アプリ名+プロジェクトでは、CREATE2 によって同じアドレスが生成されます。」と報告し、Deploy Block は出力しません(--json のコードは ALREADY_DEPLOYED、その他のデプロイ失敗は DEPLOY_CONTRACT_FAILED です)。コンストラクター引数、ソース、またはアプリ名を変更すると、新しいアドレスが生成されます。アプリ名は CREATE2 のソルトに使われるため、アプリ名を変更すると、今後のすべてのデプロイアドレスが変わる点に注意してください。成功すると、コントラクトアドレス、トランザクションハッシュ、Deploy Block が出力され、ABI が src/contracts/<Name>.json に自動保存されます。その後 compose codegen を実行すると、型付きバインディングが生成されます。
compose writeContract — デプロイ済みコントラクトに書き込み呼び出しを送信します。
| フラグ | 目的 |
|---|---|
--chain-id <id> | 対象チェーン(必須)。 |
--to <address> | 対象コントラクトアドレス(必須)。 |
--function "sig(types)" | 関数シグネチャ。例:"setValue(uint256)"。 |
--args <tokens...> | --constructor-args と同じ forge 形式の文法。 |
--data <hex> | --function/--args の代わりに使用する、生の calldata。 |
--value <amount> | 送信するネイティブ通貨の値。単位(wei、gwei、ether)を付けます。例:--value 1ether。 |
--wallet <name> | 署名に使用するアプリのウォレット(デフォルトは default)。 |
--api-server | API サーバーの URL(グローバルフラグ)。 |
--json | JSON 出力(CLI JSON スキーマを参照)。 |
実行結果の確認
| コマンド | 目的 | 主なフラグ |
|---|---|---|
compose runs [runId] | 実行の一覧表示、または単一実行の詳細表示 | --limit、--offset、--task <name>、--status <success|error|pending>、--since <1h|30m|7d>、--until <duration>、--json、-n/-m、-t、--api-server |
compose collections list | アプリのコレクション名を表形式で表示 | 対象指定+--json |
compose collections query <collectionName> | 1 つのコレクションをクエリ | --filter <json>(JSON オブジェクトが必須)、--limit(デフォルトは 100、バックエンドの上限は 1000)、--offset、--json、対象指定 |
compose source [taskName] | デプロイ済みアプリのソースファイル一覧、または指定したタスクのソースを表示。ディスクには書き込みません | 対象指定+--json |
compose download | デプロイ済みアプリのソースアーカイブをダウンロード | -o/--output <path>(デフォルトは <app>.zip。既存ファイルへの上書きは拒否します)、--json、対象指定 |
TaskContext API
main(context: TaskContext, params?: Record<string, unknown>): Promise<unknown> は次を受け取ります。
type TaskContext = {
env: Record<string, string>;
logger: {
info(message: string, data?: Record<string, unknown>): void;
warn(message: string, data?: Record<string, unknown>): void;
error(message: string, data?: Record<string, unknown>): void;
};
fetch: FetchFn;
callTask: <Args, T>(name: string, args: Args, retryConfig?: RetryConfig) => Promise<T>;
logEvent: (event: { code: string; message: string; data?: unknown }) => Promise<void>;
evm: {
chains: Record<string, Chain>; // re-exported from viem internally — access via context.evm.chains.<name>, do NOT import viem
wallet: (config: WalletConfig) => Promise<IWallet>;
decodeEventLog: <T>(abi: AbiItem[], log: OnchainEvent) => Promise<T>;
contracts: Record<string, ContractClass>; // populated by codegen
};
collection: <T>(name: string, indexes?: CollectionIndexSpec[]) => Promise<Collection<T>>;
sideEffect: <T>(fn: () => T | Promise<T>) => Promise<T>;
};
secrets 名前空間はありません。 シークレットは context.env にフラット化されます。出力には、構造化され実行と関連付けられたロガーである context.logger.info/warn/error(message, data?) を使用します(各行には taskName、runId、appId、level、timestamp が含まれます)。自由形式の出力には console.log を使用できます。logEvent は引き続き動作しますが、ランタイム型では @deprecated とマークされており、今後のメジャーバージョンで削除されます。
fetch(オーバーロード)
type FetchConfig = {
method?: string; // defaults to "GET"
headers?: Record<string, string>;
body?: Record<string, unknown> | string; // objects are JSON.stringify'd
};
interface FetchFn {
<T>(url: string, retryConfig?: RetryConfig): Promise<T | undefined>;
<T>(url: string, config?: FetchConfig, retryConfig?: RetryConfig): Promise<T | undefined>;
}
- 2 番目の引数は設定オブジェクトであり、本文そのものではありません:
ctx.fetch(url, { method: "POST", body: { a: 1 }, headers: { "X-Key": k } })。2 番目の引数にペイロードオブジェクトをそのまま渡しても、本文は送信されません。認識されないキーは破棄され、リクエストは GET として送信されます。 - 2xx 以外のレスポンスでは、
Fetch failed with status <code> <statusText>: <body>がスローされます。 - レスポンスは JSON として解析され、本文が JSON でない場合は
undefinedを返します。 - これは
window.fetchではありません。ネイティブのfetchではなく、こちらを使用してください。
callTask
callTask<Args, T>(name: string, args: Args, retryConfig?: RetryConfig): Promise<T>
Tは呼び出し先が返す値です。voidを返すタスクはundefinedに解決されます。- タスク間の呼び出し(親/子のパターン)に使用します。
sideEffect
sideEffect<T>(fn: () => T | Promise<T>): Promise<T>
非決定的な値(タイムスタンプ、UUID、乱数)をラップし、ほかのコンテキスト呼び出しと同様にキャッシュします。永続的な再開ではタスクが最初から再実行されるため、ラップされていない Date.now() は再実行時に変化します。コールバックは一度だけ実行されます。再実行時にはホストがキャッシュ済みの値を返し、コールバックは実行されません。
RetryConfig
type RetryConfig = {
max_attempts: number; // ≥0
initial_interval_ms: number; // >0
backoff_factor: number; // >0
};
retryConfig を明示的に渡す場合は、3つのフィールドすべてが必須です(マニフェストバリデーターは retry_config に対してもこれを適用します)。省略しても、試行回数が1回になるわけではありません。
| スコープ | デフォルト |
|---|---|
retry_config のないタスク | { max_attempts: 3, initial_interval_ms: 1000, backoff_factor: 2 } |
安全な読み取り専用コンテキスト呼び出し:readContract、simulate、getBalance、および GET/HEAD/OPTIONS を使用する ctx.fetch | { max_attempts: 3, initial_interval_ms: 500, backoff_factor: 2 } |
その他すべて(callTask、writeContract、sendTransaction、prepareUserOperation、submitSignedUserOperation、ウォレットの作成/保存、POST/PUT/PATCH/DELETE を使用する ctx.fetch) | { max_attempts: 1, initial_interval_ms: 500, backoff_factor: 2 }。冪等でない呼び出しを無条件に再試行しないよう、意図的に1回に固定されています |
OnchainEvent(decodeEventLog および onchain_event トリガー用)
type OnchainEvent = {
blockNumber: number;
blockHash: string;
transactionIndex: number;
removed: boolean;
address: string;
data: Hex;
topics: Hex[];
transactionHash: string;
logIndex: number;
};
onchain_event トリガーのタスクでは、params に { log: OnchainEvent } とチェーン固有のメタデータが含まれます。decodeEventLog(abi, params.log) はデコード済みの構造体を返します。
IWallet
interface IWallet {
readonly name: string;
readonly address: Address;
writeContract(
chain: Chain,
contractAddress: Address,
functionSig: string, // signature string only, no ABI item
args: unknown[],
confirmation?: TransactionConfirmation,
retryConfig?: RetryConfig,
): Promise<{ hash: string; receipt: TransactionReceipt; userOpHash?: string }>;
sendTransaction(
config: {
to: Address; data: Hex; chain: Chain;
value?: bigint; maxFeePerGas?: bigint; maxPriorityFeePerGas?: bigint;
gas?: bigint; nonce?: number;
},
confirmation?: TransactionConfirmation,
retryConfig?: RetryConfig,
): Promise<{ hash: string; receipt: TransactionReceipt; userOpHash?: string }>;
readContract<T = unknown>(
chain: Chain, contractAddress: Address, functionSig: string,
args: unknown[], retryConfig?: RetryConfig,
): Promise<T>;
simulate( // throws on revert
chain: Chain, contractAddress: Address, functionSig: string,
args: unknown[], retryConfig?: RetryConfig,
): Promise<unknown>; // viem simulateContract result
getBalance(chain: Chain, retryConfig?: RetryConfig): Promise<string>; // decimal wei string
}
type TransactionConfirmation = {
confirmations?: number;
onReorg?: {
action:
| { type: "replay" }
| { type: "log"; logLevel?: "error" | "info" | "warn" } // default "error"
| { type: "task"; task: string };
depth: number;
};
};
TransactionReceipt には、status: "success" | "reverted"、blockNumber: bigint、blockHash、gasUsed: bigint、effectiveGasPrice: bigint、cumulativeGasUsed: bigint、from、to、contractAddress: Address | null、logs: Log[]、logsBloom、transactionHash、transactionIndex、type が含まれます。
具体的には、string | AbiItem のオーバーロードはありません。retryConfig は独立した第6位置引数であり、オプションバッグ内のキーではありません。writeContract に gas/gasPrice オプションはありません。戻り値に chainId もトップレベルの blockNumber もありません(ドキュメントに記載されている TxResult 型は存在しません)。sendTransaction はオブジェクトを最初の引数に取り、位置引数 (chain, to, value, data?, options?) の形式は存在しません。simulate は { result, request } を返し、リバート時には例外をスローするため、SimulateResult { success, ... } と if (!sim.success) は実行されないコードです。getBalance は10進表記の wei の 文字列 を返すため、BigInt(...) を使わない演算では文字列が連結されます。onReorg.action.type は "replay" | "log" | "task" であり、"skip" はありません。
コレクション
type CollectionIndexSpec = {
path: string;
type: "text" | "numeric" | "boolean" | "timestamptz";
unique?: boolean;
};
interface Collection<T> {
readonly name: string;
insertOne(doc: T, opts?: { id?: string }): Promise<{ id: string }>;
findOne(filter: Filter): Promise<(T & { id: string }) | null>;
findMany(filter: Filter, options?: { limit?: number; offset?: number }): Promise<Array<T & { id: string }>>;
getById(id: string): Promise<(T & { id: string }) | null>;
setById(id: string, doc: T, opts?: { upsert?: boolean }): Promise<{ id: string; upserted?: boolean; matched?: number }>; // upsert defaults true; false throws if absent
deleteById(id: string): Promise<{ deletedCount: number }>;
drop(): Promise<void>;
}
collection<T>(name, indexes?) が受け取るのは string[] ではなく CollectionIndexSpec[] です。findMany のオプションは { limit?, offset? } です。skip は存在せず、無視されるため、これを使ったページングでは常に1ページ目が返されます。読み取り結果は T & { id: string } です。フィルターはフラットな Record<string, string | number | boolean | HelperValue> であり、ネストしたパスによるフィルターには対応していません。
フィルター演算子:$gt、$gte、$lt、$lte、$in、$ne、$nin、$exists。等価条件:{ field: value }。
CLI JSON スキーマ
--json の出力を解析するエージェント向け:
compose status -n <app> --json
{
"name": "my-app",
"status": "RUNNING",
"created_at": 1771630350411,
"updated_at": 1774473580871
}
status は RUNNING、PAUSED、STARTING、STOPPING、ERROR、NOT_FOUND のいずれかです(値は API から返されるため、この一覧がすべてとは限りません)。タイムスタンプはミリ秒単位のエポック時刻です。
compose list --json
[
{ "name": "my-app", "status": "RUNNING", "created_at": 1771630350411, "updated_at": 1774473580871 }
]
compose logs --json
NDJSON(1行に1つのオブジェクト):
{"timestamp":"2026-04-20T10:00:00Z","level":"info","message":"..."}
フィールドは3つだけです。CLI のログ出力に dashboard_url はありません。特定の実行へのリンクをユーザーに提示するには、compose runs で実行 ID を取得し、https://app.goldsky.com/<project_id>/dashboard/compose/<app-name>/runs/<run_id> を自分で組み立ててください。CLI の logs コマンドには --run-id フィルターもありません(基盤となる API は受け付けますが、CLI は渡しません)。実行ごとの詳細には compose runs <runId> を使用してください。
compose secret list -n <app> --json
[{ "name": "MY_SECRET", "created_at": 1771630350411 }]
値が返されることはありません。
compose wallet list --json
[{ "name": "updater", "address": "0x...", "type": "privy", "created_at": 1771630350411 }]
type は privy(スマートウォレット)、private_key(BYO EOA)、tevm(ローカルフォーク)のいずれかです。
--json モードのエラー
--json モードでは、標準出力には結果ドキュメントのみが出力されます(アスキーアートと進行状況バーは抑制されます)。失敗は 標準エラー出力 に {"error": true, "code": "<CODE>", "message": "..."} の形式で出力され、終了コードは 1 です。CLI に存在するコードは次のとおりです:VALIDATION_FAILED、SECRET_MISSING、DEPLOY_FAILED、DEPLOY_CONTRACT_FAILED、ALREADY_DEPLOYED、WRITE_CONTRACT_FAILED、WALLET_CREATE_FAILED、WALLET_LIST_FAILED、NOT_FOUND、TASK_NOT_FOUND、CONNECTION_REFUSED、INVALID_ENV、INVALID_FLAGS、INVALID_PAYLOAD、INVALID_RESPONSE、INVALID_FILTER、UNKNOWN。
ウォレット — 詳細
スマートウォレット(マネージド、Privy 対応)
const w = await evm.wallet({ name: "my-oracle" }); // sponsorGas defaults TRUE
Privy によってクラウド側で作成されます。アドレスは永続化されます。デフォルトでガス代がスポンサーされます。 通常のローカル開発では使用できません。次のエラーがスローされます:"You cannot use a named wallet without a private key in local dev. Start with "goldsky compose start --fork-chains" for full wallet support, or use a private key wallet: const wallet = await evm.wallet({ privateKey: MY_SECRET }); See https://docs.goldsky.com/compose/secrets for more info on private key wallets" ローカルでのイテレーションには compose start --fork-chains を使用するか、BYO EOA に切り替えてください。
BYO EOA(秘密鍵)
const w = await evm.wallet({
privateKey: env.MY_KEY,
name: "my-pk-wallet", // optional; defaults to the derived address
sponsorGas: true, // DEFAULTS TO FALSE — opt in explicitly
});
クラウドとローカルの両方で動作します。sponsorGas: true の場合、ウォレットは初回使用時にチェーンごとに EIP-7702 の委任を設定し、その後、スポンサー付きバンドラーを通じて UserOperation を送信します。
ガス代のスポンサー
バンドラーのフォールバック順:Alchemy → Pimlico → Gelato。BUNDLER_PROVIDER=<alchemy|pimlico|gelato> 環境変数で上書きできます。
対応チェーン
3 つのバンドラープロバイダーのうちいずれかが対応していれば、そのチェーンではランタイム時のスポンサーが可能です(フォールバック順の Alchemy → Pimlico → Gelato で試行され、それぞれ API キーが設定されている場合に限ります)。バージョン 0.8.1 のソースでは、この集合は112 チェーンに及びます。これはランタイムタスクのガス代スポンサー対象であり、10 チェーンの Alchemy 対応セットを対象とする deployContract / writeContract のクラウド デプロイ パスよりはるかに広範です(1、11155111、137、80002、42161、421614、10、11155420、8453、84532。より広い対応範囲は FOU-991 で追跡中)。ランタイムのスポンサー対象には、Arbitrum、Optimism(Arbitrum Sepolia(421614)/Optimism Sepolia(11155420)を含む)、Polygon、Ethereum、BNB の各ファミリーなど、多数のチェーンが含まれます。リストをハードコードしないでください。内容は変わるため、Goldsky のドキュメントにあるチェーンのページで現在の対応状況を確認してください。
非対応チェーンでのエラー
No bundler provider available for chain <id>. Providers: alchemy: chain not supported; pimlico: missing keys (PIMLICO_API_KEY); gelato: …
対応チェーンを使用するか、sponsorGas: false を設定して EOA に手動で資金を入れてください。
注意点
onReorgはガス代スポンサー付きトランザクションではサポートされていません(警告がログに記録されますが、致命的なエラーではありません)。- スポンサー付き
sendTransactionにカスタムnonceを渡しても無視されます(ERC-4337 スマートウォレットでは異なる nonce 構造を使用します)。
コントラクトのコード生成(完全な例)
入力
ABI JSON ファイルを src/contracts/ に配置します:
src/contracts/
├── ERC20.json
└── PriceFeed.json
受け入れ可能な ABI 形式: ABI 配列のみ([{ "type": "function", ... }, ...])、ラップされたオブジェクト({ "abi": [...] })、または Foundry/Hardhat アーティファクト(ジェネレーターが abi フィールドを抽出します)。拡張子を除いたファイル名が、生成されるクラス名になります。
生成
goldsky compose codegen
(init、start、deploy の実行時にも自動的に実行されます。)
出力
.compose/generated/index.ts は ABI ごとのクラスをエクスポートします。.compose/types.d.ts は、スキャフォールドされた tsconfig.json から参照される compose パスエイリアス配下のアンビエント型を宣言します。
タスクでの利用
import type { TaskContext } from "compose";
export async function main({ evm, env }: TaskContext) {
const wallet = await evm.wallet({ name: "oracle" });
const PriceFeed = evm.contracts.PriceFeed;
// Read — generated view methods call wallet.readContract under the hood
const feed = new PriceFeed(env.FEED_ADDRESS, evm.chains.ethereum, wallet);
const price = await feed.latestAnswer();
// Write — generated state-changing methods call wallet.writeContract under the hood
const tx = await feed.setPrice(1234n);
return { price: price.toString(), hash: tx.hash };
}
クラスは context.evm.contracts.<Name> 配下に公開されます。コード生成された名前が Class で終わる場合(例:ERC20Class)、実行時には ERC20 として公開されます。生成されたコンストラクターは new <Name>(address, chain, wallet) です。evm.wallet(...) から取得した IWallet を渡してください。読み取り専用メソッドはそのウォレット経由で読み取り、状態変更メソッドはそのウォレット経由で書き込みます。どちらもウォレットのガス代スポンサー設定に従います。
サポート対象のチェーン
context.evm.chains は viem/chains から再エクスポートされています。viem が認識するチェーンはすべて、evm.chains.<name> で指定できます(例:evm.chains.polygonAmoy、evm.chains.monadTestnet、evm.chains.baseSepolia)。ガスのスポンサー提供については、「ガススポンサー提供」セクションをご覧ください。スポンサー提供の対象は、viem のチェーンリストの一部です。
ダッシュボード
URL のパターン:
https://app.goldsky.com/<project_id>/dashboard/compose/<app-name>
https://app.goldsky.com/<project_id>/dashboard/compose/<app-name>/runs/<run_id>
ダッシュボードには、ステータス、シークレットの名前、ログ、「Code」タブのファイルブラウザー、「Download app」ボタン、実行ごとのトレースが表示されます。compose runs から返された実行 ID を使って、実行の URL を作成してください。
料金
料金は公開されていません。使用量は、関数呼び出し(compose_function_calls)、ワーカー時間(compose_worker_hours)、ガスの使用量(compose_gas_spend)の 3 つの指標で計測されます。writeContract と deployContract が使用したガスには、実行時タスクのガスと同じ料金が適用されます。単位ごとの価格は契約ごとに設定されるため、料金プランを引用するのではなく、ユーザーに https://goldsky.com/pricing を案内してください。
関連項目
/compose— 新しいアプリを構築する、または Compose について説明します。/compose-doctor— 壊れたアプリを診断して修正します。/auth-setup—goldsky loginのヘルプです。/secrets— シークレット管理全般について説明します。