Documentation Index
Fetch the complete documentation index at: https://docs.privy.io/llms.txt
Use this file to discover all available pages before exploring further.
0. Prerequisites
This guide assumes that you have completed the Setup guide.
1. Creating a wallet
First, we will create a wallet.
You will use this wallet’s id in future calls to sign messages and send transactions.
try {
WalletCreateRequestBody walletRequest = WalletCreateRequestBody.builder()
.chainType(WalletChainType.ETHEREUM)
.build();
WalletCreateResponse response = privyClient.wallets().create(walletRequest)
if (response.wallet().isPresent()) {
Wallet createdWallet = response.wallet().get();
}
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
WalletCreateRequestBody walletRequest = WalletCreateRequestBody.builder()
.chainType(WalletChainType.SOLANA)
.build();
WalletCreateResponse response = privyClient.wallets().create(walletRequest)
if (response.wallet().isPresent()) {
Wallet createdWallet = response.wallet().get();
}
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
2. Signing a message
Next, we’ll sign a plaintext message with the wallet using the signMessage method.
Make sure to specify your wallet ID (not address) from creation in the input.
try {
String message = "Hello, Privy!";
EthereumPersonalSignRpcResponseData response = privyClient
.wallets()
.ethereum()
.signMessage(
walletId,
message.getBytes(StandardCharsets.UTF_8),
AuthorizationContext.builder().build()
);
String signature = response.signature();
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
String message = "Hello, Privy!";
EthereumPersonalSignRpcResponseData response = privyClient
.wallets()
.solana()
.signMessage(
walletId,
message.getBytes(StandardCharsets.UTF_8),
AuthorizationContext.builder().build()
);
String signature = response.signature();
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
3. Sending transactions
Your wallet must have some funds in order to send a transaction. You can use a testnet
faucet to test transacting on a testnet (e.g. Base Sepolia)
or send funds to the wallet on the network of your choice.
To send a transaction from your wallet, use the sendTransaction method.
It will populate missing network-related values (gas limit, gas fee values, nonce, type), sign your
transaction, broadcast it to the network, and return the transaction hash to you.
In the request, make sure to specify your wallet id from your wallet creation above, as well as
the caip2 chain ID and chainId values for the network you want to transact on.
Also, input your recipient or smart contract address in the to field.
try {
String caip2 = "eip155:11155111"; // Sepolia testnet
UnsignedStandardEthereumTransaction txn = UnsignedStandardEthereumTransaction.builder()
.to(recipientAddress)
.value(Quantity.of("0x1")) // 1 wei
.chainId(Quantity.of(11_155_111)) // Sepolia testnet
.build();
EthereumSendTransactionRpcResponseData response = privyClient
.wallets()
.ethereum()
.sendTransaction(
senderWalletId,
caip2,
txn,
AuthorizationContext.builder().build()
);
String transactionHash = response.hash();
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
try {
String caip2 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"; // Solana Mainnet
// A base64 encoded serialized transaction to sign
String transaction = "insert-base-64-encoded-serialized-transaction";
SolanaSignAndSendTransactionRpcResponseData response = privyClient.wallets().solana()
.signAndSendTransaction(
senderWalletId,
caip2,
transaction,
AuthorizationContext.builder().build()
);
String transactionHash = response.hash();
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
If you’re interested in more control, you can prepare and broadcast the transaction yourself, and
simply use eth_signTransaction (EVM) and
signTransaction (Solana) RPCs to sign the
transaction with a wallet.
4. Creating a user
To create a user for your application, you can use the create method, passing in
a UserCreateRequestBody object, which allows you to specify the linked accounts, custom metadata,
and wallets that should be associated with said user.
try {
// Linked accounts to be created for user
List<LinkedAccountInput> createUserLinkedAccounts = List.of(
LinkedAccountInput.customAuth(subjectId),
LinkedAccountInput.email(email)
);
// Build request body
UserCreateRequestBody requestBody = UserCreateRequestBody
.builder()
.linkedAccounts(createUserLinkedAccounts)
.build();
// Send request to create user
UserCreateResponse response = privyClient.users().create(requestBody);
if (response.user().isPresent()) {
User user = response.user().get();
String userId = user.id();
}
} catch (APIException e) {
String errorBody = e.bodyAsString();
System.err.println(errorBody);
} catch (Exception e) {
System.err.println(e.getMessage());
}
Next steps & advanced topics
- For an additional layer of security, you can choose to sign your requests with authorization keys.
- To restrict what wallets can do, you can set up policies.
- To prevent double sending the same transaction, take a look at our support for idempotency keys.
- If you want to require multiple parties to sign off before sending a transaction for a wallet, you can accomplish this through the use of quorum approvals.