Підсумок
Стандартний протокол для кодування запитів транзакцій Solana в URL-адресах для здійснення платежів та інших варіантів використання.
Цей стандарт черпає натхнення з BIP 21 та EIP 681.
Мотивація
Стандартний URL-протокол для запиту нативних переказів SOL, переказів токенів SPL та транзакцій Solana забезпечує кращий користувацький досвід у різних додатках та гаманцях екосистеми Solana.
Ці URL-адреси можуть бути закодовані в QR-кодах або NFC-мітках, або надіслані між користувачами та додатками для запиту платежу та складання транзакцій.
Додатки повинні переконатися, що транзакція підтверджена і є дійсною, перш ніж надавати товари чи послуги, що продаються, або надавати доступ до об'єктів чи подій.
Мобільні гаманці повинні зареєструватися для обробки URL-схеми, щоб забезпечити безперебійний, але безпечний досвід при виявленні URL-адрес Solana Pay у середовищі.
Стандартизуючи простий підхід до вирішення цих проблем, ми забезпечуємо базову сумісність додатків і гаманців, щоб розробники могли зосередитися на абстракціях вищого рівня.
Специфікація: Запит на переказ
URL-адреса запиту на переказ Solana Pay описує неінтерактивний запит на переказ SOL або токена SPL.
solana:<recipient>?amount=<amount>&spl-token=<spl-token>&reference=<reference>&label=<label>&message=<message>&memo=<memo>
Запит є неінтерактивним, оскільки параметри в URL-адресі використовуються гаманцем для безпосереднього складання транзакції.
Одержувач
Одне поле recipient є обов'язковим як шлях. Значення має бути кодованим у
base58 публічним ключем нативного облікового запису SOL. Асоційовані токенові
облікові записи не повинні використовуватися.
Натомість, щоб запитати переказ токена SPL, необхідно використовувати поле
spl-token для вказівки адреси mint токена SPL, з якої має бути отримана адреса
асоційованого токенового облікового запису одержувача.
Сума
Одне поле amount дозволено як необов'язковий параметр запиту. Значення повинно
бути невід'ємним цілим числом або десятковим числом «користувацьких» одиниць.
Для SOL це SOL, а не lamport. Для токенів використовуйте
uiAmountString, а не amount.
0 є дійсним значенням. Якщо значення є десятковим числом менше 1, воно
повинно мати провідний 0 перед .. Наукова нотація заборонена.
Якщо значення не надано, гаманець повинен запитати у користувача суму. Якщо кількість десяткових знаків перевищує підтримувану для SOL (9) або SPL Token (специфічну для mint), гаманець повинен відхилити URL як некоректний.
SPL Token
Одне поле spl-token дозволено як необов'язковий параметр запиту. Значення
повинно бути публічним ключем облікового запису mint SPL Token у кодуванні
base58.
Якщо поле надано, необхідно використовувати конвенцію
Associated Token Account, і
гаманець повинен включити інструкцію TokenProgram.Transfer або
TokenProgram.TransferChecked як останню інструкцію транзакції.
Якщо поле не надано, URL описує нативний переказ SOL, і гаманець повинен
включити інструкцію SystemProgram.Transfer як останню інструкцію транзакції
замість цього.
Гаманець повинен вивести адресу ATA з полів recipient та spl-token. Перекази
на допоміжні token account не підтримуються.
Посилання
Декілька полів reference дозволено як необов'язкові параметри запиту. Значення
повинні бути 32-байтовими масивами у кодуванні base58. Вони можуть бути або не
бути публічними ключами, на кривій чи поза нею, і можуть відповідати або не
відповідати обліковим записам на Solana.
Якщо значення надані, гаманець повинен включити їх у наданому порядку як ключі
лише для читання, які не підписують, до інструкції SystemProgram.Transfer або
TokenProgram.Transfer/TokenProgram.TransferChecked у транзакції платежу.
Значення можуть бути унікальними або не унікальними для запиту платежу, і можуть
відповідати або не відповідати обліковому запису в Solana.
Оскільки валідатори Solana індексують транзакції за цими ключами облікових
записів, значення reference можна використовувати як ідентифікатори клієнта
(ідентифікатори, які можна використовувати до того, як стане відома остаточна
транзакція платежу). Метод RPC
getSignaturesForAddress
можна використовувати для пошуку транзакцій таким чином.
Мітка
Одне поле label дозволено як необов'язковий параметр запиту. Значення має бути
URL-кодованим
рядком UTF-8, що описує джерело запиту на переказ.
Наприклад, це може бути назва бренду, магазину, додатка або особи, яка робить запит. Гаманець повинен декодувати URL значення та відобразити декодоване значення користувачеві.
Повідомлення
Одне поле message дозволено як необов'язковий параметр запиту. Значення має
бути
URL-кодованим
рядком UTF-8, що описує характер запиту на переказ.
Наприклад, це може бути назва товару, що купується, ідентифікатор замовлення або подяка. Гаманець повинен декодувати URL значення та відобразити декодоване значення користувачеві.
Мемо
Одне поле memo дозволено як необов'язковий параметр запиту. Значення має бути
URL-кодованим
рядком UTF-8, який повинен бути включений в інструкцію
SPL Memo у транзакції платежу.
Гаманець повинен декодувати URL значення і має відобразити декодоване значення користувачеві. Мемо буде записано валідаторами і не повинно містити приватну або конфіденційну інформацію.
Якщо поле надано, гаманець повинен включити інструкцію MemoProgram як
передостанню інструкцію транзакції, безпосередньо перед інструкцією передачі SOL
або SPL Token, щоб уникнути неоднозначності з іншими інструкціями в транзакції.
Приклади
URL, що описує запит на переказ 1 SOL
solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=1&label=Michael&message=Thanks%20for%20all%20the%20fish&memo=OrderId12345
URL, що описує запит на переказ 0,01 USDC
solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?amount=0.01&spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
URL, що описує запит на переказ SOL (користувач вводить суму)
solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael
Специфікація: Запит транзакції
URL запиту транзакції Solana Pay описує інтерактивний запит для будь-якої транзакції Solana.
solana:<link>
Запит є інтерактивним, оскільки параметри в URL використовуються гаманцем для здійснення HTTP-запиту для формування транзакції.
Посилання
Обов'язковим є одне поле link як шлях. Значення повинно бути умовно
закодованою URL-адресою
абсолютною HTTPS URL-адресою.
Якщо URL містить параметри запиту, він повинен бути закодованим URL-адресою. До цієї специфікації можуть бути додані параметри запиту протоколу. URL-кодування значення запобігає конфлікту з параметрами протоколу.
Якщо URL не містить параметрів запиту, він не повинен бути закодованим URL-адресою. Це створює коротшу URL-адресу та менш щільний QR-код.
У будь-якому випадку гаманець повинен декодувати URL-адресу значення. Це не має ефекту, якщо значення не закодоване URL-адресою. Якщо декодоване значення не є абсолютною HTTPS URL-адресою, гаманець повинен відхилити його як неправильно сформоване.
GET-запит
Гаманець повинен зробити HTTP GET JSON-запит до URL-адреси. Запит не повинен
ідентифікувати гаманець або користувача.
Гаманець повинен зробити запит з заголовком Accept-Encoding, і застосунок повинен відповісти з заголовком Content-Encoding для HTTP-стиснення.
Гаманець повинен відображати домен URL під час виконання запиту.
Відповідь GET
Гаманець має обробляти HTTP
клієнтські помилки,
серверні помилки
та
відповіді перенаправлення.
Додаток має відповідати цими кодами або HTTP OK JSON відповіддю з тілом:
{ "label": "<label>", "icon": "<icon>" }
Значення <label> має бути рядком UTF-8, який описує джерело запиту транзакції.
Наприклад, це може бути назва бренду, магазину, додатка або особи, що робить
запит.
Значення <icon> має бути абсолютним HTTP або HTTPS URL зображення іконки. Файл
має бути зображенням SVG, PNG або WebP, інакше гаманець повинен відхилити його
як некоректний.
Гаманець не повинен кешувати відповідь, окрім випадків, зазначених у HTTP кешуванні заголовками відповіді.
Гаманець повинен відображати мітку та рендерити зображення іконки для користувача.
Запит POST
Гаманець має виконати HTTP POST JSON запит до URL з тілом:
{ "account": "<account>" }
Значення <account> має бути публічним ключем облікового запису в кодуванні
base58, який може підписати транзакцію.
Гаманець повинен виконувати запит із заголовком Accept-Encoding, а додаток має відповідати заголовком Content-Encoding для HTTP стиснення.
Гаманець повинен відображати домен URL під час виконання запиту. Якщо був
виконаний запит GET, гаманець також повинен відображати мітку та рендерити
зображення іконки з відповіді.
Відповідь POST
Гаманець має обробляти HTTP
клієнтські помилки,
серверні помилки
та
відповіді перенаправлення.
Додаток має відповідати цими кодами або HTTP OK JSON відповіддю з тілом:
{ "transaction": "<transaction>" }
Значення <transaction> має бути закодованою в base64
серіалізованою транзакцією.
Гаманець повинен декодувати транзакцію з base64 та
десеріалізувати її.
Додаток може відповісти частково або повністю підписаною транзакцією. Гаманець повинен валідувати транзакцію як недовірену.
Порожні підписи
Якщо
signatures
транзакції порожні:
- Додаток повинен встановити
feePayerнаaccountіз запиту, або нульове значення (new PublicKey(0)абоnew PublicKey("11111111111111111111111111111111")). - Додаток повинен встановити
recentBlockhashна останній хеш блоку, або нульове значення (new PublicKey(0).toBase58()або"11111111111111111111111111111111"). - Гаманець повинен ігнорувати
feePayerу транзакції та встановитиfeePayerнаaccountіз запиту. - Гаманець повинен ігнорувати
recentBlockhashу транзакції та встановитиrecentBlockhashна останній хеш блоку.
Непорожні підписи
Якщо
signatures
транзакції непорожні:
- Додаток повинен встановити
feePayerна публічний ключ першого підпису. - Додаток повинен встановити
recentBlockhashна останній хеш блоку. - Додаток повинен серіалізувати та десеріалізувати транзакцію перед її підписанням. Це забезпечує послідовне впорядкування ключів облікових записів як обхідне рішення для цієї проблеми.
- Гаманець не повинен встановлювати
feePayerтаrecentBlockhash. - Гаманець повинен перевірити підписи, і якщо будь-який з них недійсний, гаманець повинен відхилити транзакцію як некоректну.
Гаманець повинен підписувати транзакцію лише з account із запиту, і повинен
робити це лише якщо очікується підпис для account із запиту.
Якщо очікується будь-який підпис, крім підпису для account із запиту, гаманець
повинен відхилити транзакцію як шкідливу.
Необов'язкове поле повідомлення
Додаток також може включати необов'язкове поле message у тілі відповіді:
{ "message": "<message>", "transaction": "<transaction>" }
Значення <message> має бути рядком UTF-8, який описує характер відповіді на
транзакцію.
Наприклад, це може бути назва товару, що купується, знижка, застосована до покупки, або подяка. Гаманець повинен відображати це значення користувачеві.
Гаманець і додаток повинні дозволяти додаткові поля в тілі запиту та тілі відповіді, які можуть бути додані майбутньою специфікацією.
Приклади
URL-адреса, що описує запит транзакції
solana:https://example.com/solana-pay
URL-адреса, що описує запит транзакції з параметрами запиту
solana:https%3A%2F%2Fexample.com%2Fsolana-pay%3Forder%3D12345
Приклад GET-запиту
GET /solana-pay?order=12345 HTTP/1.1Host: example.comConnection: closeAccept: application/jsonAccept-Encoding: br, gzip, deflate
Приклад GET-відповіді
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 62Content-Encoding: gzip{"label":"Michael Vines","icon":"https://example.com/icon.svg"}
Приклад 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"}
Приклад POST-відповіді
HTTP/1.1 200 OKConnection: closeContent-Type: application/jsonContent-Length: 298Content-Encoding: gzip{"message":"Thanks for all the fish","transaction":"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECC4JMKqNplIXybGb/GhK1ofdVWeuEjXnQor7gi0Y2hMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAAAMAgAAAAAAAAAAAAAA"}
Розширення
Додаткові формати та поля можуть бути включені до цієї специфікації для забезпечення нових сценаріїв використання, зберігаючи при цьому сумісність з додатками та гаманцями.
Будь ласка, відкрийте issue на Github, щоб запропонувати зміни до специфікації та отримати відгуки від розробників додатків і гаманців.
Фактичний приклад такої пропозиції.
Дивіться також
- Специфікація Solana Pay v1.1 - Остання версія з покращеннями
- Посібник швидкого старту - Керівництва з впровадження
- Репозиторій GitHub - Еталонні реалізації
Is this page helpful?