@abstraxn/server-signer
v1.0.1
Published
Server wallet SDK for backend integrations with Abstraxn wallet-service
Readme
@abstraxn/server-signer
Backend SDK for Abstraxn server-wallet authentication, signing, and transaction execution.
This package is for server environments (Node.js). It provides:
- server-wallet auth (
create,exchange,authenticate) - automatic access-token refresh on
401 - provider-stamped backend operations (
whoami, signing, export) - Viem-style transaction flow (
prepare,estimate,sign,send,receipt)
Installation
npm install @abstraxn/server-signerRequired Inputs
ABSTRAXN_API_KEY: backend API keyuserIdentity: unique identity string for your server wallet useraccessKey: 64-char hex server wallet access key (optional on first run, required to recover same identity later)
Quick Start (Recommended)
import { ServerSignerClient } from '@abstraxn/server-signer';
const client = new ServerSignerClient({
apiKey: process.env.ABSTRAXN_API_KEY!,
});
const session = await client.authenticate({
userIdentity: 'merchant-backend-user-001',
// Optional: provide existing key. If omitted, SDK generates one.
accessKey: process.env.SERVER_WALLET_ACCESS_KEY,
userName: 'Merchant Backend',
userEmail: '[email protected]',
});
console.log(session.didCreate); // true if create+exchange happened, false if token already existed
console.log(session.accessToken); // current access token
console.log(session.accessKey); // persist this securely
console.log(session.targetPublicKey);
const whoami = await client.whoami();Authentication Model
authenticate() is idempotent:
- if token exists in token store -> reuses it
- if token is missing -> derives public key from
accessKey, runs create+exchange, stores token
Automatic Token Refresh
Authenticated calls automatically retry once on 401:
- calls
POST /auth/refreshwithcredentials: 'include' - updates access token if refresh succeeds
No configuration is required for default behavior.
Viem-Style Public Client
Create a public client wrapper with backend signing:
const publicClient = client.createPublicClient({
rpcUrl: process.env.RPC_URL!,
chainId: 137,
organizationId: 'fdbbad46-047f-4ff7-a13c-9e14bca69857',
fromAddress: '0x5bBF0b7847A7a35E419eD431069fE92542B4f5c3',
});Transaction Flow
const prepared = await publicClient.prepareTransaction({
to: '0x1111111111111111111111111111111111111111',
value: 1_000_000_000_000_000n,
});
const txHash = await publicClient.signAndSendPreparedTransaction(prepared.unsignedTransaction);
const receipt = await publicClient.waitForTransactionReceipt(txHash);Sign Features
const messageSig = await publicClient.signMessage({
message: 'hello from server-signer',
});
const typedDataSig = await publicClient.signTypedData({
typedData: {
domain: { name: 'Abstraxn', version: '1', chainId: 137 },
message: { contents: 'Hi' },
primaryType: 'Mail',
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
],
Mail: [{ name: 'contents', type: 'string' }],
},
},
});
const rawSig = await publicClient.signRawPayload({
payload: '0x1234',
encoding: 'PAYLOAD_ENCODING_HEXADECIMAL',
hashFunction: 'HASH_FUNCTION_SHA256',
});Export Private Key
const decryptedPrivateKey = await client.exportPrivateKey({
organizationId: 'fdbbad46-047f-4ff7-a13c-9e14bca69857',
address: '0x5bBF0b7847A7a35E419eD431069fE92542B4f5c3',
embeddedPrivateKey: process.env.SERVER_WALLET_ACCESS_KEY!,
blockchain: 'evm', // or 'solana'
});Main Methods
authenticate(input)- primary auth entrypointwhoami(input?)createPublicClient(config)- viem-style transaction/sign helpersignTransaction(payload)- raw backend sign endpoint wrappersignMessage/signTypedData/signRawPayload(via public client)exportPrivateKey(input)mfaStatus,mfaEnable,mfaVerifySetup,mfaVerify,mfaVerifySign,mfaDisable
Backward-compatible aliases are still available:
ensureServerWalletSession(...)(deprecated; useauthenticate)createViemClient(...)(deprecated; usecreatePublicClient)
Errors
SDK throws typed errors (ValidationError, UnauthorizedError, ConflictError, etc.) with backend code/message preserved when available.
Common cases:
409 CONFLICTon create:userIdentityalready exists with a different access key/public key400 BAD_REQUESTon whoami/sign: missing stamped payload fields401 UNAUTHORIZED: token missing/expired (SDK auto-refreshes once)
Security Notes
- Store
accessKeyin a secure secrets manager. - Never expose
accessKeyor decrypted private keys in frontend code. - Avoid logging raw keys or sensitive signatures in production.
