Getting Started with Privy
Let's get started with a basic example using Privy
Pre-requisites
1. Set Up Authorization Keys
What is an authorization key?
The authorization key is a user created by you, the client application, for the Enclave team, that allows us to issue transaction policies that enforce resource locks on users that wish to enable Magicspend++.
You can create an authorization key on the Privy dashboard by following the steps mentioned here.
Once you have created the authorization key, share the all key details with the Enclave team to enable integration. Also note down it's public key and API key name, these values are required for the next step.
2. Creating Users and Wallets with Key Quorums
Modify the existing user creation logic in your onboarding flow to provision a wallet with a key quorum that includes both the end user and the authorization key created in the previous step.
The key quorum structure is such that each unique user has a wallet owned by a key quorum with 2 members: the end user and the authorization key that issues policies on the user's wallet.
Given below is some sample code that can be used as reference:
Creating a wallet with authorization key
import { usePrivy } from '@privy-io/react-auth';
const WalletComponent = () => {
const { getAccessToken, authenticated } = usePrivy();
const authPublicKey = process.env.NEXT_PUBLIC_ENCLAVE_AUTH_PUBLIC_KEY!;
if (!authPublicKey) {
console.log('⚠️ Authorization key not found in environment variables, skipping');
return;
}
const createWalletWithQuorum = async (chainType: 'ethereum' | 'solana') => {
const token = await getAccessToken();
const response = await fetch('/api/wallets/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ chainType }),
});
const result = await response.json();
return result.wallet;
};
};Server-side implementation
import { usePrivy } from '@privy-io/react-auth';
const WalletComponent = () => {
const { getAccessToken, authenticated } = usePrivy();
const authPublicKey = process.env.NEXT_PUBLIC_ENCLAVE_AUTH_PUBLIC_KEY!;
if (!authPublicKey) {
console.log('⚠️ Authorization key not found in environment variables, skipping');
return;
}
const createWalletWithQuorum = async (chainType: 'ethereum' | 'solana') => {
const token = await getAccessToken();
const response = await fetch('/api/wallets/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ chainType }),
});
const result = await response.json();
return result.wallet;
};
};
Server-side implementation
import { NextResponse } from 'next/server';
import { getAccessTokenFromRequest, verifyAccessToken } from '@/lib/privy-server';
const PRIVY_APP_ID = process.env.NEXT_PUBLIC_PRIVY_APP_ID;
const PRIVY_APP_SECRET = process.env.NEXT_PUBLIC_PRIVY_APP_SECRET;
const PRIVY_AUTHORIZATION_PUBLIC_KEY = process.env.PRIVY_AUTHORIZATION_PUBLIC_KEY;
const PRIVY_API_URL = 'https://api.privy.io/v1';
export async function POST(request: Request) {
// Extract and verify token
const token = getAccessTokenFromRequest(request);
if (!token) {
return NextResponse.json({ error: 'No access token' }, { status: 401 });
}
const claims = await verifyAccessToken(token);
if (!claims) {
return NextResponse.json({ error: 'Invalid token' }, { status: 401 });
}
const userId = claims.userId;
const { chainType } = await request.json();
// Format public key
const formattedPublicKey = PRIVY_AUTHORIZATION_PUBLIC_KEY!.replace(/\\n/g, '\n');
// Create 1-of-2 key quorum
const keyQuorumResponse = await fetch(`${PRIVY_API_URL}/key_quorums`, {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(`${PRIVY_APP_ID}:${PRIVY_APP_SECRET}`).toString('base64')}`,
'privy-app-id': PRIVY_APP_ID!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
public_keys: [formattedPublicKey],
user_ids: [userId],
authorization_threshold: 1,
}),
});
const keyQuorum = await keyQuorumResponse.json();
// Create wallet owned by key quorum
const walletResponse = await fetch(`${PRIVY_API_URL}/wallets`, {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(`${PRIVY_APP_ID}:${PRIVY_APP_SECRET}`).toString('base64')}`,
'privy-app-id': PRIVY_APP_ID!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
chain_type: chainType,
owner_id: keyQuorum.id,
}),
});
const wallet = await walletResponse.json();
return NextResponse.json({
success: true,
wallet: {
id: wallet.id,
address: wallet.address,
chainType: wallet.chain_type,
}
});
}
Next let's see how we can fetch a quote
Fetching a quoteLast updated