Authentication
Builder API key + challenge-bound EOA user JWT for @bento.fun/sdk.
Bento uses two layers:
- Builder API key identifies your app (
apiKey→x-builder-api-key). Required bycreateBentoSdk. For hackathons, generate a testnet key. - User JWT identifies the user. Attach it with
walletAuthProvider/jwtAuthProvideroncreateBentoSdk({ auth }).
Use baseUrl: 'https://internal-server.bento.fun' on testnet. You store the session. Bento does not keep platform logins for you.
EOA (canonical)
Sign the login message, then login — or register once if the wallet is new:
import { createBentoSdk, walletAuthProvider } from '@bento.fun/sdk';
const sdk = createBentoSdk({
baseUrl: 'https://internal-server.bento.fun',
apiKey: process.env.BENTO_BUILDER_API_KEY!,
auth: walletAuthProvider(() => ({})),
});
const challenge = await sdk.public.auth.eoaChallenge({
address: account.address,
domain: 'yourapp.example',
});
const signature = await account.signMessage({ message: challenge.message });
type AuthRes = { exists?: boolean; token?: string; address?: string };
let res = (await sdk.public.auth.eoaLogin({
address: account.address,
signature,
timestamp: challenge.timestamp,
domain: challenge.domain,
})) as AuthRes;
// New wallet: eoaLogin returns { exists: false } (HTTP 200, no token)
if (!res.exists || !res.token) {
res = (await sdk.public.auth.eoaRegister({
address: account.address,
signature,
timestamp: challenge.timestamp,
domain: challenge.domain,
username: `builder-${account.address.slice(2, 8)}`,
// mainnet also requires inviteCode
})) as AuthRes;
}
const token = res.token!;
const managedAccountAddress = res.address!; // custodial — funds live here
const authed = createBentoSdk({
baseUrl: 'https://internal-server.bento.fun',
apiKey: process.env.BENTO_BUILDER_API_KEY!,
auth: walletAuthProvider(() => ({ Authorization: `Bearer ${token}` })),
});| Field on session | Meaning |
|---|---|
token | Bearer JWT for sdk.user |
address | Managed account (balances / positions) |
| Signing wallet | Your EOA — proves identity only |
Register / login does not fund you. On testnet, call sdk.public.faucet.mint({ address: managedAccountAddress }) next. → Money
Auth providers
| Provider | Headers | Use with |
|---|---|---|
walletAuthProvider | Injected headers — put Authorization: Bearer here for markets | auth |
jwtAuthProvider | Authorization: Bearer | tournamentsAuth |
staticHeadersProvider | Fixed headers you supply | either |
Tournaments host
sdk.tournaments.auth.login uses the same signed login message and returns a
tournaments-host JWT. Prefer Bearer via tournamentsAuth over legacy x-wallet-* headers.