How to sign Transactions using multiple signers on Solana
Program execution on Solana Blockchain begins with a Transaction being submitted to the cluster. Transactions are a group of instructions that a client (typically a wallet) signs using one or more key pairs and then is executed atomically with only two possible outcomes: success or failure. The Solana runtime will execute a program to process each of the instructions contained in the transaction, in order, and atomically.
Each transaction contains a compact array of signatures, followed by a message. Each item in the signatures array is a digital signature of the given message. The Solana runtime verifies that each signature was signed by the private key corresponding to the public key at the same index in the message's account addresses array.
In some cases, Transactions require a single signature, and in other cases, they require more than one signature. A few APIs from SHYFT, such as the create_v2
, and the update_v2
return encoded_transaction
in their response, which in most cases require signatures from two or more wallets. In this blog, we will see how we can sign transactions that require more than one signer.
Before getting started
To get started, we will need a few things.
Phantom Wallet
We will need the Phantom wallet browser extension, you can download it from the link below.
Once done, set up your Phantom wallet account. On-screen tips are available, which will guide you through setting up and getting started. You can also find a detailed guide related to this here.
Authentication: Getting your Shyft API key
x-api-key
is an authentication parameter, which gives you access to SHYFT APIs. You can get your own API Key from the SHYFT website. Just signup with your email id here and you can get it for free. This is not really required for signing transactions, but this finds its application when making the API call which returns the encoded_transaction
.
Read SHYFT API Documentation here.
Signing Transactions: Two Signers
Letâs consider the following scenario, we are making a create_v2
API call which to mint a new NFT, but the NFT creator (creator_wallet
parameter) and the fee payer (fee_payer
parameter) for the create operation are different wallets. Such situations arise, in cases such as where an application is allowing users to create NFTs in a gasless manner, where the application is paying the gas fees (fee_payer
) and the end user is the NFT creator (creator_address
).
Check out Minting Gasless NFTs with SHYFT APIs.
In such scenarios, the encoded_transaction
received will need two signatures to be successfully executed by the Solana Runtime; first using the private_key
of the fee_payer
wallet, and next using the wallet of the end user. First, we attempt to sign the encoded_transaction
using the private_key
of the fee payer wallet, which in this case is the service provider, (Assuming the private_key
of the service provided is available in the environment variable of the application or embedded somewhere in the application) using the partialSign()
method . Once that is successful, we go on and sign the recoveredTransaction
using the userâs wallet (creator_wallet
).
The function for signing using both wallets is illustrated below
This function accepts the connection
to the userâs wallet, the encodedTransaction
received in response of the API call, privateKey
of the fee_payer
, and the wallet
object. We can get the connection
and the wallet
object for phantom in the following manner.
This connection and wallet objects is then passed on to the partialSignWithKeyAndWallet()
function, along with the encodedTransaction
and the privateKey
in the following manner.
This will sign the transaction both via the fee_payer
âs private key and the user's wallet. Once the user clicks approve, the transaction will be signed and the instruction will be executed.
We can verify if the instruction execution is complete or not, using the following method, where callback is a function, which is executed once the instruction has completed execution.
Now that we have seen how we can sign transactions using two different signer wallets, letâs see how we can sign transactions when there are more than two wallets.
Signing Transaction: More than Two Signers
In some instances, it may happen that, the fee_payer
, creator_wallet
and the collection owner( owner of the collection whose collection_address
is used) are three different wallets, and the encoded_transaction
generated needs 3 different signatures (or n different signatures). In such scenarios, we will use the fee_payer
private key and the collection owner's private key to partially sign the transaction from the backend, and then we will use the end userâs wallet (creator_wallet
) to sign the transaction finally.
We use a tweaked version of the same function to partially sign the transaction using the private keys of fee_payer
and the collection owner. This function can be used in the previous case as well, as this function can partially sign transactions using n number of wallets as long as their private keys are available. Once that step is complete we go on and sign the recoveredTransaction
using the userâs wallet (creator_wallet
)
Similar to its previous version, this function accepts the connection
to the userâs wallet, the encodedTransaction
received in the response of the API call and the wallet
object. The only difference is, along with these parameters, this function also takes in an array of private keys, which can contain all the private keys required to partially sign the transaction.
The wallet object and the connection to the userâs wallet can be obtained in the same manner as shown in the previous step.
This will also allow the user to sign the transaction via their wallet, once they click approve, the transaction will be signed and the instruction will be executed.
Signing multiple Transactions with one wallet
In certain situations, instead of one encoded_transaction
SHYFT APIs return more than one, or an array of encoded_transactions
, which will need a sign from the wallet in the front end. This happens in API endpoints such as transfer_many
API, where the encoded_transactions
returned is an array of encoded_transaction. In such cases, we will use the following function to sign the transaction from the front end:
This function accepts connection
, the encoded_transactions
(an array of encoded_transaction
) from the SHYFT API response and the wallet
object. Then all the transactions in the encoded_transactions
array will be signed from the wallet in one go using the signAllTransactions()
method. The wallet object and the connection to the userâs wallet can be obtained in the same manner as shown in the previous step.
Thatâs pretty much all about signing transactions using wallet and private keys on Solana. If you liked this blog, feel free to checkout our blog on adding NFTs to Collections on Solana or getting all NFT collections from a wallet. We hope you have a great time building dApps on Solana using SHYFT APIs. Happy Hacking. đ
Resources
Join our Discord
Last updated