Skip to content

How to use a DFNS signer with permissionless.js

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.

Setup

To use Dfns with permissionless.js, first create an application that integrates with Dfns.

Integration

Integrating permissionless.js with Dfns is straightforward after setting up the project. Dfns provides an Externally Owned Account (EOA) wallet to use as a signer with permissionless.js accounts.

Set up Dfns

After following the Dfns documentation, you will have access to a dfnsWallet object as shown below:

import { DfnsWallet } from "@dfns/lib-viem"
import { DfnsApiClient } from "@dfns/sdk"
import { AsymmetricKeySigner } from "@dfns/sdk-keysigner"
import { AccountSource, createWalletClient, http } from "viem"
import { toAccount } from "viem/accounts"
 
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,
	})
}
 
const sepoliaWallet = await initDfnsWallet(SEPOLIA_WALLET_ID)
const account = toAccount(sepoliaWallet as AccountSource)
const smartAccountOwner = createWalletClient({
	account,
	transport: http("https://rpc.ankr.com/eth_sepolia"),
})

Use with permissionless.js

SimpleAccount
import { createSmartAccountClient } from "permissionless"
import { toSimpleSmartAccount } from "permissionless/accounts"
import { createPublicClient, http } from "viem"
import { sepolia } from "viem/chains"
import { createPimlicoClient } from "permissionless/clients/pimlico"
import { entryPoint07Address } from "viem/account-abstraction"
 
const publicClient = createPublicClient({
	chain: sepolia, // or whatever chain you are using
	transport: http(),
})
 
const pimlicoUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=<PIMLICO_API_KEY>`
 
const pimlicoClient = createPimlicoClient({
	transport: http(pimlicoUrl),
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
})
 
const simpleSmartAccount = await toSimpleSmartAccount({
	owner: smartAccountOwner,
	client: publicClient,
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
})
 
const smartAccountClient = createSmartAccountClient({
	account: simpleSmartAccount,
	chain: sepolia,
	bundlerTransport: http(pimlicoUrl),
	paymaster: pimlicoClient,
	userOperation: {
		estimateFeesPerGas: async () => {
			return (await pimlicoClient.getUserOperationGasPrice()).fast
		},
	},
})