@txwallet/auth-express
v1.0.1
Published
Express helper for Sign in with TX Wallet request endpoints and ADR-36 completion verification.
Maintainers
Readme
@txwallet/auth-express
Express helper for product-domain Sign in with TX Wallet endpoints. It installs the four Auth endpoints, creates short-lived sign-in challenges, verifies ADR-36 completions, and calls your session hook only after proof verification succeeds.
Auth is login only. It does not move funds, submit an on-chain transaction, or authorize checkout.
The package also exposes a separate typed transaction-request helper surface for server-side request creation, status polling, callback parsing, and receipt fetching.
Install
npm install @txwallet/auth-express expressMinimal Use
import express from 'express';
import { installTxWalletAuthRoutes } from '@txwallet/auth-express';
const app = express();
app.use(express.json());
installTxWalletAuthRoutes(app, {
appId: process.env.TX_WALLET_APP_ID,
appDomain: process.env.TX_WALLET_APP_DOMAIN,
txWalletBaseUrl: 'https://txwallet.tesbert.com',
allowedOrigins: ['https://example.com'],
allowedCallbackPaths: ['/tx-wallet/callback'],
allowedChainIds: ['coreum-mainnet-1'],
async createSessionForAccount({ account }) {
console.log('Verified TX Wallet account', account.address);
},
});Rate Limiting
The installed routes ship with a built-in fixed-window rate limit (default 120 requests per minute per IP) so the auth endpoints are never exposed unthrottled. Tune or disable it:
installTxWalletAuthRoutes(app, {
// ...config
rateLimit: { windowMs: 60_000, max: 60 }, // tune
// rateLimit: false, // disable if the host app rate-limits upstream
});Routes Installed
POST /api/tx-wallet/signin/requests
GET /api/tx-wallet/signin/requests/:requestId
POST /api/tx-wallet/signin/requests/:requestId/complete
GET /api/tx-wallet/signin/requests/:requestId/statusTransaction Request Helpers
Use the request helpers when your app needs to create or inspect a typed TX Wallet Request from server code.
import {
createTxWalletTransactionRequest,
pollTxWalletTransactionStatus,
fetchTxWalletTransactionReceipt,
readTxWalletTransactionCallbackResult,
} from '@txwallet/auth-express';
const request = await createTxWalletTransactionRequest({
endpoint: '/api/tx-wallet/requests',
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
chainId: 'coreum-mainnet-1',
body: {
category: 'token_payment',
payer: 'core1payer...',
recipient: 'core1recipient...',
amount: '1',
},
});
const status = await pollTxWalletTransactionStatus(request.status_url);
const receipt = status.receipt_url ? await fetchTxWalletTransactionReceipt(status.receipt_url) : null;
const callback = readTxWalletTransactionCallbackResult('https://partner.example.com/tx-wallet/callback?tx_wallet_status=broadcasted');Transaction helper exports:
createTxWalletTransactionRequest()createTxWalletTransactionRequestWithPolicyCheck()pollTxWalletTransactionStatus()fetchTxWalletTransactionReceipt()normalizeTxWalletTransactionRequest()normalizeTxWalletTransactionStatus()normalizeTxWalletTransactionReceipt()readTxWalletTransactionCallbackResult()
Policy/capability helper exports:
fetchTxWalletRequestCapabilities()fetchTxWalletAppPolicy()normalizeTxWalletRequestCapabilitiesSnapshot()normalizeTxWalletAppPolicy()resolveTxWalletCategoryCapability()assertTxWalletCategoryPolicy()
Policy-checked request creation example:
import { createTxWalletTransactionRequestWithPolicyCheck } from '@txwallet/auth-express';
const { request, policy } = await createTxWalletTransactionRequestWithPolicyCheck({
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
category: 'checkout_payment',
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
chainId: 'coreum-mainnet-1',
body: {
payer: 'core1payer...',
recipient: 'core1recipient...',
amount: '1',
order_id: 'order_123',
merchant_name: 'Example Store',
},
});
console.log(policy.status, request.request_id);By default, policy-checked creation blocks categories marked review-only by capability policy to reduce onboarding mistakes. Pass allowReviewOnly: true only for deliberate review-fixture workflows.
Production Notes
The helper verifies the ADR-36 proof before returning an approved completion. Store requests and sessions durably before using this pattern in production; the package baseline keeps request state in memory so teams can inspect the contract without a database decision baked in. If the wallet completion request cannot set your product's browser session directly, persist the verified approved request and let your same-origin callback/status flow exchange it for a normal session.
Before creating a product session, the verifier checks that the request is pending, unexpired, and not consumed; the signed challenge matches stored request state; the ADR-36 sign doc has the required fixed fields; and the public key derives the signed Coreum/TX address.
Safety Boundary
- Use these routes for login/account-linking only.
- Keep transaction-request create/status/complete routes separate from Auth routes.
- Never ask for a recovery phrase, wallet password, private key, or seed.
- Never store raw management tokens, recovery codes, signatures, or session secrets in logs.
