From goldsky
Builds and deploys the Goldsky Compose bitcoin-oracle cron task that fetches BTC/USD from CoinGecko and writes timestamp/price on-chain via a managed wallet.
How this skill is triggered — by the user, by Claude, or both
Slash command
/goldsky:compose-bitcoin-oracleThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Stand up the bitcoin-oracle example under the user's own Goldsky account. A cron task fetches BTC/USD from CoinGecko and writes `(timestamp, price * 100)` as two `bytes32` values to a `PriceOracle` contract via a Compose-managed wallet. It also appends the price to a Compose `collection` for historical queries.
Stand up the bitcoin-oracle example under the user's own Goldsky account. A cron task fetches BTC/USD from CoinGecko and writes (timestamp, price * 100) as two bytes32 values to a PriceOracle contract via a Compose-managed wallet. It also appends the price to a Compose collection for historical queries.
This skill is the single source of truth for the procedure. It merges the runnable example in goldsky-io/documentation-examples (compose/bitcoin-oracle) with the in-app seed-prompt flow. The recommended path uses a shared, fully-unpermissioned PriceOracle on Base Sepolia, so the user deploys nothing and the Compose smart wallet is auto-created and gas-sponsored. Assume the user has never used Goldsky Compose before. Do not skip preflight.
Pick the mode from the tools available to you:
A deployComposeApp tool is available (Goldsky webapp chatbot) — this is the preferred in-app flow. Do NOT emit goldsky terminal commands or cliCommand cards, and do NOT use Step 0 / degit / forge / goldsky compose deploy. Instead: give a 2-3 sentence plain explanation, then ask the config questions one at a time with askUser (tag the recommended option with recommendedIndex):
bitcoin-oracle).PriceOracle contract, or should we use a shared demo oracle on Base Sepolia to get running quickly?" Options: "Use the shared demo oracle on Base Sepolia (recommended — nothing to deploy)" and "I'll use my own contract." On the shared path, ORACLE_CONTRACT is the HARDCODED address 0x53deB3fF6E6e82A3b5E96f14E185e3Fe66BF5113 on baseSepolia — copy it character-for-character, do NOT alter or retype it from memory; mention in prose that it's demos-only, not production. On the own path, ask the user to paste their contract address and chain, and use exactly what they paste (their PriceOracle must let the Compose wallet write).* * * * *).The Compose smart wallet is auto-created at runtime and gas-sponsored — never tell the user to create or fund a wallet. After the interview, scaffold the files in-memory and pass them to deployComposeApp (do NOT degit): compose.yaml (a single cron task on the chosen schedule), src/contracts/PriceOracle.json (the verbatim ABI in Step 3), and src/tasks/bitcoin-oracle.ts (fetch BTC/USD from CoinGecko, then evm.contracts.PriceOracle.write(toBytes32(timestamp), toBytes32(Math.round(price*100))) on the chosen chain via the gas-sponsored smart wallet, wired to ORACLE_CONTRACT, appending each price to a bitcoin_prices collection). First load /compose-reference for the manifest schema and the sandbox import rule, then write these files following them — do not invent the manifest shape or import external packages (evm/fetch/collection come from the injected context; the only imports allowed are compose and sibling files). Then call deployComposeApp in the SAME turn to present the in-app deploy card — do not ask the user to confirm first, do not emit any goldsky command, and do not make them run anything in a terminal. After the deploy card, print nothing else. In this mode, ignore Steps 0–8 below entirely — they are the CLI/local procedure.
Bash is available (local CLI / coding agent): execute the steps below directly, parse output, and substitute captured values into later commands.
Neither (pure reference Q&A): explain what the app does; only if asked for step-by-step help, output one command at a time and have the user paste output back. Point them at npx skills add goldsky-io/goldsky-agent to run it locally with Bash.
0x53deB3fF6E6e82A3b5E96f14E185e3Fe66BF5113 on Base Sepolia is fully unpermissioned — anyone can write to it. It exists for getting started and demos only. Tell the user, in prose, that it must NOT be used in production. It only exists on Base Sepolia.forge create, goldsky compose deploy, git push, or gh repo create without showing the exact command first and getting explicit confirmation.write() reverts. On the shared-oracle path there is no writer restriction, so this does not apply.src/contracts/PriceOracle.json (the ABI), not Solidity source. If deploying fresh, use the reference contract in this skill. Write the ABI verbatim — see Step 3.src/lib/utils.ts. toBytes32 is coupled to how the contract stores the value.When this skill says $FOO, capture the literal value from the prior command's output and substitute it directly into the next command. Do not rely on shell variables persisting between separate Bash tool invocations — each invocation gets a fresh shell with no env carryover from earlier commands.
Steps 0–8 below are the Bash / local-CLI procedure. If a
deployComposeApptool is available (webapp chatbot), do NOT follow them — use the deploy-tool flow in Mode Detection above.
Pull just the bitcoin-oracle example into a fresh directory (no git history):
npx degit goldsky-io/documentation-examples/compose/bitcoin-oracle bitcoin-oracle
cd bitcoin-oracle
If npx degit is unavailable, fall back to a sparse clone:
git clone --depth 1 --filter=blob:none --sparse https://github.com/goldsky-io/documentation-examples.git
cd documentation-examples && git sparse-checkout set compose/bitcoin-oracle && cd compose/bitcoin-oracle
If the user already cloned the example, skip this step and cd into it.
goldsky CLI — goldsky --version. Install per https://docs.goldsky.com/reference/cli.goldsky authenticated — goldsky project list. If it errors, stop and tell the user: "Please run goldsky login in your terminal — browser flow. Tell me to continue when you see the success message." Do not spawn goldsky login from Bash; it requires an interactive browser.deno — deno --version. curl -fsSL https://deno.land/install.sh | sh if missing.foundry — forge --version. Only needed on the deploy-your-own path.Ask one question at a time; let each answer inform the next. Use readable labels and translate to machine values yourself.
bitcoin-oracle) → top-level name: in compose.yaml.baseSepolia).0x53deB3fF6E6e82A3b5E96f14E185e3Fe66BF5113 (mention the address in prose, not in any option label). Demos/getting-started only, not production.* * * * *), every 5 minutes (*/5 * * * *), or every hour. Set the expression: under the cron trigger in compose.yaml.evm.wallet({ name: "bitcoin-oracle-wallet" }) in src/tasks/bitcoin-oracle.ts) and capture its address as $COMPOSE_WALLET:
goldsky compose wallet create bitcoin-oracle-wallet
Branch A — Reuse shared oracle (recommended). $CONTRACT_ADDRESS = 0x53deB3fF6E6e82A3b5E96f14E185e3Fe66BF5113 on Base Sepolia. No deploy, no writer authorization. Skip to Step 4.
Branch B — Deploy your own. First confirm src/contracts/PriceOracle.json contains exactly this ABI (write it verbatim if scaffolding inline; never invent ABI):
[{"inputs":[{"internalType":"bytes32","name":"timestamp","type":"bytes32"},{"internalType":"bytes32","name":"price","type":"bytes32"}],"name":"write","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"latestTimestamp","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestPrice","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"timestamp","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"price","type":"bytes32"}],"name":"PriceUpdated","type":"event"}]
Run mkdir -p contracts, write this reference Solidity to contracts/PriceOracle.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract PriceOracle {
address public writer;
bytes32 public latestTimestamp;
bytes32 public latestPrice;
event PriceUpdated(bytes32 indexed timestamp, bytes32 price);
error OnlyWriter();
constructor(address _writer) { writer = _writer; }
function setWriter(address newWriter) external {
if (msg.sender != writer) revert OnlyWriter();
writer = newWriter;
}
function write(bytes32 timestamp, bytes32 price) external {
if (msg.sender != writer) revert OnlyWriter();
latestTimestamp = timestamp;
latestPrice = price;
emit PriceUpdated(timestamp, price);
}
}
Then output this for the user to run with their own funded EOA (constructor arg authorizes the Compose wallet from Step 2):
forge create contracts/PriceOracle.sol:PriceOracle \
--rpc-url <RPC_URL_FOR_CHOSEN_CHAIN> \
--private-key $PRIVATE_KEY \
--broadcast \
--constructor-args $COMPOSE_WALLET
RPC URLs: baseSepolia → https://sepolia.base.org, base → https://mainnet.base.org, polygonAmoy → https://rpc-amoy.polygon.technology, polygon → https://polygon-rpc.com, arbitrum → https://arb1.arbitrum.io/rpc, optimism → https://mainnet.optimism.io. Capture Deployed to: 0x... as $CONTRACT_ADDRESS. (Already have a PriceOracle-shaped contract? Grant the Compose wallet write permission via setWriter($COMPOSE_WALLET) from the owner EOA and use its address instead.)
Edit src/tasks/bitcoin-oracle.ts — use grep anchors:
const ORACLE_CONTRACT = "0x..." near the top and replace the address with $CONTRACT_ADDRESS.evm.chains.* reference inside the new evm.contracts.PriceOracle(...) call and set it to evm.chains.<chosen chain in camelCase> (e.g. baseSepolia).If the user changed the cron cadence, edit the expression: under the cron trigger in compose.yaml.
Compose-managed wallets default to sponsorGas: true on sponsored chains (Base, Base Sepolia, Polygon, Polygon Amoy, and others). On those chains the wallet needs no funding — skip this step. On a non-sponsored chain, send native gas token to $COMPOSE_WALLET (testnet faucet, or budget for the cron cadence on mainnet: every-minute writes ≈ 1,440 tx/day).
git init
git add .
git ls-files --cached | grep -iE '(keypair\.json|\.env|private[._-]?key|\.pem|id_rsa)' && \
{ echo "ABORT: secret-shaped file staged"; exit 1; }
git commit -m "Initial commit: Compose bitcoin-oracle"
gh repo create <user's repo name> --<public|private> --source=. --push
goldsky compose deploy
Tail logs and wait for the next cron fire (up to 1 minute):
goldsky compose logs
Good output is a return payload with success: true and an oracleHash 0x-prefixed tx hash, repeating on cadence with no retries.
Verify on-chain (Base Sepolia explorer: https://sepolia.basescan.org/address/$CONTRACT_ADDRESS#events): you should see a PriceUpdated event per cron fire, and latestPrice() / latestTimestamp() should return recent bytes32 values.
compose.yaml or source files don't take effect after redeploy. The local .compose/ bundle cache is stale. Run rm -rf .compose/ and redeploy.setWriter($COMPOSE_WALLET) (Branch A of your own contract) or re-check the forge create constructor arg. (Shared oracle has no writer restriction, so this can't be the cause there.)insufficient funds for gas. Only possible on a non-sponsored chain with deploy-your-own. Fund $COMPOSE_WALLET.evm.chains.* reference matches the chain where the contract lives. A wallet on the wrong chain signs a tx that never appears on the intended chain.toBytes32 helper in src/lib/utils.ts. The contract reads price as bytes32 and the example scales by 100 (cents); changing either side silently breaks the stored value.PriceOracle ABI. Use the verbatim ABI in Step 3./compose — Build a new/custom Compose app from scratch, or explain what Compose is./compose-reference — Manifest, CLI, TaskContext API, wallets, gas sponsorship, codegen./compose-doctor — Diagnose and fix a broken Compose app./auth-setup — goldsky login walkthrough.npx claudepluginhub goldsky-io/goldsky-agentGenerates brand assets: logos (55+ styles, Gemini AI), CIP mockups, HTML slides (Chart.js), banners (22 styles), SVG icons (15 styles), and social media photos. Routes to sub-skills for design tokens and UI styling.