Trying to controll who pays the fee

I am having a problem with Web3.js

I want to send token from a wallet to another. But i want to choose who is the one paying the fees.

Here is my code:

var connection = new solanaWeb3.Connection(solanaWeb3.clusterApiUrl(“mainnet-beta”));
var fromWallet = solanaWeb3.Keypair.fromSecretKey(SENDERSECRET);
var toWallet = solanaWeb3.Keypair.fromSecretKey(RECEIVERSECRET);
varr myMint = new solanaWeb3.PublicKey(token);
var myToken = new splToken .Token(
connection,
myMint,
splToken .TOKEN_PROGRAM_ID,
toWallet
);
myToken.getOrCreateAssociatedAccountInfo(fromWallet.publicKey ).then(fromTokenAccount=>{
myToken.getOrCreateAssociatedAccountInfo(toWallet.publicKey).then(toTokenAccount=>{
let lamportQuantity=1000000000*quantity;
var transaction = new solanaWeb3.Transaction({
feePayer: toWallet.publicKey
}).add(
splToken .Token.createTransferInstruction(
splToken .TOKEN_PROGRAM_ID,
fromTokenAccount.address,
toTokenAccount.address,
fromWallet.publicKey,
,
lamportQuantity
)

            );

            connection.getRecentBlockhash().then(recentBlockhash=>{

              transaction.recentBlockhash = recentBlockhash.blockhash;

              transaction.sign(toWallet)

                solanaWeb3.sendAndConfirmTransaction(connection,transaction,[fromWallet] ).then(signature=>{

});

This code was supposed to send a token from an account to another, choosing toWallet as the fee payer.

But it gives me:
core.es5.js:1020 ERROR Error: Uncaught (in promise): Error: !signature
Error: !signature
at Connection.sendTransaction (connection.ts:3617)

Every time.

What am i doing wrong? And one more thing…can the fee Payer be a wallet that is not the one sending and receiving, but my company wallet?
I want to pay the fees of my customer transactions.

If I get the chance I’ll look at the code more closely to see if I can find out what’s wrong.

As far as who can pay the fees, it can be anybody, but the issue is that you need to get the fee payer to sign the transaction. This may actually be your problem. If you want the person you are sending the funds to to pay the transaction fees, then they need to sign the transaction, and you have to have some way to get the transaction to the person receiving the funds so that they can make the signature.

If you want your company wallet to pay the fees, you will have to setup a web service with like a REST API that will sign transactions that meet certain criteria, so that it can pay the fees for those transactions.

You just have to be very careful only to code the API so that it only signs transactions that you trust and understand and not ones that, for instance, transfer all the money out of your company wallet or something like that.


Let me know if you have any more questions!

Man thank you for answering my question.
Thing is…all wallets in question are created by me.
I created the sender wallet
I created the receiver wallet
I created the my company wallet.
I have the secret key, the 12 word phrases…all the info of all accounts on my secure database. Because this wallets are meant to transfer tokens which represent game itens from one to the other.

Knowing that i have full access of all wallets. If the problem I am having is to sign the transaction…and i have all information of all wallets, how do i make my feePayer wallet to sign the transaction?

This post was flagged by the community and is temporarily hidden.

OK, I think I what your problem is. After creating your transaction object, before you send it, you need to call transaction.sign(fromWallet, toWallet).

This will add a signature from both the from wallet, which is needed to transfer the funds, and from the to wallet, which is needed to authorize the fee payer.

I should have read your code more carefully when I replied the first time, you situation was much simpler that I initially thought. :slight_smile: Sorry!


PS: When posting code on the forum, wrap all the code in tripple backticks ``` to make it pop up nice and easy to read, like this:

```
var test = "hello code";
```

Ok. I tried what you said…and it didnt work.
That’s the bad news. The good news is…i found the solution.
=P
The problem was I was trying to use this function:
solanaWeb3.sendAndConfirmTransaction(connection,transaction,[fromWallet] )
with only [fromWallet] on the array. I came back to this source:

And noticed this comment:
// Note: feePayer is by default the first signer, or payer, if the parameter is not set
await web3.sendAndConfirmTransaction(connection, transaction, [payer])

Looking deeper on this function, says [payer] is actually an array with all signers.

So my solution was not on signing the transaction. It doesnt work.
My solution was this:
solanaWeb3.sendAndConfirmTransaction(connection,transaction,[toWallet,fromWallet]
To add an array of signers, where the first item of the array is the wallet i wanted to pay.

That worked perfectly. So i am leaving this information here for whoever has the same issue.

1 Like