Palindrome Crypto Pay - Blockchain Escrow Payment Solution

Signatures (EIP-712)

signWalletAuthorization

async signWalletAuthorization(
  walletClient: WalletClient,
  walletAddress: Address,
  escrowId: bigint,
  outcome: PayoutOutcome
): Promise<Hex>

Signs an EIP-712 typed message authorizing a participant (buyer, seller, or arbiter) for the escrow's 2-of-3 multisig wallet. Since Multisig v2, authorizations are outcome-bound: a signature consents to exactly one terminal escrow state (COMPLETE, REFUNDED, or CANCELED), so a signature collected for one outcome can never be replayed to authorize a different one.

Parameters

  • walletClient: WalletClient – The participant's connected wallet
  • walletAddress: Address – The escrow's dedicated wallet address
  • escrowId: bigint – The escrow ID
  • outcome: PayoutOutcome – The terminal state this signature consents to: EscrowState.COMPLETE (3), EscrowState.REFUNDED (4), or EscrowState.CANCELED (5)

Returns

Promise<Hex> – 65-byte EIP-712 signature

import { connectAndInitSDK } from '@/lib/createSDK';
import { EscrowState } from '@palindromepay/sdk';

const { sdk, walletClient } = await connectAndInitSDK();

// Get escrow to find wallet address
const escrow = await sdk.getEscrowByIdParsed(42n);

try {
  const signature = await sdk.signWalletAuthorization(
    walletClient,
    escrow.wallet,
    42n,
    EscrowState.COMPLETE
  );

  console.log("Payout authorization signature:", signature);
  // 0x1234...abcd (130 hex chars + 0x prefix = 132 total)

} catch (error: any) {
  console.error("Signing failed:", error.message);
}

Signature Structure (EIP-712)

// Domain
{
  name: "PalindromePayWallet",
  version: "1",
  chainId: 84532,  // chain-dependent: 8453 Base mainnet, 84532 Base Sepolia
  verifyingContract: walletAddress
}

// Types
{
  PayoutAuthorization: [
    { name: "escrowId", type: "uint256" },
    { name: "wallet", type: "address" },
    { name: "escrowContract", type: "address" },
    { name: "participant", type: "address" },
    { name: "outcome", type: "uint8" }
  ]
}

// Message
{
  escrowId: 42n,
  wallet: "0xEscrowWallet...",
  escrowContract: "0xEscrowContract...",
  participant: "0xYourAddress...",
  outcome: 3 // COMPLETE
}

When It's Used

This signature is automatically generated by other SDK methods:

MethodWho SignsOutcome
createEscrow()SellerCOMPLETE (3)
createEscrowAndDeposit()BuyerCOMPLETE (3)
deposit()BuyerCOMPLETE (3)
acceptEscrow()SellerCOMPLETE (3)
confirmDelivery()BuyerCOMPLETE (3)
requestCancel()Buyer or SellerCANCELED (5)
submitArbiterDecision()ArbiterThe arbiter's ruling (3 or 4)
refundAfterDisputeTimeout()BuyerREFUNDED (4)

Manual Usage

You typically don't need to call this directly — the SDK handles it. But for custom flows:

import { EscrowState } from '@palindromepay/sdk';

// Predict wallet before escrow exists
const nextId = await sdk.getNextEscrowId();
const predictedWallet = await sdk.predictWalletAddress(nextId);

// Pre-sign authorization for the COMPLETE outcome
const sig = await sdk.signWalletAuthorization(
  walletClient,
  predictedWallet,
  nextId,
  EscrowState.COMPLETE
);

// Use in custom contract call
await contract.write.customFunction([escrowId, sig]);

See alsopredictWalletAddress() · deposit() · Enums & Types

Previous
predictWalletAddress