Samenvatting
Een standaardprotocol voor het coderen van Solana-transactieverzoeken binnen URL's om betalingen en andere gebruikssituaties mogelijk te maken.
Er is een ruwe consensus bereikt over deze specificatie, en implementaties bestaan in Phantom, FTX en Slope.
Deze standaard is geïnspireerd op 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 worden 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 én 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 basis- compatibiliteit van applicaties en wallets, zodat ontwikkelaars zich kunnen richten op abstraties op hoger niveau.
Specificatie: Overdrachtsverzoek
Een Solana Pay overdrachtsverzoek-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 vereist als het pathname. De waarde moet de
base58-gecodeerde pubkey zijn van een native SOL account. Associated token
accounts mogen niet worden gebruikt.
In plaats daarvan moet het spl-token veld worden gebruikt om een SPL Token
mint op te geven, waarvan het bijbehorende tokenadres 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 is 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 leidende 0 voor de . hebben. Wetenschappelijke notatie is niet
toegestaan.
Als er geen waarde is opgegeven, moet de wallet de gebruiker vragen om het bedrag. Als het aantal decimalen meer is dan wat wordt ondersteund voor SOL (9) of de SPL Token (mint-specifiek), moet de wallet de URL afwijzen als onjuist geformatteerd.
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 wordt opgegeven, moet de
Associated Token Account
conventie worden gebruikt, en moet de wallet een TokenProgram.Transfer of
TokenProgram.TransferChecked instructie opnemen als de laatste instructie van
de transactie.
Als het veld niet wordt opgegeven, beschrijft de URL een native SOL-overdracht,
en moet de wallet in plaats daarvan een SystemProgram.Transfer instructie
opnemen als de laatste instructie van de transactie.
De wallet moet het ATA-adres afleiden uit de recipient en spl-token velden.
Overdrachten naar auxiliaire tokenaccounts 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 aangegeven volgorde
opnemen als alleen-lezen, niet-ondertekende sleutels voor 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 basis van 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 op deze manier worden gebruikt om transacties te lokaliseren.
Label
Een enkel label veld is toegestaan als optionele queryparameter. De waarde
moet een
URL-gecodeerde
UTF-8 tekenreeks zijn die de bron van het overdrachtsverzoek 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 tekenreeks zijn die de aard van het overdrachtsverzoek 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 tekenreeks 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 door validators vastgelegd en mag geen privé- of gevoelige informatie bevatten.
Als het veld is opgegeven, moet de wallet 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 dubbelzinnigheid 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 wallet worden gebruikt om een HTTP-verzoek te doen om een transactie samen te stellen.
Link
Een enkel link veld is vereist als pathname. 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 wallet 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 wallet deze als onjuist geformatteerd afwijzen.
GET-verzoek
De wallet moet een HTTP GET JSON-verzoek naar de URL doen. Het verzoek mag de
wallet of de gebruiker niet identificeren.
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.
GET Response
De wallet moet HTTP
client errors,
server errors
en
redirect responses
afhandelen. De applicatie moet hiermee reageren, of met een HTTP OK JSON
response 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 icon
afbeelding. Het bestand moet een SVG, PNG of WebP afbeelding zijn, anders moet
de wallet het als malformed afwijzen.
De wallet mag de response niet cachen, behalve zoals aangegeven door HTTP caching response headers.
De wallet moet het label weergeven en de icon afbeelding aan de gebruiker tonen.
POST Request
De wallet moet een HTTP POST JSON request doen 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 request is gedaan, moet de wallet ook het label weergeven en de
icon afbeelding uit de response tonen.
POST Response
De wallet moet HTTP
client errors,
server errors
en
redirect responses
afhandelen. De applicatie moet hiermee reageren, of met een HTTP OK JSON
response 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 laatste 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 laatste blockhash.
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 laatste blockhash. - De applicatie moet de transactie serialiseren en deserialiseren voordat deze wordt ondertekend. Dit zorgt voor een 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 deze ongeldig zijn, moet de wallet de transactie afwijzen als onjuist geformatteerd.
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.
De applicatie kan ook een optioneel message veld opnemen in de response body:
{ "message": "<message>", "transaction": "<transaction>" }
De <message> waarde moet een UTF-8 string zijn die de aard van het
transactie-antwoord beschrijft.
Dit kan bijvoorbeeld de naam zijn van een artikel dat wordt gekocht, een korting die op de aankoop wordt toegepast, of een bedankje. De wallet moet de waarde aan de gebruiker tonen.
De wallet en applicatie moeten extra velden in de request body en response body toestaan, die mogelijk door toekomstige specificaties worden toegevoegd.
Voorbeeld
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
GET-verzoek
GET /solana-pay?order=12345 HTTP/1.1Host: example.comConnection: closeAccept: application/jsonAccept-Encoding: br, gzip, deflate
GET-antwoord
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 62Content-Encoding: gzip{"label":"Michael Vines","icon":"https://example.com/icon.svg"}
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"}
POST-antwoord
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 use cases 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 wallet-ontwikkelaars te verkrijgen.
Is this page helpful?