Actions et Blinks
Les Actions Solana sont des API conformes aux spécifications qui retournent des transactions sur la blockchain Solana pour être prévisualisées, signées et envoyées via un certain nombre de contextes différents tels que les QR codes, les boutons + widgets et les sites Internet. Les Actions permettent aux développeurs d'intégrer facilement dans leur environnement les choses qu'il est possible de faire dans l'écosystème Solana, ce qui leur permet d'effectuer des transactions blockchain sans avoir à naviguer vers une autre application ou une autre page web.
Les liens blockchain – ou blinks – transforment toute Action Solana en un lien partageable et contenant des métadonnées. Les blinks permettent aux clients sensibles aux Actions (portefeuilles de navigateur, robots) d'afficher des fonctionnalités supplémentaires pour l'utilisateur. Par exemple, sur un site web, un blink peut immédiatement déclencher une prévisualisation de la transaction dans un portefeuille sans passer par une application décentralisée ou encore sur Discord où un robot peut étendre le blink en un ensemble de boutons interactif. La possibilité d'interagir avec la chaîne est ainsi étendue à toute interface web capable d'afficher une URL.
Get Started #
To quickly get started with creating custom Solana Actions:
npm install @solana/actions
- install the Solana Actions SDK in your application
- build an API endpoint for the GET request that returns the metadata about your Action
- create an API endpoint that accepts the POST request and returns the signable transaction for the user
Checkout this video tutorial on
how to build a Solana Action
using the @solana/actions
SDK.
You can also find the source code for an Action that performs a native SOL transfer here and several other example Actions in this repo.
When deploying your custom Solana Actions to production:
- ensure your application has a valid actions.json file at the root of your domain
- ensure your application responds with the
required Cross-Origin headers on all Action endpoints,
including the
actions.json
file
If you are looking for inspiration around building Actions and blinks, checkout the Awesome Blinks repository for some community creations and even ideas for new ones.
Actions #
La spécification des Actions Solana utilise un ensemble d'API standard pour retourner des transactions pouvant être signées (et éventuellement des messages pouvant être signés) à partir d'une application directement à un utilisateur. Ils sont hébergés sur des URL accessibles au public et sont donc accessibles par leur URL à tout client qui souhaite interagir avec eux.
Vous pouvez considérer les Actions comme un point de terminaison de l'API qui retournera des métadonnées et quelque chose qu'un utilisateur pourra signer (une transaction ou un message d'authentification) avec son portefeuille blockchain.
L'API Actions consiste à effectuer de simples requêtes GET
et POST
à
l'adresse URL d'une Action et à traiter les réponses conformément à l'interface
Actions.
- la requête GET retourne des métadonnées qui fournissent au client des informations lisibles par l'homme sur les actions disponibles à cette URL, ainsi qu'une liste facultative d'actions associées.
- la requête POST retourne une transaction ou un message pouvant être signé que le client demande ensuite au portefeuille de l'utilisateur de signer et d'exécuter sur la blockchain ou sur un autre service hors chaîne.
Exécution et Cycle de vie des Actions #
En pratique, l'interaction avec les Actions ressemble beaucoup à l'interaction avec une API REST classique :
- un client fait une requête
GET
initiale à une URL d'Action afin d'obtenir les métadonnées sur les actions disponibles - le point de terminaison retourne une réponse qui contient les métadonnées relatives au point de terminaison (comme le titre et l'icône de l'application) et une liste des actions disponibles pour ce point de terminaison
- l'application client (comme un portefeuille mobile, un chat bot ou un site web) affiche une interface utilisateur permettant à l'utilisateur d'effectuer l'une des actions
- après que l'utilisateur a sélectionné une action (en cliquant sur un bouton),
le client envoie une requête
POST
au point de terminaison afin d'obtenir la transaction à faire signer par l'utilisateur - le portefeuille permet à l'utilisateur de signer la transaction et envoie finalement la transaction à la blockchain pour confirmation
Solana Actions Execution and Lifecycle
Lorsqu'ils reçoivent des transactions d'une URL d'Actions, les clients doivent se charger de la soumission de ces transactions à la blockchain et gérer le cycle de vie de leur état.
Les Actions supportent également un certain niveau d'invalidation avant
l'exécution. Les requêtes GET
et POST
peuvent retourner des métadonnées
indiquant si l'action peut être réalisée (comme avec le champ disabled
).
Par exemple, s'il existe un point de terminaison Action qui permet de voter sur une proposition de gouvernance d'une DAO dont la fenêtre de vote est fermée, la requête GET initiale peut retourner le message d'erreur "Cette proposition n'est plus soumise au vote" et les boutons "Voter Oui" et "Voter Non" comme étant "désactivés".
Blinks #
Les Blinks (liens blockchain) sont des applications client qui analysent les API d'Action et construisent des interfaces utilisateur permettant d'interagir avec les Actions et de les exécuter.
Les applications client qui prennent en charge les blinks ne font que détecter les URL compatibles avec les Actions, les analyser et permettre aux utilisateurs d'interagir avec eux au moyen d'interfaces utilisateur standardisées.
Toute application client qui analyse en profondeur une API d'Actions pour en construire une interface complète est un blink. Par conséquent, tous les clients qui utilisent des API d'Actions ne sont pas forcément des blinks.
Spécification d'une URL Blink #
Une URL blink décrit une application client qui permet à un utilisateur d'effectuer le cycle de vie complet de l'exécution d'une Action, y compris la signature avec son portefeuille.
https://example.domain/?action=<action_url>
Pour qu'une application client devienne un blink :
-
L'URL blink doit contenir un paramètre de requête
action
dont la valeur est une URL d'Action encodée. Cette valeur doit être encodée pour ne pas entrer en conflit avec d'autres paramètres du protocole. -
L'application client doit décoder le paramètre de requête
action
et analyser le lien de l'API Action fourni (voir schéma d'URL d'Action). -
Le client doit afficher une interface utilisateur riche qui permet à un utilisateur d'effectuer le cycle de vie complet de l'exécution d'une Action, y compris la signature avec son portefeuille.
Toutes les applications client blink (ex. sites Web ou dApps) ne prendront pas en charge toutes les Actions. En effet, les développeurs d'applications peuvent choisir les Actions qu'ils souhaitent prendre en charge dans leurs interfaces blink.
L'exemple suivant montre une URL blink valide avec une valeur action
égale à
solana-action:https://actions.alice.com/donate
qui est encodée dans l'URL :
https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2Fdonate
Détection des Actions via Blinks #
Les blinks peuvent être liés à des Actions d'au moins 3 façons :
-
Partage d'une URL d'Action explicite :
solana-action:https://actions.alice.com/donate
Dans ce cas, seuls les clients pris en charge peuvent rendre le blink. Il n'y aura pas de prévisualisation de lien de remplacement, ni de site pouvant être visité en dehors du client non supporté.
-
Partage d'un lien vers un site web lié à une API Actions via un fichier
actions.json
présent à la racine du domaine du site web.Par exemple,
https://alice.com/actions.json
associehttps://alice.com/donate
, URL d'un site web où les utilisateurs peuvent faire un don à Alice, à l'URL de l'APIhttps://actions.alice.com/donate
, où sont hébergées les Actions permettant de faire un don à Alice. -
Intégration d'une URL d'Action dans l'URL d'un site "interstitiel" qui comprend comment analyser les Actions.
https://example.domain/?action=<action_url>
Les clients qui prennent en charge les blinks doivent être en mesure d'accepter l'un des formats ci-dessus et d'afficher correctement une interface pour faciliter l'exécution de l'action directement dans le client.
Pour les clients qui ne prennent pas en charge les blinks, il doit y avoir un site web sous-jacent (le navigateur devenant ainsi la solution de remplacement universelle).
Si un utilisateur appuie sur un élément du client qui n'est pas un bouton d'action ou un champ de saisie de texte, il doit être redirigé vers le site sous-jacent.
Test et Vérification d'un Blink #
Bien que les Actions Solana et les blinks soient un protocole/une spécification ne nécessitant pas de permission (permissionless), les applications client et les portefeuilles sont toujours nécessaires pour faciliter la signature des transactions par les utilisateurs.
Chacune de ces applications client ou portefeuilles peut avoir des exigences différentes concernant les points de terminaison d'Action que leurs clients déploieront automatiquement et afficheront immédiatement à leurs utilisateurs sur les plateformes de médias sociaux.
Par exemple, certains clients peuvent fonctionner selon une approche de "liste d'autorisation" qui peut nécessiter une vérification avant que le client ne déploie une Action pour des utilisateurs tel que le Registre d'Actions de Dialect (détaillé ci-dessous).
Tous les blinks seront toujours affichés et permettront de signer sur le site interstitiel de blinks dial.to de Dialect avec leur statut d'enregistrement affiché dans le blink.
Registre d'Actions de Dialect #
En tant que bien public pour l'écosystème Solana, Dialect maintient un registre public - avec l'aide de la Fondation Solana et d'autres membres de la communauté - des liens blockchain qui ont été pré-vérifiés à partir de sources connues. Dès le lancement, seules les Actions enregistrées dans le registre de Dialect se déploieront dans le fil Twitter lorsqu'elles seront publiées.
Les applications client et les portefeuilles peuvent librement choisir d'utiliser ce registre public ou une autre solution pour garantir la sécurité des utilisateurs. S'il n'est pas vérifié par le registre Dialect, le lien blockchain ne sera pas touché par le client blink et sera rendu comme une URL classique.
Les développeurs peuvent demander à être vérifiés par Dialect ici : dial.to/register
Spécification #
La spécification des Actions Solana consiste en des sections clés qui font partie d'un flux d'interaction de requête/réponse :
- Schéma d'URL d'Action Solana fournissant une URL d'Action
- Réponse OPTIONS à une URL d'Action pour passer les exigences CORS
- Requête GET à une URL d'Action
- Réponse GET du serveur
- Requête POST à une URL d'Action
- Réponse POST du serveur
Chacune de ces requêtes est effectuée par le client d'Action (par exemple application de portefeuille, extension de navigateur, dApp, site web, etc.) afin de recueillir des métadonnées spécifiques pour les interfaces utilisateur enrichies et pour faciliter la saisie de l'utilisateur dans l'API d'Actions.
Chacune des réponses est élaborée par une application (site web, serveur backend, etc.) et renvoyée au client d'Action. Finalement, elle fournit une transaction ou un message pouvant être signé par un portefeuille et invite l'utilisateur à l'approuver, le ou la signer et à l'envoyer à la blockchain.
Schéma d'URL #
Une URL d'Action Solana décrit une requête interactive pour une transaction ou
un message Solana pouvant être signé, en utilisant le protocole solana-action
.
La requête est interactive car les paramètres de l'URL sont utilisés par un client pour effectuer une série de requêtes HTTP standardisées afin de composer une transaction ou un message pouvant être signé par l'utilisateur à l'aide de son portefeuille.
solana-action:<link>
-
Un seul champ
link
est requis comme chemin d'accès. La valeur doit être une URL HTTPS absolue encodée de manière conditionnelle. -
Si l'URL contient des paramètres de requête, elle doit être encodée. L'encodage de la valeur permet d'éviter tout conflit avec les paramètres du protocole Actions qui peuvent être ajoutés via la spécification du protocole.
-
Si l'URL ne contient pas de paramètres de requête, elle ne doit pas être encodée. Il en résulte une URL plus courte et un QR code moins dense.
Dans les deux cas, les clients doivent décoder la valeur. Cela n'a aucun effet si la valeur n'est pas encodée. Si la valeur décodée n'est pas une URL HTTPS absolue, le portefeuille doit la rejeter comme étant malformée.
Réponse OPTIONS #
Afin de permettre le Cross-Origin Resource Sharing
(CORS) dans les
clients Actions (y compris les blinks), tous les points de terminaison Action
doivent répondre aux requêtes HTTP par la méthode OPTIONS
avec des en-têtes
valides ce qui permettra aux clients de passer les contrôles CORS pour toutes
les requêtes ultérieures provenant du même domaine d'origine.
Un client Actions peut effectuer des demandes de
"contrôle préalable"
au point de terminaison de l'URL d'Action afin de vérifier si la demande GET
ultérieure à l'URL d'Action passera toutes les vérifications CORS. Ces contrôles
préalables CORS sont effectués à l'aide de la méthode HTTP OPTIONS
et doivent
répondre avec tous les en-têtes HTTP nécessaires pour permettre aux clients
Action (comme les blinks) d'effectuer correctement toutes les requêtes
ultérieures à partir de leur domaine d'origine.
Au minimum, les en-têtes HTTP requis sont les suivants :
Access-Control-Allow-Origin
avec une valeur de*
- cela permet de s'assurer que tous les clients Action peuvent passer les contrôles CORS en toute sécurité afin d'effectuer toutes les requêtes nécessaires
Access-Control-Allow-Methods
avec une valeur deGET,POST,PUT,OPTIONS
- cela permet de s'assurer que toutes les méthodes de requête HTTP requises sont prises en charge par les Actions
Access-Control-Allow-Headers
avec une valeur minimum deContent-Type, Authorization, Content-Encoding, Accept-Encoding
Pour des raisons de simplicité, les développeurs devraient envisager de
retourner la même réponse et les mêmes en-têtes aux requêtes OPTIONS
que leur
réponse GET
.
The actions.json
file response must also return valid Cross-Origin headers for
GET
and OPTIONS
requests, specifically the Access-Control-Allow-Origin
header value of *
.
See actions.json below for more details.
Requête GET #
Le client d'Action (par exemple portefeuille, extension de navigateur, etc.)
doit effectuer une requête JSON HTTP GET
au point de terminaison de l'URL
d'Action.
- La requête ne doit pas identifier le portefeuille ou l'utilisateur.
- Le client doit faire la requête avec un
en-tête
Accept-Encoding
. - Le client doit afficher le domaine de l'URL lors de la requête.
Réponse GET #
Le point de terminaison de l'URL d'Action (par exemple application ou serveur
backend) doit répondre par une réponse JSON HTTP OK
(avec une charge utile
valide dans le corps) ou par une erreur HTTP appropriée.
-
Le client doit gérer les erreurs de client HTTP, les erreurs de serveur et les réponses de redirection.
-
Le point de terminaison doit répondre avec un en-tête
Content-Encoding
pour la compression HTTP. -
Le point de terminaison doit répondre avec un en-tête
Content-Type
de typeapplication/json
. -
Le client ne doit pas mettre la réponse en cache, sauf si les en-têtes de réponse HTTP de mise en cache l'indiquent.
-
Le client doit afficher le
title
et rendre l'imageicon
à l'utilisateur.
Corps de la réponse GET #
Une réponse GET
avec une réponse JSON HTTP OK
doit inclure dans le corps une
charge utile conforme à la spécification de l'interface :
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
- La valeur doit être une URL HTTP ou HTTPS absolue d'une image d'icône. Le fichier doit être une image SVG, PNG ou WebP, sinon le client/le portefeuille doit le rejeter comme étant malformé. -
title
- La valeur doit être une chaîne UTF-8 qui représente la source de la requête d'action. Il peut s'agir, par exemple, du nom d'une marque, d'un magasin, d'une application ou de la personne qui fait la requête. -
description
- La valeur doit être une chaîne UTF-8 qui fournit des informations sur l'action. La description doit être affichée à l'utilisateur. -
label
- La valeur doit être une chaîne UTF-8 qui sera affichée sur un bouton sur lequel l'utilisateur pourra cliquer. Toutes les étiquettes (labels) ne doivent pas dépasser 5 mots et doivent commencer par un verbe pour renforcer l'action que vous voulez que l'utilisateur fasse. Par exemple, "Mint NFT", "Votez Oui" ou "Staker 1 SOL". -
disabled
- La valeur doit être un booléen pour représenter l'état désactivé du bouton affiché (qui affiche la chaînelabel
). Si aucune valeur n'est fournie, la valeur par défaut dedisabled
estfalse
(c'est-à-dire activée par défaut). Par exemple, si le point de terminaison de l'action concerne un vote de gouvernance qui a été clôturé, définissezdisabled=true
et lelabel
pourrait être "Vote Clôturé". -
error
- Une indication d'erreur facultative pour les erreurs non fatales. Si l'indication est présente, le client doit l'afficher à l'utilisateur. Si défini, cela ne doit pas empêcher le client d'interpréter l'action ou de l'afficher à l'utilisateur. Par exemple, l'erreur peut être utilisée avecdisabled
pour afficher une raison comme des contraintes commerciales, une autorisation, un état ou une erreur de ressource externe.
export interface ActionError {
/** non-fatal error message to be displayed to the user */
message: string;
}
-
links.actions
- Un tableau optionnel d'actions associées au point de terminaison. Une interface utilisateur doit présenter aux utilisateurs chacune des actions listées et il doit leur être demandé de n'en effectuer qu'une seule. Par exemple, un point de terminaison d'action de vote de gouvernance peut renvoyer trois options à l'utilisateur : "Voter Oui", "Voter Non" et "S'abstenir de Voter".-
Si aucun
links.actions
n'est fourni, le client doit afficher un seul bouton en utilisant la chaînelabel
de la racine et envoyer une requête POST au même point de terminaison de l'URL d'action que la requête GET initiale. -
Si des
links.actions
sont fournis, le client ne doit afficher les boutons et les champs de saisie qu'en fonction des éléments listés dans le champlinks.actions
. Le client ne doit donc pas afficher de bouton pour le contenu dulabel
de la racine.
-
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;
}
Exemple de réponse GET #
L'exemple de réponse suivant fournit une action "root" unique qui doit être présentée à l'utilisateur sous la forme d'un bouton unique intitulé "Claim Access Token" (Réclamer un Jeton d'Accès) :
{
"title": "HackerHouse Events",
"icon": "<url-to-image>",
"description": "Claim your Hackerhouse access token.",
"label": "Claim Access Token" // button text
}
L'exemple de réponse suivant fournit 3 liens d'action associée qui permettent à l'utilisateur de cliquer sur l'un des 3 boutons pour voter lors d'une proposition de 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"
}
]
}
}
Exemple de réponse GET avec Paramètres #
Les exemples de réponse suivants montrent comment accepter une saisie de texte
de la part de l'utilisateur (via des parameters
(paramètres)) et inclure cette
saisie dans le point de terminaison de la requête POST finale (via le champ
href
d'une LinkedAction
) :
L'exemple de réponse suivant fournit à l'utilisateur 3 actions associées pour staker des SOL : un bouton libellé "Staker 1 SOL", un autre bouton libellé "Staker 5 SOL" et un champ de saisie de texte qui permet à l'utilisateur d'entrer une valeur spécifique de "amount" (montant) qui sera envoyée à l'API d'Action :
{
"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
}
]
}
]
}
}
L'exemple de réponse suivant fournit un champ de saisie unique permettant à
l'utilisateur d'entrer un amount
(montant) qui est envoyé avec la requête POST
(soit en tant que paramètre de requête, soit en tant que sous-chemin) :
{
"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
}
]
}
]
}
}
Requête POST #
Le client doit faire une requête JSON HTTP POST
à l'URL de l'action avec dans
le corps une charge utile contenant :
{
"account": "<account>"
}
account
- La valeur doit être la clé publique encodée en base58 d'un compte qui peut signer la transaction.
Le client doit faire la requête avec un en-tête Accept-Encoding et l'application peut répondre avec un en-tête Content-Encoding pour la compression HTTP.
Le client doit afficher le domaine de l'URL de l'action lorsque la requête est
effectuée. Si une requête GET
a été faite, le client doit également afficher
le title
et afficher l'image icon
de cette réponse GET.
Réponse POST #
Le point de terminaison POST
de l'Action doit répondre par une réponse JSON
HTTP OK
(avec une charge utile valide dans le corps) ou par une erreur HTTP
appropriée.
- Le client doit gérer les erreurs de client HTTP, les erreurs de serveur et les réponses de redirection.
- Le point de terminaison doit répondre avec un
en-tête
Content-Type
de typeapplication/json
.
Corps de la réponse POST #
Une réponse POST
avec une réponse JSON HTTP OK
doit inclure dans le corps de
la charge utile :
export interface ActionPostResponse {
/** base64 encoded serialized transaction */
transaction: string;
/** describes the nature of the transaction */
message?: string;
}
-
transaction
- La valeur doit être une transaction sérialisée encodée en base64. Le client doit décoder la transaction en base64 et la désérialiser. -
message
- La valeur doit être une chaîne UTF-8 décrivant la nature de la transaction incluse dans la réponse. Le client doit afficher cette valeur à l'utilisateur. Il peut s'agir, par exemple, du nom d'un article acheté, d'une réduction appliquée lors d'un achat ou d'une note de remerciement. -
Le client et l'application doivent autoriser des champs supplémentaires dans le corps de la requête et dans le corps de la réponse qui pourront être ajoutés par de futures mises à jour de la spécification.
L'application peut répondre par une transaction partiellement ou totalement signée. Le client et le portefeuille doivent valider la transaction comme étant non fiable.
Réponse POST - Transaction #
Si les
signatures
de la transaction sont vides ou si la transaction n'a PAS été partiellement
signée :
- Le client doit ignorer
feePayer
présent dans la transaction et fixerfeePayer
à la valeur duaccount
indiquée dans la requête. - Le client doit ignorer
recentBlockhash
présent dans la transaction et fixerrecentBlockhash
à la valeur du dernier blockhash. - Le client doit sérialiser et désérialiser la transaction avant de la signer. Cela permet d'assurer un ordre cohérent des clés de compte et constitue une solution de contournement à ce problème.
Si la transaction a été partiellement signée :
- Le client ne doit PAS modifier
feePayer
ourecentBlockhash
car cela invaliderait les signatures existantes. - Le client doit vérifier les signatures existantes, et si l'une d'entre elles n'est pas valide, il doit rejeter la transaction comme étant malformée.
Le client ne doit signer la transaction qu'avec le account
indiqué dans la
requête, et ne doit le faire que si une signature pour le account
indiqué dans
la requête est attendue.
Si une signature autre que celle du account
présent dans la requête est
attendue, le client doit rejeter la transaction comme étant malveillante.
actions.json #
L'objectif du fichier actions.json
est de permettre à une
application d'indiquer aux clients quelles URL de sites web prennent en charge
les Actions Solana et de fournir un mappage qui peut être utilisé pour effectuer
des requêtes GET à un serveur API d'Actions.
The actions.json
file response must also return valid Cross-Origin headers for
GET
and OPTIONS
requests, specifically the Access-Control-Allow-Origin
header value of *
.
See OPTIONS response above for more details.
Le fichier actions.json
doit être stocké et universellement accessible à la
racine du domaine.
Par exemple, si votre application web est déployée à l'adresse my-site.com
alors le fichier actions.json
doit être accessible à l'adresse
https://my-site.com/actions.json
. This file should also be Cross-Origin
accessible via any browser by having a Access-Control-Allow-Origin
header
value of *
.
Règles #
Le champ rules
(règles) permet à l'application de mapper un ensemble de
chemins d'accès relatifs d'un site web à un ensemble d'autres chemins d'accès.
Type: Array
de 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
- Un modèle qui correspond à chaque chemin d'accès entrant. -
apiPath
- Une destination définie comme un chemin d'accès absolu ou une URL externe.
Règles - pathPattern #
Un modèle qui correspond à chaque chemin d'accès entrant. Il peut s'agir d'un chemin absolu ou relatif et prend en charge les formats suivants :
-
Exact Match (Correspondance Exacte) : Correspond au chemin d'accès exact de l'URL.
- Exemple :
/exact-path
- Exemple :
https://website.com/exact-path
- Exemple :
-
Wildcard Match (Correspondance avec des Caractères Génériques) : Utilise des caractères génériques pour correspondre à n'importe quelle séquence de caractères dans le chemin d'accès de l'URL. Il peut s'agir d'un seul segment (en utilisant
*
) ou de plusieurs segments (en utilisant**
). (voir Correspondance des Chemins ci-dessous).- Exemple :
/trade/*
correspondra à/trade/123
et à/trade/abc
, capturant seulement le premier segment après/trade/
. - Exemple :
/category/*/item/**
correspondra à/category/123/item/456
et à/category/abc/item/def
. - Exemple :
/api/actions/trade/*/confirm
correspondra à/api/actions/trade/123/confirm
.
- Exemple :
Règles - apiPath #
Le chemin de destination de la requête d'action. Il peut être défini comme un nom de chemin absolu ou une URL externe.
- Exemple :
/api/exact-path
- Exemple :
https://api.example.com/v1/donate/*
- Exemple :
/api/category/*/item/*
- Exemple :
/api/swap/**
Règles - Paramètres de Requête #
Les paramètres de requête de l'URL d'origine sont toujours conservés et ajoutés à l'URL mappée.
Règles - Correspondance des Chemins #
Le tableau suivant présente la syntaxe des modèles de correspondance de chemin :
Opérateur | Correspondance |
---|---|
* | Un seul segment de chemin sans inclure le séparateur de chemin / caractères environnant. |
** | Correspond à zéro ou plusieurs caractères, y compris tout séparateur de chemin / caractères entre plusieurs segments de chemin. Si d'autres opérateurs sont inclus, l'opérateur ** doit être le dernier opérateur. |
? | Modèle non pris en charge. |
Exemples de règles #
L'exemple suivant montre une règle de correspondance exacte pour mapper les
requêtes /buy
depuis la racine de votre site au chemin exact /api/buy
relatif à la racine de votre site :
{
"rules": [
{
"pathPattern": "/buy",
"apiPath": "/api/buy"
}
]
}
L'exemple suivant utilise la correspondance des chemins d'accès avec des
caractères génériques pour faire correspondre les requêtes à n'importe quel
chemin d'accès (en excluant les sous-répertoires) sous /actions/
depuis la
racine de votre site à un chemin d'accès correspondant sous /api/actions/
relatif à la racine de votre site :
{
"rules": [
{
"pathPattern": "/actions/*",
"apiPath": "/api/actions/*"
}
]
}
L'exemple suivant utilise la correspondance des chemins d'accès avec des
caractères génériques pour faire correspondre les requêtes à n'importe quel
chemin d'accès (en excluant les sous-répertoires) sous /donate/
depuis la
racine de votre site à un chemin d'accès absolu correspondant,
https://api.dialect.com/api/v1/donate/\`, sur un site externe :
{
"rules": [
{
"pathPattern": "/donate/*",
"apiPath": "https://api.dialect.com/api/v1/donate/*"
}
]
}
L'exemple suivant utilise la correspondance des chemins d'accès avec des
caractères génériques pour une règle idempotente pour faire correspondre les
requêtes à n'importe quel chemin d'accès (y compris les sous-répertoires) sous
/api/actions/
de la racine de votre site à lui-même :
Les règles idempotentes permettent aux clients blink de déterminer plus
facilement si un chemin donné prend en charge les requêtes de l'API Action
sans avoir à être préfixé par l'URI solana-action:
ou à effectuer des tests
de réponse supplémentaires.
{
"rules": [
{
"pathPattern": "/api/actions/**",
"apiPath": "/api/actions/**"
}
]
}
Identité d'Action #
Les points de terminaison d'Action peuvent inclure une Action Identity (Identité d'Action) dans les transactions qui sont retournées dans leur réponse POST que l'utilisateur doit signer. Cela permet aux indexeurs et aux plateformes d'analyse d'attribuer facilement et de manière vérifiable l'activité sur la chaîne à un Action Provider (Fournisseur d'Action) en particulier (c'est-à-dire un service).
L'Identité d'Action est une paire de clés utilisée pour signer un message spécifiquement formaté qui est inclus dans la transaction à l'aide d'une instruction Memo. Ce Identifier Message (Message d'Identification) peut être attribué de manière vérifiable à une Identité d'Action en particulier, et donc attribuer des transactions à un Fournisseur d'Action en particulier.
La paire de clés n'est pas nécessaire pour signer la transaction. Cela permet aux portefeuilles et aux applications d'améliorer la délivrabilité des transactions lorsqu'aucune autre signature ne figure dans la transaction retournée à l'utilisateur (voir Réponse POST - Transaction).
Si le cas d'utilisation d'un Fournisseur d'Action nécessite que ses services backend pré-signent la transaction avant l'utilisateur, il doit utiliser cette paire de clés comme Identité d'Action. Cela permettra d'inclure un compte de moins dans la transaction, réduisant la taille totale de la transaction de 32 octets.
Message d'Identification d'Action #
Le Message d'Identification d'Action est une chaîne UTF-8 séparée par deux points, incluse dans une transaction à l'aide d'une seule instruction SPL Memo.
protocol:identity:reference:signature
protocol
- La valeur du protocole utilisé (fixé àsolana-action
selon le Schéma d'URL ci-dessus)identity
- La valeur doit être l'adresse de la clé publique encodée en base58 de la paire de clés de l'Identité d'Actionreference
- La valeur doit être un tableau de 32 octets encodé en base58. Il peut s'agir ou non de clés publiques, sur ou en dehors de la courbe, et correspondre ou non à des comptes sur Solana.signature
- signature encodée en base58 créée à partir de la paire de clés de l'Identité d'Action et signant uniquement la valeurreference
.
La valeur reference
ne doit être utilisée qu'une seule fois et dans une seule
transaction. Afin d'associer des transactions à un Fournisseur d'Actions, seule
la première utilisation de la valeur reference
est considérée comme valide.
Les transactions peuvent avoir plusieurs instructions Mémo. Lors de l'exécution
d'un
getSignaturesForAddress
,
le champ memo
résultant retournera le message de chaque instruction memo sous
la forme d'une chaîne unique, chaque instruction étant séparée par un
point-virgule.
Aucune autre donnée ne doit être incluse dans l'instruction Memo du Message d'Identification.
L'identity
et la reference
doivent être incluses en tant que
clés
en lecture seule et non signataires dans la transaction sur une instruction qui
n'est PAS l'instruction Memo du Message d'Identification.
L'instruction Memo du Message d'Identification doit avoir aucun compte fourni. Si des comptes sont fournis, le programme Memo exige que ces comptes soient des signataires valides. Pour identifier les actions, cela limite la flexibilité et peut dégrader l'expérience utilisateur. C'est pourquoi il est considéré comme un anti-modèle et doit être évité.
Vérification de l'Identité d'Action #
Toute transaction qui inclut le compte identity
peut être associée de manière
vérifiable au Fournisseur d'Actions grâce à un processus en plusieurs étapes :
- Obtenir toutes les transactions pour une
identity
donnée. - Analyser et vérifier la chaîne mémo de chaque transaction, en s'assurant que
la
signature
est valide pour lareference
stockée. - Vérifier que la transaction en question est la première occurrence sur la
chaine de la
reference
:- Si cette transaction est la première occurrence, la transaction est considérée comme vérifiée et peut être attribuée en toute sécurité au Fournisseur d'Actions.
- Si cette transaction n'est PAS la première occurrence, elle est considérée comme invalide et n'est donc pas attribuée au Fournisseur d'Actions.
Comme les validateurs Solana indexent les transactions selon les clés de compte,
la méthode RPC
getSignaturesForAddress
peut être utilisée pour localiser toutes les transactions incluant le compte
identity
.
La réponse de cette méthode RPC inclut toutes les données Memo dans le champ
memo
. Si plusieurs instructions Memo ont été utilisées dans la transaction,
chaque message memo sera inclus dans le champ memo
et devra être analysé en
conséquence par le vérificateur afin d'obtenir le Identity Verification Message
(Message de Vérification d'Identité).
Ces transactions doivent être initialement considérées comme NON VÉRIFIÉES.
Cela est dû au fait que l'identity
n'est pas requise pour signer la
transaction, ce qui permet à toute transaction d'inclure ce compte en tant que
non-signataire. Cela peut ainsi potentiellement gonfler artificiellement le
nombre d'attributions et d'utilisations.
Le Message de Vérification d'Identité doit être vérifié pour s'assurer que la
signature
a été créée par l'identity
qui signe la reference
. Si la
vérification de la signature échoue, la transaction n'est pas valide et doit
être attribuée au Fournisseur d'Action.
Si la vérification de la signature réussie, le vérificateur doit s'assurer que
cette transaction est la première occurrence sur la chaîne de la reference
. Si
ce n'est pas le cas, la transaction est considérée comme invalide.