Prepare Transaction Claim
The prepareTx
claim is a powerful feature for scenarios where an application needs a user to submit a transaction but wants to delegate the construction of the transaction's inputs to the user's wallet. This is common in payment flows, asset acquisitions, or any interaction that requires the user to provide tokens or assets.
Instead of the application pre-defining all transaction details, it constructs a partial transaction, typically specifying only the desired outputs (e.g., "pay 10 ABC tokens to the application"). It then defines a requirement
object that tells the wallet what resources are needed to complete the transaction. The wallet then automatically selects the necessary inputs from the user's account, signs the completed transaction, and returns it to the application for broadcasting.
This approach provides flexibility and enhances user experience, as the wallet can intelligently manage the user's assets (like UTXOs) to fulfill the request.
How It Works#
Here is the typical sequence for a prepareTx
claim:
Claim Parameters#
The prepareTx
claim object is configured with the following parameters:
Parameter | Type | Description |
---|---|---|
|
| Must be |
|
| A user-friendly message displayed in the wallet, e.g., "Prepare and sign this transaction to continue." |
|
| The Base58-encoded, partially constructed transaction. It usually contains the outputs but no inputs. |
|
| An object specifying the tokens and/or assets the user's wallet must provide as inputs to complete the transaction. |
|
| (Optional) A JSON string for rendering rich content within the wallet interface. |
|
| (Optional) A random string to prevent replay attacks. |
|
| (Optional) Specifies the blockchain where the transaction will occur. If not provided, the default |
|
| (Optional) Any additional metadata you wish to associate with the claim. This data is returned in the response. |
The requirement
Object#
The requirement
object is central to the prepareTx
claim. It tells the wallet exactly what resources are needed.
Field | Type | Description |
---|---|---|
|
| An array of token objects required. Each object has an |
|
| (Optional) An object specifying on-chain assets (like NFTs) required. You can filter by |
Example 1: Requiring Tokens#
Here’s how to implement a prepareTx
flow that asks the user to send a specific amount of two different tokens to the application's wallet.
Step 1: Requesting the Claim#
First, you define the prepareTx
claim in your DID Connect handler. The partialTx
defines the outputs (where the tokens should go), and the requirement
specifies the total amount the user needs to provide.
// Source: ocap-playground/api/routes/auth/prepare.js
const { fromTokenToUnit } = require('@ocap/util');
// ... inside your WalletHandlers configuration
claims: {
prepareTx: async ({ userPk, userDid }) => {
const token = await getTokenInfo(); // Helper to get token decimals
const amountPrimary = 11.1;
const amountForeign = 22.2;
const valuePrimary = fromTokenToUnit(amountPrimary, token.local.decimal).toString();
const valueForeign = fromTokenToUnit(amountForeign, token.foreign.decimal).toString();
const requiredTokens = [
{ address: env.localTokenId, value: valuePrimary },
{ address: env.foreignTokenId, value: valueForeign },
];
return {
type: 'TransferV3Tx', // This will be encoded into partialTx
description: 'Complete this transaction using tokens from your wallet.',
// The partialTx defines the outputs. Inputs are left empty for the wallet to fill.
partialTx: {
itx: {
inputs: [], // Wallet will populate this
outputs: [
{
owner: wallet.address, // The application's wallet address
tokens: requiredTokens,
},
],
},
},
// The requirement tells the wallet what it needs to find and add as inputs.
requirement: {
tokens: requiredTokens,
},
};
},
},
In this setup, WalletAuthenticator
's internal prepareTx
method will automatically encode the partialTx
object into a Base58 string before sending it to the wallet.
Step 2: Handling the Wallet Response#
After the user approves and signs the transaction in their wallet, the onAuth
callback on your server receives the completed transaction in the claims
array. Your application is then responsible for broadcasting it.
// Source: ocap-playground/api/routes/auth/prepare.js
// ... inside your WalletHandlers configuration
onAuth: async ({ req, userDid, claims }) => {
const prepareTxClaim = claims.find(c => c.type === 'prepareTx');
if (!prepareTxClaim || !prepareTxClaim.finalTx) {
throw new Error('Transaction was not completed by the wallet.');
}
// The finalTx is the complete, signed transaction returned by the wallet
const tx = client.decodeTx(prepareTxClaim.finalTx);
// Broadcast the transaction to the blockchain
const hash = await client.sendTransferV3Tx({ tx, wallet: fromAddress(userDid) });
console.log('Transaction broadcasted successfully:', hash);
return { hash, tx: prepareTxClaim.finalTx };
},
Example 2: Requiring Tokens and Assets#
You can also require the user to provide on-chain assets (like NFTs) in addition to tokens. This is useful for scenarios like crafting, where a user combines several NFTs to create a new one.
// Source: ocap-playground/api/routes/auth/prepare.js
claims: {
prepareTx: async ({ userPk, userDid, input }) => {
// ... logic to get factory state and pre-mint asset details ...
const { state } = await client.getFactoryState({ address: factories.tokenInputTest });
return {
type: 'AcquireAssetV3Tx',
description: 'Acquire an asset by providing tokens and other assets.',
partialTx: {
// ... partial transaction details ...
},
requirement: {
tokens: [
{ address: env.localTokenId, value: state.input.value }
],
assets: {
// Require 2 assets that have one of these DIDs as their parent
parent: [
'z3CtMVWsnBAMmU941LGo5eRokLxfAcNZ3p2p1',
'z3Ct6eubBZzbK1pETFkVn9DBkE6f9MbBwTPNe',
],
amount: 2,
},
},
};
},
},
In this example, the requirement.assets
object instructs the wallet to find and include 2 assets from the user's account that descend from the specified parent DIDs. The wallet will handle the selection of these assets as inputs for the final transaction.
This completes the flow. The application has successfully requested and processed a complex transaction without needing to know about the user's specific unspent transaction outputs (UTXOs), making the process much smoother.