Solana Pay Spezifikation v1

Zusammenfassung

Ein Standardprotokoll zur Kodierung von Solana-Transaktionsanfragen in URLs, um Zahlungen und andere Anwendungsfälle zu ermöglichen.

Dieser Standard ist inspiriert von BIP 21 und EIP 681.

Motivation

Ein Standard-URL-Protokoll für die Anforderung nativer SOL-Überweisungen, SPL-Token- Überweisungen und Solana-Transaktionen ermöglicht eine bessere Benutzererfahrung über Apps und Wallets im Solana-Ökosystem hinweg.

Diese URLs können in QR-Codes oder NFC-Tags kodiert oder zwischen Nutzern und Anwendungen gesendet werden, um Zahlungen anzufordern und Transaktionen zu erstellen.

Anwendungen sollten sicherstellen, dass eine Transaktion bestätigt wurde und gültig ist, bevor sie Waren oder Dienstleistungen freigeben oder Zugang zu Objekten oder Veranstaltungen gewähren.

Mobile Wallets sollten sich registrieren, um das URL-Schema zu verarbeiten und so eine nahtlose und dennoch sichere Erfahrung zu bieten, wenn Solana Pay URLs in der Umgebung angetroffen werden.

Durch die Standardisierung eines einfachen Ansatzes zur Lösung dieser Probleme stellen wir grundlegende Kompatibilität von Anwendungen und Wallets sicher, sodass sich Entwickler auf höhere Abstraktionsebenen konzentrieren können.

Spezifikation: Überweisungsanfrage

Eine Solana Pay Überweisungsanfrage-URL beschreibt eine nicht-interaktive Anfrage für eine SOL- oder SPL-Token-Überweisung.

solana:<recipient>
?amount=<amount>
&spl-token=<spl-token>
&reference=<reference>
&label=<label>
&message=<message>
&memo=<memo>

Die Anfrage ist nicht-interaktiv, da die Parameter in der URL von einer Wallet verwendet werden, um direkt eine Transaktion zu erstellen.

Empfänger

Ein einzelnes recipient-Feld ist als Pfadname erforderlich. Der Wert muss der base58-kodierte öffentliche Schlüssel eines nativen SOL-Konten sein. Associated Token Accounts dürfen nicht verwendet werden.

Um stattdessen eine SPL-Token-Überweisung anzufordern, muss das spl-token-Feld verwendet werden, um eine SPL-Token-Mint anzugeben, von der die associated token account-Adresse des Empfängers abgeleitet werden muss.

Betrag

Ein einzelnes amount-Feld ist als optionaler Abfrageparameter zulässig. Der Wert muss eine nicht-negative ganze Zahl oder Dezimalzahl in „Benutzer“-Einheiten sein. Bei SOL sind das SOL und nicht Lamports. Verwenden Sie bei Token uiAmountString und nicht amount.

0 ist ein gültiger Wert. Wenn der Wert eine Dezimalzahl kleiner als 1 ist, muss vor dem . eine führende 0 stehen. Wissenschaftliche Notation ist nicht zulässig.

Wenn kein Wert angegeben wird, muss die Wallet den Benutzer zur Eingabe des Betrags auffordern. Wenn die Anzahl der Dezimalstellen die für SOL (9) oder das SPL-Token (Mint-spezifisch) unterstützte Anzahl überschreitet, muss die Wallet die URL als fehlerhaft ablehnen.

SPL-Token

Ein einzelnes spl-token-Feld ist als optionaler Abfrageparameter zulässig. Der Wert muss der base58-kodierte öffentliche Schlüssel eines SPL-Token-Mint-Kontos sein.

Wenn das Feld angegeben wird, muss die Associated Token Account-Konvention verwendet werden, und die Wallet muss eine TokenProgram.Transfer- oder TokenProgram.TransferChecked- Anweisungen als letzte Anweisung der Transaktion einfügen.

Wenn das Feld nicht angegeben wird, beschreibt die URL eine native SOL-Übertragung, und die Wallet muss stattdessen eine SystemProgram.Transfer- Anweisungen als letzte Anweisung der Transaktion einfügen.

Die Wallet muss die ATA-Adresse aus den Feldern recipient und spl-token ableiten. Überweisungen an zusätzliche Token-Konten werden nicht unterstützt.

Referenz

Mehrere reference-Felder sind als optionale Abfrageparameter zulässig. Die Werte müssen base58-kodierte 32-Byte-Arrays sein. Diese können öffentliche Schlüssel sein oder auch nicht, auf oder außerhalb der Kurve, und können Konten auf Solana entsprechen oder auch nicht.

Wenn die Werte bereitgestellt werden, muss die Wallet sie in der angegebenen Reihenfolge als schreibgeschützte, nicht signierende Schlüssel in die SystemProgram.Transfer- oder TokenProgram.Transfer/TokenProgram.TransferChecked-Anweisung in der Zahlungstransaktion einfügen. Die Werte können, müssen aber nicht eindeutig für die Zahlungsanforderung sein und können, müssen aber nicht einem Konto auf Solana entsprechen.

Da Solana-Validatoren Transaktionen anhand dieser Kontoschlüssel indizieren, können reference-Werte als Client-IDs verwendet werden (IDs, die verwendet werden können, bevor die endgültige Zahlungstransaktion bekannt ist). Die RPC-Methode getSignaturesForAddress kann verwendet werden, um Transaktionen auf diese Weise zu lokalisieren.

Beschriftung

Ein einzelnes label-Feld ist als optionaler Abfrageparameter zulässig. Der Wert muss eine URL-kodierte UTF-8-Zeichenkette sein, die die Quelle der Übertragungsanforderung beschreibt.

Dies könnte beispielsweise der Name einer Marke, eines Geschäfts, einer Anwendung oder einer Person sein, die die Anforderung stellt. Die Wallet sollte den Wert URL-dekodieren und den dekodierten Wert dem Benutzer anzeigen.

Nachricht

Ein einzelnes message-Feld ist als optionaler Abfrageparameter zulässig. Der Wert muss eine URL-kodierte UTF-8-Zeichenkette sein, die die Art der Übertragungsanforderung beschreibt.

Dies könnte beispielsweise der Name eines zu kaufenden Artikels, eine Bestellnummer oder eine Danksagung sein. Die Wallet sollte den Wert URL-dekodieren und den dekodierten Wert dem Benutzer anzeigen.

Memo

Ein einzelnes memo-Feld ist als optionaler Abfrageparameter zulässig. Der Wert muss eine URL-kodierte UTF-8-Zeichenkette sein, die in einer SPL Memo-Anweisung in der Zahlungstransaktion enthalten sein muss.

Die Wallet muss den Wert URL-dekodieren und sollte den dekodierten Wert dem Benutzer anzeigen. Das Memo wird von Validatoren aufgezeichnet und sollte keine privaten oder sensiblen Informationen enthalten.

Falls das Feld angegeben wird, muss die Wallet eine MemoProgram-Anweisung als vorletzte Anweisung der Transaktion einfügen, unmittelbar vor der SOL- oder SPL-Token-Transferanweisung, um Mehrdeutigkeiten mit anderen Anweisungen in der Transaktion zu vermeiden.

Beispiele

URL, die eine Transferanfrage für 1 SOL beschreibt

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=1&label=Michael&message=Thanks%20for%20all%20the%20fish&memo=OrderId12345

URL, die eine Transferanfrage für 0,01 USDC beschreibt

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=0.01&spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

URL, die eine Transferanfrage für SOL beschreibt (Benutzer wird nach Betrag gefragt)

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael

Spezifikation: Transaktionsanfrage

Eine Solana Pay-Transaktionsanfrage-URL beschreibt eine interaktive Anfrage für jede beliebige Solana-Transaktion.

solana:<link>

Die Anfrage ist interaktiv, da die Parameter in der URL von einer Wallet verwendet werden, um eine HTTP-Anfrage zur Zusammenstellung einer Transaktion zu stellen.

Ein einzelnes link-Feld ist als Pfadname erforderlich. Der Wert muss eine bedingt URL-kodierte absolute HTTPS-URL sein.

Falls die URL Query-Parameter enthält, muss sie URL-kodiert sein. Protokoll-Query-Parameter können dieser Spezifikation hinzugefügt werden. Die URL-Kodierung des Werts verhindert Konflikte mit Protokollparametern.

Falls die URL keine Query-Parameter enthält, sollte sie nicht URL-kodiert sein. Dies erzeugt eine kürzere URL und einen weniger dichten QR-Code.

In jedem Fall muss die Wallet den Wert URL-dekodieren. Dies hat keine Auswirkung, wenn der Wert nicht URL-kodiert ist. Falls der dekodierte Wert keine absolute HTTPS-URL ist, muss die Wallet ihn als fehlerhaft ablehnen.

GET-Anfrage

Die Wallet sollte eine HTTP-GET-JSON-Anfrage an die URL stellen. Die Anfrage sollte weder die Wallet noch den Benutzer identifizieren.

Die Wallet sollte die Anfrage mit einem Accept-Encoding-Header stellen, und die Anwendung sollte mit einem Content-Encoding-Header für HTTP-Komprimierung antworten.

Das Wallet sollte die Domain der URL anzeigen, während die Anfrage durchgeführt wird.

GET-Antwort

Das Wallet muss HTTP- Client-Fehler, Server-Fehler und Weiterleitungsantworten verarbeiten. Die Anwendung muss mit diesen oder mit einer HTTP OK JSON-Antwort mit folgendem Body antworten:

{ "label": "<label>", "icon": "<icon>" }

Der <label>-Wert muss eine UTF-8-Zeichenkette sein, die die Quelle der Transaktionsanfrage beschreibt. Dies könnte beispielsweise der Name einer Marke, eines Geschäfts, einer Anwendung oder einer Person sein, die die Anfrage stellt.

Der <icon>-Wert muss eine absolute HTTP- oder HTTPS-URL eines Icon-Bildes sein. Die Datei muss ein SVG-, PNG- oder WebP-Bild sein, andernfalls muss das Wallet sie als fehlerhaft ablehnen.

Das Wallet sollte die Antwort nicht zwischenspeichern, außer dies wird durch HTTP-Caching- Antwort-Header angewiesen.

Das Wallet sollte das Label anzeigen und das Icon-Bild für den Benutzer darstellen.

POST-Anfrage

Das Wallet muss eine HTTP POST JSON-Anfrage an die URL mit folgendem Body senden:

{ "account": "<account>" }

Der <account>-Wert muss der base58-kodierte öffentliche Schlüssel eines Kontos sein, das die Transaktion signieren darf.

Das Wallet sollte die Anfrage mit einem Accept-Encoding-Header senden, und die Anwendung sollte mit einem Content-Encoding-Header für HTTP-Komprimierung antworten.

Das Wallet sollte die Domain der URL anzeigen, während die Anfrage durchgeführt wird. Wenn eine GET-Anfrage durchgeführt wurde, sollte das Wallet außerdem das Label anzeigen und das Icon-Bild aus der Antwort darstellen.

POST-Antwort

Das Wallet muss HTTP- Client-Fehler, Server-Fehler und Weiterleitungsantworten verarbeiten. Die Anwendung muss mit diesen oder mit einer HTTP OK JSON-Antwort mit folgendem Body antworten:

{ "transaction": "<transaction>" }

Der <transaction>-Wert muss eine base64-kodierte serialisierte Transaktion sein. Die Wallet muss die Transaktion base64-dekodieren und deserialisieren.

Die Anwendung kann mit einer teilweise oder vollständig signierten Transaktion antworten. Die Wallet muss die Transaktion als nicht vertrauenswürdig validieren.

Leere Signaturen

Wenn die Transaktions- signatures leer sind:

  • Die Anwendung sollte den feePayer auf den account in der Anfrage oder auf den Nullwert (new PublicKey(0) oder new PublicKey("11111111111111111111111111111111")) setzen.
  • Die Anwendung sollte den recentBlockhash auf den neuesten Blockhash oder auf den Nullwert (new PublicKey(0).toBase58() oder "11111111111111111111111111111111") setzen.
  • Die Wallet muss den feePayer in der Transaktion ignorieren und den feePayer auf den account in der Anfrage setzen.
  • Die Wallet muss den recentBlockhash in der Transaktion ignorieren und den recentBlockhash auf den neuesten Blockhash setzen.

Nicht-leere Signaturen

Wenn die Transaktions- signatures nicht leer sind:

Die Wallet darf die Transaktion nur mit dem account in der Anfrage signieren, und muss dies nur tun, wenn eine Signatur für den account in der Anfrage erwartet wird.

Falls irgendeine Signatur außer einer Signatur für den account in der Anfrage erwartet wird, muss die Wallet die Transaktion als bösartig ablehnen.

Optionales Nachrichtenfeld

Die Anwendung kann auch ein optionales message-Feld im Antwortkörper enthalten:

{ "message": "<message>", "transaction": "<transaction>" }

Der <message>-Wert muss eine UTF-8-Zeichenkette sein, die die Art der Transaktionsantwort beschreibt.

Dies könnte beispielsweise der Name eines gekauften Artikels, ein auf den Kauf angewendeter Rabatt oder eine Danksagung sein. Das Wallet sollte den Wert dem Benutzer anzeigen.

Das Wallet und die Anwendung sollten zusätzliche Felder im Anfragekörper und Antwortkörper zulassen, die durch zukünftige Spezifikationen hinzugefügt werden können.

Beispiele

URL zur Beschreibung einer Transaktionsanfrage

solana:https://example.com/solana-pay

URL zur Beschreibung einer Transaktionsanfrage mit Abfrageparametern

solana:https%3A%2F%2Fexample.com%2Fsolana-pay%3Forder%3D12345

GET-Anfrage-Beispiel

GET /solana-pay?order=12345 HTTP/1.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate

GET-Antwort-Beispiel

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Content-Length: 62
Content-Encoding: gzip
{"label":"Michael Vines","icon":"https://example.com/icon.svg"}

POST-Anfrage-Beispiel

POST /solana-pay?order=12345 HTTP/1.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate
Content-Type: application/json
Content-Length: 57
{"account":"mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN"}

POST-Antwort-Beispiel

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Content-Length: 298
Content-Encoding: gzip
{"message":"Thanks for all the fish","transaction":"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECC4JMKqNplIXybGb/GhK1ofdVWeuEjXnQor7gi0Y2hMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAMAgAAAAAAAAAAAAAA"}

Erweiterungen

Zusätzliche Formate und Felder können in diese Spezifikation aufgenommen werden, um neue Anwendungsfälle zu ermöglichen und gleichzeitig die Kompatibilität mit Apps und Wallets sicherzustellen.

Bitte öffnen Sie ein Github-Issue, um Änderungen an der Spezifikation vorzuschlagen und Feedback von Anwendungs- und Wallet-Entwicklern einzuholen.

Ein tatsächliches Beispiel für einen solchen Vorschlag.

Siehe auch

Is this page helpful?

Verwaltet von

© 2026 Solana Foundation.
Alle Rechte vorbehalten.
Verbinden Sie sich