Skip to content

Invalid Auth Key / Transaction Expired with External Signer #650

Open
@Bereket-G

Description

@Bereket-G

When trying to submit a transaction using an externally signed message (via Fireblocks in our case), we're encountering consistent "Invalid Auth Key" and "Transaction Expired" errors.

Reproduction Steps

  1. Build a simple transfer transaction
  2. Get the signing message
  3. Sign the message with an external signer
  4. Verify the signature (passes verification)
  5. Submit the transaction
  6. Receive "Invalid Auth Key" error

Minimal Example

I've attached a simplified reproduction in aptos-repro.ts that demonstrates the core flow.

Expected Behavior

The transaction should be accepted and processed by the network when submitted with a valid signature.

Actual Behavior

  • The signature verification passes
  • The transaction submission fails with "Invalid Auth Key"
  • Sometimes we also get "Transaction Expired" errors

Questions

  1. Is there a specific format requirement for the auth key that we're missing?
  2. Are we correctly handling the signing message format?
  3. Is there additional preprocessing needed for externally signed transactions?

Environment

  • @aptos-labs/ts-sdk version: 1.35.0
  • Network: Devnet
  • External Signer: Fireblocks

import {
  Aptos,
  AptosConfig,
  Network,
  Ed25519PublicKey,
  Ed25519Signature,
  AccountAddress,
} from "@aptos-labs/ts-sdk";

const main = async () => {
  // Setup
  const config = new AptosConfig({ network: Network.DEVNET });
  const client = new Aptos(config);

  // Test accounts (you can get these from Petra wallet or Aptos CLI)
  const senderAddress = "0x123..."; // Replace with actual address
  const recipientAddress = "0x456..."; // Replace with actual address

  // 1. Build the transaction
  const tx = await client.transaction.build.simple({
    sender: AccountAddress.fromString(senderAddress),
    data: {
      function: "0x1::coin::transfer",
      typeArguments: ["0x1::aptos_coin::AptosCoin"],
      functionArguments: [AccountAddress.fromString(recipientAddress), 1000],
    },
    options: {
      expireTimestamp: Math.floor(Date.now() / 1000) + 600, // 10 minutes
    }
  });

  // 2. Get the signing message
  const rawTx = tx.bcsToBytes();
  const signingMessage = client.getSigningMessage({ transaction: tx });

  // 3. Sign the message (in your case, this would be done by Fireblocks)
  // Replace these with your actual values from Fireblocks
  const publicKey = new Ed25519PublicKey("your_public_key");
  const signature = new Ed25519Signature("your_signature");

  // 4. Verify signature
  const isValid = publicKey.verifySignature({
    message: signingMessage,
    signature: signature
  });

  console.log("Signature valid:", isValid);

  // 5. Submit transaction
  try {
    const result = await client.transaction.submit.simple({
      transaction: tx,
      senderAuthenticator: {
        publicKey: publicKey,
        signature: signature
      }
    });
    console.log("Transaction hash:", result.hash);
  } catch (error) {
    console.error("Transaction failed:", error);
  }
};

main().catch(console.error); 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions