Yes you can do this by adding additional singers in the frontend like this:
let tx = await program.methods
.mintNft()
.accounts(
{
signer: payer.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
tokenProgram: TOKEN_2022_PROGRAM_ID,
associatedTokenProgram: ASSOCIATED_PROGRAM_ID,
tokenAccount: destinationTokenAccount,
mint: mint.publicKey,
}
).signers([mint])
.rpc({skipPreflight: true});
Here you can see that for the NFT mint we also put the mint keypair as an additional signer.
You can then in the program as a signer:
#[account(mut)]
pub mint: Signer<'info>,
and then use the account as normal in the program. And just use the signer for your system program transfer.
If you want to partial sign in the backend and then add the users signature in the fronten you can do this like this:
const hash = await CONNECTION.getLatestBlockhash();
const transaction = await mintCompressedNft(
CONNECTION,
nftArgs,
ownerWallet.publicKey,
TreeAccount,
CollectionMint,
collectionMetadataAccount,
collectionMasterEditionAccount,
feepayer
);
transaction.recentBlockhash = hash.blockhash;
transaction.partialSign(ownerWallet);
console.log("transaction " + transaction.instructions.length);
const serializedTransaction = transaction.serialize({
verifySignatures: false,
requireAllSignatures: false,
});
const base64Transaction = serializedTransaction.toString('base64');
res.status(200).json({
transaction: base64Transaction,
message: "OK",
});
Here is a complete example:
https://github.com/solana-developers/one-milion-nfts/blob/main/next/pages/api/mint.ts