Actions και Blinks

Τα Solana Actions είναι APIs συμβατά με προδιαγραφές που επιστρέφουν συναλλαγές στο blockchain της Solana για προεπισκόπηση, υπογραφή και αποστολή σε ποικίλα πλαίσια, συμπεριλαμβανομένων QR codes, κουμπιών + widgets και ιστοσελίδων σε όλο το διαδίκτυο. Τα Actions διευκολύνουν τους developers να ενσωματώσουν ό,τι μπορείτε να κάνετε στο οικοσύστημα της Solana απευθείας στο περιβάλλον σας, επιτρέποντάς σας να εκτελείτε συναλλαγές blockchain χωρίς να χρειάζεται να μεταβείτε σε διαφορετική εφαρμογή ή ιστοσελίδα.

Οι blockchain links – ή blinks – μετατρέπουν οποιοδήποτε Solana Action σε ένα κοινοποιήσιμο link πλούσιο σε μεταδεδομένα. Τα Blinks επιτρέπουν σε clients που αναγνωρίζουν Actions (πορτοφόλια επεκτάσεων προγράμματος περιήγησης, bots) να εμφανίζουν πρόσθετες δυνατότητες για τον χρήστη. Σε έναν ιστότοπο, ένα blink μπορεί να ενεργοποιήσει αμέσως προεπισκόπηση συναλλαγής σε ένα πορτοφόλι χωρίς μετάβαση σε αποκεντρωμένη εφαρμογή· στο Discord, ένα bot μπορεί να αναπτύξει το blink σε ένα διαδραστικό σύνολο κουμπιών. Αυτό μεταφέρει τη δυνατότητα αλληλεπίδρασης onchain σε οποιαδήποτε web επιφάνεια που μπορεί να εμφανίσει ένα URL.

Ξεκινώντας

Για να ξεκινήσετε γρήγορα με τη δημιουργία προσαρμοσμένων Solana Actions:

npm install @solana/actions
  • εγκαταστήστε το Solana Actions SDK στην εφαρμογή σας
  • δημιουργήστε ένα API endpoint για το GET request που επιστρέφει τα μεταδεδομένα σχετικά με το Action σας
  • δημιουργήστε ένα API endpoint που δέχεται το POST request και επιστρέφει την υπογράψιμη συναλλαγή για τον χρήστη

Δείτε αυτό το βίντεο tutorial για πώς να δημιουργήσετε ένα Solana Action χρησιμοποιώντας το SDK @solana/actions.

Μπορείτε επίσης να βρείτε τον πηγαίο κώδικα για ένα Action που εκτελεί μεταφορά εγγενούς SOL εδώ και αρκετά άλλα παραδείγματα Actions στο αυτό το repo.

Κατά την ανάπτυξη των προσαρμοσμένων Solana Actions σας σε παραγωγή:

  • βεβαιωθείτε ότι η εφαρμογή σας διαθέτει έγκυρο αρχείο actions.json στο ριζικό κατάλογο του domain σας
  • βεβαιωθείτε ότι η εφαρμογή σας απαντά με τα απαιτούμενα Cross-Origin headers σε όλα τα Action endpoints, συμπεριλαμβανομένου του αρχείου actions.json
  • δοκιμάστε και αποσφαλματώστε τα blinks/actions σας χρησιμοποιώντας το Blinks Inspector

Αν αναζητάτε έμπνευση για τη δημιουργία Actions και blinks, δείτε το αποθετήριο Awesome Blinks για δημιουργίες της κοινότητας και ακόμα ιδέες για νέα.

Actions

Η προδιαγραφή Solana Actions χρησιμοποιεί ένα σύνολο τυπικών APIs για την παράδοση υπογράψιμων συναλλαγών (και τελικά υπογράψιμων μηνυμάτων) από μια εφαρμογή απευθείας σε έναν χρήστη. Φιλοξενούνται σε δημόσια προσβάσιμα URLs και είναι επομένως προσβάσιμα μέσω του URL τους από οποιονδήποτε client.

Μπορείτε να σκεφτείτε τα Actions ως ένα API endpoint που επιστρέφει μεταδεδομένα και κάτι για να υπογράψει ο χρήστης (είτε συναλλαγή είτε μήνυμα ταυτοποίησης) με το πορτοφόλι blockchain του.

Το Actions API αποτελείται από απλά GET και POST requests στο URL endpoint ενός Action και την επεξεργασία των αποκρίσεων που συμμορφώνονται με τη διεπαφή Actions.

  1. το GET request επιστρέφει μεταδεδομένα που παρέχουν αναγνώσιμες από τον άνθρωπο πληροφορίες στον client σχετικά με τα διαθέσιμα actions σε αυτό το URL, και μια προαιρετική λίστα σχετικών actions.
  2. το POST request επιστρέφει μια υπογράψιμη συναλλαγή ή μήνυμα που ο client στη συνέχεια ζητά από το πορτοφόλι του χρήστη να υπογράψει και να εκτελέσει στο blockchain ή σε άλλη υπηρεσία offchain.

Εκτέλεση και Κύκλος Ζωής Action

Στην πράξη, η αλληλεπίδραση με τα Actions μοιάζει στενά με την αλληλεπίδραση με ένα τυπικό REST API:

  • ο client κάνει το αρχικό GET request σε ένα Action URL για να λάβει μεταδεδομένα σχετικά με τα διαθέσιμα Actions
  • το endpoint επιστρέφει μια απόκριση που περιλαμβάνει μεταδεδομένα σχετικά με το endpoint (όπως τον τίτλο και το εικονίδιο της εφαρμογής) και μια λίστα με τα διαθέσιμα actions για αυτό το endpoint
  • η εφαρμογή client (όπως ένα mobile wallet, chat bot ή ιστοσελίδα) εμφανίζει ένα UI για τον χρήστη ώστε να εκτελέσει ένα από τα actions
  • αφού ο χρήστης επιλέξει ένα action (κάνοντας κλικ σε ένα κουμπί), ο client κάνει POST request στο endpoint για να λάβει τη συναλλαγή που θα υπογράψει ο χρήστης
  • το πορτοφόλι διευκολύνει την υπογραφή της συναλλαγής από τον χρήστη και τελικά αποστέλλει τη συναλλαγή στο blockchain για επιβεβαίωση

Εκτέλεση και Κύκλος Ζωής Solana ActionsΕκτέλεση και Κύκλος Ζωής Solana Actions

Κατά τη λήψη συναλλαγών από ένα Actions URL, οι clients θα πρέπει να χειρίζονται την υποβολή αυτών των συναλλαγών στο blockchain και να διαχειρίζονται τον κύκλο ζωής της κατάστασής τους.

Τα Actions υποστηρίζουν επίσης κάποιο επίπεδο ακύρωσης πριν από την εκτέλεση. Το GET και το POST request μπορεί να επιστρέψουν ορισμένα μεταδεδομένα που δηλώνουν εάν το action είναι δυνατό να εκτελεστεί (όπως με το πεδίο disabled).

Για παράδειγμα, εάν υπήρχε ένα Action endpoint που διευκολύνει την ψηφοφορία σε μια πρόταση διακυβέρνησης DAO της οποίας το παράθυρο ψηφοφορίας έχει κλείσει, το αρχικό GET request μπορεί να επιστρέψει το μήνυμα σφάλματος "Αυτή η πρόταση δεν τίθεται πλέον σε ψηφοφορία" και τα κουμπιά "Ψήφος Ναι" και "Ψήφος Όχι" ως "disabled".

Τα Blinks (blockchain links) είναι εφαρμογές client που αναλύουν τα Action APIs και κατασκευάζουν διεπαφές χρήστη για αλληλεπίδραση και εκτέλεση Actions.

Οι εφαρμογές client που υποστηρίζουν blinks εντοπίζουν απλώς URLs συμβατά με Actions, τα αναλύουν και επιτρέπουν στους χρήστες να αλληλεπιδρούν μαζί τους μέσω τυποποιημένων διεπαφών χρήστη.

Οποιαδήποτε εφαρμογή client που αναλύει πλήρως ένα Actions API για να δημιουργήσει μια πλήρη διεπαφή γι' αυτό είναι ένα blink. Επομένως, δεν είναι όλοι οι clients που χρησιμοποιούν Actions APIs blinks.

Ένα blink URL περιγράφει μια εφαρμογή client που επιτρέπει σε έναν χρήστη να ολοκληρώσει τον πλήρη κύκλο ζωής εκτέλεσης ενός Action, συμπεριλαμβανομένης της υπογραφής με το πορτοφόλι του.

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

Για να γίνει οποιαδήποτε εφαρμογή client ένα blink:

  • Το blink URL πρέπει να περιέχει μια παράμετρο query action της οποίας η τιμή είναι ένα URL-encoded Action URL. Αυτή η τιμή πρέπει να είναι URL-encoded ώστε να μην έρχεται σε σύγκρουση με άλλες παραμέτρους πρωτοκόλλου.

  • Η εφαρμογή client πρέπει να URL-decode την παράμετρο query action και να αναλύσει τον παρεχόμενο σύνδεσμο API Action (δείτε σχήμα URL Action).

  • Ο client πρέπει να αποδώσει μια πλούσια διεπαφή χρήστη που επιτρέπει σε έναν χρήστη να ολοκληρώσει τον πλήρη κύκλο ζωής εκτέλεσης ενός Action, συμπεριλαμβανομένης της υπογραφής με το πορτοφόλι του.

Δεν θα υποστηρίζουν όλες οι εφαρμογές blink client (π.χ. ιστοσελίδες ή dApps) όλα τα Actions. Οι developers εφαρμογών μπορούν να επιλέξουν ποια Actions θέλουν να υποστηρίξουν στις διεπαφές blink τους.

Το παρακάτω παράδειγμα παρουσιάζει ένα έγκυρο blink URL με τιμή action solana-action:https://actions.alice.com/donate που είναι URL encoded:

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

Τα Blinks μπορούν να συνδέονται με Actions με τουλάχιστον 3 τρόπους:

  1. Κοινοποίηση ενός ρητού Action URL: solana-action:https://actions.alice.com/donate

    Σε αυτή την περίπτωση, μόνο οι υποστηριζόμενοι clients μπορούν να αποδώσουν το blink. Δεν θα υπάρχει εφεδρική προεπισκόπηση συνδέσμου, ούτε ιστότοπος που να μπορεί να επισκεφθεί κάποιος εκτός του client που δεν υποστηρίζει blinks.

  2. Κοινοποίηση ενός συνδέσμου προς ιστότοπο που συνδέεται με ένα Actions API μέσω αρχείου actions.json στο ριζικό κατάλογο του domain του ιστότοπου.

    Για παράδειγμα, το https://alice.com/actions.json αντιστοιχίζει το https://alice.com/donate, ένα URL ιστότοπου στο οποίο οι χρήστες μπορούν να δωρίσουν στην Alice, στο API URL https://actions.alice.com/donate, όπου φιλοξενούνται τα Actions για δωρεά στην Alice.

  3. Ενσωμάτωση ενός Action URL σε ένα URL ιστότοπου "ενδιάμεσης σελίδας" που κατανοεί πώς να αναλύει Actions.

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

Οι clients που υποστηρίζουν blinks θα πρέπει να μπορούν να λαμβάνουν οποιαδήποτε από τις παραπάνω μορφές και να αποδίδουν σωστά μια διεπαφή που διευκολύνει την εκτέλεση του action απευθείας στον client.

Για clients που δεν υποστηρίζουν blinks, θα πρέπει να υπάρχει ένας υποκείμενος ιστότοπος (καθιστώντας τον browser το παγκόσμιο εφεδρικό μέσο).

Εάν ένας χρήστης πατήσει οπουδήποτε σε έναν client που δεν είναι κουμπί action ή πεδίο εισαγωγής κειμένου, θα πρέπει να μεταφερθεί στον υποκείμενο ιστότοπο.

Ενώ τα Solana Actions και τα blinks αποτελούν ένα πρωτόκολλο/προδιαγραφή χωρίς άδεια, οι εφαρμογές client και τα πορτοφόλια εξακολουθούν να απαιτείται να διευκολύνουν τελικά τους χρήστες να υπογράψουν τη συναλλαγή.

Χρησιμοποιήστε το εργαλείο Blinks Inspector για να επιθεωρήσετε, να αποσφαλματώσετε και να δοκιμάσετε τα blinks και actions σας απευθείας στο πρόγραμμα περιήγησής σας. Μπορείτε να δείτε τα payloads απόκρισης GET και POST, τα response headers και να δοκιμάσετε όλες τις εισόδους σε καθένα από τα συνδεδεμένα Actions σας.

Κάθε εφαρμογή client ή πορτοφόλι μπορεί να έχει διαφορετικές απαιτήσεις σχετικά με τα Action endpoints που οι clients τους θα αναλύουν αυτόματα και θα εμφανίζουν άμεσα στους χρήστες τους σε πλατφόρμες κοινωνικής δικτύωσης.

Για παράδειγμα, ορισμένοι clients ενδέχεται να λειτουργούν με προσέγγιση "λίστας επιτρεπόμενων" που μπορεί να απαιτεί επαλήθευση πριν ο client τους αναλύσει ένα Action για χρήστες, όπως το Actions Registry του Dialect (που αναλύεται παρακάτω).

Όλα τα blinks θα εξακολουθούν να αποδίδονται και να επιτρέπουν υπογραφή στον ιστότοπο ενδιάμεσης σελίδας blinks dial.to του Dialect, με την κατάσταση μητρώου τους να εμφανίζεται στο blink.

Μητρώο Actions του Dialect

Ως δημόσιο αγαθό για το οικοσύστημα της Solana, το Dialect διατηρεί ένα δημόσιο μητρώο — μαζί με τη βοήθεια του Solana Foundation και άλλων μελών της κοινότητας — blockchain links που προέρχονται από προ-επαληθευμένες γνωστές πηγές. Από την έναρξη, μόνο τα Actions που έχουν καταχωριστεί στο μητρώο Dialect θα εμφανίζονται στη ροή του Twitter όταν δημοσιευτούν.

Οι εφαρμογές client και τα πορτοφόλια μπορούν ελεύθερα να επιλέξουν να χρησιμοποιήσουν αυτό το δημόσιο μητρώο ή μια άλλη λύση για να διασφαλίσουν την ασφάλεια των χρηστών. Εάν δεν επαληθευτεί μέσω του μητρώου Dialect, ο blockchain link δεν θα αναλυθεί από τον client blink και θα αποδοθεί ως τυπικό URL.

Οι developers μπορούν να υποβάλουν αίτηση επαλήθευσης από το Dialect εδώ: dial.to/register

Προδιαγραφή

Η προδιαγραφή Solana Actions αποτελείται από βασικές ενότητες που αποτελούν μέρος μιας ροής αλληλεπίδρασης αίτησης/απόκρισης:

Καθεμία από αυτές τις αιτήσεις γίνεται από τον Action client (π.χ. εφαρμογή πορτοφολιού, επέκταση προγράμματος περιήγησης, dApp, ιστότοπος κ.λπ.) για τη συλλογή συγκεκριμένων μεταδεδομένων για πλούσιες διεπαφές χρήστη και για τη διευκόλυνση της εισόδου χρήστη στο Actions API.

Καθεμία από τις απαντήσεις δημιουργείται από μια εφαρμογή (π.χ. ιστότοπος, backend διακομιστή κ.λπ.) και επιστρέφεται στον Action client. Τελικά, παρέχει μια υπογράψιμη συναλλαγή ή μήνυμα για ένα πορτοφόλι, ώστε να ζητά από τον χρήστη να εγκρίνει, να υπογράψει και να αποστείλει στο blockchain.

Οι τύποι και οι διεπαφές που δηλώνονται σε αυτά τα αρχεία readme είναι συχνά η απλοποιημένη έκδοση των τύπων για καλύτερη αναγνωσιμότητα.

Για καλύτερη ασφάλεια τύπων και βελτιωμένη εμπειρία προγραμματιστή, το πακέτο @solana/actions-spec περιέχει πιο σύνθετους ορισμούς τύπων. Μπορείτε να βρείτε τον πηγαίο κώδικα εδώ.

Σχήμα URL

Ένα URL Solana Action περιγράφει μια διαδραστική αίτηση για μια υπογράψιμη συναλλαγή ή μήνυμα Solana χρησιμοποιώντας το πρωτόκολλο solana-action.

Η αίτηση είναι διαδραστική επειδή οι παράμετροι στο URL χρησιμοποιούνται από έναν client για να πραγματοποιήσει μια σειρά τυποποιημένων HTTP αιτήσεων, ώστε να συνθέσει μια υπογράψιμη συναλλαγή ή μήνυμα που θα υπογράψει ο χρήστης με το πορτοφόλι του.

solana-action:<link>
  • Απαιτείται ένα μοναδικό πεδίο link ως pathname. Η τιμή πρέπει να είναι ένα υπό συνθήκες κωδικοποιημένο URL απόλυτο HTTPS URL.

  • Εάν το URL περιέχει παραμέτρους ερωτήματος, πρέπει να είναι κωδικοποιημένο ως URL. Η κωδικοποίηση URL της τιμής αποτρέπει συγκρούσεις με τυχόν παραμέτρους πρωτοκόλλου Actions, οι οποίες μπορεί να προστεθούν μέσω της προδιαγραφής πρωτοκόλλου.

  • Εάν το URL δεν περιέχει παραμέτρους ερωτήματος, δεν πρέπει να κωδικοποιείται ως URL. Αυτό παράγει ένα πιο σύντομο URL και έναν λιγότερο πυκνό κώδικα QR.

Σε κάθε περίπτωση, οι clients πρέπει να αποκωδικοποιούν ως URL την τιμή. Αυτό δεν έχει καμία επίδραση αν η τιμή δεν είναι κωδικοποιημένη ως URL. Εάν η αποκωδικοποιημένη τιμή δεν είναι απόλυτο HTTPS URL, το πορτοφόλι πρέπει να το απορρίψει ως εσφαλμένο.

Απόκριση OPTIONS

Για να επιτραπεί η Κοινή Χρήση Πόρων μεταξύ Διαφορετικών Προελεύσεων (CORS) εντός των Action clients (συμπεριλαμβανομένων των blinks), όλα τα endpoints Action θα πρέπει να ανταποκρίνονται σε HTTP αιτήσεις για τη μέθοδο OPTIONS με έγκυρες κεφαλίδες που θα επιτρέπουν στους clients να περνούν τους ελέγχους CORS για όλες τις επόμενες αιτήσεις από τον ίδιο τομέα προέλευσής τους.

Ένας Action client μπορεί να εκτελεί "προκαταρκτικές" αιτήσεις προς το endpoint URL του Action για να ελέγξει αν η επόμενη αίτηση GET προς το URL του Action θα περάσει όλους τους ελέγχους CORS. Αυτοί οι προκαταρκτικοί έλεγχοι CORS γίνονται χρησιμοποιώντας τη μέθοδο HTTP OPTIONS και θα πρέπει να ανταποκρίνονται με όλες τις απαιτούμενες HTTP κεφαλίδες που θα επιτρέπουν στους Action clients (όπως τα blinks) να πραγματοποιούν σωστά όλες τις επόμενες αιτήσεις από τον τομέα προέλευσής τους.

Τουλάχιστον, οι απαιτούμενες κεφαλίδες HTTP περιλαμβάνουν:

  • Access-Control-Allow-Origin με τιμή *
    • αυτό διασφαλίζει ότι όλοι οι Action clients μπορούν να περνούν με ασφάλεια τους ελέγχους CORS προκειμένου να πραγματοποιούν όλες τις απαιτούμενες αιτήσεις
  • Access-Control-Allow-Methods με τιμή GET,POST,PUT,OPTIONS
    • διασφαλίζει ότι υποστηρίζονται όλες οι απαιτούμενες μέθοδοι HTTP αιτήσεων για τα Actions
  • Access-Control-Allow-Headers με ελάχιστη τιμή Content-Type, Authorization, Content-Encoding, Accept-Encoding

Για απλότητα, οι προγραμματιστές θα πρέπει να εξετάσουν το ενδεχόμενο να επιστρέφουν την ίδια απόκριση και κεφαλίδες στις αιτήσεις OPTIONS όπως και στην απόκριση GET.

Κεφαλίδες Cross-Origin για το actions.json

Η απόκριση του αρχείου actions.json πρέπει επίσης να επιστρέφει έγκυρες κεφαλίδες Cross-Origin για αιτήσεις GET και OPTIONS, ειδικότερα την τιμή * της κεφαλίδας Access-Control-Allow-Origin.

Δείτε actions.json παρακάτω για περισσότερες λεπτομέρειες.

Αίτηση GET

Ο Action client (π.χ. πορτοφόλι, επέκταση προγράμματος περιήγησης κ.λπ.) θα πρέπει να πραγματοποιεί μια HTTP αίτηση GET JSON προς το endpoint URL του Action.

  • Η αίτηση δεν πρέπει να αναγνωρίζει το πορτοφόλι ή τον χρήστη.
  • Ο client θα πρέπει να πραγματοποιεί την αίτηση με μια κεφαλίδα Accept-Encoding.
  • Ο client θα πρέπει να εμφανίζει τον τομέα του URL κατά τη διάρκεια της αίτησης.

Απόκριση GET

Το endpoint URL του Action (π.χ. εφαρμογή ή backend διακομιστή) θα πρέπει να ανταποκρίνεται με μια HTTP OK JSON απόκριση (με έγκυρο payload στο σώμα) ή με ένα κατάλληλο σφάλμα HTTP.

Οι αποκρίσεις σφαλμάτων (δηλ. κωδικοί κατάστασης HTTP 4xx και 5xx) θα πρέπει να επιστρέφουν ένα σώμα JSON απόκρισης που ακολουθεί το ActionError για να παρουσιάζεται ένα χρήσιμο μήνυμα σφάλματος στους χρήστες. Βλ. Action Errors.

Σώμα Απόκρισης GET

Μια απόκριση GET με HTTP OK JSON απόκριση θα πρέπει να περιλαμβάνει ένα payload σώματος που ακολουθεί την προδιαγραφή διεπαφής:

ActionGetResponse
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 - Ο τύπος της ενέργειας που δίνεται στον χρήστη. Η προεπιλογή είναι action. Το αρχικό ActionGetResponse απαιτείται να έχει τύπο action.

    • action - Τυπική ενέργεια που θα επιτρέπει στον χρήστη να αλληλεπιδρά με οποιοδήποτε από τα LinkedActions
    • completed - Χρησιμοποιείται για τη δήλωση της κατάστασης "ολοκλήρωσης" εντός της αλυσίδας ενεργειών.
  • icon - Η τιμή πρέπει να είναι ένα απόλυτο HTTP ή HTTPS URL εικόνας εικονιδίου. Το αρχείο πρέπει να είναι εικόνα SVG, PNG ή WebP, διαφορετικά ο client/πορτοφόλι πρέπει να το απορρίψει ως εσφαλμένο.

  • title - Η τιμή πρέπει να είναι ένα string UTF-8 που αντιπροσωπεύει την πηγή της αίτησης ενέργειας. Για παράδειγμα, αυτό μπορεί να είναι το όνομα μιας επωνυμίας, καταστήματος, εφαρμογής ή ατόμου που κάνει την αίτηση.

  • description - Η τιμή πρέπει να είναι ένα string UTF-8 που παρέχει πληροφορίες για την ενέργεια. Η περιγραφή θα πρέπει να εμφανίζεται στον χρήστη.

  • label - Η τιμή πρέπει να είναι ένα string UTF-8 που θα αποδίδεται σε ένα κουμπί για κλικ από τον χρήστη. Όλες οι ετικέτες δεν πρέπει να υπερβαίνουν τις 5 λέξεις και θα πρέπει να ξεκινούν με ρήμα για να ενισχύουν την ενέργεια που θέλετε να κάνει ο χρήστης. Για παράδειγμα, "Mint NFT", "Vote Yes" ή "Stake 1 SOL".

  • disabled - Η τιμή πρέπει να είναι boolean για να αντιπροσωπεύει την κατάσταση απενεργοποίησης του αποδιδόμενου κουμπιού (το οποίο εμφανίζει το string label). Εάν δεν παρέχεται τιμή, το disabled θα πρέπει να έχει ως προεπιλογή false (δηλ. ενεργοποιημένο από προεπιλογή). Για παράδειγμα, εάν το endpoint ενέργειας αφορά ψηφοφορία διακυβέρνησης που έχει κλείσει, ορίστε disabled=true και το label θα μπορούσε να είναι "Vote Closed".

  • error - Μια προαιρετική ένδειξη σφάλματος για μη κρίσιμα σφάλματα. Εάν υπάρχει, ο client θα πρέπει να το εμφανίζει στον χρήστη. Εάν οριστεί, δεν θα πρέπει να εμποδίζει τον client από την ερμηνεία της ενέργειας ή την εμφάνισή της στον χρήστη (βλ. Action Errors). Για παράδειγμα, το σφάλμα μπορεί να χρησιμοποιηθεί μαζί με το disabled για να εμφανίσει έναν λόγο όπως επιχειρηματικούς περιορισμούς, εξουσιοδότηση, την κατάσταση ή ένα σφάλμα εξωτερικού πόρου.

  • links.actions - Ένας προαιρετικός πίνακας σχετικών ενεργειών για το endpoint. Στους χρήστες θα πρέπει να εμφανίζεται διεπαφή χρήστη για καθεμία από τις αναφερόμενες ενέργειες και αναμένεται να εκτελούν μόνο μία. Για παράδειγμα, ένα endpoint ενέργειας ψηφοφορίας διακυβέρνησης μπορεί να επιστρέφει τρεις επιλογές για τον χρήστη: "Vote Yes", "Vote No" και "Abstain from Vote".

    • Εάν δεν παρέχεται links.actions, ο client θα πρέπει να αποδίδει ένα μόνο κουμπί χρησιμοποιώντας το ριζικό string label και να πραγματοποιεί την αίτηση POST στο ίδιο endpoint URL ενέργειας με την αρχική αίτηση GET.

    • Εάν παρέχονται links.actions, ο client θα πρέπει να αποδίδει μόνο κουμπιά και πεδία εισόδου βάσει των στοιχείων που αναφέρονται στο πεδίο links.actions. Ο client δεν θα πρέπει να αποδίδει κουμπί για τα περιεχόμενα του ριζικού label.

LinkedAction
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 επιτρέπει τη δήλωση της εισόδου που ζητά το Actions API από τον χρήστη:

ActionParameter
/**
* 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 θα πρέπει να είναι ένα string ισοδύναμο με μια έγκυρη κανονική έκφραση. Αυτό το μοτίβο κανονικής έκφρασης θα πρέπει να χρησιμοποιείται από τους blink-clients για την επικύρωση της εισόδου χρήστη πριν από την αίτηση POST. Εάν το pattern δεν είναι έγκυρη κανονική έκφραση, θα πρέπει να αγνοείται από τους clients.

Το patternDescription είναι μια αναγνώσιμη από τον άνθρωπο περιγραφή των αναμενόμενων αιτήσεων εισόδου από τον χρήστη. Εάν παρέχεται pattern, το patternDescription απαιτείται να παρέχεται.

Οι τιμές min και max επιτρέπουν στην είσοδο να ορίσει κάτω ή/και άνω όρια της εισόδου που ζητείται από τον χρήστη (δηλ. ελάχιστος/μέγιστος αριθμός ή/και ελάχιστο/μέγιστο μήκος χαρακτήρων), και θα πρέπει να χρησιμοποιούνται για επικύρωση από την πλευρά του client. Για types εισόδου date ή datetime-local, αυτές οι τιμές θα πρέπει να είναι string ημερομηνιών. Για άλλους types εισόδου βάσει string, οι τιμές θα πρέπει να είναι αριθμοί που αντιπροσωπεύουν το ελάχιστο/μέγιστο μήκος χαρακτήρων τους.

Εάν η τιμή εισόδου χρήστη δεν θεωρείται έγκυρη σύμφωνα με το pattern, ο χρήστης θα πρέπει να λαμβάνει ένα μήνυμα σφάλματος από την πλευρά του client που υποδεικνύει ότι το πεδίο εισόδου δεν είναι έγκυρο και να εμφανίζεται το string patternDescription.

Το πεδίο type επιτρέπει στο Actions API να δηλώνει πιο συγκεκριμένα πεδία εισόδου χρήστη, παρέχοντας καλύτερη επικύρωση από την πλευρά του client και βελτιώνοντας την εμπειρία χρήστη. Σε πολλές περιπτώσεις, αυτός ο τύπος θα μοιάζει με το τυπικό στοιχείο εισόδου HTML.

Το ActionParameterType μπορεί να απλοποιηθεί στον ακόλουθο τύπο:

ActionParameterType
/**
* Input field type to present to the user
* @default `text`
*/
export type ActionParameterType =
| "text"
| "email"
| "url"
| "number"
| "date"
| "datetime-local"
| "checkbox"
| "radio"
| "textarea"
| "select";

Καθεμία από τις τιμές type θα πρέπει συνήθως να οδηγεί σε ένα πεδίο εισόδου χρήστη που μοιάζει με ένα τυπικό στοιχείο input HTML του αντίστοιχου type (δηλ. <input type="email" />) για καλύτερη επικύρωση από την πλευρά του client και εμπειρία χρήστη:

  • text - ισοδύναμο του στοιχείου εισόδου "text" HTML
  • email - ισοδύναμο του στοιχείου εισόδου "email" HTML
  • url - ισοδύναμο του στοιχείου εισόδου "url" HTML
  • number - ισοδύναμο του στοιχείου εισόδου "number" HTML
  • date - ισοδύναμο του στοιχείου εισόδου "date" HTML
  • datetime-local - ισοδύναμο του στοιχείου εισόδου "datetime-local" HTML
  • checkbox - ισοδύναμο με ομαδοποίηση τυπικών στοιχείων εισόδου "checkbox" HTML. Το Actions API θα πρέπει να επιστρέφει options όπως αναλύεται παρακάτω. Ο χρήστης θα πρέπει να μπορεί να επιλέγει πολλές από τις παρεχόμενες επιλογές checkbox.
  • radio - ισοδύναμο με ομαδοποίηση τυπικών στοιχείων εισόδου "radio" HTML. Το Actions API θα πρέπει να επιστρέφει options όπως αναλύεται παρακάτω. Ο χρήστης θα πρέπει να μπορεί να επιλέγει μόνο μία από τις παρεχόμενες επιλογές radio.
  • Άλλοι τύποι εισόδου HTML που δεν αναφέρονται παραπάνω (hidden, button, submit, file, κ.λπ.) δεν υποστηρίζονται προς το παρόν.

Εκτός από τα στοιχεία που μοιάζουν με τύπους εισόδου HTML παραπάνω, υποστηρίζονται επίσης τα ακόλουθα στοιχεία εισόδου χρήστη:

  • textarea - ισοδύναμο του HTML στοιχείου textarea. Επιτρέπει στον χρήστη να παρέχει πολυγραμμική εισαγωγή κειμένου.
  • select - ισοδύναμο του HTML στοιχείου select, που επιτρέπει στον χρήστη να χρησιμοποιεί ένα πεδίο τύπου "αναπτυσσόμενης λίστας". Το Action API πρέπει να επιστρέφει options όπως περιγράφεται παρακάτω.

Όταν το type ορίζεται ως select, checkbox ή radio, τότε το Action API πρέπει να περιλαμβάνει έναν πίνακα options όπου κάθε στοιχείο παρέχει τουλάχιστον ένα label και ένα value. Κάθε επιλογή μπορεί επίσης να έχει μια τιμή selected για να ενημερώσει τον blink-client ποια από τις επιλογές πρέπει να επιλέγεται από προεπιλογή για τον χρήστη (βλ. checkbox και radio για τις διαφορές).

Αυτό το ActionParameterSelectable μπορεί να απλοποιηθεί στον ακόλουθο ορισμό τύπου:

ActionParameterSelectable
/**
* 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;
}>;
}

Εάν δεν έχει οριστεί type ή έχει οριστεί μια άγνωστη/μη υποστηριζόμενη τιμή, οι blink-clients πρέπει να χρησιμοποιούν ως προεπιλογή text και να αποδίδουν ένα απλό πεδίο εισαγωγής κειμένου.

Το Action API εξακολουθεί να είναι υπεύθυνο για την επικύρωση και την εξυγίανση όλων των δεδομένων από τις παραμέτρους εισόδου του χρήστη, επιβάλλοντας οποιαδήποτε "υποχρεωτική" εισαγωγή χρήστη κατά περίπτωση.

Για πλατφόρμες άλλες από αυτές που βασίζονται σε HTML/web (όπως native mobile), πρέπει να χρησιμοποιείται το αντίστοιχο native στοιχείο εισόδου χρήστη για να επιτευχθεί ισοδύναμη εμπειρία και επικύρωση από την πλευρά του client, όπως οι τύποι εισόδου HTML/web που περιγράφονται παραπάνω.

Παράδειγμα Απόκρισης GET

Το ακόλουθο παράδειγμα απόκρισης παρέχει μία μεμονωμένη "ριζική" ενέργεια που αναμένεται να παρουσιαστεί στον χρήστη ως ένα μεμονωμένο κουμπί με ετικέτα "Claim Access Token":

{
"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 με Παραμέτρους

Τα ακόλουθα παραδείγματα απόκρισης δείχνουν πώς να αποδεχτείτε εισαγωγή κειμένου από τον χρήστη (μέσω parameters) και να συμπεριλάβετε αυτή την εισαγωγή στο τελικό αίτημα POST (μέσω του πεδίου href εντός ενός LinkedAction):

Το ακόλουθο παράδειγμα απόκρισης παρέχει στον χρήστη 3 συνδεδεμένες ενέργειες για να κάνει stake SOL: ένα κουμπί με ετικέτα "Stake 1 SOL", ένα άλλο κουμπί με ετικέτα "Stake 5 SOL", και ένα πεδίο εισαγωγής κειμένου που επιτρέπει στον χρήστη να εισάγει μια συγκεκριμένη τιμή "amount" που θα αποσταλεί στο Action API:

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

Το ακόλουθο παράδειγμα απόκρισης παρέχει ένα μεμονωμένο πεδίο εισαγωγής για τον χρήστη ώστε να εισάγει ένα amount που αποστέλλεται με το αίτημα POST (μπορεί να χρησιμοποιηθεί είτε ως παράμετρος ερωτήματος είτε ως υποδιαδρομή):

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

Αίτημα POST

Ο client πρέπει να κάνει ένα αίτημα HTTP POST JSON στη διεύθυνση URL της ενέργειας με ένα σώμα αίτησης:

{
"account": "<account>"
}
  • account - Η τιμή πρέπει να είναι το δημόσιο κλειδί ενός λογαριασμού κωδικοποιημένο σε base58 που μπορεί να υπογράψει τη συναλλαγή.

Ο client πρέπει να κάνει το αίτημα με κεφαλίδα Accept-Encoding και η εφαρμογή μπορεί να απαντήσει με κεφαλίδα Content-Encoding για συμπίεση HTTP.

Ο client πρέπει να εμφανίζει το domain της διεύθυνσης URL της ενέργειας καθώς γίνεται το αίτημα. Εάν έγινε αίτημα GET, ο client πρέπει επίσης να εμφανίζει τον title και να αποδίδει την εικόνα icon από εκείνη την απόκριση GET.

Απόκριση POST

Το endpoint POST της ενέργειας πρέπει να αποκρίνεται με μια απόκριση HTTP OK JSON (με έγκυρο φορτίο στο σώμα) ή με κατάλληλο σφάλμα HTTP.

Οι αποκρίσεις σφαλμάτων (δηλ. κωδικοί κατάστασης HTTP 4xx και 5xx) πρέπει να επιστρέφουν ένα σώμα απόκρισης JSON που ακολουθεί το ActionError για να παρουσιάζουν ένα χρήσιμο μήνυμα σφάλματος στους χρήστες. Βλ. Σφάλματα Ενεργειών.

Σώμα Απόκρισης POST

Μια απόκριση POST με απόκριση HTTP OK JSON πρέπει να περιλαμβάνει ένα σώμα αίτησης:

ActionPostResponse
/**
* 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 - Η τιμή πρέπει να είναι μια κωδικοποιημένη σε base64 σειριοποιημένη συναλλαγή. Ο client πρέπει να αποκωδικοποιήσει σε base64 τη συναλλαγή και να την αποσειριοποιήσει.

  • message - Η τιμή πρέπει να είναι μια συμβολοσειρά UTF-8 που περιγράφει τη φύση της συναλλαγής που περιλαμβάνεται στην απόκριση. Ο client πρέπει να εμφανίζει αυτή την τιμή στον χρήστη. Για παράδειγμα, αυτό μπορεί να είναι το όνομα ενός αντικειμένου που αγοράζεται, μια έκπτωση που εφαρμόζεται σε μια αγορά ή ένα σημείωμα ευχαριστίας.

  • links.next - Μια προαιρετική τιμή που χρησιμοποιείται για να "αλυσοδέσει" πολλαπλές Ενέργειες μαζί σε σειρά. Αφού η συμπεριλαμβανόμενη transaction επιβεβαιωθεί onchain, ο client μπορεί να ανακτήσει και να αποδώσει την επόμενη ενέργεια. Βλ. Αλυσόδεση Ενεργειών για περισσότερες λεπτομέρειες.

  • Ο client και η εφαρμογή πρέπει να επιτρέπουν πρόσθετα πεδία στο σώμα του αιτήματος και στο σώμα της απόκρισης, τα οποία μπορεί να προστεθούν από μελλοντικές ενημερώσεις προδιαγραφών.

Η εφαρμογή μπορεί να αποκριθεί με μια μερικώς ή πλήρως υπογεγραμμένη συναλλαγή. Ο client και το πορτοφόλι πρέπει να επικυρώνουν τη συναλλαγή ως μη αξιόπιστη.

Απόκριση POST - Συναλλαγή

Εάν οι signatures της συναλλαγής είναι κενές ή η συναλλαγή ΔΕΝ έχει υπογραφεί μερικώς:

  • Ο client πρέπει να αγνοεί το feePayer στη συναλλαγή και να ορίζει το feePayer στο account του αιτήματος.
  • Ο client πρέπει να αγνοεί το recentBlockhash στη συναλλαγή και να ορίζει το recentBlockhash στο πιο πρόσφατο blockhash.
  • Ο client πρέπει να σειριοποιεί και να αποσειριοποιεί τη συναλλαγή πριν την υπογράψει. Αυτό διασφαλίζει συνεπή διάταξη των κλειδιών λογαριασμού, ως λύση για αυτό το ζήτημα.

Εάν η συναλλαγή έχει υπογραφεί μερικώς:

  • Ο client ΔΕΝ πρέπει να τροποποιεί το feePayer ή το recentBlockhash καθώς αυτό θα ακύρωνε τυχόν υπάρχουσες υπογραφές.
  • Ο client πρέπει να επαληθεύει τις υπάρχουσες υπογραφές, και εάν οποιαδήποτε είναι άκυρη, ο client πρέπει να απορρίπτει τη συναλλαγή ως παραμορφωμένη.

Ο client πρέπει να υπογράφει τη συναλλαγή μόνο με το account του αιτήματος, και πρέπει να το κάνει μόνο εάν αναμένεται υπογραφή για το account του αιτήματος.

Εάν αναμένεται οποιαδήποτε υπογραφή εκτός από υπογραφή για το account του αιτήματος, ο client πρέπει να απορρίπτει τη συναλλαγή ως κακόβουλη.

Σφάλματα Ενεργειών

Τα Actions APIs πρέπει να επιστρέφουν σφάλματα χρησιμοποιώντας ActionError προκειμένου να παρουσιάζουν χρήσιμα μηνύματα σφάλματος στον χρήστη. Ανάλογα με το πλαίσιο, αυτό το σφάλμα μπορεί να είναι κρίσιμο ή μη κρίσιμο.

ActionError
export interface ActionError {
/** simple error message to be displayed to the user */
message: string;
}

Όταν ένα Actions API αποκρίνεται με κωδικό κατάστασης HTTP σφάλματος (δηλ. 4xx και 5xx), το σώμα της απόκρισης πρέπει να είναι ένα φορτίο JSON που ακολουθεί το ActionError. Το σφάλμα θεωρείται κρίσιμο και το συμπεριλαμβανόμενο message πρέπει να παρουσιάζεται στον χρήστη.

Για αποκρίσεις API που υποστηρίζουν το προαιρετικό χαρακτηριστικό error (όπως το ActionGetResponse), το σφάλμα θεωρείται μη κρίσιμο και το συμπεριλαμβανόμενο message πρέπει να παρουσιάζεται στον χρήστη.

Αλυσόδεση Ενεργειών

Οι Solana Actions μπορούν να "αλυσοδεθούν" μαζί σε μια διαδοχική σειρά. Αφού η συναλλαγή μιας Ενέργειας επιβεβαιωθεί onchain, η επόμενη ενέργεια μπορεί να ληφθεί και να παρουσιαστεί στον χρήστη.

Η αλυσόδεση ενεργειών επιτρέπει στους developers να δημιουργούν πιο σύνθετες και δυναμικές εμπειρίες εντός των blinks, συμπεριλαμβανομένων:

  • παροχή πολλαπλών συναλλαγών (και τελικά υπογραφής μηνύματος) σε έναν χρήστη
  • προσαρμοσμένα μεταδεδομένα ενεργειών βάσει της διεύθυνσης πορτοφολιού του χρήστη
  • ανανέωση των μεταδεδομένων blink μετά από επιτυχημένη συναλλαγή
  • λήψη callback API με την υπογραφή συναλλαγής για πρόσθετη επικύρωση και λογική στον server του Action API
  • προσαρμοσμένα μηνύματα "επιτυχίας" με ενημέρωση των εμφανιζόμενων μεταδεδομένων (π.χ. νέα εικόνα και περιγραφή)

Για να αλυσοδέσετε πολλαπλές ενέργειες μαζί, σε οποιοδήποτε ActionPostResponse συμπεριλάβετε ένα links.next είτε:

  • PostNextActionLink - Σύνδεσμος αιτήματος POST με URL callback ίδιας προέλευσης για λήψη της signature και του account του χρήστη στο σώμα. Αυτό το URL callback πρέπει να αποκρίνεται με ένα NextAction.
  • InlineNextActionLink - Ενσωματωμένα μεταδεδομένα για την επόμενη ενέργεια που θα παρουσιαστεί στον χρήστη αμέσως μετά την επιβεβαίωση της συναλλαγής. Δεν θα πραγματοποιηθεί κανένα callback.
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

Αφού η συμπεριλαμβανόμενη transaction του ActionPostResponse υπογραφεί από τον χρήστη και επιβεβαιωθεί onchain, ο blink client πρέπει είτε:

  • να εκτελέσει το αίτημα callback για να ανακτήσει και να εμφανίσει το NextAction, ή
  • εάν ένα NextAction παρέχεται ήδη μέσω links.next, ο blink client πρέπει να ενημερώσει τα εμφανιζόμενα μεταδεδομένα και να μην κάνει κανένα αίτημα callback

Εάν το URL callback δεν είναι της ίδιας προέλευσης με το αρχικό αίτημα POST, δεν πρέπει να πραγματοποιηθεί κανένα αίτημα callback. Οι blink clients πρέπει να εμφανίζουν ένα σφάλμα που να ειδοποιεί τον χρήστη.

NextAction
/** 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">;

Βάσει του type, η επόμενη ενέργεια πρέπει να παρουσιάζεται στον χρήστη μέσω blink clients με έναν από τους ακόλουθους τρόπους:

  • action - (προεπιλογή) Μια τυπική ενέργεια που θα επιτρέψει στον χρήστη να δει τα συμπεριλαμβανόμενα μεταδεδομένα Ενέργειας, να αλληλεπιδράσει με τα παρεχόμενα LinkedActions, και να συνεχίσει να αλυσοδένει τυχόν επόμενες ενέργειες.

  • completed - Η τερματική κατάσταση μιας αλυσίδας ενεργειών που μπορεί να ενημερώσει το blink UI με τα συμπεριλαμβανόμενα μεταδεδομένα Ενέργειας, αλλά δεν θα επιτρέψει στον χρήστη να εκτελέσει περαιτέρω ενέργειες.

Εάν δεν παρέχεται links.next, οι blink clients πρέπει να θεωρούν ότι η τρέχουσα ενέργεια είναι η τελευταία στην αλυσίδα, παρουσιάζοντας την κατάσταση UI "completed" μετά την επιβεβαίωση της συναλλαγής.

actions.json

Ο σκοπός του αρχείου actions.json επιτρέπει σε μια εφαρμογή να ενημερώνει τους clients για τις διευθύνσεις URL ιστοτόπων που υποστηρίζουν Solana Actions και να παρέχει μια αντιστοίχιση που μπορεί να χρησιμοποιηθεί για την εκτέλεση αιτημάτων GET σε έναν server Actions API.

Απαιτούνται κεφαλίδες Cross-Origin

Η απόκριση του αρχείου actions.json πρέπει επίσης να επιστρέφει έγκυρες κεφαλίδες Cross-Origin για αιτήματα GET και OPTIONS, ειδικά την τιμή * για την κεφαλίδα Access-Control-Allow-Origin.

Βλ. απόκριση OPTIONS παραπάνω για περισσότερες λεπτομέρειες.

Το αρχείο actions.json πρέπει να αποθηκεύεται και να είναι καθολικά προσβάσιμο στο ριζικό κατάλογο του domain.

Για παράδειγμα, εάν η web εφαρμογή σας έχει αναπτυχθεί στο my-site.com, τότε το αρχείο actions.json πρέπει να είναι προσβάσιμο στη διεύθυνση https://my-site.com/actions.json. Αυτό το αρχείο πρέπει επίσης να είναι προσβάσιμο Cross-Origin από οποιοδήποτε πρόγραμμα περιήγησης έχοντας τιμή * στην κεφαλίδα Access-Control-Allow-Origin.

Κανόνες

Το πεδίο rules επιτρέπει στην εφαρμογή να αντιστοιχίσει ένα σύνολο σχετικών διαδρομών ροών ενός ιστοτόπου σε ένα σύνολο άλλων διαδρομών.

Τύπος: Array του ActionRuleObject.

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.

Κανόνες - Αντιστοίχιση Διαδρομής

Ο παρακάτω πίνακας περιγράφει τη σύνταξη για τα μοτίβα αντιστοίχισης διαδρομής:

ΤελεστήςΑντιστοιχίσεις
*Ένα μεμονωμένο τμήμα διαδρομής, χωρίς τους περιβάλλοντες χαρακτήρες διαχωρισμού διαδρομής /.
**Αντιστοιχεί σε μηδέν ή περισσότερους χαρακτήρες, συμπεριλαμβανομένων των χαρακτήρων διαχωρισμού διαδρομής / μεταξύ πολλαπλών τμημάτων διαδρομής. Εάν συμπεριληφθούν άλλοι τελεστές, ο τελεστής ** πρέπει να είναι ο τελευταίος.
?Μη υποστηριζόμενο μοτίβο.

Παραδείγματα Κανόνων

Το παρακάτω παράδειγμα δείχνει έναν κανόνα ακριβούς αντιστοίχισης για αντιστοίχιση αιτημάτων στο /buy από τη ρίζα του ιστότοπού σας με το ακριβές μονοπάτι /api/buy σχετικά με τη ρίζα του ιστότοπού σας:

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

Το παρακάτω παράδειγμα χρησιμοποιεί αντιστοίχιση διαδρομής με χαρακτήρα πλήρωσης για αντιστοίχιση αιτημάτων σε οποιαδήποτε διαδρομή (εκτός υποκαταλόγων) κάτω από το /actions/ από τη ρίζα του ιστότοπού σας με μια αντίστοιχη διαδρομή κάτω από το /api/actions/ σχετικά με τη ρίζα του ιστότοπού σας:

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

Το παρακάτω παράδειγμα χρησιμοποιεί αντιστοίχιση διαδρομής με χαρακτήρα πλήρωσης για αντιστοίχιση αιτημάτων σε οποιαδήποτε διαδρομή (εκτός υποκαταλόγων) κάτω από το /donate/ από τη ρίζα του ιστότοπού σας με ένα αντίστοιχο απόλυτο μονοπάτι https://api.dialect.com/api/v1/donate/ σε εξωτερικό ιστότοπο:

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

Το παρακάτω παράδειγμα χρησιμοποιεί αντιστοίχιση διαδρομής με χαρακτήρα πλήρωσης για έναν ιδεμποτέντ κανόνα για αντιστοίχιση αιτημάτων σε οποιαδήποτε διαδρομή (συμπεριλαμβανομένων υποκαταλόγων) κάτω από το /api/actions/ από τη ρίζα του ιστότοπού σας με τον εαυτό του:

Οι ιδεμποτέντ κανόνες επιτρέπουν στους blink clients να προσδιορίζουν πιο εύκολα εάν μια δεδομένη διαδρομή υποστηρίζει αιτήματα Action API χωρίς να απαιτείται το πρόθεμα solana-action: URI ή η εκτέλεση πρόσθετων δοκιμών απόκρισης.

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

Ταυτότητα Ενέργειας

Τα endpoints ενέργειας μπορούν να συμπεριλάβουν μια Ταυτότητα Ενέργειας στις συναλλαγές που επιστρέφονται στην απόκριση POST για να υπογράψει ο χρήστης. Αυτό επιτρέπει σε indexers και πλατφόρμες αναλυτικών στοιχείων να αποδίδουν εύκολα και επαληθεύσιμα δραστηριότητα onchain σε έναν συγκεκριμένο Πάροχο Ενέργειας (δηλ. υπηρεσία) με επαληθεύσιμο τρόπο.

Η Ταυτότητα Ενέργειας είναι ένα keypair που χρησιμοποιείται για την υπογραφή ενός ειδικά μορφοποιημένου μηνύματος που περιλαμβάνεται στη συναλλαγή με χρήση εντολής Memo. Αυτό το Μήνυμα Αναγνώρισης μπορεί να αποδοθεί επαληθεύσιμα σε μια συγκεκριμένη Ταυτότητα Ενέργειας, και επομένως να αποδώσει συναλλαγές σε έναν συγκεκριμένο Πάροχο Ενέργειας.

Το keypair δεν απαιτείται να υπογράψει την ίδια τη συναλλαγή. Αυτό επιτρέπει σε πορτοφόλια και εφαρμογές να βελτιώσουν την παραδοσιμότητα συναλλαγών όταν δεν υπάρχουν άλλες υπογραφές στη συναλλαγή που επιστρέφεται σε έναν χρήστη (βλ. συναλλαγή απόκρισης POST).

Εάν η περίπτωση χρήσης ενός Παρόχου Ενέργειας απαιτεί οι υπηρεσίες backend να προ-υπογράψουν τη συναλλαγή πριν το κάνει ο χρήστης, θα πρέπει να χρησιμοποιήσουν αυτό το keypair ως Ταυτότητα Ενέργειάς τους. Αυτό θα επιτρέψει να συμπεριληφθεί ένας λιγότερος λογαριασμός στη συναλλαγή, μειώνοντας το συνολικό μέγεθος των συναλλαγών κατά 32 bytes.

Μήνυμα Αναγνώρισης Ενέργειας

Το Μήνυμα Αναγνώρισης Ενέργειας είναι μια συμβολοσειρά UTF-8 διαχωρισμένη με άνω και κάτω τελεία, που περιλαμβάνεται σε μια συναλλαγή χρησιμοποιώντας μία μόνο εντολή SPL Memo.

protocol:identity:reference:signature
  • protocol - Η τιμή του πρωτοκόλλου που χρησιμοποιείται (ορίζεται σε solana-action σύμφωνα με το Σχήμα URL παραπάνω)
  • identity - Η τιμή πρέπει να είναι η διεύθυνση δημόσιου κλειδιού κωδικοποιημένη σε base58 του keypair Ταυτότητας Ενέργειας
  • reference - Η τιμή πρέπει να είναι ένας πίνακας 32 byte κωδικοποιημένος σε base58. Αυτό μπορεί ή να μην αποτελεί δημόσια κλειδιά, εντός ή εκτός της καμπύλης, και μπορεί ή να μην αντιστοιχεί σε λογαριασμούς στο Solana.
  • signature - υπογραφή κωδικοποιημένη σε base58 που δημιουργήθηκε από το keypair Ταυτότητας Ενέργειας υπογράφοντας μόνο την τιμή reference.

Η τιμή reference πρέπει να χρησιμοποιείται μόνο μία φορά και σε μία μόνο συναλλαγή. Για τον σκοπό της συσχέτισης συναλλαγών με έναν Πάροχο Ενέργειας, λαμβάνεται υπόψη μόνο η πρώτη χρήση της τιμής reference ως έγκυρη.

Οι συναλλαγές μπορεί να έχουν πολλαπλές εντολές Memo. Κατά την εκτέλεση getSignaturesForAddress, τα αποτελέσματα του πεδίου memo θα επιστρέψουν το μήνυμα κάθε εντολής memo ως μία ενιαία συμβολοσειρά με κάθε μήνυμα διαχωρισμένο με ερωτηματικό.

Δεν πρέπει να συμπεριληφθούν άλλα δεδομένα με την εντολή Memo του Μηνύματος Αναγνώρισης.

Τα identity και reference θα πρέπει να συμπεριληφθούν ως μη υπογράφοντα κλειδιά μόνο για ανάγνωση keys στη συναλλαγή σε μια εντολή που ΔΕΝ είναι η εντολή Memo Μηνύματος Αναγνώρισης.

Η εντολή Memo Μηνύματος Αναγνώρισης πρέπει να έχει μηδέν λογαριασμούς. Εάν παρέχονται λογαριασμοί, το πρόγραμμα Memo απαιτεί αυτούς τους λογαριασμούς να είναι έγκυροι υπογράφοντες. Για τους σκοπούς αναγνώρισης ενεργειών, αυτό περιορίζει την ευελιξία και μπορεί να υποβαθμίσει την εμπειρία χρήστη. Επομένως θεωρείται αντι-μοτίβο και πρέπει να αποφεύγεται.

Επαλήθευση Ταυτότητας Ενέργειας

Οποιαδήποτε συναλλαγή που περιλαμβάνει τον λογαριασμό identity μπορεί να συσχετιστεί επαληθεύσιμα με τον Πάροχο Ενέργειας σε μια διαδικασία πολλαπλών βημάτων:

  1. Λήψη όλων των συναλλαγών για ένα δεδομένο identity.
  2. Ανάλυση και επαλήθευση της συμβολοσειράς memo κάθε συναλλαγής, διασφαλίζοντας ότι το signature είναι έγκυρο για το αποθηκευμένο reference.
  3. Επαλήθευση ότι η συγκεκριμένη συναλλαγή είναι η πρώτη onchain εμφάνιση του reference onchain:
    • Εάν αυτή η συναλλαγή είναι η πρώτη εμφάνιση, η συναλλαγή θεωρείται επαληθευμένη και μπορεί να αποδοθεί με ασφάλεια στον Πάροχο Ενέργειας.
    • Εάν αυτή η συναλλαγή ΔΕΝ είναι η πρώτη εμφάνιση, θεωρείται άκυρη και επομένως δεν αποδίδεται στον Πάροχο Ενέργειας.

Επειδή οι validator του Solana ευρετηριάζουν συναλλαγές βάσει κλειδιών λογαριασμού, η μέθοδος getSignaturesForAddress RPC μπορεί να χρησιμοποιηθεί για τον εντοπισμό όλων των συναλλαγών που περιλαμβάνουν τον λογαριασμό identity.

Η απόκριση αυτής της μεθόδου RPC περιλαμβάνει όλα τα δεδομένα Memo στο πεδίο memo. Εάν χρησιμοποιήθηκαν πολλαπλές εντολές Memo στη συναλλαγή, κάθε μήνυμα memo θα συμπεριληφθεί σε αυτό το πεδίο memo και πρέπει να αναλυθεί αναλόγως από τον επαληθευτή για την απόκτηση του Μηνύματος Επαλήθευσης Ταυτότητας.

Αυτές οι συναλλαγές θα πρέπει αρχικά να θεωρούνται ΜΗ ΕΠΑΛΗΘΕΥΜΕΝΕΣ. Αυτό οφείλεται στο γεγονός ότι το identity δεν απαιτείται να υπογράψει τη συναλλαγή, γεγονός που επιτρέπει σε οποιαδήποτε συναλλαγή να συμπεριλάβει αυτόν τον λογαριασμό ως μη υπογράφοντα. Αυτό ενδεχομένως τεχνητά να διογκώνει τις μετρήσεις απόδοσης και χρήσης.

Το Μήνυμα Επαλήθευσης Ταυτότητας θα πρέπει να ελεγχθεί για να διασφαλιστεί ότι το signature δημιουργήθηκε από το identity υπογράφοντας το reference. Εάν αυτή η επαλήθευση υπογραφής αποτύχει, η συναλλαγή είναι άκυρη και δεν θα πρέπει να αποδοθεί στον Πάροχο Ενέργειας.

Εάν η επαλήθευση υπογραφής είναι επιτυχής, ο επαληθευτής θα πρέπει να διασφαλίσει ότι αυτή η συναλλαγή είναι η πρώτη onchain εμφάνιση του reference. Εάν δεν είναι, η συναλλαγή θεωρείται άκυρη.

Is this page helpful?

© 2026 Ίδρυμα Solana. Με επιφύλαξη παντός δικαιώματος.