@ukeyfe/react-native-nfc-litecard 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/reader.js CHANGED
@@ -46,18 +46,20 @@ var __importStar = (this && this.__importStar) || (function () {
46
46
  };
47
47
  })();
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.DEFAULT_PIN_RETRY_COUNT = exports.clearNfcOperationCancelledByCleanup = exports.getNfcOperationCancelledByCleanupTimestamp = exports.consumeNfcOperationCancelledByCleanup = exports.markNfcOperationCancelledByCleanup = exports.releaseNfcOperationLock = exports.isNfcOperationLocked = exports.ResultCode = void 0;
49
+ exports.DEFAULT_PIN_RETRY_COUNT = exports.clearNfcOperationCancelledByCleanup = exports.getNfcOperationCancelledByCleanupTimestamp = exports.consumeNfcOperationCancelledByCleanup = exports.markNfcOperationCancelledByCleanup = exports.releaseNfcOperationLock = exports.isNfcOperationLocked = exports.NfcStatusCode = void 0;
50
50
  exports.cardInfoToJson = cardInfoToJson;
51
51
  exports.checkCard = checkCard;
52
52
  exports.readMnemonic = readMnemonic;
53
53
  exports.readUserNickname = readUserNickname;
54
54
  exports.readMnemonicRetryCount = readMnemonicRetryCount;
55
55
  exports.resetRetryCountTo10 = resetRetryCountTo10;
56
+ exports.getCardVersion = getCardVersion;
57
+ exports.readOriginality = readOriginality;
56
58
  const bip39 = __importStar(require("bip39"));
57
59
  const constants_1 = require("./constants");
58
60
  Object.defineProperty(exports, "DEFAULT_PIN_RETRY_COUNT", { enumerable: true, get: function () { return constants_1.DEFAULT_PIN_RETRY_COUNT; } });
59
61
  const types_1 = require("./types");
60
- Object.defineProperty(exports, "ResultCode", { enumerable: true, get: function () { return types_1.ResultCode; } });
62
+ Object.defineProperty(exports, "NfcStatusCode", { enumerable: true, get: function () { return types_1.NfcStatusCode; } });
61
63
  const utils_1 = require("./utils");
62
64
  const crypto_1 = require("./crypto");
63
65
  const nfc_core_1 = require("./nfc-core");
@@ -72,13 +74,6 @@ Object.defineProperty(exports, "clearNfcOperationCancelledByCleanup", { enumerab
72
74
  // ===========================================================================
73
75
  // Internal read helpers
74
76
  // ===========================================================================
75
- /** FAST_READ pages 0x08–0x27 (user memory). */
76
- async function readUserMemory() {
77
- const response = await (0, nfc_core_1.transceive)([constants_1.CMD_FAST_READ, constants_1.USER_PAGE_START, constants_1.USER_PAGE_END]);
78
- if (!response || response.length < constants_1.USER_MEMORY_SIZE)
79
- throw new Error('READ_FAILED');
80
- return new Uint8Array(response.slice(0, constants_1.USER_MEMORY_SIZE));
81
- }
82
77
  /** FAST_READ pages 0x04–0x07 (card info area). */
83
78
  async function readUserCardInfo() {
84
79
  const response = await (0, nfc_core_1.transceive)([constants_1.CMD_FAST_READ, constants_1.USER_CARD_INFO_PAGE_START, constants_1.USER_CARD_INFO_PAGE_END]);
@@ -125,32 +120,7 @@ function entropyToMnemonic(data) {
125
120
  throw new Error('INVALID_CARD_DATA');
126
121
  if (data.every(b => b === 0))
127
122
  throw new Error('EMPTY_CARD');
128
- const typeId = data[0];
129
- let entropyLength;
130
- let typeStr;
131
- switch (typeId) {
132
- case constants_1.MNEMONIC_TYPE_12:
133
- entropyLength = 16;
134
- typeStr = '12 words (128-bit)';
135
- break;
136
- case constants_1.MNEMONIC_TYPE_15:
137
- entropyLength = 20;
138
- typeStr = '15 words (160-bit)';
139
- break;
140
- case constants_1.MNEMONIC_TYPE_18:
141
- entropyLength = 24;
142
- typeStr = '18 words (192-bit)';
143
- break;
144
- case constants_1.MNEMONIC_TYPE_21:
145
- entropyLength = 28;
146
- typeStr = '21 words (224-bit)';
147
- break;
148
- case constants_1.MNEMONIC_TYPE_24:
149
- entropyLength = 32;
150
- typeStr = '24 words (256-bit)';
151
- break;
152
- default: throw new Error('INVALID_CARD_DATA');
153
- }
123
+ const { entropyLength, description } = (0, utils_1.getMnemonicTypeInfo)(data[0]);
154
124
  const expectedTotal = 1 + entropyLength + 2;
155
125
  if (data.length < expectedTotal)
156
126
  throw new Error('INVALID_CARD_DATA');
@@ -163,7 +133,7 @@ function entropyToMnemonic(data) {
163
133
  const entropyHex = (0, utils_1.bytesToHex)(Array.from(entropyBytes));
164
134
  const rawBytes = (0, utils_1.bytesToHex)(Array.from(dataBlock));
165
135
  const mnemonic = bip39.entropyToMnemonic(entropyHex);
166
- return { mnemonic, entropyHex, type: typeStr, rawBytes, crc16: calcCRC };
136
+ return { mnemonic, entropyHex, type: description, rawBytes, crc16: calcCRC };
167
137
  }
168
138
  // ===========================================================================
169
139
  // Card info parsing
@@ -243,7 +213,7 @@ async function checkCard(password, onCardIdentified) {
243
213
  await (0, nfc_core_1.acquireNfcLock)();
244
214
  }
245
215
  catch {
246
- return { code: types_1.ResultCode.UNKNOWN_ERROR, success: false };
216
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
247
217
  }
248
218
  try {
249
219
  try {
@@ -251,25 +221,41 @@ async function checkCard(password, onCardIdentified) {
251
221
  }
252
222
  catch {
253
223
  (0, nfc_core_1.releaseNfcLock)();
254
- return { code: types_1.ResultCode.NFC_CONNECT_FAILED, success: false };
224
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
255
225
  }
256
226
  try {
257
227
  if (password) {
258
- // Authenticated check: authenticate → read full memory → validate CRC16
228
+ // Authenticated check: decrement retry → authenticate → read → validate CRC16
229
+ try {
230
+ await (0, nfc_core_1.decrementRetryCountInSession)();
231
+ }
232
+ catch (error) {
233
+ const code = (0, types_1.errorToCode)(error);
234
+ if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
235
+ await (0, nfc_core_1.releaseNfcTech)();
236
+ (0, nfc_core_1.releaseNfcLock)();
237
+ return (0, types_1.nfcResultRetryCountExhausted)();
238
+ }
239
+ }
259
240
  const aesKey = (0, crypto_1.passwordToAesKey)(password);
260
241
  await (0, nfc_core_1.authenticate)(aesKey);
242
+ // Auth succeeded – reset retry counter
243
+ try {
244
+ await (0, nfc_core_1.writeRetryCountInSession)(constants_1.DEFAULT_PIN_RETRY_COUNT);
245
+ }
246
+ catch { /* non-fatal */ }
261
247
  onCardIdentified?.();
262
- const data = await readUserMemory();
248
+ const data = await (0, nfc_core_1.readUserMemory)();
263
249
  try {
264
250
  const decoded = (0, utils_1.validateMnemonicPayload)(data);
265
251
  await (0, nfc_core_1.releaseNfcTech)();
266
252
  (0, nfc_core_1.releaseNfcLock)();
267
- return { code: types_1.ResultCode.CHECK_HAS_DATA, success: true, data: { type: decoded.type } };
253
+ return { code: types_1.NfcStatusCode.CHECK_HAS_DATA, success: true, data: { type: decoded.type } };
268
254
  }
269
255
  catch {
270
256
  await (0, nfc_core_1.releaseNfcTech)();
271
257
  (0, nfc_core_1.releaseNfcLock)();
272
- return { code: types_1.ResultCode.CHECK_EMPTY, success: true };
258
+ return { code: types_1.NfcStatusCode.CHECK_EMPTY, success: true };
273
259
  }
274
260
  }
275
261
  else {
@@ -283,16 +269,16 @@ async function checkCard(password, onCardIdentified) {
283
269
  await (0, nfc_core_1.releaseNfcTech)();
284
270
  (0, nfc_core_1.releaseNfcLock)();
285
271
  if (response && response.length >= 4) {
286
- const first = response[0];
287
- const hasData = first === constants_1.MNEMONIC_TYPE_12 ||
288
- first === constants_1.MNEMONIC_TYPE_15 ||
289
- first === constants_1.MNEMONIC_TYPE_18 ||
290
- first === constants_1.MNEMONIC_TYPE_21 ||
291
- first === constants_1.MNEMONIC_TYPE_24;
292
- return { code: hasData ? types_1.ResultCode.CHECK_HAS_DATA : types_1.ResultCode.CHECK_EMPTY, success: true };
272
+ let hasData = false;
273
+ try {
274
+ (0, utils_1.getMnemonicTypeInfo)(response[0]);
275
+ hasData = true;
276
+ }
277
+ catch { /* not a valid type */ }
278
+ return { code: hasData ? types_1.NfcStatusCode.CHECK_HAS_DATA : types_1.NfcStatusCode.CHECK_EMPTY, success: true };
293
279
  }
294
280
  // Read failed = protection is on, assume has data
295
- return { code: types_1.ResultCode.CHECK_HAS_DATA, success: true };
281
+ return { code: types_1.NfcStatusCode.CHECK_HAS_DATA, success: true };
296
282
  }
297
283
  }
298
284
  catch (error) {
@@ -318,7 +304,7 @@ async function readMnemonic(password, onCardIdentified) {
318
304
  await (0, nfc_core_1.acquireNfcLock)();
319
305
  }
320
306
  catch {
321
- return { code: types_1.ResultCode.UNKNOWN_ERROR, success: false };
307
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
322
308
  }
323
309
  let retryCountAfterPreDecrement;
324
310
  try {
@@ -327,7 +313,7 @@ async function readMnemonic(password, onCardIdentified) {
327
313
  }
328
314
  catch {
329
315
  (0, nfc_core_1.releaseNfcLock)();
330
- return { code: types_1.ResultCode.NFC_CONNECT_FAILED, success: false };
316
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
331
317
  }
332
318
  try {
333
319
  // Pre-decrement retry counter before auth attempt
@@ -338,7 +324,7 @@ async function readMnemonic(password, onCardIdentified) {
338
324
  }
339
325
  catch (error) {
340
326
  const code = (0, types_1.errorToCode)(error);
341
- if (code === types_1.ResultCode.RETRY_COUNT_EXHAUSTED) {
327
+ if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
342
328
  await (0, nfc_core_1.releaseNfcTech)();
343
329
  (0, nfc_core_1.releaseNfcLock)();
344
330
  return (0, types_1.nfcResultRetryCountExhausted)();
@@ -347,8 +333,7 @@ async function readMnemonic(password, onCardIdentified) {
347
333
  const aesKey = (0, crypto_1.passwordToAesKey)(password);
348
334
  await (0, nfc_core_1.authenticate)(aesKey);
349
335
  onCardIdentified?.();
350
- const data = await readUserMemory();
351
- await readUserCardInfo(); // read but not used directly yet
336
+ const data = await (0, nfc_core_1.readUserMemory)();
352
337
  const result = entropyToMnemonic(data);
353
338
  let nickname;
354
339
  try {
@@ -365,7 +350,7 @@ async function readMnemonic(password, onCardIdentified) {
365
350
  await (0, nfc_core_1.releaseNfcTech)();
366
351
  (0, nfc_core_1.releaseNfcLock)();
367
352
  return {
368
- code: types_1.ResultCode.READ_SUCCESS,
353
+ code: types_1.NfcStatusCode.READ_SUCCESS,
369
354
  success: true,
370
355
  data: {
371
356
  mnemonic: result.mnemonic,
@@ -405,7 +390,7 @@ async function readUserNickname(password, onCardIdentified) {
405
390
  await (0, nfc_core_1.acquireNfcLock)();
406
391
  }
407
392
  catch {
408
- return { code: types_1.ResultCode.UNKNOWN_ERROR, success: false };
393
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
409
394
  }
410
395
  try {
411
396
  try {
@@ -413,7 +398,7 @@ async function readUserNickname(password, onCardIdentified) {
413
398
  }
414
399
  catch {
415
400
  (0, nfc_core_1.releaseNfcLock)();
416
- return { code: types_1.ResultCode.NFC_CONNECT_FAILED, success: false };
401
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
417
402
  }
418
403
  try {
419
404
  if (password) {
@@ -425,7 +410,7 @@ async function readUserNickname(password, onCardIdentified) {
425
410
  await (0, nfc_core_1.releaseNfcTech)();
426
411
  (0, nfc_core_1.releaseNfcLock)();
427
412
  return {
428
- code: types_1.ResultCode.READ_NICKNAME_SUCCESS,
413
+ code: types_1.NfcStatusCode.READ_NICKNAME_SUCCESS,
429
414
  success: true,
430
415
  data: { nickname },
431
416
  };
@@ -448,7 +433,7 @@ async function readMnemonicRetryCount(onCardIdentified) {
448
433
  await (0, nfc_core_1.acquireNfcLock)();
449
434
  }
450
435
  catch {
451
- return { code: types_1.ResultCode.UNKNOWN_ERROR, success: false };
436
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
452
437
  }
453
438
  try {
454
439
  try {
@@ -456,7 +441,7 @@ async function readMnemonicRetryCount(onCardIdentified) {
456
441
  }
457
442
  catch {
458
443
  (0, nfc_core_1.releaseNfcLock)();
459
- return { code: types_1.ResultCode.NFC_CONNECT_FAILED, success: false };
444
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
460
445
  }
461
446
  try {
462
447
  onCardIdentified?.();
@@ -465,7 +450,7 @@ async function readMnemonicRetryCount(onCardIdentified) {
465
450
  await (0, nfc_core_1.releaseNfcTech)();
466
451
  (0, nfc_core_1.releaseNfcLock)();
467
452
  return {
468
- code: types_1.ResultCode.READ_RETRY_COUNT_SUCCESS,
453
+ code: types_1.NfcStatusCode.READ_RETRY_COUNT_SUCCESS,
469
454
  success: true,
470
455
  data: { retryCount: 0 },
471
456
  };
@@ -474,7 +459,7 @@ async function readMnemonicRetryCount(onCardIdentified) {
474
459
  await (0, nfc_core_1.releaseNfcTech)();
475
460
  (0, nfc_core_1.releaseNfcLock)();
476
461
  return {
477
- code: types_1.ResultCode.READ_RETRY_COUNT_SUCCESS,
462
+ code: types_1.NfcStatusCode.READ_RETRY_COUNT_SUCCESS,
478
463
  success: true,
479
464
  data: { retryCount },
480
465
  };
@@ -497,7 +482,7 @@ async function resetRetryCountTo10(onCardIdentified) {
497
482
  await (0, nfc_core_1.acquireNfcLock)();
498
483
  }
499
484
  catch {
500
- return { code: types_1.ResultCode.UNKNOWN_ERROR, success: false };
485
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
501
486
  }
502
487
  try {
503
488
  try {
@@ -505,7 +490,7 @@ async function resetRetryCountTo10(onCardIdentified) {
505
490
  }
506
491
  catch {
507
492
  (0, nfc_core_1.releaseNfcLock)();
508
- return { code: types_1.ResultCode.NFC_CONNECT_FAILED, success: false };
493
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
509
494
  }
510
495
  try {
511
496
  onCardIdentified?.();
@@ -513,7 +498,7 @@ async function resetRetryCountTo10(onCardIdentified) {
513
498
  await (0, nfc_core_1.releaseNfcTech)();
514
499
  (0, nfc_core_1.releaseNfcLock)();
515
500
  return {
516
- code: types_1.ResultCode.READ_RETRY_COUNT_SUCCESS,
501
+ code: types_1.NfcStatusCode.READ_RETRY_COUNT_SUCCESS,
517
502
  success: true,
518
503
  data: { retryCount: constants_1.DEFAULT_PIN_RETRY_COUNT },
519
504
  };
@@ -530,3 +515,105 @@ async function resetRetryCountTo10(onCardIdentified) {
530
515
  throw error;
531
516
  }
532
517
  }
518
+ /**
519
+ * Read card product version info (GET_VERSION command).
520
+ * No authentication required.
521
+ */
522
+ async function getCardVersion(onCardIdentified) {
523
+ try {
524
+ await (0, nfc_core_1.acquireNfcLock)();
525
+ }
526
+ catch {
527
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
528
+ }
529
+ try {
530
+ try {
531
+ await (0, nfc_core_1.requestNfcTech)();
532
+ }
533
+ catch {
534
+ (0, nfc_core_1.releaseNfcLock)();
535
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
536
+ }
537
+ try {
538
+ onCardIdentified?.();
539
+ const response = await (0, nfc_core_1.transceive)([constants_1.CMD_GET_VERSION]);
540
+ if (!response || response.length < 8) {
541
+ throw new Error('READ_FAILED');
542
+ }
543
+ await (0, nfc_core_1.releaseNfcTech)();
544
+ (0, nfc_core_1.releaseNfcLock)();
545
+ return {
546
+ code: types_1.NfcStatusCode.GET_VERSION_SUCCESS,
547
+ success: true,
548
+ data: {
549
+ version: {
550
+ vendorId: response[1],
551
+ productType: response[2],
552
+ productSubtype: response[3],
553
+ majorVersion: response[4],
554
+ minorVersion: response[5],
555
+ storageSize: response[6],
556
+ protocolType: response[7],
557
+ },
558
+ },
559
+ };
560
+ }
561
+ catch (error) {
562
+ await (0, nfc_core_1.releaseNfcTech)();
563
+ (0, nfc_core_1.releaseNfcLock)();
564
+ const code = (0, types_1.errorToCode)(error);
565
+ return { code, success: false };
566
+ }
567
+ }
568
+ catch (error) {
569
+ (0, nfc_core_1.releaseNfcLock)();
570
+ throw error;
571
+ }
572
+ }
573
+ /**
574
+ * Read the ECC originality signature (READ_SIG command).
575
+ * Verifies the card is a genuine NXP product.
576
+ * No authentication required (unless Random ID is enabled).
577
+ */
578
+ async function readOriginality(onCardIdentified) {
579
+ try {
580
+ await (0, nfc_core_1.acquireNfcLock)();
581
+ }
582
+ catch {
583
+ return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
584
+ }
585
+ try {
586
+ try {
587
+ await (0, nfc_core_1.requestNfcTech)();
588
+ }
589
+ catch {
590
+ (0, nfc_core_1.releaseNfcLock)();
591
+ return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
592
+ }
593
+ try {
594
+ onCardIdentified?.();
595
+ const response = await (0, nfc_core_1.transceive)([constants_1.CMD_READ_SIG, 0x00]);
596
+ if (!response || response.length < 48) {
597
+ throw new Error('READ_FAILED');
598
+ }
599
+ const signatureHex = (0, utils_1.bytesToHex)(response.slice(0, 48));
600
+ await (0, nfc_core_1.releaseNfcTech)();
601
+ (0, nfc_core_1.releaseNfcLock)();
602
+ return {
603
+ code: types_1.NfcStatusCode.READ_SIG_SUCCESS,
604
+ success: true,
605
+ data: { signature: signatureHex },
606
+ };
607
+ }
608
+ catch (error) {
609
+ await (0, nfc_core_1.releaseNfcTech)();
610
+ (0, nfc_core_1.releaseNfcLock)();
611
+ const code = (0, types_1.errorToCode)(error);
612
+ return { code, success: false };
613
+ }
614
+ }
615
+ catch (error) {
616
+ (0, nfc_core_1.releaseNfcLock)();
617
+ throw error;
618
+ }
619
+ }
package/dist/types.d.ts CHANGED
@@ -7,14 +7,16 @@
7
7
  * - Failure : 4xxxx (shared)
8
8
  *
9
9
  * This library does NOT provide user-facing messages.
10
- * The caller should map ResultCode to their own localised strings.
10
+ * The caller should map NfcStatusCode to their own localised strings.
11
11
  */
12
- export declare const ResultCode: {
12
+ export declare const NfcStatusCode: {
13
13
  readonly READ_SUCCESS: 10102;
14
14
  readonly READ_NICKNAME_SUCCESS: 10103;
15
15
  readonly CHECK_EMPTY: 10104;
16
16
  readonly CHECK_HAS_DATA: 10105;
17
17
  readonly READ_RETRY_COUNT_SUCCESS: 10106;
18
+ readonly GET_VERSION_SUCCESS: 10107;
19
+ readonly READ_SIG_SUCCESS: 10108;
18
20
  readonly INIT_SUCCESS: 10201;
19
21
  readonly WRITE_SUCCESS: 10203;
20
22
  readonly UPDATE_PASSWORD_SUCCESS: 10204;
@@ -40,7 +42,7 @@ export declare const ResultCode: {
40
42
  readonly RETRY_COUNT_EXHAUSTED: 40015;
41
43
  };
42
44
  export interface NfcResult {
43
- /** Numeric result code – compare against ResultCode constants */
45
+ /** Numeric result code – compare against NfcStatusCode constants */
44
46
  code: number;
45
47
  /** Whether the operation succeeded */
46
48
  success: boolean;
@@ -54,6 +56,16 @@ export interface NfcResult {
54
56
  retryCount?: number;
55
57
  aesKeyHex?: string;
56
58
  crc16?: number;
59
+ version?: {
60
+ vendorId: number;
61
+ productType: number;
62
+ productSubtype: number;
63
+ majorVersion: number;
64
+ minorVersion: number;
65
+ storageSize: number;
66
+ protocolType: number;
67
+ };
68
+ signature?: string;
57
69
  };
58
70
  }
59
71
  /**
@@ -62,7 +74,7 @@ export interface NfcResult {
62
74
  */
63
75
  export declare function nfcResultRetryCountExhausted(): NfcResult;
64
76
  /**
65
- * Derive a ResultCode from an error thrown during NFC operations.
77
+ * Derive a NfcStatusCode from an error thrown during NFC operations.
66
78
  * Handles iOS-specific cancel detection, known error strings, and fallback.
67
79
  */
68
80
  export declare function errorToCode(error: any): number;
package/dist/types.js CHANGED
@@ -8,23 +8,25 @@
8
8
  * - Failure : 4xxxx (shared)
9
9
  *
10
10
  * This library does NOT provide user-facing messages.
11
- * The caller should map ResultCode to their own localised strings.
11
+ * The caller should map NfcStatusCode to their own localised strings.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.ResultCode = void 0;
14
+ exports.NfcStatusCode = void 0;
15
15
  exports.nfcResultRetryCountExhausted = nfcResultRetryCountExhausted;
16
16
  exports.errorToCode = errorToCode;
17
17
  const react_native_1 = require("react-native");
18
18
  // ---------------------------------------------------------------------------
19
19
  // Unified result codes
20
20
  // ---------------------------------------------------------------------------
21
- exports.ResultCode = {
21
+ exports.NfcStatusCode = {
22
22
  // Reader success (101xx)
23
23
  READ_SUCCESS: 10102,
24
24
  READ_NICKNAME_SUCCESS: 10103,
25
25
  CHECK_EMPTY: 10104,
26
26
  CHECK_HAS_DATA: 10105,
27
27
  READ_RETRY_COUNT_SUCCESS: 10106,
28
+ GET_VERSION_SUCCESS: 10107,
29
+ READ_SIG_SUCCESS: 10108,
28
30
  // Writer success (102xx)
29
31
  INIT_SUCCESS: 10201,
30
32
  WRITE_SUCCESS: 10203,
@@ -57,7 +59,7 @@ exports.ResultCode = {
57
59
  */
58
60
  function nfcResultRetryCountExhausted() {
59
61
  return {
60
- code: exports.ResultCode.RETRY_COUNT_EXHAUSTED,
62
+ code: exports.NfcStatusCode.RETRY_COUNT_EXHAUSTED,
61
63
  success: false,
62
64
  data: { retryCount: 0 },
63
65
  };
@@ -66,7 +68,7 @@ function nfcResultRetryCountExhausted() {
66
68
  // Error → code mapping (internal use)
67
69
  // ---------------------------------------------------------------------------
68
70
  /**
69
- * Derive a ResultCode from an error thrown during NFC operations.
71
+ * Derive a NfcStatusCode from an error thrown during NFC operations.
70
72
  * Handles iOS-specific cancel detection, known error strings, and fallback.
71
73
  */
72
74
  function errorToCode(error) {
@@ -78,34 +80,34 @@ function errorToCode(error) {
78
80
  if (error &&
79
81
  typeof error === 'object' &&
80
82
  (error.name === 'UserCancel' || error.constructor?.name === 'UserCancel')) {
81
- return exports.ResultCode.NFC_USER_CANCELED;
83
+ return exports.NfcStatusCode.NFC_USER_CANCELED;
82
84
  }
83
85
  if (!msg || msg.includes('User Canceled') || msg.includes('Unknown empty error')) {
84
- return exports.ResultCode.NFC_USER_CANCELED;
86
+ return exports.NfcStatusCode.NFC_USER_CANCELED;
85
87
  }
86
88
  }
87
89
  if (msg.includes('NFC_USER_CANCELED_SIGNAL'))
88
- return exports.ResultCode.NFC_USER_CANCELED;
90
+ return exports.NfcStatusCode.NFC_USER_CANCELED;
89
91
  const keywords = [
90
- ['RETRY_COUNT_EXHAUSTED', exports.ResultCode.RETRY_COUNT_EXHAUSTED],
91
- ['AUTH_WRONG_PASSWORD', exports.ResultCode.AUTH_WRONG_PASSWORD],
92
- ['AUTH_INVALID_RESPONSE', exports.ResultCode.AUTH_INVALID_RESPONSE],
93
- ['AUTH_VERIFY_FAILED', exports.ResultCode.AUTH_VERIFY_FAILED],
94
- ['READ_FAILED', exports.ResultCode.READ_FAILED],
95
- ['WRITE_FAILED', exports.ResultCode.WRITE_FAILED],
96
- ['CRC16_CHECK_FAILED', exports.ResultCode.CRC16_CHECK_FAILED],
97
- ['EMPTY_CARD', exports.ResultCode.CHECK_EMPTY],
98
- ['INVALID_CARD_DATA', exports.ResultCode.INVALID_CARD_DATA],
99
- ['INVALID_MNEMONIC', exports.ResultCode.INVALID_MNEMONIC],
100
- ['UNSUPPORTED_MNEMONIC_LENGTH', exports.ResultCode.UNSUPPORTED_MNEMONIC_LENGTH],
101
- ['NFC_LOCK_TIMEOUT', exports.ResultCode.NFC_LOCK_TIMEOUT],
102
- ['NFC_CONNECT_FAILED', exports.ResultCode.NFC_CONNECT_FAILED],
103
- ['connection failed', exports.ResultCode.NFC_CONNECT_FAILED],
104
- ['transceive fail', exports.ResultCode.NFC_CONNECT_FAILED],
92
+ ['RETRY_COUNT_EXHAUSTED', exports.NfcStatusCode.RETRY_COUNT_EXHAUSTED],
93
+ ['AUTH_WRONG_PASSWORD', exports.NfcStatusCode.AUTH_WRONG_PASSWORD],
94
+ ['AUTH_INVALID_RESPONSE', exports.NfcStatusCode.AUTH_INVALID_RESPONSE],
95
+ ['AUTH_VERIFY_FAILED', exports.NfcStatusCode.AUTH_VERIFY_FAILED],
96
+ ['READ_FAILED', exports.NfcStatusCode.READ_FAILED],
97
+ ['WRITE_FAILED', exports.NfcStatusCode.WRITE_FAILED],
98
+ ['CRC16_CHECK_FAILED', exports.NfcStatusCode.CRC16_CHECK_FAILED],
99
+ ['EMPTY_CARD', exports.NfcStatusCode.CHECK_EMPTY],
100
+ ['INVALID_CARD_DATA', exports.NfcStatusCode.INVALID_CARD_DATA],
101
+ ['INVALID_MNEMONIC', exports.NfcStatusCode.INVALID_MNEMONIC],
102
+ ['UNSUPPORTED_MNEMONIC_LENGTH', exports.NfcStatusCode.UNSUPPORTED_MNEMONIC_LENGTH],
103
+ ['NFC_LOCK_TIMEOUT', exports.NfcStatusCode.NFC_LOCK_TIMEOUT],
104
+ ['NFC_CONNECT_FAILED', exports.NfcStatusCode.NFC_CONNECT_FAILED],
105
+ ['connection failed', exports.NfcStatusCode.NFC_CONNECT_FAILED],
106
+ ['transceive fail', exports.NfcStatusCode.NFC_CONNECT_FAILED],
105
107
  ];
106
108
  for (const [keyword, code] of keywords) {
107
109
  if (msg.includes(keyword))
108
110
  return code;
109
111
  }
110
- return exports.ResultCode.UNKNOWN_ERROR;
112
+ return exports.NfcStatusCode.UNKNOWN_ERROR;
111
113
  }
package/dist/utils.d.ts CHANGED
@@ -15,6 +15,22 @@ export declare function crc16ToBytes(crc16: number): Uint8Array;
15
15
  * @throws if buffer is shorter than 2 bytes.
16
16
  */
17
17
  export declare function extractCRC16(data: Uint8Array): number;
18
+ /**
19
+ * Get entropy length and description for a mnemonic type ID.
20
+ * @throws INVALID_CARD_DATA if the type ID is unknown.
21
+ */
22
+ export declare function getMnemonicTypeInfo(typeId: number): {
23
+ entropyLength: number;
24
+ description: string;
25
+ };
26
+ /**
27
+ * Get type ID and description for a given entropy byte length.
28
+ * @throws UNSUPPORTED_MNEMONIC_LENGTH if the length is not recognized.
29
+ */
30
+ export declare function getMnemonicTypeByEntropyLength(entropyLength: number): {
31
+ typeId: number;
32
+ description: string;
33
+ };
18
34
  /**
19
35
  * Validate whether raw card data contains a valid mnemonic payload.
20
36
  * Checks type byte, length, and CRC16 — does NOT decode the mnemonic.
package/dist/utils.js CHANGED
@@ -8,6 +8,8 @@ exports.hexToBytes = hexToBytes;
8
8
  exports.calculateCRC16 = calculateCRC16;
9
9
  exports.crc16ToBytes = crc16ToBytes;
10
10
  exports.extractCRC16 = extractCRC16;
11
+ exports.getMnemonicTypeInfo = getMnemonicTypeInfo;
12
+ exports.getMnemonicTypeByEntropyLength = getMnemonicTypeByEntropyLength;
11
13
  exports.validateMnemonicPayload = validateMnemonicPayload;
12
14
  const constants_1 = require("./constants");
13
15
  // ---------------------------------------------------------------------------
@@ -23,7 +25,7 @@ function bytesToHex(bytes) {
23
25
  function hexToBytes(hex) {
24
26
  const bytes = new Uint8Array(hex.length / 2);
25
27
  for (let i = 0; i < hex.length; i += 2) {
26
- bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
28
+ bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
27
29
  }
28
30
  return bytes;
29
31
  }
@@ -64,6 +66,37 @@ function extractCRC16(data) {
64
66
  return data[data.length - 2] | (data[data.length - 1] << 8);
65
67
  }
66
68
  // ---------------------------------------------------------------------------
69
+ // Mnemonic type info
70
+ // ---------------------------------------------------------------------------
71
+ /** Mnemonic type info table: [typeId, entropyLength, description] */
72
+ const MNEMONIC_TYPE_TABLE = [
73
+ [constants_1.MNEMONIC_TYPE_12, 16, '12 words (128-bit)'],
74
+ [constants_1.MNEMONIC_TYPE_15, 20, '15 words (160-bit)'],
75
+ [constants_1.MNEMONIC_TYPE_18, 24, '18 words (192-bit)'],
76
+ [constants_1.MNEMONIC_TYPE_21, 28, '21 words (224-bit)'],
77
+ [constants_1.MNEMONIC_TYPE_24, 32, '24 words (256-bit)'],
78
+ ];
79
+ /**
80
+ * Get entropy length and description for a mnemonic type ID.
81
+ * @throws INVALID_CARD_DATA if the type ID is unknown.
82
+ */
83
+ function getMnemonicTypeInfo(typeId) {
84
+ const entry = MNEMONIC_TYPE_TABLE.find(([id]) => id === typeId);
85
+ if (!entry)
86
+ throw new Error('INVALID_CARD_DATA');
87
+ return { entropyLength: entry[1], description: entry[2] };
88
+ }
89
+ /**
90
+ * Get type ID and description for a given entropy byte length.
91
+ * @throws UNSUPPORTED_MNEMONIC_LENGTH if the length is not recognized.
92
+ */
93
+ function getMnemonicTypeByEntropyLength(entropyLength) {
94
+ const entry = MNEMONIC_TYPE_TABLE.find(([, len]) => len === entropyLength);
95
+ if (!entry)
96
+ throw new Error('UNSUPPORTED_MNEMONIC_LENGTH');
97
+ return { typeId: entry[0], description: entry[2] };
98
+ }
99
+ // ---------------------------------------------------------------------------
67
100
  // Mnemonic payload validation
68
101
  // ---------------------------------------------------------------------------
69
102
  /**
@@ -78,32 +111,7 @@ function validateMnemonicPayload(data) {
78
111
  throw new Error('INVALID_CARD_DATA');
79
112
  if (data.every(b => b === 0))
80
113
  throw new Error('EMPTY_CARD');
81
- const typeId = data[0];
82
- let entropyLength;
83
- let typeStr;
84
- switch (typeId) {
85
- case constants_1.MNEMONIC_TYPE_12:
86
- entropyLength = 16;
87
- typeStr = '12 words (128-bit)';
88
- break;
89
- case constants_1.MNEMONIC_TYPE_15:
90
- entropyLength = 20;
91
- typeStr = '15 words (160-bit)';
92
- break;
93
- case constants_1.MNEMONIC_TYPE_18:
94
- entropyLength = 24;
95
- typeStr = '18 words (192-bit)';
96
- break;
97
- case constants_1.MNEMONIC_TYPE_21:
98
- entropyLength = 28;
99
- typeStr = '21 words (224-bit)';
100
- break;
101
- case constants_1.MNEMONIC_TYPE_24:
102
- entropyLength = 32;
103
- typeStr = '24 words (256-bit)';
104
- break;
105
- default: throw new Error('INVALID_CARD_DATA');
106
- }
114
+ const { entropyLength, description } = getMnemonicTypeInfo(data[0]);
107
115
  const expectedTotal = 1 + entropyLength + 2;
108
116
  if (data.length < expectedTotal)
109
117
  throw new Error('INVALID_CARD_DATA');
@@ -112,5 +120,5 @@ function validateMnemonicPayload(data) {
112
120
  const calcCRC = calculateCRC16(dataBlock);
113
121
  if (storedCRC !== calcCRC)
114
122
  throw new Error('CRC16_CHECK_FAILED');
115
- return { type: typeStr };
123
+ return { type: description };
116
124
  }