Next.js (App Router)
Use the@imtbl/auth-nextjs package for the simplest integration:
Copy
Ask AI
npm install @imtbl/auth-nextjs
Setup
Copy
Ask AI
// app/layout.tsx
import { ImmutableProvider } from '@imtbl/auth-nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ImmutableProvider
clientId={process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!}
redirectUri={`${process.env.NEXT_PUBLIC_URL}/callback`}
logoutRedirectUri={process.env.NEXT_PUBLIC_URL!}
>
{children}
</ImmutableProvider>
</body>
</html>
);
}
Using the Hooks
Copy
Ask AI
// app/page.tsx
'use client';
import { useAuth, useWallet } from '@imtbl/auth-nextjs';
export default function Home() {
const { user, login, logout, isLoading } = useAuth();
const { address, connect } = useWallet();
if (isLoading) return <div>Loading...</div>;
if (!user) {
return <button onClick={login}>Login with Passport</button>;
}
return (
<div>
<p>Welcome, {user.email}</p>
{address ? (
<p>Wallet: {address}</p>
) : (
<button onClick={connect}>Connect Wallet</button>
)}
<button onClick={logout}>Logout</button>
</div>
);
}
Callback Route
Copy
Ask AI
// app/callback/page.tsx
'use client';
import { AuthCallback } from '@imtbl/auth-nextjs';
export default function Callback() {
return <AuthCallback redirectTo="/" errorRedirectTo="/?error=auth" />;
}
Environment Variables
Copy
Ask AI
NEXT_PUBLIC_IMMUTABLE_CLIENT_ID=your_client_id
NEXT_PUBLIC_URL=http://localhost:3000
Vite
Copy
Ask AI
npm install @imtbl/auth @imtbl/wallet
Initialization
Copy
Ask AI
// src/lib/immutable.ts
import { Auth } from '@imtbl/auth';
import { connectWallet, ZkEvmProvider } from '@imtbl/wallet';
export const auth = new Auth({
clientId: import.meta.env.VITE_CLIENT_ID,
redirectUri: `${window.location.origin}/callback`,
logoutRedirectUri: window.location.origin,
audience: 'platform_api',
scope: 'openid offline_access email transact',
});
let providerPromise: Promise<ZkEvmProvider> | null = null;
export function getProvider() {
if (!providerPromise) {
providerPromise = connectWallet({ auth });
}
return providerPromise;
}
Node.js (Backend)
For server-side operations like minting:Copy
Ask AI
import { Environment } from '@imtbl/config';
const API_BASE = Environment.SANDBOX === 'sandbox'
? 'https://api.sandbox.immutable.com'
: 'https://api.immutable.com';
async function mintNFT(address: string, tokenId: string, metadata: object) {
const response = await fetch(
`${API_BASE}/v1/chains/imtbl-zkevm-testnet/collections/${CONTRACT}/nfts/mint-requests`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-immutable-api-key': process.env.IMMUTABLE_SECRET_KEY!,
},
body: JSON.stringify({
assets: [{
owner_address: address,
token_id: tokenId,
metadata,
}],
}),
}
);
if (!response.ok) throw new Error('Mint failed');
return response.json();
}
wagmi Integration
Use Passport with wagmi for React hooks:Copy
Ask AI
import { createConfig, http } from 'wagmi';
import { immutableZkEvmTestnet } from 'wagmi/chains';
import { injected } from 'wagmi/connectors';
// Passport injects as EIP-1193 provider
export const wagmiConfig = createConfig({
chains: [immutableZkEvmTestnet],
connectors: [injected()],
transports: {
[immutableZkEvmTestnet.id]: http(),
},
});
Copy
Ask AI
// In your component
import { useAccount, useConnect, useSendTransaction } from 'wagmi';
function WalletButton() {
const { address, isConnected } = useAccount();
const { connect, connectors } = useConnect();
if (isConnected) {
return <span>{address?.slice(0, 8)}...</span>;
}
return (
<button onClick={() => connect({ connector: connectors[0] })}>
Connect
</button>
);
}