Spesifikasi Solana Pay v1

Ringkasan

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

Standar ini mengambil inspirasi dari BIP 21 dan EIP 681.

Motivasi

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

URL ini dapat disandikan 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 melepaskan barang atau layanan yang dijual, atau memberikan akses ke objek atau acara.

Dompet seluler harus mendaftar 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 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 menggambarkan 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 bidang recipient diperlukan sebagai pathname. Nilai harus berupa kunci publik yang disandikan base58 dari akun SOL asli. Associated token accounts tidak boleh digunakan.

Sebagai gantinya, untuk meminta transfer Token SPL, bidang spl-token harus digunakan untuk menentukan mint Token SPL, dari mana alamat token account terkait dari penerima harus diturunkan.

Jumlah

Satu kolom amount diizinkan sebagai parameter kueri opsional. Nilainya harus berupa bilangan bulat non-negatif atau bilangan 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, maka harus memiliki 0 di depan sebelum .. Notasi ilmiah dilarang.

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

SPL Token

Satu kolom spl-token diizinkan sebagai parameter kueri opsional. Nilainya harus berupa pubkey yang dikodekan base58 dari mint account SPL Token.

Jika kolom ini disediakan, konvensi Associated Token Program harus digunakan, dan dompet harus menyertakan instruksi TokenProgram.Transfer atau TokenProgram.TransferChecked sebagai instruksi terakhir dari transaksi.

Jika kolom tidak disediakan, URL mendeskripsikan transfer SOL asli, dan dompet harus menyertakan instruksi SystemProgram.Transfer sebagai instruksi terakhir dari transaksi.

Dompet harus menurunkan alamat ATA dari kolom recipient dan spl-token. Transfer ke token account tambahan tidak didukung.

Referensi

Beberapa kolom reference diizinkan sebagai parameter kueri opsional. Nilainya harus berupa array 32 byte yang dikodekan base58. Ini mungkin atau mungkin bukan pubkey, di atau di luar kurva, dan mungkin atau mungkin tidak berkorespondensi dengan akun di Solana.

Jika nilai-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-nilai tersebut mungkin atau mungkin tidak unik untuk permintaan pembayaran, dan mungkin atau mungkin tidak sesuai 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 kueri 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 men-decode URL nilai tersebut dan menampilkan nilai yang telah di-decode kepada pengguna.

Pesan

Satu bidang message diperbolehkan sebagai parameter kueri 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 kata ucapan terima kasih. Dompet harus men-decode URL nilai tersebut dan menampilkan nilai yang telah di-decode kepada pengguna.

Memo

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

Dompet harus men-decode URL 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, dompet 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 menjelaskan permintaan transfer untuk 1 SOL

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

URL yang menjelaskan permintaan transfer untuk 0,01 USDC

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

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

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael

Spesifikasi: Permintaan Transaksi

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

solana:<link>

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

Tautan

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

Jika URL berisi parameter kueri, maka harus di-encode URL. Parameter kueri protokol dapat ditambahkan ke spesifikasi ini. Encoding URL pada nilai mencegah konflik dengan parameter protokol.

Jika URL tidak berisi parameter kueri, maka tidak perlu di-encode URL. Ini menghasilkan URL yang lebih pendek dan kode QR yang kurang padat.

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

Permintaan GET

Dompet harus membuat permintaan JSON HTTP GET ke URL tersebut. Permintaan tidak boleh mengidentifikasi dompet atau pengguna.

Dompet harus membuat permintaan dengan header Accept-Encoding, dan aplikasi harus 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. Misalnya, ini bisa berupa nama merek, toko, aplikasi, atau orang yang membuat permintaan.

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

Dompet sebaiknya tidak 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 dalam 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 melakukan decode base64 pada transaksi dan mendeserializasikannya.

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 mengatur feePayer ke account dalam permintaan, atau nilai nol (new PublicKey(0) atau new PublicKey("11111111111111111111111111111111")).
  • Aplikasi harus mengatur recentBlockhash ke blockhash terbaru, atau nilai nol (new PublicKey(0).toBase58() atau "11111111111111111111111111111111").
  • Dompet harus mengabaikan feePayer dalam transaksi dan mengatur feePayer ke account dalam permintaan.
  • Dompet harus mengabaikan recentBlockhash dalam transaksi dan mengatur recentBlockhash ke blockhash terbaru.

Tanda Tangan Tidak Kosong

Jika signatures transaksi tidak kosong:

Dompet hanya boleh menandatangani transaksi dengan account dalam permintaan, dan harus melakukannya hanya 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.

Kolom Pesan Opsional

Aplikasi juga dapat menyertakan kolom message opsional dalam body respons:

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

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

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

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

Contoh

URL yang menjelaskan permintaan transaksi

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

URL yang menjelaskan permintaan transaksi dengan parameter kueri

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

Contoh Permintaan GET

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

Contoh 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"}

Contoh 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"}

Contoh 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 dimasukkan ke dalam spesifikasi ini untuk mengaktifkan kasus penggunaan baru sambil memastikan kompatibilitas dengan aplikasi dan wallet.

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

Contoh nyata dari proposal semacam itu.

Lihat Juga

Is this page helpful?

Dikelola oleh

© 2026 Yayasan Solana.
Semua hak dilindungi.
Terhubung