Skip to main content

Scaffold

npx create-inco-app@latest my-app --wallet dynamic --framework hardhat --chain evm --yes

Environment Setup

Get your environment ID from app.dynamic.xyz and add it to frontend/.env.local:
NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID=your_environment_id_here
NEXT_PUBLIC_CONFLOTTERY_ADDRESS=<deployed_contract_address>

Provider Setup

Dynamic uses DynamicContextProvider for wallet orchestration and DynamicWagmiConnector to bridge wallet state into wagmi. You also need to manually configure the EVM network details.
Providers.tsx
"use client";

import { ReactNode } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider, createConfig, http } from "wagmi";
import {
  DynamicContextProvider,
} from "@dynamic-labs/sdk-react-core";
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";
import { DynamicWagmiConnector } from "@dynamic-labs/wagmi-connector";
import { ThemeProvider } from "next-themes";
import { baseSepolia } from "wagmi/chains";

const queryClient = new QueryClient();

const environmentId = process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID || "";

const config = createConfig({
  chains: [baseSepolia],
  multiInjectedProviderDiscovery: false,
  transports: {
    [baseSepolia.id]: http(),
  },
  ssr: true,
});

const evmNetworks = [
  {
    blockExplorerUrls: ["https://sepolia.basescan.org"],
    chainId: 84532,
    name: "Base Sepolia",
    rpcUrls: ["https://sepolia.base.org"],
    iconUrls: ["https://avatars.githubusercontent.com/u/108554348?v=4"],
    nativeCurrency: { name: "Ethereum", symbol: "ETH", decimals: 18 },
    networkId: 84532,
  },
];

const Providers = ({ children }: { children: ReactNode }) => {
  return (
    <ThemeProvider attribute="class" defaultTheme="dark" enableSystem>
      <DynamicContextProvider
        settings={{
          environmentId,
          walletConnectors: [EthereumWalletConnectors],
          overrides: { evmNetworks },
        }}
      >
        <WagmiProvider config={config}>
          <QueryClientProvider client={queryClient}>
            <DynamicWagmiConnector>{children}</DynamicWagmiConnector>
          </QueryClientProvider>
        </WagmiProvider>
      </DynamicContextProvider>
    </ThemeProvider>
  );
};

export { Providers };
Provider hierarchy: ThemeProviderDynamicContextProviderWagmiProviderQueryClientProviderDynamicWagmiConnector Key details:
  • EthereumWalletConnectors enables Ethereum-compatible wallets in Dynamic’s modal.
  • evmNetworks configures Base Sepolia as the target network with its chain ID, RPC, and block explorer.
  • DynamicWagmiConnector bridges Dynamic’s wallet state into wagmi hooks.
  • multiInjectedProviderDiscovery: false prevents conflicts between Dynamic and wagmi’s wallet detection.

Inco SDK Integration

The Inco SDK works with the walletClient provided by wagmi (which Dynamic bridges through DynamicWagmiConnector). Here’s the core pattern:
useConfLottery.ts
import { Lightning } from "@inco/js/lite";
import { handleTypes } from "@inco/js";
import { useAccount, useWalletClient, useWriteContract } from "wagmi";
import { parseEther } from "viem";

// Initialize Inco once
const zap = await Lightning.latest("testnet", 84532);

// Encrypt a value before sending on-chain
const { address } = useAccount();
const { data: walletClient } = useWalletClient();

async function deposit(amount: string) {
  const ciphertext = await zap.encrypt(parseEther(amount), {
    accountAddress: address,
    dappAddress: LOTTERY_ADDRESS,
    handleType: handleTypes.euint256,
  });

  const fee = await publicClient.readContract({
    address: zap.executorAddress,
    abi: getFeeAbi,
    functionName: "getFee",
  });

  writeContract({
    address: LOTTERY_ADDRESS,
    abi: confLotteryAbi,
    functionName: "deposit",
    args: [ciphertext],
    value: fee,
  });
}

// Decrypt with attestation
async function checkWinner() {
  const encryptedHandle = await publicClient.readContract({
    address: LOTTERY_ADDRESS,
    abi: confLotteryAbi,
    functionName: "getMyWinnerCheck",
    args: [currentRound],
    account: address,
  });

  const result = await zap.attestedDecrypt(walletClient, [encryptedHandle]);
  const isWinner = result[0].plaintext.value; // true or false
}
Dynamic manages the wallet connection and network switching — once connected, wagmi’s useWalletClient() provides the signer that Inco’s attestedDecrypt uses for signing attestation requests.

Dependencies

PackagePurpose
@dynamic-labs/sdk-react-coreDynamic wallet orchestration
@dynamic-labs/ethereumEthereum wallet connectors
@dynamic-labs/wagmi-connectorDynamic-wagmi bridge
@inco/jsInco encryption/decryption
wagmiEVM wallet hooks
viemEthereum utilities