Skip to main content
The sync sub-module handles bulk migration of customer data between your existing systems and Trusset. It is designed for institutions with established customer databases that need to onboard thousands of records without manual entry. Records are mapped by externalId - your system’s unique customer identifier. This key is used for deduplication and conflict resolution across syncs.

Import records

import { SyncRecord } from '@trusset/sdk'

const records: SyncRecord[] = existingCustomers.map(row => ({
  externalId: row.customerId,       // required - your unique ID
  name: row.fullName,
  walletAddress: row.ethAddress,    // optional
  country: row.countryCode,
  investorType: 'RETAIL',
  metadata: { source: 'core-banking', migrationBatch: '2025-Q1' },
}))

const result = await trusset.customers.sync.importRecords(records, {
  batchSize: 50,
  onConflict: 'update',
  onProgress: (done, total) => {
    console.log(`${done}/${total} processed`)
  },
})

result.total    // total records submitted
result.created  // new customers created
result.updated  // existing customers updated
result.skipped  // skipped due to onConflict: 'skip'
result.errors   // array of { externalId, code, message }
The SDK processes records in configurable batches to avoid overloading the API. Each record is matched against existing customers by externalId. If a match is found, the onConflict strategy determines the outcome.

Conflict strategies

StrategyBehavior
updateOverwrites name, country, investorType, walletAddress, and metadata on the existing record. Default.
skipLeaves the existing record untouched. Counted in result.skipped.

With on-chain verification

Set verifyOnChain: true to automatically batch-verify imported records that have both a walletAddress and a country. This runs after the database import completes and requires a configured relayer.
const result = await trusset.customers.sync.importRecords(records, {
  onConflict: 'update',
  verifyOnChain: true,
  verificationDefaults: {
    softExpiryDays: 365,
    hardExpiryDays: 730,
  },
})
On-chain verification failures do not roll back the database import. Failed verifications appear in result.errors with code VERIFY_FAILED.

Export records

Pull all customer data back out as flat SyncRecord objects. Useful for syncing Trusset state back into your core systems or for audit purposes.
const records = await trusset.customers.sync.exportRecords({
  includeArchived: false,
})

// records: SyncRecord[]
// Each record: { externalId, walletAddress?, name?, country?, investorType?, metadata? }
The method paginates internally - it fetches all records regardless of total count. For very large datasets (50k+ customers), consider using the list endpoint directly with pagination for more control.

SyncRecord schema

Every record requires externalId. All other fields are optional.
interface SyncRecord {
  externalId: string          // your system's unique customer ID
  walletAddress?: string      // Ethereum address
  name?: string               // display name
  country?: string            // ISO country code
  investorType?: 'RETAIL' | 'PROFESSIONAL' | 'ELIGIBLE_COUNTERPARTY'
  metadata?: Record<string, unknown>
}

Error handling

Import errors are collected per-record rather than failing the entire batch. The errors array in the result contains one entry per failed record:
const result = await trusset.customers.sync.importRecords(records)

for (const err of result.errors) {
  console.error(`Failed: ${err.externalId} - ${err.code}: ${err.message}`)
}
Common error codes:
CodeCause
INVALID_ADDRESSWallet address failed checksum validation
CUSTOMER_EXISTSDuplicate wallet address (different externalId)
VERIFY_FAILEDOn-chain batch verification failed for this entry
UNKNOWNUnexpected server error - check message for details