Skip to main content

Contract Events

All events emitted by Aruvi contracts. Use these for indexing, notifications, and tracking.

Querying Events

Using viem

import { createPublicClient, http, parseAbiItem } from 'viem';
import { sepolia } from 'viem/chains';

const client = createPublicClient({
chain: sepolia,
transport: http(),
});

// Get past events
const logs = await client.getLogs({
address: PAYMENT_GATEWAY,
event: parseAbiItem('event PaymentSent(uint256 indexed paymentId, address indexed from, address indexed to)'),
fromBlock: 1000000n,
toBlock: 'latest',
args: {
to: userAddress, // Filter to specific recipient
},
});

Using ethers

const filter = gateway.filters.PaymentSent(null, null, userAddress);
const events = await gateway.queryFilter(filter, -10000);

Watching Real-time

client.watchContractEvent({
address: PAYMENT_GATEWAY,
abi: gatewayAbi,
eventName: 'PaymentSent',
onLogs: (logs) => {
console.log('New payment:', logs);
},
});

PaymentGateway Events

PaymentSent

Emitted when a confidential payment is made.

event PaymentSent(
uint256 indexed paymentId,
address indexed from,
address indexed to
);
ParameterIndexedDescription
paymentIdUnique payment identifier
fromSender address
toRecipient address

Use cases:

  • Track incoming payments
  • Build transaction history
  • Trigger notifications

Note: Amount is NOT included — it's confidential.


PaymentRequestCreated

Emitted when someone requests a payment.

event PaymentRequestCreated(
uint256 indexed requestId,
address indexed from,
address indexed to
);
ParameterIndexedDescription
requestIdRequest identifier
fromRequested payer
toRequester (recipient)

PaymentRequestFulfilled

Emitted when a request is paid.

event PaymentRequestFulfilled(
uint256 indexed requestId
);

PaymentRequestCancelled

Emitted when a request is cancelled.

event PaymentRequestCancelled(
uint256 indexed requestId
);

SubscriptionCreated

Emitted when a new subscription starts.

event SubscriptionCreated(
uint256 indexed subscriptionId,
address indexed payer,
address indexed recipient,
uint256 interval
);
ParameterIndexedDescription
subscriptionIdSubscription identifier
payerWho pays
recipientWho receives
intervalSeconds between payments

SubscriptionExecuted

Emitted each time a subscription payment is made.

event SubscriptionExecuted(
uint256 indexed subscriptionId,
uint256 executionCount
);
ParameterIndexedDescription
subscriptionIdWhich subscription
executionCountHow many times executed total

SubscriptionCancelled

Emitted when subscription is cancelled.

event SubscriptionCancelled(
uint256 indexed subscriptionId
);

ConfidentialUSDCWrapper Events

Wrapped

Emitted when USDC is wrapped into confidential tokens.

event Wrapped(
address indexed account,
uint256 amount
);
ParameterIndexedDescription
accountUser who wrapped
amountUSDC amount wrapped

Note: Wrap amount IS visible (it's the input before encryption).


Unwrapped

Emitted when confidential tokens are unwrapped.

event Unwrapped(
address indexed account,
uint256 amount
);
ParameterIndexedDescription
accountUser who unwrapped
amountUSDC amount received

ConfidentialTransfer

Emitted on encrypted token transfer.

event ConfidentialTransfer(
address indexed from,
address indexed to
);
ParameterIndexedDescription
fromSender
toRecipient

Note: No amount — it's encrypted!


RefundManager Events

RefundRequested

Emitted when refund is requested.

event RefundRequested(
uint256 indexed refundId,
uint256 indexed paymentId,
address indexed requester
);

RefundApproved

Emitted when refund is approved.

event RefundApproved(
uint256 indexed refundId
);

RefundDeclined

Emitted when refund is declined.

event RefundDeclined(
uint256 indexed refundId
);

Event Indexing Strategies

Full Indexer

For complete history, index all events:

const eventTypes = [
'PaymentSent',
'SubscriptionCreated',
'SubscriptionExecuted',
'Wrapped',
'Unwrapped',
];

for (const eventName of eventTypes) {
const logs = await client.getLogs({
address: contractAddress,
event: abiEvents[eventName],
fromBlock: deploymentBlock,
toBlock: 'latest',
});

for (const log of logs) {
await database.insert({
event: eventName,
...log.args,
blockNumber: log.blockNumber,
transactionHash: log.transactionHash,
});
}
}

User-Specific

For one user's activity:

async function getUserActivity(userAddress: string) {
const [sent, received, subscriptions] = await Promise.all([
// Payments sent
client.getLogs({
event: PaymentSentEvent,
args: { from: userAddress },
}),
// Payments received
client.getLogs({
event: PaymentSentEvent,
args: { to: userAddress },
}),
// Subscriptions
client.getLogs({
event: SubscriptionCreatedEvent,
args: { payer: userAddress },
}),
]);

return { sent, received, subscriptions };
}

Block Range Limits

Some RPC providers limit query size. Chunk your queries:

const CHUNK_SIZE = 900n; // Stay under 1000 block limit

async function queryInChunks(fromBlock: bigint, toBlock: bigint) {
const allLogs = [];

for (let start = fromBlock; start <= toBlock; start += CHUNK_SIZE) {
const end = start + CHUNK_SIZE - 1n > toBlock
? toBlock
: start + CHUNK_SIZE - 1n;

const logs = await client.getLogs({
fromBlock: start,
toBlock: end,
// ... other params
});

allLogs.push(...logs);
}

return allLogs;
}

Building a Notification System

// Watch for payments to your address
client.watchContractEvent({
address: PAYMENT_GATEWAY,
abi: gatewayAbi,
eventName: 'PaymentSent',
args: { to: MY_ADDRESS },
onLogs: async (logs) => {
for (const log of logs) {
await sendNotification({
title: 'Payment Received',
body: `From ${truncateAddress(log.args.from)}`,
});
}
},
});

// Watch for subscription executions
client.watchContractEvent({
address: PAYMENT_GATEWAY,
abi: gatewayAbi,
eventName: 'SubscriptionExecuted',
onLogs: async (logs) => {
for (const log of logs) {
const sub = await gateway.getSubscription(log.args.subscriptionId);
if (sub.recipient === MY_ADDRESS) {
await sendNotification({
title: 'Subscription Payment',
body: `Execution #${log.args.executionCount}`,
});
}
}
},
});