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
feePayerkeaccountdalam permintaan, atau nilai nol (new PublicKey(0)ataunew PublicKey("11111111111111111111111111111111")). - Aplikasi harus mengatur
recentBlockhashke blockhash terbaru, atau nilai nol (new PublicKey(0).toBase58()atau"11111111111111111111111111111111"). - Dompet harus mengabaikan
feePayerdalam transaksi dan mengaturfeePayerkeaccountdalam permintaan. - Dompet harus mengabaikan
recentBlockhashdalam transaksi dan mengaturrecentBlockhashke blockhash terbaru.
Tanda Tangan Tidak Kosong
Jika
signatures
transaksi tidak kosong:
- Aplikasi harus mengatur
feePayerke kunci publik dari tanda tangan pertama. - Aplikasi harus mengatur
recentBlockhashke blockhash terbaru. - Aplikasi harus melakukan serialisasi dan deserialisasi transaksi sebelum menandatanganinya. Ini memastikan urutan kunci akun yang konsisten, sebagai solusi sementara untuk masalah ini.
- Dompet tidak boleh mengatur
feePayerdanrecentBlockhash. - Dompet harus memverifikasi tanda tangan, dan jika ada yang tidak valid, dompet harus menolak transaksi tersebut sebagai tidak valid.
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.1Host: example.comConnection: closeAccept: application/jsonAccept-Encoding: br, gzip, deflate
Contoh Respons GET
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 62Content-Encoding: gzip{"label":"Michael Vines","icon":"https://example.com/icon.svg"}
Contoh Permintaan POST
POST /solana-pay?order=12345 HTTP/1.1Host: example.comConnection: closeAccept: application/jsonAccept-Encoding: br, gzip, deflateContent-Type: application/jsonContent-Length: 57{"account":"mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN"}
Contoh Respons POST
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 298Content-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
- Spesifikasi Solana Pay v1.1 - Versi terbaru dengan perbaikan
- Panduan Mulai Cepat - Panduan implementasi
- Repositori GitHub - Implementasi referensi
Is this page helpful?