Export Private Key

You can export the decrypted private key from a server wallet. This is useful for migration or backup scenarios.
const decryptedPrivateKey = await client.exportPrivateKey({
  organizationId: 'fdbbad46-047f-4ff7-a13c-9e14bca69857',
  address: '0x5bBF0b7847A7a35E419eD431069fE92542B4f5c3',
  embeddedPrivateKey: process.env.SERVER_WALLET_ACCESS_KEY!,
  blockchain: 'evm',
});
ParameterTypeDescription
organizationIdstringOrganization ID from your authenticated session
addressstringWallet address to export
embeddedPrivateKeystringYour 64-char hex access key
blockchainstring'evm' or 'solana'
The exported key gives full control over the wallet. Handle it with extreme care — encrypt it at rest, never log it, and never transmit it over insecure channels.

Error Handling

The SDK throws typed errors that preserve the backend’s error code and message. Wrap your calls in try/catch to handle them gracefully:
import {
  ValidationError,
  UnauthorizedError,
  ConflictError,
} from '@abstraxn/server-signer';

try {
  const session = await client.authenticate({
    userIdentity: 'merchant-backend-user-001',
    accessKey: process.env.SERVER_WALLET_ACCESS_KEY,
  });
} catch (error) {
  if (error instanceof ConflictError) {
    // 409: identity exists with a different access key
    console.error('Access key mismatch for this identity');
  } else if (error instanceof UnauthorizedError) {
    // 401: token expired and refresh failed
    console.error('Authentication failed');
  } else if (error instanceof ValidationError) {
    // 400: missing or invalid parameters
    console.error('Invalid input:', error.message);
  } else {
    throw error;
  }
}

Common Error Codes

StatusError TypeWhen It Happens
400ValidationErrorMissing required fields (e.g. stamped payload fields for whoami or signTransaction)
401UnauthorizedErrorToken missing or expired, and automatic refresh failed
409ConflictErroruserIdentity already registered with a different access key or public key

MFA (Multi-Factor Authentication)

The SDK includes MFA methods for additional security on sensitive operations:
// Check MFA status
const status = await client.mfaStatus();

// Enable MFA
await client.mfaEnable();

// Verify MFA setup with a TOTP code
await client.mfaVerifySetup({ code: '123456' });

// Verify MFA for a standard operation
await client.mfaVerify({ code: '123456' });

// Verify MFA specifically for signing
await client.mfaVerifySign({ code: '123456' });

// Disable MFA
await client.mfaDisable({ code: '123456' });

Security Best Practices

Store secrets securely

Never hardcode accessKey or API keys in source code. Use a secrets manager:
// ✅ Good — loaded from environment / secrets manager
const client = new ServerSignerClient({
  apiKey: process.env.ABSTRAXN_API_KEY!,
});

const session = await client.authenticate({
  userIdentity: 'payout-service',
  accessKey: process.env.SERVER_WALLET_ACCESS_KEY,
});
// ❌ Bad — hardcoded secrets
const client = new ServerSignerClient({
  apiKey: 'ak_live_abc123...',
});

Never expose keys in frontend code

The @abstraxn/server-signer package is designed for Node.js backends. If you need wallet functionality in a browser, use @abstraxn/signer-react instead.

Avoid logging sensitive data

Do not log raw access keys, private keys, or full signatures in production:
// ❌ Bad
console.log('Access key:', session.accessKey);
console.log('Private key:', decryptedPrivateKey);

// ✅ Good — log only non-sensitive identifiers
console.log('Authenticated identity:', session.userIdentity);
console.log('Wallet address:', session.walletAddress);

Rotate and audit

  • Rotate API keys periodically from the Abstraxn Dashboard
  • Monitor your wallet transactions for unexpected activity
  • Use separate userIdentity values for different services (e.g. payout-service, minting-service)

Deprecated Aliases

These methods still work but will be removed in a future version:
DeprecatedUse Instead
ensureServerWalletSession(...)authenticate(...)
createViemClient(...)createPublicClient(...)

Next Steps