Skip to main content

Frequently Asked Questions

General Questions

Link Core is the central orchestrator microservice for the LedgerLink platform. It manages the entire lifecycle of transactions, balance tracking, and digital asset management across the ecosystem.

Technology Stack:

  • NestJS backend with TypeScript
  • PostgreSQL database with TypeORM
  • Bull queues for background job processing
  • Blockchain integration for digital asset transactions
  • RESTful API with Swagger documentation

Core Responsibilities:

  • Transaction processing (deposits, withdrawals, transfers)
  • AML/compliance screening integration
  • Balance management and ledger operations
  • Digital asset configuration
  • Job processing and event handling

Deposit Transactions:

  • Detected via blockchain event monitoring
  • Automatically screened for AML/compliance
  • Can be frozen for manual review
  • Balance updated upon approval

Withdrawal Transactions:

  • Customer-initiated via API
  • Screened before processing
  • Can be frozen for manual review
  • Blockchain transaction executed upon approval

Internal Transfers:

  • Between customer accounts
  • Real-time balance updates
  • Audit trail maintained

How does transaction screening work?

Link Core uses a webhook/callback pattern for screening:

  1. Transaction Created:

    • Transaction enters PENDING status
    • Link Core logs "Starting AML verification"
    • Transaction awaits external screening
  2. External Screening (outside LedgerLink):

    • External AML/compliance system performs checks
    • This could be a third-party service or manual compliance team
    • External system has access to Link Core API
  3. Screening Callback:

    • External system calls POST /transactions/complete-screening
    {
    "id": "transaction-id",
    "isApproved": true/false,
    "screeningData": { /* screening details */ }
    }
  4. Link Core Processes Result:

    • If approved: Transaction queued for processing
    • If rejected: Status changed to FROZEN for manual review
  5. Manual Review (for frozen transactions):

    • Admin reviews transaction details and screening data
    • Decision: Approve or Reject
    • API endpoints: /transactions/:id/approve-frozen-* or /transactions/:id/reject-frozen-*

What are transaction statuses?

  • PENDING: Created, awaiting external screening callback
  • FROZEN: Flagged by external screening, requires manual review
  • APPROVED: Approved (automatically or after manual review), processing
  • COMPLETED: Fully processed, balance updated
  • REJECTED: Rejected by external screening or manual review
  • FAILED: Processing error occurred

Note: There is no "SCREENING" status - transactions remain PENDING while awaiting the external screening webhook callback.

How are balances calculated?

Link Core uses double-entry bookkeeping:

  • Available Balance: Funds available for withdrawal
  • Frozen Balance: Funds held (pending transactions, frozen deposits)
  • Total Balance: Available + Frozen

Balance Updates:

  • Real-time updates on transaction completion
  • Atomic operations ensure consistency
  • Audit trail maintained for all changes

Technical Questions

For Dashboard/Frontend:

// Access through Auth Server proxy
const response = await fetch('/api/link-core/v1/transactions', {
credentials: 'include' // Include session cookies
});

For Internal Services:

// Direct service-to-service calls (within secure network)
const response = await fetch('http://link-core:3000/transactions');

What authentication is required?

Production: All requests go through the Link Dashboard's Auth Server:

  • User authentication handled by Dashboard
  • Session validation by Auth Server
  • Requests proxied to Link Core

Development: Direct access to service (no authentication required)

How do I request a withdrawal?

POST /transactions/withdrawal
{
"customerId": "customer-123",
"assetId": "btc-asset-id",
"amount": "0.5",
"destinationAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
}

Flow:

  1. Request validated
  2. Balance checked
  3. Transaction created (PENDING)
  4. Sent to screening
  5. If approved → Blockchain transaction initiated
  6. If frozen → Manual review required

How do I handle frozen transactions?

Check Transaction Status:

GET /transactions/:id

Approve Frozen Deposit:

POST /transactions/:id/approve-frozen-deposit

Reject Frozen Deposit:

POST /transactions/:id/reject-frozen-deposit
{
"reason": "AML compliance violation"
}

Approve Frozen Withdrawal:

POST /transactions/:id/approve-frozen-withdrawal

Reject Frozen Withdrawal:

POST /transactions/:id/reject-frozen-withdrawal
{
"reason": "Suspicious activity detected"
}

How do I query customer balances?

Get All Balances:

GET /balances/customer/:customerId

Filter by Asset:

GET /balances/customer/:customerId?filter[assetCode]=BTC

Response includes:

  • Asset details (code, name, ID)
  • Available balance
  • Frozen balance
  • Total balance

What happens during background job processing?

Screening Complete Job:

  • Processes approved transactions
  • Updates balances
  • Sends notifications
  • Logs to Link Tracker

Omnibus Balance Monitor:

  • Tracks omnibus wallet balances
  • Alerts on low balance conditions
  • Ensures liquidity for withdrawals

Link Quote:

  • Fetches real-time asset prices
  • Values transactions in USD/fiat
  • Used for reporting and analytics

Link Tracker:

  • Logs all transaction events
  • Maintains audit trail
  • Provides activity monitoring

Wallet Manager:

  • Executes blockchain transactions
  • Manages digital asset custody
  • Processes withdrawals

Blockchain Listener:

  • Monitors incoming deposits
  • Detects blockchain events
  • Triggers transaction creation

External AML/Compliance System:

  • Independent system (outside LedgerLink)
  • Performs AML/compliance checks
  • Calls back to Link Core via webhook: POST /transactions/complete-screening
  • Provides screening metadata and approval/rejection decisions

What are the rate limits?

Link Dashboard (Auth Server): Rate limiting is implemented at the Dashboard/Auth Server level to protect the entire platform.

Link Core Service: No rate limiting at the service level (relies on Dashboard protection).

Best Practices:

  • Dashboard rate limiting protects against excessive requests
  • Implement client-side caching where appropriate
  • Use appropriate pagination for list endpoints
  • Monitor your request patterns

Integration Questions

How do I monitor transaction status?

Polling Approach:

async function monitorTransaction(id: string): Promise<Transaction> {
while (true) {
const tx = await fetchTransaction(id);

if (['COMPLETED', 'REJECTED', 'FAILED'].includes(tx.status)) {
return tx;
}

await sleep(5000); // Wait 5 seconds
}
}

Event-Driven Approach:

  • Subscribe to Link Tracker events
  • Filter by transaction ID
  • React to status changes in real-time

How do I handle transaction failures?

  1. Check Transaction Status:

    • GET /transactions/:id
    • Review status and error details
  2. Common Failure Reasons:

    • Insufficient balance
    • Invalid blockchain address
    • Network errors
    • Screening rejection
  3. Recovery:

    • For FAILED withdrawals: Balance automatically refunded
    • For REJECTED transactions: Customer notified
    • Retry logic for network errors

Can I cancel a transaction?

Pending/Screening Transactions: Not currently supported (transactions process quickly)

Frozen Transactions: Can be rejected via API:

  • Deposits: POST /transactions/:id/reject-frozen-deposit
  • Withdrawals: POST /transactions/:id/reject-frozen-withdrawal

Approved/Completed Transactions: Cannot be cancelled (use reversal transaction if needed)

How do I create a new digital asset?

POST /assets
{
"code": "ETH",
"name": "Ethereum",
"decimals": 18,
"blockchain": "ethereum",
"contractAddress": "0x..."
}

Required for:

  • Adding new blockchain support
  • Supporting new tokens
  • Custom digital asset definitions

What happens if the external screening system is unavailable?

  • Transactions remain in PENDING status indefinitely
  • No automatic retry (webhook pattern - external system must call back)
  • Manual intervention options:
    • External system can call /transactions/complete-screening when back online
    • Admins can manually approve/reject via freeze endpoints
  • Monitor PENDING transactions for extended delays

Troubleshooting

Transaction stuck in PENDING status

Causes:

  • External screening system hasn't called back yet
  • External screening system unavailable
  • Webhook endpoint not reachable from external system
  • External system configuration issue

Solution:

  • Check external screening system status
  • Verify webhook endpoint is accessible
  • Review Link Tracker logs for "Starting AML verification"
  • Manually complete screening via webhook endpoint if needed
  • Contact external screening system administrator

Balance mismatch

Causes:

  • Concurrent transaction processing
  • Database replication lag
  • Failed transaction not rolled back

Solution:

  • Check transaction history
  • Review all transactions for customer/account
  • Verify ledger entries
  • Contact support if issue persists

Withdrawal not executing

Causes:

  • Transaction frozen for review
  • Insufficient omnibus balance
  • Wallet Manager service down
  • Invalid destination address

Solution:

  • Check transaction status
  • Verify omnibus balances
  • Check Wallet Manager service health
  • Validate destination address format

Support & Maintenance

What support is available?

  • Documentation: Comprehensive guides and API reference
  • Email Support: helpdesk@ledgerlink.ai
  • JIRA: Report bugs and request features
  • Development Team: Contact for technical assistance

How do I report a bug?

  1. Check existing JIRA tickets
  2. Gather information:
    • Steps to reproduce
    • Expected vs actual behavior
    • Relevant log output
    • Transaction IDs (if applicable)
  3. Create JIRA task or email helpdesk@ledgerlink.ai
# Install dependencies
npm install

# Start PostgreSQL
npm run docker

# Run migrations
npm run migration:run

# Start development server
npm run start:dev

Access Swagger docs at http://localhost:3000/api


Still have questions? Contact helpdesk@ledgerlink.ai or create an issue in the GitHub repository.