@notabene/javascript-sdk 2.15.0 → 2.16.0

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/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "author": "Notabene <developers@notabene.id>",
11
11
  "license": "MIT",
12
12
  "packageManager": "yarn@4.5.1",
13
- "version": "2.15.0",
13
+ "version": "2.16.0",
14
14
  "source": "src/notabene.ts",
15
15
  "main": "dist/cjs/notabene.cjs",
16
16
  "module": "dist/esm/notabene.js",
@@ -72,6 +72,7 @@
72
72
  "@semantic-release/git": "^10.0.1",
73
73
  "@semantic-release/gitlab": "^13.2.1",
74
74
  "@semantic-release/npm": "^12.0.1",
75
+ "@taprsvp/types": "^1.14.0",
75
76
  "@vitest/coverage-v8": "^2.1.8",
76
77
  "eslint": "^9.14.0",
77
78
  "eslint-config-prettier": "^9.1.0",
@@ -79,6 +80,7 @@
79
80
  "fast-check": "^3.23.1",
80
81
  "globals": "^15.11.0",
81
82
  "husky": "^9.1.6",
83
+ "jose": "^6.1.0",
82
84
  "jsdom": "^25.0.1",
83
85
  "lint-staged": "^15.2.10",
84
86
  "prettier": "^3.3.3",
@@ -104,9 +106,5 @@
104
106
  "extends": [
105
107
  "@commitlint/config-conventional"
106
108
  ]
107
- },
108
- "dependencies": {
109
- "@taprsvp/types": "^1.13.0",
110
- "jose": "^6.1.0"
111
109
  }
112
110
  }
@@ -340,6 +340,30 @@ describe('Notabene', () => {
340
340
  });
341
341
  });
342
342
 
343
+ describe('createInvoiceReader', () => {
344
+ test.prop([
345
+ fc.string({ minLength: 3 }), // authToken
346
+ arbitraryNodeUrl(), // nodeUrl
347
+ ])(
348
+ 'Should create invoice reader component with correct URL',
349
+ (authToken, nodeUrl) => {
350
+ const notabene = new Notabene({
351
+ nodeUrl,
352
+ authToken,
353
+ });
354
+
355
+ const component = notabene.createInvoiceReader();
356
+ const url = new URL(component.url);
357
+
358
+ return (
359
+ url.pathname === '/flow-link/invoice-reader' &&
360
+ url.hash ===
361
+ `#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify({}))}` &&
362
+ url.searchParams.get('nodeUrl') === nodeUrl
363
+ );
364
+ },
365
+ );
366
+ });
343
367
  describe('uxUrl trailing slash normalization', () => {
344
368
  it('should strip a single trailing slash', () => {
345
369
  const notabene = new Notabene({
package/src/notabene.ts CHANGED
@@ -30,6 +30,7 @@ import type {
30
30
  FieldTypes,
31
31
  HostMessage,
32
32
  InvalidValue,
33
+ InvoiceReaderResponse,
33
34
  IVMS101,
34
35
  LegalPerson,
35
36
  LegalPersonFieldName,
@@ -96,6 +97,7 @@ export type {
96
97
  TransactionCreateRequestV2,
97
98
  TransactionIVMS101Request,
98
99
  } from './responseTransformer';
100
+ export type { Invoice } from './types';
99
101
  export {
100
102
  ConnectionManager,
101
103
  getRefreshResult,
@@ -153,6 +155,7 @@ export type {
153
155
  FieldTypes,
154
156
  HostMessage,
155
157
  InvalidValue,
158
+ InvoiceReaderResponse,
156
159
  IVMS101,
157
160
  LegalPerson,
158
161
  LegalPersonFieldName,
@@ -403,6 +406,23 @@ export default class Notabene {
403
406
  );
404
407
  }
405
408
 
409
+ /**
410
+ * Creates an invoice reader component for extracting TAIP-16 invoice data from PDF invoices
411
+ *
412
+ * The component provides a PDF drag-and-drop upload UI. On upload, the PDF is
413
+ * parsed and the extracted invoice data is returned. On completion,
414
+ * the response contains the TAIP-16 invoice data.
415
+ *
416
+ * @returns A new EmbeddedComponent instance for invoice reader creation
417
+ * @public
418
+ */
419
+ public createInvoiceReader() {
420
+ return this.createComponent<InvoiceReaderResponse, Record<string, never>>(
421
+ 'flow-link/invoice-reader',
422
+ {},
423
+ );
424
+ }
425
+
406
426
  /**
407
427
  * Creates a deposit assist component
408
428
  *
@@ -2,7 +2,11 @@ import { describe, expect, it } from 'vitest';
2
2
  import type { OriginatorV2 } from '../../ivms/v2Types';
3
3
  import type { Deposit, TransactionResponse, Withdrawal } from '../../types';
4
4
  import { PersonType } from '../../types';
5
- import { componentResponseToTxRequests, enrichConfig } from '../transformer';
5
+ import {
6
+ componentResponseToTxRequests,
7
+ enrichConfig,
8
+ uuid,
9
+ } from '../transformer';
6
10
 
7
11
  // Common test constants
8
12
  const TEST_DELEGATE_TOKEN = 'test-delegate-token';
@@ -506,6 +510,35 @@ describe('componentResponseToTxRequests', () => {
506
510
  });
507
511
  });
508
512
 
513
+ const UUID_REGEX =
514
+ /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
515
+
516
+ describe('uuid', () => {
517
+ it('should return a valid UUID v4 format', () => {
518
+ const result = uuid();
519
+ expect(result).toMatch(UUID_REGEX);
520
+ });
521
+
522
+ it('should return unique values on each call', () => {
523
+ const results = new Set(Array.from({ length: 100 }, () => uuid()));
524
+ expect(results.size).toBe(100);
525
+ });
526
+
527
+ it('should always have version 4 indicator', () => {
528
+ for (let i = 0; i < 50; i++) {
529
+ const result = uuid();
530
+ expect(result[14]).toBe('4');
531
+ }
532
+ });
533
+
534
+ it('should always have a valid variant nibble (8, 9, a, or b)', () => {
535
+ for (let i = 0; i < 50; i++) {
536
+ const result = uuid();
537
+ expect('89ab').toContain(result[19]);
538
+ }
539
+ });
540
+ });
541
+
509
542
  describe('enrichConfig', () => {
510
543
  const CUSTOMER_DID = 'did:key:customer123';
511
544
  const SOURCE_ADDRESS = '0xsource123';
@@ -520,7 +553,7 @@ describe('enrichConfig', () => {
520
553
  }
521
554
 
522
555
  describe('withdrawal transactions', () => {
523
- it('should extract originatorId from delegate token and generate beneficiaryId from destination', () => {
556
+ it('should extract originatorId from delegate token and fall back to urn:uuid for beneficiaryId', () => {
524
557
  const delegateToken = createDelegateToken(CUSTOMER_DID);
525
558
  const withdrawal = {
526
559
  destination: DESTINATION_ADDRESS,
@@ -531,7 +564,7 @@ describe('enrichConfig', () => {
531
564
  const result = enrichConfig({}, delegateToken, withdrawal);
532
565
 
533
566
  expect(result.originatorId).toBe(CUSTOMER_DID);
534
- expect(result.beneficiaryId).toBe(`did:key:${DESTINATION_ADDRESS}`);
567
+ expect(result.beneficiaryId).toMatch(/^urn:uuid:[0-9a-f-]{36}$/);
535
568
  });
536
569
 
537
570
  it('should set beneficiaryId equal to originatorId for self-transfers', () => {
@@ -572,7 +605,7 @@ describe('enrichConfig', () => {
572
605
  });
573
606
 
574
607
  describe('deposit transactions', () => {
575
- it('should extract beneficiaryId from delegate token and generate originatorId from source', () => {
608
+ it('should extract beneficiaryId from delegate token and fall back to urn:uuid for originatorId', () => {
576
609
  const delegateToken = createDelegateToken(CUSTOMER_DID);
577
610
  const deposit = {
578
611
  source: SOURCE_ADDRESS,
@@ -583,7 +616,7 @@ describe('enrichConfig', () => {
583
616
  const result = enrichConfig({}, delegateToken, deposit);
584
617
 
585
618
  expect(result.beneficiaryId).toBe(CUSTOMER_DID);
586
- expect(result.originatorId).toBe(`did:key:${SOURCE_ADDRESS}`);
619
+ expect(result.originatorId).toMatch(/^urn:uuid:[0-9a-f-]{36}$/);
587
620
  });
588
621
 
589
622
  it('should set originatorId equal to beneficiaryId for self-transfers', () => {
@@ -632,7 +665,51 @@ describe('enrichConfig', () => {
632
665
 
633
666
  const result = enrichConfig({}, 'invalid-token', withdrawal);
634
667
 
635
- expect(result.originatorId).toBeUndefined();
636
- expect(result.beneficiaryId).toBe(`did:key:${DESTINATION_ADDRESS}`);
668
+ expect(result.originatorId).toMatch(/^urn:uuid:[0-9a-f-]{36}$/);
669
+ expect(result.beneficiaryId).toMatch(/^urn:uuid:[0-9a-f-]{36}$/);
670
+ });
671
+
672
+ describe('UUID fallback', () => {
673
+ it('should generate a valid urn:uuid for missing beneficiaryId', () => {
674
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
675
+ const withdrawal = {
676
+ destination: DESTINATION_ADDRESS,
677
+ asset: TEST_ASSET,
678
+ amountDecimal: 100,
679
+ } as Withdrawal;
680
+
681
+ const result = enrichConfig({}, delegateToken, withdrawal);
682
+
683
+ expect(result.originatorId).toBe(CUSTOMER_DID);
684
+ expect(result.beneficiaryId).toMatch(/^urn:uuid:[0-9a-f-]{36}$/);
685
+ });
686
+
687
+ it('should generate a valid urn:uuid for missing originatorId', () => {
688
+ const delegateToken = createDelegateToken(CUSTOMER_DID);
689
+ const deposit = {
690
+ source: SOURCE_ADDRESS,
691
+ asset: TEST_ASSET,
692
+ amountDecimal: 100,
693
+ } as Deposit;
694
+
695
+ const result = enrichConfig({}, delegateToken, deposit);
696
+
697
+ expect(result.beneficiaryId).toBe(CUSTOMER_DID);
698
+ expect(result.originatorId).toMatch(/^urn:uuid:[0-9a-f-]{36}$/);
699
+ });
700
+
701
+ it('should generate unique UUIDs for each call', () => {
702
+ const withdrawal = {
703
+ destination: DESTINATION_ADDRESS,
704
+ asset: TEST_ASSET,
705
+ amountDecimal: 100,
706
+ } as Withdrawal;
707
+
708
+ const result1 = enrichConfig({}, 'invalid-token', withdrawal);
709
+ const result2 = enrichConfig({}, 'invalid-token', withdrawal);
710
+
711
+ expect(result1.beneficiaryId).not.toBe(result2.beneficiaryId);
712
+ expect(result1.originatorId).not.toBe(result2.originatorId);
713
+ });
637
714
  });
638
715
  });
@@ -1,5 +1,25 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { getCaip10ChainPrefix } from '../utils';
2
+ import { getCaip10ChainPrefix, getPartyId } from '../utils';
3
+
4
+ describe('getPartyId', () => {
5
+ it('should return mailto: IRI when party has email', () => {
6
+ expect(getPartyId({ email: 'test@example.com' })).toBe(
7
+ 'mailto:test@example.com',
8
+ );
9
+ });
10
+
11
+ it('should return undefined when party has no email', () => {
12
+ expect(getPartyId({})).toBeUndefined();
13
+ });
14
+
15
+ it('should return undefined when party is undefined', () => {
16
+ expect(getPartyId(undefined)).toBeUndefined();
17
+ });
18
+
19
+ it('should return undefined when called with no arguments', () => {
20
+ expect(getPartyId()).toBeUndefined();
21
+ });
22
+ });
3
23
 
4
24
  describe('getCaip10ChainPrefix', () => {
5
25
  it('should extract chain prefix from EIP155 CAIP-10 address', () => {
@@ -1,11 +1,11 @@
1
+ import type { Agent, DID } from '@taprsvp/types';
1
2
  import type {
2
3
  Beneficiary,
3
4
  NaturalPerson,
4
5
  NaturalPersonName,
5
6
  Originator,
6
7
  Person,
7
- } from '@notabene/javascript-sdk/src/ivms/types';
8
- import type { Agent } from '@taprsvp/types';
8
+ } from '../ivms';
9
9
  import {
10
10
  PersonType,
11
11
  type Deposit,
@@ -14,6 +14,7 @@ import {
14
14
  type Withdrawal,
15
15
  } from '../types';
16
16
  import type {
17
+ BaseRequestConfig,
17
18
  ResponseToIVMS101RequestConfig,
18
19
  ResponseToTxCreateRequestConfig,
19
20
  TransactionCreateRequest,
@@ -23,7 +24,6 @@ import type {
23
24
  import {
24
25
  convertPersonToV2,
25
26
  getCaip10ChainPrefix,
26
- getPartyId,
27
27
  isDeposit,
28
28
  isWithdrawal,
29
29
  } from './utils';
@@ -237,22 +237,10 @@ export function mapToV1CreateRequest(
237
237
  export function mapToTransactCreateRequest(
238
238
  transaction: Withdrawal | Deposit,
239
239
  payload: V1Transaction,
240
- config: ResponseToTxCreateRequestConfig = {},
240
+ config: ResponseToTxCreateRequestConfig & Required<BaseRequestConfig>,
241
241
  ): TransactionCreateRequestV2 {
242
- // For withdrawals: customer sends to counterparty
243
- // For deposits: counterparty sends to customer
244
- const isWithdrawalTx = isWithdrawal(transaction);
245
- const originatorParty = isWithdrawalTx
246
- ? transaction.customer
247
- : transaction.counterparty;
248
- const beneficiaryParty = isWithdrawalTx
249
- ? transaction.counterparty
250
- : transaction.customer;
251
-
252
- const originatorId =
253
- config?.originatorId || getPartyId('originator', originatorParty);
254
- const beneficiaryId =
255
- config?.beneficiaryId || getPartyId('beneficiary', beneficiaryParty);
242
+ const originatorId = config.originatorId;
243
+ const beneficiaryId = config.beneficiaryId;
256
244
  const referenceId =
257
245
  config?.referenceId ||
258
246
  payload.transactionId ||
@@ -262,7 +250,8 @@ export function mapToTransactCreateRequest(
262
250
  if (payload.originatorVASPdid) {
263
251
  agents.push({
264
252
  '@id': payload.originatorVASPdid,
265
- for: originatorId,
253
+ // tap type needs to be updated to accept IRI as valid id
254
+ for: originatorId as DID,
266
255
  role: 'VASP',
267
256
  });
268
257
  }
@@ -270,7 +259,8 @@ export function mapToTransactCreateRequest(
270
259
  if (payload.beneficiaryVASPdid) {
271
260
  agents.push({
272
261
  '@id': payload.beneficiaryVASPdid,
273
- for: beneficiaryId,
262
+ // tap type needs to be updated to accept IRI as valid id
263
+ for: beneficiaryId as DID,
274
264
  role: 'VASP',
275
265
  });
276
266
  }
@@ -278,7 +268,8 @@ export function mapToTransactCreateRequest(
278
268
  if (isWithdrawal(transaction) && transaction?.account?.did) {
279
269
  agents.push({
280
270
  '@id': transaction.account.did,
281
- for: payload.beneficiaryVASPdid || beneficiaryId,
271
+ // tap type needs to be updated to accept IRI as valid id
272
+ for: (payload.beneficiaryVASPdid || beneficiaryId) as DID,
282
273
  role: 'SettlementAddress',
283
274
  });
284
275
  }
@@ -287,7 +278,8 @@ export function mapToTransactCreateRequest(
287
278
  if (transaction.account.did) {
288
279
  agents.push({
289
280
  '@id': transaction.account.did,
290
- for: payload.originatorVASPdid || originatorId,
281
+ // tap type needs to be updated to accept IRI as valid id
282
+ for: (payload.originatorVASPdid || originatorId) as DID,
291
283
  role: 'SourceAddress',
292
284
  });
293
285
  }
@@ -296,7 +288,8 @@ export function mapToTransactCreateRequest(
296
288
  const chainPrefix = getCaip10ChainPrefix(transaction.account.caip10);
297
289
  agents.push({
298
290
  '@id': `did:pkh:${chainPrefix}:${config.settlementAddress}`,
299
- for: payload.beneficiaryVASPdid || beneficiaryId,
291
+ // tap type needs to be updated to accept IRI as valid id
292
+ for: (payload.beneficiaryVASPdid || beneficiaryId) as DID,
300
293
  role: 'SettlementAddress',
301
294
  });
302
295
  }
@@ -315,12 +308,10 @@ export function mapToTransactCreateRequest(
315
308
  export function mapToAppendPiiRequest(
316
309
  transaction: Withdrawal | Deposit,
317
310
  ivms101: IVMS101,
318
- config: ResponseToIVMS101RequestConfig = {},
311
+ config: ResponseToIVMS101RequestConfig & Required<BaseRequestConfig>,
319
312
  ): TransactionIVMS101Request {
320
313
  if (isWithdrawal(transaction)) {
321
- const beneficiaryId =
322
- config.beneficiaryId ||
323
- getPartyId('beneficiary', transaction.counterparty);
314
+ const beneficiaryId = config.beneficiaryId;
324
315
 
325
316
  const beneficiaryPersons =
326
317
  // If counterparty type is SELF, reuse originator data for beneficiary
@@ -341,8 +332,7 @@ export function mapToAppendPiiRequest(
341
332
  };
342
333
  }
343
334
 
344
- const originatorId =
345
- config.originatorId || getPartyId('originator', transaction.counterparty);
335
+ const originatorId = config.originatorId;
346
336
 
347
337
  const originatorPersons =
348
338
  transaction.counterparty?.type === PersonType.SELF && config.beneficiary
@@ -1,4 +1,5 @@
1
1
  import { decodeJwt } from 'jose';
2
+
2
3
  import {
3
4
  PersonType,
4
5
  type Deposit,
@@ -13,6 +14,7 @@ import {
13
14
  mapToV1CreateRequest,
14
15
  } from './mappers';
15
16
  import type {
17
+ BaseRequestConfig,
16
18
  DelegateToken,
17
19
  ResponseToIVMS101RequestConfig,
18
20
  ResponseToTxCreateRequestConfig,
@@ -21,7 +23,33 @@ import type {
21
23
  TransactionCreateRequestV2,
22
24
  TransactionIVMS101Request,
23
25
  } from './types';
24
- import { isDeposit, isWithdrawal } from './utils';
26
+ import { getPartyId, isDeposit, isWithdrawal } from './utils';
27
+
28
+ export function uuid(): string {
29
+ if (typeof crypto === 'undefined') {
30
+ throw new Error(
31
+ '[Notabene/SDK] Web Crypto API is not available. A secure environment with crypto support is required (Node.js 16+ or a modern browser).',
32
+ );
33
+ }
34
+ // Use native randomUUID when available (Node 19+, modern browsers)
35
+ if (typeof crypto.randomUUID === 'function') {
36
+ return crypto.randomUUID();
37
+ }
38
+
39
+ // Fallback for older environments (Node 16–18) using crypto.getRandomValues
40
+ return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>
41
+ (
42
+ +c ^
43
+ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))
44
+ ).toString(16),
45
+ );
46
+ }
47
+
48
+ // This is the format we expect for beneficiaryId and originatorId;
49
+ // however for now we don't use it since the backend doesn't do the check
50
+ // const validateIRI = (uri: string): uri is IRI => {
51
+ // return uri.indexOf(':') > 0;
52
+ // };
25
53
 
26
54
  /**
27
55
  * Fills in missing config values by extracting them from the delegate token and transaction data
@@ -31,7 +59,7 @@ export function enrichConfig(
31
59
  config: ResponseToTxRequestConfig,
32
60
  delegateToken: string,
33
61
  transaction: Withdrawal | Deposit,
34
- ): ResponseToTxRequestConfig {
62
+ ): ResponseToTxRequestConfig & Required<BaseRequestConfig> {
35
63
  const enrichedConfig = { ...config };
36
64
 
37
65
  // Extract customer ID from delegate token
@@ -42,6 +70,7 @@ export function enrichConfig(
42
70
  customerIdFromToken = tokenPayload?.sub;
43
71
  } catch {
44
72
  // If decoding fails, customerIdFromToken remains undefined
73
+ // TODO: check what should we do in this scenario.
45
74
  }
46
75
 
47
76
  if (isWithdrawal(transaction)) {
@@ -54,9 +83,8 @@ export function enrichConfig(
54
83
  if (transaction.counterparty?.type === PersonType.SELF) {
55
84
  enrichedConfig.beneficiaryId = enrichedConfig.originatorId;
56
85
  } else if (transaction.destination) {
57
- // Generate beneficiaryId from destination if not provided.
58
- // TODO: Replace with proper DID key identifier creation
59
- enrichedConfig.beneficiaryId = `did:key:${transaction.destination}`;
86
+ // no-op: TODO: review this logic later if we need to derive beneficiaryId using a public key scheme.
87
+ // enrichedConfig.beneficiaryId = `did:key:${transaction.destination}`;
60
88
  }
61
89
  }
62
90
  } else if (isDeposit(transaction)) {
@@ -69,14 +97,54 @@ export function enrichConfig(
69
97
  if (transaction.counterparty?.type === PersonType.SELF) {
70
98
  enrichedConfig.originatorId = enrichedConfig.beneficiaryId;
71
99
  } else if (transaction.source) {
72
- // Generate originatorId from source if not provided.
73
- // TODO: Replace with proper DID key identifier creation
74
- enrichedConfig.originatorId = `did:key:${transaction.source}`;
100
+ // no-op: TODO: review this logic later if we need to derive originatorId using a public key scheme.
101
+ // enrichedConfig.originatorId = `did:key:${transaction.source}`;
75
102
  }
76
103
  }
77
104
  }
78
105
 
79
- return enrichedConfig;
106
+ // Resolve IDs from party information (email/name) if still missing
107
+ if (!enrichedConfig.originatorId) {
108
+ const party = isWithdrawal(transaction)
109
+ ? transaction.customer
110
+ : transaction.counterparty;
111
+ enrichedConfig.originatorId = getPartyId(party);
112
+ }
113
+
114
+ if (!enrichedConfig.beneficiaryId) {
115
+ const party = isWithdrawal(transaction)
116
+ ? transaction.counterparty
117
+ : transaction.customer;
118
+ enrichedConfig.beneficiaryId = getPartyId(party);
119
+ }
120
+
121
+ if (!enrichedConfig.beneficiaryId) {
122
+ // TODO : Check if we should throw an exception instead
123
+ console.warn(
124
+ `[Notabene/SDK] beneficiaryId not provided; falling back to a generated random identifier.`,
125
+ );
126
+ enrichedConfig.beneficiaryId = `urn:uuid:${uuid()}`;
127
+ }
128
+
129
+ if (!enrichedConfig.originatorId) {
130
+ // TODO : Check if we should throw an exception instead
131
+ console.warn(
132
+ `[Notabene/SDK] originatorId not provided; falling back to a generated random identifier.`,
133
+ );
134
+ enrichedConfig.originatorId = `urn:uuid:${uuid()}`;
135
+ }
136
+
137
+ // TODO: Re-enable IRI validation once the backend enforces it
138
+ // if (!validateIRI(enrichedConfig.beneficiaryId)) {
139
+ // throw new Error('beneficiaryId is not a valid IRI');
140
+ // }
141
+
142
+ // if (!validateIRI(enrichedConfig.originatorId)) {
143
+ // throw new Error('originatorId is not a valid IRI');
144
+ // }
145
+
146
+ return enrichedConfig as ResponseToTxRequestConfig &
147
+ Required<BaseRequestConfig>;
80
148
  }
81
149
 
82
150
  /**
@@ -3,7 +3,7 @@
3
3
  * These are specific to the API transformation logic
4
4
  */
5
5
 
6
- import type { Agent, DID } from '@taprsvp/types';
6
+ import type { Agent, DID, IRI } from '@taprsvp/types';
7
7
  import type { BeneficiaryV2, OriginatorV2 } from '../ivms';
8
8
 
9
9
  export interface DelegateToken {
@@ -14,9 +14,9 @@ export interface DelegateToken {
14
14
  iat?: number;
15
15
  }
16
16
 
17
- interface BaseRequestConfig {
18
- originatorId?: DID;
19
- beneficiaryId?: DID;
17
+ export interface BaseRequestConfig {
18
+ originatorId?: IRI;
19
+ beneficiaryId?: IRI;
20
20
  }
21
21
 
22
22
  export interface ResponseToTxCreateRequestConfig extends BaseRequestConfig {
@@ -1,9 +1,10 @@
1
+ import { CAIP10Schema } from '@taprsvp/types';
1
2
  import type {
2
3
  NaturalPersonName,
4
+ NaturalPersonNameV2,
3
5
  Person,
4
- } from '@notabene/javascript-sdk/src/ivms/types';
5
- import { CAIP10Schema, type DID } from '@taprsvp/types';
6
- import type { NaturalPersonNameV2, PersonV2 } from '../ivms';
6
+ PersonV2,
7
+ } from '../ivms';
7
8
  import type { Deposit, Withdrawal } from '../types';
8
9
 
9
10
  export function isDeposit(
@@ -19,21 +20,15 @@ export function isWithdrawal(
19
20
  }
20
21
 
21
22
  /**
22
- * Generates a backup DID identifier for a party
23
+ * Resolves a party's IRI identifier from their email, if available.
23
24
  */
24
- export function getPartyId(
25
- identifier: 'originator' | 'beneficiary',
26
- party?: { email?: string; name?: string },
27
- ): DID {
25
+ export function getPartyId(party?: {
26
+ email?: string;
27
+ }): `${string}:${string}` | undefined {
28
28
  if (party?.email) {
29
- return `did:email:${party.email}`;
29
+ return `mailto:${party.email}`;
30
30
  }
31
- if (party?.name) {
32
- return `did:name:${encodeURIComponent(party.name.replace(/\s+/g, '-'))}`;
33
- }
34
- throw new Error(
35
- `Unable to generate ${identifier} ID: missing required ${identifier} information`,
36
- );
31
+ return undefined;
37
32
  }
38
33
 
39
34
  /**
package/src/types.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Invoice, Party } from '@taprsvp/types';
1
2
  import type {
2
3
  Address,
3
4
  Beneficiary,
@@ -23,6 +24,8 @@ export type {
23
24
  NationalIdentification,
24
25
  Originator,
25
26
  };
27
+ // Re-export TAIP-16 invoice types for SDK consumers
28
+ export type { Invoice };
26
29
  /**
27
30
  * Interoperable Virtual Asset Service Provider (VASP) Messaging Standard
28
31
  * @public
@@ -209,6 +212,7 @@ export type Source = BlockchainAddress | CAIP10;
209
212
 
210
213
  /**
211
214
  * A Uniform Resource Identifier
215
+ * @remarks This type will be narrowed to `` `${string}:${string}` `` in the next major release.
212
216
  * @public
213
217
  */
214
218
  export type URI = string;
@@ -617,6 +621,14 @@ export interface DepositRequestOptions {
617
621
  showQrCode?: boolean; // Defaults to true
618
622
  }
619
623
 
624
+ /** Output fields populated by the component on completion */
625
+ export interface InvoiceReaderResponse {
626
+ /** TAIP-16 compliant invoice data (populated by the component after PDF parsing) */
627
+ invoice?: Invoice;
628
+ merchant?: Party;
629
+ customer?: Party;
630
+ }
631
+
620
632
  /**
621
633
  * An object representing a connection request
622
634
  * @public
@@ -920,6 +932,7 @@ export interface TransactionOptions {
920
932
  microTransfer?: {
921
933
  destination: BlockchainAddress;
922
934
  amountSubunits: string;
935
+ requireHash?: boolean; // Defaults true
923
936
  };
924
937
  fallbacks?: ProofTypes[]; // Legacy — replaced by agentSections.fallback
925
938
  deminimis?: ThresholdOptions;
@@ -208,6 +208,7 @@ export const arbitraryTransactionOptions =
208
208
  fc.record({
209
209
  destination: arbitraryBlockchainAddress(),
210
210
  amountSubunits: fc.string(),
211
+ requireHash: fc.option(fc.boolean()),
211
212
  }),
212
213
  ),
213
214
  fallbacks: fc.option(