jpskill.com
📦 その他 コミュニティ

nostr-marketplace-builder

Nostrプロトコル上で、NIP-15の販売所、商品、オークションやNIP-69のP2P注文を活用し、eコマースや商品リスト作成、オークションシステム構築、P2P取引などを実現するアプリケーションを開発するSkill。

📜 元の英語説明(参考)

Build Nostr marketplace applications using NIP-15 stalls, products, auctions, and NIP-69 P2P orders. Use when creating e-commerce on Nostr, building product listings, setting up stalls with shipping zones, implementing auction bidding systems, constructing checkout flows with NIP-04 DMs, creating P2P trading orders, or generating marketplace UI configurations. Covers kind:30017 stalls, kind:30018 products, kind:30020 auctions, kind:1021 bids, kind:1022 bid confirmations, kind:30019 marketplace UI, and kind:38383 P2P orders.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Nostrプロトコル上で、NIP-15の販売所、商品、オークションやNIP-69のP2P注文を活用し、eコマースや商品リスト作成、オークションシステム構築、P2P取引などを実現するアプリケーションを開発するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o nostr-marketplace-builder.zip https://jpskill.com/download/9137.zip && unzip -o nostr-marketplace-builder.zip && rm nostr-marketplace-builder.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/9137.zip -OutFile "$d\nostr-marketplace-builder.zip"; Expand-Archive "$d\nostr-marketplace-builder.zip" -DestinationPath $d -Force; ri "$d\nostr-marketplace-builder.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して nostr-marketplace-builder.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → nostr-marketplace-builder フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Nostr Marketplace Builder

概要

商用アプリケーション向けの正しい Nostr マーケットプレイスイベントを構築します。このスキルは、わかりにくい部分、つまり、ストール/製品の関係、配送料の計算、オークションのライフサイクルルール、NIP-04 を介したチェックアウトメッセージのシーケンス、および NIP-69 からの P2P 注文タグ構造を処理します。

どのような時に使用するか

  • 配送ゾーンを持つマーチャントストールを作成する (kind:30017)
  • カテゴリと仕様を持つ製品をリストする (kind:30018)
  • 入札によるオークションを設定する (kind:30020, kind:1021, kind:1022)
  • チェックアウトフローを構築する (NIP-04 order → payment → status)
  • ビットコイントレード用の P2P 売買注文を作成する (NIP-69 kind:38383)
  • カスタムマーケットプレイス UI を構成する (kind:30019)
  • ゾーンと製品全体の配送料を計算する

以下の場合には使用しないでください:

  • 一般的な Nostr イベントを構築する (nostr-event-builder を使用)
  • リレー WebSocket ロジックを実装する
  • NIP-19 のエンコード/デコードを扱う

ワークフロー

1. 構築するものを特定する

インテント Kind(s) NIP
マーチャントストールを作成/更新する 30017 NIP-15
販売する製品をリストする 30018 NIP-15
マーケットプレイス UI を構成する 30019 NIP-15
オークション出品を作成する 30020 NIP-15
オークションに入札する 1021 NIP-15
入札を承認/拒否する 1022 NIP-15
チェックアウト (order/pay/status) NIP-04 DMs NIP-15
P2P 売買注文 38383 NIP-69

2. イベントを構築する

ストール (Kind:30017) — アドレス指定可能

ストールはマーチャントのストアです。製品はストールに属します。配送ゾーンは、基本コストとともにストールレベルで定義されます。

{
  "kind": 30017,
  "tags": [["d", "my-stall-001"]],
  "content": "{\"id\":\"my-stall-001\",\"name\":\"Satoshi's Electronics\",\"description\":\"Quality electronics for sats\",\"currency\":\"USD\",\"shipping\":[{\"id\":\"us-domestic\",\"name\":\"US Domestic\",\"cost\":5.99,\"regions\":[\"US\"]},{\"id\":\"worldwide\",\"name\":\"Worldwide\",\"cost\":15.00,\"regions\":[\"EU\",\"AS\",\"SA\"]}]}"
}

ルール:

  • d タグの値は、コンテンツ JSON の id と一致する必要があります
  • id は UUID または記述的なスラッグである必要があります — 連番 ID (0, 1, 2) は推奨されません
  • currency は文字列です (例: "USD", "BTC", "EUR")
  • shipping 配列はゾーンを定義します。顧客はチェックアウト時に正確に 1 つのゾーンを選択する必要があります
  • 各ゾーンには、ストールの通貨での基本 cost があります

製品 (Kind:30018) — アドレス指定可能

製品は stall_id を介してストールに属します。ストールの基本配送料に加えて、製品ごとの配送料を追加できます。

{
  "kind": 30018,
  "tags": [
    ["d", "product-xyz-789"],
    ["t", "electronics"],
    ["t", "gadgets"]
  ],
  "content": "{\"id\":\"product-xyz-789\",\"stall_id\":\"my-stall-001\",\"name\":\"Lightning Node Kit\",\"description\":\"Pre-configured Bitcoin node\",\"images\":[\"https://example.com/node.jpg\"],\"currency\":\"USD\",\"price\":299.99,\"quantity\":25,\"specs\":[[\"processor\",\"ARM Cortex-A72\"],[\"storage\",\"1TB SSD\"],[\"connectivity\",\"Ethernet + WiFi\"]],\"shipping\":[{\"id\":\"us-domestic\",\"cost\":10.00},{\"id\":\"worldwide\",\"cost\":25.00}]}"
}

ルール:

  • d タグの値は、コンテンツ JSON の id と一致する必要があります
  • stall_id は、既存のストールの id を参照する必要があります
  • quantity: 在庫が限られている場合は整数、無制限の場合は null (デジタル商品/サービス)
  • t タグは検索可能なカテゴリです — 発見可能性を高めるために複数使用します
  • specs は、構造化された表示のための [key, value] ペアの配列です
  • 製品の shipping[].id は、親ストールのゾーン id と一致する必要があります
  • 合計配送料 = ストールの基本コスト + (製品配送料 × 数量)

マーケットプレイス UI (Kind:30019) — アドレス指定可能

マーチャントをグループ化するカスタムマーケットプレイス構成:

{
  "kind": 30019,
  "tags": [["d", "my-marketplace"]],
  "content": "{\"name\":\"Bitcoin Bazaar\",\"about\":\"A curated marketplace for Bitcoin products\",\"ui\":{\"picture\":\"https://example.com/logo.png\",\"banner\":\"https://example.com/banner.jpg\",\"theme\":\"dark\",\"darkMode\":true},\"merchants\":[\"pubkey1hex...\",\"pubkey2hex...\"]}"
}

オークション (Kind:30020) — アドレス指定可能

オークションは製品に似ていますが、入札メカニズムがあります。

{
  "kind": 30020,
  "tags": [["d", "auction-rare-item-001"]],
  "content": "{\"id\":\"auction-rare-item-001\",\"stall_id\":\"my-stall-001\",\"name\":\"Signed Hal Finney Print\",\"description\":\"Limited edition signed print\",\"images\":[\"https://example.com/print.jpg\"],\"starting_bid\":50000,\"start_date\":1719391096,\"duration\":86400,\"specs\":[[\"condition\",\"mint\"],[\"authentication\",\"verified\"]],\"shipping\":[{\"id\":\"worldwide\",\"cost\":20.00}]}"
}

ルール:

  • starting_bid はストールの通貨 (整数) です
  • start_date は Unix タイムスタンプです。開始日が不明な場合は省略します
  • duration はオークションが実行される秒数です (延長を除く)
  • 実際の終了 = start_date + duration + SUM(確認からのすべての duration_extended)
  • 最初の入札を受け取った後はオークションを編集できません — 入札は製品 UUID ではなくイベント ID を参照するため、編集すると新しいイベント ID が作成され、すべての入札が失われます

入札 (Kind:1021) — 通常

{
  "kind": 1021,
  "content": "75000",
  "tags": [["e", "<auction-event-id>"]]
}

ルール:

  • content は、オークションの通貨での入札額を文字列として表したものです
  • e タグは、製品 UUID ではなく、オークションの イベント ID を参照します
  • これが入札後にオークションを編集すると、それらの入札が破棄される理由です

入札確認 (Kind:1022) — 通常

マーチャントによって送信され、入札を検証します。

{
  "kind": 1022,
  "content": "{\"status\":\"accepted\",\"message\":\"Bid received and validated\",\"duration_extended\":300}",
  "tags": [
    ["e", "<bid-event-id>"],
    ["e", "<auction-event-id>"]
  ]
}

ステータス値: accepted, rejected, pending, winner

  • winner は winnin に送信されます

(原文がここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Nostr Marketplace Builder

Overview

Construct correct Nostr marketplace events for commerce applications. This skill handles the non-obvious parts: stall/product relationships, shipping cost calculations, auction lifecycle rules, checkout message sequencing via NIP-04, and P2P order tag structures from NIP-69.

When to Use

  • Creating a merchant stall with shipping zones (kind:30017)
  • Listing products with categories and specs (kind:30018)
  • Setting up auctions with bidding (kind:30020, kind:1021, kind:1022)
  • Building checkout flows (NIP-04 order → payment → status)
  • Creating P2P buy/sell orders for bitcoin trading (NIP-69 kind:38383)
  • Configuring a custom marketplace UI (kind:30019)
  • Calculating shipping costs across zones and products

Do NOT use when:

  • Building generic Nostr events (use nostr-event-builder)
  • Implementing relay WebSocket logic
  • Working with NIP-19 encoding/decoding

Workflow

1. Identify What to Build

Intent Kind(s) NIP
Create/update a merchant stall 30017 NIP-15
List a product for sale 30018 NIP-15
Configure marketplace UI 30019 NIP-15
Create an auction listing 30020 NIP-15
Place a bid on an auction 1021 NIP-15
Confirm/reject a bid 1022 NIP-15
Checkout (order/pay/status) NIP-04 DMs NIP-15
P2P buy/sell order 38383 NIP-69

2. Build the Event

Stall (Kind:30017) — Addressable

The stall is the merchant's store. Products belong to stalls. Shipping zones are defined at the stall level with base costs.

{
  "kind": 30017,
  "tags": [["d", "my-stall-001"]],
  "content": "{\"id\":\"my-stall-001\",\"name\":\"Satoshi's Electronics\",\"description\":\"Quality electronics for sats\",\"currency\":\"USD\",\"shipping\":[{\"id\":\"us-domestic\",\"name\":\"US Domestic\",\"cost\":5.99,\"regions\":[\"US\"]},{\"id\":\"worldwide\",\"name\":\"Worldwide\",\"cost\":15.00,\"regions\":[\"EU\",\"AS\",\"SA\"]}]}"
}

Rules:

  • d tag value MUST equal the id in content JSON
  • id should be a UUID or descriptive slug — sequential IDs (0, 1, 2) are discouraged
  • currency is a string (e.g., "USD", "BTC", "EUR")
  • shipping array defines zones; customer must choose exactly one zone at checkout
  • Each zone has a base cost in the stall's currency

Product (Kind:30018) — Addressable

Products belong to a stall via stall_id. They can add per-product shipping costs on top of the stall's base shipping cost.

{
  "kind": 30018,
  "tags": [
    ["d", "product-xyz-789"],
    ["t", "electronics"],
    ["t", "gadgets"]
  ],
  "content": "{\"id\":\"product-xyz-789\",\"stall_id\":\"my-stall-001\",\"name\":\"Lightning Node Kit\",\"description\":\"Pre-configured Bitcoin node\",\"images\":[\"https://example.com/node.jpg\"],\"currency\":\"USD\",\"price\":299.99,\"quantity\":25,\"specs\":[[\"processor\",\"ARM Cortex-A72\"],[\"storage\",\"1TB SSD\"],[\"connectivity\",\"Ethernet + WiFi\"]],\"shipping\":[{\"id\":\"us-domestic\",\"cost\":10.00},{\"id\":\"worldwide\",\"cost\":25.00}]}"
}

Rules:

  • d tag value MUST equal the id in content JSON
  • stall_id MUST reference an existing stall's id
  • quantity: integer for limited stock, null for unlimited (digital goods/services)
  • t tags are searchable categories — use multiple for discoverability
  • specs is an array of [key, value] pairs for structured display
  • Product shipping[].id MUST match a zone id from the parent stall
  • Total shipping = stall base cost + (product shipping cost × quantity)

Marketplace UI (Kind:30019) — Addressable

Custom marketplace configuration grouping merchants together:

{
  "kind": 30019,
  "tags": [["d", "my-marketplace"]],
  "content": "{\"name\":\"Bitcoin Bazaar\",\"about\":\"A curated marketplace for Bitcoin products\",\"ui\":{\"picture\":\"https://example.com/logo.png\",\"banner\":\"https://example.com/banner.jpg\",\"theme\":\"dark\",\"darkMode\":true},\"merchants\":[\"pubkey1hex...\",\"pubkey2hex...\"]}"
}

Auction (Kind:30020) — Addressable

Auctions are similar to products but with bidding mechanics:

{
  "kind": 30020,
  "tags": [["d", "auction-rare-item-001"]],
  "content": "{\"id\":\"auction-rare-item-001\",\"stall_id\":\"my-stall-001\",\"name\":\"Signed Hal Finney Print\",\"description\":\"Limited edition signed print\",\"images\":[\"https://example.com/print.jpg\"],\"starting_bid\":50000,\"start_date\":1719391096,\"duration\":86400,\"specs\":[[\"condition\",\"mint\"],[\"authentication\",\"verified\"]],\"shipping\":[{\"id\":\"worldwide\",\"cost\":20.00}]}"
}

Rules:

  • starting_bid is in the stall's currency (integer)
  • start_date is a Unix timestamp; omit if start date is unknown
  • duration is seconds the auction runs (excluding extensions)
  • Actual end = start_date + duration + SUM(all duration_extended from confirmations)
  • Cannot edit auction after receiving first bid — bids reference the event ID (not product UUID), so editing creates a new event ID and loses all bids

Bid (Kind:1021) — Regular

{
  "kind": 1021,
  "content": "75000",
  "tags": [["e", "<auction-event-id>"]]
}

Rules:

  • content is the bid amount as a string (in the auction's currency)
  • The e tag references the event ID of the auction, not the product UUID
  • This is why editing an auction after bids destroys those bids

Bid Confirmation (Kind:1022) — Regular

Sent by the merchant to validate bids:

{
  "kind": 1022,
  "content": "{\"status\":\"accepted\",\"message\":\"Bid received and validated\",\"duration_extended\":300}",
  "tags": [
    ["e", "<bid-event-id>"],
    ["e", "<auction-event-id>"]
  ]
}

Status values: accepted, rejected, pending, winner

  • winner is sent to the winning bid after auction ends
  • duration_extended (optional): seconds added to auction duration
  • Clients must verify the confirmation pubkey matches the merchant's pubkey

3. Checkout Flow (NIP-04 DMs)

Checkout uses encrypted direct messages. See references/checkout-flow.md for full details.

Step 1 — Customer sends order (type:0):

{
  "id": "order-uuid-123",
  "type": 0,
  "name": "Alice",
  "address": "123 Bitcoin St, Miami, FL",
  "message": "Please ship ASAP",
  "contact": {
    "nostr": "<customer-pubkey-hex>",
    "phone": null,
    "email": "alice@example.com"
  },
  "items": [
    { "product_id": "product-xyz-789", "quantity": 2 }
  ],
  "shipping_id": "us-domestic"
}

Step 2 — Merchant sends payment request (type:1):

{
  "id": "order-uuid-123",
  "type": 1,
  "message": "Payment required within 15 minutes",
  "payment_options": [
    { "type": "ln", "link": "lnbc..." },
    { "type": "btc", "link": "bc1q..." },
    { "type": "url", "link": "https://pay.example.com/order-123" }
  ]
}

Step 3 — Merchant sends status update (type:2):

{
  "id": "order-uuid-123",
  "type": 2,
  "message": "Payment confirmed, shipping tomorrow",
  "paid": true,
  "shipped": false
}

4. P2P Orders (NIP-69 Kind:38383)

For peer-to-peer bitcoin trading. See references/marketplace-events.md for full tag reference.

{
  "kind": 38383,
  "tags": [
    ["d", "order-uuid-456"],
    ["k", "sell"],
    ["f", "USD"],
    ["s", "pending"],
    ["amt", "100000"],
    ["fa", "50"],
    ["pm", "zelle", "cashapp"],
    ["premium", "3"],
    ["network", "mainnet"],
    ["layer", "lightning"],
    ["name", "SatoshiTrader"],
    ["bond", "1000"],
    ["expires_at", "1719391096"],
    ["expiration", "1719995896"],
    ["y", "my-platform"],
    ["z", "order"]
  ],
  "content": ""
}

Required tags: d, k, f, s, amt, fa, pm, premium, network, layer, expires_at, expiration, y, z

Status flow: pendingin-progresssuccess | canceled | expired

5. Validate Before Publishing

  • [ ] d tag matches content id (for kinds 30017, 30018, 30020)
  • [ ] Product stall_id references a valid stall
  • [ ] Product shipping zone IDs match stall shipping zone IDs
  • [ ] quantity is integer or null (not string, not undefined)
  • [ ] Auction starting_bid is an integer
  • [ ] Bid e tag references auction event ID (not product UUID)
  • [ ] Bid confirmation has two e tags (bid + auction)
  • [ ] Checkout messages use correct type values (0, 1, 2)
  • [ ] P2P order has z tag set to "order"
  • [ ] P2P order f tag uses ISO 4217 currency code
  • [ ] P2P order k tag is "buy" or "sell"
  • [ ] All timestamps are Unix seconds (not milliseconds)
  • [ ] Content is stringified JSON where required

Shipping Cost Calculation

Total shipping for an order:

base_cost = stall.shipping[chosen_zone].cost
per_product = SUM(product.shipping[chosen_zone].cost × quantity) for each item
total_shipping = base_cost + per_product

Example: Stall base shipping $5.99, buying 2 units of a product with $10 extra shipping per unit → total shipping = $5.99 + (2 × $10) = $25.99.

Common Mistakes

Mistake Why It Breaks Fix
d tag doesn't match content id Relay can't address the event correctly Always keep d tag and content id identical
Sequential IDs (0, 1, 2) Collision risk across merchants Use UUIDs or descriptive slugs
Editing auction after bids received Bids reference event ID which changes on edit Never edit auctions that have bids
Bid references product UUID instead of event ID Bid won't be associated with the auction Use the auction's Nostr event ID in the e tag
Missing z tag on P2P orders Clients can't identify the event as an order Always include ["z", "order"]
Using buy/sell without ISO 4217 f tag Currency is ambiguous Use standard codes: USD, EUR, BRL, VES
Product shipping zone ID doesn't match stall Shipping calculation breaks Product shipping IDs must exist in parent stall
quantity as string "10" instead of int 10 Type mismatch in clients Use integer or null, never string
Checkout type as string "0" instead of int 0 Message routing fails Use integer type values: 0, 1, 2
Bid confirmation missing auction e tag Can't link confirmation to auction Include both bid and auction e tags

Quick Reference

Event Kind Category Key Fields
Stall 30017 Addressable id, name, currency, shipping zones
Product 30018 Addressable id, stall_id, price, quantity, specs, shipping
Marketplace UI 30019 Addressable name, ui config, merchant pubkeys
Auction 30020 Addressable id, stall_id, starting_bid, start_date, duration
Bid 1021 Regular amount in content, e tag → auction event ID
Bid Confirmation 1022 Regular status, e tags → bid + auction
P2P Order 38383 Addressable k (buy/sell), f (currency), s (status), amt, fa

Key Principles

  1. IDs must be consistent — The d tag and the id field inside content JSON must always match. This is how addressable events are located.

  2. Shipping is hierarchical — Stalls define base shipping zones and costs. Products add per-unit costs on top. The customer picks one zone at checkout.

  3. Auctions are immutable after bids — Because bids reference the event ID (not a UUID), editing an auction creates a new event and orphans existing bids. Design auctions carefully before publishing.

  4. Checkout is sequential — Order (type:0) → Payment request (type:1) → Status update (type:2). Each message references the same order ID. All messages are NIP-04 encrypted DMs.

  5. P2P orders are self-contained — All trade parameters live in tags, not content. The z tag must be "order" for client discovery. Status transitions follow: pending → in-progress → success/canceled/expired.