Solana Pay Spezifikation v1.1

Zusammenfassung

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

Ein grober Konsens über diese Spezifikation wurde erreicht, und Implementierungen existieren in Phantom, FTX und Slope.

Dieser Standard orientiert sich an 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 Benutzern 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, die verkauft werden, oder Zugang zu Objekten oder Veranstaltungen gewähren.

Mobile Wallets sollten sich registrieren, um das URL-Schema zu verarbeiten und 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 gewährleisten wir grundlegende Kompatibilität von Anwendungen und Wallets, 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-Kontos sein. Associated Token Accounts dürfen nicht verwendet werden.

Stattdessen muss das Feld spl-token verwendet werden, um eine SPL-Token-Mint anzugeben, von der die zugehörige Token-Adresse des Empfängers abgeleitet werden muss.

Betrag

Ein einzelnes Feld amount ist als optionaler Abfrageparameter zulässig. Der Wert muss eine nicht-negative Ganzzahl oder Dezimalzahl in "Benutzer"-Einheiten sein. Für SOL bedeutet das SOL und nicht Lamports. Für Token verwenden Sie uiAmountString und nicht amount.

0 ist ein gültiger Wert. Wenn der Wert eine Dezimalzahl kleiner als 1 ist, muss er eine führende 0 vor dem . haben. 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 Feld spl-token ist als optionaler Abfrageparameter zulässig. Der Wert muss der base58-codierte ö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 Anweisung TokenProgram.Transfer oder TokenProgram.TransferChecked 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 Anweisung SystemProgram.Transfer als letzte Anweisung der Transaktion einfügen.

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

Referenz

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

Wenn die Werte bereitgestellt werden, muss das 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 einschließen. Die Werte können für die Zahlungsanforderung eindeutig sein oder nicht und können einem Konto auf Solana entsprechen oder nicht.

Da Solana-Validatoren Transaktionen anhand dieser Kontoschlüssel indexieren, 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.

Label

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 Anfrage stellt. Das 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 gekauften Artikels, eine Bestellnummer oder eine Danksagung sein. Das 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.

Das 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.

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

Beispiele

URL, die eine Übertragungsanfrage für 1 SOL beschreibt

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

URL, die eine Übertragungsanfrage für 0,01 USDC beschreibt

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

URL, die eine Übertragungsanfrage für SOL beschreibt (Benutzer wird zur Eingabe des Betrags aufgefordert)

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 zum Erstellen einer Transaktion zu stellen.

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

Wenn die URL Abfrageparameter enthält, muss sie URL-codiert sein. Protokollabfrageparameter können zu dieser Spezifikation hinzugefügt werden. Die URL-Codierung des Werts verhindert Konflikte mit Protokollparametern.

Wenn die URL keine Abfrageparameter enthält, sollte sie nicht URL-codiert sein. Dies erzeugt eine kürzere URL und einen weniger dichten QR-Code.

In beiden Fällen muss die Wallet den Wert URL-decodieren. Dies hat keine Auswirkung, wenn der Wert nicht URL-codiert ist. Wenn der decodierte 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.

Die Wallet sollte die Domain der URL anzeigen, während die Anfrage gestellt wird.

GET-Antwort

Die 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 die Wallet sie als fehlerhaft ablehnen.

Die Wallet sollte die Antwort nicht zwischenspeichern, außer wie durch HTTP-Caching-Antwortheader angewiesen.

Die Wallet sollte das Label anzeigen und das Icon-Bild für den Benutzer rendern.

POST-Anfrage

Die Wallet muss eine HTTP-POST-JSON-Anfrage an die URL mit folgendem Body stellen:

{ "account": "<account>" }

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

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.

Die Wallet sollte die Domain der URL anzeigen, während die Anfrage gestellt wird. Wenn eine GET-Anfrage gestellt wurde, sollte die Wallet auch das Label anzeigen und das Icon-Bild aus der Antwort rendern.

POST-Antwort

Die 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-codierte serialisierte Transaktion sein. Das Wallet muss die Transaktion base64-decodieren und deserialisieren.

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

Leere Signaturen

Wenn die signatures der Transaktion 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.
  • Das Wallet muss den feePayer in der Transaktion ignorieren und den feePayer auf den account in der Anfrage setzen.
  • Das Wallet muss den recentBlockhash in der Transaktion ignorieren und den recentBlockhash auf den neuesten Blockhash setzen.

Wenn die signatures der Transaktion nicht leer sind:

Das Wallet darf die Transaktion nur mit dem account in der Anfrage signieren, und zwar nur dann, wenn eine Signatur für den account in der Anfrage erwartet wird.

Wenn eine andere Signatur als eine Signatur für den account in der Anfrage erwartet wird, muss das Wallet die Transaktion als bösartig ablehnen.

Die Anwendung kann auch ein optionales message-Feld im Antworttext 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 Dankesnachricht sein. Das Wallet sollte den Wert dem Benutzer anzeigen.

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

Beispiel

URL, die eine Transaktionsanfrage beschreibt.
solana:https://example.com/solana-pay
URL, die eine Transaktionsanfrage mit Abfrageparametern beschreibt.
solana:https%3A%2F%2Fexample.com%2Fsolana-pay%3Forder%3D12345
GET-Anfrage
GET /solana-pay?order=12345 HTTP/1.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate
GET-Antwort
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
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
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.

Is this page helpful?

Verwaltet von

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