Scaffold
npx create-inco-app@latest my-app --wallet privy --framework anchor --chain svm --yes
pnpm create inco-app@latest my-app --wallet privy --framework anchor --chain svm --yes
yarn create inco-app my-app --wallet privy --framework anchor --chain svm --yes
bunx create-inco-app@latest my-app --wallet privy --framework anchor --chain svm --yes
Environment Setup
Create a.env.local file in the frontend/ directory:
NEXT_PUBLIC_PRIVY_APP_ID=your-privy-app-id
Provider Setup
Privy for SVM is configured in Solana-only mode with embedded wallet support and external wallet connectors (Phantom, Solflare, etc.):components/Providers.tsx
"use client";
import { PrivyProvider } from "@privy-io/react-auth";
import { toSolanaWalletConnectors } from "@privy-io/react-auth/solana";
import { createSolanaRpc, createSolanaRpcSubscriptions } from "@solana/kit";
import { ThemeProvider } from "next-themes";
const appId = process.env.NEXT_PUBLIC_PRIVY_APP_ID || "";
const solanaConnectors = toSolanaWalletConnectors();
export const Providers = ({ children }: { children: React.ReactNode }) => {
if (!appId) {
console.warn(
"Missing NEXT_PUBLIC_PRIVY_APP_ID. Get one at https://dashboard.privy.io/"
);
}
return (
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem>
<PrivyProvider
appId={appId}
config={{
appearance: {
theme: "dark",
showWalletLoginFirst: true,
walletChainType: "solana-only",
},
loginMethods: ["wallet"],
embeddedWallets: {
solana: {
createOnLogin: "users-without-wallets",
},
},
externalWallets: {
solana: { connectors: solanaConnectors },
},
solana: {
rpcs: {
"solana:devnet": {
rpc: createSolanaRpc("https://api.devnet.solana.com"),
rpcSubscriptions: createSolanaRpcSubscriptions(
"wss://api.devnet.solana.com"
),
},
},
},
}}
>
{children}
</PrivyProvider>
</ThemeProvider>
);
};
Inco SDK Integration
The hook usesusePrivy and useWallets from Privy to get the Solana wallet, and @inco/solana-sdk for client-side encryption:
hooks/useConfPool.ts
import { usePrivy, useWallets } from "@privy-io/react-auth";
import { PublicKey, SystemProgram, Connection } from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
import { encryptValue } from "@inco/solana-sdk/encryption";
import { hexToBuffer } from "@inco/solana-sdk/utils";
const INCO_LIGHTNING_PROGRAM_ID = new PublicKey(
"5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"
);
export function useConfPool() {
const { user } = usePrivy();
const { wallets } = useWallets();
// Get Solana wallet — filter out EVM addresses (0x prefix)
const solanaWallet = wallets.find(
(w) => w.address && !w.address.startsWith("0x")
);
const deposit = async (amount: string) => {
// 1. Encrypt the deposit amount client-side
const amountBn = BigInt(Math.floor(parseFloat(amount) * 1e9));
const encryptedHex = await encryptValue(amountBn);
// 2. Build the Anchor transaction
const tx = await program.methods
.deposit(hexToBuffer(encryptedHex), 0)
.accounts({
pool: poolPda,
participant: participantPda,
depositor: publicKey,
systemProgram: SystemProgram.programId,
incoLightningProgram: INCO_LIGHTNING_PROGRAM_ID,
})
.transaction();
// 3. Sign via Phantom provider and send
const provider = window?.phantom?.solana;
const signed = await provider.signTransaction(tx);
const sig = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(sig, "confirmed");
};
}
Dependencies
| Package | Purpose |
|---|---|
@privy-io/react-auth | Privy authentication and wallet management |
@privy-io/react-auth/solana | Solana wallet connectors for Privy |
@solana/kit | Solana RPC setup |
@solana/web3.js | Solana RPC and transactions |
@coral-xyz/anchor | Anchor program interaction |
@inco/solana-sdk | Client-side encryption |