Spesifikasi Solana Pay v1.1

Ringkasan

Protokol standar untuk mengodekan permintaan transaksi Solana dalam URL guna memungkinkan pembayaran dan kasus penggunaan lainnya.

Konsensus kasar mengenai spesifikasi ini telah tercapai, dan implementasinya sudah ada di Phantom, FTX, dan Slope.

Standar ini mengambil inspirasi dari BIP 21 dan EIP 681.

Motivasi

Protokol URL standar untuk meminta transfer SOL native, transfer Token SPL, dan transaksi Solana memungkinkan pengalaman pengguna yang lebih baik di seluruh aplikasi dan dompet dalam ekosistem Solana.

URL ini dapat dikodekan dalam kode QR atau tag NFC, atau dikirim antara pengguna dan aplikasi untuk meminta pembayaran dan menyusun transaksi.

Aplikasi harus memastikan bahwa transaksi telah dikonfirmasi dan valid sebelum mereka merilis barang atau layanan yang dijual, atau memberikan akses ke objek atau acara.

Dompet seluler harus terdaftar untuk menangani skema URL guna memberikan pengalaman yang mulus namun aman ketika URL Solana Pay ditemukan di lingkungan.

Dengan menstandarkan pendekatan sederhana untuk menyelesaikan masalah-masalah ini, kami memastikan kompatibilitas dasar aplikasi dan dompet sehingga pengembang dapat fokus pada abstraksi tingkat yang lebih tinggi.

Spesifikasi: Permintaan Transfer

URL permintaan transfer Solana Pay mendeskripsikan permintaan non-interaktif untuk transfer SOL atau Token SPL.

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

Permintaan bersifat non-interaktif karena parameter dalam URL digunakan oleh dompet untuk langsung menyusun transaksi.

Penerima

Satu field recipient diperlukan sebagai pathname. Nilainya harus berupa pubkey yang dikodekan base58 dari akun SOL native. associated token account tidak boleh digunakan.

Sebaliknya, untuk meminta transfer SPL Token, field spl-token harus digunakan untuk menentukan mint SPL Token, dari mana alamat token terkait penerima harus diturunkan.

Jumlah

Satu field amount diperbolehkan sebagai parameter query opsional. Nilainya harus berupa bilangan bulat non-negatif atau desimal dalam satuan "pengguna". Untuk SOL, itu adalah SOL dan bukan lamport. Untuk token, gunakan uiAmountString dan bukan amount.

0 adalah nilai yang valid. Jika nilainya adalah bilangan desimal kurang dari 1, harus memiliki 0 di depan sebelum .. Notasi ilmiah dilarang.

Jika nilai tidak disediakan, wallet harus meminta pengguna untuk memasukkan jumlah. Jika jumlah tempat desimal melebihi yang didukung untuk SOL (9) atau SPL Token (spesifik mint), wallet harus menolak URL sebagai tidak valid.

SPL Token

Satu field spl-token diperbolehkan sebagai parameter query opsional. Nilainya harus berupa pubkey yang dikodekan base58 dari akun mint SPL Token.

Jika field disediakan, konvensi Associated Token Account harus digunakan, dan wallet harus menyertakan instruksi TokenProgram.Transfer atau TokenProgram.TransferChecked sebagai instruksi terakhir dari transaksi.

Jika field tidak disediakan, URL mendeskripsikan transfer SOL native, dan wallet harus menyertakan instruksi SystemProgram.Transfer sebagai instruksi terakhir dari transaksi.

Wallet harus menurunkan alamat ATA dari field recipient dan spl-token. Transfer ke akun token tambahan tidak didukung.

Referensi

Beberapa field reference diperbolehkan sebagai parameter query opsional. Nilainya harus berupa array 32 byte yang dikodekan base58. Ini bisa atau tidak bisa berupa pubkey, di atau di luar kurva, dan mungkin atau tidak sesuai dengan akun di Solana.

Jika nilai disediakan, dompet harus menyertakannya dalam urutan yang diberikan sebagai kunci read-only, non-signer ke instruksi SystemProgram.Transfer atau TokenProgram.Transfer/TokenProgram.TransferChecked dalam transaksi pembayaran. Nilai tersebut mungkin unik atau tidak untuk permintaan pembayaran, dan mungkin sesuai atau tidak dengan akun di Solana.

Karena validator Solana mengindeks transaksi berdasarkan kunci akun ini, nilai reference dapat digunakan sebagai ID klien (ID yang dapat digunakan sebelum mengetahui transaksi pembayaran akhir). Metode RPC getSignaturesForAddress dapat digunakan untuk menemukan transaksi dengan cara ini.

Label

Satu bidang label diperbolehkan sebagai parameter query opsional. Nilainya harus berupa string UTF-8 yang di-encode URL yang menjelaskan sumber permintaan transfer.

Sebagai contoh, ini mungkin nama merek, toko, aplikasi, atau orang yang membuat permintaan. Dompet harus melakukan decode URL pada nilai tersebut dan menampilkan nilai yang telah di-decode kepada pengguna.

Pesan

Satu bidang message diperbolehkan sebagai parameter query opsional. Nilainya harus berupa string UTF-8 yang di-encode URL yang menjelaskan sifat permintaan transfer.

Sebagai contoh, ini mungkin nama barang yang dibeli, ID pesanan, atau ucapan terima kasih. Dompet harus melakukan decode URL pada nilai tersebut dan menampilkan nilai yang telah di-decode kepada pengguna.

Memo

Satu bidang memo diperbolehkan sebagai parameter query opsional. Nilainya harus berupa string UTF-8 yang di-encode URL yang harus disertakan dalam instruksi SPL Memo dalam transaksi pembayaran.

Dompet harus melakukan decode URL pada nilai tersebut dan sebaiknya menampilkan nilai yang telah di-decode kepada pengguna. Memo akan dicatat oleh validator dan tidak boleh menyertakan informasi pribadi atau sensitif.

Jika field disediakan, wallet harus menyertakan instruksi MemoProgram sebagai instruksi kedua dari terakhir dalam transaksi, tepat sebelum instruksi transfer SOL atau SPL Token, untuk menghindari ambiguitas dengan instruksi lain dalam transaksi.

Contoh

URL yang mendeskripsikan permintaan transfer untuk 1 SOL

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

URL yang mendeskripsikan permintaan transfer untuk 0.01 USDC

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

URL yang mendeskripsikan permintaan transfer untuk SOL (pengguna diminta memasukkan jumlah)

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael

Spesifikasi: Permintaan Transaksi

URL permintaan transaksi Solana Pay mendeskripsikan permintaan interaktif untuk transaksi Solana apa pun.

solana:<link>

Permintaan bersifat interaktif karena parameter dalam URL digunakan oleh wallet untuk membuat permintaan HTTP guna menyusun transaksi.

Satu field link diperlukan sebagai pathname. Nilainya harus berupa URL HTTPS absolut yang di-encode secara kondisional sesuai URL-encoding.

Jika URL mengandung parameter query, URL tersebut harus di-encode. Parameter query protokol mungkin ditambahkan ke spesifikasi ini. URL-encoding nilai mencegah konflik dengan parameter protokol.

Jika URL tidak mengandung parameter query, sebaiknya tidak di-encode. Ini menghasilkan URL yang lebih pendek dan kode QR yang kurang padat.

Dalam kedua kasus, wallet harus melakukan URL-decode pada nilai tersebut. Ini tidak berpengaruh jika nilai tidak di-encode. Jika nilai yang di-decode bukan URL HTTPS absolut, wallet harus menolaknya sebagai tidak valid.

Permintaan GET

Wallet sebaiknya membuat permintaan JSON GET HTTP ke URL. Permintaan sebaiknya tidak mengidentifikasi wallet atau pengguna.

Wallet sebaiknya membuat permintaan dengan header Accept-Encoding, dan aplikasi sebaiknya merespons dengan header Content-Encoding untuk kompresi HTTP.

Dompet harus menampilkan domain dari URL saat permintaan sedang dibuat.

Respons GET

Dompet harus menangani kesalahan klien HTTP, kesalahan server, dan respons pengalihan. Aplikasi harus merespons dengan ini, atau dengan respons JSON HTTP OK dengan body:

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

Nilai <label> harus berupa string UTF-8 yang menjelaskan sumber dari permintaan transaksi. Sebagai contoh, ini bisa berupa nama merek, toko, aplikasi, atau orang yang membuat permintaan.

Nilai <icon> harus berupa URL HTTP atau HTTPS absolut dari gambar ikon. File tersebut harus berupa gambar SVG, PNG, atau WebP, atau dompet harus menolaknya sebagai tidak valid.

Dompet tidak boleh menyimpan respons dalam cache kecuali diinstruksikan oleh header respons HTTP caching.

Dompet harus menampilkan label dan merender gambar ikon kepada pengguna.

Permintaan POST

Dompet harus membuat permintaan JSON HTTP POST ke URL dengan body:

{ "account": "<account>" }

Nilai <account> harus berupa kunci publik yang dikodekan base58 dari akun yang mungkin menandatangani transaksi.

Dompet sebaiknya membuat permintaan dengan header Accept-Encoding, dan aplikasi sebaiknya merespons dengan header Content-Encoding untuk kompresi HTTP.

Dompet harus menampilkan domain dari URL saat permintaan sedang dibuat. Jika permintaan GET telah dibuat, dompet juga harus menampilkan label dan merender gambar ikon dari respons.

Respons POST

Dompet harus menangani kesalahan klien HTTP, kesalahan server, dan respons pengalihan. Aplikasi harus merespons dengan ini, atau dengan respons JSON HTTP OK dengan body:

{ "transaction": "<transaction>" }

Nilai <transaction> harus berupa transaksi terserialisasi yang dikodekan base64. Dompet harus mendekode base64 transaksi tersebut dan mendeserialisasinya.

Aplikasi dapat merespons dengan transaksi yang ditandatangani sebagian atau sepenuhnya. Dompet harus memvalidasi transaksi tersebut sebagai tidak terpercaya.

Tanda Tangan Kosong

Jika signatures transaksi kosong:

  • Aplikasi harus menetapkan feePayer ke account dalam permintaan, atau nilai nol (new PublicKey(0) atau new PublicKey("11111111111111111111111111111111")).
  • Aplikasi harus menetapkan recentBlockhash ke blockhash terbaru, atau nilai nol (new PublicKey(0).toBase58() atau "11111111111111111111111111111111").
  • Dompet harus mengabaikan feePayer dalam transaksi dan menetapkan feePayer ke account dalam permintaan.
  • Dompet harus mengabaikan recentBlockhash dalam transaksi dan menetapkan recentBlockhash ke blockhash terbaru.

Jika signatures transaksi tidak kosong:

Dompet hanya boleh menandatangani transaksi dengan account dalam permintaan, dan hanya boleh melakukannya jika tanda tangan untuk account dalam permintaan diharapkan.

Jika ada tanda tangan selain tanda tangan untuk account dalam permintaan yang diharapkan, dompet harus menolak transaksi tersebut sebagai berbahaya.

Aplikasi juga dapat menyertakan kolom message opsional dalam body respons:

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

Nilai <message> harus berupa string UTF-8 yang mendeskripsikan sifat respons transaksi.

Sebagai contoh, ini bisa berupa nama item yang dibeli, diskon yang diterapkan pada pembelian, atau catatan terima kasih. Dompet harus menampilkan nilai tersebut kepada pengguna.

Dompet dan aplikasi harus mengizinkan kolom tambahan dalam body permintaan dan body respons, yang mungkin ditambahkan oleh spesifikasi di masa mendatang.

Contoh

URL yang mendeskripsikan permintaan transaksi.
solana:https://example.com/solana-pay
URL yang mendeskripsikan permintaan transaksi dengan parameter kueri.
solana:https%3A%2F%2Fexample.com%2Fsolana-pay%3Forder%3D12345
Permintaan GET
GET /solana-pay?order=12345 HTTP/1.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate
Respons GET
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"}
Permintaan POST
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"}
Respons POST
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"}

Ekstensi

Format dan kolom tambahan dapat diintegrasikan ke dalam spesifikasi ini untuk memungkinkan kasus penggunaan baru sambil memastikan kompatibilitas dengan aplikasi dan dompet.

Silakan buka issue di Github untuk mengusulkan perubahan pada spesifikasi guna mendapatkan masukan dari pengembang aplikasi dan dompet.

Contoh nyata dari usulan semacam itu.

Is this page helpful?

Dikelola oleh

© 2026 Yayasan Solana.
Semua hak dilindungi.
Terhubung