Wallet Provider Spec

[Previous << Cadence VS Code Extension](https://qiita.com/flowcadence/items/1b5bde9635935c1e4d8d)
[Next >> Authorization Function](https://qiita.com/flowcadence/items/9ba3fc7d18f53dedc98a)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#reference-2020832ebee1810a325a

<h1>Status</h1>

* Last Updated: June 20th 2022
* Stable: Yes
* Risk of Breaking Change: Medium
* Compatibility: >= @onflow/fcl@1.0.0-alpha.0

<h1>Definitions</h1>

この文書は、今これを読んでいるあなたがFCLウォレット開発者であるという前提で書かれています。この文書における*あなた*への言及はすべて、この前提を念頭に置いて行われています。
<h1>Overview</h1>

Flow Client Library (FCL) は、他のブロックチェーンでサポートされているウォレットとは異なる方法で、Flow上のブロックチェーンウォレットのアイデアにアプローチしています。例えば、FCLでは、ウォレットは必ずしもブラウザ拡張機能やユーザーデバイス上の(ネイティブ)アプリケーションに限定されるものではありません。FCLは、ウォレット開発者に、様々なタイプのアプリケーションを構築するための柔軟性と自由を提供します。ウォレットアプリケーションにはさまざまな形態があるため、これらの多様なアプリケーションが互いに通信し、連携できる仕組みが必要でした。

FCLは、ブロックチェーンアプリケーションに関わるさまざまな当事者間の通信と設定を促進するプロトコルとして、さまざまな役割を果たします。*アプリケーション*はFCLを使用してユーザーを*認証*し、トランザクションの*承認*を要求したり、ブロックチェーンの変更や問い合わせを行うことができます。FCLを使用するアプリケーションは、*ユーザー*に対して、任意の数のウォレットプロバイダーおよびウォレットサービスに接続し、選択する方法を提供します。選択された*ウォレット*は、FCLのアプリケーションインスタンスに、ウォレット自身とウォレットサービスに関する設定情報を提供し、それによって*ユーザー*と*アプリケーション*がそれらとやりとりできるようになります。

以下の段落では、さまざまなFCLサービスの実装を提供することで、FCLと統合する方法を紹介します。

以下のサービスがカバーされることとなります:

* Authentication (Authn) Service
* Authorization (Authz) Service
* User Signature Service
* Pre-Authz Service
<h1>Service Methods</h1>

ウォレットが何ができるかに関する情報をFCLに対して設定したウォレットプロバイダーの手段がFCLサービスです。FCLは、サポートされているFCLサービスを実行するために、`Service Methods`と呼ばれるものを使用します。Service Methodsは、FCLがあなたのウォレットと通信する手段です。ウォレットは、サポートされているサービスがあなたとの通信に使用するサービスメソッドのいずれかを決定します。

サービスによっては、FCLの設定を行うだけのものもあります。その例としては、認証サービス(Authentication Service)とOpenIDサービスが挙げられます。この2つのサービスでは、あなたはFCLに「これが現在のユーザーに関する一連の情報です」と伝えるだけでいいです。（この2つのサービスはどちらもそれらに、`method: "DATA"`フィールドを持っていること分かるでしょう。現在、データサービスとして利用できるのは、この2つのケースのみです。)

その他のサービスは、もう少し複雑になる場合があります。例えば、FCLと当該サービスとの間で、交互にやり取りが必要になる場合があります。最終的には、セキュアなバック・チャネル（サーバーへのhttpsリクエスト）を介して前後のやり取りを行いたいと考えていますが、**状況によってはそれが実行可能なオプションではない場合もあります。そのため、フロント・チャネルのオプションも用意しています**。可能な場合は、サービスに対してバックチャネルのサポートを提供することを目指すべきであり、どうしても必要な場合のみフロントチャネルに切り替えるべきです。

Back-channel communications use `method: "HTTP/POST"`, while front-channel communications use `method: "IFRAME/RPC"`, `method: "POP/RPC"`, `method: "TAB/RPC` and `method: "EXT/RPC"`.
| Service Method | Front | Back |
|:-:|:-:|:-:|
| HTTP/POST | ⛔ | ✅ |
| IFRAME/RPC | ✅ | ⛔ |
| POP/RPC | ✅ | ⛔ |
| TAB/RPC | ✅ | ⛔ |
| EXT/RPC | ✅ | ⛔ |

重要なのは、コミュニケーションの方法に関わらず、当事者間でやり取りされるデータは同じであるということです。
<h1>Protocol schema definitions</h1>

このセクションでは、プロトコルで使用されるオブジェクトのスキーマを定義します。JavaScriptオブジェクトではありますが、JSONでサポートされている機能のみを使用します。（つまり、オブジェクトをJSONに変換しても、変換前と変換後で情報が失われることはありません。）

スキーマ定義言語にはTypeScriptを選択し、FCLの実装を行う際に使用する実際の型定義にスキーマをできるだけ近づけるようにしました。

**NOTE. 現在、FCLで利用できる公式の型定義は提供されていません。TypeScriptを使用する場合は、独自の型定義を作成する必要があります（このドキュメントで提示されているスキーマ定義を基に作成することもできます）。**
<h1>Common definitions</h1>

このセクションでは、個々のオブジェクト定義が継承される、一般的な定義をいくつか紹介します。

まず、利用可能なFCLオブジェクトの種類を定義します。
```ruby
type ObjectType =
  | 'PollingResponse'
  | 'Service'
  | 'Identity'
  | 'ServiceProvider'
  | 'AuthnResponse'
  | 'Signable'
  | 'CompositeSignature'
  | 'OpenID'
```
すべてのFCLオブジェクトに共通するフィールドは、以下のように定義できます。
```ruby
interface ObjectBase<Version = '1.0.0'> {
  f_vsn: Version
  f_type: ObjectType
}
```
`f_vsn`フィールドは、この仕様では通常は`1.0.0`ですが、いくつかの例外が、`ObjectBase`に異なる`Version`タイプのパラメータを渡すことで、定義されます。

すべてのFCLオブジェクトは、`f_type`フィールドを持ち、実行時にその型を識別できるようにしています。
<h1>FCL objects</h1>

このセクションでは、`ObjectType`ごとにFCLオブジェクトを定義します。

また、それらの集合をFCLオブジェクトを意味するものとして定義します:
```ruby
type FclObject =
  | PollingResponse
  | Service
  | Identity
  | ServiceProvider
  | AuthnResponse
  | Signable
  | CompositeSignature
  | OpenID
```

<h3>PollingResponse</h3>

```ruby
interface PollingResponse extends ObjectBase {
  f_type: 'PollingResponse'
  status: 'APPROVED' | 'DECLINED' | 'PENDING' | 'REDIRECT'
  reason: string | null
  data?: FclObject
  updates?: FclObject
  local?: FclObject
}
```
FCLに返される各レスポンスは、`PollingResponse`で"ラップ"する必要があります。`status`フィールドがレスポンスの意味を決定します。
* `APPROVED`ステータスは、リクエストが承認されたことを意味します。`data`フィールドを持っています。
* `DECLINED`ステータスは、リクエストが拒否されたことを意味します。`reason`フィールドには、拒否の理由が人間が読める形式で含まれている必要があります。
* `PENDING`のステータスは、リクエストが処理中であることを意味します。さらに`PENDING`の応答が続く場合もありますが、最終的にはpendingでないステータスが返されるはずです。`updates`および`local`フィールドが存在する場合もあります。
* `REDIRECT`ステータスは予約されており、ウォレットサービスでは使用しないでください。

まとめると、ゼロかそれ以上の`PENDING`の応答の後には、pendingでない応答が続くはずです。`APPROVED`のPollingResponseを即座に返すことは、`PENDING`の状態をスキップするので、あなたのサービスはまったく問題なく受け入れられます。

[PollingResponse](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/polling-response.js) も参照してください。

以下に、有効な`PollingResponse`オブジェクトの例を示します。
```ruby
/* APPROVED */
{
  f_type: "PollingResponse",
  f_vsn: "1.0.0",
  status: "APPROVED",
  data: ___, /* what the service needs to send to FCL */
}

/* Declined */
{
  f_type: "PollingResponse",
  f_vsn: "1.0.0",
  status: "DECLINED",
  reason: "Declined by user."
}

/* Pending - Simple */
{
  f_type: "PollingResponse",
  f_vsn: "1.0.0",
  status: "PENDING",
  updates: {
    f_type: "Service",
    f_vsn: "1.0.0",
    type: "back-channel-rpc",
    endpoint: "https://____", /* where post request will be sent */
    method: "HTTP/POST",
    data: {},   /* will be included in the request's body */
    params: {}, /* will be included in the request's url */
  }
}

/* Pending - First Time with Local */
{
  f_type: "PollingResponse",
  f_vsn: "1.0.0",
  status: "PENDING",
  updates: {
    f_type: "Service",
    f_vsn: "1.0.0",
    type: "back-channel-rpc",
    endpoint: "https://____", /* where post request will be sent */
    method: "HTTP/POST",
    data: {},   /* included in body of request */
    params: {}, /* included as query params on endpoint */
  },
  local: {
    f_type: "Service",
    f_vsn: "1.0.0",
    endpoint: "https://____", /* the iframe that will be rendered, */
    method: "VIEW/IFRAME",
    data: {}, /* sent to frame when ready */
    params: {}, /* included as query params on endpoint */
  }
}
```
`"APPROVED"`または`"DECLINED"`レスポンスを送信する時は、`PollingResponse`は`WalletUtils`を使用して構築することもできます。
```ruby
import {WalletUtils} from "@onflow/fcl"

/* Approving a PollingResponse
   Example using an AuthnResponse as the PollingResponse data */
WalletUtils.approve({
  f_type: "AuthnResponse",
  f_vsn: "1.0.0"
  ...
})

/* Rejecting a PollingResponse
   Supplies a reason for declining */
const reason = "User declined to authenticate."
WalletUtils.decline(reason)
```
<h3>Service</h3>

```ruby
type ServiceType =
  | 'authn'
  | 'authz'
  | 'user-signature'
  | 'pre-authz'
  | 'open-id'
  | 'back-channel-rpc'
  | 'authn-refresh'

type ServiceMethod =
  | 'HTTP/POST'
  | 'IFRAME/RPC'
  | 'POP/RPC'
  | 'TAB/RPC'
  | 'EXT/RPC'
  | 'DATA'

interface Service extends ObjectBase {
  f_type: 'Service'
  type: ServiceType
  method: ServiceMethod
  uid: string
  endpoint: string
  id: string
  identity: Identity
  provider?: ServiceProvider
  data?: FclObject
}
```
フィールドの意味は以下の通りです。
* `type`: このサービスのタイプ。
* `method`: このサービスが使用するサービスメソッド。`DATA`は、このサービスがこの`Service`オブジェクト内の情報を提供することのみを目的としており、アクティブ通信サービスは提供しないことを意味します。
* `uid`: サービス用の一意の識別子。これを作り出す一般的なスキーマは、`'wallet-name#${type}'`を使用することです。ここで`${type}`はこのサービスの型を表します。
* `endpoint`：サービスと通信する先を定義します。
  - `method`が`EXT/RPC`の場合、これは任意のユニークな文字列にすることができ、拡張機能は自身のサービスを識別するためにそれを使用する必要があります。`endpoint`を生成するための一般的なスキーマは、`'ext:${address}'`を使用することです。ここで、`${address}`はウォレットのアドレスを指します。（詳細は、`ServiceProvider`をご確認ください)
* `id`: ウォレットが内部で持つユーザー識別子。他の識別子が使用されていない場合、ユーザーのFlowアカウントアドレスがここに使用できます。
* `identity`: ユーザーの識別情報に関する情報。
* `provider`: ウォレットに関する情報。
* `data`: `open-id`型のサービスで使用される追加情報。

See also:
* [authn](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/authn.js)
* [authz](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/authz.js)
* [user-signature](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/user-signature.js)
* [pre-authz](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/pre-authz.js)
* [open-id](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/open-id.js)
* [back-channel-rpc](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/back-channel-rpc.js)

<h3>Identity</h3>

このオブジェクトは、ユーザーの識別情報を定義するために使用されます。
```ruby
interface Identity extends ObjectBase {
  f_type: 'Identity'
  address: string
  keyId?: number
}
```
各フィールドの意味は以下の通りです。
* `address`：ユーザーのFlowアカウントのアドレス。
* `keyId`：署名に使用される、このアカウントに関連付けられたキーのID。
<h3>ServiceProvider</h3>

このオブジェクトは、ウォレットに関する情報を伝えるために使用されます。
```ruby
interface ServiceProvider extends ObjectBase {
  f_type: 'ServiceProvider'
  address: string
  name?: string
  description?: string
  icon?: string
  website?: string
  supportUrl?: string
  supportEmail?: string
}
```
各フィールドの意味は以下の通りです。
* `address`：ウォレットが所有するFlowアカウントのアドレス。これが何に使用されるかは未定です。
* `name`：ウォレットの名称。
* `description`：ウォレットの簡単な説明。
* `icon`：ウォレットのアイコン画像のURL。
* `website`：ウォレットのウェブサイト。
* `supportUrl`：ユーザーがウォレットのサポートを受ける際に使用できるURL。
* `supportEmail`: ユーザーがウォレットのサポートを受ける際に使用できるメールアドレス。
<h3>AuthnResponse</h3>

このオブジェクトは、ウォレットが提供するサービスをFCLに通知するために使用されます。
```ruby
interface AuthnResponse extends ObjectBase {
  f_type: 'AuthnResponse'
  addr: string
  services: Service[]
}
```
各フィールドの意味は以下の通りです。
* `addr`：ユーザーのFlowアカウントのアドレス。
* `services`：ウォレットが提供するサービスの一覧。

<h3>Signable</h3>

```ruby
interface Signable extends ObjectBase<'1.0.1'> {
  f_type: 'Signable'
  addr: string
  keyId: number
  voucher: {
    cadence: string
    refBlock: string
    computeLimit: number
    arguments: {
      type: string
      value: unknown
    }[]
    proposalKey: {
      address: string
      keyId: number
      sequenceNum: number
    }
    payer: string
    authorizers: string[]
  }
}
```
`WalletUtils.encodeMessageFromSignable` 関数を使用して、署名が必要なメッセージを計算することができます。

<h3>CompositeSignature</h3>

```ruby
interface CompositeSignature extends ObjectBase {
  f_type: 'CompositeSignature'
  addr: string
  keyId: number
  signature: string
}
```
[CompositeSignature](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/composite-signature.js)も参照してください。

<h3>OpenID</h3>

(現時点でTODOです。翻訳元を参照ください)
<h1>Miscellaneous objects</h1>
<h3>Message</h3>

```ruby
type MessageType =
  | 'FCL:VIEW:READY'
  | 'FCL:VIEW:READY:RESPONSE'
  | 'FCL:VIEW:RESPONSE'
  | 'FCL:VIEW:CLOSE'

type Message = {
  type: MessageType
}
```
プロトコル呼び出しのステータスを示すメッセージ。

この型は、*intersection type*の一部として使用されることがあります。例えば、`Message & PollingResponse`という型は、`PollingResponse`が`Message`の`type`フィールドで拡張されたことを意味します。

<h3>ExtensionServiceInitiationMessage</h3>

```ruby
type ExtensionServiceInitiationMessage = {
  service: Service
}
```
このオブジェクトは、`EXT/RPC`サービスメソッドが使用される時にサービスを呼び出すために使用されます。

**See also**
* [local-view](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/local-view.js)
* [frame](https://github.com/onflow/fcl-js/blob/master/packages/fcl-core/src/normalizers/service/frame.js)

<h1>Service Methods</h1>
<h2>IFRAME/RPC (Front Channel)</h2>

`IFRAME/RPC` が最も簡単に説明できるので、まずこれについて説明します。
* iframe がレンダリングされます（サービス内の`endpoint`から取得されます）。
* レンダリングされた iframe はリスナー(listener)を追加し、そして`"FCL:VIEW:READY"`メッセージを送信します。これは`WalletUtils.ready(callback)`によって簡略化できます。
* FCL が処理対象のデータを送信します。
  * `body`が、あなたが気にすべき部分です。`params`および`data`は、あなたがサービスオブジェクトの中で提供できる追加情報です。
* ウォレットは、`"APPROVED"`または`"DECLINED"`のPOSTメッセージを返信します。（それは`f_type: "PollingResponse"`であり、後ほど説明いたします）。これは、`WalletUtils.approve`と`WalletUtils.decline`を使用して簡略化できます
  * 承認された場合、ポーリング応答のdataフィールドはFCLが期待する内容である必要があります。
  * 拒否された場合、ポーリング応答のreasonフィールドには拒否された理由が記載される必要があります。
```ruby
export const WalletUtils.approve = data => {
  sendMsgToFCL("FCL:VIEW:RESPONSE", {
    f_type: "PollingResponse",
    f_vsn: "1.0.0",
    status: "APPROVED",
    reason: null,
    data: data,
  })
}

export const WalletUtils.decline = reason => {
  sendMsgToFCL("FCL:VIEW:RESPONSE", {
    f_type: "PollingResponse",
    f_vsn: "1.0.0",
    status: "DECLINED",
    reason: reason,
    data: null,
  })
}
```
```ruby
graph LR
    Start1(Start)
    --Bot 启动--> check1[检查群内的非 Authing 用户]
    --> addUser[添加 Authing 用户并消息提醒绑定手机号]
    --> End1(End)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/0ae3c484-b976-7d7d-3ce6-f063c0980bd5.png)


<h2>POP/RPC | TAB/RPC (Front Channel)</h2>

`POP/RPC`および`TAB/RPC`は、`IFRAME/RPC`とほぼ完全に同様の方法で動作します。ただし、`method`をiframeでレンダリングする代わりに、ポップアップまたは新しいタブでレンダリングします。レンダリングされたビューとFCL間の通信プロトコルは同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/d454c5a6-d97a-35fb-1df7-d6fd8f6aa44e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/56fcdd4e-d992-867c-a60e-5f180bb1fecb.png)


<h2>HTTP/POST (Back Channel)</h2>

`HTTP/POST` は、サービスで指定された`endpoint`に最初にPOSTリクエストを送信します。これはすぐに`f_type: "PollingResponse"`を返すべきです。

`IFRAME/RPC`や`POP/RPC`や`TAB/RPC`と同様に、最終的には`APPROVED`または`DECLINED`のポーリングレスポンスを取得することが目的であり、技術的にはこのエンドポイントはすぐにそれらのいずれかを返すことができます。

`IFRAME/RPC`や`POP/RPC`や`TAB/RPC`と同様に、最終的には`APPROVED`または`DECLINED`のポーリングレスポンスを取得することが目的であり、技術的にはこのエンドポイントはすぐにそれらのいずれかを返すことができます。

しかし、実際にはそうではなく、`PENDING`の状態になる可能性が高いでしょう（`PENDING`は`IFRAME/RPC`、`POP/RPC`、`TAB/RPC`では使用できません）。ポーリングレスポンスが`PENDING`の場合、`updates`フィールドが必要になります。このフィールドには、FCLが更新された`PollingResponse`を要求するために使用できるサービス、`BackChannelRpc`が含まれます。FCLは、その`BackChannelRpc`を使用して新しい`PollingResponse`を要求します。その`PollingResponse`自体は、`APPROVED`、`DECLINED`、または`PENDING`のいずれかになります。それが`APPROVED`の場合、FCLはそれを返します。それ以外の場合、それが`DECLINED`の場合、FCLはエラーを返します。しかし、それが`PENDING`の場合、FCLは新しい`PollingResponse`のupdatesフィールドで指定された`BackChannelRpc`を使用します。FCLは、それが`APPROVED`または`DECLINED`になるまで、このサイクルを繰り返します。

追加のオプション機能として、`HTTP/POST` により、最初に返される`PollingResponse`を有効にすることができます。このオプション機能は、FCLがiframe、ポップアップ、または新しいタブを表示する機能であり、サービス`type："VIEW/IFRAME"`や`type："VIEW/POP"`や`type："VIEW/TAB"`と、`endpoint`を指定することでトリガーされることができ、`PollingResponse`の`local`フィールドの中でウォレットがレンダリングしたいことです。これは、ウォレットプロバイダーが、そのサービスでUIの表示が必要な場合にウェブページに切り替えるための優れた方法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/7bc1089a-a3dc-a42b-e4ed-59d05473f31c.png)


<h2>EXT/RPC (Front Channel)</h2>

（省略。翻訳元をご確認ください）
```ruby
  chrome.tabs.sendMessage(tabs[0].id, {
    f_type: "PollingResponse",
    f_vsn: "1.0.0",
    status: "APPROVED",
    reason: null,
    data: {
      f_type: "AuthnResponse",
      f_vsn: "1.0.0",
      addr: address,
      services: services,
    },
  });
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/1ef3db26-1c28-7408-86c9-d2698b95c80b.png)

<h2>data and params</h2>

`data`および`params`は、FCLがサービスに返すサービス設定の中でウォレットが提供できる情報です。
* `params`は、`endpoint`にクエリパラメータとして追加されます。
* `data`は、`HTTP/POST`リクエストのボディに含まれます。または、`IFRAME/RPC`、`POP/RPC`、`TAB/RPC`、`EXT/RPC`の`FCL:VIEW:READY:RESPONSE`にも含まれます。
***
<h1>Authentication Service</h1>

以下の例では、認証サービスの構築プロセスを順を追って説明します。

FCLでは、`discovery.wallet` 設定変数にウォレットプロバイダーの認証URLまたは拡張エンドポイントを渡すことで、ウォレットが設定されます。

FCLが使用する認証エンドポイントで、ホストされるウェブページまたはAPIを、作成・公開する必要があります。
```ruby
/* IN APPLICATION
   configuring fcl to point at a wallet looks like this */
import {config} from "@onflow/fcl"

config({
  /* FCL Discovery endpoint, wallet provider's authentication URL or extension endpoint */
  "discovery.wallet": "url-or-endpoint-fcl-will-use-for-authentication",
  "discovery.wallet.method": "IFRAME/RPC" /* Optional. Available methods are "IFRAME/RPC", "POP/RPC", "TAB/RPC", "EXT/RPC" or "HTTP/POST", defaults to "IFRAME/RPC". */
})
```
指定されたメソッドが `IFRAME/RPC`、`POP/RPC`、または `TAB/RPC`の場合、`discovery.wallet`として指定されたURLはウェブページとしてレンダリングされます。設定されたメソッドが `EXT/RPC`の場合、`discovery.wallet`は拡張部分の `authn` `endpoint`に設定する必要があります。 それ以外の場合は、指定されたメソッドが `HTTP/POST`の場合、認証プロセスはHTTPリクエストを介して行われます。（認証は、これらのサービスメソッドのいずれかを使用して行うことができますが、ここでは`IFRAME/RPC`サービスメソッドを使用します。）

認証ウェブページがレンダリングされ、拡張機能のポップアップが有効になり、またはAPIが準備完了すると、FCLに準備完了を通知する必要があります。あなたはこれをFCLにメッセージを送信することでこれを行い、ユーザーに代わって認証を要求するアプリケーションについての、あなたが使用できる追加情報を含めたメッセージをFCLは返します。

以下の例では、`IFRAME/RPC` メソッドを使用しています。あなたの認証ウェブページは、おそらく以下のコードに類似したものになるでしょう:
```ruby
/* IN WALLET AUTHENTICATION FRAME */
import {WalletUtils} from "@onflow/fcl"

function callback(data) {
  if (typeof data != "object") return
  if (data.type !== "FCL:VIEW:READY:RESPONSE") return

  ... /* Do authentication things */ ...

  /* Send back AuthnResponse */
  WalletUtils.sendMsgToFCL("FCL:VIEW:RESPONSE", {
    f_type: "PollingResponse",
    f_vsn: "1.0.0",
    status: "APPROVED",
    data: {
      f_type: "AuthnResponse",
      f_vsn: "1.0.0"
      ...
    }
  })

  /* Alternatively be sent using WalletUtils.approve (or WalletUtils.decline)
     which will wrap AuthnResponse in a PollingResponse */
  WalletUtils.approve({
    f_type: "AuthnResponse",
    f_vsn: "1.0.0"
    ...
  })
}
/* add event listener first */
WalletUtils.onMsgFromFCL("FCL:VIEW:READY:RESPONSE", callback)

/* tell fcl the wallet is ready */
WalletUtils.sendMsgToFCL("FCL:VIEW:READY")

/* alternatively adds "FCL:VIEW:READY:RESPONSE" listener and sends "FCL:VIEW:READY" */
WalletUtils.ready(callback)
```
認証中、アプリケーションは、アプリケーションに送り返してほしい情報をリクエストする機会があります。これらのリクエストは、FCLからウォレットに送信される`FCL:VIEW:READY:RESPONSE`メッセージに含まれています。

このようなリクエストの例としては、OpenIDサービスがあります。例えば現在のユーザーのメールアドレスを送信するよう、アプリケーションはあなた(ウォレット)にリクエストすることができます。この情報を要求するアプリケーションは、必ずしもあなた(ウォレット)がその情報を送信する必要があるわけではありません。送信するかしないかは完全に任意です。しかし、一部のアプリケーションは、リクエストされた情報を送信してもらうことを前提としている場合があり、送信を拒否するとアプリケーションが動作しなくなる可能性があります。

設定では、アプリケーションの名前やアプリケーションのアイコンのURLなど、さまざまな情報をあなたに通知できます。あなたはこれらの情報を使用して、必要に応じてウォレットのユーザーエクスペリエンスをカスタマイズできます。

ウォレットとアプリケーションは視覚的に区別できますが、シームレスにコネクテッドされたエクスペリエンスを提供することが、私たちのここでの目標です。

あなた(ウォレット)の認証プロセスが`IFRAME/RPC`、`POP/RPC`、`TAB/RPC`メソッドによるウェブページ使用して行われるのか、`EXT/RPC`メソッドを使用した有効な拡張機能経由で行われるか、または`HTTP/POST`メソッドを使用したAPIに対するバックチャネル経由で行われるかには関わらず、ハンドシェイクは同じになります。ただし、伝送メカニズムは変わります。`IFRAME/RPC`、`POP/RPC`、`TAB/RPC`、または`EXT/RPC`メソッドの場合、通信手段は`window.postMessage()`になり、`HTTP/POST`メソッドの場合は、通信手段はHTTP POSTメッセージです。

これまでと同様に、アプリケーションから受信したものは決して信用してはなりません。常に十分な注意を払い、潜在的に悪意のあるアプリケーションに対するユーザーの第一の防御線となるよう警戒してください。
<h3>Authenticate your User</h3>

ユーザーが、ユーザーが主張する通りの人物であるとあなたが確信できることが重要です。

FCLにユーザーの詳細情報を転送することに問題がないことを確認できるだけの十分な証拠を提出してもらいます。Bloctoを例にとると、認証コードはユーザーがログイン時に入力したメールアドレスに送信されます。このコードは認証に使用でき、Bloctoがユーザーの身元を確実に確認するために必要なすべての情報となります。

<h3>Once you know who your User is</h3>

ユーザーの身元に確信が持てたら、認証プロセスを完了できます。


FCLが現在のユーザー用のFCL Servicesが、FCLに設定がされた応答を受け戻すと、認証プロセスは完了します。このレスポンスはFCLにとって非常に重要です。その中核となる部分では、ユーザーが誰であるかをFCLに通知し、さらに、付属のサービスを介して、ユーザーがどのように認証されたか、トランザクション署名をどのように要求するか、個人メッセージに署名を取得する方法、および要求された場合のユーザーの電子メールやその他の詳細をFCLに通知します。将来的には、さらに多くの内容が含まれるようになるかもしれません！

あなたはFCLをプラグインシステムのようなものと考えることができます。ただし、これらのプラグインはFCL以外の場所にも存在するため、FCLはそれらと通信する方法に関する情報を設定されている必要があります。

FCLに送り返すすものは、あなたが提供するプラグインと通信するために必要なすべての情報です。ウォレットはFCLに対するプラグインのようなものであり、これらの詳細情報は、FCLにあなたをプラグインとして使用する方法を伝えます。

認証レスポンスの例は以下の通りです:
```ruby
/* IN WALLET AUTHENTICATION FRAME */
import {WalletUtils} from "@onflow/fcl"

WalletUtils.approve({
  f_type: "AuthnResponse",
  f_vsn: "1.0.0",
  addr: "0xUSER",                      /* The user's flow address */

  services: [                          /* All the stuff that configures FCL */

      /* Authentication Service - REQUIRED */
      {
          f_type: "Service",                                         /* It's a service! */
          f_vsn: "1.0.0",                                            /* Follows the v1.0.0 spec for the service */
          type: "authn",                                             /* the type of service it is */
          method: "DATA",                                            /* It's data! */
          uid: "amazing-wallet#authn",                               /* A unique identifier for the service */
          endpoint: "your-url-that-fcl-will-use-for-authentication", /* should be the same as was passed into the config */
          id: "0xUSER",                                              /* the wallet's internal id for the user, use flow address if you don't have one */
          /* The User's Info */
          identity: {
              f_type: "Identity",  /* It's an Identity! */
              f_vsn: "1.0.0",      /* Follows the v1.0.0 spec for an identity */
              address: "0xUSER",   /* The user's address */
              keyId: 0,            /* OPTIONAL - The User's KeyId they will use */
          },
          // The Wallet's Info
          provider: {
              f_type: "ServiceProvider",      /* It is a Service Provider */
              f_vsn: "1.0.0",                 /* Follows the v1.0.0 spec for service providers */
              address: "0xWallet",            /* A flow address owned by the wallet */
              name: "Amazing Wallet",         /* OPTIONAL - The name of your wallet. ie: "Dapper Wallet" or "Blocto Wallet" */
              description: "The best wallet", /* OPTIONAL - A short description for your wallet */
              icon: "https://___",            /* OPTIONAL - Image url for your wallet icon */
              website: "https://___",         /* OPTIONAL - Your wallet website */
              supportUrl: "https://___",      /* OPTIONAL - An url the user can use to get support from you */
              supportEmail: "help@aw.com",    /* OPTIONAL - An email the user can use to get support from you */
          },
      },

      /* Authorization Service */
      {
          f_type: "Service",
          f_vsn: "1.0.0",
          type: "authz",
          uid: "amazing-wallet#authz",
          ...
          /* We will cover this at length in the authorization section of this guide */
      },

      /* User Signature Service */
      {
          f_type: "Service",
          f_vsn: "1.0.0",
          type: "user-signature",
          uid: "amazing-wallet#user-signature",
          ...
          /* We will cover this at length in the user signature section of this guide */
      },

      /* OpenID Service */
      {
          f_type: "Service",
          f_vsn: "1.0.0",
          type: "open-id",
          uid: "amazing-wallet#open-id",
          method: "DATA",
          data: { /* only include data that was request, ideally only if the user approves the sharing of data, everything is optional */
              f_type: "OpenID",
              f_vsn: "1.0.0",
              profile: {
                  name: "Jeff",
                  family_name: "D", /* icky underscored names because of OpenID Connect spec */
                  given_name: "Jeffrey",
                  middle_name: "FakeMiddleName",
                  nickname: "JeffJeff",
                  preferred_username: "Jeff",
                  profile: "https://www.jeff.jeff/",
                  picture: "https://avatars.onflow.org/avatar/jeff",
                  website: "https://www.jeff.jeff/",
                  gender: "male",
                  birthday: "1900-01-01", /* can use 0000 for year if year is not known */
                  zoneinfo: "America/Vancouver",
                  locale: "en",
                  updated_at: "1625588304427"
              },
              email: {
                  email: "jeff@jeff.jeff",
                  email_verified: false,
              }
          },
      }
  ]
})
```

<h3>Stopping an Authentication Process</h3>

どのフレームからでも、`FCL:VIEW:CLOSE` というポストメッセージをFCLに送信することができます。これにより、FCLの現在のルーチンが停止し、フレームが閉じられます。

```ruby
import {WalletUtils} from "@onflow/fcl"

WalletUtils.sendMsgToFCL("FCL:VIEW:CLOSE")
```


*Last updated on **Dec 6, 2024** by **Alex Ni***

翻訳元

https://developers.flow.com/tools/wallet-provider-spec

***
<b>[Previous << Cadence VS Code Extension](https://qiita.com/flowcadence/items/1b5bde9635935c1e4d8d)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Wallet Provider Spec)

<b>[Next >> Authorization Function](https://qiita.com/flowcadence/items/9ba3fc7d18f53dedc98a)</b>