Samenvatting
Een standaardprotocol om Solana-transactieverzoeken te coderen binnen URL's om betalingen en andere gebruikssituaties mogelijk te maken.
Deze standaard is geïnspireerd door BIP 21 en EIP 681.
Motivatie
Een standaard URL-protocol voor het aanvragen van native SOL-overdrachten, SPL Token-overdrachten en Solana-transacties zorgt voor een betere gebruikerservaring binnen apps en wallets in het Solana-ecosysteem.
Deze URL's kunnen worden gecodeerd in QR-codes of NFC-tags, of verzonden tussen gebruikers en applicaties om betaling aan te vragen en transacties samen te stellen.
Applicaties moeten ervoor zorgen dat een transactie is bevestigd en geldig is voordat ze goederen of diensten vrijgeven die worden verkocht, of toegang verlenen tot objecten of evenementen.
Mobiele wallets moeten zich registreren om het URL-schema af te handelen en zo een naadloze maar veilige ervaring te bieden wanneer Solana Pay URL's worden aangetroffen.
Door een eenvoudige aanpak voor het oplossen van deze problemen te standaardiseren, waarborgen we basiscompatibiliteit van applicaties en wallets zodat ontwikkelaars zich kunnen richten op abstracties op een hoger niveau.
Specificatie: Overdrachtverzoek
Een Solana Pay-overdrachtverzoek-URL beschrijft een niet-interactief verzoek voor een SOL- of SPL Token-overdracht.
solana:<recipient>?amount=<amount>&spl-token=<spl-token>&reference=<reference>&label=<label>&message=<message>&memo=<memo>
Het verzoek is niet-interactief omdat de parameters in de URL door een wallet worden gebruikt om direct een transactie samen te stellen.
Ontvanger
Een enkel recipient-veld is verplicht als het pathname. De waarde moet de
base58-gecodeerde pubkey zijn van een native SOL-account. Associated token
accounts mogen niet worden gebruikt.
Om in plaats daarvan een SPL Token-overdracht aan te vragen, moet het
spl-token-veld worden gebruikt om een SPL Token mint te specificeren, waarvan
het associated token account-adres van de ontvanger moet worden afgeleid.
Bedrag
Een enkel amount veld is toegestaan als optionele queryparameter. De waarde
moet een niet-negatief geheel getal of decimaal getal zijn in
"gebruikers"-eenheden. Voor SOL, betekent dat SOL en niet lamports. Voor tokens,
gebruik
uiAmountString en niet amount.
0 is een geldige waarde. Als de waarde een decimaal getal is kleiner dan 1,
moet het een voorloopnul 0 hebben vóór de .. Wetenschappelijke notatie is
niet toegestaan.
Als er geen waarde wordt opgegeven, moet de wallet de gebruiker om het bedrag vragen. Als het aantal decimalen groter is dan wat ondersteund wordt voor SOL (9) of het SPL Token (mint-specifiek), moet de wallet de URL als onjuist geformatteerd afwijzen.
SPL Token
Een enkel spl-token veld is toegestaan als optionele queryparameter. De waarde
moet de base58-gecodeerde publieke sleutel zijn van een SPL Token mint account.
Als het veld is opgegeven, moet de
Associated Token Account
conventie worden gebruikt, en moet de wallet een TokenProgram.Transfer of
TokenProgram.TransferChecked instructie opnemen als laatste instructie van de
transactie.
Als het veld niet is opgegeven, beschrijft de URL een native SOL-overdracht, en
moet de wallet in plaats daarvan een SystemProgram.Transfer instructie opnemen
als laatste instructie van de transactie.
De wallet moet het ATA-adres afleiden uit de recipient en spl-token velden.
Overdrachten naar aanvullende token accounts worden niet ondersteund.
Referentie
Meerdere reference velden zijn toegestaan als optionele queryparameters. De
waarden moeten base58-gecodeerde 32-byte arrays zijn. Deze kunnen al dan niet
publieke sleutels zijn, op of buiten de curve, en kunnen al dan niet
overeenkomen met accounts op Solana.
Als de waarden worden verstrekt, moet de wallet deze in de opgegeven volgorde
opnemen als alleen-lezen, niet-ondertekende sleutels in de
SystemProgram.Transfer of
TokenProgram.Transfer/TokenProgram.TransferChecked instructie in de
betalingstransactie. De waarden kunnen al dan niet uniek zijn voor het
betalingsverzoek en kunnen al dan niet overeenkomen met een account op Solana.
Omdat Solana-validators transacties indexeren op deze accountsleutels, kunnen
reference waarden worden gebruikt als client-ID's (ID's die bruikbaar zijn
voordat de uiteindelijke betalingstransactie bekend is). De
getSignaturesForAddress
RPC-methode kan worden gebruikt om transacties op deze manier te lokaliseren.
Label
Een enkel label veld is toegestaan als optionele queryparameter. De waarde
moet een
URL-gecodeerde
UTF-8 string zijn die de bron van het overdrachtverzoek beschrijft.
Dit kan bijvoorbeeld de naam zijn van een merk, winkel, applicatie of persoon die het verzoek doet. De wallet moet de waarde URL-decoderen en de gedecodeerde waarde aan de gebruiker tonen.
Bericht
Een enkel message veld is toegestaan als optionele queryparameter. De waarde
moet een
URL-gecodeerde
UTF-8 string zijn die de aard van het overdrachtverzoek beschrijft.
Dit kan bijvoorbeeld de naam zijn van een artikel dat wordt gekocht, een order-ID of een bedankje. De wallet moet de waarde URL-decoderen en de gedecodeerde waarde aan de gebruiker tonen.
Memo
Een enkel memo veld is toegestaan als optionele queryparameter. De waarde moet
een
URL-gecodeerde
UTF-8 string zijn die moet worden opgenomen in een
SPL Memo instructie in de betalingstransactie.
De wallet moet de waarde URL-decoderen en zou de gedecodeerde waarde aan de gebruiker moeten tonen. De memo wordt geregistreerd door validators en mag geen privé- of gevoelige informatie bevatten.
Als het veld wordt verstrekt, moet de portemonnee een MemoProgram instructie
opnemen als de op één na laatste instructie van de transactie, direct vóór de
SOL- of SPL Token-overdracht instructie, om onduidelijkheid met andere
instructies in de transactie te voorkomen.
Voorbeelden
URL die een overdrachtverzoek voor 1 SOL beschrijft
solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=1&label=Michael&message=Thanks%20for%20all%20the%20fish&memo=OrderId12345
URL die een overdrachtverzoek voor 0,01 USDC beschrijft
solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=0.01&spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
URL die een overdrachtverzoek voor SOL beschrijft (gebruiker wordt gevraagd om bedrag)
solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael
Specificatie: Transactieverzoek
Een Solana Pay transactieverzoek-URL beschrijft een interactief verzoek voor elke Solana-transactie.
solana:<link>
Het verzoek is interactief omdat de parameters in de URL door een portemonnee worden gebruikt om een HTTP-verzoek te doen voor het samenstellen van een transactie.
Link
Een enkel link veld is vereist als het pad. De waarde moet een voorwaardelijk
URL-gecodeerde
absolute HTTPS-URL zijn.
Als de URL queryparameters bevat, moet deze URL-gecodeerd zijn. Protocolqueryparameters kunnen aan deze specificatie worden toegevoegd. URL-codering van de waarde voorkomt conflicten met protocolparameters.
Als de URL geen queryparameters bevat, hoeft deze niet URL-gecodeerd te zijn. Dit levert een kortere URL en een minder dichte QR-code op.
In beide gevallen moet de portemonnee de waarde URL-decoderen. Dit heeft geen effect als de waarde niet URL-gecodeerd is. Als de gedecodeerde waarde geen absolute HTTPS-URL is, moet de portemonnee deze als onjuist gevormd afwijzen.
GET-verzoek
De portemonnee moet een HTTP GET JSON-verzoek naar de URL doen. Het verzoek
mag de portemonnee of de gebruiker niet identificeren.
De portemonnee moet het verzoek doen met een Accept-Encoding header, en de applicatie moet reageren met een Content-Encoding header voor HTTP-compressie.
De wallet moet het domein van de URL weergeven terwijl het verzoek wordt gedaan.
GET Respons
De wallet moet HTTP
client error,
server error,
en
redirect responses
afhandelen. De applicatie moet hiermee reageren, of met een HTTP OK JSON
respons met een body van:
{ "label": "<label>", "icon": "<icon>" }
De <label> waarde moet een UTF-8 string zijn die de bron van het
transactieverzoek beschrijft. Dit kan bijvoorbeeld de naam zijn van een merk,
winkel, applicatie of persoon die het verzoek doet.
De <icon> waarde moet een absolute HTTP of HTTPS URL zijn van een
pictogramafbeelding. Het bestand moet een SVG, PNG of WebP afbeelding zijn, of
de wallet moet dit als onjuist geformatteerd afwijzen.
De wallet mag de respons niet cachen, behalve zoals geïnstrueerd door HTTP caching respons headers.
De wallet moet het label weergeven en de pictogramafbeelding aan de gebruiker tonen.
POST Verzoek
De wallet moet een HTTP POST JSON verzoek maken naar de URL met een body van:
{ "account": "<account>" }
De <account> waarde moet de base58-gecodeerde publieke sleutel zijn van een
account dat de transactie mag ondertekenen.
De wallet moet het verzoek doen met een Accept-Encoding header, en de applicatie moet reageren met een Content-Encoding header voor HTTP compressie.
De wallet moet het domein van de URL weergeven terwijl het verzoek wordt gedaan.
Als een GET verzoek is gedaan, moet de wallet ook het label weergeven en het
pictogram uit de respons tonen.
POST Respons
De wallet moet HTTP
client error,
server error,
en
redirect responses
afhandelen. De applicatie moet hiermee reageren, of met een HTTP OK JSON
respons met een body van:
{ "transaction": "<transaction>" }
De <transaction> waarde moet een base64-gecodeerde
geserialiseerde transactie
zijn. De wallet moet de transactie base64-decoderen en
deserialiseren.
De applicatie kan reageren met een gedeeltelijk of volledig ondertekende transactie. De wallet moet de transactie valideren als niet vertrouwd.
Lege handtekeningen
Als de transactie
signatures
leeg zijn:
- De applicatie moet de
feePayerinstellen op deaccountin het verzoek, of de nulwaarde (new PublicKey(0)ofnew PublicKey("11111111111111111111111111111111")). - De applicatie moet de
recentBlockhashinstellen op de nieuwste blockhash, of de nulwaarde (new PublicKey(0).toBase58()of"11111111111111111111111111111111"). - De wallet moet de
feePayerin de transactie negeren en defeePayerinstellen op deaccountin het verzoek. - De wallet moet de
recentBlockhashin de transactie negeren en derecentBlockhashinstellen op de nieuwste blockhash.
Niet-lege handtekeningen
Als de transactie
signatures
niet leeg zijn:
- De applicatie moet de
feePayerinstellen op de publieke sleutel van de eerste handtekening. - De applicatie moet de
recentBlockhashinstellen op de nieuwste blockhash. - De applicatie moet de transactie serialiseren en deserialiseren voordat deze wordt ondertekend. Dit zorgt voor consistente volgorde van de accountsleutels, als tijdelijke oplossing voor dit probleem.
- De wallet mag de
feePayerenrecentBlockhashniet instellen. - De wallet moet de handtekeningen verifiëren, en als een daarvan ongeldig is, moet de wallet de transactie afwijzen als onjuist gevormd.
De wallet mag de transactie alleen ondertekenen met de account in het verzoek,
en mag dit alleen doen als een handtekening voor de account in het verzoek
wordt verwacht.
Als een andere handtekening dan een handtekening voor de account in het
verzoek wordt verwacht, moet de wallet de transactie afwijzen als
kwaadaardig.
Optioneel Berichtveld
De applicatie kan ook een optioneel message veld opnemen in de responsbody:
{ "message": "<message>", "transaction": "<transaction>" }
De <message> waarde moet een UTF-8 string zijn die de aard van het
transactierespons beschrijft.
Dit kan bijvoorbeeld de naam zijn van een artikel dat wordt gekocht, een korting die op de aankoop wordt toegepast, of een bedankbericht. De wallet moet de waarde aan de gebruiker tonen.
De wallet en applicatie moeten aanvullende velden in de request body en response body toestaan, die door toekomstige specificaties kunnen worden toegevoegd.
Voorbeelden
URL die een transactieverzoek beschrijft
solana:https://example.com/solana-pay
URL die een transactieverzoek met queryparameters beschrijft
solana:https%3A%2F%2Fexample.com%2Fsolana-pay%3Forder%3D12345
Voorbeeld van een GET-verzoek
GET /solana-pay?order=12345 HTTP/1.1Host: example.comConnection: closeAccept: application/jsonAccept-Encoding: br, gzip, deflate
Voorbeeld van een GET-respons
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 62Content-Encoding: gzip{"label":"Michael Vines","icon":"https://example.com/icon.svg"}
Voorbeeld van een POST-verzoek
POST /solana-pay?order=12345 HTTP/1.1Host: example.comConnection: closeAccept: application/jsonAccept-Encoding: br, gzip, deflateContent-Type: application/jsonContent-Length: 57{"account":"mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN"}
Voorbeeld van een POST-respons
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 298Content-Encoding: gzip{"message":"Thanks for all the fish","transaction":"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECC4JMKqNplIXybGb/GhK1ofdVWeuEjXnQor7gi0Y2hMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAMAgAAAAAAAAAAAAAA"}
Uitbreidingen
Aanvullende formats en velden kunnen in deze specificatie worden opgenomen om nieuwe gebruiksscenario's mogelijk te maken, terwijl compatibiliteit met apps en wallets wordt gewaarborgd.
Open een Github-issue om wijzigingen in de specificatie voor te stellen en zo feedback van applicatie- en walletontwikkelaars te verzamelen.
Een concreet voorbeeld van zo'n voorstel.
Zie ook
- Solana Pay Specificatie v1.1 - Nieuwste versie met verbeteringen
- Snelstartgids - Implementatiehandleidingen
- GitHub Repository - Referentie-implementaties
Is this page helpful?