Appearance
Setting up your environment
Follow the guide below to set up your environment to execute actions with wallets from your server.
Node SDK vs. REST API
To execute delegated actions with wallets, your server must make HTTP requests to Privy's REST API with information about your intended action and appropriate authorization details.
Privy also offers a NodeJS SDK (@privy-io/server-auth
) that wraps requests to Privy's REST API in a simple TypeScript interface. If your app uses a TypeScript/JavaScript backend, we strongly recommend using @privy-io/server-auth
for executing delegated actions.
Make sure to follow the instructions here to set up your @privy-io/server-auth
client or to configure your HTTP requests to Privy's REST API with the required authorization headers.
Authorization signatures
If your app has an authorization keypair enabled for delegated actions, your server must sign any request payloads for executing actions with wallets with your app's authorization private key. This signature must be included as a privy-authorization-signature
header on RPC requests.
Follow the instructions below to ensure authorization signatures are included on requests to Privy's API, if applicable for your app.
Using @privy-io/server-auth
When initializing your instance of the PrivyClient
, pass your authorization private key from the dashboard to the client's constructor like so:
tsx
import { PrivyClient } from '@privy-io/server-auth';
...
const privy = new PrivyClient('insert-your-app-id', 'insert-your-app-secret', {
walletApi: {
authorizationPrivateKey: 'insert-your-authorization-private-key-from-the-dashboard'
}
});
If an authorization private key is passed in the constructor, the Privy client will automatically sign requests with the private key and include the signature as the required privy-authorization-signature
header to Privy's API.
Using the REST API
If requesting Privy's REST API directly, your app must manually sign request payloads with your authorization private key. This involves three steps at a high-level:
- Generate a JSON payload containing the following fields. All fields are required unless otherwise specified.
Field | Type | Description |
---|---|---|
version | 1 | Authorization signature version. Currently, 1 is the only version. |
method | 'POST' | HTTP method for the request. Currently, only 'POST' requests are used. |
url | string | The full URL for the request. Should not include a trailing slash. |
body | JSON | JSON body for the request. |
headers | JSON | JSON object containing any Privy-specific headers, e.g. those that are prefixed with 'privy-' . This should not include any other headers, such as authentication headers, content-type , or trace headers. |
headers['privy-app-id'] | string | Privy app ID header (required). |
- Canonicalize the payload per RFC8785 and serialize it to a string. This GitHub repository links to various libraries for JSON canonicalization in different languages.
- Sign the serialized JSON with ECDSA P-256 using your app's private key and serialize it to a base64-encoded string.
See the code snippets below to serialize and sign requests with your app's private key.
ts
import canonicalize from 'canonicalize'; // Support JSON canonicalization
import crypto from 'crypto'; // Support P-256 signing
// Replace this with your private key from the Dashboard
const PRIVY_AUTHORIZATION_KEY = 'wallet-auth:insert-your-private-key-here';
...
function getAuthorizationSignature({url, body}: {url: string; body: object}) {
const payload = {
version: 1,
method: 'POST',
url,
body,
headers: {
'privy-app-id': 'insert-your-app-id'
}
};
// JSON-canonicalize the payload and convert it to a buffer
const serializedPayload = canonicalize(payload) as string;
const serializedPayloadBuffer = Buffer.from(serializedPayload);
// Replace this with your app's authorization key. We remove the 'wallet-auth:' prefix
// from the key before using it to sign requests
const privateKeyAsString = PRIVY_AUTHORIZATION_KEY.replace('wallet-auth:', '');
// Convert your private key to PEM format, and instantiate a node crypto KeyObject for it
const privateKeyAsPem = `-----BEGIN PRIVATE KEY-----\n${privateKeyAsString}\n-----END PRIVATE KEY-----`;
const privateKey = crypto.createPrivateKey({
key: privateKeyAsPem,
format: 'pem',
});
// Sign the payload buffer with your private key and serialize the signature to a base64 string
const signatureBuffer = crypto.sign('sha256', serializedPayloadBuffer, privateKey);
const signature = signatureBuffer.toString('base64');
return signature;
}
const authorizationSignature = getAuthorizationSignature({
url: 'https://auth.privy.io/api/v1/wallets/rpc',
// Replace with your desired body
body: {
address: '0xb8B849D7647937eB7331Dc7b6C445651A3EC55aE',
chain_type: 'ethereum',
method: 'personal_sign',
params: {
message: 'Hello, Ethereum',
encoding: 'utf-8'
}
},
});
Setting the privy-authorization-signature
header
Once you have signed your request with your authorization keypair, include the produced signature
as the 'privy-authorization-signature'
header for your request.