# アカウント能力 (Capability) の委任

### Capabilityを委任する

通常のCapabilityは`signer.capabilities`に対して公開しますが、Capabilityの委任時は`signer.inbox`に対して公開します。

**通常のCapabilityの公開**

```swift
/* Create a Thief resource */
signer.storage
    .save(<- MMORPG.createThiefResource(payment: <- payment),
            to: /storage/MMORPGThiefResource)

/* リソースのaccess(all)のフィールドをCapabilityで公開する */
let cap = signer.capabilities
    .storage
    .issue<&MMORPG.Thief>(/storage/MMORPGThiefResource)

signer.capabilities
    .publish(cap, at: /public/MMORPGThiefResource)
                    }
```

**委任時のCapabilityの公開**

```swift
/* Issue a resource capability for ThiefAbility1 entitlement */
let capability = signer.capabilities
    .storage
    .issue<auth(MMORPG.ThiefAbility1) &MMORPG.Thief>
                                (/storage/MMORPGThiefResource)

/* Publish the capability for the specified recipient */
signer.inbox
    .publish(
        capability,
        name: "PoisonMakingSkill",
        recipient: recipient
    )
```

recipientは委任する相手のアドレスです。

* * *

### 委任された能力(Capability)を使用する

```swift
/* Claim the capability published by buddy */
let capability = signer.inbox
    .claim<auth(MMORPG.ThiefAbility1) &MMORPG.Thief>(
        "PoisonMakingSkill",
        provider: providerAddress
    )
capability!.borrow()!.PoisonMaking(battleId: battleId)
```

providerAddressは委任したアカウントのアドレス

* * *

### 委任された Capability の一覧表示と UI 設計

Flow の Inbox 仕様上、委任データは受取側へのストレージスパムを防ぐため、受取人（Recipient）のアカウントではなく**発行者（Provider）のストレージ**に保持されます。

そのため、実務の Web3 ゲーム開発では「発行者が公開中の委任一覧スクリプト」**や**「オンチェーンイベントをオフチェーン DB でインデックスしたデータ」を活用して、受取可能な能力を UI にリアルタイム表示します。

#### **発行中（委任中）の Capability を一覧取得するスクリプト**

発行者（Provider）が「誰にどの能力を委任したまま未受取になっているか」を確認、あるいはフロントエンドで利用可能な能力を特定するためのスクリプトです。

```cadence
import MMORPG from 0xMMORPGAddress

// UI表示用のデータ構造体
access(all) struct InboxItemData {
    access(all) let inboxName: String
    access(all) let ability: String

    init(inboxName: String, ability: String) {
        self.inboxName = inboxName
        self.ability = ability
    }
}

/* クエリー処理 */
access(all) fun main(providerAddress: Address): [InboxItemData] {
    let account = getAccount(providerAddress)
    let inboxItems: [InboxItemData] = []

    // 発行者のアカウントで現在公開・委任中の Inbox 名一覧を取得
    let inboxStorageNames = account.inbox.getNames()

    for name in inboxStorageNames {
        // 具象型 &MMORPG.Thief として中身を安全に参照 (peek)
        if let cap = account.inbox.peek<&MMORPG.Thief>(name: name) {
            if let thief = cap.borrow() {
                inboxItems.append(InboxItemData(
                    inboxName: name,
                    ability: thief.getAbilityDetail()
                ))
            }
        }
    }

    return inboxItems
}
```

### オフチェーン連携と UI 表示の流れ

1.  **イベント検知と DB 保存:** 発行者が `signer.inbox.publish(...)` を実行すると、Flow のシステムイベント（`flow.AccountInboxPublished`）が発火します。ゲームのバックエンド（インデクサー）でこれを検知し、`providerAddress`、`recipientAddress`、`inboxName` をデータベースへ保存します。
    
2.  **利用可能スキルの UI レンダリング:** 受取人（Recipient）がログインした際、DB から「自分宛てに届いている委任一覧」を取得して UI 上に「仲間から借りられるスキル」として表示します。
    
3.  **安全な Claim と実行:** UI から対象のスキルを選択すると、保存されている `providerAddress` と `name` を渡して `signer.inbox.claim` トランザクションを実行し、即座にゲーム内で能力を発動できます。
    

### ゲーム・UI 設計におけるメリット

*   **ブラインド Claim の防止:** プレイヤーは事前に DB やスクリプト経由で「どの仲間から、どんなスキルが委任されているか」を確認してから Claim できます。
    
*   **リアルタイム通知・バフ表示:** 仲間からスキルが委任された瞬間に「パーティメンバーから支援スキルが届きました！」という通知バッジを表示可能です。
    
*   **ガス代ゼロでの事前確認:** スクリプト（Read-only）やオフチェーンキャッシュを利用するため、不要なガス代をかけることなく UI を更新できます。
