Solana Actions & Blinks 开发指南

Solana Actions使用户在网页即可执行区块链交易,Blinks则将任何 Solana Action 变成可共享的、元数据丰富的链接。

Solana Actions & Blinks 开发指南
一键发币: SOL | BNB | ETH | BASE | Blast | ARB | OP | POLYGON | AVAX | FTM | OK

Solana Actions 是符合规范的 API,可返回 Solana 区块链上的交易,以便在各种不同的环境中预览、签名和发送,包括二维码、按钮 + 小部件和互联网上的网站。Actions 使开发人员可以轻松地将你在整个 Solana 生态系统中执行的操作集成到你的环境中,从而使你无需导航到其他应用程序或网页即可执行区块链交易。

区块链链接(或Blinks)将任何 Solana Action 变成可共享的、元数据丰富的链接。Blinks允许 Action 感知客户端(浏览器扩展钱包、机器人)向用户显示其他功能。在网站上,Blinks可能会立即触发钱包中的交易预览,而无需转到去中心化应用程序;在 Discord 中,机器人可能会将Blinks扩展为一组交互式按钮。这将链上交互的能力推向任何能够显示 URL 的 Web 表面。

1、开始使用

要快速开始创建自定义 Solana Actions:

npm install @solana/actions
  • 在你的应用程序中安装 Solana Actions SDK
  • 为 GET 请求构建一个 API 端点,该端点返回有关你的 Action 的元数据
  • 创建一个 API 端点,该端点接受 POST 请求并为用户返回可签名交易
查看此视频教程了解如何使用 @solana/actions SDK 构建 Solana Action。你还可以在此处找到执行本机 SOL 传输的操作的源代码,以及此 repo 中的其他几个示例操作。

将自定义 Solana Actions 部署到生产环境时:

  • 确保你的应用程序在域的根目录中有一个有效的 action.json 文件
  • 确保你的应用程序在所有 Action 端点(包括 action.json 文件)上响应所需的跨域标头

如果你正在寻找构建 Actions 和 blinks 的灵感,请查看 Awesome Blinks 存储库以获取一些社区创作,甚至是新创意。

2、Actions

Solana Actions 规范使用一组标准 API 将可签名交易(以及最终的可签名消息)从应用程序直接传递给用户。它们托管在可公开访问的 URL 上,因此任何客户端都可以通过其 URL 进行交互。

你可以将 Actions 视为一个 API 端点,它将返回元数据和一些供用户使用其区块链钱包签名的内容(交易或身份验证消息)。

Actions API 包括向 Action 的 URL 端点发出简单的 GET 和 POST 请求,并处理符合 Actions 接口的响应。

  • GET 请求返回元数据,该元数据向客户端提供有关此 URL 上可用的操作的人性化信息,以及相关操作的可选列表。
  • POST 请求返回可签名的交易或消息,然后客户端提示用户的钱包在区块链或其他链下服务上签名并执行。

2.1 操作执行和生命周期

实际上,与操作的交互与与典型的 REST API 的交互非常相似:

  • 客户端向操作 URL 发出初始 GET 请求,以获取有关可用操作的元数据
  • 端点返回一个响应,其中包括有关端点的元数据(如应用程序的标题和图标)以及此端点可用操作的列表
  • 客户端应用程序(如移动钱包、聊天机器人或网站)显示 UI 供用户执行其中一项操作
  • 在用户选择操作(通过单击按钮)后,客户端向端点发出 POST 请求,以获取供用户签名的交易
  • 钱包帮助用户签署交易,并最终将交易发送到区块链进行确认
Solana Actions 的执行和生命周期

从 Actions URL 接收交易时,客户端应处理这些交易向区块链的提交并管理其状态生命周期。

Actions 还支持在执行之前进行一定程度的失效。 GET 和 POST 请求可能会返回一些元数据,说明是否可以执行该操作(例如禁用字段)。

例如,如果有一个 Action 端点有助于对投票窗口已关闭的 DAO 治理提案进行投票,则初始 GET 请求可能会返回错误消息“此提案不再可供投票”,并将“投票赞成”和“投票反对”按钮返回为“已禁用”。

Blinks(区块链链接)是自省 Action API 并围绕与 Actions 交互和执行 Actions 构建用户界面的客户端应用程序。

支持 blinks 的客户端应用程序只需检测与 Action 兼容的 URL、解析它们,并允许用户在标准化用户界面中与它们交互。

任何完全自省 Actions API 以为其构建完整界面的客户端应用程序都是 blink。因此,并非所有使用 Actions API 的客户端都是blinks。

Blink URL 描述了一个客户端应用程序,使用户能够完成执行操作的整个生命周期,包括使用钱包签名。

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

任何客户端应用程序若要成为 blink:

  • blink URL 必须包含 action 查询参数,其值为 URL 编码的 Action URL。此值必须经过 URL 编码,以免与任何其他协议参数冲突。
  • 客户端应用程序必须对 action 查询参数进行 URL 解码,并检查提供的 Action API 链接(请参阅 Action URL 方案)。
  • 客户端必须呈现丰富的用户界面,使用户能够完成执行 Action 的整个生命周期,包括使用钱包签名。
并非所有 blink 客户端应用程序(例如网站或 dApp)都支持所有 Action。应用程序开发人员可以选择他们希望在其 blink 界面中支持哪些 Action。

以下示例演示了一个有效的 blink URL,其 action 值为 solana-action:https://actions.alice.com/donate,该 URL 经过编码后如下所示:

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

Blinks 至少可以通过 3 种方式链接到Actoins操作:

  • 共享显式操作 URL: solana-action:https://actions.alice.com/donate

在这种情况下,只有受支持的客户端才能呈现 Blink。不会有后备链接预览,也不会有非支持客户端之外可以访问的网站。

  • 通过网站域根目录上的 action.json 文件共享链接到操作 API 的网站链接。

例如, https://alice.com/actions.jsonhttps://alice.com/donate(用户可以向 Alice 捐款的网站 URL)映射到 API URL  https://actions.alice.com/donate(向 Alice 捐款的操作托管在该 URL)。

  • 将操作 URL 嵌入了解如何解析操作的“插页式”网站 URL 中。
https://example.domain/?action=<action_url>

支持 blinks 的客户端应该能够采用上述任何格式并正确呈现界面,以便直接在客户端中执行操作。

对于不支持 blinks 的客户端,应该有一个底层网站(使浏览器成为通用的后备)。

如果用户点击客户端上任何不是操作按钮或文本输入字段的地方,他们应该被带到底层网站。

虽然 Solana Actions 和 blinks 是一种无需许可的协议/规范,但客户端应用程序和钱包仍然需要最终方便用户签署交易。

这些客户端应用程序或钱包中的每一个可能对其客户端将自动展开并立即在社交媒体平台上向其用户显示的操作端点有不同的要求。

例如,某些客户端可能采用“允许列表”方法,可能需要在其客户端为用户展开操作之前进行验证,例如 Dialect 的 Actions Registry(详见下文)。

所有blinks仍将呈现并允许在 Dialect 的 dial.to 网站上签名,其注册状态显示在blinks中。

3.4 Dialect 的操作注册表

作为 Solana 生态系统的公共产品,Dialect 在 Solana 基金会和其他社区成员的帮助下维护了一个公共注册表,其中包含来自已知来源的预先验证过的区块链链接。自发布以来,只有在 Dialect 注册表中注册的操作才会在发布时在 Twitter 提要中展开。

客户端应用程序和钱包可以自由选择使用此公共注册表或其他解决方案来帮助确保用户安全。如果未通过 Dialect 注册表进行验证,区块链链接将不会被 blink 客户端触及,并将呈现为典型 URL。

开发人员可以在此处申请通过 Dialect 验证:dial.to/register

4、规范

Solana Actions 规范由请求/响应交互流程的关键部分组成:

  • Solana Action URL Schema提供 Action URL
  • OPTIONS 响应 Action URL 以传递 CORS 要求
  • GET 请求到 Action URL
  • GET 来自服务器的响应
  • POST 请求到 Action URL
  • POST 来自服务器的响应

这些请求中的每一个都由 Action 客户端(例如钱包应用程序、浏览器扩展、dApp、网站等)发出,以收集特定元数据以提供丰富的用户界面并方便用户输入 Actions API。

每个响应都由应用程序(例如网站、服务器后端等)制作并返回到 Action 客户端。最终,为钱包提供可签名的交易或消息,以提示用户批准、签名并发送到区块链。

4.1 URL Schema

Solana Action URL 描述了使用 solana-action 协议对可签名 Solana 交易或消息的交互式请求。

该请求是交互式的,因为客户端使用 URL 中的参数发出一系列标准化 HTTP 请求,以编写可签名交易或消息,供用户使用其钱包进行签名。

solana-action:<link>
  • 需要单个 link字段作为路径名。该值必须是有条件的 URL 编码的绝对 HTTPS URL。
  • 如果 URL 包含查询参数,则必须对其进行 URL 编码。对值进行 URL 编码可防止与任何 Actions 协议参数发生冲突,这些参数可以通过协议规范添加。
  • 如果 URL 不包含查询参数,则不应对其进行 URL 编码。这样会产生较短的 URL 和密度较低的二维码。

无论哪种情况,客户端都必须对值进行 URL 解码。如果值未进行 URL 编码,则此操作无效。如果解码后的值不是绝对 HTTPS URL,则钱包必须将其拒绝为格式错误。

4.2 OPTIONS 响应

为了允许 Actions 客户端(包括 blinks)内的跨源资源共享 (CORS),所有 Action 端点都应使用有效标头响应 OPTIONS 方法的 HTTP 请求,这将允许客户端通过来自其同一源域的所有后续请求的 CORS 检查。

Actions 客户端可以对 Action URL 端点执行“预检”请求,以检查对 Action URL 的后续 GET 请求是否会通过所有 CORS 检查。这些 CORS 预检检查是使用 OPTIONS HTTP 方法进行的,并且应使用所有必需的 HTTP 标头进行响应,这将允许 Action 客户端(如 blinks)正确地从其源域发出所有后续请求。

至少,所需的 HTTP 标头包括:

  • Access-Control-Allow-Origin 值为 *,这确保所有 Action 客户端都可以安全地通过 CORS 检查,以便发出所有必需的请求
  • Access-Control-Allow-Methods 值为 GETPOSTPUTOPTIONS,确保 Actions 支持所有必需的 HTTP 请求方法
  • Access-Control-Allow-Headers 的最小值为 Content-TypeAuthorizationContent-EncodingAccept-Encoding

为简单起见,开发人员应考虑向 OPTIONS 请求返回与其 GET 响应相同的响应和标头。

ACTIONS.JSON 的跨源标头
actions.json 文件响应还必须返回 GET 和 OPTIONS 请求的有效跨源标头,特别是 Access-Control-Allow-Origin 标头值 *。

有关更多详细信息,请参阅下面的 action.json。

4.3 GET 请求

Action 客户端(例如钱包、浏览器扩展等)应向 Action 的 URL 端点发出 HTTP GET JSON 请求。

  • 请求不应识别钱包或用户。
  • 客户端应使用 Accept-Encoding 标头发出请求。
  • 客户端应在发出请求时显示 URL 的域。

4.4 GET 响应

Action 的 URL 端点(例如应用程序或服务器后端)应使用 HTTP OK JSON 响应(主体中带有有效负载)或适当的 HTTP 错误进行响应。

  • 客户端必须处理 HTTP 客户端错误、服务器错误和重定向响应。
  • 端点应使用 Content-Encoding 标头进行响应以进行 HTTP 压缩。
  • 端点应使用 application/json 的 Content-Type 标头进行响应。
  • 客户端不应缓存响应,除非 HTTP 缓存响应标头指示。
  • 客户端应显示标题并向用户呈现图标图像。
GET 响应主体

具有 HTTP OK JSON 响应的 GET 响应应包含遵循接口规范的主体负载:

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 图像,否则客户端/钱包必须拒绝它,因为它格式不正确。
  • title - 该值必须是 UTF-8 字符串,表示操作请求的来源。例如,这可能是发出请求的品牌、商店、应用程序或人员的名称。
  • description - 该值必须是 UTF-8 字符串,提供有关操作的信息。应向用户显示描述。
  • label - 该值必须是 UTF-8 字符串,将呈现在按钮上供用户单击。所有标签都不应超过 5 个单词短语,并且应以动词开头,以巩固您希望用户采取的操作。例如,“Mint NFT”、“Vote Yes”或“Stake 1 SOL”。
  • disabled - 该值必须是布尔值,以表示呈现的按钮(显示标签字符串)的禁用状态。如果未提供任何值,则禁用应默认为 false(即默认启用)。例如,如果操作端点用于已关闭的治理投票,则设置 disabled=true,标签可以是“投票已关闭”。
  • error - 非致命错误的可选错误指示。如果存在,客户端应将其显示给用户。如果设置,它不应阻止客户端解释操作或将其显示给用户。例如,错误可以与禁用一起使用,以显示原因,如业务限制、授权、状态或外部资源错误。
export interface ActionError {
  /** non-fatal error message to be displayed to the user */
  message: string;
}
  • links.actions - 端点相关操作的可选数组。应为用户显示每个列出的操作的 UI,并期望用户只执行一项操作。例如,治理投票操作端点可能会为用户返回三个选项:“投赞成票”、“投反对票”和“弃权”。

如果没有提供 links.actions,客户端应使用根标签字符串呈现单个按钮,并向与初始 GET 请求相同的操作 URL 端点发出 POST 请求。

如果提供了任何 links.actions,客户端应仅根据 links.actions 字段中列出的项目呈现按钮和输入字段。客户端不应为根标签的内容呈现按钮。

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 响应

以下示例响应提供了单个“根”操作,预计会向用户显示一个带有“索取访问令牌”标签的按钮:

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

以下示例响应提供了 3 个相关的操作链接,允许用户单击 3 个按钮之一来为 DAO 提案投票:

{
  "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 响应

以下示例响应演示了如何接受来自用户的文本输入(通过参数)并将该输入包含在最终 POST 请求端点中(通过 LinkedAction 中的 href 字段):

以下示例响应为用户提供了 3 个链接操作来质押 SOL:一个标记为“质押 1 SOL”的按钮,另一个标记为“质押 5 SOL”的按钮,以及一个文本输入字段,允许用户输入将发送到操作 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
          }
        ]
      }
    ]
  }
}

以下示例响应提供了一个输入字段,供用户输入随 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
          }
        ]
      }
    ]
  }
}

4.5 POST 请求

客户端必须向操作 URL 发出 HTTP POST JSON 请求,其主体负载如下:

{
  "account": "<account>"
}
  • ccount - 该值必须是可以签署交易的帐户的 base58 编码公钥。

客户端应使用 Accept-Encoding 标头发出请求,应用程序可以使用 Content-Encoding 标头进行响应以进行 HTTP 压缩。

客户端应在发出请求时显示操作 URL 的域。如果发出了 GET 请求,客户端还应显示标题并从该 GET 响应中呈现图标图像。

4.6 POST 响应

Action 的 POST 端点应使用 HTTP OK JSON 响应(主体中具有有效负载)或适当的 HTTP 错误进行响应。

  • 客户端必须处理 HTTP 客户端错误、服务器错误和重定向响应。
  • 端点应使用 application/json 的 Content-Type 标头进行响应。
POST 响应主体

具有 HTTP OK JSON 响应的 POST 响应应包含主体负载:

export interface ActionPostResponse {
  /** base64 encoded serialized transaction */
  transaction: string;
  /** describes the nature of the transaction */
  message?: string;
}
  • transaction - 该值必须是 base64 编码的序列化交易。客户端必须对交易进行 base64 解码并反序列化。
  • message - 该值必须是 UTF-8 字符串,用于描述响应中包含的交易的性质。客户端应向用户显示此值。例如,这可能是正在购买的商品的名称、购买的折扣或感谢信。

客户端和应用程序应允许在请求正文和响应正文中添加其他字段,这些字段可能会在未来的规范更新中添加。应用程序可能会以部分或完全签名的交易进行响应。客户端和钱包必须验证交易是否不受信任。

POST 响应 - 交易

如果交易签名为空或交易尚未部分签名:

  • 客户端必须忽略交易中的 feePayer,并将 feePayer 设置为请求中的帐户。
  • 客户端必须忽略交易中的 recentBlockhash,并将 recentBlockhash 设置为最新的 blockhash。
  • 客户端必须在签署交易之前对其进行序列化和反序列化。这可确保帐户密钥的一致排序,作为解决此问题的解决方法。

如果交易已部分签名:

  • 客户端不得更改 feePayer 或 recentBlockhash,因为这会使任何现有签名无效。
  • 客户端必须验证现有签名,如果任何签名无效,客户端必须拒绝交易,因为格式不正确。

客户端必须仅使用请求中的帐户签署交易,并且只有在需要请求中帐户的签名时才必须这样做。

如果需要除请求中帐户签名之外的任何签名,客户端必须拒绝交易,因为交易是恶意的。

5、action.json

actions.json 文件的目的是允许应用程序指示客户端哪些网站 URL 支持 Solana Actions,并提供可用于向 Actions API 服务器执行 GET 请求的映射。

actions.json 文件响应还必须返回有效的跨源标头,用于 GET 和 OPTIONS 请求,特别是 Access-Control-Allow-Origin 标头值 *。

有关更多详细信息,请参阅上面的 OPTIONS 响应。

action.json 文件应存储在域的根目录中,并可在其中普遍访问。

例如,如果你的 Web 应用程序部署到 my-site.com,则应可在 https://my-site.com/actions.json 上访问 action.json 文件。此文件还应具有 Access-Control-Allow-Origin 标头值  *,可通过任何浏览器进行跨源访问。

5.1 规则

规则字段允许应用程序将一组网站的相对路由路径映射到一组其他路径。

类型: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

与每个传入路径名匹配的模式。它可以是绝对路径或相对路径,并支持以下格式:

精确匹配:匹配精确的 URL 路径。

  • 示例: /exact-path
  • 示例: https://website.com/exact-path

通配符匹配:使用通配符匹配 URL 路径中的任何字符序列。这可以匹配单个(使用 *)或多个段(使用 **)。(请参阅下面的路径匹配)。

  • 示例: /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。

  • 示例: /api/exact-path
  • 示例: https://api.example.com/v1/donate/*
  • 示例: /api/category/*/item/
  • 示例: /api/swap/**
规则 - 查询参数

原始 URL 中的查询参数始终保留并附加到映射 URL。

规则 - 路径匹配

下表概述了路径匹配模式的语法:

运算符 匹配
* 单个路径段,不包括周围的路径分隔符/字符。
** 匹配零个或多个字符,包括多个路径段之间的任何路径分隔符/字符。如果包含其他运算符,则**运算符必须是最后一个运算符。
? 不支持的模式。

5.2 规则示例

以下示例演示了精确匹配规则,将你网站根目录中对 /buy 的请求映射到相对于您网站根目录的精确路径 /api/buy

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

以下示例使用通配符路径匹配将对站点根目录中 /actions/ 下任意路径(不包括子目录)的请求映射到相对于站点根目录的 /api/actions/ 下的相应路径:

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

以下示例使用通配符路径匹配将对站点根目录中 /donate/ 下的任何路径(不包括子目录)的请求映射到外部站点绝对路径  https://api.dialect.com/api/v1/donate/

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

以下示例使用幂等规则的通配符路径匹配将请求映射到 /api/actions/ 下的任何路径(包括子目录),从你网站的根目录到其自身:

幂等规则允许 blink 客户端更轻松地确定给定路径是否支持 Action API 请求,而无需使用 solana-action: URI 作为前缀或执行其他响应测试。
{
  "rules": [
    {
      "pathPattern": "/api/actions/**",
      "apiPath": "/api/actions/**"
    }
  ]
}

6、Action标识

Action端点可能在交易中包含标识,这些交易在其 POST 响应中返回,供用户签名。这允许索引器和分析平台以可验证的方式轻松且可验证地将链上活动归因于特定的Action提供者(即服务)。

Action标识是一个密钥对,用于使用备忘录指令对包含在交易中的特殊格式的消息进行签名。此标识符消息可以可验证地归因于特定的操作标识,因此将交易归因于特定的操作提供者。

密钥对不需要对交易本身进行签名。当返回给用户的交易上没有其他签名时,这允许钱包和应用程序提高交易的可交付性(请参阅 POST 响应交易)。

如果Action提供者的用例要求其后端服务在用户之前预先签署交易,则他们应该使用此密钥对作为其操作标识。这将允许在交易中包含一个更少的帐户,从而将总交易大小降低 32 字节。

6.1 Action标识符消息

动作标识符消息是一个冒号分隔的 UTF-8 字符串,包含在使用单个 SPL 备忘录指令的交易中。

protocol:identity:reference:signature
  • protocol - 正在使用的协议的值(根据上面的 URL 方案设置为 solana-action)
  • identity - 该值必须是 Action Identity 密钥对的 base58 编码公钥地址
  • reference - 该值必须是 base58 编码的 32 字节数组。这可能是也可能不是公钥,在曲线上或曲线外,也可能与 Solana 上的账户相对应,也可能不对应。
  • signature - 从 Action Identity 密钥对创建的 base58 编码签名,仅对参考值进行签名。

reference只能在单个交易中使用一次。为了将交易与 Action Provider 关联,只有第一次使用参考值才被视为有效。

交易可能有多个备忘录指令。执行 getSignaturesForAddress 时,结果 memo字段将以单个字符串的形式返回每个备忘录指令的消息,每个消息用分号分隔。

标识符消息的 memo指令中不应包含任何其他数据。

identityreference应作为只读、非签名者密钥包含在交易中,该交易不是标识符消息备忘录指令。

标识符消息备忘录指令必须提供零个账户。如果提供了任何账户,备忘录程序要求这些账户是有效的签名者。为了识别操作,这会限制灵活性并可能降低用户体验。因此,它被视为反模式,必须避免。

6.2 操作身份验证

任何包含身份账户的交易都可以通过多步骤过程与操作提供者进行可验证的关联:

  • 获取给定身份的所有交易。
  • 解析并验证每笔交易的备忘录字符串,确保签名对于存储的引用有效。
  • 验证特定交易是否是链上引用的第一次链上发生:如果此交易是第一次发生,则认为该交易已验证,并且可以安全地归因于操作提供者。如果此交易不是第一次发生,则认为它无效,因此不归因于操作提供者。

由于 Solana 验证器通过账户密钥索引交易,因此可以使用 getSignaturesForAddress RPC 方法查找包括身份账户在内的所有交易。

此 RPC 方法的响应包括备忘录字段中的所有备忘录数据。如果交易中使用了多个备忘录指令,则每个备忘录消息都将包含在此备忘录字段中,并且必须由验证者进行相应解析以获取身份验证消息。

这些交易最初应被视为未经验证。这是因为无需身份即可签署交易,这允许任何交易将此帐户作为非签名者。可能会人为地夸大归因和使用计数。

应检查身份验证消息以确保签名是由签署引用的身份创建的。如果此签名验证失败,则交易无效,应归因于操作提供者。

如果签名验证成功,验证者应确保此交易是引用的第一次链上发生。如果不是,则交易被视为无效。


原文链接:Actions and Blinks

DefiPlot翻译整理,转载请标明出处

通过 NowPayments 打赏