Skip to main content

Non-Custodial Wallet Condensed Flow

Create complete transactions to self-hosted (non-custodial) wallets with automatic KYC screening and workflow optimization in a single API call.

Use Case

Perfect for transactions where the beneficiary wallet is self-hosted by an individual rather than managed by a VASP. The system automatically handles the simplified workflow required for non-custodial recipients.

Key Features

  • No VASP Required: Beneficiary manages their own wallet
  • Simplified Workflow: Automatic skip of beneficiary VASP communication
  • Enhanced KYC: Additional screening for self-custody scenarios
  • Compliance Maintained: Full Travel Rule compliance despite non-custodial nature

Request

Endpoint: POST https://api.trpcontinuum.com/trp/transactions/condensed

Headers:

Content-Type: application/json
Authorization: Bearer {your-token}

Request Body:

{
"transaction": {
"network": "bitcoin",
"virtualAsset": "Bitcoin (BTC)",
"amount": "50.25",
"beneficiaryWalletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"originatorWalletAddress": "bc1qabc123def456ghi789jkl012mno345pqr678stu",
"memo": "Payment to non-custodial wallet"
},
"beneficiary": {
"isNonCustodialWallet": true,
"beneficiaryIsLegalPerson": false,
"beneficiaryFirstName": "Jane",
"beneficiaryLastName": "Smith",
"dateOfBirth": "1992-07-15",
"placeOfBirth": "Boston, MA",
"beneficiaryIdNumber": "555666777",
"beneficiaryIdType": "PASSPORT",
"beneficiaryIdCountryOfIssue": "US",
"buildingNumber": "789",
"streetName": "Crypto Street",
"townName": "Boston",
"postCode": "02101",
"country": "US"
},
"originator": {
"originatorIsLegalPerson": false,
"originatorFirstName": "John",
"originatorLastName": "Doe",
"originatorDob": "1985-03-20",
"originatorPlaceOfBirth": "Chicago, IL",
"originatorIdNumber": "987654321",
"originatorIdType": "PASSPORT",
"originatorIdCountryOfIssue": "US",
"originatorAddressLine1": "456 Oak Street",
"originatorAddressLine2": "Apt 3A",
"originatorCity": "San Francisco",
"originatorState": "CA",
"originatorPostalCode": "94102",
"originatorCountry": "US"
}
}

Response Examples

Success (No KYC Matches)

{
"success": true,
"data": {
"id": "txn_noncust123",
"status": "Waiting for TX Hash",
"network": "bitcoin",
"virtualAsset": "Bitcoin (BTC)",
"amount": "50.25",
"beneficiaryWalletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"originatorWalletAddress": "bc1qabc123def456ghi789jkl012mno345pqr678stu",
"beneficiary": {
"beneficiaryFirstName": "Jane",
"beneficiaryLastName": "Smith",
"isNonCustodialWallet": true,
"beneficiaryVaspName": "NON-CUSTODIAL-WALLET"
},
"originator": {
"originatorFirstName": "John",
"originatorLastName": "Doe"
},
"kycCheck": {
"hasMatches": false,
"totalMatches": 0,
"beneficiaryChecked": true,
"originatorChecked": true,
"nonCustodialScreening": true,
"screenedAt": "2024-08-07T10:00:00Z"
},
"workflowType": "non_custodial",
"autoSkippedSteps": [
"send_to_beneficiary_vasp",
"approve_originator",
"payment_check"
],
"createdAt": "2024-08-07T10:00:00Z",
"updatedAt": "2024-08-07T10:00:00Z"
}
}

Success (KYC Matches Found)

{
"success": true,
"data": {
"id": "txn_noncust456",
"status": "KYC Beneficiary Pending Review",
"network": "bitcoin",
"virtualAsset": "Bitcoin (BTC)",
"amount": "50.25",
"kycCheck": {
"hasMatches": true,
"totalMatches": 1,
"beneficiaryMatches": 1,
"originatorMatches": 0,
"topMatch": {
"score": 0.87,
"name": "Jane Smith",
"riskLevel": "high",
"sources": ["watchlist"],
"details": {
"birthDate": "1992-07-15",
"country": "US",
"matchType": "name_dob_country",
"walletType": "non_custodial"
}
},
"nonCustodialScreening": true,
"enhancedScreening": {
"walletAnalysis": true,
"addressRiskScore": 0.1,
"previousTransactions": 0
},
"screenedAt": "2024-08-07T10:00:00Z"
},
"workflowType": "non_custodial",
"createdAt": "2024-08-07T10:00:00Z",
"updatedAt": "2024-08-07T10:00:00Z"
}
}

Required Fields

Transaction

  • network - Blockchain network
  • virtualAsset - Asset name
  • amount - Transaction amount as string
  • beneficiaryWalletAddress - Self-hosted wallet address
  • originatorWalletAddress - Sender wallet address

Beneficiary (Non-Custodial)

  • isNonCustodialWallet - Must be true
  • beneficiaryIsLegalPerson - Usually false (individuals)
  • beneficiaryFirstName - First name (if natural person)
  • beneficiaryLastName - Last name (if natural person)
  • dateOfBirth - Birth date (YYYY-MM-DD format)
  • country - Country code (ISO 3166-1 alpha-2)

Originator

  • originatorIsLegalPerson - true or false
  • originatorFirstName/originatorLastName (if natural person)
  • originatorLegalName (if legal person)
  • originatorDob (natural person) / originatorDateOfIncorporation (legal person)
  • originatorCountry - Country code

Optional Fields

Enhanced Beneficiary Data

  • beneficiaryIdNumber - ID document number
  • beneficiaryIdType - ID type ("PASSPORT", "NATIONAL_ID", "DRIVERS_LICENSE")
  • beneficiaryIdCountryOfIssue - Issuing country
  • placeOfBirth - Place of birth
  • Address fields: buildingNumber, streetName, townName, postCode

Wallet Information

  • walletProvider - Wallet software/provider (if known)
  • walletType - Type of non-custodial wallet
  • selfCustodyConfirmation - Confirmation that wallet is self-hosted

Non-Custodial Workflow

Automatic Skip Steps

When isNonCustodialWallet: true, the system automatically:

  1. Skips Beneficiary VASP Communication - No VASP to notify
  2. Skips Originator Approval - No beneficiary VASP to approve
  3. Skips Payment Check - No VASP payment verification needed
  4. Direct to TX Hash - Ready for blockchain transaction

Status Progression (No KYC Matches)

  1. Waiting for TX Hash - Ready for blockchain transaction
  2. Submit TX hash via /tx-hash-submit endpoint
  3. Tx Hash Sent Successfully - Transaction complete

Status Progression (With KYC Matches)

  1. KYC Beneficiary Pending Review - Manual review required
  2. After KYC approval → Waiting for TX Hash
  3. Submit TX hash → Tx Hash Sent Successfully

Enhanced KYC for Non-Custodial

Additional Screening

Non-custodial transactions receive enhanced screening:

  • Wallet Address Analysis: Risk scoring of destination address
  • Blockchain Analysis: Previous transaction history review
  • Enhanced Entity Screening: Additional focus on self-custody risks
  • Geographic Risk Assessment: Country-specific non-custodial regulations

Risk Factors

Higher scrutiny applied for:

  • Large amounts to non-custodial wallets
  • First-time recipients
  • High-risk jurisdictions
  • Privacy coins or mixers
  • Suspicious address patterns

Code Examples

JavaScript/Node.js

const axios = require('axios');

async function createNonCustodialTransaction() {
try {
const response = await axios.post('https://api.trpcontinuum.com/trp/transactions/condensed', {
transaction: {
network: "bitcoin",
virtualAsset: "Bitcoin (BTC)",
amount: "25.50",
beneficiaryWalletAddress: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
originatorWalletAddress: "bc1qabc123def456ghi789jkl012mno345pqr678stu",
memo: "Payment to personal wallet"
},
beneficiary: {
isNonCustodialWallet: true,
beneficiaryIsLegalPerson: false,
beneficiaryFirstName: "Alice",
beneficiaryLastName: "Johnson",
dateOfBirth: "1988-11-22",
country: "US",
beneficiaryIdNumber: "123987456",
beneficiaryIdType: "PASSPORT",
walletProvider: "Electrum"
},
originator: {
originatorIsLegalPerson: false,
originatorFirstName: "Bob",
originatorLastName: "Wilson",
originatorDob: "1985-03-20",
originatorCountry: "US"
}
}, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});

if (response.data.success) {
const transaction = response.data.data;

if (transaction.kycCheck.hasMatches) {
console.log(`Non-custodial transaction ${transaction.id} held for review`);
console.log(`Enhanced screening flagged ${transaction.kycCheck.totalMatches} matches`);
// Handle KYC review
} else {
console.log(`Non-custodial transaction ${transaction.id} ready for blockchain execution`);
console.log(`Status: ${transaction.status}`);
console.log(`Skipped steps: ${transaction.autoSkippedSteps.join(', ')}`);

// Proceed directly to blockchain transaction
// await executeBlockchainTransaction(transaction);
}
}
} catch (error) {
console.error('Non-custodial transaction failed:', error.response?.data);
}
}

async function submitTransactionHash(transactionId, txHash) {
try {
const response = await axios.post(`https://api.trpcontinuum.com/trp/transactions/${transactionId}/tx-hash-submit`, {
txHash: txHash,
note: "Transaction broadcast to Bitcoin network"
}, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});

if (response.data.success) {
console.log(`Transaction ${transactionId} completed successfully`);
console.log(`TX Hash: ${txHash}`);
}
} catch (error) {
console.error('TX hash submission failed:', error.response?.data);
}
}

Python

import requests
import hashlib

def create_non_custodial_transaction():
payload = {
"transaction": {
"network": "bitcoin",
"virtualAsset": "Bitcoin (BTC)",
"amount": "25.50",
"beneficiaryWalletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"originatorWalletAddress": "bc1qabc123def456ghi789jkl012mno345pqr678stu",
"memo": "Payment to personal wallet"
},
"beneficiary": {
"isNonCustodialWallet": True,
"beneficiaryIsLegalPerson": False,
"beneficiaryFirstName": "Alice",
"beneficiaryLastName": "Johnson",
"dateOfBirth": "1988-11-22",
"country": "US",
"beneficiaryIdNumber": "123987456",
"beneficiaryIdType": "PASSPORT",
"walletProvider": "Electrum"
},
"originator": {
"originatorIsLegalPerson": False,
"originatorFirstName": "Bob",
"originatorLastName": "Wilson",
"originatorDob": "1985-03-20",
"originatorCountry": "US"
}
}

response = requests.post(
'https://api.trpcontinuum.com/trp/transactions/condensed',
json=payload,
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)

if response.status_code == 200:
data = response.json()
if data['success']:
transaction = data['data']

print(f"Non-custodial transaction created: {transaction['id']}")
print(f"Workflow type: {transaction['workflowType']}")
print(f"Status: {transaction['status']}")

if transaction['kycCheck']['hasMatches']:
print("⚠️ KYC review required")
handle_kyc_review(transaction['id'])
else:
print("✅ Ready for blockchain execution")
print(f"Auto-skipped: {', '.join(transaction['autoSkippedSteps'])}")

# Simulate blockchain transaction
tx_hash = simulate_blockchain_transaction(transaction)
submit_transaction_hash(transaction['id'], tx_hash)
else:
print(f"Error: {response.status_code} - {response.text}")

def simulate_blockchain_transaction(transaction):
# In real implementation, this would broadcast to blockchain
import uuid
return f"0x{uuid.uuid4().hex}"

def submit_transaction_hash(transaction_id, tx_hash):
response = requests.post(
f'https://api.trpcontinuum.com/trp/transactions/{transaction_id}/tx-hash-submit',
json={
'txHash': tx_hash,
'note': 'Non-custodial transaction completed'
},
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)

if response.status_code == 200:
print(f"✅ Transaction completed with hash: {tx_hash}")
else:
print(f"❌ TX hash submission failed: {response.text}")

Next Steps

After Successful Creation (No KYC Matches)

  1. Execute Blockchain Transaction: Send actual cryptocurrency
  2. Submit TX Hash: Use /tx-hash-submit endpoint
  3. Transaction Complete: Status becomes Tx Hash Sent Successfully

After KYC Approval

  1. Status Updates: KYC Beneficiary Pending ReviewWaiting for TX Hash
  2. Execute Blockchain Transaction: Proceed with crypto transfer
  3. Submit TX Hash: Complete the transaction record

Compliance Considerations

Travel Rule Compliance

Even with non-custodial recipients:

  • Full originator information collected
  • Beneficiary information verified
  • Transaction records maintained
  • Regulatory reporting requirements met

Enhanced Monitoring

  • Higher scrutiny for large amounts
  • Blockchain analysis for suspicious patterns
  • Geographic risk assessment
  • Ongoing transaction monitoring

Regulatory Variations

Different jurisdictions may have specific requirements:

  • US: FinCEN guidance on self-hosted wallets
  • EU: 5AMLD requirements for crypto-to-crypto transfers
  • Japan: JVCEA self-custody reporting requirements

Common Errors

Missing Non-Custodial Flag

{
"success": false,
"error": "MISSING_BENEFICIARY_TYPE",
"message": "Must specify beneficiary type",
"details": {
"required_fields": ["beneficiaryVaspId", "isNonCustodialWallet", "unregisteredVaspWebsite"],
"suggestion": "Set isNonCustodialWallet: true for self-hosted wallets"
}
}

Invalid Wallet Address

{
"success": false,
"error": "INVALID_WALLET_ADDRESS",
"message": "Wallet address format invalid for specified network",
"details": {
"network": "bitcoin",
"address": "0x1234...",
"expectedFormat": "bc1... (Bech32) or 1... (P2PKH) or 3... (P2SH)"
}
}

Testing

Test Scenarios

Low Risk Non-Custodial:

{
"beneficiaryFirstName": "Test",
"beneficiaryLastName": "User",
"dateOfBirth": "1990-01-01",
"isNonCustodialWallet": true
}

High Risk (Will Trigger Review):

{
"beneficiaryFirstName": "High",
"beneficiaryLastName": "Risk",
"dateOfBirth": "1980-01-01",
"country": "IR",
"isNonCustodialWallet": true
}

Wallet Address Testing

Use valid test addresses for different networks:

  • Bitcoin: bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh
  • Ethereum: 0x742C4B4f7c1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e
  • Polygon: Same as Ethereum format