In-Depth: Sponsored Transactions for Developers
Sponsored transactions were added to the Stacks blockchain to enable developers and/or infrastructure operators to pay for users to call into their smart contracts, even if users do not hold STX to pay for fees. (See SIP-005).
The process consists of two steps: 1) signing by user and 2) signing by sponsor
Signing Transaction by User
Sponsored transactions are build in the same way as normal transactions. The only difference is that fees are set to 0 and the sponsored flag is set to true. The sponsored transaction is then send to the user's wallet for confirmation. The wallet can't broadcast the transaction, instead it is returned to the app and needs to be handled separately.
An example with @stacks/connect library looks like the following (see also send-many example):
const txOptions = {...};
txOptions.fee = 0;
txOptions.sponsored = true;
openContractCall({...txOptions,
onFinish: (finishedTxData) => handleSignedSponsoredTransaction(finishTxData)
}
)
Signing Transaction by Sponsor
The signed transaction is returned from the wallet as part of the finished transaction data. The authentication type of the transaction will be of type Sponsored
data.stacksTransaction.auth.authType === AuthType.Sponsored;
The serialized transaction (data.txRaw
) can then be sent to a server for signing by the sponsor. There, the sponsor sets the fee
for the transaction, add the sponsor's nonce
and signs the transaction with the private key.
An example using the javascript library @stacks/transactions on a server looks like the following (see also not-sponsoring example):
import {deserializeTransaction, sponsorTransaction} from '@stacks/transactions';
...
const transaction = deserializeTransaction(txRaw);
const feeEstimate = await estimateTransactionFeeWithFallback(transaction, network);
const sponsorNonce = nonce; // next nonce of sponsor account
const sponsoredTx = await sponsorTransaction({
sponsorPrivateKey: env.SPONSOR_PRIVATE_KEY,
transaction,
network,
fee,
sponsorNonce: nonce,
});
const result = await broadcastTransaction(sponsoredTx);