Casa Tookan 開発者
連携ガイド

あなたのサイトを、すべての Casa に。

Casa Tookan は、あなたのサイトが使うウォレット API にすでに対応しています。コードゼロからプレイヤーアカウントまで、小さなレベルを一つずつ進みましょう。

必要なレベルまで進めてください。

Casa Tookan では、プレイヤーのアドレスはすべて Casa の中にあります。Casa は小屋から城へと育つプロフィールです。あなたの連携も同じように育ちます。各レベルは単独で機能するので、好きなところで止めてかまいません。

レベル 0 · 0 分

もう動いています。

サイトが MetaMask、Xverse、Magic Eden、Unisat で動くなら、Casa Tookan でも動きます。インストールする SDK も、コード内の特別扱いも要りません。

EVMwindow.ethereum(EIP-1193)を EIP-6963 で通知します。wagmi、RainbowKit、Web3Modal で動作します。
Bitcoinsats-connect、Wallet Standard、window.unisat。SegWit、Taproot、Legacy アドレスに対応します。
Counterpartywindow.webXCP と window.web3xcp。ユーザーは署名する前に、PSBT が何をするかを確認できます。
Spells of Genesis への接続を求める Casa Tookan のシート。共有する Casa と Bitcoin アドレスが表示されている
サイトが接続を求めるCasa Tookan のシートにあなたのサイト名が表示され、ユーザーは Casa とアドレスを選べます。
Casa Tookan のブラウザで接続済みの Spells of Genesis。アドレスバーに Casa のピルが表示されている
サイトが接続されたバーの Casa のピルが、誰がサインインしているかを示します。緑の点は接続中の印です。
  1. アプリでサイトを開く

    Casa Tookan でブラウザを開き、URL を入力します。

  2. いつもどおり接続して署名する

    リクエストのたびに Casa Tookan の署名シートが開きます。あなたのサイトと署名する Casa が表示されるので、UI を作る必要はありません。

    connect.js
    const [address] = await window.ethereum.request({ method: 'eth_requestAccounts' });
    const signature = await window.ethereum.request({
      method: 'personal_sign',
      params: ['Welcome to Orb Quest!', address],
    });
  3. Casa の切り替えに追従する

    ユーザーはいつでもアドレスバーから Casa を切り替えられ、ページには通常のイベントが届きます。各 Casa には専用の localStorage もあるので、セッションが混ざりません。

    connect.js
    window.ethereum.on('accountsChanged', ([next]) => setPlayer(next));
他のウォレットの中から Casa Tookan を選ぶ · EIP-6963

デスクトップブラウザでは、MetaMask が window.ethereum をロックし、Casa Tookan のウェブ版を含む他のウォレットが使えなくなることがあります。代わりに com.everdreamsoft.casatookan として通知されるプロバイダーを選んでください。どこでも動きます。スマートフォンでは、window.ethereum はいずれにしても Casa Tookan のものです。

detect.js
window.addEventListener('eip6963:announceProvider', (e) => {
  if (e.detail.info.rdns === 'com.everdreamsoft.casatookan') useProvider(e.detail.provider);
});
window.dispatchEvent(new Event('eip6963:requestProvider'));

// Just want to know you're inside Casa Tookan?
const inCasaTookan = window.casaTookan?.isCasaTookan === true;

検出は、あいさつを表示したり、ウォレットの選択画面を省いたりするために使ってください。機能のオン/オフには使わないでください。API はプロバイダーそのものです。

手数料を宣言する · sats-connect, unisat

sats-connect は Xverse が公開している Bitcoin ウォレット向けのリクエスト形式です(window.BitcoinProvider、またはそれを見つける npm パッケージ sats-connect)。多くの Bitcoin ウォレットが採用しています。unisat(window.unisat)は UniSat の形式で、多くの Ordinals・Counterparty マーケットプレイスが使っています。Casa Tookan は同じ署名機能で両方に応答します。Xverse や UniSat 向けに書いたコードをそのまま使えます。

トランザクションがあなたへの支払いも含む場合(購入時のサービス手数料、ロイヤリティ、チップ)、PSBT と一緒に宣言してください。Casa Tookan は「宣言されていないアドレスに BTC が送られる」と警告する代わりに、Service fee · 0.0000075 BTC → bc1q… (declared by the site) と表示します。

buy.js · sats-connect
await window.BitcoinProvider.request('signPsbt', {
  psbt,                                    // base64
  signInputs: { [address]: [0, 1] },
  broadcast: true,
  fees: [{ kind: 'service', address: 'bc1q…', sats: 750 }],
});

// Unisat 方式:同じ fees をオプションに(signPsbts では各 PSBT のオプションに)。
await window.unisat.signPsbt(psbtHex, {
  toSignInputs,
  fees: [{ kind: 'service', address: 'bc1q…', sats: 750 }],
});
  • kind:'service'、'royalty'、'tip' のいずれか。表示文は Casa Tookan が書きます。テキスト欄はありません。
  • address と sats:トランザクションの出力の一つと完全に一致すること。手数料は最大 3 件。
  • 一致する出力がない(金額やアドレスが違う)場合、ユーザーには赤い警告が表示されます。アクション自体の支払い(dispense のディスペンサー、send の宛先)は手数料になりません。
  • リストにそれ以外のもの(別の kind、ラベル、余分なフィールド)があれば、宣言全体が無視され、ユーザーに通知されます。

fees を知らないウォレットは無視するので、宣言しても問題は起きません。すべての Counterparty アクションと通常の Bitcoin トランザクションで使えます。旧来の webXCP にはオプションがないため、sats-connect か unisat を使ってください。

デスクトップからテストする · スマートフォン不要

devapp.casatookan.com は、ブラウザで動く Casa Tookan で、テスト用ウォレットが付いています。サイトはフレームの中で動くため、スマートフォンにはないルールがブラウザによって適用されます。必要な変更は 4 つで、すべてあなたの側で行います。

  • <head> からウェブブリッジを読み込む。
  • devapp がページをフレームに入れられるようにする: frame-ancestors 'self' https://devapp.casatookan.com。
  • /.well-known/ へのすべてのリクエストに、404 も含めて Access-Control-Allow-Origin: * を返す(レベル 2 を参照)。
  • セッション Cookie に SameSite=None; Secure; Partitioned を付ける。

ブリッジのスニペット付きの手順: ウェブ版でアプリをテストする。

レベル 1 · リンク 1 つ

プレイヤーをまっすぐ迎え入れる。

Safari や Chrome でサイトを訪れた人は、そこにウォレットを持っていません。ボタン 1 つで、同じページが Casa Tookan の中で開きます。アプリがなければ、App Store・Google Play・「ブラウザで続ける」のページが開きます。

open-in-casa.html
<a id="open-casa" href="#">
  <img src="https://casatookan.com/assets/badges/open-in-casatookan-ja-dark.svg"
       alt="Casa Tookan で開く" width="212" height="56">
</a>
<script>
  // すでに Casa Tookan の中: 開くものはありません
  if (window.casaTookan) document.getElementById('open-casa').hidden = true;
  else document.getElementById('open-casa').href =
    'https://casatookan.com/open?url=' + encodeURIComponent(location.href) + '&ref=your-app';
</script>
i
https リンク 1 つで、どの場合も。Casa Tookan が入っていれば、iOS と Android は casatookan.com/open をそのままアプリに渡します(ウォレットがロック中なら、解除の直後にページが開きます)。アプリがなければ、リンクのページがストアとブラウザでのサイトを案内し、パソコンではスマートフォン用の QR コードを表示します。開くのは https の url だけです。ref(a–z、0–9、. _ -、64 文字まで)で、あなたが連れてきたプレイヤーを数えます。name はページの見出しになります。バッジ: /assets/badges/open-in-casatookan-{en|fr|ja}-{dark|light}.svg。
レベル 2 · 5 分

アプリになる。

サイトにはおそらく、すでにウェブマニフェストがあります。wallet メンバーを 1 つ追加すれば、Casa Tookan はあなたのサイトをアプリとして表示します。

Casa Tookan での Dev Playground のページ: バナー、アイコン、名前、サブタイトル、カテゴリ、チェーン、説明 1 2 3 4 5 6 7
  1. 1
    バナー · wallet.heroImageUrl、1200×630
  2. 2
    アイコン · icons、1024×1024、不透明
  3. 3
    名前 · name、32 文字
  4. 4
    サブタイトル · wallet.subtitle、30 文字
  5. 5
    カテゴリ · categories の最初の値
  6. 6
    チェーン · wallet.chains
  7. 7
    説明 · description、170 文字

Dev Playground のページです。バリデーターが、そのマニフェストから Casa Tookan のレイアウトで描画しました。あなたのマニフェストが、これらすべてを埋めます。

  • あなたの名前とアイコンアドレスバーと署名シートに
  • スプラッシュ画面読み込み中、あなたの色の上にあなたのアートを
  • ブラウザ › アプリ にカードバナー付きで、ワンタップで開ける
  • 明確な動作要件壊れたページの代わりにお知らせを表示
  1. アプリの情報を入力する

    必須なのは名前だけです。入力に合わせて JSON が更新されます。

    必要なチェーン

    まだマニフェストがないサイト向け。

    site.webmanifest
    W3C 標準。すでにお持ちかもしれませんwallet、追加する部分
  2. 公開する

    次のどちらかを使います。Casa Tookan は両方を確認し、wallet メンバーを持つ最初のものを使います。

    場所選ぶとき
    ホームページの <link rel="manifest"> でリンクされた既存のマニフェストすでにある場合。リンクはスクリプトで追加せず、配信される HTML に含めてください。
    /.well-known/wallet-app.json別にしておきたい場合。同じ JSON を単独で配信します。

    application/json として配信してください。画像はその隣に置きます: 1024×1024 の不透明なアイコン、1200×630 のバナー、200×200 のスプラッシュ。これは Farcaster と同じサイズなので、1 セットで両方に使えます。

  3. ブラウザが読めるようにする

    /.well-known/ 以下のすべて(404 を含む)と画像に、Access-Control-Allow-Origin: * を付けてください。スマートフォンのアプリには不要ですが、バリデーターとウェブ版の Casa Tookan には必要です。これがないと、存在しない farcaster.json がネットワーク障害に見えてしまいます。

    .htaccess
    # THE_REQUEST, not REQUEST_URI: still /.well-known/ after a rewrite to index.php
    <If "%{THE_REQUEST} =~ m#\s/\.well-known/#">
      Header always set Access-Control-Allow-Origin "*"
    </If>
  4. 確認する

    バリデーターは公開中のマニフェストを読み込み、すべての画像をテストし、Casa Tookan が描画するとおりにアプリを表示します。Casa Tookan はマニフェストを起動ごとに 1 回読み込むので、変更を確認するにはアプリを再起動してください。

farcaster.json や casatookan.json がすでにある場合

どちらも引き続き読み込まれ、フィールドごとにマージされます。順番は casatookan.json(以前の形式)、次に Wallet App Manifest、最後に farcaster.json です。Farcaster ミニアプリは、バナー、Bitcoin、Counterparty など、Casa Tookan で異なる部分だけを追加すれば十分です。

wallet は、どのウォレットでも読めるオープンな形式、Wallet App Manifest です。Casa Tookan だけが理解するフィールドには casatookan: 接頭辞が付きます。サーバーに障害が起きても、Casa Tookan はアプリについてすでに知っていた情報を保持します。完全なリファレンス: Casa Tookan アプリを作る。

レベル 3 · 1 行

準備ができたらスプラッシュを閉じる。

capabilities で wallet.ready を宣言します。するとスプラッシュは最初の画面が描画されるまで表示されたままになり、プレイヤーが読み込み途中のページを見ることはありません。

main.js
await loadAssets();
renderTitleScreen();
window.wallet?.ready();   // the splash fades, your game is there
wallet.ready ありスプラッシュは ready() を最大 10 秒待ちます。
なしページが落ち着いてから 2.5 秒後にスプラッシュが消えます。
Farcaster ミニアプリsdk.actions.ready() も同じように動作します。
i
アップグレードする場合 casatookan.ready と window.casaTookan.ready() は引き続き動作します。wallet.ready は中立的な名前で、アプリをホストするどのウォレットでも提供できます。
レベル 4 · 30 分

どこからでもログイン。

通常のブラウザやネイティブゲームから、チャレンジを付けてプレイヤーを Casa Tookan に送ります。プレイヤーは Bitcoin と Ethereum のアドレスを持って戻ってきます。どちらも署名で証明されています。パスワードも拡張機能も要りません。

  1. プレイヤーを Casa Tookan に送る

    サーバーがランダムで使い捨てのチャレンジを作り、ページがリンクを開きます。

    login.js
    const { challenge } = await fetch('/auth/challenge').then((r) => r.json());
    
    location.href = 'casatookan://x-callback-url/getaddress'
      + '?x-success=' + encodeURIComponent('https://orbquest.game/auth/casa')
      + '&msg=' + encodeURIComponent(challenge);
  2. プレイヤーが承認する

    プレイヤーは署名シートであなたのサイトを確認し、Casa を選んでサインインをタップします。その後 Casa Tookan は、address、msg、sig を付けてコールバックを開きます。

    https://orbquest.game/auth/casa?address=…&msg=…&sig=…
    address = chain:bitcoin;1Ca5a…T00k;;separator;;chain:ethereum;0x1614…1313
    sig     = chain:bitcoin;H8k2…=;;separator;;chain:ethereum;0x5f1c…1b
  3. サーバーで検証する

    チャレンジが自分のもので未使用であることを確認し、次に両方の署名を確認します。注意: EVM の署名は personal_sign ではありません。

    verify.js
    import bitcoinMessage from 'bitcoinjs-message';
    import { recoverAddress, keccak256, toUtf8Bytes } from 'ethers';
    
    // "chain:bitcoin;1Ca5…;;separator;;chain:ethereum;0x16…" → { bitcoin, ethereum }
    const entries = (s) => Object.fromEntries(s.split(';;separator;;').map((e) => {
      const i = e.indexOf(';');
      return [e.slice('chain:'.length, i), e.slice(i + 1)];
    }));
    
    export function verifyCasaLogin(query, expectedChallenge) {
      const p = new URLSearchParams(query);
      const msg = p.get('msg');
      if (msg !== expectedChallenge) throw new Error('challenge');   // then burn it
      const addr = entries(p.get('address'));
      const sig = entries(p.get('sig'));
    
      // Bitcoin: BIP-137, signed by the Legacy address.
      if (!bitcoinMessage.verify(msg, addr.bitcoin, sig.bitcoin)) throw new Error('bitcoin');
    
      // EVM: raw secp256k1 over keccak256(msg), not EIP-191.
      const signer = recoverAddress(keccak256(toUtf8Bytes(msg)), sig.ethereum);
      if (signer.toLowerCase() !== addr.ethereum.toLowerCase()) throw new Error('ethereum');
    
      return addr;
    }
ネイティブアプリや他のチェーンは?

ネイティブアプリ: コールバックにアプリのスキームを使います(x-success=orbquest)。Casa Tookan は orbquest://sendaddress?address=…&msg=…&sig=… を開きます。既存の web3XCP アプリが想定しているとおり、これらの値は URL エンコードされないので、クエリを &address=、&msg=、&sig= で分割してください。

他のチェーン: signForAddress?chain=bitcoin,base&… は、指定したチェーンで、その順に署名します。

コールバックは https:// かアプリのスキームでなければなりません。http:// は拒否されます。詳細はすべて dApp 接続とディープリンクにあります。

i
まず動くところを見てみましょう。スマートフォンでディープリンクテスターを開いてください。実際のリクエストを送り、応答を検証します。
レベル 5 · 半日 プレビュー

プレイヤーを知る。

Casa Estates ID は、デバイスやリカバリーフレーズをまたいで、プレイヤーごとに 1 つのアカウントです。セーブデータは変わらない番号に紐づけ、アドレスは必要なときだけ求めます。報酬を配るゲームのために作られています。

  1. マニフェストで宣言する

    wallet メンバーの中に:

    site.webmanifest · wallet
    "capabilities": { "required": ["casatookan:identity.ceid"] },
    "extensions": {
      "casatookan": {
        "identity": { "reason": "Your CEID keeps your progress across devices." }
      }
    }
  2. プレイヤーをサインインさせる

    signin.js
    if (window.casaTookan?.ceid?.available) {
      const { nonce } = await fetch('/auth/nonce').then((r) => r.json());
      const { token } = await window.casaTookan.ceid.signIn({ nonce });
      await fetch('/auth/casa', { method: 'POST', body: token });
    }
  3. サーバーでトークンを検証する

    server.js · jose
    import { createRemoteJWKSet, jwtVerify } from 'jose';
    
    const JWKS = createRemoteJWKSet(new URL('https://ctserver.everdreamsoft.com/.well-known/jwks.json'));
    
    const { payload } = await jwtVerify(token, JWKS, {
      issuer: 'https://ctserver.everdreamsoft.com',
      audience: 'https://orbquest.game',
      clockTolerance: 60,
    });
    // check payload.nonce, then key the player on payload.ceid
i
プレビュー。CEID は Casa Tookan の Dev ビルドで動作しており、ストア版のアプリではまだ使えません。jwks-dev.json でテストしてください。トークン、複数アカウント対策のための情報、プレイヤーに適用されるルールは Casa Estates ID でサインインにあります。

公開する前に

確認項目は 6 つです。チェックした状態はこのブラウザに保存されます。

AI に任せる。

これを Claude、Cursor など、コードを書くツールに貼り付けてください。レベル 0 から 4 までをカバーします。

casa-tookan-brief.md
Casa Tookan ウォレット(casatookan.com/docs/integrate.html)と私のサイトを連携してください。

前提:
- Casa Tookan のアプリ内ブラウザは標準のプロバイダーを注入する。独自の SDK は追加しないこと:
  window.ethereum(EIP-1193、EIP-6963 rdns "com.everdreamsoft.casatookan")、
  Bitcoin 用に sats-connect / WBIP-004 / Wallet Standard / window.unisat
  (unisat = Legacy アドレス。Counterparty の資産はここにある)、
  Counterparty 用に window.webXCP と window.web3xcp。
- トランザクションがサイトへの手数料も支払う場合は PSBT と一緒に宣言する:signPsbt の params /
  unisat の options に fees: [{ kind: "service"|"royalty"|"tip", address, sats }](出力と完全一致、最大 3 件、テキストなし)。
- rdns "com.everdreamsoft.casatookan" の EIP-6963 プロバイダーを優先する(デスクトップでは
  MetaMask が window.ethereum をロックすることがある)。検出は window.casaTookan?.isCasaTookan で行う。
  accountsChanged を監視すること: ユーザーはいつでも casa(アカウント)を切り替えられる。
  casa ごとに専用の localStorage がある。
- 「Casa Tookan で開く」リンク: https://casatookan.com/open?url={encodeURIComponent(url)}&ref={your-app}(アプリがあればアプリで、なければストアのページで開きます。window.casaTookan があるときは隠します)。casatookan://browse/{encodeURIComponent(url)} もスマートフォン上で引き続き使えます。
- アプリのマニフェスト = Wallet App Manifest(github.com/wallet-apps/manifest): W3C の
  ウェブマニフェスト(name、icons 1024x1024 の不透明な PNG、start_url、scope、background_color、
  description、categories)に "wallet" メンバーを加えたもの:
  { "version": "1", "subtitle"(30 文字), "heroImageUrl"(1200x630),
    "splashImageUrl"(200x200), "chains": { "required": [CAIP-2] },
    "capabilities": { "required": [...] }, "extensions": { "casatookan": {...} } }
  ホームページの <link rel="manifest"> または /.well-known/wallet-app.json で、
  application/json として配信する。/.well-known/ 以下のすべて(404 を含む)と画像に
  Access-Control-Allow-Origin: * を付ける。
  Bitcoin = bip122:000000000019d6689c085ae165831e93, Ethereum = eip155:1, Base = eip155:8453.
  Capabilities: provider.ethereum, provider.bitcoin, provider.counterparty, wallet.ready;
  Casa Tookan のみ: casatookan:identity.ceid。Counterparty = Bitcoin + provider.counterparty。
- wallet.ready を宣言した場合は、最初の画面が描画されたら window.wallet?.ready() を呼ぶ。
- 通常のブラウザやネイティブアプリからのログイン:
  casatookan://x-callback-url/getaddress?x-success={encodeURIComponent(https callback)}&msg={encodeURIComponent(challenge)}
  応答: callback?address=…&msg=…&sig=…(https のコールバックでは URL エンコードされる)。
  address/sig = "chain:bitcoin;VALUE;;separator;;chain:ethereum;VALUE"。
  Bitcoin の署名: Legacy アドレスによる BIP-137 base64(bitcoinjs-message の verify)。
  EVM の署名: keccak256(utf8(msg)) に対する生の secp256k1、0x r s v(v=27+recid)。EIP-191 ではない:
  ethers recoverAddress(keccak256(toUtf8Bytes(msg)), sig)。
  チャレンジはランダムかつ使い捨てで、サーバーで検証する。
- devapp.casatookan.com でのデスクトップテスト(ctserver.everdreamsoft.com/docs/web.html を参照):
  <head> にウェブブリッジ、frame-ancestors 'self' https://devapp.casatookan.com、
  /.well-known/ に CORS、セッション Cookie に SameSite=None; Secure; Partitioned。

ツールボックス