Sign Transaction (Batch)

This API allows developers to sign a batch of transactions in a single call. This is useful if you want to sign multiple transactions in a single call e.g. approve a token, mint an NFT, and transfer the NFT on blockchains likeSolana where the transaction size is limited. This improves the user experience by reducing the number of popups shown to the user to get their consent.

📘

This API is only supported for the Solana apps at the moment.

📘

The API requires SDK version 2.2.3 or higher.

Sign Solana Transaction

Once you have built multiple Solana transaction objects using @solana/web3.js, you can ask the user to sign them by using thesignTransactionMultiple function in the MetaKeep SDK. The function expects a non-empty reason for the request and for each transaction in the batch which will be shown to the user at the time of requesting consent.

If you are not using @solana/web3.js, you need to serialize the transaction message that needs to be signed before sending it to the MetaKeep SDK.

👍

Solana versioned transactions are supported

// Legacy transaction
const legacyTx = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: fromPublicKey,
    toPubkey: toPublicKey,
    lamports: 1 * LAMPORTS_PER_SOL,
  })
);

// Versioned transaction
const messageV0WithLookupTable = new TransactionMessage({
  payerKey: payerPublicKey,
  recentBlockhash: recentBlockhash,
  instructions: [
    SystemProgram.transfer({
      fromPubkey: fromPublicKey,
      toPubkey: toPublicKey,
      lamports: amountToTransfer * LAMPORTS_PER_SOL,
    }),
  ],
}).compileToV0Message([lookupTableAccount]);

const versionedTx = new VersionedTransaction(messageV0WithLookupTable);

await sdk.signTransactionMultiple(
  // Transaction batch with reason for each transaction
  [
    {
      transactionObject: legacyTx,
      reason: "Sign reason 1",
    },
    {
      transactionObject: versionedTx,
      reason: "Sign reason 2",
    },
    // You can also send a serialized Solana transaction message if You
    // only have access to the serialized message.
    {
      transactionObject: {
        serializedTransactionMessage:
          "0x" +
          Buffer.from(messageV0WithLookupTable.serialize()).toString("hex"),
      },
      reason: "Sign reason 3",
    },
  ],
  // Signing reason
  "test sign transaction batch"
);

Here's a reference implementation of this code: https://codesandbox.io/p/sandbox/metakeep-sign-solana-transaction-batch-tw38y5?file=%2Fsrc%2FApp.js%3A50%2C35

📘

The latest @solana/web3.js supported version is 1.75.0

Let us know if you would like us to support a more recent version :)


Response

signTransactionMultiple returns a promise which succeeds when the sign operation is successful. The response looks like this-

{
  "status": "SUCCESS",
  // Signatures array with each signature in the hex format.
  "signatures": [
    {
      "signature": "0x023d9a5700b77971b8de539936143e0d82808809b856cc9ab9bcc41a02a3794ec516a44db6ed666f3e4f7549ae91939062ce076a9ef419febc21c41eebb98f0a"
    },
    {
      "signature": "0xee1af2c9bd70596a2bd41727126de50de3e834f29a5ef4afae1b9c4b7522779a071408faa667529260fb3d26ec312f81647cc5996f0562d98ec3757ea431c50a"
    }
  ]
}

Error status

signTransactionMultiple returns a promise which throws an error when the sign operation is unsuccessful. The error object looks like this-

{
  status: "USER_CONSENT_DENIED"
}

Here's a table of all possible error status returned by the SDK

StatusDescription
USER_REQUEST_DENIEDThe user has denied the sign operation.
In this case, you should ask the user if they want to try again.
INVALID_REQUESTInvalid data passed to sign operation.
Please get in touch with us if you are unable to fix this.
MISSING_NONCEThe nonce is missing. Please specify nonce for the transaction.
MISSING_GASGas is missing. Please specify gas for the transaction.
INVALID_GAS_FEE_PARAMSThe transaction contains gasPrice maxFeePerGas and maxPriorityFeePerGas. Please specify either gasPrice or maxFeePerGas and maxPriorityFeePerGas
MISSING_GAS_PRICEGas price is missing for type 1 transactions. Please specify gasPrice.
MISSING_MAX_FEE_PER_GASThe max fee per gas is missing for type 2 transactions. Please specify both maxFeePerGas and maxPriorityFeePerGas
MISSING_MAX_PRIORITY_FEE_PER_GASThe max priority fee per gas is missing for type 2 transactions. Please specify both maxFeePerGas and maxPriorityFeePerGas
APP_ID_REQUIREDNo app-id was provided when initializing the SDK.
You can find the app id in the MetaKeep Developer Console.
APP_NOT_FOUNDThe provided app-id is invalid.
You can find the correct app-id in the MetaKeep Developer Console.
FROM_ADDRESS_DOES_NOT_MATCH_SIGNERThe from address in the transaction message does not match the signer's address.
TOO_MANY_TRANSACTIONSThere are too many transactions in the batch. Currently, only up to 5 transactions are supported in a single batch.
SOMETHING_WENT_WRONGAn unknown error happened.
Please get in touch with us if you continue seeing this error.

© Copyright 2024, Passbird Research Inc.