Skip to content

Dfns Integration Guide

Dfns is an MPC/TSS Wallet-as-a-Service API/SDK provider. Dfns aims to optimize the balance of security and UX by deploying key shares into a decentralized network on the backend while enabling wallet access via biometric open standards on the frontend like Webauthn. Reach out here to set up a sandbox environment to get started.

Dfns seamlessly integrates with Account Abstraction by signing UserOperations. See the examples below for initializing a DFNS signer and creating a provider with that signer. You can follow this guide to send and sponsor UserOperations with the provider created.

Dfns created a full example of a gas-less transaction via a paymaster in our SDK, adapted from our gas sponsorship example.

Install Dfns SDK

bash
npm i @dfns/lib-viem @dfns/sdk @dfns/sdk-keysigner
bash
yarn add @dfns/lib-viem @dfns/sdk @dfns/sdk-keysigner

Create a SmartAccountSigner

Setup the Dfns Web3 Provider and wrap it in an AlchemyProvider.

ts
import { LocalAccountSigner, type SmartAccountSigner } from "@alchemy/aa-core";
import { DfnsWallet } from "@dfns/lib-viem";
import { DfnsApiClient } from "@dfns/sdk";
import { AsymmetricKeySigner } from "@dfns/sdk-keysigner";
import { LocalAccount, toAccount } from "viem/accounts";

// See the Dfns example https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/alchemy-aa-gasless for details on populating the environment variables.
const DFNS_PRIVATE_KEY = null;
const DFNS_CRED_ID = null;
const DFNS_APP_ORIGIN = null;
const DFNS_APP_ID = null;
const DFNS_AUTH_TOKEN = null;
const DFNS_API_URL = null;
const SEPOLIA_WALLET_ID = null;

const initDfnsWallet = (walletId: string) => {
  const signer = new AsymmetricKeySigner({
    privateKey: DFNS_PRIVATE_KEY!,
    credId: DFNS_CRED_ID!,
    appOrigin: DFNS_APP_ORIGIN!,
  });

  const dfnsClient = new DfnsApiClient({
    appId: DFNS_APP_ID!,
    authToken: DFNS_AUTH_TOKEN!,
    baseUrl: DFNS_API_URL!,
    signer,
  });

  return DfnsWallet.init({
    walletId,
    dfnsClient,
    maxRetries: 10,
  });
};

export const createDfnsSigner = async (): Promise<SmartAccountSigner> => {
  const sepoliaWallet = await initDfnsWallet(SEPOLIA_WALLET_ID!);
  const account = toAccount(sepoliaWallet) as LocalAccount;
  const dfnsSigner = new LocalAccountSigner(account as any);
  return dfnsSigner;
};

Use it with Light Account

ts
import { createModularAccountAlchemyClient } from "@alchemy/aa-alchemy";
import { sepolia } from "@alchemy/aa-core";
import { createDfnsSigner } from "./dfns";

// Remember to replace "ALCHEMY_API_KEY" with your own Alchemy API key, get one here: https://dashboard.alchemy.com/
const ALCHEMY_API_KEY = "API_KEY";
const chain = sepolia;

const createAlchemyProvider = async () => {
  return createModularAccountAlchemyClient({
    apiKey: ALCHEMY_API_KEY,
    chain,
    signer: await createDfnsSigner(),
  });
};
ts
import { LocalAccountSigner, type SmartAccountSigner } from "@alchemy/aa-core";
import { DfnsWallet } from "@dfns/lib-viem";
import { DfnsApiClient } from "@dfns/sdk";
import { AsymmetricKeySigner } from "@dfns/sdk-keysigner";
import { LocalAccount, toAccount } from "viem/accounts";

// See the Dfns example https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/alchemy-aa-gasless for details on populating the environment variables.
const DFNS_PRIVATE_KEY = null;
const DFNS_CRED_ID = null;
const DFNS_APP_ORIGIN = null;
const DFNS_APP_ID = null;
const DFNS_AUTH_TOKEN = null;
const DFNS_API_URL = null;
const SEPOLIA_WALLET_ID = null;

const initDfnsWallet = (walletId: string) => {
  const signer = new AsymmetricKeySigner({
    privateKey: DFNS_PRIVATE_KEY!,
    credId: DFNS_CRED_ID!,
    appOrigin: DFNS_APP_ORIGIN!,
  });

  const dfnsClient = new DfnsApiClient({
    appId: DFNS_APP_ID!,
    authToken: DFNS_AUTH_TOKEN!,
    baseUrl: DFNS_API_URL!,
    signer,
  });

  return DfnsWallet.init({
    walletId,
    dfnsClient,
    maxRetries: 10,
  });
};

export const createDfnsSigner = async (): Promise<SmartAccountSigner> => {
  const sepoliaWallet = await initDfnsWallet(SEPOLIA_WALLET_ID!);
  const account = toAccount(sepoliaWallet) as LocalAccount;
  const dfnsSigner = new LocalAccountSigner(account as any);
  return dfnsSigner;
};