Learn how to build on the decentralized web
Account Abstraction Wallet
Backend Guide

Using the pier wallet SDK in your backend

Using pier wallet SDK in your backend is pretty straight forward. Main motivation to do this if you want to do one of the following:

  • mint custom tokens and NFTs for your users
  • recover a wallet for a user

Setup and Usage with Typescript, NestJS for default guardians

  • You'll need to implement an endoint on your backend, that can trigger a recovery for a user.
  • You'll need to store one or multiple web3 private keys (DEFAULT GUARDIANS) in your backend
  • You'll need to sign a specific message and send this to pier to confirm the recovery
  • You'll need to use trpc to communicate with pier
yarn add @pier-wallet/relayer @pier-wallet/utils @trpc/client:9.27.0 ethers:^5.7.2
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { AppRouter } from "@pier-wallet/relayer";
import { trpcTransformer } from "@pier-wallet/utils";
import { TRPCClient, createTRPCClient } from "@trpc/client";
import { BigNumber, Wallet } from "ethers";
import { AppConfigType } from "../../configs/appConfigType";
enum PierChainId {
export class PierService {
  private readonly trpcClient: TRPCClient<AppRouter>;
  private readonly authorizedWallet: Wallet;
  private readonly chainId: PierChainId;
  constructor(private readonly configService: ConfigService<AppConfigType>) {
    const { relayerUrl, authorizedPrivateKey, chainId } =
      this.configService.get("pier", { infer: true });
    this.chainId = Number(chainId) as PierChainId;
    this.trpcClient = createTRPCClient<AppRouter>({
      url: relayerUrl,
      transformer: trpcTransformer({ BigNumber }),
    this.authorizedWallet = new Wallet(authorizedPrivateKey);
  async recoverWalletWithDefaultGuardian(
    smartWalletAddress: string,
    newDumbWalletAddress: string
  ) {
    const signedMessageAuthData = await this.getSignedMessageAuthData();
    await this.trpcClient.mutation(
  private async getSignedMessageAuthData() {
    const messageParams = {
      chainId: this.chainId,
      signedAtTimestamp: Date.now(),
      signerAddress: this.authorizedWallet.address,
    const messageToSign = await this.trpcClient.query(
    const signature = await this.authorizedWallet.signMessage(
    return {