PartyLayer Integration

PartyLayer is the Canton wallet abstraction SDK that Dualis Finance uses to connect users to the Canton Network. It handles wallet discovery, party identification, transaction signing, and balance queries without exposing low-level Canton gRPC or JSON API details.

What Is PartyLayer?

Canton operates on a party-based identity model rather than the address-based model common on EVM chains. Each participant on the network is identified by a party ID — a long opaque string tied to a specific Canton participant node. PartyLayer abstracts this complexity behind a familiar wallet-connection interface.

When a user connects their Canton wallet through PartyLayer, the SDK:

  • Discovers available Canton wallet providers in the browser
  • Prompts the user to select and authorize a wallet connection
  • Retrieves the user's party ID from the connected wallet
  • Signs DAML command submissions on behalf of the user
  • Queries Canton Coin (CC) balances via the Splice Scan external-party API
Wallet-Agnostic Design
Dualis Finance is wallet-agnostic. All DeFi operations (supply, borrow, repay, withdraw, add collateral) use PartyLayer signing payloads, meaning any Canton-compatible wallet can be used without code changes.

How It Works

The integration follows a three-step pattern for every Canton transaction:

  1. Prepare: The API server builds a DAML command payload (e.g., exercise the Supply choice on a LendingPool contract) and returns it to the frontend as a signing request.
  2. Sign: The frontend passes the payload to PartyLayer, which routes it to the connected wallet for user approval and cryptographic signing. The connected wallet's party is used as the actAs party in the signing payload.
  3. Submit: The signed command is submitted to the Canton participant node via the JSON API. The transaction settles atomically on the Canton ledger.

Integration Example

The following example shows how to connect a wallet and execute a supply operation using PartyLayer in a React component:

useCantonWallet.ts
import { usePartyLayer } from '@aspect/party-layer-react';
import { useCallback } from 'react';

export function useCantonWallet() {
  const {
    connect,
    disconnect,
    connected,
    partyId,
    signPayload,
    getBalance,
  } = usePartyLayer();

  const supply = useCallback(async (poolId: string, amount: string) => {
    if (!connected || !partyId) {
      throw new Error('Wallet not connected');
    }

    // 1. Request signing payload from API
    const res = await fetch('/api/v1/supply/prepare', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ poolId, amount, partyId }),
    });
    const { payload } = await res.json();

    // 2. Sign with connected wallet (actAs = connected party)
    const signed = await signPayload(payload);

    // 3. Submit signed command
    const submitRes = await fetch('/api/v1/supply/submit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ signed }),
    });

    return submitRes.json();
  }, [connected, partyId, signPayload]);

  return { connect, disconnect, connected, partyId, supply, getBalance };
}

Balance Queries

PartyLayer exposes Canton Coin (CC) balance queries through the Splice Scan external-party API. The SDK handles the authentication and request formatting:

BalanceDisplay.tsx
import { useCantonWallet } from '@/hooks/useCantonWallet';
import { useEffect, useState } from 'react';

export function BalanceDisplay() {
  const { connected, partyId, getBalance } = useCantonWallet();
  const [balance, setBalance] = useState<string | null>(null);

  useEffect(() => {
    if (connected && partyId) {
      getBalance(partyId).then(setBalance);
    }
  }, [connected, partyId, getBalance]);

  if (!connected) return <p>Connect your wallet to view balance.</p>;

  return <p>CC Balance: {balance ?? 'Loading...'}</p>;
}
Fallback Behavior
If the Splice Scan API is unreachable, the SDK falls back to querying the Canton participant's JSON API directly. This ensures balance display remains functional even during Scan API outages.

Devnet Configuration

On the Dualis devnet, the PartyLayer SDK connects to the Canton validator running at 84.32.223.16. The validator party ID is configured in the environment:

.env
NEXT_PUBLIC_CANTON_PARTICIPANT_URL=http://172.18.0.7:7575
NEXT_PUBLIC_PARTYLAYER_NETWORK=devnet

The participant container runs within the Docker network splice-validator_splice_validator. External access is routed through the host's Nginx reverse proxy.

Error Handling

Canton errors from DAML command submissions are mapped to user-friendly messages by the API's error mapper (packages/api/src/canton/error-mapper.ts). Common scenarios include insufficient balance, contract not found, and authorization failures. PartyLayer surfaces these as typed exceptions that the frontend can catch and display.

Resources