Actions と Blinks

[Solana Actions] (#actions) は、Solanaブロックチェーン上のトランザクションをプレ ビュー、署名、送信するための仕様準拠のAPIです。QRコード、ボタンやウィジェット、 インターネット上のウェブサイトなど、さまざまなコンテキストで利用できます。 Actionsにより、開発者はSolanaエコシステム全体の機能を自分の環境に簡単に統合で き、別のアプリやウェブページに移動することなくブロックチェーントランザクションを 実行できます。

Blockchain links は、あらゆるSolana Actionsを共有可能でメタデータ豊富 なリンクに変換します。 BlinksはActionsに対応したクライアント (ブラウザ拡張ウォ レット、ボット) は、ユーザーに追加の機能を表示できます。 ウェブサイト上で は、Blinksはウォレット内でトランザクションプレビューを即座にトリガーし、分散型ア プリに移動することなく実行されます。Discordでは、ボットがBlinksをインタラクティ ブなボタンセットに展開するかもしれません。 これにより、URLを表示できる任意のウェ ブサーフェスでオンチェーンのやり取りが可能になります。

はじめに #

カスタムSolana Actionsの作成をすぐに始めるには:

npm install @solana/actions
  • アプリケーション にSolana Actions SDK をインス トールします。
  • Action に関するメタデータを返す GET request 用のAPIエンドポイ ントを構築します。
  • ユーザーに署名可能なトランザクションを返す POST request を受 け付けるAPIエンドポイントを作成します。
Info

このビデオチュートリアルをチェックして、@solana/actions SDKを使用してSolana Actionを構築する方法を学びましょう: how to build a Solana Action

こちら のsource code for an Action で、ネイティブSOLの転送を行うアクション と、this repo 内の他の例示アクションを確認することもできます。

カスタムSolana Actionsを本番環境にデプロイする場合:

  • ドメインのルートに有効なactions.json file があることを確認しま す。
  • actions.json ファイルを含むすべてのActionエンドポイント で、required Cross-Origin headers を返すようにアプリケー ションが対応していることを確認します。

アクションやblinksの構築に関するインスピレーションを求めている場合 は、Awesome Blinks リポジ トリをチェックして、コミュニティの作品 やideas for new ones から見つけてください。

Actions #

Solana Actionsの仕様は、アプリケーションから直接ユーザーに署名可能なトランザク ション (将来的には署名可能なメッセージ) を提供する一連の標準APIを使用します。 こ れらは公開URLにホストされ、URLを介して任意のクライアントが相互作用できます。

Info

Actionsは、メタデータとユーザーがブロックチェーンウォレットで署名 (トランザク ションまたは認証メッセージ) するための情報を返すAPIエンドポイントとして考える ことができます。

Actions APIは、ActionのURLエンドポイントへの簡単なGET およびPOST リクエスト を行い、Actionsインターフェースに準拠したレスポンスを処理します。

  1. GET request は、このURLで利用可能なアクションに関する人間が読 み取れる情報をクライアントに提供し、関連するActionsのリストを返します。
  2. POST request は、クライアントがユーザーのウォレットに署名 と、ブロックチェーンやオフチェーンサービスで実行する署名可能なトランザクショ ンまたはメッセージを返します。

Actionの実行とライフサイクル #

実際には、Actionsとのやり取りは通常のREST APIとのやり取りに非常に似ています:

  • クライアントが最初のGET リクエストをAction URLに送信して、利用可能なアクショ ンに関するメタデータを取得します。
  • エンドポイントは、エンドポイントに関するメタデータ (アプリケーションのタイトル やアイコンなど) と、このエンドポイントで利用可能なアクションの一覧を含むレスポ ンスを返します。
  • クライアントアプリケーション (モバイルウォレット、チャットボット、ウェブサイト など) は、ユーザーがアクションを実行するためのUIを表示します。
  • ユーザーがアクションを選択 (ボタンをクリックするなど) した場合、クライアントは エンドポイントにPOST リクエストを送信して、ユーザーが署名するトランザクショ ンを取得します。
  • ウォレットはユーザーがトランザクションに署名するのを支援し、最終的にはトランザ クションをブロックチェーンに送信して確認します。

Solana Actions Execution and LifecycleSolana Actions Execution and Lifecycle

Action URLからトランザクションを受け取る際、クライアントはこれらのトランザクショ ンをブロックチェーンに送信し、その状態のライフサイクルを管理する必要があります。

Actionsは、実行前にいくつかの無効化レベルもサポートしています。 GET およ びPOST リクエストは、アクションが実行可能かどうかを示すメタデータを返す場合が あります。(例:disabled フィールド)

例えば、投票ウィンドウが閉じたDAOガバナンス提案に対する投票を促進するActionエン ドポイントがあった場合、最初のGET request は「この提案は投票の対 象ではありません」というエラーメッセージと「賛成票」「反対票」ボタンを「無効」に します。

Blinks (ブロックチェーンリンク) は、Action APIを調査し、Actionsとのやり取りおよ び実行のためのユーザーインターフェイスを構築するクライアントアプリケーションで す。

Blinksに対応するクライアントアプリケーションは、Action互換のURLを検出し、解析し て、標準化されたユーザーインターフェイスでユーザーがそれらと相互作用できるように します。

Info

完全にAction APIを調査して完全なインターフェースを構築するクライアントアプリ ケーションはblinkと呼ばれます。 したがって、Actions APIを利用するすべてのクラ イアントがblinksというわけではありません。

Blink URLは、ユーザー がlifecycle of executing an Action を完了でき るクライアントアプリケーションを記述しています。これには、ウォレットでの署名も含 まれます。

https://example.domain/?action=<action_url>

クライアントアプリケーションがblinkになるには:

  • Blink URLには、URLエンコードされたAction URL を値とするクエリパ ラメータaction が含まれている必要があります。 この値は、他のプロトコルパラ メータと競合しないように URL-encoded されなければなりません。

  • クライアントアプリケーションは、actionクエリパラメータを URL-decode し、提供されたAction APIリンクを調査する必要があります (Action URL scheme参照)。

  • クライアントは、ユーザーが lifecycle of executing an Action を完了でき るリッチなユーザーインターフェースをレンダリングする必要があります。これには ウォレットでの署名も含まれます。

Info

すべてのblinkクライアントアプリケーション (例:ウェブサイトやdApp) がすべての アクションをサポートするわけではありません。 アプリケーション開発者は、自分の blinkインターフェースでサポートするアクションを選択できます。

次の例は、URLエンコードされたaction値 solana-action:https://actions.alice.com/donate を持つ有効なblink URLを示していま す:

https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2Fdonate

Blinks経由でActionsを検出する #

Blinksは、少なくとも3つの方法でActionsにリンクできます:

  1. 明確なAction URLの共有:solana-action:https://actions.alice.com/donate

    この場合、サポートされているクライアントのみがblinkをレンダリングできます。 フォールバックリンクのプレビューや、非対応クライアント以外からアクセスできる サイトはありません。

  2. Actions APIにリンクされているウェブサイトへのリンクを actions.json file でウェブサイトのドメインルート上で共有し ます。

    例えば、https://alice.com/actions.jsonは、ユーザーがアリスに寄付できるウェ ブサイトのURLであるhttps://alice.com/donateと、アリスに寄付するためのアク ションがホストされているAPIのURLであるhttps://actions.alice.com/donateを マッピングします。

  3. Action URLを解析する方法を理解している “interstitial” サイトURLにAction URLを 埋め込む

    https://example.domain/?action=<action_url>

Blinksをサポートするクライアントは、上記のいずれかの形式を受け取り、クライアント 内で直接アクションを実行するためのインターフェースを正しくレンダリングする必要が あります。

Blinksをサポートしないクライアントには、基礎となるウェブサイトが存在する必要があ ります (ブラウザがユニバーサルフォールバックになります) 。

ユーザーがクライアント内のアクションボタンやテキスト入力フィールド以外の場所を タップした場合、基礎となるサイトに移動する必要があります。

Blinkのテストと検証 #

Solana Actionsとblinksはパーミッションレスのプロトコル/仕様であるにもかかわら ず、クライアントアプリケーションやウォレットは依然としてユーザーがトランザクショ ンに署名するのを最終的に促す必要があります。

これらのクライアントアプリケーションやウォレットは、クライアントが自動的に展開 し、ソーシャルメディアプラットフォーム上でユーザーに即座に表示するActionエンドポ イントについて異なる要件を持つ場合があります。

例えば、一部のクライアントは "allow list" アプローチを採用しており、Dialectの Actions Registry (詳細は下記) など、ユーザーのためのActionを展開する前に検証が必 要になることがあります。

すべてのblinksは、Dialectの dial.to blinks Interstitialサイト でレンダリングされ、署名が可能となりますが、そのレジストリステータスがblink内で 表示されます。

DialectのActions Registry #

公共の利益としてSolanaエコシステムのために、Dialect は Solana Foundationおよび他のコミュニティメンバーの協力を得て、事前に検証済みの既 知のソースからのブロックチェーンリンクの公開レジストリを維持しています。 ローン チ時点で、Dialectのレジストリに登録されたActionsのみが、Twitterフィードに投稿さ れた際に展開されます。

クライアントアプリケーションとウォレットは、この公開レジストリを使用するか、また は別のソリューションを使用してユーザーの安全とセキュリティを確保するかを自由に選 択できます。 Dialectのレジストリを通じて検証されない場合、ブロックチェーンリンク はblinkクライアントによって触れられず、通常のURLとしてレンダリングされます。

開発者はここでDialectによる検証を申請することができま す:dial.to/register

仕様 #

Solana Actions仕様は、リクエスト/レスポンスのやり取りフローの一部である重要なセ クションで構成されています:

これらのリクエストはすべて、リッチなユーザーインターフェース向けの特定のメタデー タを収集し、Actions APIへのユーザー入力を促進するためにAction Client (例:ウォ レットアプリ、ブラウザ拡張機能、dApp、ウェブサイトなど) によって行われます。

それぞれのレスポンスは、アプリケーション(ウェブサイト、サーバーバックエンドなど) によって作成され、Action client に返されます。 最終的には、署名可能なトランザ クションまたはウォレットのメッセージを提供して、ユーザーが署名を承認し、ブロック チェーンに送信するように促します。

URLスキーム #

Solana Action URL は solana-action プロトコルを使用して署名可能なSolanaトラン ザクションまたはメッセージに対するインタラクティブな要求を記述します。

リクエストはインタラクティブです。URL内のパラメータはクライアントによって、署名 可能なトランザクションを構成するための一連の標準化されたHTTPリクエストや、ユー ザーがウォレットで署名するためのメッセージを作成するために使用されます。

solana-action:<link>
  • パス名には link フィールドが必要です。 値は条件付きで URLエンコード された完全なHTTPS URLである必要があります。

  • URLにクエリパラメータが含まれている場合、URLエンコードされていなければなりませ ん。 URLエンコードすることで、プロトコル仕様によって追加される可能性のある他の アクションプロトコルパラメータと競合しないようにします。

  • URLにクエリパラメータが含まれていない場合、URLエンコードしないでください。これ により、短いURLとより少ない密度のQRコードが生成されます。

いずれの場合も、クライアントは値 をURL-decodeし なければならない。 これは、値が URL エンコードされていない場合には効果はありませ ん。 デコードされた値が絶対的なHTTPSURLでない場合、ウォレットはmalformedとし て拒否する必要があります。

OPTIONSレスポンス #

Cross-Origin Resource Sharing (CORS) をActionsクライ アント (blinksを含む) で許可するために、すべてのActionエンドポイントは、同一オリ ジンドメインからのすべての後続のリクエストに対してCORSチェックを通過させることが できる有効なヘッダーを含むOPTIONSメソッドに対するHTTPリクエストに応答すべきで す。

Actionsクライアントは、後続のGETリクエストがすべてのCORSチェックを通過するかどう かを確認するために、Action URLエンドポイントに対し て"preflight" リクエストを実行することがあります。 これらのCORSプレフライトチェックはOPTIONS HTTPメソッドを使用して行われ、Actionsクライアント (blinksのような) が自身のオリ ジンドメインからすべての後続のリクエストを適切に行うことができるように、必要なす べてのHTTPヘッダーで応答するべきです。

必要最低限のHTTPヘッダーには以下のものが含まれます:

  • Access-Control-Allow-Origin は値として * を持ち、
    • これによりすべてのActionクライアントが安全にCORSチェックを通過し、必要なリク エストを行うことが保証されます。
  • Access-Control-Allow-Methods は値として GET,POST,PUT,OPTIONS を持ち、
    • Actionsに必要なすべてのHTTPリクエスト方法がサポートされることを保証します。
  • Access-Control-Allow-Headers は最低限 Content-Type, Authorization, Content-Encoding, Accept-Encoding の値を持つべ きです。

簡単のため、開発者はGET response と同じ応答とヘッダー をOPTIONS リクエストに対しても返すことを検討すべきです。

Cross-Origin headers for actions.json

actions.json ファイルのレスポンスも、GET およびOPTIONS リクエストに対して 有効なクロスオリジンヘッダーを返さなければならず、特 にAccess-Control-Allow-Origin ヘッダーの値は * である必要があります。

詳細については以下のactions.json を参照してください。

GETリクエスト #

Actionクライアント (例えばウォレット、ブラウザ拡張機能など) は、ActionのURLエン ドポイントにHTTP GET JSONを要求する必要があります。

  • リクエストはウォレットまたはユーザーを識別しないでください。
  • クライアントは [Accept-Encoding ヘッダーを使用してリクエストを行う必要があり ます。(https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Encoding)
  • クライアントは、リクエストが行われている間、URL のドメインを表示する必要があり ます。

GETレスポンス #

ActionのURLエンドポイント (例:アプリケーションまたはサーバーのバックエンド) は、HTTP OK JSON レスポンス (有効なペイロードをボディに含む) または適切なHTTP エラーで応答するべきです。

  • クライアントはHTTP のclient errorsserver errorsredirect responses を処理しなければならない。

  • エンドポイントはHTTP圧縮のために Content-Encoding header で応答するべきです。

  • エンドポイント はapplication/jsonContent-Type header ヘッダーで応答するべきです。

  • クライアント は、HTTP caching のレスポンスヘッダーに指示された場合を除き、レスポンスをキャッシュすべきではあ りません。

  • クライアントは title を表示し、icon 画像をユーザーにレンダリングするべきで す。

GETレスポンスボディ #

HTTP OK JSON レスポンスを持つ GET レスポンスは、インターフェイスの仕様に従う bodyペイロードを含める必要があります。

ActionGetResponse
export interface ActionGetResponse {
  /** image url that represents the source of the action request */
  icon: string;
  /** describes the source of the action request */
  title: string;
  /** brief summary of the action to be performed */
  description: string;
  /** button text rendered to the user */
  label: string;
  /** UI state for the button being rendered to the user */
  disabled?: boolean;
  links?: {
    /** list of related Actions a user could perform */
    actions: LinkedAction[];
  };
  /** non-fatal error message to be displayed to the user */
  error?: ActionError;
}
  • icon - アイコン画像のHTTPまたはHTTPSのURLを指定する必要があります。 ファイル はSVG、PNG、またはWebPイメージである必要があり、クライアント/ウォレット はmalformedとして拒否しなければなりません。

  • title - アクションリクエストのソースを表すUTF-8文字列でなければなりません。 例えば、ブランド名、ストア名、アプリケーション名、またはリクエストを行っている 人名などです。

  • description - アクションに関する情報を提供するUTF-8文字列である必要がありま す。 説明はユーザーに表示されます。

  • label - ユーザーがクリックするためには、ボタンにレンダリングされるUTF-8文字 列である必要があります。 すべてのラベルは5ワードフレーズを超えないようにし、 ユーザーに取って欲しいアクションを確立するために動詞で始めるべきです。 例: 「NFTをミントする」「賛成票を投じる」「1 SOLをステークする」など。

  • disabled - 値はレンダリングされたボタンの無効状態を表すブール値でなければな りません(label文字列を表示します) 。 値が指定されていない場合、 disabledfalse (デフォルトで有効) になります。 例えば、ガバナンス投票が終了した場 合、disabled=true を設定し、label は"Vote Closed" と表示されることがありま す。

  • error - 致命的でないエラーのためのオプションのエラー表示。 errorがある場合 は、クライアントはそれをユーザーに表示する必要があります。 設定されている場 合、アクションの解釈やユーザーへの表示を妨げるべきではありません。 例えば、エ ラーは、ビジネスの制約、認証、状態、または外部リソースのエラーの理由を表示する ために、disabled と一緒に使用されることがあります。

ActionError
export interface ActionError {
  /** ユーザーに表示される非致命的なエラーメッセージ */
  message: string;
}
  • links.actions - エンドポイントに関連するアクションのオプション配列。 ユー ザーは、リストされたアクションごとにUIを表示し、1つのみを実行する必要がありま す。 例えば、ガバナンス投票アクションエンドポイントは、ユーザーに"Vote Yes"、"Vote No"、"Abstain from Vote" の3つのオプションを提供することがありま す。

    • もし links.actions が提供されていない場合、クライアントはルートの label 文字列を使用して単一のボタンを表示し、初期の GET リクエストと同じアクション URLエンドポイントに対して POST リクエストを行うべきです。

    • links.actions が提供されている場合、クライアントは links.actions フィー ルドに記載されている項目に基づいてボタンと入力フィールドのみを表示すべきで す。 クライアントはルートの label の内容に対するボタンを表示すべきではあり ません。

LinkedAction
export interface LinkedAction {
  /** URL endpoint for an action */
  href: string;
  /** button text rendered to the user */
  label: string;
  /** Parameter to accept user input within an action */
  parameters?: [ActionParameter];
}
 
/** Parameter to accept user input within an action */
export interface ActionParameter {
  /** parameter name in url */
  name: string;
  /** placeholder text for the user input field */
  label?: string;
  /** declare if this field is required (defaults to `false`) */
  required?: boolean;
}

GETレスポンスの例 #

以下の例は、ユーザーに "Claim Access Token" というラベルのボタンを表示することが 期待される単一の"root" アクションを提供します:

{
  "title": "HackerHouse Events",
  "icon": "<url-to-image>",
  "description": "Claim your Hackerhouse access token.",
  "label": "Claim Access Token" // button text
}

以下の例は、DAO提案に対して3つのボタンのいずれかをクリックして投票するための3つ の関連アクションリンクを提供します:

{
  "title": "Realms DAO Platform",
  "icon": "<url-to-image>",
  "description": "Vote on DAO governance proposals #1234.",
  "label": "Vote",
  "links": {
    "actions": [
      {
        "label": "Vote Yes", // button text
        "href": "/api/proposal/1234/vote?choice=yes"
      },
      {
        "label": "Vote No", // button text
        "href": "/api/proposal/1234/vote?choice=no"
      },
      {
        "label": "Abstain from Vote", // button text
        "href": "/api/proposal/1234/vote?choice=abstain"
      }
    ]
  }
}

パラメータを使用した GET レスポンスの例 #

以下の例は、ユーザーからのテキスト入力を受け取り (parameters を介して) 、最終 的なPOST リクエストエンドポイント(LinkedAction内の href フィールドを介し て) にその入力を含める方法を示しています :

以下の例のレスポンスは、ユーザーがクリックできる3つの関連アクションリンクを提供 します:1 SOLをステークする"Stake 1 SOL" 、5 SOLをステークする"Stake 5 SOL" 、お よび特定の"amount" 値を入力するテキスト入力フィールド「ステークする量」を提供し ます。これは、Action APIに送信されます:

{
  "title": "Stake-o-matic",
  "icon": "<url-to-image>",
  "description": "Stake SOL to help secure the Solana network.",
  "label": "Stake SOL", // not displayed since `links.actions` are provided
  "links": {
    "actions": [
      {
        "label": "Stake 1 SOL", // button text
        "href": "/api/stake?amount=1"
        // no `parameters` therefore not a text input field
      },
      {
        "label": "Stake 5 SOL", // button text
        "href": "/api/stake?amount=5"
        // no `parameters` therefore not a text input field
      },
      {
        "label": "Stake", // button text
        "href": "/api/stake?amount={amount}",
        "parameters": [
          {
            "name": "amount", // field name
            "label": "SOL amount" // text input placeholder
          }
        ]
      }
    ]
  }
}

以下の例のレスポンスは、ユーザーが入力する amount を受け取り、それをPOSTリクエ ストに送信します (クエリパラメータまたはサブパスとして使用できます) :

{
  "icon": "<url-to-image>",
  "label": "Donate SOL",
  "title": "Donate to GoodCause Charity",
  "description": "Help support this charity by donating SOL.",
  "links": {
    "actions": [
      {
        "label": "Donate", // button text
        "href": "/api/donate/{amount}", // or /api/donate?amount={amount}
        "parameters": [
          // {amount} input field
          {
            "name": "amount", // input field name
            "label": "SOL amount" // text input placeholder
          }
        ]
      }
    ]
  }
}

POSTリクエスト #

クライアントは、次のボディペイロードを持つアクションURLへのHTTP POST JSON リク エストを行う必要があります:

{
  "account": "<account>"
}
  • account - 値は、トランザクションに署名する可能性のあるアカウントのbase58エン コードされた公開鍵でなければなりません。

クライアントは Accept-Encoding header を使用してリクエストを行うべきで、アプリケーションはHTTP圧縮のために Content-Encoding header で応答する可能性があります。

クライアントは、リクエストが行われている間、URL のドメインを表示する必要がありま す。 GET リクエストが行われた場合、クライアントは title を表示し、GET リクエ ストからの icon イメージをレンダリングする必要があります。

POSTレスポンス #

ActionのPOST エンドポイントは、HTTP OK JSONレスポンス (有効なペイロードをボ ディに含む) または適切なHTTPエラーで応答するべきです。

POSTレスポンスボディ #

HTTP OK JSONレスポンスを持つPOSTレスポンスには、以下のボディペイロードを含め る必要があります。

ActionPostResponse
export interface ActionPostResponse {
  /** base64 encoded serialized transaction */
  transaction: string;
  /** describes the nature of the transaction */
  message?: string;
}
  • transaction - 値はベース64エンコードされた シリアル化されたトランザクション でなければなりません。クライアントはトランザクションをbase64デコード し、deserialize it 必要があります。

  • message - レスポンスに含まれるトランザクションの性質を記述するUTF-8文字列で ある必要があります。 クライアントはこの値をユーザーに表示する必要があります。 例えば、購入するアイテムの名前、購入に適用された割引、または感謝のメッセージな どです。

  • クライアントとアプリケーションは、将来の仕様更新によって追加される可能性のある リクエストボディおよびレスポンスボディの追加フィールドを許可するべきです。

Info

アプリケーションは、部分的または完全に署名されたトランザクションで応答すること ができます。 ウォレットは untrusted としてトランザクションを検証する必要が あります。

POSTレスポンス - トランザクション #

トランザクション のsignatures が空であるか、トランザクションが部分的に署名されていない場合:

  • クライアントはトランザクション内 のfeePayer を無視し、リクエスト内のaccountfeePayer として設定する必要があります。
  • また、クライアントはトランザクション内 のrecentBlockhash を無視し、 recentBlockhashlatest blockhash に設定する必要があります。
  • クライアントは署名する前にトランザクションをシリアライズしてデシリアライズする 必要があります。これによ り、this issue の回避策 として、アカウントキーの順序が一貫して保たれます。

トランザクションが部分的に署名されている場合:

  • クライアントは、既存の署名を無効にするた め、feePayerrecentBlockhash を変更してはいけません。
  • クライアントは既存の署名を検証し、無効な署名がある場合は、トランザクションを malformed として拒否する必要があります。

クライアントはリクエスト内の account でトランザクションにのみ署名を行い、リク エストの account の署名が期待される場合のみこれを行うべきです。

リクエスト内の account の署名以外の署名が期待される場合、クライアントはトラン ザクションを malicious として拒否する必要があります。

actions.json #

actions.json file の目的は、クライアントにSolana Actionsをサ ポートするウェブサイトURLを指示し、 GET requests をActions API サーバーに送信するためのマッピングを提供することです。

Cross-Origin headers are required

actions.json ファイルのレスポンスは、GET および OPTIONS リクエストに対して 有効なクロスオリジンヘッダーも返さなければなりません。具体的に は、Access-Control-Allow-Origin ヘッダーの値は * である必要があります。

詳細については上記の OPTIONS response を参照してください。

actions.json ファイルは保存され、ドメインのルートに普遍的にアクセスできるよう にする必要があります。

例えば、ウェブアプリケーションが my-site.com にデプロイされている場合、 actions.json ファイルは https://my-site.com/actions.json からアクセスできま す。このファイルは、Access-Control-Allow-Origin ヘッダーの値を * にすること で、任意のブラウザからクロスオリジンでアクセス可能であるべきです。

ルール #

rules フィールドを使用すると、ウェブサイトの相対パスルートパスを他のパスのセッ トにマップすることができます。

Type: ActionRuleObjectArray

ActionRuleObject
interface ActionRuleObject {
  /** relative (preferred) or absolute path to perform the rule mapping from */
  pathPattern: string;
  /** relative (preferred) or absolute path that supports Action requests */
  apiPath: string;
}
  • pathPattern - 受信する各パス名と一致するパターン。

  • apiPath - 完全なパス名または外部 URL として定義されている ロケーション先。

ルール - pathPattern #

各入力パス名に一致するパターン。 絶対または相対パスとして定義でき、次の形式をサ ポートします:

  • Exact Match: 正確なURLパスに一致します。

    • 例: /exact-path
    • 例: https://website.com/exact-path
  • Wildcard Match: ワイルドカードを使用して、URLパス内の任意の文字列に一致さ せます。 これは単一(*) または複数のセグメント(**) を一致させます。 (Path Matching 参照)

    • 例: /trade/* は、/trade/123 および/trade/abcと一致し、 /trade/ の後の 最初のセグメントのみをキャプチャします。
    • 例: /category/*/item/**/category/123/item/456/category/abc/item/def と一致します。
    • 例: /api/actions/trade/*/confirm/api/actions/trade/123/confirm と一 致します。

ルール - apiPath #

アクション要求の宛先パス。 完全なパス名または外部 URL として定義できます。

  • 例: /exact-path
  • 例: https://api.example.com/v1/donate/*
  • 例: /api/category/*/item/*
  • 例: /api/swap/**

ルール - クエリパラメータ #

元のURLからのクエリパラメータは常に保存され、マップされたURLに追加されます。

ルール - パスマッチング #

次の表は、パスマッチングパターンの構文を示しています。

Operator一致
*パスセグメント単位で一致し、パス区切り文字/を含みません。
**任意の文字列と一致し、複数のパスセグメント間の任意のパス区切り文字/を含みます。 他の演算子が含まれる場合、**演算子は最後の演算子でなければなりません。
?サポートされていないパターン。

ルール例 #

次の例は、サイトのルートからの /buy へのリクエストを、サイトのルートからの相対 パス /api/buy に正確にマップする完全一致ルールを示しています:

actions.json
{
  "rules": [
    {
      "pathPattern": "/buy",
      "apiPath": "/api/buy"
    }
  ]
}

次の例では、ワイルドカードパスマッチングを使用して、サイトのルートにある /actions/ の下の任意のパス (サブディレクトリは除く) から、サイトのルートに相対 的な /api/actions/ の下の対応するパスへリクエストをマッピングします。

actions.json
{
  "rules": [
    {
      "pathPattern": "/actions/*",
      "apiPath": "/api/actions/*"
    }
  ]
}

次の例では、ワイルドカードパスマッチングを使用して、サイトのルートにある /donate/ の下の任意のパス (サブディレクトリは除く) から、外部サイト上の絶対パ ス https://api.dialect.com/api/v1/donate/ へのリクエストをマッピングします

actions.json
{
  "rules": [
    {
      "pathPattern": "/donate/*",
      "apiPath": "https://api.dialect.com/api/v1/donate/*"
    }
  ]
}

次の例では、idempotentルールにワイルドカードのパスマッチを使い、 サイトのルート から /api/actions/ 以下のすべてのパス (サブディレクトリを 含む) へのリクエスト をそれ自身にマップしています:

Info

solana-action: URIを先頭に付けたり、追加のレスポンステストを実行することな く、与えられたパスがAction APIリクエストをサポートしているかどうかをblinkクラ イアントがより簡単に判断できるようにする。

actions.json
{
  "rules": [
    {
      "pathPattern": "/api/actions/**",
      "apiPath": "/api/actions/**"
    }
  ]
}

アクションアイデンティティ #

アクションエンドポイントには、ユーザーが署名するPOST response 内のトランザクションに Action Identity を含めることができます。 これにより、イ ンデクサおよび分析プラットフォームが特定のアクションプロバイダー (サービス) に チェーン上の活動を簡単に帰属させ、検証することができます。

Action Identity は、メモ命令を使用してトランザクションに含ま れる特別な形式のメッセージに署名するために使用されるキーペアです。 この Identifier Message は、特定のアクション アイデンティティ、によって検証可能にな り、トランザクションを特定のアクション プロバイダーに属させることができます。

キーペアは、取引自体に署名する必要はありません。 これにより、ウォレットとアプリ ケーションは、他の署名がユーザーに返されたトランザクションにない場合、トランザク ションの配信性を向上させることができます( POST レスポンストランザクション を参照してくださ い)。

アクションプロバイダーのユースケースが、ユーザーの前にトランザクションをプリサイ ンするバックエンドサービスを必要とする場合、このキーペアをアクションアイデンティ ティとして使用する必要があります。 これにより、トランザクションに含まれるアカウ ントが32バイト削減され、トランザクション全体のサイズが小さくなります。

Action Identifier Message #

Action Identifier Messageは、単一の SPL Memo 命令 を使用して、トランザクションに含まれるコロン別のUTF-8文字列です。

protocol:identity:reference:signature
  • protocol - 使用されるプロトコルの値 ( URL Scheme に基づき solana-action に設定)
  • identity - 値は、 アクションアイデンティティキーペアのベース58エンコードされ た公開鍵アドレスでなければなりません
  • reference - 値はベース58エンコードされた32バイトの配列でなければなりません。 これは公開鍵かもしれませんし、曲線上であるかどうかにかかわらず、Solana上のアカ ウントに対応しているかもしれませんし、対応していないかもしれません。
  • signature - reference 値の署名を作成するためにアクションアイデンティティ キーペアが署名したbase58エンコードされた署名です。

referenceの値は、1つのトランザクションで1回だけ使用する必要があります。 アク ションプロバイダーにトランザクションを関連付けるためには、reference 値の最初の 使用のみが有効と見なされます。

トランザクションには複数のMemo命令が含まれていることがあります。 getSignaturesForAddress を実行すると、結果のmemoフィールドは各 memo 命令のメッセージを1つの文字列とし て返し、それぞれがセミコロンで区切られます。

Identifier MessageのMemo命令には他のデータを含めてはいけません。

identity およびreference は、識別メッセージ Memo命令ではない命令の読み取り専 用、署名者でない keys としてトランザクションに含めるべきです。

Identifier Message Memo 命令は、指定されたゼロアカウントでなければなりません。 アカウントが提供された場合、Memo プログラムでは有効な署名者である必要がありま す。 アクションを識別するために、これは柔軟性を制限し、はユーザーエクスペリエン スを低下させる可能性があります。 そのため、アンチパターンであると考えられてお り、は避けなければなりません。

アクションアイデンティティ認証 #

トランザクションに identity アカウントが含まれている場合、それをアクションプロ バイダーに検証可能に関連付けるには、以下の手順を行います:

  1. 与えられた identity のすべてのトランザクションを取得します。
  2. 各トランザクションのメモ文字列を解析して検証し、signature が格納されている reference に対して有効であることを確認する。
  3. 特定のトランザクションがオンチェーンの reference の最初のオンチェーンである ことを確認します。
    • このトランザクションが最初の発生である場合、トランザクションは検証済みと見 なされ、アクションプロバイダーに安全に関連付けることができます。
    • このトランザクションが最初の発生でない場合、無効と見なされ、アクションプロ バイダーに関連付けられません。

Solanaバリデータはトランザクションをアカウントキーによってインデックス付けするた め、getSignaturesForAddress RPCメソッドを使用して、identity アカウントを含むすべてのトランザクションを検索 できます。

このRPCメソッドのレスポンスには、すべての memo データがmemoフィールドに含まれ ます。 トランザクションに複数のMemo命令が使用されている場合、各メモメッセージは この memo フィールドに含まれ、それに応じて検証者が解析して Identity Verification Message を取得する必要があります。

これらのトランザクションは最初に UNVERIFIED と見なされるべきです。 これ は、identity がトランザクションに署名する必要がないためで、これにより、このア カウントを署名者以外として含むトランザクションが可能になります。 人工的にアトリ ビューションや使用カウントを膨らませる可能性があります。

Identity Verification Message は signaturereference に署名する identity によって作成されたことを確認する この署名検証に失敗した場合、トランザ クションは無効であり、アクションプロバイダに帰属する必要があります。

署名の検証が成功した場合、検証者はこのトランザクションが reference のチェーン 上での最初の発生であることを確認する必要があります。 そうでない場合は、トランザ クションは無効と見なされます。