A common setup for Privy apps is to configure wallets such that both users and apps themselves can execute transactions from user wallets. This serves a variety of use cases:

  • Allowing apps to execute limit orders on behalf of a user, even when a user is offline
  • Allowing apps to rebalance user portfolios based on market data, even when the user is offline
  • Creating Telegram trading bots or other agents controlled by your app’s server that can execute transactions on behalf of users

You can accomplish these use cases via session signers, which enable user to grant specific permissions to your app to transact on their behalf. Follow the guide below to learn how to integrate session signers for your use case.

0. Prerequisites

Prior to following this guide, follow the quickstart for Privy’s React SDK or React Native SDK to get your app instrumented with Privy’s basic functionality.

If you plan to use this setup as part of a Telegram trading bot, check out the guide to integrate Telegram seamless login with the React SDK for a smoother user experience when signing into Telegram mini-apps.

1. Create an app authorization key

To allow your app to be send transactions from user wallets, you must first create an app authorization key. Your app’s server will sign API requests with this key to authorize sending transactions from user wallets.

Create an authorization key locally on your machine like so:

openssl ecparam -name prime256v1 -genkey -noout -out private.pem && \
openssl ec -in private.pem -pubout -out public.pem

Retrieve the public key from the public.pem file and the private key from the private.pem file in your working directory.

Make sure to save both files securely. Privy does not store your private key and cannot help you recover it.

2. Register the app authorization key in a key quorum

Next, register the public key you created with Privy so that Privy can appropriately verify signed requests from your app.

To do so, visit the Authorization keys page of the Privy Dashboard and click the New key button in the top right. Then, click the Register key quorum instead option.

In the modal that pops up, enter the public key you generated in step 1 in the Public keys field. Set the Authorization threshold to 1, to allow that single key to sign on behalf of the key quorum, and set the Quorum name to a human readable name of your choice.

Save the id of the key quorum that is created. You will need this value later.

This creates a 1-of-1 key quorum that can be granted permission to execute actions from a user’s wallet.

You can also register the public key with Privy programmatically via the REST API.

3. Configure your Privy app to create embedded wallets on login

Next, configure your Privy app to automatically create embedded wallets when users login.

This ensures that all users have an embedded wallet, regardless of whether they login via a web app, a Telegram mini app, or a native mobile app.

In your PrivyProvider component, set the config.embeddedWallets.ethereum.createOnLogin property to 'all' to automatically create embedded wallets for users, regardless of what login method they use.

<PrivyProvider
  appId="your-privy-app-id"
  config={{
    embeddedWallets: {
      ethereum: {
        createOnLogin: 'all'
      }
    }
  }}
>
  {children}
</PrivyProvider>

4. (Optional) Create a policy for your signer

If you’d like your signer to only have specific permissions on users’ wallets, create a policy for your signer based on the transaction it needs to execute. For example, you might create a policy that only allows transacting under a certain amount with a specific contract, in order to execute a limit order when a user is offline. You can also create multiple policies to allow your signer to execute a set of actions.

Once you’ve created your desired policy for the signer, make sure to save the policy ID. You will need this when adding your signer to users’ wallets.

See example policies for Ethereum and Solana that you can modify for your use case.

5. Add a session signer to the user’s wallet

Once a user logs in, an embedded wallet will automatically be created for them.

Once a user has an embedded wallet, add the key quorum you created in step 3 as a session signer to the user’s wallet. This allows your app to sign transaction requests from the user’s wallet via your app’s authorization key.

Once a user logs in, you can use the addSessionSigners method of useSessionSigners hook to add your app’s authorization key as a session signer on the wallet.

import {useSessionSigners} from '@privy-io/react-auth';

...

const {addSessionSigners} = useSessionSigners();
// Call this method after a user logs in and has an embedded wallet
await addSessionSigners({
    address: 'insert-user-embedded-wallet-address',
    signers: [{
        signerId: 'insert-key-quorum-id-from-step-2',
        // Replace the `policyIds` array with an array of valid policy IDs if you'd like the session signer to only be able to execute certain transaction requests allowed by a policy. If you'd like the session signer to have full permission, pass an empty array ([]).
        policyIds: ['insert-policy-id-1', 'insert-policy-id-2']
    }]
})

6. Send transactions from the user’s wallet

That’s it! Now, both users and your app can send transactions from a user’s wallet.

User-initiated transactions

Users can send transactions from your app’s frontend by taking actions in a web app (via Privy’s React SDK), a mobile app (via Privy’s React Native SDK), or a Telegram mini-app (via Privy’s React SDK).

Follow the guides below to learn how to send transactions from these environments.

Ethereum

Solana

App-initiated transactions

Your app can also now initiate transactions from users’ wallets via Privy’s NodeJS SDK or REST API. This allows your app to send transactions from users’ wallets even when the user is offline, allowing for various use cases:

  • Executing limit orders
  • Rebalancing portfolios
  • Having a Telegram trading bot execute transactions on behalf of users

Follow the guides below to send transactions from your app’s server using your app’s authorization key.

Using Privy’s REST API directly is an advanced integration. If your app uses a JavaScript or TypeScript backend, we strongly recommend using Privy’s NodeJS SDK.

To start, initialize your PrivyClient with the private key of the authorization key you created in step 1. Pass this value into the walletApi.authorizationPrivateKey field of the third positional parameter to the client’s constructor.

const privy = new PrivyClient('insert-your-app-id', 'insert-your-app-secret', {
    walletApi: {
        authorizationPrivateKey: 'insert-the-private-key-from-step-1'
    }
})

Next, follow the guides to send transactions on Ethereum and Solana with the NodeJS SDK.

Building a Telegram trading bot? Check out the Telegram trading bot recipe to learn how to have your app initiate transactions on behalf of users with a trading bot.