Search code examples
node.jssolanasolana-web3jsanchor-solana

Anchor: How to ask the Nodejs backend to co-sign a transaction from the frontend without using Serum's Multisig?


Ideally, I want my Nodejs backend (which secures a keypair) to co-sign a transaction coming from the frontend app (assuming the user will sign the transaction using his / her Solana wallet). The pubkey of the backend will be also included as a signer account to the anchor program.

I can't see any tutorial from Anchor doing this, hopefully it makes sense. I was thinking that the frontend will call a backend API passing down the serialize parameters, on which the backend will sign, and will return a signature to the frontend with its public key.

I have no idea on:

  • What's the correct Anchor / Solana web3 to use to sign the transaction
  • How can I add the returning signature (of the backend) to the transaction

I initially don't want to use Multisig with this approach as it will just overcomplicate things. Just need some confirmation from the backend before submitting the transaction.


Solution

  • You probably want to do something like this (backend):

    // create the transaction, with user's public key as the feePayer
    
    // Sign the transaction as the backend
    // We must partial sign because the transaction still requires the user signature
    transaction.partialSign(backendKeypair)
    
    // Serialize the transaction and convert to base64 to return it
    const serializedTransaction = transaction.serialize({
      // We will need the buyer to sign this transaction after it's returned to them
     requireAllSignatures: false
    })
    const base64 = serializedTransaction.toString('base64')
    
    // return base64 to the frontend
    

    Then from the frontend:

    // make sure you're passing user's public key in this request
    const response = await fetch(`/your-api/`, {
      method: 'POST',
      ...
    })
    
    // assuming your API returns JSON
    const json = await response.json()
    
    // Deserialize the transaction from the response
    const transaction = Transaction.from(Buffer.from(json.transaction, 'base64'));
        
    // have the user sign transaction using their connected wallet