Solana Actions là các API tuân thủ đặc tả, trả về các giao dịch trên blockchain Solana để xem trước, ký và gửi đi trong nhiều ngữ cảnh khác nhau, bao gồm mã QR, nút + tiện ích, và các trang web trên internet. Actions giúp các nhà phát triển dễ dàng tích hợp những thao tác trong hệ sinh thái Solana trực tiếp vào môi trường của bạn, cho phép bạn thực hiện các giao dịch blockchain mà không cần điều hướng sang ứng dụng hoặc trang web khác.
Blockchain links – hay blinks – biến bất kỳ Solana Action nào thành một liên kết có thể chia sẻ, giàu metadata. Blinks cho phép các client nhận biết Action (ví tiện ích mở rộng trình duyệt, bot) hiển thị thêm các tính năng cho người dùng. Trên một trang web, một blink có thể kích hoạt ngay lập tức bản xem trước giao dịch trong ví mà không cần truy cập vào ứng dụng phi tập trung; trong Discord, một bot có thể mở rộng blink thành một tập hợp các nút tương tác. Điều này đưa khả năng tương tác onchain đến bất kỳ bề mặt web nào có thể hiển thị URL.
Bắt Đầu
Để nhanh chóng bắt đầu tạo Solana Actions tùy chỉnh:
npm install @solana/actions
- cài đặt Solana Actions SDK vào ứng dụng của bạn
- xây dựng một API endpoint cho GET request trả về metadata về Action của bạn
- tạo một API endpoint chấp nhận POST request và trả về giao dịch có thể ký cho người dùng
Xem hướng dẫn video này về cách xây dựng một Solana Action sử dụng SDK
@solana/actions.Bạn cũng có thể tìm thấy mã nguồn của một Action thực hiện chuyển SOL gốc tại đây và một số Action mẫu khác trong repo này.
Khi triển khai Solana Actions tùy chỉnh của bạn lên môi trường production:
- đảm bảo ứng dụng của bạn có file actions.json hợp lệ tại thư mục gốc của domain
- đảm bảo ứng dụng của bạn phản hồi với
các header Cross-Origin bắt buộc trên tất cả các Action endpoint,
bao gồm cả file
actions.json - kiểm tra và gỡ lỗi các blinks/actions của bạn bằng Blinks Inspector
Nếu bạn đang tìm kiếm nguồn cảm hứng để xây dựng Actions và blinks, hãy xem repository Awesome Blinks cho một số tác phẩm của cộng đồng và thậm chí ý tưởng cho những cái mới.
Actions
Đặc tả Solana Actions sử dụng một tập hợp các API tiêu chuẩn để cung cấp các giao dịch có thể ký (và cuối cùng là các thông điệp có thể ký) từ một ứng dụng trực tiếp đến người dùng. Chúng được lưu trữ tại các URL có thể truy cập công khai và do đó có thể được truy cập bằng URL của chúng bởi bất kỳ client nào.
Bạn có thể coi Actions như một API endpoint sẽ trả về metadata và nội dung để người dùng ký (hoặc là một giao dịch hoặc một thông điệp xác thực) bằng ví blockchain của họ.
Actions API bao gồm việc thực hiện các GET và POST request đơn giản đến
URL endpoint của một Action và xử lý các phản hồi tuân theo giao diện
Actions.
- GET request trả về metadata cung cấp thông tin dễ đọc cho client về những actions nào có sẵn tại URL này, và một danh sách tùy chọn các actions liên quan.
- POST request trả về một giao dịch hoặc thông điệp có thể ký mà client sau đó nhắc ví của người dùng ký và thực thi trên blockchain hoặc trong một dịch vụ offchain khác.
Thực Thi và Vòng Đời của Action
Trong thực tế, việc tương tác với Actions rất giống với việc tương tác với một REST API thông thường:
- client thực hiện
GETrequest ban đầu đến một Action URL để lấy metadata về các Actions có sẵn - endpoint trả về phản hồi bao gồm metadata về endpoint (như tiêu đề và biểu tượng của ứng dụng) và danh sách các actions có sẵn cho endpoint này
- ứng dụng client (như ví di động, chat bot, hoặc trang web) hiển thị giao diện người dùng để thực hiện một trong các actions
- sau khi người dùng chọn một action (bằng cách nhấp vào nút), client thực hiện
POSTrequest đến endpoint để lấy giao dịch cho người dùng ký - ví hỗ trợ người dùng ký giao dịch và cuối cùng gửi giao dịch đến blockchain để xác nhận
Thực Thi và Vòng Đời của Solana Actions
Khi nhận giao dịch từ một Actions URL, các client nên xử lý việc gửi các giao dịch này lên blockchain và quản lý vòng đời trạng thái của chúng.
Actions cũng hỗ trợ một mức độ vô hiệu hóa nhất định trước khi thực thi. GET và
POST request có thể trả về một số metadata cho biết liệu action có
thể được thực hiện hay không (như với trường disabled).
Ví dụ, nếu có một Action endpoint hỗ trợ bỏ phiếu cho một đề xuất quản trị DAO mà cửa sổ bỏ phiếu đã đóng, GET request ban đầu có thể trả về thông báo lỗi "Đề xuất này không còn được đưa ra bỏ phiếu" và các nút "Bỏ phiếu Có" và "Bỏ phiếu Không" ở trạng thái "disabled".
Blinks
Blinks (blockchain links) là các ứng dụng client kiểm tra các Action API và xây dựng giao diện người dùng xung quanh việc tương tác và thực thi các Actions.
Các ứng dụng client hỗ trợ blinks chỉ cần phát hiện các URL tương thích với Action, phân tích chúng và cho phép người dùng tương tác với chúng trong các giao diện người dùng tiêu chuẩn.
Bất kỳ ứng dụng client nào kiểm tra đầy đủ một Actions API để xây dựng một giao diện hoàn chỉnh cho nó đều là một blink. Do đó, không phải tất cả các client sử dụng Actions API đều là blinks.
Đặc Tả URL Blink
Một URL blink mô tả một ứng dụng client cho phép người dùng hoàn thành toàn bộ vòng đời thực thi một Action, bao gồm cả việc ký bằng ví của họ.
https://example.domain/?action=<action_url>
Để bất kỳ ứng dụng client nào trở thành một blink:
-
URL blink phải chứa tham số query
actioncó giá trị là Action URL được mã hóa URL. Giá trị này phải được mã hóa URL để không xung đột với bất kỳ tham số giao thức nào khác. -
Ứng dụng client phải giải mã URL tham số query
actionvà kiểm tra liên kết Action API được cung cấp (xem sơ đồ URL Action). -
Client phải hiển thị giao diện người dùng phong phú cho phép người dùng hoàn thành toàn bộ vòng đời thực thi một Action, bao gồm cả việc ký bằng ví của họ.
Không phải tất cả các ứng dụng client blink (ví dụ: trang web hoặc dApps) đều hỗ trợ tất cả các Actions. Nhà phát triển ứng dụng có thể chọn những Actions nào họ muốn hỗ trợ trong giao diện blink của họ.
Ví dụ sau đây minh họa một URL blink hợp lệ với giá trị action là
solana-action:https://actions.alice.com/donate được mã hóa URL:
https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2Fdonate
Phát Hiện Actions qua Blinks
Blinks có thể được liên kết với Actions theo ít nhất 3 cách:
-
Chia sẻ một Action URL rõ ràng:
solana-action:https://actions.alice.com/donateTrong trường hợp này, chỉ các client được hỗ trợ mới có thể hiển thị blink. Sẽ không có liên kết xem trước dự phòng, hoặc trang web có thể truy cập bên ngoài client không hỗ trợ.
-
Chia sẻ liên kết đến một trang web được liên kết với Actions API thông qua file
actions.jsontại thư mục gốc domain của trang web.Ví dụ,
https://alice.com/actions.jsonánh xạhttps://alice.com/donate, một URL trang web nơi người dùng có thể quyên góp cho Alice, đến URL APIhttps://actions.alice.com/donate, nơi các Actions để quyên góp cho Alice được lưu trữ. -
Nhúng một Action URL vào URL trang web "interstitial" hiểu cách phân tích Actions.
https://example.domain/?action=<action_url>
Các client hỗ trợ blinks phải có khả năng nhận bất kỳ định dạng nào trong số trên và hiển thị chính xác giao diện để hỗ trợ thực thi action trực tiếp trong client.
Đối với các client không hỗ trợ blinks, phải có một trang web cơ bản (khiến trình duyệt trở thành phương án dự phòng toàn cầu).
Nếu người dùng nhấn vào bất kỳ đâu trên client mà không phải là nút action hoặc trường nhập văn bản, họ sẽ được dẫn đến trang web cơ bản.
Kiểm Tra và Xác Minh Blink
Mặc dù Solana Actions và blinks là một giao thức/đặc tả không cần cấp phép, các ứng dụng client và ví vẫn được yêu cầu hỗ trợ người dùng ký giao dịch.
Sử dụng công cụ Blinks Inspector để kiểm tra, gỡ lỗi và thử nghiệm các blinks và actions của bạn trực tiếp trong trình duyệt. Bạn có thể xem các payload phản hồi GET và POST, header phản hồi, và kiểm tra tất cả các đầu vào cho từng Action được liên kết của bạn.
Mỗi ứng dụng client hoặc ví có thể có các yêu cầu khác nhau về việc Action endpoint nào sẽ được tự động mở rộng và hiển thị ngay lập tức cho người dùng trên các nền tảng mạng xã hội.
Ví dụ, một số client có thể hoạt động theo phương pháp "danh sách cho phép" có thể yêu cầu xác minh trước khi client mở rộng một Action cho người dùng, chẳng hạn như Dialect's Actions Registry (được mô tả chi tiết bên dưới).
Tất cả các blinks vẫn sẽ hiển thị và cho phép ký trên trang Interstitial blinks dial.to của Dialect, với trạng thái registry của chúng hiển thị trong blink.
Actions Registry của Dialect
Như một lợi ích công cộng cho hệ sinh thái Solana, Dialect duy trì một registry công khai — cùng với sự giúp đỡ của Solana Foundation và các thành viên cộng đồng khác — về các blockchain link đã được xác minh trước từ các nguồn đã biết. Kể từ khi ra mắt, chỉ các Actions đã được đăng ký trong Dialect registry mới được hiển thị trong Twitter feed khi được đăng.
Các ứng dụng client và ví có thể tự do chọn sử dụng registry công khai này hoặc một giải pháp khác để giúp đảm bảo bảo mật và an toàn cho người dùng. Nếu không được xác minh qua Dialect registry, blockchain link sẽ không được xử lý bởi blink client và sẽ được hiển thị như một URL thông thường.
Các nhà phát triển có thể đăng ký để được Dialect xác minh tại đây: dial.to/register
Đặc Tả
Đặc tả Solana Actions bao gồm các phần chính là một phần của luồng tương tác request/response:
- Sơ đồ URL của Solana Action cung cấp một Action URL
- Phản hồi OPTIONS đến một Action URL để đáp ứng các yêu cầu CORS
- GET request đến một Action URL
- Phản hồi GET từ server
- POST request đến một Action URL
- Phản hồi POST từ server
Mỗi yêu cầu này được thực hiện bởi Action client (ví dụ: ứng dụng ví, tiện ích mở rộng trình duyệt, dApp, website, v.v.) để thu thập metadata cụ thể cho giao diện người dùng phong phú và tạo điều kiện cho người dùng nhập liệu vào Actions API.
Mỗi phản hồi được tạo ra bởi một ứng dụng (ví dụ: website, server backend, v.v.) và trả về cho Action client. Cuối cùng, cung cấp một giao dịch hoặc tin nhắn có thể ký để ví nhắc người dùng phê duyệt, ký và gửi lên blockchain.
Các kiểu và giao diện được khai báo trong file readme này thường là phiên bản đơn giản hóa của các kiểu để hỗ trợ khả năng đọc.
Để đảm bảo an toàn kiểu tốt hơn và cải thiện trải nghiệm nhà phát triển, gói
@solana/actions-specchứa các định nghĩa kiểu phức tạp hơn. Bạn có thể tìm thấy mã nguồn của chúng tại đây.
Lược đồ URL
Một URL Solana Action mô tả một yêu cầu tương tác cho một giao dịch hoặc tin nhắn Solana có thể ký sử dụng giao thức solana-action.
Yêu cầu mang tính tương tác vì các tham số trong URL được client sử dụng để thực hiện một loạt các yêu cầu HTTP chuẩn hóa nhằm tạo ra một giao dịch hoặc tin nhắn có thể ký để người dùng ký bằng ví của họ.
solana-action:<link>
-
Một trường
linkduy nhất được yêu cầu là pathname. Giá trị phải là một URL HTTPS tuyệt đối được mã hóa URL có điều kiện. -
Nếu URL chứa tham số truy vấn, nó phải được mã hóa URL. Việc mã hóa URL giá trị ngăn ngừa xung đột với bất kỳ tham số giao thức Actions nào, vốn có thể được thêm vào qua đặc tả giao thức.
-
Nếu URL không chứa tham số truy vấn, nó không nên được mã hóa URL. Điều này tạo ra một URL ngắn hơn và mã QR ít dày đặc hơn.
Trong cả hai trường hợp, client phải giải mã URL giá trị. Điều này không có hiệu lực nếu giá trị không được mã hóa URL. Nếu giá trị đã giải mã không phải là một URL HTTPS tuyệt đối, ví phải từ chối nó là không hợp lệ.
Phản hồi OPTIONS
Để cho phép Chia sẻ Tài nguyên Nguồn gốc Chéo
(CORS) trong các
client Actions (bao gồm cả blinks), tất cả các endpoint Action nên phản hồi các yêu cầu HTTP
cho phương thức OPTIONS với các header hợp lệ cho phép client vượt qua
kiểm tra CORS cho tất cả các yêu cầu tiếp theo từ cùng domain gốc của họ.
Một Action client có thể thực hiện các yêu cầu
"preflight"
đến endpoint URL Action để kiểm tra xem yêu cầu GET tiếp theo
đến URL Action có vượt qua tất cả các kiểm tra CORS hay không. Các kiểm tra CORS preflight này được
thực hiện bằng phương thức HTTP OPTIONS và nên phản hồi với tất cả các HTTP header
bắt buộc cho phép các Action client (như blinks) thực hiện đúng cách tất cả
các yêu cầu tiếp theo từ domain gốc của họ.
Tối thiểu, các HTTP header bắt buộc bao gồm:
Access-Control-Allow-Originvới giá trị là*- điều này đảm bảo tất cả các Action client có thể vượt qua kiểm tra CORS một cách an toàn để thực hiện tất cả các yêu cầu cần thiết
Access-Control-Allow-Methodsvới giá trị làGET,POST,PUT,OPTIONS- đảm bảo tất cả các phương thức yêu cầu HTTP cần thiết được hỗ trợ cho Actions
Access-Control-Allow-Headersvới giá trị tối thiểu làContent-Type, Authorization, Content-Encoding, Accept-Encoding
Để đơn giản hóa, các nhà phát triển nên cân nhắc trả về cùng phản hồi và
các header cho yêu cầu OPTIONS như phản hồi GET của họ.
Header Cross-Origin cho actions.json
File actions.json khi phản hồi cũng phải trả về các header Cross-Origin hợp lệ cho
các yêu cầu GET và OPTIONS, cụ thể là giá trị header Access-Control-Allow-Origin
là *.
Xem actions.json bên dưới để biết thêm chi tiết.
Yêu cầu GET
Action client (ví dụ: ví, tiện ích mở rộng trình duyệt, v.v.) nên thực hiện một yêu cầu HTTP
GET JSON đến endpoint URL của Action.
- Yêu cầu không nên xác định ví hoặc người dùng.
- Client nên thực hiện yêu cầu với
header
Accept-Encoding. - Client nên hiển thị domain của URL khi yêu cầu đang được thực hiện.
Phản hồi GET
Endpoint URL của Action (ví dụ: ứng dụng hoặc server backend) nên phản hồi
bằng một phản hồi HTTP OK JSON (với payload hợp lệ trong body) hoặc một
lỗi HTTP thích hợp.
-
Client phải xử lý lỗi client, lỗi server, và phản hồi chuyển hướng.
-
Endpoint nên phản hồi với header
Content-Encodingđể nén HTTP. -
Endpoint nên phản hồi với header
Content-Typelàapplication/json. -
Client không nên lưu vào bộ nhớ đệm phản hồi ngoại trừ theo hướng dẫn của HTTP caching trong các header phản hồi.
-
Client nên hiển thị
titlevà render hình ảnhiconcho người dùng.
Các phản hồi lỗi (tức là mã trạng thái HTTP 4xx và 5xx) nên trả về một body phản hồi JSON
theo ActionError để trình bày thông báo lỗi hữu ích cho
người dùng. Xem Action Errors.
Body Phản hồi GET
Một phản hồi GET với HTTP OK JSON nên bao gồm một body payload
tuân theo đặc tả giao diện:
export type ActionType = "action" | "completed";export type ActionGetResponse = Action<"action">;export interface Action<T extends ActionType> {/** type of Action to present to the user */type: T;/** 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;}
-
type- Loại action được cung cấp cho người dùng. Mặc định làaction.ActionGetResponseban đầu bắt buộc phải có type làaction.action- Action tiêu chuẩn cho phép người dùng tương tác với bất kỳLinkedActionsnàocompleted- Được dùng để khai báo trạng thái "hoàn thành" trong chuỗi action.
-
icon- Giá trị phải là một URL HTTP hoặc HTTPS tuyệt đối của một hình ảnh biểu tượng. File phải là hình ảnh SVG, PNG hoặc WebP, nếu không client/ví phải từ chối nó là không hợp lệ. -
title- Giá trị phải là một chuỗi UTF-8 đại diện cho nguồn của yêu cầu action. Ví dụ: đây có thể là tên của một thương hiệu, cửa hàng, ứng dụng hoặc người thực hiện yêu cầu. -
description- Giá trị phải là một chuỗi UTF-8 cung cấp thông tin về action. Mô tả nên được hiển thị cho người dùng. -
label- Giá trị phải là một chuỗi UTF-8 sẽ được hiển thị trên một nút để người dùng nhấp vào. Tất cả nhãn không nên vượt quá 5 từ và nên bắt đầu bằng một động từ để củng cố hành động bạn muốn người dùng thực hiện. Ví dụ: "Mint NFT", "Vote Yes", hoặc "Stake 1 SOL". -
disabled- Giá trị phải là boolean để thể hiện trạng thái vô hiệu hóa của nút được hiển thị (hiển thị chuỗilabel). Nếu không có giá trị nào được cung cấp,disabledmặc định làfalse(tức là được bật theo mặc định). Ví dụ, nếu endpoint action dành cho một cuộc bỏ phiếu quản trị đã kết thúc, hãy đặtdisabled=truevàlabelcó thể là "Vote Closed". -
error- Dấu hiệu lỗi tùy chọn cho các lỗi không nghiêm trọng. Nếu có, client nên hiển thị nó cho người dùng. Nếu được đặt, nó không nên ngăn client diễn giải action hoặc hiển thị nó cho người dùng (xem Action Errors). Ví dụ, lỗi có thể được sử dụng cùng vớidisabledđể hiển thị lý do như ràng buộc kinh doanh, xác thực, trạng thái hoặc lỗi của tài nguyên bên ngoài. -
links.actions- Một mảng tùy chọn các action liên quan cho endpoint. Người dùng nên được hiển thị giao diện người dùng cho từng action được liệt kê và được kỳ vọng chỉ thực hiện một. Ví dụ: một endpoint action bỏ phiếu quản trị có thể trả về ba lựa chọn cho người dùng: "Vote Yes", "Vote No" và "Abstain from Vote".-
Nếu không có
links.actionsnào được cung cấp, client nên hiển thị một nút đơn sử dụng chuỗilabelgốc và thực hiện yêu cầu POST đến cùng endpoint URL action như yêu cầu GET ban đầu. -
Nếu có bất kỳ
links.actionsnào được cung cấp, client chỉ nên hiển thị các nút và trường nhập liệu dựa trên các mục được liệt kê trong trườnglinks.actions. Client không nên hiển thị nút cho nội dung củalabelgốc.
-
export interface LinkedAction {/** Type of action to be performed by user */type: LinkedActionType;/** URL endpoint for an action */href: string;/** button text rendered to the user */label: string;/*** Parameters to accept user input within an action* @see {ActionParameter}* @see {ActionParameterSelectable}*/parameters?: Array<TypedActionParameter>;}
ActionParameter cho phép khai báo loại đầu vào mà Action API đang yêu cầu
từ người dùng:
/*** Parameter to accept user input within an action* note: for ease of reading, this is a simplified type of the actual*/export interface ActionParameter {/** input field type */type?: ActionParameterType;/** 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;/** regular expression pattern to validate user input client side */pattern?: string;/** human-readable description of the `type` and/or `pattern`, represents a caption and error, if value doesn't match */patternDescription?: string;/** the minimum value allowed based on the `type` */min?: string | number;/** the maximum value allowed based on the `type` */max?: string | number;}
pattern nên là một chuỗi tương đương với một biểu thức chính quy hợp lệ. Mẫu biểu thức chính quy này nên được blink-client sử dụng để xác thực đầu vào của người dùng trước khi thực hiện yêu cầu POST. Nếu pattern không phải là biểu thức chính quy hợp lệ, nó nên bị client bỏ qua.
patternDescription là mô tả có thể đọc được bởi con người về các yêu cầu đầu vào mong đợi từ người dùng. Nếu pattern được cung cấp, patternDescription bắt buộc phải được cung cấp.
Các giá trị min và max cho phép đầu vào đặt giới hạn dưới và/hoặc giới hạn trên
của đầu vào được yêu cầu từ người dùng (tức là số min/max và/hoặc độ dài ký tự min/max), và nên được sử dụng để xác thực phía client. Đối với các type đầu vào
date hoặc datetime-local, các giá trị này nên là chuỗi ngày tháng.
Đối với các type đầu vào dựa trên chuỗi khác, các giá trị nên là số đại diện
cho độ dài ký tự min/max của chúng.
Nếu giá trị đầu vào của người dùng không được coi là hợp lệ theo pattern, người dùng
nên nhận được thông báo lỗi phía client cho biết trường đầu vào không
hợp lệ và hiển thị chuỗi patternDescription.
Trường type cho phép Action API khai báo các trường đầu vào người dùng cụ thể hơn,
cung cấp xác thực phía client tốt hơn và cải thiện trải nghiệm người dùng. Trong nhiều trường hợp, type này sẽ giống với phần tử
HTML input tiêu chuẩn.
ActionParameterType có thể được đơn giản hóa thành loại sau:
/*** Input field type to present to the user* @default `text`*/export type ActionParameterType =| "text"| "email"| "url"| "number"| "date"| "datetime-local"| "checkbox"| "radio"| "textarea"| "select";
Mỗi giá trị type thông thường sẽ tạo ra một trường đầu vào người dùng giống
với phần tử HTML input tiêu chuẩn có type tương ứng (tức là
<input type="email" />) để cung cấp xác thực phía client tốt hơn và trải nghiệm người dùng tốt hơn:
text- tương đương với phần tử input "text" HTMLemail- tương đương với phần tử input "email" HTMLurl- tương đương với phần tử input "url" HTMLnumber- tương đương với phần tử input "number" HTMLdate- tương đương với phần tử input "date" HTMLdatetime-local- tương đương với phần tử input "datetime-local" HTMLcheckbox- tương đương với một nhóm các phần tử input "checkbox" HTML tiêu chuẩn. Action API nên trả vềoptionsnhư được mô tả bên dưới. Người dùng có thể chọn nhiều tùy chọn checkbox được cung cấp.radio- tương đương với một nhóm các phần tử input "radio" HTML tiêu chuẩn. Action API nên trả vềoptionsnhư được mô tả bên dưới. Người dùng chỉ có thể chọn một trong các tùy chọn radio được cung cấp.- Các loại input HTML tương đương khác không được chỉ định ở trên (
hidden,button,submit,file, v.v.) hiện chưa được hỗ trợ.
Ngoài các phần tử tương tự các loại input HTML ở trên, các phần tử nhập liệu người dùng sau đây cũng được hỗ trợ:
textarea- tương đương với phần tử textarea trong HTML. Cho phép người dùng nhập nội dung nhiều dòng.select- tương đương với phần tử select trong HTML, cho phép người dùng trải nghiệm trường kiểu "dropdown". Action API cần trả vềoptionsnhư được mô tả bên dưới.
Khi type được đặt là select, checkbox, hoặc radio, Action API
cần bao gồm một mảng options, trong đó mỗi phần tử cung cấp tối thiểu một label và một value. Mỗi tùy chọn cũng có thể có giá trị selected để thông báo cho
blink-client biết tùy chọn nào sẽ được chọn mặc định cho người dùng
(xem checkbox và radio để biết sự khác biệt).
ActionParameterSelectable này có thể được rút gọn thành định nghĩa kiểu sau:
/*** note: for ease of reading, this is a simplified type of the actual*/interface ActionParameterSelectable extends ActionParameter {options: Array<{/** displayed UI label of this selectable option */label: string;/** value of this selectable option */value: string;/** whether or not this option should be selected by default */selected?: boolean;}>;}
Nếu không có type nào được đặt hoặc một giá trị không xác định/không được hỗ trợ được đặt, blink-client nên
mặc định dùng text và hiển thị một trường nhập liệu văn bản đơn giản.
Action API vẫn có trách nhiệm xác thực và làm sạch tất cả dữ liệu từ các tham số nhập liệu của người dùng, áp dụng mọi yêu cầu nhập liệu "bắt buộc" khi cần thiết.
Đối với các nền tảng khác ngoài HTML/web (như ứng dụng di động native), nên sử dụng thành phần nhập liệu người dùng native tương đương để đạt được trải nghiệm tương đương và xác thực phía client như các loại input HTML/web được mô tả ở trên.
Ví dụ về Phản hồi GET
Ví dụ phản hồi sau đây cung cấp một action "gốc" duy nhất, dự kiến sẽ được hiển thị cho người dùng dưới dạng một nút duy nhất với nhãn "Claim Access Token":
{"title": "HackerHouse Events","icon": "<url-to-image>","description": "Claim your Hackerhouse access token.","label": "Claim Access Token" // button text}
Ví dụ phản hồi sau đây cung cấp 3 liên kết action liên quan cho phép người dùng nhấp vào một trong 3 nút để bỏ phiếu cho một đề xuất 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"}]}}
Ví dụ về Phản hồi GET với Tham số
Các ví dụ phản hồi sau đây minh họa cách chấp nhận đầu vào văn bản từ
người dùng (thông qua parameters) và đưa đầu vào đó vào endpoint POST cuối cùng
(thông qua trường href trong LinkedAction):
Ví dụ phản hồi sau đây cung cấp cho người dùng 3 action liên kết để stake SOL: một nút có nhãn "Stake 1 SOL", một nút khác có nhãn "Stake 5 SOL", và một trường nhập liệu văn bản cho phép người dùng nhập giá trị "amount" cụ thể sẽ được gửi đến 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}]}]}}
Ví dụ phản hồi sau đây cung cấp một trường nhập liệu duy nhất để người dùng
nhập amount, được gửi cùng yêu cầu POST (có thể dùng dưới dạng tham số query
hoặc subpath):
{"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}]}]}}
Yêu cầu POST
Client phải thực hiện yêu cầu HTTP POST JSON đến URL action với phần thân
có payload:
{"account": "<account>"}
account- Giá trị phải là khóa công khai được mã hóa base58 của một tài khoản có thể ký giao dịch.
Client nên thực hiện yêu cầu với header Accept-Encoding và ứng dụng có thể phản hồi với header Content-Encoding cho nén HTTP.
Client nên hiển thị tên miền của URL action trong khi yêu cầu đang được
thực hiện. Nếu đã thực hiện yêu cầu GET, client cũng nên hiển thị title
và render hình ảnh icon từ phản hồi GET đó.
Phản hồi POST
Endpoint POST của Action nên phản hồi với HTTP OK JSON
(với payload hợp lệ trong phần thân) hoặc một lỗi HTTP phù hợp.
- Client phải xử lý lỗi client, lỗi server, và phản hồi chuyển hướng.
- Endpoint nên phản hồi với
header
Content-Typelàapplication/json.
Phản hồi lỗi (tức là mã trạng thái HTTP 4xx và 5xx) nên trả về phần thân
phản hồi JSON theo ActionError để hiển thị thông báo lỗi hữu ích cho
người dùng. Xem Action Errors.
Phần thân Phản hồi POST
Phản hồi POST với HTTP OK JSON nên bao gồm phần thân payload:
/*** Response body payload returned from the Action POST Request*/export interface ActionPostResponse<T extends ActionType = ActionType> {/** base64 encoded serialized transaction */transaction: string;/** describes the nature of the transaction */message?: string;links?: {/*** The next action in a successive chain of actions to be obtained after* the previous was successful.*/next: NextActionLink;};}
-
transaction- Giá trị phải là một giao dịch đã được serialize được mã hóa base64. Client phải giải mã base64 giao dịch và deserialize nó. -
message- Giá trị phải là một chuỗi UTF-8 mô tả bản chất của giao dịch được bao gồm trong phản hồi. Client nên hiển thị giá trị này cho người dùng. Ví dụ, đây có thể là tên của một mặt hàng đang được mua, một khoản giảm giá áp dụng cho giao dịch mua, hoặc một lời cảm ơn. -
links.next- Một giá trị tùy chọn dùng để "xâu chuỗi" nhiều Action lại với nhau theo thứ tự. Sau khitransactionđược bao gồm đã được xác nhận trên chuỗi, client có thể tải và hiển thị action tiếp theo. Xem Action Chaining để biết thêm chi tiết. -
Client và ứng dụng nên cho phép các trường bổ sung trong phần thân yêu cầu và phần thân phản hồi, có thể được thêm vào bởi các bản cập nhật đặc tả trong tương lai.
Ứng dụng có thể phản hồi với một giao dịch đã được ký một phần hoặc toàn bộ. Client và ví phải xác thực giao dịch là không đáng tin cậy.
Phản hồi POST - Giao dịch
Nếu
signatures
của giao dịch trống hoặc giao dịch CHƯA được ký một phần:
- Client phải bỏ qua
feePayertrong giao dịch và đặtfeePayerthànhaccounttrong yêu cầu. - Client phải bỏ qua
recentBlockhashtrong giao dịch và đặtrecentBlockhashthành blockhash mới nhất. - Client phải serialize và deserialize giao dịch trước khi ký. Điều này đảm bảo thứ tự nhất quán của các khóa tài khoản, như một giải pháp thay thế cho vấn đề này.
Nếu giao dịch đã được ký một phần:
- Client KHÔNG được thay đổi
feePayerhoặcrecentBlockhashvì điều này sẽ làm mất hiệu lực mọi chữ ký hiện có. - Client phải xác minh các chữ ký hiện có, và nếu có bất kỳ chữ ký nào không hợp lệ, client phải từ chối giao dịch là không hợp lệ.
Client chỉ được ký giao dịch bằng account trong yêu cầu, và
chỉ được làm như vậy nếu chữ ký cho account trong yêu cầu được yêu cầu.
Nếu có bất kỳ chữ ký nào khác ngoài chữ ký cho account trong yêu cầu được
yêu cầu, client phải từ chối giao dịch là độc hại.
Action Errors
Actions API nên trả về lỗi sử dụng ActionError để hiển thị
thông báo lỗi hữu ích cho người dùng. Tùy thuộc vào ngữ cảnh, lỗi này có thể
là nghiêm trọng hoặc không nghiêm trọng.
export interface ActionError {/** simple error message to be displayed to the user */message: string;}
Khi một Actions API phản hồi với mã trạng thái lỗi HTTP (tức là 4xx và 5xx),
phần thân phản hồi nên là một payload JSON theo ActionError. Lỗi được
coi là nghiêm trọng và message được bao gồm nên được hiển thị cho người dùng.
Đối với các phản hồi API hỗ trợ thuộc tính error tùy chọn (như
ActionGetResponse), lỗi được coi là không nghiêm trọng và
message được bao gồm nên được hiển thị cho người dùng.
Action Chaining
Solana Actions có thể được "xâu chuỗi" lại với nhau theo một chuỗi liên tiếp. Sau khi giao dịch của một Action được xác nhận trên chuỗi, action tiếp theo có thể được lấy và hiển thị cho người dùng.
Action chaining cho phép các nhà phát triển xây dựng các trải nghiệm phức tạp và năng động hơn trong blink, bao gồm:
- cung cấp nhiều giao dịch (và cuối cùng là ký tin nhắn) cho người dùng
- tùy chỉnh metadata action dựa trên địa chỉ ví của người dùng
- làm mới metadata blink sau một giao dịch thành công
- nhận một callback API với chữ ký giao dịch để xác thực và logic bổ sung trên server Action API
- thông báo "thành công" tùy chỉnh bằng cách cập nhật metadata được hiển thị (ví dụ: hình ảnh và mô tả mới)
Để xâu chuỗi nhiều action lại với nhau, trong bất kỳ ActionPostResponse nào, hãy bao gồm
links.next thuộc một trong hai loại:
PostNextActionLink- Liên kết yêu cầu POST với URL callback cùng origin để nhậnsignaturevàaccountcủa người dùng trong phần thân. URL callback này nên phản hồi với mộtNextAction.InlineNextActionLink- Metadata nội tuyến cho action tiếp theo sẽ được hiển thị cho người dùng ngay sau khi giao dịch được xác nhận. Không có callback nào được thực hiện.
export type NextActionLink = PostNextActionLink | InlineNextActionLink;/** @see {NextActionPostRequest} */export interface PostNextActionLink {/** Indicates the type of the link. */type: "post";/** Relative or same origin URL to which the POST request should be made. */href: string;}/*** Represents an inline next action embedded within the current context.*/export interface InlineNextActionLink {/** Indicates the type of the link. */type: "inline";/** The next action to be performed */action: NextAction;}
NextAction
Sau khi transaction được bao gồm trong ActionPostResponse được người dùng ký và
xác nhận trên chuỗi, blink client nên:
- thực thi yêu cầu callback để tải và hiển thị
NextAction, hoặc - nếu
NextActionđã được cung cấp thông qualinks.next, blink client nên cập nhật metadata được hiển thị và không thực hiện yêu cầu callback
Nếu URL callback không cùng origin với yêu cầu POST ban đầu, thì không có yêu cầu callback nào được thực hiện. Blink client nên hiển thị thông báo lỗi cho người dùng.
/** The next action to be performed */export type NextAction = Action<"action"> | CompletedAction;/** The completed action, used to declare the "completed" state within action chaining. */export type CompletedAction = Omit<Action<"completed">, "links">;
Dựa trên type, action tiếp theo nên được hiển thị cho người dùng thông qua blink
client theo một trong các cách sau:
-
action- (mặc định) Một action tiêu chuẩn cho phép người dùng xem metadata Action được bao gồm, tương tác vớiLinkedActionsđược cung cấp, và tiếp tục xâu chuỗi các action tiếp theo. -
completed- Trạng thái kết thúc của một chuỗi action có thể cập nhật giao diện blink với metadata Action được bao gồm, nhưng sẽ không cho phép người dùng thực hiện các action tiếp theo.
Nếu links.next không được cung cấp, blink client nên giả định action hiện tại
là action cuối cùng trong chuỗi, hiển thị trạng thái giao diện "hoàn thành" sau khi
giao dịch được xác nhận.
actions.json
Mục đích của tệp actions.json là cho phép ứng dụng
hướng dẫn client về các URL trang web nào hỗ trợ Solana Actions và cung cấp một
bảng ánh xạ có thể được sử dụng để thực hiện yêu cầu GET đến một
server Actions API.
Yêu cầu header Cross-Origin
Phản hồi của tệp actions.json cũng phải trả về các header Cross-Origin hợp lệ cho
các yêu cầu GET và OPTIONS, cụ thể là giá trị header Access-Control-Allow-Origin
là *.
Xem phản hồi OPTIONS ở trên để biết thêm chi tiết.
Tệp actions.json nên được lưu trữ và có thể truy cập toàn cầu tại thư mục gốc
của tên miền.
Ví dụ, nếu ứng dụng web của bạn được triển khai tại my-site.com thì tệp
actions.json phải có thể truy cập tại https://my-site.com/actions.json.
Tệp này cũng nên có thể truy cập Cross-Origin từ bất kỳ trình duyệt nào bằng cách có giá trị
header Access-Control-Allow-Origin là *.
Rules
Trường rules cho phép ứng dụng ánh xạ một tập hợp các đường dẫn tương đối
của trang web đến một tập hợp các đường dẫn khác.
Kiểu: Array của 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- Một mẫu khớp với từng đường dẫn đến (pathname). -
apiPath- Đích đến được xác định là một đường dẫn tuyệt đối hoặc URL bên ngoài.
Quy tắc - pathPattern
Một mẫu khớp với từng đường dẫn đến (pathname). Có thể là đường dẫn tuyệt đối hoặc tương đối và hỗ trợ các định dạng sau:
-
Khớp chính xác: Khớp với đường dẫn URL chính xác.
- Ví dụ:
/exact-path - Ví dụ:
https://website.com/exact-path
- Ví dụ:
-
Khớp ký tự đại diện: Sử dụng ký tự đại diện để khớp với bất kỳ chuỗi ký tự nào trong đường dẫn URL. Có thể khớp một phân đoạn đơn (dùng
*) hoặc nhiều phân đoạn (dùng**). (xem Khớp đường dẫn bên dưới).- Ví dụ:
/trade/*sẽ khớp với/trade/123và/trade/abc, chỉ nắm bắt phân đoạn đầu tiên sau/trade/. - Ví dụ:
/category/*/item/**sẽ khớp với/category/123/item/456và/category/abc/item/def. - Ví dụ:
/api/actions/trade/*/confirmsẽ khớp với/api/actions/trade/123/confirm.
- Ví dụ:
Quy tắc - apiPath
Đường dẫn đích cho yêu cầu action. Có thể được xác định là đường dẫn tuyệt đối hoặc URL bên ngoài.
- Ví dụ:
/api/exact-path - Ví dụ:
https://api.example.com/v1/donate/* - Ví dụ:
/api/category/*/item/* - Ví dụ:
/api/swap/**
Quy tắc - Tham số truy vấn
Các tham số truy vấn từ URL gốc luôn được giữ nguyên và thêm vào URL được ánh xạ.
Quy tắc - Khớp đường dẫn
Bảng sau mô tả cú pháp cho các mẫu khớp đường dẫn:
| Toán tử | Khớp với |
|---|---|
* | Một phân đoạn đường dẫn đơn, không bao gồm ký tự phân tách đường dẫn /. |
** | Khớp với không hoặc nhiều ký tự, bao gồm cả ký tự phân tách đường dẫn / giữa nhiều phân đoạn đường dẫn. Nếu có các toán tử khác, toán tử ** phải là toán tử cuối cùng. |
? | Mẫu không được hỗ trợ. |
Ví dụ về quy tắc
Ví dụ sau minh họa quy tắc khớp chính xác để ánh xạ các yêu cầu đến /buy
từ gốc của trang web tới đường dẫn chính xác /api/buy tương đối so với gốc trang web:
{"rules": [{"pathPattern": "/buy","apiPath": "/api/buy"}]}
Ví dụ sau sử dụng khớp đường dẫn ký tự đại diện để ánh xạ các yêu cầu đến bất kỳ đường dẫn nào
(không bao gồm thư mục con) trong /actions/ từ gốc trang web tới
đường dẫn tương ứng trong /api/actions/ tương đối so với gốc trang web:
{"rules": [{"pathPattern": "/actions/*","apiPath": "/api/actions/*"}]}
Ví dụ sau sử dụng khớp đường dẫn ký tự đại diện để ánh xạ các yêu cầu đến bất kỳ đường dẫn nào
(không bao gồm thư mục con) trong /donate/ từ gốc trang web tới
đường dẫn tuyệt đối tương ứng https://api.dialect.com/api/v1/donate/ trên
trang web bên ngoài:
{"rules": [{"pathPattern": "/donate/*","apiPath": "https://api.dialect.com/api/v1/donate/*"}]}
Ví dụ sau sử dụng khớp đường dẫn ký tự đại diện cho quy tắc bất biến (idempotent) để ánh xạ
các yêu cầu đến bất kỳ đường dẫn nào (bao gồm cả thư mục con) trong /api/actions/ từ
gốc trang web tới chính nó:
Các quy tắc bất biến (idempotent) cho phép các blink client dễ dàng xác định hơn xem một đường dẫn nhất định có hỗ trợ yêu cầu Action API hay không mà không cần phải có tiền tố
solana-action:URI hoặc thực hiện kiểm tra phản hồi bổ sung.
{"rules": [{"pathPattern": "/api/actions/**","apiPath": "/api/actions/**"}]}
Action Identity
Các endpoint action có thể bao gồm một Action Identity trong các giao dịch được trả về trong phản hồi POST để người dùng ký. Điều này cho phép các indexer và nền tảng phân tích dễ dàng và có thể xác minh việc quy kết hoạt động onchain cho một Action Provider cụ thể (tức là dịch vụ) theo cách có thể xác minh.
Action Identity là một keypair được dùng để ký một thông điệp có định dạng đặc biệt được đưa vào giao dịch bằng lệnh Memo. Thông điệp định danh này có thể được quy kết một cách xác minh cho một Action Identity cụ thể, và do đó quy kết các giao dịch cho một Action Provider cụ thể.
keypair không bắt buộc phải ký giao dịch. Điều này cho phép các ví và ứng dụng cải thiện khả năng giao dịch khi không có chữ ký nào khác trên giao dịch được trả về cho người dùng (xem giao dịch phản hồi POST).
Nếu trường hợp sử dụng của Action Provider yêu cầu các dịch vụ backend của họ phải ký trước giao dịch trước khi người dùng ký, họ nên sử dụng keypair này làm Action Identity của mình. Điều này sẽ giảm được một tài khoản cần đưa vào giao dịch, giảm tổng kích thước giao dịch xuống 32 byte.
Thông điệp định danh Action
Thông điệp định danh Action là một chuỗi UTF-8 được phân tách bằng dấu hai chấm, được đưa vào giao dịch bằng một lệnh SPL Memo duy nhất.
protocol:identity:reference:signature
protocol- Giá trị của giao thức đang được sử dụng (đặt thànhsolana-actiontheo Sơ đồ URL ở trên)identity- Giá trị phải là địa chỉ khóa công khai được mã hóa base58 của keypair Action Identityreference- Giá trị phải là mảng 32 byte được mã hóa base58. Đây có thể là hoặc không phải là khóa công khai, trên hoặc ngoài đường cong, và có thể hoặc không tương ứng với các tài khoản trên Solana.signature- chữ ký được mã hóa base58 được tạo từ keypair Action Identity chỉ ký giá trịreference.
Giá trị reference chỉ được sử dụng một lần và trong một giao dịch duy nhất. Để
liên kết các giao dịch với một Action Provider, chỉ lần sử dụng đầu tiên
của giá trị reference được coi là hợp lệ.
Các giao dịch có thể có nhiều lệnh Memo. Khi thực hiện
getSignaturesForAddress, trường memo trong kết quả
sẽ trả về thông điệp của từng lệnh memo dưới dạng một chuỗi duy nhất với
mỗi thông điệp được phân tách bằng dấu chấm phẩy.
Không có dữ liệu nào khác nên được bao gồm trong lệnh Memo của Thông điệp định danh.
identity và reference nên được đưa vào dưới dạng
khóa chỉ đọc, không ký
trong giao dịch trên một lệnh KHÔNG phải là lệnh Memo của Thông điệp định danh.
Lệnh Memo của Thông điệp định danh phải có không tài khoản nào được cung cấp. Nếu có bất kỳ tài khoản nào được cung cấp, chương trình Memo yêu cầu các tài khoản này phải là các người ký hợp lệ. Với mục đích xác định các action, điều này hạn chế tính linh hoạt và có thể làm giảm trải nghiệm người dùng. Do đó, đây được coi là anti-pattern và phải tránh.
Xác minh Action Identity
Bất kỳ giao dịch nào có tài khoản identity đều có thể được xác minh
liên kết với Action Provider qua quy trình nhiều bước:
- Lấy tất cả các giao dịch cho một
identitynhất định. - Phân tích và xác minh chuỗi memo của từng giao dịch, đảm bảo
signaturelà hợp lệ choreferenceđược lưu trữ. - Xác minh giao dịch cụ thể là lần xuất hiện onchain đầu tiên của
referencetrên chuỗi:- Nếu giao dịch này là lần xuất hiện đầu tiên, giao dịch được coi là đã xác minh và có thể được quy kết an toàn cho Action Provider.
- Nếu giao dịch này KHÔNG phải là lần xuất hiện đầu tiên, nó được coi là không hợp lệ và do đó không được quy kết cho Action Provider.
Vì các validator Solana lập chỉ mục giao dịch theo các khóa tài khoản, phương thức RPC
getSignaturesForAddress
có thể được dùng để định vị tất cả các giao dịch có tài khoản identity.
Phản hồi của phương thức RPC này bao gồm tất cả dữ liệu Memo trong trường memo. Nếu
nhiều lệnh Memo được sử dụng trong giao dịch, mỗi thông điệp memo sẽ
được bao gồm trong trường memo này và phải được trình xác minh phân tích phù hợp
để lấy Thông điệp xác minh danh tính.
Các giao dịch này ban đầu nên được coi là CHƯA ĐƯỢC XÁC MINH. Điều này là do
identity không bắt buộc phải ký giao dịch, cho phép bất kỳ
giao dịch nào đưa tài khoản này vào dưới dạng không ký. Điều này có khả năng
làm tăng giả tạo số lần quy kết và số lượt sử dụng.
Thông điệp xác minh danh tính nên được kiểm tra để đảm bảo signature
được tạo bởi identity ký reference. Nếu việc xác minh chữ ký này
thất bại, giao dịch không hợp lệ và nên được quy kết cho Action Provider.
Nếu việc xác minh chữ ký thành công, trình xác minh nên đảm bảo rằng
giao dịch này là lần xuất hiện onchain đầu tiên của reference. Nếu không,
giao dịch được coi là không hợp lệ.
Is this page helpful?