Skip to content
Last updated

Counterfactual Wallets & Signing Accounts

Overview

PERS implements a counterfactual wallet system that provides users with blockchain addresses before their first transaction. The system automatically determines the best execution strategy for each transaction request.

How Counterfactual Wallets Work

Immediate Wallet Creation

  • Address Generation: Users receive a deterministic wallet address immediately upon account creation
  • Zero Cost: No blockchain fees required for initial wallet setup
  • Pre-Computed: Wallet address exists mathematically before being deployed on-chain
  • Receiving Tokens: Users can receive tokens to their address immediately
  • Multi-Chain Support: Same address calculation across different blockchain networks

Transaction Execution

When users make their first transaction, the system automatically determines whether to:

  • Execute immediately (for internal wallets)
  • Prepare for signing (for external wallets)
  • Provide setup guidance (when wallet configuration is needed)

Unified Transaction API

Single Endpoint Intelligence

The system provides a single transaction endpoint that automatically handles complexity:

Endpoint: POST /transactions

The API automatically handles the complexity of determining execution strategy and provides appropriate responses.

Response Types

The API returns a unified response structure that eliminates frontend complexity:

interface TransactionRequestResponseDTO {
  transaction: TransactionDTO;           // Always present
  signingData?: AnyTransactionData;     // Present when client signing required
  walletStatus: WalletSigningScenarioType; // Execution strategy indicator
  actionable?: ActionableWalletResponse;    // Guidance when setup needed
}

Signing Account Management

Signing Account Management

The system supports multiple signing account providers for flexible wallet integration.

Signing Account Status

  • ACTIVE: Account is ready for use with all required information
  • INACTIVE: Account is temporarily disabled but can be reactivated
  • REVOKED: Account is permanently disabled and cannot be used

Wallet Signing Scenarios

The system identifies different wallet states and provides appropriate responses:

  1. WALLET_AND_SIGNING_READY: Wallet exists with active signing capability
  2. WALLET_MISSING_SIGNING: Wallet exists but lacks signing account
  3. WALLET_NOT_FOUND: No wallet found for the user

Actionable User Guidance

When wallet setup is required, the system provides actionable information:

interface ActionableWalletResponse {
  message: string;                    // User-friendly guidance message
  actionUrl?: string;                 // URL for wallet setup/signup
  actionType: 'SIGN_UP' | 'LINK_WALLET' | 'CREATE_SIGNING_ACCOUNT' | 'NONE';
  priority: 'LOW' | 'MEDIUM' | 'HIGH';
  category: 'WALLET_CREATION' | 'WALLET_CONFIGURATION' | 'WALLET_READY';
}

## API Integration Patterns

### **Unified Transaction Creation**
Frontend applications use a single endpoint regardless of wallet type or execution strategy:

```typescript
// Single API call for all transaction types
const response = await fetch('/transactions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${userToken}`,
    'x-project-key': projectKey,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    transactionType: 'SPEND',
    recipient: { accountId: 'recipient-id', accountType: 'USER' },
    token: { tokenDbId: 'token-uuid' },
    amount: 100
  })
});

const result = await response.json();

Response Handling

Frontend handles different execution strategies based on the response:

// Intelligent response handling
if (result.walletStatus === 'WALLET_AND_SIGNING_READY') {
  // Transaction completed server-side
  showSuccess(result.transaction);
  
} else if (result.walletStatus === 'WALLET_MISSING_SIGNING' && result.signingData) {
  // Client signing required
  const signature = await userWallet.signTransaction(result.signingData);
  await submitSignedTransaction(result.transaction.id, signature);
  
} else if (result.actionable) {
  // Setup required - guide user
  showWalletSetupDialog(result.actionable);
}

Authentication

The API supports different authentication methods:

  • User Authentication: Authorization: Bearer {userToken}
  • Admin Authentication: Authorization: Bearer {adminToken}
  • Project Authentication: x-project-key: {projectKey}

Key Benefits

User Experience

  • Instant Participation: Users can start participating immediately
  • No Upfront Costs: Eliminates blockchain transaction fees for new users
  • Progressive Enhancement: Advanced features unlock as users engage more deeply

Cost Optimization

  • Reduced Gas Costs: Only active users incur deployment costs
  • Predictable Costs: Clear cost structure for wallet deployment and transactions

Technical Implementation

Backend Architecture

The backend automatically handles wallet capability detection and execution strategy routing.

Smart Contract Architecture

  • Deterministic Address Generation: Consistent address calculation using factory contracts
  • Multi-Chain Compatibility: Same address calculation across different blockchain networks
  • Counterfactual Deployment: Wallets deployed only when first outgoing transaction occurs

API Endpoints

Core Transaction Endpoints

Create Transaction (Unified)

HTTP Request

POST /transactions
Authorization: Bearer {token}
X-Project-Key: {projectKey}
Content-Type: application/json

Request Body:

{
  "transactionType": "SPEND",
  "recipient": {
    "accountId": "user_123",
    "accountType": "USER"
  },
  "token": {
    "tokenDbId": "token_456",
    "chainId": 1
  },
  "amount": 100
}

Response Example:

{
  "transaction": {
    "id": "txn_123",
    "status": "PENDING",
    "amount": "100",
    "tokenId": "token_456"
  },
  "walletStatus": "WALLET_AND_SIGNING_READY",
  "signingData": null
}

Submit Signed Transaction

HTTP Request

POST /transactions/{transactionId}/submit
Authorization: Bearer {userToken}
X-Project-Key: {projectKey}
Content-Type: application/json

Request Body:

{
  type: "EIP_712" | "LEGACY" | "EIP_1559",
  signature?: string,           // For EIP-712
  signedTransaction?: string    // For other formats
}

Authentication Endpoints

User Authentication

HTTP Request

POST /auth/token
X-Project-Key: {projectKey}
Content-Type: application/json

Request Body:

{
  authToken: string  // Token from external provider (DFNS, etc.)
}

Integration Checklist

  • Implement unified /transactions endpoint for all transaction types
  • Handle both immediate execution and signing preparation responses
  • Implement actionable error handling for setup scenarios
  • Use proper authentication headers
  • Add transaction status tracking

Getting Started

  1. Authentication Setup: Implement user authentication using /auth/token endpoint
  2. Transaction Integration: Use unified /transactions endpoint for all transaction types
  3. Response Handling: Implement intelligent response handling for different execution strategies
  4. Error Management: Handle actionable responses for wallet setup scenarios
  5. Testing: Validate all scenarios including server execution, client signing, and setup flows

For detailed implementation assistance, contact our integration team or refer to the complete API documentation.