Fee splitting & events

Understand how ZynPay automatically splits payments between merchants and the platform, and how to listen for payment events.

Automatic Fee Splitting

Every payment processed through ZynPay's router automatically splits funds in a single atomic transaction:

Customer pays100 USDC
↓ Router splits automatically ↓
Merchant receives97 USDC (97%)
ZynPay fee3 USDC (3%)
1

Understanding the fee structure

The default fee is 3% of each payment. This fee is automatically deducted and sent to ZynPay's platform wallet, while the remaining 97% goes to your merchant wallet.

typescript
// When a customer pays 100 USDC:
const payment = client.createPayment(100, 'base')

// After payment is processed:
// - Merchant wallet receives: 97 USDC
// - ZynPay platform wallet receives: 3 USDC
// - All in a single atomic transaction
2

Listening for payment events

You can listen for payment events on-chain to automatically update your system when payments are completed.

typescript
import { ZynPayClient, Environment } from '@zyntrialabs/zynpay-sdk'
import { JsonRpcProvider } from 'ethers'

const client = new ZynPayClient({
  merchantWallet: process.env.MERCHANT_WALLET_ADDRESS!,
  environment: Environment.TESTNET,
  defaultChain: 'base',
})

// Listen for PaymentCompleted events
const provider = new JsonRpcProvider('https://sepolia.base.org')
const routerAddress = '0x73a499e043b03fc84ca62b99f58103436c52221a'

// Event signature: PaymentCompleted(address indexed merchant, uint256 amount, bytes32 paymentId)
const filter = {
  address: routerAddress,
  topics: [
    '0x...', // PaymentCompleted event signature
    null, // merchant address (any)
  ],
}

provider.on(filter, async (log) => {
  // Parse the event
  const event = parsePaymentEvent(log)
  
  console.log('Payment completed:', {
    merchant: event.merchant,
    amount: event.amount,
    paymentId: event.paymentId,
  })
  
  // Update your database
  await db.payments.update({
    where: { paymentId: event.paymentId },
    data: {
      status: 'completed',
      txHash: log.transactionHash,
      completedAt: new Date(),
    },
  })
  
  // Unlock access or fulfill order
  await fulfillOrder(event.paymentId)
})
3

Querying payment status

You can query the payment status at any time using the payment ID or transaction hash.

typescript
// Get payment by ID
const payment = await client.getPayment(paymentId)

if (payment.status === 'completed') {
  console.log('Payment confirmed:', {
    amount: payment.amount,
    merchant: payment.merchantAddress,
    txHash: payment.txHash,
    metadata: payment.metadata,
  })
}

// Or verify by transaction hash
const provider = new JsonRpcProvider('https://sepolia.base.org')
const receipt = await provider.getTransactionReceipt(txHash)

if (receipt && receipt.status === 1) {
  // Transaction confirmed
  // Parse events from receipt to get payment details
  const events = parseReceiptEvents(receipt)
  console.log('Payment events:', events)
}

Future: Custom Fee Splits

In the future, merchants will be able to define custom splits for collaborators and affiliates. For example:

  • Split revenue with content creators (e.g., 70% merchant, 20% creator, 10% platform)
  • Affiliate commissions (e.g., 5% to referrer)
  • Multi-party revenue sharing

All splits will still happen in a single atomic transaction for maximum security and efficiency.