@notabene/javascript-sdk 2.13.0 → 2.14.0-next.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/README.md +4 -4
- package/dist/cjs/notabene.cjs +1 -1
- package/dist/cjs/notabene.d.ts +223 -0
- package/dist/cjs/package.json +6 -2
- package/dist/esm/notabene.d.ts +223 -0
- package/dist/esm/notabene.js +476 -163
- package/dist/esm/package.json +6 -2
- package/dist/notabene.d.ts +223 -0
- package/dist/notabene.js +476 -163
- package/package.json +6 -2
- package/src/ivms/index.ts +5 -0
- package/src/ivms/v2Types.ts +35 -0
- package/src/notabene.ts +12 -0
- package/src/responseTransformer/README.md +164 -0
- package/src/responseTransformer/index.ts +21 -0
- package/src/responseTransformer/mappers.ts +293 -0
- package/src/responseTransformer/transformer.ts +278 -0
- package/src/responseTransformer/types.ts +60 -0
- package/src/responseTransformer/utils.ts +61 -0
- package/src/types.ts +1 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { decodeJwt } from 'jose';
|
|
2
|
+
import {
|
|
3
|
+
PersonType,
|
|
4
|
+
type OwnershipProof,
|
|
5
|
+
type TransactionResponse,
|
|
6
|
+
type Withdrawal,
|
|
7
|
+
} from '../types';
|
|
8
|
+
import {
|
|
9
|
+
mapToAppendPiiRequest,
|
|
10
|
+
mapToTransactCreateRequest,
|
|
11
|
+
mapToV1CreateRequest,
|
|
12
|
+
} from './mappers';
|
|
13
|
+
import type {
|
|
14
|
+
DelegateToken,
|
|
15
|
+
ResponseToTxRequestConfig,
|
|
16
|
+
TransactionCreateRequest,
|
|
17
|
+
TransactionCreateRequestV2,
|
|
18
|
+
TransactionIVMS101Request,
|
|
19
|
+
} from './types';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Fills in missing config values by extracting them from the delegate token and withdrawal data
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
function enrichConfig(
|
|
26
|
+
config: ResponseToTxRequestConfig,
|
|
27
|
+
delegateToken: string,
|
|
28
|
+
withdrawal: Withdrawal,
|
|
29
|
+
): ResponseToTxRequestConfig {
|
|
30
|
+
const enrichedConfig = { ...config };
|
|
31
|
+
|
|
32
|
+
// Extract originatorId from delegate token if not provided
|
|
33
|
+
if (!enrichedConfig.originatorId) {
|
|
34
|
+
try {
|
|
35
|
+
const tokenPayload = decodeJwt<DelegateToken>(delegateToken);
|
|
36
|
+
if (tokenPayload?.sub) {
|
|
37
|
+
enrichedConfig.originatorId = tokenPayload.sub;
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
// If decoding fails, originatorId remains undefined
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!enrichedConfig.beneficiaryId) {
|
|
45
|
+
if (withdrawal.counterparty?.type === PersonType.SELF) {
|
|
46
|
+
enrichedConfig.beneficiaryId = enrichedConfig.originatorId;
|
|
47
|
+
} else if (withdrawal.destination) {
|
|
48
|
+
// Generate beneficiaryId from destination if not provided.
|
|
49
|
+
// TODO: Replace with proper DID key identifier creation
|
|
50
|
+
enrichedConfig.beneficiaryId = `did:key:${withdrawal.destination}`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return enrichedConfig;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Transforms a Notabene component response to a Version 1 API request body
|
|
59
|
+
*
|
|
60
|
+
* @param response - The response from the Notabene TX Create component
|
|
61
|
+
* @returns The transformed request body ready for the Version 1 API
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* import { componentResponseToV1TxCreateRequest } from '$lib/notabene-tx-transformer';
|
|
66
|
+
*
|
|
67
|
+
* withdrawal.on('complete', async (result) => {
|
|
68
|
+
* const requestBody = componentResponseToV1TxCreateRequest(result.response);
|
|
69
|
+
*
|
|
70
|
+
* await fetch(endpointUrl, {
|
|
71
|
+
* method: 'POST',
|
|
72
|
+
* body: JSON.stringify(requestBody)
|
|
73
|
+
* });
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export function componentResponseToV1TxCreateRequest(
|
|
78
|
+
response: TransactionResponse<Withdrawal>,
|
|
79
|
+
): TransactionCreateRequest {
|
|
80
|
+
if (!response.txCreate || !response.ivms101) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
'Invalid response: missing required txCreate or ivms101 data',
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const { value, ivms101, proof, txCreate } = response;
|
|
87
|
+
|
|
88
|
+
// Build withdrawal object from response data for V1 API
|
|
89
|
+
const withdrawal: Withdrawal = {
|
|
90
|
+
destination: value?.destination || '',
|
|
91
|
+
counterparty: value?.counterparty || {},
|
|
92
|
+
agent: value?.agent,
|
|
93
|
+
account: value?.account,
|
|
94
|
+
proof,
|
|
95
|
+
asset:
|
|
96
|
+
value?.asset ||
|
|
97
|
+
(typeof txCreate.transactionAsset === 'string'
|
|
98
|
+
? txCreate.transactionAsset
|
|
99
|
+
: txCreate.transactionAsset?.caip19) ||
|
|
100
|
+
'',
|
|
101
|
+
amountDecimal:
|
|
102
|
+
value?.amountDecimal ||
|
|
103
|
+
(txCreate.transactionAmount ? parseFloat(txCreate.transactionAmount) : 0),
|
|
104
|
+
customer: value?.customer,
|
|
105
|
+
} as Withdrawal;
|
|
106
|
+
|
|
107
|
+
return mapToV1CreateRequest(withdrawal, txCreate, ivms101 as any);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Transforms a Notabene component response into txCreate, IVMS101, and confirmRelationship request bodies
|
|
112
|
+
*
|
|
113
|
+
* This is a convenience function that generates the transaction creation request,
|
|
114
|
+
* the IVMS101 data, and optionally the relationship confirmation proof in a single call,
|
|
115
|
+
* which is useful for V2 workflows where you need to create a transaction first,
|
|
116
|
+
* then append IVMS101 data to it, and finally confirm the relationship.
|
|
117
|
+
*
|
|
118
|
+
* @param response - The response from the Notabene Embedded Component
|
|
119
|
+
* @param delegateToken - The JWT delegate token for extracting the originator ID
|
|
120
|
+
* @param config - Optional configuration for IDs and reference
|
|
121
|
+
* @param config.originatorId - Optional originator ID (auto-extracted from delegateToken if not provided)
|
|
122
|
+
* @param config.beneficiaryId - Optional beneficiary ID (auto-generated if not provided)
|
|
123
|
+
* @param config.referenceId - Optional reference ID (auto-generated if not provided)
|
|
124
|
+
* @param config.originator - Optional originator data in V2 format
|
|
125
|
+
* @returns Object with `createTx`, `ivms101`, and optional `confirmRelationship` properties containing the respective request bodies
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* import { componentResponseToTxRequests } from '$lib/notabene-tx-transformer';
|
|
130
|
+
*
|
|
131
|
+
* withdrawal.on('complete', async (result) => {
|
|
132
|
+
* const { createTx, ivms101, confirmRelationship } = componentResponseToTxRequests(
|
|
133
|
+
* result.response,
|
|
134
|
+
* session.user.token,
|
|
135
|
+
* { originator: originatorData }
|
|
136
|
+
* );
|
|
137
|
+
*
|
|
138
|
+
* // First, create the transaction
|
|
139
|
+
* const txResponse = await fetch('/entity/${vaspDid}/tx', {
|
|
140
|
+
* method: 'POST',
|
|
141
|
+
* body: JSON.stringify(createTx)
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // Then, append IVMS101 data
|
|
145
|
+
* const txId = txResponse.transfer['@id'];
|
|
146
|
+
* await fetch(`/entity/${vaspDid}/tx/${txId}/append`, {
|
|
147
|
+
* method: 'POST',
|
|
148
|
+
* body: JSON.stringify(ivms101)
|
|
149
|
+
* });
|
|
150
|
+
*
|
|
151
|
+
* // Finally, confirm relationship
|
|
152
|
+
* if (confirmRelationship) {
|
|
153
|
+
* await fetch(`/entity/${vaspDid}/relationship?to=${to}&from=${from}`, {
|
|
154
|
+
* method: 'PATCH',
|
|
155
|
+
* body: JSON.stringify({ proof: confirmRelationship.proof })
|
|
156
|
+
* });
|
|
157
|
+
* }
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
export function componentResponseToTxRequests(
|
|
162
|
+
response: TransactionResponse<Withdrawal>,
|
|
163
|
+
delegateToken: string,
|
|
164
|
+
config: ResponseToTxRequestConfig = {},
|
|
165
|
+
): {
|
|
166
|
+
createTx: TransactionCreateRequestV2;
|
|
167
|
+
ivms101: TransactionIVMS101Request;
|
|
168
|
+
confirmRelationship?: {
|
|
169
|
+
proof: OwnershipProof;
|
|
170
|
+
};
|
|
171
|
+
} {
|
|
172
|
+
if (!response.txCreate || !response.ivms101) {
|
|
173
|
+
throw new Error(
|
|
174
|
+
'Invalid response: missing required txCreate or ivms101 data',
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const { value, txCreate, ivms101, proof } = response;
|
|
179
|
+
const enrichedConfig = enrichConfig(config, delegateToken, value);
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
createTx: mapToTransactCreateRequest(value, txCreate, enrichedConfig),
|
|
183
|
+
ivms101: mapToAppendPiiRequest(value, ivms101, enrichedConfig),
|
|
184
|
+
...(proof && { confirmRelationship: { proof } }),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Transforms a Notabene component response to a Version 2 transaction create API request body
|
|
190
|
+
*
|
|
191
|
+
* @param response - The response from the Notabene Embedded Component
|
|
192
|
+
* @param delegateToken - The JWT delegate token for extracting the originator ID
|
|
193
|
+
* @param config - Configuration object with optional IDs
|
|
194
|
+
* @param config.originatorId - Optional originator ID (auto-extracted from delegateToken if not provided)
|
|
195
|
+
* @param config.beneficiaryId - Optional beneficiary ID (auto-generated if not provided)
|
|
196
|
+
* @param config.referenceId - Optional reference ID for the transaction
|
|
197
|
+
* @returns The transformed request body ready for the Version 2 transaction create API
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* import { componentResponseToTxCreateRequest } from '$lib/notabene-tx-transformer';
|
|
202
|
+
*
|
|
203
|
+
* withdrawal.on('complete', async (result) => {
|
|
204
|
+
* const requestBody = componentResponseToTxCreateRequest(
|
|
205
|
+
* result.response,
|
|
206
|
+
* {
|
|
207
|
+
* originatorId: 'mailto:user@example.com',
|
|
208
|
+
* beneficiaryId: 'urn:beneficiary:recipient',
|
|
209
|
+
* referenceId: 'tx-12345'
|
|
210
|
+
* }
|
|
211
|
+
* );
|
|
212
|
+
*
|
|
213
|
+
* await fetch('/entity/${vaspDid}/tx', {
|
|
214
|
+
* method: 'POST',
|
|
215
|
+
* body: JSON.stringify(requestBody)
|
|
216
|
+
* });
|
|
217
|
+
* });
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
export function componentResponseToTxCreateRequest(
|
|
221
|
+
response: TransactionResponse<Withdrawal>,
|
|
222
|
+
delegateToken: string,
|
|
223
|
+
config: Omit<ResponseToTxRequestConfig, 'originator'> = {},
|
|
224
|
+
) {
|
|
225
|
+
if (!response.txCreate || !response.ivms101) {
|
|
226
|
+
throw new Error(
|
|
227
|
+
'Invalid response: missing required txCreate or ivms101 data',
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const { value, txCreate } = response;
|
|
232
|
+
const enrichedConfig = enrichConfig(config, delegateToken, value);
|
|
233
|
+
|
|
234
|
+
return mapToTransactCreateRequest(value, txCreate, enrichedConfig);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Transforms a Notabene component response to IVMS101 format
|
|
239
|
+
*
|
|
240
|
+
* @param response - The response from the Notabene Embedded Component
|
|
241
|
+
* @param delegateToken - The JWT delegate token for extracting the originator ID
|
|
242
|
+
* @param config - Configuration object with optional IDs
|
|
243
|
+
* @param config.originatorId - Optional originator ID (auto-extracted from delegateToken if not provided)
|
|
244
|
+
* @param config.beneficiaryId - Optional beneficiary ID (auto-generated if not provided)
|
|
245
|
+
* @param config.referenceId - Optional reference ID for the transaction
|
|
246
|
+
* @param config.originator - Optional originator data in V2 format
|
|
247
|
+
* @returns The transformed request body in IVMS101 format
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* import { componentResponseToIVMS101 } from '$lib/notabene-tx-transformer';
|
|
252
|
+
*
|
|
253
|
+
* const requestBody = componentResponseToIVMS101(
|
|
254
|
+
* result.response,
|
|
255
|
+
* session.user.token,
|
|
256
|
+
* { originator: myOriginatorData }
|
|
257
|
+
* );
|
|
258
|
+
*
|
|
259
|
+
* await fetch('/entity/${vaspDid}/tx/${txId}/append', {
|
|
260
|
+
* method: 'POST',
|
|
261
|
+
* body: JSON.stringify(requestBody)
|
|
262
|
+
* });
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
export function componentResponseToIVMS101(
|
|
266
|
+
response: TransactionResponse<Withdrawal>,
|
|
267
|
+
delegateToken: string,
|
|
268
|
+
config: ResponseToTxRequestConfig = {},
|
|
269
|
+
) {
|
|
270
|
+
if (!response.ivms101) {
|
|
271
|
+
throw new Error('Invalid response: missing required ivms101 data');
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const { value, ivms101 } = response;
|
|
275
|
+
const enrichedConfig = enrichConfig(config, delegateToken, value);
|
|
276
|
+
|
|
277
|
+
return mapToAppendPiiRequest(value, ivms101, enrichedConfig);
|
|
278
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types that are not available in @notabene/javascript-sdk
|
|
3
|
+
* These are specific to the API transformation logic
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Agent, DID } from '@taprsvp/types';
|
|
7
|
+
import type { BeneficiaryV2, OriginatorV2 } from '../ivms';
|
|
8
|
+
|
|
9
|
+
export interface DelegateToken {
|
|
10
|
+
sub?: DID;
|
|
11
|
+
iss?: DID;
|
|
12
|
+
scope?: 'delegate';
|
|
13
|
+
exp?: number;
|
|
14
|
+
iat?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ResponseToTxRequestConfig {
|
|
18
|
+
originatorId?: DID;
|
|
19
|
+
beneficiaryId?: DID;
|
|
20
|
+
referenceId?: string;
|
|
21
|
+
originator?: OriginatorV2;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TransactionCreateRequest {
|
|
25
|
+
transactionAsset: any;
|
|
26
|
+
transactionAmount: string;
|
|
27
|
+
beneficiaryDid?: string;
|
|
28
|
+
originatorVASPdid: string;
|
|
29
|
+
beneficiaryVASPdid?: string;
|
|
30
|
+
beneficiaryVASPname?: string;
|
|
31
|
+
beneficiaryVASPwebsite?: string;
|
|
32
|
+
transactionBlockchainInfo: {
|
|
33
|
+
origin?: string;
|
|
34
|
+
destination?: string;
|
|
35
|
+
};
|
|
36
|
+
beneficiaryProof?: any;
|
|
37
|
+
beneficiary?: any;
|
|
38
|
+
originator?: any;
|
|
39
|
+
originatorEqualsBeneficiary?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface TransactionCreateRequestV2 {
|
|
43
|
+
originator: {
|
|
44
|
+
'@id': string;
|
|
45
|
+
};
|
|
46
|
+
beneficiary: {
|
|
47
|
+
'@id': string;
|
|
48
|
+
};
|
|
49
|
+
asset: string;
|
|
50
|
+
amount: string;
|
|
51
|
+
agents: Agent[];
|
|
52
|
+
ref: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TransactionIVMS101Request {
|
|
56
|
+
ivms101: {
|
|
57
|
+
originator?: OriginatorV2;
|
|
58
|
+
beneficiary?: BeneficiaryV2;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NaturalPersonName,
|
|
3
|
+
Person,
|
|
4
|
+
} from '@notabene/javascript-sdk/src/ivms/types';
|
|
5
|
+
import type { DID } from '@taprsvp/types';
|
|
6
|
+
import type { NaturalPersonNameV2, PersonV2 } from '../ivms';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generates a backup DID identifier for a party
|
|
10
|
+
*/
|
|
11
|
+
export function getPartyId(
|
|
12
|
+
identifier: 'originator' | 'beneficiary',
|
|
13
|
+
party?: { email?: string; name?: string },
|
|
14
|
+
): DID {
|
|
15
|
+
if (party?.email) {
|
|
16
|
+
return `did:email:${party.email}`;
|
|
17
|
+
}
|
|
18
|
+
if (party?.name) {
|
|
19
|
+
return `did:name:${encodeURIComponent(party.name.replace(/\s+/g, '-'))}`;
|
|
20
|
+
}
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Unable to generate ${identifier} ID: missing required ${identifier} information`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Converts NaturalPersonName from V1 format to V2 format
|
|
28
|
+
* Changes the nameIdentifierType field name to naturalPersonNameIdentifierType
|
|
29
|
+
*/
|
|
30
|
+
export function convertNaturalPersonNameToV2(
|
|
31
|
+
name: NaturalPersonName,
|
|
32
|
+
): NaturalPersonNameV2 {
|
|
33
|
+
const { nameIdentifier, ...rest } = name;
|
|
34
|
+
return {
|
|
35
|
+
...rest,
|
|
36
|
+
nameIdentifier: nameIdentifier?.map(({ nameIdentifierType, ...rest }) => ({
|
|
37
|
+
...rest,
|
|
38
|
+
naturalPersonNameIdentifierType: nameIdentifierType,
|
|
39
|
+
})),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Converts a Person from V1 format to V2 format
|
|
45
|
+
* Applies deep conversion to natural person names and adds account number
|
|
46
|
+
*/
|
|
47
|
+
export function convertPersonToV2(
|
|
48
|
+
person: Person,
|
|
49
|
+
accountNumber: string,
|
|
50
|
+
): PersonV2 {
|
|
51
|
+
return {
|
|
52
|
+
naturalPerson: person.naturalPerson
|
|
53
|
+
? {
|
|
54
|
+
...person.naturalPerson,
|
|
55
|
+
name: convertNaturalPersonNameToV2(person.naturalPerson.name),
|
|
56
|
+
}
|
|
57
|
+
: undefined,
|
|
58
|
+
legalPerson: person.legalPerson,
|
|
59
|
+
accountNumber: [accountNumber],
|
|
60
|
+
};
|
|
61
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -888,6 +888,7 @@ export interface TransactionOptions {
|
|
|
888
888
|
vasps?: VASPOptions;
|
|
889
889
|
hide?: ValidationSections[]; // You can hide a specific section of the component by listing it here
|
|
890
890
|
counterpartyAssist?: CounterpartyAssistConfig;
|
|
891
|
+
autoSubmit?: boolean; // Defaults to false
|
|
891
892
|
}
|
|
892
893
|
/**
|
|
893
894
|
* Component Message Type enum representing different message types that can be sent
|