Offer safety check
Skill Spacetime-Technology/chia-skills/skills/offer-safety-check
Claude Code skills that turn chia-explorer into finished workflows: address watches, price alerts, offer safety checks, NFT provenance, invoice watching.
npx -y skills add Spacetime-Technology/chia-skills --skill offer-safety-checkAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Decode a Chia offer1... string, classify what's being traded on each side, fetch market prices, and surface a risk report before the user takes it. Use when the user pastes an offer they were sent, asks "is this offer fair?", or wants to vet a deal before opening their wallet. Accepts offer, max_unfavourable_pct as arguments for programmatic invocation.
SKILL.md
6.4 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
Offer safety check
You are vetting a Chia offer string for the user before they take it. Decode it locally via chia-explorer, classify both sides, fetch market prices, and produce a clear "looks fine" / "looks off" / "outright bad" verdict. Read-only. No wallet, no signing — the user takes the offer in their own wallet if they want to.
This skill follows the conventions in this repo's SKILLS.md. Read that if anything below is unclear.
Required capabilities
- chia-explorer (
mcp__chia-explorer__*) — mandatory. Thedecode_offeranddecompile_puzzletools do the heavy lifting; offer decoding is local (no RPC).
Resolve inputs
You need: $offer, $max_unfavourable_pct.
$offer— theoffer1...bech32m string. Required.$max_unfavourable_pct— how much worse than market you're willing to accept on the side you're giving up. Default5(5%). Set higher for less liquid CATs.
Resolve: arguments → context → ask user.
Strip whitespace from $offer (offers often get word-wrapped). If it doesn't start with offer1, emit STATUS: failed, REASON: not an offer string.
Decode
Decode the offer locally. Extract:
- Offered side — what the other party is offering (what you'd receive).
- Requested side — what they want from you in return.
Each side is a list of assets:
- XCH amounts (mojos → XCH)
- CAT amounts, each with an
asset_id - NFT(s), each with a
launcher_id
If decoding fails, emit STATUS: failed, REASON: offer failed to decode. Don't try to be heroic with a malformed string.
Classify each asset
For every CAT, identify the asset. chia-explorer's decompile/classify tools return the asset_id. Match against the small set of well-known tickers (DBX, SBX, USDS, etc.). If unmatched, call it unknown CAT (asset_id 0x...) and flag risk: unknown CATs can be worthless or scammy clones with deceptively similar names.
For every NFT, fetch the launcher_id. Don't bulk-fetch off-chain metadata — that's slow and out of scope. Surface the launcher_id and tell the user to verify the NFT in their wallet before taking.
Fetch market prices
For each side:
- XCH — current spot price from chia-explorer (USD).
- Known CATs — chia-explorer does not currently price CATs. State this explicitly and leave the CAT side unvalued. Don't invent prices.
- NFTs — same. No automatic floor price lookup.
Total each side's USD value where possible. If a side contains an unknown CAT or an NFT, mark the total as "partial: includes unvalued asset".
Compare and surface verdict
Compute the imbalance from the user's perspective (assume the user is taking the offer, so they receive the offered side and give the requested side):
- If both sides are fully valued in fiat:
imbalance_pct = (requested_value - offered_value) / offered_value * 100- Negative imbalance → user receives more than they give → favourable.
- Positive imbalance → user gives more than they receive → unfavourable.
- If either side has an unvalued asset, skip the percentage but still describe both sides side by side.
Verdict thresholds (against $max_unfavourable_pct):
- imbalance < 0 →
FAVOURABLE(user benefits) 0 ≤ imbalance ≤ max_unfavourable_pct→NEUTRAL- imbalance >
max_unfavourable_pct→UNFAVOURABLE(recommend declining)
Risk flags (add any that apply):
unknown_cat— at least one CAT on either side has an unrecognised asset_id.nft_present— an NFT is on either side; user must verify launcher_id matches the expected collection.large_amount— total value on a fully-priced side exceeds 1000 XCH equivalent.multi_asset_side— three or more distinct assets on a single side. Common in dump-bundling scams.decoded_but_unverifiable— at least one asset's puzzle could be decoded but classification was ambiguous.
Compose the report
Plain-text report, surfaced inline in the conversation. Don't push to a channel — this is interactive.
Offer safety check
Verdict: UNFAVOURABLE (you'd give 12.3% more than you receive)
Risk flags: unknown_cat, multi_asset_side
YOU RECEIVE (the offered side)
+ 1.000 XCH ~$50.00
+ 500 unknown CAT (asset_id 0xabc...123) unpriced
YOU GIVE (the requested side)
- 1.200 XCH ~$60.00 (rounded)
- 1 NFT launcher 0xdef...456 unpriced
NOTES
- Unknown CAT on the offered side. Don't take unless you've verified
the asset_id matches the project you think it does. Names can be
spoofed; asset_ids cannot.
- NFT on the requested side. Confirm in your wallet that this is the
launcher you intend to give up.
- You handle the trade in your wallet — this check does not sign.
Hard rules
- Read-only. Never take the offer. Never call any wallet MCP. Just report.
- Asset_id and launcher_id are truth. Names and tickers can be spoofed; identifiers cannot. Always show the full id (truncated for readability, full on request).
- Unpriced ≠ valueless. Don't tell the user a CAT is worthless because you can't price it. Just say "unpriced".
- No advice on whether to take. Verdict is mechanical (above or below the imbalance threshold). The user decides.
Recovery patterns
- Decode fails. Report failure with the verbatim error. Common cause: truncated paste.
- Price tool fails. Skip fiat valuations; render the asset list anyway. Emit
STATUS: partial. - Multi-NFT or multi-CAT offer. Render every asset. Don't summarise away detail; the user needs to see what's actually in the offer.
Output
STATUS: success | partial | failed | aborted
VERDICT: FAVOURABLE | NEUTRAL | UNFAVOURABLE | UNPRICEABLE
IMBALANCE_PCT: <decimal or none>
OFFERED_SIDE_USD: <total or partial> | none
REQUESTED_SIDE_USD: <total or partial> | none
RISK_FLAGS: <comma-separated, or none>
ARTIFACT: none
REASON: <one line, only when STATUS is failed, partial, or aborted>
Gives 0 of the 12 instructions most quality gates skills give in ~1.5k tokens
Counted across 1,195 of the 2,094 authors here whose files we hold, read 2026-08-06
- read the output and check the exit codein 55 of 1195, across 14 files
- verify requirements using a line-by-line checklistin 53 of 1195, across 12 files
- identify the verification command proving the claimin 53 of 1195, across 12 files
- run the full verification commandin 51 of 1195, across 11 files
- verify output confirms the claimin 49 of 1195, across 10 files
- check version control diff after agent delegationin 45 of 1195, across 5 files
- state claim with evidencein 43 of 1195, across 3 files
- run the test suitein 32 of 1195, across 24 files
- keep state in memory by defaultin 27 of 1195, across 6 files
- make prototype runnable with one commandin 26 of 1195, across 5 files
- detect the package manager from lockfilesin 24 of 1195, across 5 files
- produce a verification reportin 23 of 1195, across 12 files
Said here and by no other author read
- decode the offer string locally
- classify assets on both sides
- match cat asset ids against known tickers
- fetch current xch spot prices
- compute the fiat value imbalance
- compare the imbalance against maximum threshold
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.