Skip to content

Ud identities#481

Merged
cwilvx merged 56 commits intotestnetfrom
ud_identities
Nov 24, 2025
Merged

Ud identities#481
cwilvx merged 56 commits intotestnetfrom
ud_identities

Conversation

@tcsenpai
Copy link
Contributor

@tcsenpai tcsenpai commented Oct 21, 2025

PR Type

Enhancement, Dependencies


Description

  • Implemented comprehensive multi-chain Unstoppable Domain (UD) identity verification system supporting EVM (Polygon, Base, Sonic, Ethereum L1) and Solana networks

  • Added UDIdentityManager class for cross-chain domain resolution with signature-based ownership verification using both ethers and nacl cryptography

  • Implemented SolanaDomainResolver with PDA derivation for resolving UD domains on Solana blockchain

  • Integrated UD domain points incentive system with configurable rewards (3 points for .demos TLD, 1 point for others)

  • Added complete Solana UNS program IDL type definitions and JSON configuration for UD operations

  • Extended GCR identity routines with applyUdIdentityAdd() and applyUdIdentityRemove() methods for domain linking/unlinking with validation

  • Created blockchain address signature type detection utility for EVM and Solana address format validation

  • Updated data models with SavedUdIdentity interface and udDomains tracking fields in GCR entity

  • Added UD identity request handling in transaction processing with verification workflow

  • Updated dependencies including @kynesyslabs/demosdk, Solana Web3.js, Anchor, tweetnacl, and Unstoppable Domains resolution library

  • Enhanced type safety in Uint8Array validation utility

  • Comprehensive documentation of UD integration phases, security patterns, and technical reference


Diagram Walkthrough

flowchart LR
  A["UD Domain Request"] --> B["UDIdentityManager"]
  B --> C["SolanaDomainResolver"]
  B --> D["EVM Resolution"]
  C --> E["PDA Derivation"]
  D --> F["Contract Queries"]
  E --> G["Signature Verification"]
  F --> G
  G --> H["GCRIdentityRoutines"]
  H --> I["Award/Deduct Points"]
  I --> J["Update GCR Entity"]
Loading

File Walkthrough

Relevant files
Dependencies
2 files
uns_sol.ts
Unstoppable Domains Solana Program IDL Type Definitions   

src/libs/blockchain/UDTypes/uns_sol.ts

  • Added comprehensive TypeScript type definitions for the Unstoppable
    Domains Solana program IDL
  • Includes 16 instruction definitions (addMinter, addRecord, mintSld,
    etc.) with account and argument specifications
  • Defines 5 account types (domainProperties, minter, programAuthority,
    record, tld) with discriminators
  • Includes 8 event types (domainMinted, recordAdded, recordRemoved,
    etc.) and 13 error codes with descriptions
+2403/-0
package.json
Update dependencies and scripts for UD integration             

package.json

  • Updated @kynesyslabs/demosdk from v2.3.22 to v2.4.24
  • Added Solana-related dependencies: @solana/web3.js, @coral-xyz/anchor,
    tweetnacl, bs58
  • Added UD resolution dependency: @unstoppabledomains/resolution
  • Added Metaplex dependency for NFT operations
  • Updated lint scripts to ignore local_tests and aptos_tests directories
  • Added type-check and type-check-ts scripts
+11/-3   
Enhancement
11 files
udSolanaResolverHelper.ts
Solana Domain Resolution Helper with PDA Derivation           

src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts

  • Implemented SolanaDomainResolver class for resolving Unstoppable
    Domains on Solana blockchain
  • Provides methods to resolve single records, multiple records, and
    check domain existence
  • Handles PDA derivation for SLD, domain properties, and record accounts
  • Includes comprehensive error handling with custom error classes
    (DomainNotFoundError, RecordNotFoundError, ConnectionError)
+675/-0 
udIdentityManager.ts
Multi-Chain Unstoppable Domain Identity Verification Manager

src/libs/blockchain/gcr/gcr_routines/udIdentityManager.ts

  • Implemented UDIdentityManager for multi-chain UD domain verification
    (EVM and Solana)
  • Supports domain resolution across Polygon, Base, Sonic, Ethereum L1,
    and Solana networks
  • Verifies signatures using both EVM (ethers) and Solana (nacl)
    cryptography
  • Extracts authorized addresses from domain records and validates
    ownership before identity assignment
+565/-0 
PointSystem.ts
Unstoppable Domain Points Incentive System Integration     

src/features/incentive/PointSystem.ts

  • Added udDomains field to UserPoints breakdown structure for tracking
    UD domain points
  • Implemented awardUdDomainPoints() method with domain ownership
    verification and duplicate prevention
  • Implemented deductUdDomainPoints() method for unlinking domains with
    point deduction
  • Added point values for UD domain linking (3 points for .demos, 1 point
    for other TLDs)
+264/-2 
GCRIdentityRoutines.ts
GCR Identity Routines for Unstoppable Domain Management   

src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts

  • Added applyUdIdentityAdd() method to handle UD domain identity linking
    with validation
  • Added applyUdIdentityRemove() method to handle UD domain identity
    unlinking
  • Extended isFirstConnection() method to support UD domain type checking
  • Integrated IncentiveManager hooks for awarding/deducting points on
    domain link/unlink events
+210/-1 
signatureDetector.ts
Blockchain Address Signature Type Detection Utility           

src/libs/blockchain/gcr/gcr_routines/signatureDetector.ts

  • Created utility module for detecting signature types from blockchain
    addresses
  • Implements pattern matching for EVM (0x-prefixed hex) and Solana
    (base58) address formats
  • Provides validation functions validateAddressType() and
    isSignableAddress()
  • Includes security guards against non-string inputs and regex attacks
+75/-0   
IdentityTypes.ts
Unstoppable Domain Identity Type Definitions                         

src/model/entities/types/IdentityTypes.ts

  • Added SavedUdIdentity interface for storing UD domain identity data in
    GCR
  • Includes fields for domain, signing address, signature type, and
    multi-chain metadata
  • Supports both EVM and Solana signature types with network and registry
    type tracking
  • Updated StoredIdentities type to include ud array field for UD
    identities
+27/-1   
IncentiveManager.ts
Incentive Manager Hooks for UD Domain Linking Events         

src/libs/blockchain/gcr/gcr_routines/IncentiveManager.ts

  • Added udDomainLinked() hook method to award points when UD domain is
    linked
  • Added udDomainUnlinked() hook method to deduct points when UD domain
    is unlinked
  • Updated class documentation to include UD domain support in incentive
    management
+26/-1   
handleIdentityRequest.ts
Add UD identity request handling with verification             

src/libs/network/routines/transactions/handleIdentityRequest.ts

  • Added import for UDIdentityAssignPayload from SDK abstraction
  • Added import for UDIdentityManager for UD domain verification
  • Added new case handler for ud_identity_assign that verifies UD domain
    payloads using signature-based verification
  • Added ud_identity_remove case to handle UD domain removal operations
+10/-0   
validateUint8Array.ts
Enhance type safety and validation in Uint8Array conversion

src/utilities/validateUint8Array.ts

  • Improved type safety with explicit Record type
    casting
  • Added validation to ensure all values are numbers before conversion
  • Enhanced code clarity with better variable naming and comments
  • Fixed quote style consistency (single to double quotes)
+14/-6   
GCR_Main.ts
Add UD domains and Telegram tracking to GCR entity             

src/model/entities/GCRv2/GCR_Main.ts

  • Added optional telegram field to socialAccounts for backward
    compatibility
  • Added optional udDomains field to track UD domain points per domain
  • Both fields marked as optional to maintain compatibility with
    historical records
+2/-0     
handleGCR.ts
Initialize UD identities array in GCR                                       

src/libs/blockchain/gcr/handleGCR.ts

  • Added ud: [] initialization to identities breakdown for new GCR
    accounts
  • Ensures UD domain identities array is properly initialized
+1/-0     
Formatting
2 files
server_rpc.ts
Fix formatting in server RPC response                                       

src/libs/network/server_rpc.ts

  • Added trailing comma to JSON response object for consistency
+1/-1     
PeerManager.ts
Simplify type inference in peer list loading                         

src/libs/peer/PeerManager.ts

  • Removed explicit type annotation from variable declaration, allowing
    TypeScript inference
+1/-1     
Configuration
2 files
uns_sol.json
Add Solana UNS program IDL for UD integration                       

src/libs/blockchain/UDTypes/uns_sol.json

  • Added complete Solana UNS program IDL (Interface Definition Language)
    with 2397 lines
  • Includes all instruction definitions, account types, events, and error
    codes
  • Defines program address and metadata for Solana UD domain operations
+2397/-0
.eslintrc.cjs
Allow uppercase constants in ESLint naming rules                 

.eslintrc.cjs

  • Updated ESLint naming convention rule to allow both camelCase and
    UPPER_CASE formats
  • Enables use of uppercase constants alongside camelCase variables
+1/-1     
Documentation
9 files
ud_phases_tracking.md
Document UD multi-chain integration phases tracking           

.serena/memories/ud_phases_tracking.md

  • Comprehensive tracking document for all 6 phases of UD multi-chain
    integration
  • Documents completed phases 1-5 with commits and implementation details
  • Includes UD points system implementation details
  • Outlines pending Phase 6 SDK client method updates
+466/-0 
ud_phase5_complete.md
Document Phase 5 UD identity types implementation               

.serena/memories/ud_phase5_complete.md

  • Detailed documentation of Phase 5 implementation (IdentityTypes
    updates)
  • Documents breaking changes to SavedUdIdentity interface
  • Explains field changes: resolvedAddresssigningAddress, added
    signatureType
  • Covers GCR storage structure and incentive system integration
+260/-0 
session_ud_ownership_verification_2025_10_21.md
Document UD ownership verification security session           

.serena/memories/session_ud_ownership_verification_2025_10_21.md

  • Session notes on UD domain ownership verification implementation
  • Documents security fix for deductUdDomainPoints with blockchain
    verification
  • Explains import path fix for UDIdentityManager
  • Details ownership verification pattern and vulnerability prevention
+138/-0 
ud_integration_complete.md
Document UD integration completion status                               

.serena/memories/ud_integration_complete.md

  • Status overview of UD multi-chain integration (Phases 1-6)
  • Documents completed points system implementation
  • Lists modified files and integration status
  • Outlines Phase 6 requirements for SDK updates
+143/-0 
ud_security_patterns.md
Document UD security patterns and verification                     

.serena/memories/ud_security_patterns.md

  • Defines ownership verification architecture and patterns
  • Documents security checkpoints for domain linking and unlinking
  • Explains multi-chain considerations and signature type handling
  • Outlines error handling patterns and attack prevention
+157/-0 
ud_architecture_patterns.md
Document UD architecture patterns and flows                           

.serena/memories/ud_architecture_patterns.md

  • Documents multi-chain resolution cascade flow (5-network fallback)
  • Defines UnifiedDomainResolution structure
  • Explains verification flow and multi-address authorization
  • Covers storage patterns, helper methods, and error messages
+146/-0 
session_ud_points_implementation_2025_01_31.md
Document UD points system implementation session                 

.serena/memories/session_ud_points_implementation_2025_01_31.md

  • Session documentation for UD domain points system implementation
  • Details point values: 3 for .demos TLD, 1 for others
  • Documents awardUdDomainPoints and deductUdDomainPoints methods
  • Covers type system updates and infrastructure changes
+103/-0 
ud_technical_reference.md
Document UD technical reference and configurations             

.serena/memories/ud_technical_reference.md

  • Technical reference for UD network configurations and contracts
  • Lists EVM network addresses and Solana program details
  • Documents record keys priority and signature detection patterns
  • Includes test data examples and environment variables
+65/-0   
_index.md
Add memory index for documentation navigation                       

.serena/memories/_index.md

  • Memory index for quick navigation of UD integration documentation
  • Organizes memories by domain (UD integration, project core,
    development)
  • Provides recommended reading order for different work contexts
+40/-0   

Summary by CodeRabbit

  • New Features

    • Unstoppable Domains multi‑chain support (EVM + Solana) with multi‑address authentication
    • On‑chain ownership verification for domain linking and unlinking
    • Automated point awards/deductions for UD domain linking (TLD‑based incentives, e.g. .demos higher)
    • Domain resolution API for client use (resolve web3 domains)
  • Documentation

    • Added UD architecture, security patterns, technical reference, phase tracking, and integration guides
    • Memory/index pages for UD workflows and implementation notes

✏️ Tip: You can customize this high-level summary in your review settings.

tcsenpai and others added 30 commits October 4, 2025 19:02
- Import UDIdentityAssignPayload and UDIdentityManager
- Add 'ud_identity_assign' case routing to UDIdentityManager.verifyPayload()
- Add 'ud_identity_remove' to identity removal cases
- Follows signature-based verification pattern like XM
- Create UDIdentityManager class following XM signature-based pattern
- Implement resolveUDDomain() with UNS/CNS registry fallback
- Implement verifyPayload() with signature and ownership verification
- Add helper methods for getting UD identities
- Use ethers.js for free Ethereum contract reads
- Full error handling and logging
- Add SavedUdIdentity interface to IdentityTypes.ts
- Update StoredIdentities type to include ud: SavedUdIdentity[]
- Add ud: [] to default identities initialization in handleGCR.ts
- Update UDIdentityManager with proper type imports
- Database will auto-update via JSONB (no migration needed)
- Update SavedUdIdentity interface with network field
- Add Polygon L2 UNS registry: 0xa9a6A3626993D487d2Dbda3173cf58cA1a9D9e9f
- Rewrite resolveUDDomain() with 3-tier fallback strategy:
  1. Polygon L2 UNS (primary - most new domains, cheaper gas)
  2. Ethereum L1 UNS (legacy domains)
  3. Ethereum L1 CNS (oldest legacy domains)
- Add network verification in verifyPayload()
- Add logging for fallback chain attempts
- Per UD docs: check Polygon first for better UX
- Added Base L2 (0xF6c1b83977DE3dEffC476f5048A0a84d3375d498) registry support
- Added Sonic (0xDe1DAdcF11a7447C3D093e97FdbD513f488cE3b4) registry support
- Updated resolution strategy: Polygon → Base → Sonic → Ethereum UNS → Ethereum CNS
- Extended network type to include "base" and "sonic" in UD identity types
- Maintained backward compatibility with existing Polygon and Ethereum domains

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add signatureDetector utility for detecting signature types from
address formats, supporting multi-address UD identity verification.

Features:
- detectSignatureType(): Auto-detect EVM vs Solana from address format
- validateAddressType(): Validate address matches expected type
- isSignableAddress(): Check if address is in recognized format

Pattern matching:
- EVM: 0x-prefixed 40 hex characters (secp256k1)
- Solana: Base58-encoded 32-44 characters (ed25519)

Includes comprehensive test coverage in local_tests/.

Part of UD multi-chain identity refactor supporting multi-address
signing (users can sign with any address in domain records).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Extend EVM domain resolution to fetch ALL domain records, not just
owner address. This enables multi-address verification where users
can sign with any address in their domain records.

Changes:
- Updated resolveUDDomain() return type to EVMDomainResolution
- Added resolver ABI with get() method for record fetching
- Defined UD_RECORD_KEYS array (8 common crypto address records)
- Created fetchDomainRecords() helper for batch record retrieval
- Created extractSignableAddresses() helper with auto-detection
- Applied record fetching to all 5 networks:
  * Polygon L2 UNS
  * Base L2 UNS
  * Sonic UNS
  * Ethereum L1 UNS
  * Ethereum L1 CNS

Technical details:
- Resolver may differ from registry (fetched via resolverOf())
- Records include: crypto.ETH/SOL/BTC/MATIC.address, token.EVM/SOL.*
- Signature type auto-detected via signatureDetector utility
- Null/empty records handled gracefully

Next phase: Integrate Solana resolution with EVM fallback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…tion

Phase 3: Solana Resolution Integration
- Add Solana fallback after EVM cascade in resolveUDDomain()
- Migrate to UnifiedDomainResolution format (EVM + Solana)
- Add evmToUnified() and solanaToUnified() conversion helpers
- Support .demos domains via SolanaDomainResolver
- Return authorizedAddresses array from all domain records

Phase 4: Multi-Signature Verification
- Rewrite verifyPayload() for multi-address authorization
- Add verifySignature() helper supporting EVM + Solana
- Install tweetnacl & bs58 for Solana signature verification
- Users can now sign with ANY address in domain records
- Support mixed signature types (EVM + Solana in same domain)

Technical:
- EVM verification: ethers.verifyMessage()
- Solana verification: nacl.sign.detached.verify() with base58
- Enhanced error messages listing authorized addresses
- Detailed logging of signing address and signature type

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Breaking changes to SavedUdIdentity interface:
- resolvedAddress → signingAddress (address that signed challenge)
- Added signatureType field ("evm" | "solana")
- Added "solana" to network options

Updated GCRIdentityRoutines to handle new signature types and validate
multi-address verification. Users can now sign with ANY address from
their domain records, not just the owner address.

This phase completes the node-side changes for multi-chain UD support.
Phase 6 (SDK updates) is in progress in ../sdks repository.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Security Fixes:
1. Challenge validation: Replace unsafe substring matching with regex-based
   exact match validation to prevent public key spoofing attacks
2. Input validation: Add comprehensive validation for Solana domain resolution
   methods (label, tld, recordKeys) with early-return pattern
3. Type safety: Fix unsafe indexing in validateUint8Array with proper type
   narrowing and runtime validation
4. BigInt conversion: Validate recordVersion is non-negative integer before
   conversion to prevent TypeError

Code Quality Improvements:
1. Major refactoring: Extract duplicated EVM network resolution logic into
   reusable tryEvmNetwork() helper method, reducing code by 73 lines
2. Security documentation: Add comprehensive rationale for network/registry
   mismatch handling with clear threat model explanation
3. Error messages: Improve clarity and consistency across all validation errors
4. Performance: Early validation prevents unnecessary async operations

Changes:
- udIdentityManager.ts: 331 lines changed (129+, 202-)
  * Refactored 5 nested try/catch blocks into clean loop
  * Added tryEvmNetwork() helper method
  * Fixed challenge validation vulnerability
  * Added security documentation for mismatch handling
  * Updated all resolvedAddress → signingAddress references

- udSolanaResolverHelper.ts: 66 lines changed (53+, 13-)
  * Added input validation for resolveRecord() method
  * Added comprehensive validation for resolve() method
  * Added recordVersion validation before BigInt conversion
  * Handles empty recordKeys array correctly

- validateUint8Array.ts: 16 lines changed (11+, 5-)
  * Fixed unsafe indexing into unknown type
  * Added proper type narrowing with validation
  * Ensures all values are numbers before conversion

All changes are ESLint compliant and TypeScript safe.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive points system for Unstoppable Domains integration:
- Award 3 points for .demos TLD domains
- Award 1 point for other UD domains
- Implement awardUdDomainPoints() with duplicate detection and referral support
- Implement deductUdDomainPoints() with domain-specific point tracking
- Extend GCR entity breakdown with udDomains field
- Add telegram field to socialAccounts breakdown
- Update UserPoints interface to match GCR structure

Resolves missing UD points methods in IncentiveManager hooks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
SECURITY: Prevent point farming by normalizing all UD domain names to
lowercase before comparison, lookup, and storage. This ensures:
- Same domain with different cases (MyDomain.demos vs mydomain.demos)
  cannot be linked multiple times to farm points
- Domain lookups always work regardless of input case
- Behavior matches DNS standard (domains are case-insensitive)

Changes:
- awardUdDomainPoints(): Normalize domain at start, use normalizedDomain
  for TLD check, duplicate detection, and storage
- deductUdDomainPoints(): Normalize domain at start, use normalizedDomain
  for TLD check, lookup, and deduction

Fixes vulnerability identified in code review where case-variant domains
could bypass duplicate detection and allow unlimited point farming.
SECURITY VULNERABILITY FIX: Prevent authentication bypass via case manipulation

Issue: Previous code applied toLowerCase() to ALL addresses including Solana
addresses, which are case-sensitive (base58 encoding). This allowed attackers
to bypass authorization by changing the case of a valid Solana address.

Example Attack:
- Domain authorized for: 8VqZ8cqQ8h9FqF7cXNx5bXKqNz9V8F7h9FqF7cXNx5b
- Attacker uses:       8vqz8cqq8h9fqf7cxnx5bxkqnz9v8f7h9fqf7cxnx5b
- Previous code: ACCEPTED (case-insensitive match)
- Fixed code: REJECTED (case-sensitive for Solana)

Fix:
- Conditional address comparison based on signature type
- Solana addresses: Exact case-sensitive match (base58 standard)
- EVM addresses: Case-insensitive match (EVM standard)

Security Impact: HIGH - Closes critical authentication bypass vulnerability
Affected: All Solana UD domain verifications in production

Reviewer Concern #4
Issue: Function called regex.test() on address parameter without validating
it is a string, causing TypeError when called with null/undefined/non-string.

Fix:
- Add early type guard checking typeof address === 'string'
- Return null for non-string or empty inputs
- Trim whitespace before regex matching for consistency

Security Impact: Prevents runtime crashes from malformed inputs
Error Handling: Gracefully returns null instead of throwing TypeError

Reviewer Concern #2
Issue: evmToUnified() hardcoded registryType as 'UNS', mislabeling CNS
domains and losing registry type information from the resolver.

Fix:
- Update evmToUnified() signature to accept registryType parameter
- Pass registryType from tryEvmNetwork() to evmToUnified()
- Correctly label CNS domains as CNS instead of UNS

Data Integrity: Ensures accurate domain metadata
Client Impact: Enables correct filtering and display based on registry type

Reviewer Concern #5
Issue: New required fields (udDomains, telegram) break loading historical
JSONB records that don't have these fields, causing TypeORM/PostgreSQL
errors when loading existing user data.

Fix:
- Make udDomains optional: udDomains?: { [domain: string]: number }
- Make telegram optional: telegram?: number
- Ensures backward compatibility with pre-existing records
- All usage sites already handle undefined with safe access patterns

Database Impact: Prevents data loading failures in production
Migration: No migration needed - field addition is non-breaking

Reviewer Concerns #9 & #10
Issue: Only checked field presence, not valid values. Invalid enum values
or timestamps could cause downstream errors with unclear messages.

Fix:
- Validate signatureType is 'evm' or 'solana'
- Validate network is one of: polygon, base, sonic, ethereum, solana
- Validate registryType is 'UNS' or 'CNS'
- Validate timestamp is valid number or parseable date (>0)
- Provide clear, actionable error messages for each validation failure

Data Integrity: Prevents invalid data from entering system
Developer Experience: Clear error messages aid debugging
Error Prevention: Catches issues before database write

Reviewer Concern #1
@github-actions
Copy link

⚠️ MCP Memory Files Detected

This PR modifies .serena/ files. After merge, these changes will be automatically reverted to preserve branch-specific MCP memories.

Files that will be reverted:

  • .serena/memories/_index.md
  • .serena/memories/session_ud_ownership_verification_2025_10_21.md
  • .serena/memories/session_ud_points_implementation_2025_01_31.md
  • .serena/memories/ud_architecture_patterns.md
  • .serena/memories/ud_integration_complete.md
  • .serena/memories/ud_phase5_complete.md
  • .serena/memories/ud_phases_tracking.md
  • .serena/memories/ud_security_patterns.md
  • .serena/memories/ud_technical_reference.md

tcsenpai added 3 commits October 21, 2025 23:30
Add import for SavedUdIdentity type used in type annotation at line 936
to resolve TypeScript compilation error.
Update regex to accept optional 0x prefix in challenge message and
normalize both extracted value and sender before comparison by removing
0x prefix and lowercasing. This prevents validation failures when one
value has 0x prefix and the other doesn't.
Add early exit for arrays and typed arrays to prevent incorrect Buffer
conversion. Add validation that all keys are numeric integer strings
before treating input as Uint8Array-like object. This prevents data
corruption when regular arrays or TypedArrays are passed to the function.
@github-actions
Copy link

⚠️ MCP Memory Files Detected

This PR modifies .serena/ files. After merge, these changes will be automatically reverted to preserve branch-specific MCP memories.

Files that will be reverted:

  • .serena/memories/_index.md
  • .serena/memories/session_ud_ownership_verification_2025_10_21.md
  • .serena/memories/session_ud_points_implementation_2025_01_31.md
  • .serena/memories/ud_architecture_patterns.md
  • .serena/memories/ud_integration_complete.md
  • .serena/memories/ud_phase5_complete.md
  • .serena/memories/ud_phases_tracking.md
  • .serena/memories/ud_security_patterns.md
  • .serena/memories/ud_technical_reference.md

Remove local UserPoints interface duplication in PointSystem.ts
and import from @kynesyslabs/demosdk/abstraction instead.

The SDK interface is the source of truth and has proper optional
fields for telegram and udDomains, making it more flexible for
newer features.

This eliminates interface duplication and ensures consistency
with SDK type definitions.
@github-actions
Copy link

⚠️ MCP Memory Files Detected

This PR modifies .serena/ files. After merge, these changes will be automatically reverted to preserve branch-specific MCP memories.

Files that will be reverted:

  • .serena/memories/_index.md
  • .serena/memories/session_ud_ownership_verification_2025_10_21.md
  • .serena/memories/session_ud_points_implementation_2025_01_31.md
  • .serena/memories/ud_architecture_patterns.md
  • .serena/memories/ud_integration_complete.md
  • .serena/memories/ud_phase5_complete.md
  • .serena/memories/ud_phases_tracking.md
  • .serena/memories/ud_security_patterns.md
  • .serena/memories/ud_technical_reference.md

claude and others added 3 commits November 5, 2025 11:51
Fixed critical syntax error in the isFirstConnection method that was preventing
TypeScript compilation. The if-else chain was malformed with orphaned braces
and unreachable code.

Changes:
- Restructured the if-else chain to properly handle web2, ud, and web3 types
- Changed condition from `if (type !== "web3")` to `if (type !== "web3" && type !== "ud")`
- Removed orphaned closing braces and unreachable return statement
- Fixed indentation for the web3 (else) block

This resolves the following TypeScript errors:
- TS1068: Unexpected token
- TS1005: ',' expected
- TS1128: Declaration or statement expected

The UD identity integration will now function correctly with proper first-time
connection detection for incentive points.
…CUoJ58PE2u6TuoV6QTs8K

fix(gcr): fix syntax error in isFirstConnection function
@github-actions
Copy link

github-actions bot commented Nov 5, 2025

⚠️ MCP Memory Files Detected

This PR modifies .serena/ files. After merge, these changes will be automatically reverted to preserve branch-specific MCP memories.

Files that will be reverted:

  • .serena/memories/_index.md
  • .serena/memories/session_ud_ownership_verification_2025_10_21.md
  • .serena/memories/session_ud_points_implementation_2025_01_31.md
  • .serena/memories/ud_architecture_patterns.md
  • .serena/memories/ud_integration_complete.md
  • .serena/memories/ud_phase5_complete.md
  • .serena/memories/ud_phases_tracking.md
  • .serena/memories/ud_security_patterns.md
  • .serena/memories/ud_technical_reference.md

@tcsenpai tcsenpai mentioned this pull request Nov 5, 2025
@github-actions
Copy link

github-actions bot commented Nov 6, 2025

⚠️ MCP Memory Files Detected

This PR modifies .serena/ files. After merge, these changes will be automatically reverted to preserve branch-specific MCP memories.

Files that will be reverted:

  • .serena/memories/_index.md
  • .serena/memories/session_ud_ownership_verification_2025_10_21.md
  • .serena/memories/session_ud_points_implementation_2025_01_31.md
  • .serena/memories/ud_architecture_patterns.md
  • .serena/memories/ud_integration_complete.md
  • .serena/memories/ud_phase5_complete.md
  • .serena/memories/ud_phases_tracking.md
  • .serena/memories/ud_security_patterns.md
  • .serena/memories/ud_technical_reference.md

tcsenpai and others added 4 commits November 6, 2025 12:19
+ update udIdentityManager.ts to accept signatures from mint owner
+ add getTokenOwner on usSolanaResolverHelper.ts
+ update solana rpc url
+ add checkOwnerLinkedWallets method on udIdentityManager.ts
+ update awardUdDomainPoints to use the new method
+ check linkedWallets ownership on tx broadcast
+ return message to show whether points will be awarded
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (1)

600-616: Verify cross-account duplicate check is enforced before save.

A previous review flagged that the domain is saved before checking cross-account uniqueness, allowing the same domain to exist in multiple accounts. The current code checks only the current account's domains (lines 601-611), then saves at line 616. The isFirstConnection call at line 621 checks other accounts but runs after the save, and only affects incentive awarding, not persistence.

Run this script to confirm whether a cross-account uniqueness constraint exists elsewhere:

#!/bin/bash
# Search for cross-account UD domain uniqueness checks before save
rg -nP --type=ts 'ud.*domain|domain.*unique|EXISTS.*SELECT.*ud' src/libs/blockchain/gcr/ -C3
🧹 Nitpick comments (6)
package.json (1)

12-13: Clarify the purpose of dual type-checking scripts.

Two separate type-checking scripts have been added:

  • Line 12: type-check using bun build with --no-emit
  • Line 13: type-check-ts using tsc --noEmit

Both perform type checking without emitting output. Consider:

  1. Are both necessary, or should one be removed?
  2. If both are needed, add brief comments or documentation clarifying when to use each.
  3. The primary CI/CD pipeline likely needs a consistent, single type-check command.

Please clarify which script is the canonical type-checker for the project (e.g., for CI/CD) and consider consolidating or documenting the purpose of each.

src/libs/blockchain/gcr/gcr_routines/identityManager.ts (1)

329-336: Key union tightening looks good; return type could be made safer later.

Restricting key to "xm" | "web2" | "pqc" | "ud" matches the actual identity map and doesn’t change runtime behavior. As a follow‑up (optional), you could introduce a typed identity map (e.g., type IdentityKey = "xm" | "web2" | "pqc" | "ud") and replace Promise<any> with a keyed identity type to avoid any leakage at call sites.

src/libs/network/manageNodeCall.ts (1)

268-284: Add basic data.domain validation before resolving.

Right now resolveUDDomain will be called even if data.domain is missing or non‑string, leading to confusing deep‑stack errors. To match the rest of this handler, consider an upfront guard:

case "resolveWeb3Domain": {
    if (!data?.domain || typeof data.domain !== "string") {
        response.result = 400
        response.response = "No domain specified"
        break
    }

    try {
        const res = await UDIdentityManager.resolveUDDomain(data.domain)
        if (res) {
            response.response = res
        }
    } catch (error) {
        console.error(error)
        response.result = 400
        response.response = {
            success: false,
            error: "Failed to resolve web3 domain",
        }
    }
    break
}
src/libs/blockchain/gcr/gcr_routines/udIdentityManager.ts (2)

52-63: Multi-chain UD resolution is well-structured; consider externalizing RPC and registry config.

The EVM + Solana resolution pipeline (UD_RECORD_KEYStryEvmNetwork across Polygon/Base/Sonic/Ethereum UNS/CNS → SolanaDomainResolver fallback) is clear and matches the intended strategy.

For operational flexibility, you may eventually want to move the hard-coded RPC URLs and registry addresses into configuration (env or a shared constants module), e.g.:

  • Allow overriding RPC endpoints per network to deal with rate limits/outages.
  • Make it easier to point at testnets or alternative providers in non‑prod environments.
  • Centralize UNS/CNS contract addresses so they stay in sync if UD deploys new registries.

This doesn’t block correctness now but will make production operations and future changes less brittle.

Also applies to: 202-262, 280-360


616-669: Normalize EVM addresses in checkOwnerLinkedWallets to avoid false negatives.

checkOwnerLinkedWallets builds a set of linked XM addresses and then compares them directly against resolutionData.authorizedAddresses and resolutionData.metadata[network].owner:

for (const identity of identities[chainType][network]) {
    if (identity.address) {
        accounts.add(identity.address)
    }
}

// ...

for (const address of resolutionData.authorizedAddresses) {
    if (accounts.has(address.address)) {
        return true
    }
}

// ...

if (
    resolutionData.metadata[network].owner === signer &&
    accounts.has(signer)
) {
    return true
}

For Solana (base58) this is fine, but for EVM addresses the comparison is case‑sensitive; if XM identities store checksummed addresses and UD records or signers come in lowercased (or vice versa), you’ll miss legitimate matches and incorrectly decide the domain owner isn’t linked (no points).

To make this more robust without weakening security, consider normalizing hex addresses to lowercase when populating and checking the set, e.g.:

const normalize = (addr: string) =>
  /^0x[0-9a-fA-F]+$/.test(addr) ? addr.toLowerCase() : addr

// when collecting accounts
accounts.add(normalize(identity.address))

// when comparing
if (accounts.has(normalize(address.address))) { ... }

if (
  normalize(resolutionData.metadata[network].owner) === normalize(signer) &&
  accounts.has(normalize(signer))
) { ... }

This keeps Solana addresses untouched while preventing EVM casing differences from causing false negatives.

src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (1)

547-564: Consider normalizing signingAddress for EVM networks.

For EVM networks (Polygon, Base, Sonic, Ethereum), addresses should be lowercased for consistency, similar to how targetAddress is normalized in applyXmIdentityAdd (lines 52-54). This prevents duplicate entries differing only in case.

Add normalization after line 595:

+        // Normalize signingAddress for EVM networks
+        if (["polygon", "base", "sonic", "ethereum"].includes(payload.network)) {
+            payload.signingAddress = payload.signingAddress.toLowerCase()
+        }
+
         const accountGCR = await ensureGCRForUser(editOperation.account)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c3f0f7a and a9dbc3c.

📒 Files selected for processing (9)
  • package.json (3 hunks)
  • src/features/incentive/PointSystem.ts (6 hunks)
  • src/index.ts (1 hunks)
  • src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (5 hunks)
  • src/libs/blockchain/gcr/gcr_routines/IncentiveManager.ts (2 hunks)
  • src/libs/blockchain/gcr/gcr_routines/identityManager.ts (1 hunks)
  • src/libs/blockchain/gcr/gcr_routines/udIdentityManager.ts (1 hunks)
  • src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts (1 hunks)
  • src/libs/network/manageNodeCall.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/libs/blockchain/gcr/gcr_routines/IncentiveManager.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/features/incentive/PointSystem.ts (3)
src/libs/blockchain/gcr/gcr_routines/ensureGCRForUser.ts (1)
  • ensureGCRForUser (8-33)
src/model/entities/types/IdentityTypes.ts (1)
  • SavedUdIdentity (43-53)
src/libs/blockchain/gcr/gcr_routines/udIdentityManager.ts (1)
  • UDIdentityManager (64-698)
src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (4)
src/libs/blockchain/gcr/handleGCR.ts (1)
  • GCRResult (73-77)
src/libs/blockchain/gcr/gcr_routines/ensureGCRForUser.ts (1)
  • ensureGCRForUser (8-33)
src/model/entities/types/IdentityTypes.ts (1)
  • SavedUdIdentity (43-53)
src/libs/blockchain/gcr/gcr_routines/IncentiveManager.ts (1)
  • IncentiveManager (9-164)
🔇 Additional comments (5)
package.json (2)

51-51: The Solana ecosystem libraries are declared but not integrated—no implementations found.

The dependencies (@coral-xyz/anchor, @solana/web3.js, @metaplex-foundation/js) are listed in package.json but:

  • The mentioned implementations (SolanaDomainResolver, UDIdentityManager) do not exist in the codebase
  • None of these Solana packages are imported or used anywhere in src/
  • No resolver directory structure is present

This suggests the PR adds dependencies without corresponding implementation code. Either the Solana support code is missing from this PR, or the dependencies are premature. Verify the implementation status: are the resolver implementations planned for a follow-up PR, or should this PR include them?

If the code is incomplete, consider either deferring these dependencies until the implementation is ready, or including the full Solana resolver implementations.


10-11: The ignore patterns reference directories that do not exist—verification confirms the original concern.

The verification shows:

  • local_tests doesn't exist but is intentionally gitignored (appears in .gitignore), so including it in lint ignore patterns is reasonable for planned local development
  • aptos_tests doesn't exist, is NOT in .gitignore, and has no references anywhere in the codebase, documentation, or configuration except in the lint patterns being added

The pattern for aptos_tests appears to be either an error, prematurely added, or leftover from a previous change. The developer should clarify whether these directories are genuinely needed for future use or if the patterns should be removed/corrected.

src/features/incentive/PointSystem.ts (1)

137-203: UD domain points logic is consistent; confirm the intended “one-time per domain” behavior.

The new udDomains breakdown and awardUdDomainPoints / deductUdDomainPoints flows look well wired:

  • Domains are normalized to lowercase, preventing case-based double counting.
  • You require the domain to exist in account.identities.ud and then re‑validate ownership via UDIdentityManager.checkOwnerLinkedWallets before awarding.
  • Deduction uses udDomains[normalizedDomain] > 0 to guard against double‑deducting.

One subtle behavior: awardUdDomainPoints treats a domain as “already awarded” based on key existence:

const udDomains = account.points.breakdown?.udDomains || {}
const domainAlreadyLinked = normalizedDomain in udDomains

After an unlink + deduction, the entry’s value becomes 0 but the key remains, so a future re‑link of the same domain will never award points again (lifetime one‑time reward per domain).

If that’s intentional anti‑farming behavior, this is perfect. If instead you expect users to be able to re‑earn points after unlinking (per link/unlink cycle), you’d want the award guard to mirror the deduct guard, e.g.:

const domainPoints = udDomains[normalizedDomain] ?? 0
const domainAlreadyLinked = domainPoints > 0

and optionally delete the key when udDomains[normalizedDomain] reaches 0 on full deduction.

Also applies to: 997-1202

src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (2)

621-626: LGTM: Cross-account check for incentive deduplication.

The isFirstConnection check correctly queries whether the domain exists in any other account before awarding incentive points, preventing duplicate point awards for the same domain.


876-933: LGTM: Control flow correctly handles all identity types.

The restructured conditional logic properly branches between web2 (twitter, github, telegram, discord), UD, and web3 identity types. The UD domain check uses case-insensitive comparison, consistent with the add/remove operations.

"@fastify/swagger": "^8.15.0",
"@fastify/swagger-ui": "^4.1.0",
"@kynesyslabs/demosdk": "^2.4.18",
"@kynesyslabs/demosdk": "file:../../demos/sdks",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that the local demosdk reference is available in all environments.

Changing @kynesyslabs/demosdk to a local file path (file:../../demos/sdks) works for local development but requires a sibling demos/sdks directory. This will break in CI/CD environments without the same monorepo structure, isolated clean checkouts, or containerized builds.

Please verify:

  1. How is this path accessed in CI/CD pipelines (GitHub Actions, etc.)?
  2. Is the monorepo layout documented and guaranteed across all environments?
  3. Should this be reverted to a pinned version or published package for production builds?

Run the following script to check if this path is intended to be relative to repo root:


🏁 Script executed:

#!/bin/bash
# Verify the structure of the expected monorepo layout
find ../.. -maxdepth 3 -type d -name "sdks" 2>/dev/null | head -20
find ../.. -maxdepth 3 -name "package.json" 2>/dev/null | grep -E "(demos|sdk)" | head -20

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check repository structure and validate demosdk path

# Find package.json and show its directory
echo "=== Locating package.json ==="
find . -maxdepth 3 -name "package.json" -type f

# From package.json location, check if ../../demos/sdks exists
echo -e "\n=== Checking ../../demos/sdks relative path ==="
if [ -d "../../demos/sdks" ]; then
  echo "✓ Path exists: ../../demos/sdks"
  ls -la "../../demos/sdks"
else
  echo "✗ Path does NOT exist: ../../demos/sdks"
fi

# Check if there's a demos directory at all
echo -e "\n=== Checking for demos directory ==="
find .. -maxdepth 2 -type d -name "demos" 2>/dev/null

# Check CI/CD configuration files
echo -e "\n=== Checking CI/CD configs ==="
find . -maxdepth 2 -name "*.yml" -o -name "*.yaml" | grep -E "(github|gitlab|ci)" | head -10

# Check for any monorepo configuration
echo -e "\n=== Checking for monorepo configs ==="
ls -la .github/workflows/ 2>/dev/null || echo "No .github/workflows found"

# Check recent references to demosdk in config/docs
echo -e "\n=== Searching for demosdk references ==="
rg -i "demosdk|demos/sdk" --type-list | head -5
rg -i "demosdk" . --type yaml --type json -C 2 | head -30

Length of output: 1839


🏁 Script executed:

#!/bin/bash
# Check git history and structure for demosdk-related changes

# Check git log for demosdk or demos changes
echo "=== Recent commits mentioning demosdk or demos ==="
git log --oneline --all -20 | grep -i -E "(demosdk|demos|sdk)" || echo "No matching commits in last 20"

# Check if demos/sdks should exist as a submodule
echo -e "\n=== Checking .gitmodules ==="
cat .gitmodules 2>/dev/null || echo "No .gitmodules file"

# Check branch structure
echo -e "\n=== Current branch and status ==="
git branch -a | head -20
git status --short | head -20

# Search for any reference to demos directory structure
echo -e "\n=== Searching for references to demos structure in repo ==="
rg "demos" -C 2 --type md --type json --type yaml | head -40

# Check if there's a README explaining monorepo setup
echo -e "\n=== Checking README files ==="
find . -maxdepth 2 -name "README*" -type f -exec echo "--- {} ---" \; -exec grep -i -E "(monorepo|demosdk|demos)" {} \;

Length of output: 4975


The local demosdk path reference is broken and must be fixed before merge.

The dependency @kynesyslabs/demosdk currently points to file:../../demos/sdks, but this directory does not exist in the repository or any parent directories. The relative path resolves outside the repository root and will cause immediate build failures in all environments (CI/CD, local clones, clean checkouts).

Previous version history shows this was managed as a semantic version constraint (bun update @kynesyslabs/demosdk --latest), suggesting it is a published package.

Required actions:

  • Either revert to a pinned version (e.g., ^X.Y.Z) if using a published package, OR
  • Ensure the ../../demos/sdks directory exists with proper package structure if this is intended as a monorepo setup, OR
  • Correct the relative path if it should point elsewhere

Comment on lines +547 to +564
const payload = editOperation.data as UDIdentityAssignPayload["payload"]

// REVIEW: Validate required fields presence
if (
!payload.domain ||
!payload.signingAddress ||
!payload.signature ||
!payload.publicKey ||
!payload.timestamp ||
!payload.signedData ||
!payload.network ||
!payload.registryType
) {
return {
success: false,
message: "Invalid edit operation data: missing required fields",
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate signatureType field.

The payload is cast to UDIdentityAssignPayload["payload"] but signatureType (required by SavedUdIdentity) is never validated at runtime. If the payload is missing this field or contains an invalid value, it will be persisted incorrectly.

Add this validation after line 564:

+        // Validate signatureType
+        const validSignatureTypes = ["evm", "solana"]
+        if (!payload.signatureType || !validSignatureTypes.includes(payload.signatureType)) {
+            return {
+                success: false,
+                message: `Invalid or missing signatureType. Must be "evm" or "solana"`,
+            }
+        }
🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts around lines 547
to 564, the runtime validation checks required payload fields but omits
validating signatureType; add a check after line 564 to ensure
payload.signatureType exists and is one of the allowed values (match the
SavedUdIdentity/UDIdentityAssignPayload enum or constants used elsewhere), and
return the same error object if missing/invalid; implement the check by
comparing against the canonical list of valid signature types (or a type guard)
and include a clear error message when rejecting the operation.

Comment on lines +600 to +613
// Check if domain already exists for this account
const domainExists = accountGCR.identities.ud.some(
(id: SavedUdIdentity) =>
id.domain.toLowerCase() === payload.domain.toLowerCase(),
)

if (domainExists) {
return {
success: false,
message: "Domain already linked to this account",
}
}

accountGCR.identities.ud.push(payload)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Normalize domain before storage to prevent case inconsistencies.

The domain is compared case-insensitively (line 603) but stored as-is from the payload (line 613). This means "Brad.crypto" and "brad.crypto" are treated as duplicates during checks but stored as distinct strings, causing inconsistency in the data layer.

Apply this diff:

+        // Normalize domain to lowercase for consistency
+        const domain = payload.domain.toLowerCase()
+
         // Check if domain already exists for this account
         const domainExists = accountGCR.identities.ud.some(
             (id: SavedUdIdentity) =>
-                id.domain.toLowerCase() === payload.domain.toLowerCase(),
+                id.domain === domain,
         )
 
         if (domainExists) {
             return {
                 success: false,
                 message: "Domain already linked to this account",
             }
         }
 
-        accountGCR.identities.ud.push(payload)
+        accountGCR.identities.ud.push({
+            ...payload,
+            domain,
+        })
🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts around lines 600
to 613, the code checks domains case-insensitively but pushes the original
payload, causing storage inconsistencies (e.g., "Brad.crypto" vs "brad.crypto").
Normalize the domain to a canonical form before storing: create a copy of the
payload (or mutate safely) with domain set to payload.domain.toLowerCase() (or
another agreed canonical form) and push that normalized object into
accountGCR.identities.ud so stored values match the comparison logic.

Comment on lines +254 to +281
private deriveRecordPda(
recordVersion: number,
sldPda: PublicKey,
recordKey: string,
version = this.defaultVersion,
): PublicKey {
// Validate recordVersion before BigInt conversion to prevent TypeError
if (!Number.isInteger(recordVersion) || recordVersion < 0) {
throw new Error(
`Invalid record version: ${recordVersion}. Must be a non-negative integer.`,
)
}

const versionBuffer = Buffer.alloc(8)
versionBuffer.writeBigUInt64LE(BigInt(recordVersion.toString()))

const [userRecordPda] = PublicKey.findProgramAddressSync(
[
version,
Buffer.from("record"),
versionBuffer,
sldPda.toBuffer(),
this.hashSeedStr(recordKey),
],
this.unsProgramId,
)
return userRecordPda
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

deriveRecordPda likely rejects valid BN recordsVersion values from Anchor.

recordVersion is validated with:

if (!Number.isInteger(recordVersion) || recordVersion < 0) {
  throw new Error(`Invalid record version: ${recordVersion}. Must be a non-negative integer.`)
}

but deriveRecordPda is called with domainProperties.recordsVersion, which for Anchor-generated types is typically a BN (for u64 fields). For BN values, Number.isInteger(recordVersion) is always false, so you’ll throw even for valid on-chain data, breaking Solana record resolution.

Since you already convert via recordVersion.toString() for the BigInt write, it’s safer to accept BN-like inputs explicitly and only range-check plain numbers. For example:

-  private deriveRecordPda(
-    recordVersion: number,
+  private deriveRecordPda(
+    recordVersion: number | { toString(): string },
@@
-    // Validate recordVersion before BigInt conversion to prevent TypeError
-    if (!Number.isInteger(recordVersion) || recordVersion < 0) {
-      throw new Error(
-        `Invalid record version: ${recordVersion}. Must be a non-negative integer.`,
-      )
-    }
-
-    const versionBuffer = Buffer.alloc(8)
-    versionBuffer.writeBigUInt64LE(BigInt(recordVersion.toString()))
+    const versionBuffer = Buffer.alloc(8)
+    const asBigInt =
+      typeof recordVersion === "number"
+        ? BigInt(recordVersion)
+        : BigInt(recordVersion.toString())
+    versionBuffer.writeBigUInt64LE(asBigInt)

This keeps the BN→BigInt fix while avoiding false “invalid record version” errors when Anchor returns BN.

🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts around lines
254 to 281, the current validation rejects Anchor BN u64 values because it uses
Number.isInteger(recordVersion); change the validation to accept BN-like inputs
(objects with toString), numbers and bigint: if recordVersion is a number,
ensure it is an integer >= 0; otherwise attempt to convert via
BigInt(recordVersion.toString()) and ensure the resulting BigInt is >= 0 before
calling versionBuffer.writeBigUInt64LE; remove the Number.isInteger() branch
that rejects non-number BN values and use the normalized BigInt for the write
and PDA derivation.

+ reenable mainloop
+ fix: deriveRecordPda bigint ambiguity
+ validate signatureType in applyUdIdentityAdd
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (4)
src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (2)

601-614: Normalize domain to lowercase before storage.

The duplicate check compares domains case-insensitively (line 604), but the payload is stored as-is (line 614). This means "Brad.crypto" and "brad.crypto" pass the duplicate check but are stored as distinct strings, causing data inconsistency.

Apply this diff:

+        // Normalize domain to lowercase for consistency
+        const normalizedDomain = payload.domain.toLowerCase()
+
         // Check if domain already exists for this account
         const domainExists = accountGCR.identities.ud.some(
             (id: SavedUdIdentity) =>
-                id.domain.toLowerCase() === payload.domain.toLowerCase(),
+                id.domain === normalizedDomain,
         )
 
         if (domainExists) {
             return {
                 success: false,
                 message: "Domain already linked to this account",
             }
         }
 
-        accountGCR.identities.ud.push(payload)
+        accountGCR.identities.ud.push({
+            ...payload,
+            domain: normalizedDomain,
+        })

547-565: Validate signatureType against allowed values.

The presence of signatureType is checked (line 553), but its value is never validated at runtime. Per the SavedUdIdentity interface, only "evm" or "solana" are valid. If an invalid value is passed, it will be persisted and could cause verification or display issues downstream.

Apply this diff after line 565:

+        // Validate signatureType
+        const validSignatureTypes = ["evm", "solana"]
+        if (!validSignatureTypes.includes(payload.signatureType)) {
+            return {
+                success: false,
+                message: `Invalid signatureType: ${payload.signatureType}. Must be "evm" or "solana"`,
+            }
+        }
+
src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts (2)

310-310: Pass programId explicitly to Program constructor and improve IDL typing.

The two-argument Program constructor form relies on idl.metadata.address, which may not be present. The three-argument form with an explicit programId is safer and more explicit.

Apply this diff:

-      this.program = new Program(UnsSolIdl as any, provider) as Program<UnsSol>
+      this.program = new Program(UnsSolIdl as any, this.unsProgramId, provider) as Program<UnsSol>

Additionally, improve IDL typing by importing Idl:

- import { AnchorProvider, Program } from "@coral-xyz/anchor"
+ import { AnchorProvider, Program, type Idl } from "@coral-xyz/anchor"

And update line 310:

-      this.program = new Program(UnsSolIdl as any, this.unsProgramId, provider) as Program<UnsSol>
+      this.program = new Program(UnsSolIdl as Idl, this.unsProgramId, provider) as Program<UnsSol>

Based on past review comments flagging this as a critical issue.


254-283: Fix BN to BigInt conversion to handle Anchor BN values.

The current code will throw "Cannot convert object to BigInt" when recordVersion is an Anchor BN object (typical for u64 fields). Evidence: line 606 uses Number(domainProperties.recordsVersion), indicating it's a BN type.

Apply this diff to handle both number and BN-like inputs:

   private deriveRecordPda(
-    recordVersion: number,
+    recordVersion: number | { toString(): string },
     sldPda: PublicKey,
     recordKey: string,
     version = this.defaultVersion,
   ): PublicKey {
-    const bigIntRecordVersion = BigInt(recordVersion)
-
-    // Validate recordVersion before BigInt conversion to prevent TypeError
-    if (bigIntRecordVersion < BigInt(0)) {
-      throw new Error(
-        `Invalid record version: ${bigIntRecordVersion}. Must be a non-negative integer.`,
-      )
-    }
+    // Handle both number and BN-like inputs
+    const bigIntRecordVersion =
+      typeof recordVersion === "number"
+        ? BigInt(recordVersion)
+        : BigInt(recordVersion.toString())
+    
+    if (bigIntRecordVersion < BigInt(0)) {
+      throw new Error(
+        `Invalid record version: ${bigIntRecordVersion}. Must be a non-negative integer.`,
+      )
+    }
 
     const versionBuffer = Buffer.alloc(8)
     versionBuffer.writeBigUInt64LE(bigIntRecordVersion)

Based on past review comments addressing the same issue.

🧹 Nitpick comments (1)
src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts (1)

556-556: Consider removing verbose debug logging for production.

The debug log at line 556 serializes the entire domainProperties object, which may be verbose in production environments. Since it's at debug level, the impact is minimal, but consider removing it if not needed.

-        log.debug("domainProperties: " + JSON.stringify(domainProperties))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a9dbc3c and 8398a67.

📒 Files selected for processing (3)
  • src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (5 hunks)
  • src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts (1 hunks)
  • src/libs/network/manageNodeCall.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/libs/network/manageNodeCall.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-10T12:30:35.789Z
Learnt from: tcsenpai
Repo: kynesyslabs/node PR: 475
File: src/features/incentive/PointSystem.ts:711-727
Timestamp: 2025-10-10T12:30:35.789Z
Learning: In the TelegramSignedAttestation from kynesyslabs/demosdk (v2.4.18+), the `group_membership` field in the payload is a boolean, not an object. Check it as: `attestation?.payload?.group_membership === true`

Applied to files:

  • src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts
🧬 Code graph analysis (2)
src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (4)
src/libs/blockchain/gcr/handleGCR.ts (1)
  • GCRResult (73-77)
src/libs/blockchain/gcr/gcr_routines/ensureGCRForUser.ts (1)
  • ensureGCRForUser (8-33)
src/model/entities/types/IdentityTypes.ts (1)
  • SavedUdIdentity (43-53)
src/libs/blockchain/gcr/gcr_routines/IncentiveManager.ts (1)
  • IncentiveManager (9-164)
src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts (4)
src/libs/blockchain/UDTypes/uns_sol.ts (1)
  • UnsSol (7-2403)
src/libs/blockchain/transaction.ts (1)
  • hash (98-106)
src/utilities/cli_libraries/wallet.ts (1)
  • Wallet (10-134)
src/utilities/logger.ts (1)
  • error (125-132)
🔇 Additional comments (4)
src/libs/blockchain/gcr/gcr_routines/GCRIdentityRoutines.ts (3)

645-695: LGTM! UD identity removal logic is correct.

The method properly validates the domain, checks existence with case-insensitive comparison, removes the entry, and triggers the unlinking incentive flow. Using findOneBy (rather than ensureGCRForUser) is appropriate here since removal should fail if the account doesn't exist.


827-840: LGTM! Dispatcher integration follows established patterns.

The udadd and udremove cases are correctly integrated into the switch statement and follow the same pattern as existing identity types (xm, web2, pqc).


865-935: LGTM! UD support in isFirstConnection is well-implemented.

The method is correctly extended to support UD identity type:

  • Type union includes "ud" (line 866)
  • Data payload includes optional domain field (line 872)
  • UD branch (lines 893-909) queries for cross-account domain existence with case-insensitive matching
  • Returns true when no other account has linked the domain, enabling first-connection incentive awards

The logic aligns with existing patterns for web2 and web3 identity types.

src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts (1)

111-758: Well-structured resolver implementation with clean API design.

The SolanaDomainResolver class demonstrates strong architectural decisions:

  • Clear separation of public API methods and private helpers
  • Parallel record resolution for performance (lines 570-599)
  • Comprehensive input validation and error handling
  • Proper PDA derivation following Solana patterns
  • Program instance caching for efficiency
  • Detailed documentation with examples

The critical and major issues flagged in other comments should be addressed, but the overall design is solid.

@@ -0,0 +1,759 @@
import { AnchorProvider, Program } from "@coral-xyz/anchor"
import Wallet from "@coral-xyz/anchor/dist/cjs/nodewallet"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Wallet import may have been reintroduced; use NodeWallet explicitly.

Past review comments indicated this was fixed, but the code still imports and uses Wallet instead of NodeWallet. This can cause type and bundling issues.

Apply this diff:

-import Wallet from "@coral-xyz/anchor/dist/cjs/nodewallet"
+import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet"

And update the usage:

-      const wallet = new Wallet(dummyKeypair)
+      const wallet = new NodeWallet(dummyKeypair)

Also applies to: 306-306

Also applies to: 306-306

🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts around lines 2
and 306, the module currently imports and uses Wallet from
"@coral-xyz/anchor/dist/cjs/nodewallet" which reintroduces the wrong symbol;
change the import to explicitly import NodeWallet from the same module and
update all usages of Wallet to NodeWallet (including the usage at line 306) so
types and bundling resolve correctly.

*/
constructor(config: ResolverConfig = {}) {
this.config = {
rpcUrl: config.rpcUrl || process.env.SOLANA_RPC || "https://britta-qyzo1g-fast-mainnet.helius-rpc.com/",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Replace hardcoded team-specific RPC endpoint with public mainnet URL.

The hardcoded Helius RPC URL appears to be team-specific and may not be accessible to all users or in production environments.

Apply this diff to use the public Solana mainnet endpoint:

-      rpcUrl: config.rpcUrl || process.env.SOLANA_RPC || "https://britta-qyzo1g-fast-mainnet.helius-rpc.com/",
+      rpcUrl: config.rpcUrl || process.env.SOLANA_RPC || clusterApiUrl("mainnet-beta"),

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts around line
179, the rpcUrl is set to a hardcoded, team-specific Helius RPC endpoint;
replace that value with a public Solana mainnet RPC endpoint (for example
https://api.mainnet-beta.solana.com) or use a config/env var fallback so the
code uses config.rpcUrl || process.env.SOLANA_RPC ||
"https://api.mainnet-beta.solana.com" instead of the private Helius URL.

(key) => typeof key === "string" && key.trim() !== "",
)

// try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove commented-out try-catch block.

The commented-out try-catch block (lines 547 and 610-618) appears to be a debug artifact. Either restore proper error handling or remove the comments entirely.

If error handling is not needed at this level (errors propagated naturally), apply this diff:

-    // try {
       const program = await this.getProgram()
       const sldPda = this.deriveSldPda(trimmedLabel, trimmedTld)
       ...
-    // } catch (error) {
-    //   return {
-    //     domain,
-    //     exists: false,
-    //     sldPda: this.deriveSldPda(trimmedLabel, trimmedTld).toString(),
-    //     records: [],
-    //     error: error instanceof Error ? error.message : "Unknown error occurred",
-    //   }
-    // }

Alternatively, if top-level error handling is desired, uncomment and fix the block.

Also applies to: 610-618

Also applies to: 610-618

🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts around lines
547 and 610-618, there are commented-out try/catch blocks left as debug
artifacts; either remove those commented lines entirely or restore a proper
try/catch. If you choose to remove them, delete the commented "try {" and
corresponding commented "catch" / "}" blocks so no dead commented code remains;
if you choose to restore error handling, uncomment the blocks and implement a
proper catch that logs relevant error context and rethrows or handles the error
appropriately (do not leave commented code).

log.debug("domainProperties: " + JSON.stringify(domainProperties))

} catch (error) {
console.error("domainProperties fetch error: ", error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Use log.error instead of console.error for consistency.

The file consistently uses the log utility for logging (lines 343, 360, 372, 377, 380), but line 559 uses console.error.

Apply this diff:

-        console.error("domainProperties fetch error: ", error)
+        log.error("domainProperties fetch error: ", error)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.error("domainProperties fetch error: ", error)
log.error("domainProperties fetch error: ", error)
🤖 Prompt for AI Agents
In src/libs/blockchain/gcr/gcr_routines/udSolanaResolverHelper.ts around line
559 the code uses console.error("domainProperties fetch error: ", error);
replace this with the project's logging utility by calling log.error with a
descriptive message and the error (e.g., log.error("domainProperties fetch
error:", error)) so logs remain consistent with other entries in this file and
include the same structured output.

@github-actions
Copy link

⚠️ MCP Memory Files Detected

This PR modifies .serena/ files. After merge, these changes will be automatically reverted to preserve branch-specific MCP memories.

Files that will be reverted:

  • .serena/memories/_index.md
  • .serena/memories/session_ud_ownership_verification_2025_10_21.md
  • .serena/memories/session_ud_points_implementation_2025_01_31.md
  • .serena/memories/ud_architecture_patterns.md
  • .serena/memories/ud_integration_complete.md
  • .serena/memories/ud_phase5_complete.md
  • .serena/memories/ud_phases_tracking.md
  • .serena/memories/ud_security_patterns.md
  • .serena/memories/ud_technical_reference.md

@cwilvx cwilvx merged commit 972961a into testnet Nov 24, 2025
4 of 5 checks passed
@cwilvx cwilvx deleted the ud_identities branch November 24, 2025 21:42
@coderabbitai coderabbitai bot mentioned this pull request Dec 4, 2025
@coderabbitai coderabbitai bot mentioned this pull request Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants