Changelog
All notable changes to the PAY.ID ecosystem across packages, contracts, and frontend.
May 2026
✨ New Features
1. V4 Dashboard Redesign (Inspired)
The entire V4 app UI has been redesigned with a clean, card-based layout inspired by modern fintech apps (concept). Changes span across 5 components:
-
Dashboard (
frontend/example-product/src/components/v4/Dashboard.tsx)- Stealth Balance Card — gradient green (
#00D084) with prominent USD display, QR button - Token List — ETH, USDC, PDT with individual balance items
- Demo Token Banner — green info card: "We've sent you this to experience how seamless PAY.ID withdrawals are"
- Your Personal Link — PayID card with avatar, copy/QR/share actions
- Quick Actions — Send, Receive, History with rounded-2xl icon buttons
- Activity Feed — tab filters (All / Incoming / Outgoing), Export CSV button, avatar per transaction
- Stealth Balance Card — gradient green (
-
ReceivePage (
frontend/example-product/src/components/v4/ReceivePage.tsx)- QR Card — gradient green with centered QR code
- PayID Card — copyable link with avatar and action buttons
- Wallet Address — expandable section with ChevronRight
-
HistoryPage (
frontend/example-product/src/components/v4/HistoryPage.tsx)- Summary Cards — gradient red (Sent) & green (Received) with rounded-[20px]
- Search Bar — input with Search icon
- Tab Filters — All / Incoming / Outgoing
- Transaction List — Avatar + detail + status badge + amount
-
SettingsPage (
frontend/example-product/src/components/v4/SettingsPage.tsx)- Profile Card — gradient green with avatar besar dan PayID
- Theme Toggle — modern switch
- Settings List — color-coded icons (blue, yellow, green, purple)
- Disconnect — red card with warning style
-
AppLayout (
frontend/example-product/src/components/v4/AppLayout.tsx)- Logo — "pay.id" dengan BETA badge
- Nav Items — rounded-xl active state, clean spacing
- Bottom CTA — "PAY.ID is currently in beta" dengan avatar stack
- Links — Docs, X (Twitter)
2. VRAN — Vindex Reputation & Anti-Scam Network
A new decentralized trust layer for PAY.ID and other Web3 protocols.
-
packages/contracts/contracts/VindexRegistry.sol- Reputation scores (0–1000, default 500)
- Staked reporting with evidence hash (IPFS/Arweave CID)
- Web of Trust consensus — reports valid after ≥3 high-reputation (≥700) confirmations
- Auto-blacklist when reputation drops below 100
- Slash false reporters — stake returned to victim, reputation penalty
- Role-based access:
DEFAULT_ADMIN_ROLE,ENGINE_ROLE,SENTINEL_ROLE
-
packages/payid-react/src/hooks/useReputation.tsuseReputation({ registryAddress, target })→{ score, isBlacklisted, isTrusted }useCanReport({ registryAddress })→ check if wallet can submit reportuseVranConfig({ registryAddress })→ readminStakeandconsensusThreshold
3. QRIS / Bank Bridge Extension v1.1
The fiat integration spec has been expanded from a brief memo to a full implementation guide.
- Extended Context Schema —
FiatContextwithrail,psp,mcc,terminalId,currency - 6 new rule examples — min amount, PSP allowlist, currency restriction, MCC blocklist, QRIS-only, combined policy
- PSP Adapter Pattern —
FiatAdapterclass reference implementation - Bank Verification Endpoint —
verifyPaymentProof()reference code - Failure Semantics table — fail-closed for all edge cases
- Regulatory Alignment — AML/KYC complementarity, data privacy, licensing
- 5-Phase Roadmap — QRIS MVP → Multi-PSP → VRAN → SWIFT/SEPA → CBDC
4. 0G Resolver Hardening
The 0G storage resolver is now configurable via SDK instead of relying solely on a global variable.
ResolverOptionstype —{ zgIndexerUrl?: string }resolveRule(source, options?)accepts optionalResolverOptions- URL priority:
options.zgIndexerUrl→globalThis.PAYID_ZGS_INDEXER_URL→ defaulthttps://indexer-testnet.0g.ai PayIDClientandPayIDServerconstructors acceptresolverOptions- Factory functions updated:
createPayIDClient({ resolverOptions }),createPayIDServer({ resolverOptions }) ResolverOptionsexported frompayidpackage index
🐛 Bug Fixes
- Tailwind CSS lint warnings — Converted bracket opacity syntax (
bg-white/[0.03]) to new Tailwind v4 syntax (bg-white/3) across all V4 components - LandingPageV4 TypeScript error — Fixed
easetype infadeUp()transition (array →'easeOut' as const) - v3/AppLayout warning — Fixed
md:ml-[200px]→md:ml-50 - cursor-pointer — Added to all clickable items (buttons, cards, tabs) across V4 components
📁 Files Changed
frontend/example-product/src/components/v4/Dashboard.tsx
frontend/example-product/src/components/v4/ReceivePage.tsx
frontend/example-product/src/components/v4/HistoryPage.tsx
frontend/example-product/src/components/v4/SettingsPage.tsx
frontend/example-product/src/components/v4/AppLayout.tsx
frontend/example-product/src/components/v4/SendFlow.tsx
frontend/example-product/src/components/v4/LandingPageV4.tsx
frontend/example-product/src/components/v4/theme.tsx
frontend/example-product/src/components/v3/AppLayout.tsx
packages/contracts/contracts/VindexRegistry.sol [NEW]
packages/payid-react/src/hooks/useReputation.ts [NEW]
docs/bank-qris-extension.md [UPDATED]
docs/reputation_system_draft.md [EXISTS]
packages/sdk-core/src/resolver/resolver.ts
packages/sdk-core/src/resolver/types.ts
packages/sdk-core/src/core/client/client.ts
packages/sdk-core/src/core/server/server.ts
packages/sdk-core/src/factory.ts
packages/sdk-core/src/index.ts
Additional May 2026 Updates
5. FiatAdapter SDK Implementation
packages/sdk-core/src/adapters/fiatAdapter.ts— Reference implementation for QRIS/PSP integration- Exports:
FiatAdapter,QRISPayload,FiatEvaluationResult - Methods:
evaluatePayment(),buildContext()
6. VRAN Hook Context Integration
useReputation({ target })— now readsvindexRegistryfromPayIDContextautomaticallyuseCanReport()— checks if connected wallet can submit staked reportsuseVranConfig()— readsminStakeandconsensusThreshold- All hooks exported from
payid-react
7. V4 Dashboard Reputation Card
frontend/example-product/src/components/v4/Dashboard.tsx- Displays live reputation score with color-coded badge (Trusted / Neutral / Blacklisted)
- Shows between Quick Actions and Activity Feed
8. Frontend Documentation
docs/integration/bank-qris-bridge.md— New doc page for Bank/QRIS Bridgedocs/integration/vran-reputation.md— New doc page for VRANdocs/changelog.md— This changelog pagedocs/intro.md— Updated with "What's New" section
Usage Examples
Using Custom 0G Indexer
import { createPayIDClient } from 'payid';
const client = createPayIDClient({
resolverOptions: {
zgIndexerUrl: 'https://my-custom-indexer.0g.ai',
},
});
Checking Reputation Before Payment (with Context)
import { useReputation } from 'payid-react';
function PayButton({ merchantAddress }: { merchantAddress: string }) {
// Automatically reads vindexRegistry from <PayIDProvider>
const { isBlacklisted, isTrusted, score } = useReputation({
target: merchantAddress as `0x${string}`,
});
if (isBlacklisted) return <button disabled>🚫 Merchant Blacklisted</button>;
if (!isTrusted) return <button disabled>⚠️ Low Reputation ({score})</button>;
return <button>Pay Now</button>;
}
Fiat Adapter for QRIS
import { FiatAdapter } from 'payid';
const adapter = new FiatAdapter();
const { allowed, proof, reason } = await adapter.evaluatePayment(
{
amount: '150000',
currency: 'IDR',
merchantId: 'MID123',
pspCode: 'BANK_ABC',
},
'https://rules.example.com/merchant-rules.json',
walletSigner,
{
verifyingContract: '0x...',
ruleAuthority: '0x...',
chainId: 31337,
},
);
SDK Enhancements (May 2026)
1. PayID Name Resolution API — Reverse Lookup
Resolve wallet addresses back to human-readable PayIDs.
import { reverseResolvePayID, batchReverseResolve } from 'payid';
// Single lookup
const result = await reverseResolvePayID('0x1234567890123456789012345678901234567890', {
registryUrl: 'https://registry.pay.id/v1',
});
console.log(result?.payId); // "alice.pay.id"
// Batch lookup (for contact lists / tx history)
const map = await batchReverseResolve(['0x1234...', '0xabcd...']);
2. Offline-First IndexedDB Cache
Rules, contacts, drafts, and history cached locally for offline use.
import { contactCache, draftCache, ruleCache, getCacheStats } from 'payid';
// Cache a contact
await contactCache.set({
payId: 'alice.pay.id',
address: '0x1234...',
name: 'Alice',
addedAt: Date.now(),
});
// Create offline draft (syncs when online)
await draftCache.set({
toPayId: 'bob.pay.id',
amount: '100',
asset: 'USDC',
status: 'draft',
createdAt: Date.now(),
updatedAt: Date.now(),
});
// Check cache stats
const stats = await getCacheStats();
console.log(`${stats.contacts} contacts, ${stats.drafts} drafts`);
3. SDK CLI Tool
Deploy rules and verify proofs from the command line.
# Deploy a rule JSON to IPFS + register on-chain
npx payid deploy-rule ./my-rule.json \
--authority 0xRuleAuthority \
--chain 31337 \
--key $PRIVATE_KEY \
--rpc http://127.0.0.1:8545 \
--output result.json
# Verify a Decision Proof by txHash
npx payid verify-proof 0xabc123... \
--verifier 0xPayIDVerifier \
--rpc http://127.0.0.1:8545 \
--signer 0xExpectedSigner
Frontend & Smart Contract Features (May 2026)
1. Multi-Currency Display
Toggle between USD / IDR / ETH in real-time on the Send Flow amount input.
import { useMultiCurrency } from './hooks/useMultiCurrency';
const { displayCurrency, convert, format, toggle } = useMultiCurrency();
// ≈ Rp 525.000.000 shown below amount input
2. Transaction Simulation Preview
Client-side simulation before signing: checks balance, fees, and rules.
import TransactionSimulation from './components/v4/TransactionSimulation';
<TransactionSimulation
amount="0.05"
asset="ETH"
currentBalance="1.25"
onComplete={(result) => console.log(result.decision)}
/>;
3. Policy Marketplace UI
Browse and subscribe to rule templates: Freelancer Safe Pay, Parental Control, Business Hours, DAO Payroll, etc.
Route: /v4/app/marketplace
4. VRAN Reputation Badge
Dashboard shows reputation score with color-coded badges:
- Green (800+): Trusted
- Yellow (500-799): Neutral
- Red (
<500): Low reputation - Blacklisted: Warning banner before sending
5. Push Notifications
Web Push API integration with Service Worker for payment alerts.
const { subscribe, state, sendLocalNotification } = usePushNotifications();
6. Advanced Tools (Batch, Recurring, Escrow, Vesting)
Interactive UI for all new smart contract extensions.
Route: /v4/app/tools
Tabs:
- Batch Pay — Multi-recipient ETH/ERC20 payroll
- Recurring — Subscription creation with max amount & period
- Escrow — Milestone-based freelancer escrow
- Vesting — Time-locked token vesting with cliff
Smart Contract Extensions (May 2026)
1. Batch Payment (PayWithPayIDBatch.sol)
Execute multiple ETH or ERC20 payments in a single transaction.
function batchPayETH(
PayIDVerifier.Decision[] calldata decisions,
bytes[] calldata sigs,
bytes32[][] calldata attestationUIDs
) external payable
2. Recurring Payments (RecurringPayments.sol)
Subscription billing with pre-approved max amounts per period.
function createSubscription(
address receiver,
address asset,
uint256 maxAmount,
uint256 period
) external returns (uint256 subId)
function charge(uint256 subId, Decision, sig, attestationUIDs) external
3. Escrow with Milestones (EscrowMilestone.sol)
Freelancer escrow with VRAN arbiter confirmation for each milestone.
function createEscrow(
address freelancer,
address asset,
uint256[] calldata amounts,
string[] calldata descriptions,
uint256 deadline
) external payable
function releaseMilestone(uint256 escrowId, uint256 index) external onlyArbiter
4. Time-Locked Vesting (TimeLockVesting.sol)
Token vesting with cliff and linear release. Integrates with rule engine env.timestamp.
function createSchedule(
address beneficiary,
address asset,
uint256 totalAmount,
uint256 startTime,
uint256 cliff,
uint256 duration,
bool revocable,
address revoker
) external payable
function release(uint256 scheduleId) external
Off-Chain Keeper / Cron (May 2026)
Schedules need an off-chain trigger because blockchains do not run cron natively.
Script: packages/contracts/scripts/keeper.ts
What it does
- Recurring — scans subscriptions; calls
charge()whennextChargeTime <= now - Vesting — scans schedules; calls
release()whenreleasable > 0 - Escrow — scans escrows; calls
autoRefund()whendeadline <= now
Run locally
cd packages/contracts
PRIVATE_KEY=0x... RPC_URL=http://127.0.0.1:8545 \
bun run keeper --chainId 31337
Options
--dry-run— scan only, no transactions--once— single pass, then exit- default — loops every 60 seconds
Production deployment
For production, deploy this script as:
- Gelato Relay / Web3 Functions
- Chainlink Automation (upkeep)
- AWS Lambda + EventBridge (cron)
- Self-hosted Bun service with systemd / PM2