Add product matching service with DT implant catalog

- Add product catalog with current DT implants (X-Series, Flex, Bioresin)
- Implement chip-to-product matching algorithm
- Add DESFire EV level tracking with mismatch warnings
- Display compatible implants on ResultScreen with product details
- Remove discontinued products: xDF (EV1), xDF2 (EV2), flexDF (EV1)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
michael
2026-01-22 19:36:58 -08:00
parent fb7f836abd
commit 7596e4cbfa
5 changed files with 1085 additions and 5 deletions

571
src/data/products.ts Normal file
View File

@@ -0,0 +1,571 @@
/**
* Dangerous Things Product Catalog
*
* This contains the implant products available from Dangerous Things
* and their chip compatibility information.
*
* Updated based on https://dangerousthings.com/category/implants/
* Discontinued products removed per https://forum.dangerousthings.com/t/shes-dead-jim/26308
*/
import {ChipType} from '../types/detection';
import {
Product,
FormFactor,
ProductCategory,
ChipProductMap,
} from '../types/products';
/**
* Chip types that can be cloned to NTAG216-based implants
* Any NTAG21x data can be written to an NTAG216 (same NFC Type 2 protocol)
*/
const NTAG21X_COMPATIBLE: ChipType[] = [
ChipType.NTAG213,
ChipType.NTAG215,
ChipType.NTAG216,
];
/**
* NTAG I2C compatible chips
*/
const NTAG_I2C_COMPATIBLE: ChipType[] = [
ChipType.NTAG_I2C_1K,
ChipType.NTAG_I2C_2K,
ChipType.NTAG_I2C_PLUS_1K,
ChipType.NTAG_I2C_PLUS_2K,
];
/**
* MIFARE Classic compatible chips (for magic card cloning)
*/
const MIFARE_CLASSIC_COMPATIBLE: ChipType[] = [
ChipType.MIFARE_CLASSIC_1K,
ChipType.MIFARE_CLASSIC_4K,
ChipType.MIFARE_CLASSIC_MINI,
];
/**
* All DESFire chips - any DESFire product works with any DESFire chip
*/
const DESFIRE_ALL: ChipType[] = [
ChipType.DESFIRE_EV1,
ChipType.DESFIRE_EV2,
ChipType.DESFIRE_EV3,
];
/**
* ICODE SLIX compatible
*/
const SLIX_COMPATIBLE: ChipType[] = [
ChipType.SLIX,
ChipType.SLIX2,
ChipType.SLIX_S,
ChipType.SLIX_L,
];
export const PRODUCTS: Product[] = [
// ==========================================================================
// X-Series (Glass Capsule) Implants - NFC
// ==========================================================================
{
id: 'xnt',
name: 'xNT',
description:
'NFC Type 2 implant with 888 bytes of user memory. The original and most popular NFC implant.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.NFC],
compatibleChips: [...NTAG21X_COMPATIBLE, ...NTAG_I2C_COMPATIBLE],
features: [
'NTAG216 chip',
'888 bytes user memory',
'NFC Type 2 tag',
'URL/contact sharing',
],
url: 'https://dangerousthings.com/product/xnt/',
canReceiveClone: true,
exactMatch: true,
},
{
id: 'xsiid',
name: 'xSIID',
description:
'NFC implant with built-in LED that blinks when scanned. Multiple color options available.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.NFC, ProductCategory.LED],
compatibleChips: [...NTAG21X_COMPATIBLE, ...NTAG_I2C_COMPATIBLE],
features: [
'NTAG I2C chip',
'888 bytes user memory',
'Built-in LED indicator',
'Multiple colors available',
],
url: 'https://dangerousthings.com/product/xsiid/',
canReceiveClone: true,
exactMatch: true,
},
{
id: 'xslx',
name: 'xSLX',
description: 'ISO 15693 NFC-V implant using ICODE SLIX chip.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.NFC],
compatibleChips: [...SLIX_COMPATIBLE],
features: [
'ICODE SLIX chip',
'ISO 15693 (NFC-V)',
'Long range capability',
],
url: 'https://dangerousthings.com/product/xslx/',
canReceiveClone: true,
exactMatch: true,
},
// ==========================================================================
// X-Series - Dual Frequency (NFC + 125kHz)
// ==========================================================================
{
id: 'next',
name: 'NExT',
description:
'Original dual-frequency implant combining NTAG216 (NFC) with T5577 (125kHz).',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.DUAL_FREQUENCY, ProductCategory.ACCESS],
compatibleChips: [...NTAG21X_COMPATIBLE, ...NTAG_I2C_COMPATIBLE],
features: [
'NTAG216 NFC chip',
'T5577 125kHz chip',
'Dual-frequency capability',
'HID/EM compatible',
],
url: 'https://dangerousthings.com/product/next/',
canReceiveClone: true,
exactMatch: true,
notes: 'Also includes T5577 for 125kHz access systems',
},
{
id: 'next-v2',
name: 'NExT v2',
description:
'Updated dual-frequency implant with NTAG I2C, T5577, and built-in LED indicator.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.DUAL_FREQUENCY, ProductCategory.ACCESS, ProductCategory.LED],
compatibleChips: [...NTAG21X_COMPATIBLE, ...NTAG_I2C_COMPATIBLE],
features: [
'NTAG I2C NFC chip',
'T5577 125kHz chip',
'Built-in LED indicator',
'888 bytes user memory',
],
url: 'https://dangerousthings.com/product/next-v2/',
canReceiveClone: true,
exactMatch: true,
notes: 'Also includes T5577 for 125kHz access systems',
},
{
id: 'xmagic',
name: 'xMagic',
description:
'Dual-frequency implant with magic MIFARE Classic (changeable UID) and T5577.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.DUAL_FREQUENCY, ProductCategory.ACCESS],
compatibleChips: [...MIFARE_CLASSIC_COMPATIBLE],
features: [
'Magic MIFARE Classic chip',
'Changeable UID',
'T5577 125kHz chip',
'Clone access cards',
],
url: 'https://dangerousthings.com/product/xmagic/',
canReceiveClone: true,
exactMatch: false,
notes: 'Can clone MIFARE Classic cards (requires Android + keys)',
},
// ==========================================================================
// X-Series - DESFire (Secure NFC)
// Note: xDF (EV1) and xDF2 (EV2) discontinued - see flexDF/flexDF2 for those
// ==========================================================================
{
id: 'xdf3',
name: 'xDF3',
description: 'Latest generation secure NFC implant using MIFARE DESFire EV3.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.SECURE, ProductCategory.ACCESS],
compatibleChips: [...DESFIRE_ALL],
features: [
'DESFire EV3 chip',
'8KB memory',
'Latest security features',
'Transaction MAC',
],
url: 'https://dangerousthings.com/product/xdf3/',
canReceiveClone: false,
exactMatch: true,
notes: 'Cannot clone data due to cryptographic protection',
desfireEvLevel: 3,
},
// ==========================================================================
// X-Series - Magic/Cloning
// ==========================================================================
{
id: 'xm1',
name: 'xM1',
description: 'Magic MIFARE Classic 1K implant with changeable UID for cloning access cards.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.ACCESS],
compatibleChips: [...MIFARE_CLASSIC_COMPATIBLE],
features: [
'Magic MIFARE Classic 1K',
'Changeable UID',
'Clone access cards',
'Gen1a compatible',
],
url: 'https://dangerousthings.com/product/xm1/',
canReceiveClone: true,
exactMatch: false,
notes: 'Can clone MIFARE Classic 1K cards (requires Android + keys)',
},
// ==========================================================================
// X-Series - Cryptographic/Identity
// ==========================================================================
{
id: 'spark2',
name: 'VivoKey Spark 2',
description:
'Cryptobionic identity implant for secure authentication and digital identity.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.SECURE],
compatibleChips: [ChipType.NTAG424_DNA, ChipType.NTAG424_DNA_TT, ChipType.ICODE_DNA],
features: [
'Cryptographic authentication',
'VivoKey identity platform',
'Secure web login',
'Digital signatures',
],
url: 'https://dangerousthings.com/product/vivokey-spark-2/',
canReceiveClone: false,
exactMatch: true,
notes: 'Uses cryptographic authentication - cannot clone',
},
// ==========================================================================
// X-Series - LED/Special
// ==========================================================================
{
id: 'xglow',
name: 'xGlow',
description: 'Implant with LED that glows when exposed to NFC field.',
formFactor: FormFactor.X_SERIES,
categories: [ProductCategory.LED],
compatibleChips: [], // No NFC storage
features: [
'LED indicator',
'Multiple colors',
'Field detection',
],
url: 'https://dangerousthings.com/product/xglow/',
canReceiveClone: false,
exactMatch: false,
notes: 'LED only - no NFC data storage',
},
// ==========================================================================
// Bioresin Implants - Larger capsules (incision install)
// ==========================================================================
{
id: 'dnext',
name: 'dNExT',
description:
'Jumbo-sized bioresin dual-frequency implant with NTAG216 (NFC) and T5577 (125kHz). Enhanced read range.',
formFactor: FormFactor.BIORESIN,
categories: [ProductCategory.DUAL_FREQUENCY, ProductCategory.ACCESS],
compatibleChips: [...NTAG21X_COMPATIBLE, ...NTAG_I2C_COMPATIBLE],
features: [
'NTAG216 NFC chip',
'T5577 125kHz chip',
'Enhanced read range',
'Bioresin encapsulation',
],
url: 'https://dangerousthings.com/product/dnext/',
canReceiveClone: true,
exactMatch: true,
notes: 'Larger size provides improved performance over x-series',
},
{
id: 'dug4t',
name: 'dUG4T',
description:
'Bioresin dual-frequency implant with Ultimate Gen4 magic MIFARE and T5577 for maximum compatibility.',
formFactor: FormFactor.BIORESIN,
categories: [ProductCategory.DUAL_FREQUENCY, ProductCategory.ACCESS],
compatibleChips: [...MIFARE_CLASSIC_COMPATIBLE],
features: [
'Ultimate Gen4 magic chip',
'T5577 125kHz chip',
'Changeable UID',
'Enhanced cloning capability',
],
url: 'https://dangerousthings.com/product/dug4t/',
canReceiveClone: true,
exactMatch: false,
notes: 'Can clone MIFARE Classic cards (requires Android + keys)',
},
{
id: 'dt5',
name: 'dT5',
description:
'Bioresin 125kHz implant with T5577 chip for access control systems.',
formFactor: FormFactor.BIORESIN,
categories: [ProductCategory.ACCESS],
compatibleChips: [], // 125kHz only, no NFC
features: [
'T5577 125kHz chip',
'EM41xx emulation',
'HID ProxCard compatible',
'Bioresin encapsulation',
],
url: 'https://dangerousthings.com/product/dt5/',
canReceiveClone: false,
exactMatch: false,
notes: '125kHz only - no NFC capability',
},
// ==========================================================================
// Flex Implants - NFC
// ==========================================================================
{
id: 'flexnt',
name: 'flexNT',
description:
'Flexible NTAG216 implant with larger antenna for improved read range.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.NFC],
compatibleChips: [...NTAG21X_COMPATIBLE, ...NTAG_I2C_COMPATIBLE],
features: [
'NTAG216 chip',
'888 bytes user memory',
'Flexible form factor',
'Extended read range',
],
url: 'https://dangerousthings.com/product/flexnt/',
canReceiveClone: true,
exactMatch: true,
},
// ==========================================================================
// Flex Implants - DESFire (Secure)
// Note: flexDF (EV1) discontinued - flexDF2 is current
// ==========================================================================
{
id: 'flexdf2',
name: 'flexDF2',
description: 'Flexible DESFire EV2 implant with enhanced security.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.SECURE, ProductCategory.ACCESS],
compatibleChips: [...DESFIRE_ALL],
features: [
'DESFire EV2 chip',
'8KB memory',
'AES-128 encryption',
'Flexible form factor',
],
url: 'https://dangerousthings.com/product/flexdf2/',
canReceiveClone: false,
exactMatch: true,
notes: 'Cannot clone data due to cryptographic protection',
desfireEvLevel: 2,
},
// ==========================================================================
// Flex Implants - Magic/Cloning
// ==========================================================================
{
id: 'flexm1',
name: 'flexM1',
description: 'Flexible magic MIFARE Classic 1K implant for cloning access cards.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.ACCESS],
compatibleChips: [...MIFARE_CLASSIC_COMPATIBLE],
features: [
'Magic MIFARE Classic 1K',
'Changeable UID',
'Flexible form factor',
'Extended read range',
],
url: 'https://dangerousthings.com/product/flexm1/',
canReceiveClone: true,
exactMatch: false,
notes: 'Can clone MIFARE Classic 1K cards (requires Android + keys)',
},
{
id: 'flexm1-v2',
name: 'flexM1 v2',
description: 'Updated flexible magic MIFARE Classic 1K implant.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.ACCESS],
compatibleChips: [...MIFARE_CLASSIC_COMPATIBLE],
features: [
'Magic MIFARE Classic 1K',
'Improved antenna design',
'Changeable UID',
'Better compatibility',
],
url: 'https://dangerousthings.com/product/flexm1-v2/',
canReceiveClone: true,
exactMatch: false,
notes: 'Can clone MIFARE Classic 1K cards (requires Android + keys)',
},
// ==========================================================================
// Flex Implants - Secure Element / JavaCard
// ==========================================================================
{
id: 'apex-flex',
name: 'Apex Flex',
description:
'The ultimate subdermal security key for digital identity, cryptography, and blockchain applications.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.SECURE],
compatibleChips: [ChipType.JCOP4, ChipType.JAVACARD_UNKNOWN],
features: [
'JCOP4 secure element',
'Fidesmo platform',
'Payment capable',
'FIDO2/WebAuthn',
'OTP support',
],
url: 'https://dangerousthings.com/product/apex-flex/',
canReceiveClone: false,
exactMatch: true,
notes: 'Cannot clone - programmable via Fidesmo app',
},
{
id: 'flexsecure',
name: 'flexSecure',
description:
'Developer-friendly JavaCard implant for custom secure applications.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.SECURE],
compatibleChips: [ChipType.JCOP4, ChipType.JAVACARD_UNKNOWN],
features: [
'SmartMX3 P71 chip',
'Full JavaCard access',
'GlobalPlatformPro compatible',
'Custom applet support',
],
url: 'https://dangerousthings.com/product/flexsecure/',
canReceiveClone: false,
exactMatch: true,
notes: 'Developer-focused - requires technical knowledge',
},
// ==========================================================================
// Flex Implants - Access Control
// ==========================================================================
{
id: 'flexclass',
name: 'flexClass',
description: 'Flexible HID iCLASS compatible implant for enterprise access control.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.SECURE, ProductCategory.ACCESS],
compatibleChips: [], // iCLASS uses proprietary protocol
features: [
'HID iCLASS SE compatible',
'Enterprise access control',
'Flexible form factor',
],
url: 'https://dangerousthings.com/product/flexclass/',
canReceiveClone: false,
exactMatch: false,
notes: 'For HID iCLASS systems only',
},
{
id: 'teslaflex',
name: 'TeslaFlex',
description: 'Implant designed to work as a Tesla key card.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.ACCESS],
compatibleChips: [], // Tesla proprietary
features: [
'Tesla key card compatible',
'Flexible form factor',
'Direct Tesla integration',
],
url: 'https://dangerousthings.com/product/teslaflex/',
canReceiveClone: false,
exactMatch: false,
notes: 'Specifically for Tesla vehicles',
},
{
id: 'flexug4',
name: 'flexUG4',
description: 'Flexible Ultimate Gen4 magic MIFARE implant for cloning access cards.',
formFactor: FormFactor.FLEX,
categories: [ProductCategory.ACCESS],
compatibleChips: [...MIFARE_CLASSIC_COMPATIBLE],
features: [
'Ultimate Gen4 magic chip',
'Changeable UID',
'Flexible form factor',
'Enhanced cloning capability',
],
url: 'https://dangerousthings.com/product/flexug4/',
canReceiveClone: true,
exactMatch: false,
notes: 'Can clone MIFARE Classic cards (requires Android + keys)',
},
];
/**
* Build a map of chip types to compatible products
*/
export function buildChipProductMap(): ChipProductMap {
const map: ChipProductMap = new Map();
for (const product of PRODUCTS) {
for (const chipType of product.compatibleChips) {
const existing = map.get(chipType) || [];
existing.push(product);
map.set(chipType, existing);
}
}
return map;
}
/**
* Cached chip-to-product map
*/
let chipProductMapCache: ChipProductMap | null = null;
/**
* Get the chip-to-product map (cached)
*/
export function getChipProductMap(): ChipProductMap {
if (!chipProductMapCache) {
chipProductMapCache = buildChipProductMap();
}
return chipProductMapCache;
}
/**
* Conversion service URL for chips that don't have direct matches
*/
export const CONVERSION_SERVICE_URL = 'https://dngr.us/conversion';
/**
* Get all products
*/
export function getAllProducts(): Product[] {
return PRODUCTS;
}
/**
* Get product by ID
*/
export function getProductById(id: string): Product | undefined {
return PRODUCTS.find(p => p.id === id);
}

View File

@@ -1,14 +1,26 @@
import React from 'react';
import React, {useMemo} from 'react';
import {StyleSheet, View, ScrollView, Linking} from 'react-native';
import {Button, Text, Surface, Divider, Chip} from 'react-native-paper';
import type {ResultScreenProps} from '../types/navigation';
import {DTColors} from '../theme';
import {matchChipToProducts, getMatchSummary, getDesfireEvMismatchWarning} from '../services/matching';
import {Product} from '../types/products';
export function ResultScreen({route, navigation}: ResultScreenProps) {
const {tagData, transponder} = route.params;
// Match chip to products
const matchResult = useMemo(() => {
if (!transponder) return null;
return matchChipToProducts(transponder.type);
}, [transponder]);
const handleConversionLink = () => {
Linking.openURL('https://dngr.us/conversion');
Linking.openURL(matchResult?.conversionUrl || 'https://dngr.us/conversion');
};
const handleProductLink = (product: Product) => {
Linking.openURL(product.url);
};
// Determine card colors based on detection
@@ -87,6 +99,99 @@ export function ResultScreen({route, navigation}: ResultScreenProps) {
</Surface>
)}
{/* Product Matches Card */}
{transponder && matchResult && (matchResult.exactMatches.length > 0 || matchResult.cloneTargets.length > 0) && (
<Surface style={styles.productsCard} elevation={1}>
<Text variant="labelLarge" style={styles.productsLabel}>
COMPATIBLE IMPLANTS
</Text>
<Divider style={[styles.divider, {backgroundColor: DTColors.modeEmphasis}]} />
<Text variant="bodyMedium" style={styles.matchSummary}>
{getMatchSummary(matchResult, transponder.chipName)}
</Text>
{/* Exact Matches / Clone Targets */}
{[...matchResult.exactMatches, ...matchResult.cloneTargets.filter(
p => !matchResult.exactMatches.find(e => e.id === p.id)
)].map(product => (
<Surface key={product.id} style={styles.productItem} elevation={0}>
<View style={styles.productHeader}>
<Text variant="titleMedium" style={styles.productName}>
{product.name}
</Text>
<Chip
style={styles.formFactorChip}
textStyle={styles.formFactorChipText}>
{product.formFactor.replace('_', ' ')}
</Chip>
</View>
<Text variant="bodySmall" style={styles.productDescription}>
{product.description}
</Text>
{product.notes && (
<Text variant="bodySmall" style={styles.productNote}>
Note: {product.notes}
</Text>
)}
{/* DESFire EV mismatch warning */}
{getDesfireEvMismatchWarning(transponder.type, product) && (
<Text variant="bodySmall" style={styles.evMismatchWarning}>
{getDesfireEvMismatchWarning(transponder.type, product)}
</Text>
)}
<View style={styles.productFeatures}>
{product.features.slice(0, 3).map((feature, idx) => (
<Text key={idx} variant="bodySmall" style={styles.productFeature}>
{feature}
</Text>
))}
</View>
<Button
mode="outlined"
onPress={() => handleProductLink(product)}
style={styles.productButton}
labelStyle={styles.productButtonLabel}
compact>
VIEW PRODUCT
</Button>
</Surface>
))}
</Surface>
)}
{/* No Match Card - show when chip detected but no products match */}
{transponder && matchResult && matchResult.exactMatches.length === 0 && matchResult.cloneTargets.length === 0 && (
<Surface style={styles.noMatchCard} elevation={1}>
<Text variant="labelLarge" style={styles.noMatchLabel}>
NO DIRECT MATCH
</Text>
<Divider style={[styles.divider, {backgroundColor: DTColors.modeOther}]} />
<Text variant="bodyMedium" style={styles.noMatchText}>
{getMatchSummary(matchResult, transponder.chipName)}
</Text>
{matchResult.familyMatches.length > 0 && (
<>
<Text variant="bodySmall" style={styles.familyMatchesLabel}>
Related products in the same chip family:
</Text>
{matchResult.familyMatches.slice(0, 2).map(product => (
<Text key={product.id} variant="bodySmall" style={styles.familyMatchItem}>
{product.name}
</Text>
))}
</>
)}
</Surface>
)}
{/* SAK Swap Detection Card */}
{transponder?.sakSwapInfo?.hasSakSwap && (
<Surface style={styles.sakSwapCard} elevation={1}>
@@ -195,11 +300,15 @@ export function ResultScreen({route, navigation}: ResultScreenProps) {
</Surface>
)}
{/* Conversion Service Card - only show if chip is NOT cloneable */}
{(!transponder || !transponder.isCloneable) && (
{/* Conversion Service Card - show when recommended */}
{(matchResult?.conversionRecommended || !transponder) && (
<Surface style={styles.conversionCard} elevation={1}>
<Text variant="bodyMedium" style={styles.conversionText}>
Can't clone this chip? Check out our conversion service.
{!transponder
? 'Unknown chip? Our conversion service can help.'
: matchResult?.isCloneable === false
? "This chip uses cryptographic protection and can't be cloned. Our conversion service can help find alternatives."
: "No direct product match found. Our conversion service can help."}
</Text>
<Button
mode="outlined"
@@ -387,6 +496,113 @@ const styles = StyleSheet.create({
color: DTColors.light,
opacity: 0.8,
},
// Products Card
productsCard: {
backgroundColor: '#0a0a0a',
borderRadius: 4,
borderWidth: 2,
borderColor: DTColors.modeEmphasis,
padding: 20,
marginBottom: 20,
},
productsLabel: {
color: DTColors.modeEmphasis,
letterSpacing: 2,
marginBottom: 12,
},
matchSummary: {
color: DTColors.light,
marginBottom: 16,
},
productItem: {
backgroundColor: '#111111',
borderRadius: 4,
borderWidth: 1,
borderColor: DTColors.modeNormal,
padding: 16,
marginBottom: 12,
},
productHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
},
productName: {
color: DTColors.modeEmphasis,
fontWeight: 'bold',
},
formFactorChip: {
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: DTColors.modeNormal,
height: 24,
},
formFactorChipText: {
color: DTColors.modeNormal,
fontSize: 10,
},
productDescription: {
color: DTColors.light,
opacity: 0.8,
marginBottom: 8,
},
productNote: {
color: DTColors.modeOther,
fontStyle: 'italic',
marginBottom: 8,
},
evMismatchWarning: {
color: DTColors.modeEmphasis,
backgroundColor: 'rgba(255, 255, 0, 0.1)',
padding: 8,
borderRadius: 4,
marginBottom: 8,
},
productFeatures: {
marginBottom: 12,
},
productFeature: {
color: DTColors.light,
opacity: 0.7,
marginBottom: 2,
},
productButton: {
borderColor: DTColors.modeEmphasis,
borderWidth: 1,
},
productButtonLabel: {
color: DTColors.modeEmphasis,
fontSize: 12,
},
// No Match Card
noMatchCard: {
backgroundColor: '#0a0a0a',
borderRadius: 4,
borderWidth: 1,
borderColor: DTColors.modeOther,
padding: 20,
marginBottom: 20,
},
noMatchLabel: {
color: DTColors.modeOther,
letterSpacing: 2,
marginBottom: 12,
},
noMatchText: {
color: DTColors.light,
opacity: 0.8,
marginBottom: 12,
},
familyMatchesLabel: {
color: DTColors.light,
opacity: 0.6,
marginBottom: 8,
},
familyMatchItem: {
color: DTColors.modeNormal,
marginBottom: 4,
},
// Conversion Card
conversionCard: {
backgroundColor: '#0a0a0a',

View File

@@ -0,0 +1,14 @@
/**
* Product Matching Service
*/
export {
matchChipToProducts,
getMatchSummary,
getRecommendedAction,
formatProductFeatures,
getCloneTargetsForChip,
canCloneToProduct,
getDesfireEvLevel,
getDesfireEvMismatchWarning,
} from './matcher';

View File

@@ -0,0 +1,201 @@
/**
* Product Matching Service
*
* Matches detected NFC chips to compatible Dangerous Things products
*/
import {ChipType, getChipFamily, CHIP_CLONEABILITY, ChipFamily} from '../../types/detection';
import {MatchResult, Product, DesfireEvLevel} from '../../types/products';
import {
PRODUCTS,
getChipProductMap,
CONVERSION_SERVICE_URL,
} from '../../data/products';
/**
* Match a detected chip to compatible products
*/
export function matchChipToProducts(chipType: ChipType): MatchResult {
const chipProductMap = getChipProductMap();
const cloneability = CHIP_CLONEABILITY[chipType];
const chipFamily = getChipFamily(chipType);
// Get products that directly support this chip
const directMatches = chipProductMap.get(chipType) || [];
// Separate exact matches from clone targets
const exactMatches: Product[] = [];
const cloneTargets: Product[] = [];
for (const product of directMatches) {
if (product.exactMatch) {
exactMatches.push(product);
}
if (product.canReceiveClone && cloneability?.cloneable) {
cloneTargets.push(product);
}
}
// Find products in the same chip family
const familyMatches = findFamilyMatches(chipType, chipFamily, directMatches);
// Determine if conversion is recommended
// Conversion is recommended when:
// 1. No exact matches AND no clone targets
// 2. Chip is not cloneable (crypto protection)
const hasMatches = exactMatches.length > 0 || cloneTargets.length > 0;
const conversionRecommended = !hasMatches || !cloneability?.cloneable;
return {
exactMatches,
cloneTargets,
familyMatches,
isCloneable: cloneability?.cloneable ?? false,
cloneabilityNote: cloneability?.note,
conversionRecommended,
conversionUrl: CONVERSION_SERVICE_URL,
};
}
/**
* Find products in the same chip family that might be of interest
*/
function findFamilyMatches(
chipType: ChipType,
chipFamily: ChipFamily,
excludeProducts: Product[],
): Product[] {
const excludeIds = new Set(excludeProducts.map(p => p.id));
const familyMatches: Product[] = [];
for (const product of PRODUCTS) {
// Skip already matched products
if (excludeIds.has(product.id)) {
continue;
}
// Check if any of the product's compatible chips are in the same family
const productChipFamilies = product.compatibleChips.map(getChipFamily);
if (productChipFamilies.includes(chipFamily)) {
familyMatches.push(product);
}
}
return familyMatches;
}
/**
* Get a summary message for the match result
*/
export function getMatchSummary(result: MatchResult, chipName: string): string {
if (result.exactMatches.length > 0) {
const names = result.exactMatches.map(p => p.name).join(', ');
return `Your ${chipName} is compatible with: ${names}`;
}
if (result.cloneTargets.length > 0) {
const names = result.cloneTargets.map(p => p.name).join(', ');
return `Your ${chipName} data can be cloned to: ${names}`;
}
if (!result.isCloneable) {
return `${chipName} uses cryptographic protection and cannot be cloned. Consider our conversion service for compatible options.`;
}
return `No direct product match found for ${chipName}. Check our conversion service for options.`;
}
/**
* Get recommended action based on match result
*/
export function getRecommendedAction(
result: MatchResult,
): 'purchase' | 'clone' | 'conversion' | 'contact' {
if (result.exactMatches.length > 0) {
return 'purchase';
}
if (result.cloneTargets.length > 0 && result.isCloneable) {
return 'clone';
}
if (result.conversionRecommended) {
return 'conversion';
}
return 'contact';
}
/**
* Format product features for display
*/
export function formatProductFeatures(product: Product): string[] {
return product.features;
}
/**
* Get products that can receive cloned data from a chip type
*/
export function getCloneTargetsForChip(chipType: ChipType): Product[] {
const cloneability = CHIP_CLONEABILITY[chipType];
if (!cloneability?.cloneable) {
return [];
}
const chipProductMap = getChipProductMap();
const directMatches = chipProductMap.get(chipType) || [];
return directMatches.filter(p => p.canReceiveClone);
}
/**
* Check if a chip can be cloned to any product
*/
export function canCloneToProduct(chipType: ChipType): boolean {
return getCloneTargetsForChip(chipType).length > 0;
}
/**
* Get DESFire EV level from chip type
*/
export function getDesfireEvLevel(chipType: ChipType): DesfireEvLevel | null {
switch (chipType) {
case ChipType.DESFIRE_EV1:
return 1;
case ChipType.DESFIRE_EV2:
return 2;
case ChipType.DESFIRE_EV3:
return 3;
default:
return null;
}
}
/**
* Check if there's a DESFire EV mismatch between chip and product
* Returns warning message if mismatch, null if no issue
*/
export function getDesfireEvMismatchWarning(
chipType: ChipType,
product: Product,
): string | null {
const chipEvLevel = getDesfireEvLevel(chipType);
const productEvLevel = product.desfireEvLevel;
// Not a DESFire chip or product doesn't have EV level
if (chipEvLevel === null || productEvLevel === undefined) {
return null;
}
// Perfect match
if (chipEvLevel === productEvLevel) {
return null;
}
// Mismatch - warn user
if (chipEvLevel < productEvLevel) {
return `Your card uses DESFire EV${chipEvLevel}, but this implant uses EV${productEvLevel}. Some newer features may not be compatible with your existing system.`;
} else {
return `Your card uses DESFire EV${chipEvLevel}, but this implant uses EV${productEvLevel}. This should work, but you won't have access to EV${chipEvLevel} features.`;
}
}

78
src/types/products.ts Normal file
View File

@@ -0,0 +1,78 @@
/**
* Product Types for Dangerous Things Implants
*/
import {ChipType} from './detection';
/**
* Product form factor
*/
export enum FormFactor {
X_SERIES = 'X_SERIES', // 2x12mm injectable capsule (glass or bioresin)
FLEX = 'FLEX', // Flexible PCB implant (incision install)
BIORESIN = 'BIORESIN', // Larger bioresin capsule (incision install)
CARD = 'CARD', // ISO card format
}
/**
* Product category
*/
export enum ProductCategory {
NFC = 'NFC', // NFC-only implants
DUAL_FREQUENCY = 'DUAL_FREQUENCY', // NFC + 125kHz
SECURE = 'SECURE', // Cryptographic/secure elements
LED = 'LED', // Implants with LED indicators
ACCESS = 'ACCESS', // Access control focused
}
/**
* DESFire EV level for version matching
*/
export type DesfireEvLevel = 1 | 2 | 3;
/**
* A Dangerous Things product
*/
export interface Product {
id: string;
name: string;
description: string;
formFactor: FormFactor;
categories: ProductCategory[];
compatibleChips: ChipType[];
features: string[];
url: string;
/** Whether this product can have data cloned TO it from the scanned chip */
canReceiveClone: boolean;
/** Whether this product uses the same chip type as scanned */
exactMatch: boolean;
/** Notes about compatibility or limitations */
notes?: string;
/** DESFire EV level (1, 2, or 3) for version mismatch warnings */
desfireEvLevel?: DesfireEvLevel;
}
/**
* Result of product matching
*/
export interface MatchResult {
/** Products that use the exact same chip */
exactMatches: Product[];
/** Products that can receive cloned data from this chip */
cloneTargets: Product[];
/** Products in the same chip family */
familyMatches: Product[];
/** Is this chip cloneable at all? */
isCloneable: boolean;
/** Note about cloneability */
cloneabilityNote?: string;
/** Conversion service recommendation */
conversionRecommended: boolean;
/** Conversion URL */
conversionUrl: string;
}
/**
* Chip to product mapping for quick lookup
*/
export type ChipProductMap = Map<ChipType, Product[]>;