Solana Pay仕様 v1.1

概要

URL内にSolanaトランザクションリクエストをエンコードし、支払いやその他のユースケースを実現するための標準プロトコルです。

この仕様に関する大まかな合意に達しており、Phantom、FTX、Slopeに実装が存在します。

この標準は、 BIP 21および EIP 681から着想を得ています。

動機

ネイティブSOL転送、SPLトークン転送、およびSolanaトランザクションをリクエストするための標準URLプロトコルにより、Solanaエコシステム内のアプリとウォレット全体でより良いユーザー体験が実現されます。

これらのURLは、QRコードやNFCタグにエンコードされるか、ユーザーとアプリケーション間で送信され、支払いをリクエストしたり、トランザクションを構成したりすることができます。

アプリケーションは、販売している商品やサービスを提供する前、またはオブジェクトやイベントへのアクセスを許可する前に、トランザクションが確認され、有効であることを確認する必要があります。

モバイルウォレットは、環境内でSolana Pay URLに遭遇した際に、シームレスかつ安全な体験を提供するために、URLスキームを処理するよう登録する必要があります。

これらの問題を解決するためのシンプルなアプローチを標準化することで、アプリケーションとウォレットの基本的な互換性を確保し、開発者がより高度な抽象化に集中できるようにします。

仕様:転送リクエスト

Solana Pay転送リクエストURLは、SOLまたはSPLトークンの転送に対する非対話型リクエストを記述します。

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

このリクエストが非対話型である理由は、URL内のパラメータがウォレットによってトランザクションを直接構成するために使用されるためです。

受取人

パス名として単一のrecipientフィールドが必須です。値は、ネイティブSOLアカウントのbase58エンコードされた公開鍵である必要があります。associated token accountを使用してはいけません。

代わりに、SPL Tokenの転送をリクエストするには、spl-tokenフィールドを使用してSPL Token mintを指定する必要があり、そこから受取人のassociated token addressを導出する必要があります。

金額

単一のamountフィールドは、オプションのクエリパラメータとして使用できます。値は、「ユーザー」単位の非負の整数または小数でなければなりません。SOLの場合は、lamportではなくSOLです。トークンの場合は、uiAmountStringを使用し、amountは使用しません

0は有効な値です。値が1未満の小数の場合、.の前に0を付ける必要があります。指数表記は禁止されています。

値が指定されていない場合、ウォレットはユーザーに金額の入力を求める必要があります。小数点以下の桁数がSOL(9桁)またはSPL Token(mint固有)でサポートされている桁数を超える場合、ウォレットはURLを不正な形式として拒否する必要があります。

SPL Token

単一のspl-tokenフィールドは、オプションのクエリパラメータとして使用できます。値は、SPL Token mint accountのbase58エンコードされた公開鍵である必要があります。

このフィールドが指定されている場合、Associated Token Accountの規約を使用する必要があり、ウォレットはトランザクションの最後のinstructionとしてTokenProgram.TransferまたはTokenProgram.TransferCheckedのinstructionを含める必要があります。

このフィールドが指定されていない場合、URLはネイティブSOL転送を示しており、ウォレットは代わりにトランザクションの最後のinstructionとしてSystemProgram.Transferのinstructionを含める必要があります。

ウォレットは、recipientフィールドとspl-tokenフィールドからATAアドレスを導出する必要があります。補助token accountへの転送はサポートされていません。

参照

複数のreferenceフィールドは、オプションのクエリパラメータとして使用できます。値は、base58エンコードされた32バイト配列である必要があります。これらは公開鍵である場合もそうでない場合もあり、曲線上または曲線外である場合もあり、Solana上のアカウントに対応している場合もそうでない場合もあります。

値が提供される場合、ウォレットは提供された順序でそれらを読み取り専用の非署名者キーとして、支払いトランザクション内のSystemProgram.TransferまたはTokenProgram.Transfer/TokenProgram.TransferCheckedインストラクションに含める必要があります。これらの値は支払いリクエストに固有である場合とそうでない場合があり、Solana上のアカウントに対応している場合とそうでない場合があります。

Solanaバリデータはこれらのアカウントキーによってトランザクションをインデックス化するため、referenceの値はクライアントID(最終的な支払いトランザクションを知る前に使用可能なID)として使用できます。getSignaturesForAddressRPCメソッドを使用して、この方法でトランザクションを特定することができます。

ラベル

単一のlabelフィールドは、オプションのクエリパラメータとして許可されています。値は、送金リクエストの送信元を説明するURLエンコードされたUTF-8文字列である必要があります。

例えば、これはリクエストを行っているブランド、店舗、アプリケーション、または個人の名前である可能性があります。ウォレットは値をURLデコードし、デコードされた値をユーザーに表示する必要があります。

メッセージ

単一のmessageフィールドは、オプションのクエリパラメータとして許可されています。値は、送金リクエストの性質を説明するURLエンコードされたUTF-8文字列である必要があります。

例えば、これは購入されるアイテムの名前、注文ID、または感謝のメモである可能性があります。ウォレットは値をURLデコードし、デコードされた値をユーザーに表示する必要があります。

メモ

単一のmemoフィールドは、オプションのクエリパラメータとして許可されています。値は、支払いトランザクション内のSPL Memoインストラクションに含める必要があるURLエンコードされたUTF-8文字列である必要があります。

ウォレットは値をURLデコードし、デコードされた値をユーザーに表示する必要があります。メモはバリデータによって記録されるため、プライベートまたは機密情報を含めるべきではありません。

このフィールドが提供される場合、ウォレットはトランザクション内の他のインストラクションとの曖昧さを避けるため、SOLまたはSPLトークン転送インストラクションの直前、トランザクションの最後から2番目のインストラクションとしてMemoProgramインストラクションを含める必要があります。

1 SOLの転送リクエストを記述するURL

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

0.01 USDCの転送リクエストを記述するURL

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

SOLの転送リクエストを記述するURL(ユーザーに金額の入力を促す)

solana:mvines9iiHiQTysrwkJjGf2gb9Ex9jXJX8ns3qwf2kN?label=Michael

仕様:トランザクションリクエスト

Solana PayトランザクションリクエストURLは、あらゆるSolanaトランザクションに対するインタラクティブなリクエストを記述します。

solana:<link>

このリクエストがインタラクティブであるのは、URL内のパラメータがウォレットによってHTTPリクエストを作成し、トランザクションを構成するために使用されるためです。

リンク

パス名として単一のlinkフィールドが必要です。この値は、条件付きでURLエンコードされた絶対HTTPSURLでなければなりません。

URLにクエリパラメータが含まれている場合は、URLエンコードする必要があります。プロトコルのクエリパラメータがこの仕様に追加される可能性があります。値をURLエンコードすることで、プロトコルパラメータとの競合を防ぎます。

URLにクエリパラメータが含まれていない場合は、URLエンコードすべきではありません。これにより、より短いURLと密度の低いQRコードが生成されます。

いずれの場合も、ウォレットは値をURLデコードする必要があります。値がURLエンコードされていない場合、これは何も影響しません。デコードされた値が絶対HTTPSURLでない場合、ウォレットはそれを不正な形式として拒否する必要があります。

GETリクエスト

ウォレットは、このURLに対してHTTP GET JSONリクエストを行う必要があります。リクエストはウォレットやユーザーを識別すべきではありません。

ウォレットはAccept-Encodingヘッダーを含めてリクエストを行い、アプリケーションはHTTP圧縮のためにContent-Encodingヘッダーで応答する必要があります。

ウォレットは、リクエストが行われる際に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ヘッダーを付けてリクエストを行うべきであり、アプリケーションはHTTP圧縮のためにContent-Encodingヘッダーを付けてレスポンスを返すべきです。

ウォレットは、リクエストが行われる際に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.1
Host: example.com
Connection: close
Accept: application/json
Accept-Encoding: br, gzip, deflate
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"}
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"}
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"}

拡張機能

アプリとウォレットとの互換性を確保しながら、新しいユースケースを可能にするために、追加のフォーマットとフィールドがこの仕様に組み込まれる場合があります。

アプリケーションおよびウォレット開発者からのフィードバックを募るため、仕様への変更を提案するGithub issueを開いてください。

このような提案の実際の例

Is this page helpful?

管理運営

© 2026 Solana Foundation.
無断転載を禁じます。
つながろう