@notabene/javascript-sdk 2.19.0 → 2.19.1
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/cjs/notabene.cjs +6 -6
- package/dist/cjs/notabene.d.ts +1 -40
- package/dist/cjs/package.json +1 -1
- package/dist/esm/notabene.d.ts +1 -40
- package/dist/esm/notabene.js +1525 -1651
- package/dist/esm/package.json +1 -1
- package/dist/notabene.d.ts +1 -40
- package/dist/notabene.js +1525 -1651
- package/package.json +1 -1
- package/src/__tests__/EmbeddedComponent.portless-message.test.ts +66 -0
- package/src/__tests__/EmbeddedComponent.test.ts +3 -3
- package/src/components/EmbeddedComponent.ts +18 -8
- package/src/notabene.ts +0 -2
- package/src/responseTransformer/README.md +0 -30
- package/src/responseTransformer/__tests__/transformer.test.ts +2 -2
- package/src/responseTransformer/index.ts +1 -3
- package/src/responseTransformer/mappers.ts +9 -218
- package/src/responseTransformer/transformer.ts +1 -57
- package/src/responseTransformer/types.ts +0 -18
- package/src/utils/MessageEventManager.ts +2 -0
- package/src/utils/__tests__/MessageEventManager.test.ts +8 -0
package/package.json
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from 'vitest';
|
|
2
|
+
import EmbeddedComponent from '../components/EmbeddedComponent';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Integration test (no mocks) reproducing the Banxa crash (PAY-1056):
|
|
6
|
+
*
|
|
7
|
+
* TypeError: Cannot set properties of undefined (setting 'onmessage')
|
|
8
|
+
*
|
|
9
|
+
* Cause: Reown/WalletConnect calls `parent.postMessage(event, '*')` from
|
|
10
|
+
* inside the widget iframe without transferring a MessagePort. The SDK's
|
|
11
|
+
* message listener passed `event.ports[0]` (undefined) to `setPort()`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
interface TestValue {
|
|
15
|
+
id?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('EmbeddedComponent — portless postMessage (PAY-1056)', () => {
|
|
19
|
+
let container: HTMLDivElement;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
container = document.createElement('div');
|
|
23
|
+
document.body.appendChild(container);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('should not crash when iframe sends a message without ports', () => {
|
|
27
|
+
const component = new EmbeddedComponent<TestValue, unknown>(
|
|
28
|
+
'about:blank?widget=true',
|
|
29
|
+
{},
|
|
30
|
+
);
|
|
31
|
+
component.embed(container);
|
|
32
|
+
|
|
33
|
+
const iframe = container.querySelector('iframe')!;
|
|
34
|
+
|
|
35
|
+
expect(() => {
|
|
36
|
+
window.dispatchEvent(
|
|
37
|
+
new MessageEvent('message', {
|
|
38
|
+
source: iframe.contentWindow,
|
|
39
|
+
data: { type: 'wc_sessionUpdate' },
|
|
40
|
+
ports: [],
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
}).not.toThrow();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('should still accept the handshake message with a port', () => {
|
|
47
|
+
const component = new EmbeddedComponent<TestValue, unknown>(
|
|
48
|
+
'about:blank?widget=true',
|
|
49
|
+
{},
|
|
50
|
+
);
|
|
51
|
+
component.embed(container);
|
|
52
|
+
|
|
53
|
+
const iframe = container.querySelector('iframe')!;
|
|
54
|
+
const channel = new MessageChannel();
|
|
55
|
+
|
|
56
|
+
expect(() => {
|
|
57
|
+
window.dispatchEvent(
|
|
58
|
+
new MessageEvent('message', {
|
|
59
|
+
source: iframe.contentWindow,
|
|
60
|
+
data: {},
|
|
61
|
+
ports: [channel.port2],
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
}).not.toThrow();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -12,6 +12,9 @@ interface TestOptions {
|
|
|
12
12
|
currency?: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Store callbacks for testing
|
|
16
|
+
const callbacks = new Map();
|
|
17
|
+
|
|
15
18
|
// Mock MessageEventManager
|
|
16
19
|
vi.mock('../utils/MessageEventManager', () => {
|
|
17
20
|
return {
|
|
@@ -30,9 +33,6 @@ vi.mock('../utils/MessageEventManager', () => {
|
|
|
30
33
|
};
|
|
31
34
|
});
|
|
32
35
|
|
|
33
|
-
// Store callbacks for testing
|
|
34
|
-
const callbacks = new Map();
|
|
35
|
-
|
|
36
36
|
describe('EmbeddedComponent', () => {
|
|
37
37
|
let mockParent: HTMLElement;
|
|
38
38
|
let mockAppendChild: ReturnType<typeof vi.fn>;
|
|
@@ -24,6 +24,7 @@ export default class EmbeddedComponent<V, O> {
|
|
|
24
24
|
private iframe?: HTMLIFrameElement;
|
|
25
25
|
private eventManager: MessageEventManager<V, O>;
|
|
26
26
|
private modal?: HTMLDialogElement;
|
|
27
|
+
private messageHandler?: (event: MessageEvent) => void;
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Creates an instance of EmbeddedComponent.
|
|
@@ -112,18 +113,24 @@ export default class EmbeddedComponent<V, O> {
|
|
|
112
113
|
// this.iframe.style.backgroundColor = 'transparent';
|
|
113
114
|
parent.appendChild(this.iframe);
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
this.messageHandler = (event: MessageEvent) => {
|
|
116
117
|
if (event.source !== this.iframe?.contentWindow) {
|
|
117
118
|
return;
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
if (event.ports[0]) {
|
|
121
|
+
this.eventManager?.setPort(event.ports[0]);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
window.addEventListener('message', this.messageHandler);
|
|
122
125
|
|
|
123
126
|
this.iframe?.contentWindow?.focus();
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
removeEmbed() {
|
|
130
|
+
if (this.messageHandler) {
|
|
131
|
+
window.removeEventListener('message', this.messageHandler);
|
|
132
|
+
this.messageHandler = undefined;
|
|
133
|
+
}
|
|
127
134
|
if (this.iframe) this.iframe.remove();
|
|
128
135
|
}
|
|
129
136
|
|
|
@@ -258,13 +265,15 @@ export default class EmbeddedComponent<V, O> {
|
|
|
258
265
|
'_blank',
|
|
259
266
|
'popup=true,width=600,height=600',
|
|
260
267
|
);
|
|
261
|
-
|
|
268
|
+
const popupMessageHandler = (event: MessageEvent) => {
|
|
262
269
|
if (event.source !== popup) {
|
|
263
270
|
return;
|
|
264
271
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
272
|
+
if (event.ports[0]) {
|
|
273
|
+
this.eventManager?.setPort(event.ports[0]);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
window.addEventListener('message', popupMessageHandler);
|
|
268
277
|
|
|
269
278
|
const removeCancel = this.on(CMType.CANCEL, () => {
|
|
270
279
|
popup?.close();
|
|
@@ -275,6 +284,7 @@ export default class EmbeddedComponent<V, O> {
|
|
|
275
284
|
});
|
|
276
285
|
|
|
277
286
|
return this.completion().finally(() => {
|
|
287
|
+
window.removeEventListener('message', popupMessageHandler);
|
|
278
288
|
removeCancel();
|
|
279
289
|
removeComplete();
|
|
280
290
|
});
|
package/src/notabene.ts
CHANGED
|
@@ -93,11 +93,9 @@ export {
|
|
|
93
93
|
componentResponseToIVMS101,
|
|
94
94
|
componentResponseToTxCreateRequest,
|
|
95
95
|
componentResponseToTxRequests,
|
|
96
|
-
componentResponseToV1TxCreateRequest,
|
|
97
96
|
} from './responseTransformer';
|
|
98
97
|
export type {
|
|
99
98
|
ResponseToTxRequestConfig,
|
|
100
|
-
TransactionCreateRequest,
|
|
101
99
|
TransactionCreateRequestV2,
|
|
102
100
|
TransactionIVMS101Request,
|
|
103
101
|
} from './responseTransformer';
|
|
@@ -58,26 +58,6 @@ const ivms101Body = componentResponseToIVMS101(response, delegateToken, {
|
|
|
58
58
|
});
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
### Version 1 API (Legacy)
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
import { componentResponseToV1TxCreateRequest } from '$lib/notabene-tx-transformer';
|
|
65
|
-
|
|
66
|
-
withdrawal.on('complete', async (result) => {
|
|
67
|
-
const requestBody = componentResponseToV1TxCreateRequest(result.response);
|
|
68
|
-
|
|
69
|
-
// Send to your Version 1 API
|
|
70
|
-
await fetch(`${apiUrlV1}/entity/${did}/tx`, {
|
|
71
|
-
method: 'POST',
|
|
72
|
-
headers: {
|
|
73
|
-
'Content-Type': 'application/json',
|
|
74
|
-
Authorization: `Bearer ${token}`
|
|
75
|
-
},
|
|
76
|
-
body: JSON.stringify(requestBody)
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
```
|
|
80
|
-
|
|
81
61
|
## API
|
|
82
62
|
|
|
83
63
|
### `componentResponseToTxRequests(response, delegateToken, config?)`
|
|
@@ -127,16 +107,6 @@ Transforms a Notabene component response to IVMS101 format.
|
|
|
127
107
|
|
|
128
108
|
**Returns:** IVMS101 formatted request body
|
|
129
109
|
|
|
130
|
-
### `componentResponseToV1TxCreateRequest(response)`
|
|
131
|
-
|
|
132
|
-
Transforms a Notabene component response to a V1 transaction create request.
|
|
133
|
-
|
|
134
|
-
**Parameters:**
|
|
135
|
-
|
|
136
|
-
- `response`: Response from the Notabene TX Create component
|
|
137
|
-
|
|
138
|
-
**Returns:** V1 transaction create request body
|
|
139
|
-
|
|
140
110
|
## Module Structure
|
|
141
111
|
|
|
142
112
|
```
|
|
@@ -333,7 +333,7 @@ describe('componentResponseToTxRequests', () => {
|
|
|
333
333
|
geographicAddress: [geographicAddress],
|
|
334
334
|
},
|
|
335
335
|
legalPerson: undefined,
|
|
336
|
-
accountNumber: [
|
|
336
|
+
accountNumber: [TEST_ADDRESS],
|
|
337
337
|
},
|
|
338
338
|
],
|
|
339
339
|
},
|
|
@@ -435,7 +435,7 @@ describe('componentResponseToTxRequests', () => {
|
|
|
435
435
|
},
|
|
436
436
|
},
|
|
437
437
|
legalPerson: undefined,
|
|
438
|
-
accountNumber: [
|
|
438
|
+
accountNumber: [TEST_ADDRESS],
|
|
439
439
|
},
|
|
440
440
|
],
|
|
441
441
|
},
|
|
@@ -9,13 +9,11 @@ export {
|
|
|
9
9
|
componentResponseToIVMS101,
|
|
10
10
|
componentResponseToTxCreateRequest,
|
|
11
11
|
componentResponseToTxRequests,
|
|
12
|
-
componentResponseToV1TxCreateRequest,
|
|
13
12
|
} from './transformer';
|
|
14
13
|
|
|
15
14
|
// Type exports
|
|
16
15
|
export {
|
|
17
16
|
type ResponseToTxRequestConfig,
|
|
18
|
-
type
|
|
19
|
-
type TransactionCreateRequestV2, // rename to TransactCreateRequest?
|
|
17
|
+
type TransactionCreateRequestV2,
|
|
20
18
|
type TransactionIVMS101Request,
|
|
21
19
|
} from './types';
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
import type { Agent, DID } from '@taprsvp/types';
|
|
2
|
-
import type {
|
|
3
|
-
Beneficiary,
|
|
4
|
-
NaturalPerson,
|
|
5
|
-
NaturalPersonName,
|
|
6
|
-
Originator,
|
|
7
|
-
Person,
|
|
8
|
-
} from '../ivms';
|
|
9
2
|
import {
|
|
10
3
|
PersonType,
|
|
11
4
|
type Deposit,
|
|
@@ -17,7 +10,6 @@ import type {
|
|
|
17
10
|
BaseRequestConfig,
|
|
18
11
|
ResponseToIVMS101RequestConfig,
|
|
19
12
|
ResponseToTxCreateRequestConfig,
|
|
20
|
-
TransactionCreateRequest,
|
|
21
13
|
TransactionCreateRequestV2,
|
|
22
14
|
TransactionIVMS101Request,
|
|
23
15
|
} from './types';
|
|
@@ -28,212 +20,6 @@ import {
|
|
|
28
20
|
isWithdrawal,
|
|
29
21
|
} from './utils';
|
|
30
22
|
|
|
31
|
-
// Constants
|
|
32
|
-
const DEFAULT_GEOGRAPHIC_ADDRESS = [
|
|
33
|
-
{
|
|
34
|
-
addressType: 'GEOG' as const,
|
|
35
|
-
addressLine: ['1234 Main Street'],
|
|
36
|
-
townName: 'Unknown',
|
|
37
|
-
country: 'US',
|
|
38
|
-
},
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
// Helper functions
|
|
42
|
-
function parseName(fullName: string) {
|
|
43
|
-
const trimmedName = fullName.trim();
|
|
44
|
-
if (!trimmedName) {
|
|
45
|
-
return { primaryIdentifier: '', secondaryIdentifier: '' };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const parts = trimmedName.split(/\s+/);
|
|
49
|
-
const primaryIdentifier = parts[parts.length - 1];
|
|
50
|
-
const secondaryParts = parts.slice(0, -1);
|
|
51
|
-
const secondaryIdentifier =
|
|
52
|
-
secondaryParts.length > 0 ? secondaryParts.join(' ') : primaryIdentifier;
|
|
53
|
-
|
|
54
|
-
return { primaryIdentifier, secondaryIdentifier };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function copyIVMS(
|
|
58
|
-
type: 'originator' | 'beneficiary',
|
|
59
|
-
persons?: Person[],
|
|
60
|
-
accountNumber: string[] = ['1234567890'],
|
|
61
|
-
): Originator | Beneficiary {
|
|
62
|
-
const updatedPersons = persons?.map((person) => {
|
|
63
|
-
const updatedPerson = { ...person };
|
|
64
|
-
|
|
65
|
-
if (updatedPerson.naturalPerson) {
|
|
66
|
-
updatedPerson.naturalPerson = {
|
|
67
|
-
...updatedPerson.naturalPerson,
|
|
68
|
-
geographicAddress: DEFAULT_GEOGRAPHIC_ADDRESS,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (updatedPerson.legalPerson) {
|
|
73
|
-
updatedPerson.legalPerson = {
|
|
74
|
-
...updatedPerson.legalPerson,
|
|
75
|
-
geographicAddress: DEFAULT_GEOGRAPHIC_ADDRESS,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return updatedPerson;
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return type === 'originator'
|
|
83
|
-
? { originatorPersons: updatedPersons, accountNumber }
|
|
84
|
-
: { beneficiaryPersons: updatedPersons, accountNumber };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function hostIVMS(
|
|
88
|
-
type: 'originator' | 'beneficiary',
|
|
89
|
-
name = 'John Doe',
|
|
90
|
-
): Originator | Beneficiary {
|
|
91
|
-
const { primaryIdentifier, secondaryIdentifier } = parseName(name);
|
|
92
|
-
|
|
93
|
-
const person: Person = {
|
|
94
|
-
naturalPerson: {
|
|
95
|
-
name: [
|
|
96
|
-
{
|
|
97
|
-
nameIdentifier: [
|
|
98
|
-
{
|
|
99
|
-
primaryIdentifier,
|
|
100
|
-
...(secondaryIdentifier ? { secondaryIdentifier } : {}),
|
|
101
|
-
nameIdentifierType: 'LEGL',
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
},
|
|
105
|
-
] as any,
|
|
106
|
-
geographicAddress: DEFAULT_GEOGRAPHIC_ADDRESS,
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
return type === 'originator'
|
|
111
|
-
? { originatorPersons: [person], accountNumber: ['1234567890'] }
|
|
112
|
-
: { beneficiaryPersons: [person], accountNumber: ['1234567890'] };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const wrapNameInArray = (naturalPerson: NaturalPerson): NaturalPerson => ({
|
|
116
|
-
...naturalPerson,
|
|
117
|
-
// @ts-expect-error Preserving the original logic
|
|
118
|
-
name: naturalPerson.name
|
|
119
|
-
? ([naturalPerson.name] as NaturalPersonName[])
|
|
120
|
-
: undefined,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
const transformPerson = (person: Person): Person => ({
|
|
124
|
-
...person,
|
|
125
|
-
naturalPerson: person.naturalPerson
|
|
126
|
-
? wrapNameInArray(person.naturalPerson)
|
|
127
|
-
: undefined,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const transformIVMS101 = (
|
|
131
|
-
{ beneficiary, originator }: IVMS101,
|
|
132
|
-
name?: string,
|
|
133
|
-
originatorEqualsBeneficiary?: boolean,
|
|
134
|
-
destination?: string,
|
|
135
|
-
operation?: 'withdrawal' | 'deposit',
|
|
136
|
-
) => {
|
|
137
|
-
if (operation === 'withdrawal') {
|
|
138
|
-
const transformedBeneficiary = beneficiary && {
|
|
139
|
-
...beneficiary,
|
|
140
|
-
...(destination && { accountNumber: [destination] }),
|
|
141
|
-
beneficiaryPersons: beneficiary.beneficiaryPersons?.map(transformPerson),
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
if (
|
|
145
|
-
originatorEqualsBeneficiary &&
|
|
146
|
-
transformedBeneficiary?.beneficiaryPersons
|
|
147
|
-
) {
|
|
148
|
-
const originator = copyIVMS(
|
|
149
|
-
'originator',
|
|
150
|
-
transformedBeneficiary?.beneficiaryPersons,
|
|
151
|
-
) as Originator;
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
beneficiary: {
|
|
155
|
-
accountNumber: originator.accountNumber,
|
|
156
|
-
beneficiaryPersons: originator.originatorPersons,
|
|
157
|
-
},
|
|
158
|
-
originator,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
beneficiary: transformedBeneficiary,
|
|
164
|
-
originator: hostIVMS('originator', name),
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (operation === 'deposit') {
|
|
169
|
-
const transformedOriginator = originator && {
|
|
170
|
-
...(destination && { accountNumber: [destination] }),
|
|
171
|
-
originatorPersons: originator.originatorPersons?.map(transformPerson),
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
if (
|
|
175
|
-
originatorEqualsBeneficiary &&
|
|
176
|
-
transformedOriginator?.originatorPersons
|
|
177
|
-
) {
|
|
178
|
-
const beneficiary = copyIVMS(
|
|
179
|
-
'beneficiary',
|
|
180
|
-
transformedOriginator?.originatorPersons,
|
|
181
|
-
) as Beneficiary;
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
originator: {
|
|
185
|
-
accountNumber: beneficiary.accountNumber,
|
|
186
|
-
originatorPersons: beneficiary.beneficiaryPersons,
|
|
187
|
-
},
|
|
188
|
-
beneficiary,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
originator: transformedOriginator,
|
|
194
|
-
beneficiary: hostIVMS('beneficiary', name),
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
throw new Error('Invalid operation type');
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export function mapToV1CreateRequest(
|
|
202
|
-
withdrawal: Withdrawal,
|
|
203
|
-
payload: V1Transaction,
|
|
204
|
-
ivms101: IVMS101,
|
|
205
|
-
): TransactionCreateRequest {
|
|
206
|
-
const { beneficiary, originator } = transformIVMS101(
|
|
207
|
-
ivms101,
|
|
208
|
-
withdrawal.customer?.name,
|
|
209
|
-
payload.originatorEqualsBeneficiary,
|
|
210
|
-
withdrawal.destination,
|
|
211
|
-
'withdrawal',
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
transactionAsset: payload.transactionAsset,
|
|
216
|
-
transactionAmount: payload.transactionAmount,
|
|
217
|
-
beneficiaryDid: withdrawal.counterparty?.did,
|
|
218
|
-
originatorVASPdid: payload.originatorVASPdid,
|
|
219
|
-
...(payload.beneficiaryVASPdid && !payload.beneficiaryProof
|
|
220
|
-
? { beneficiaryVASPdid: payload.beneficiaryVASPdid }
|
|
221
|
-
: {}),
|
|
222
|
-
transactionBlockchainInfo: {
|
|
223
|
-
...(originator?.accountNumber && { origin: originator.accountNumber[0] }),
|
|
224
|
-
...(withdrawal.destination && { destination: withdrawal.destination }),
|
|
225
|
-
},
|
|
226
|
-
...(payload.beneficiaryProof && {
|
|
227
|
-
beneficiaryProof: payload.beneficiaryProof,
|
|
228
|
-
}),
|
|
229
|
-
...(beneficiary && { beneficiary }),
|
|
230
|
-
...(originator && { originator }),
|
|
231
|
-
...(payload.originatorEqualsBeneficiary && {
|
|
232
|
-
originatorEqualsBeneficiary: payload.originatorEqualsBeneficiary,
|
|
233
|
-
}),
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
23
|
export function mapToTransactCreateRequest(
|
|
238
24
|
transaction: Withdrawal | Deposit,
|
|
239
25
|
payload: V1Transaction,
|
|
@@ -311,7 +97,9 @@ export function mapToAppendPiiRequest(
|
|
|
311
97
|
config: ResponseToIVMS101RequestConfig & Required<BaseRequestConfig>,
|
|
312
98
|
): TransactionIVMS101Request {
|
|
313
99
|
if (isWithdrawal(transaction)) {
|
|
314
|
-
|
|
100
|
+
// For outgoing transfers, the beneficiary is the counterparty — use the
|
|
101
|
+
// destination blockchain address as their accountNumber.
|
|
102
|
+
const beneficiaryAccountNumber = transaction.destination;
|
|
315
103
|
|
|
316
104
|
const beneficiaryPersons =
|
|
317
105
|
// If counterparty type is SELF, reuse originator data for beneficiary
|
|
@@ -319,7 +107,7 @@ export function mapToAppendPiiRequest(
|
|
|
319
107
|
? config.originator.originatorPerson
|
|
320
108
|
: // Convert all beneficiary persons from V1 to V2 format
|
|
321
109
|
ivms101.beneficiary?.beneficiaryPersons?.map((person) =>
|
|
322
|
-
convertPersonToV2(person,
|
|
110
|
+
convertPersonToV2(person, beneficiaryAccountNumber),
|
|
323
111
|
) || [];
|
|
324
112
|
|
|
325
113
|
return {
|
|
@@ -332,14 +120,17 @@ export function mapToAppendPiiRequest(
|
|
|
332
120
|
};
|
|
333
121
|
}
|
|
334
122
|
|
|
335
|
-
|
|
123
|
+
// For incoming transfers, the originator is the counterparty — use the
|
|
124
|
+
// source blockchain address as their accountNumber.
|
|
125
|
+
const source = (transaction as Deposit).source;
|
|
126
|
+
const originatorAccountNumber = Array.isArray(source) ? source[0] : source;
|
|
336
127
|
|
|
337
128
|
const originatorPersons =
|
|
338
129
|
transaction.counterparty?.type === PersonType.SELF && config.beneficiary
|
|
339
130
|
? config.beneficiary.beneficiaryPerson
|
|
340
131
|
: // Convert all originator persons from V1 to V2 format
|
|
341
132
|
ivms101.originator?.originatorPersons?.map((person) =>
|
|
342
|
-
convertPersonToV2(person,
|
|
133
|
+
convertPersonToV2(person, originatorAccountNumber),
|
|
343
134
|
) || [];
|
|
344
135
|
|
|
345
136
|
return {
|
|
@@ -8,18 +8,13 @@ import {
|
|
|
8
8
|
type TransactionResponse,
|
|
9
9
|
type Withdrawal,
|
|
10
10
|
} from '../types';
|
|
11
|
-
import {
|
|
12
|
-
mapToAppendPiiRequest,
|
|
13
|
-
mapToTransactCreateRequest,
|
|
14
|
-
mapToV1CreateRequest,
|
|
15
|
-
} from './mappers';
|
|
11
|
+
import { mapToAppendPiiRequest, mapToTransactCreateRequest } from './mappers';
|
|
16
12
|
import type {
|
|
17
13
|
BaseRequestConfig,
|
|
18
14
|
DelegateToken,
|
|
19
15
|
ResponseToIVMS101RequestConfig,
|
|
20
16
|
ResponseToTxCreateRequestConfig,
|
|
21
17
|
ResponseToTxRequestConfig,
|
|
22
|
-
TransactionCreateRequest,
|
|
23
18
|
TransactionCreateRequestV2,
|
|
24
19
|
TransactionIVMS101Request,
|
|
25
20
|
} from './types';
|
|
@@ -147,57 +142,6 @@ export function enrichConfig(
|
|
|
147
142
|
Required<BaseRequestConfig>;
|
|
148
143
|
}
|
|
149
144
|
|
|
150
|
-
/**
|
|
151
|
-
* Transforms a Notabene component response to a Version 1 API request body
|
|
152
|
-
*
|
|
153
|
-
* @param response - The response from the Notabene TX Create component
|
|
154
|
-
* @returns The transformed request body ready for the Version 1 API
|
|
155
|
-
*
|
|
156
|
-
* @example
|
|
157
|
-
* ```typescript
|
|
158
|
-
* import { componentResponseToV1TxCreateRequest } from '$lib/notabene-tx-transformer';
|
|
159
|
-
*
|
|
160
|
-
* withdrawal.on('complete', async (result) => {
|
|
161
|
-
* const requestBody = componentResponseToV1TxCreateRequest(result.response);
|
|
162
|
-
*
|
|
163
|
-
* await fetch(endpointUrl, {
|
|
164
|
-
* method: 'POST',
|
|
165
|
-
* body: JSON.stringify(requestBody)
|
|
166
|
-
* });
|
|
167
|
-
* });
|
|
168
|
-
* ```
|
|
169
|
-
*/
|
|
170
|
-
export function componentResponseToV1TxCreateRequest(
|
|
171
|
-
response: TransactionResponse<Withdrawal>,
|
|
172
|
-
): TransactionCreateRequest {
|
|
173
|
-
if (!response.txCreate || !response.ivms101) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
'Invalid response: missing required txCreate or ivms101 data',
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const { value, ivms101, proof, txCreate } = response;
|
|
180
|
-
|
|
181
|
-
// Build withdrawal object from response data for V1 API
|
|
182
|
-
const withdrawal: Withdrawal = {
|
|
183
|
-
destination: value?.destination || '',
|
|
184
|
-
counterparty: value?.counterparty || {},
|
|
185
|
-
agent: value?.agent,
|
|
186
|
-
account: value?.account,
|
|
187
|
-
proof,
|
|
188
|
-
asset:
|
|
189
|
-
value?.asset ||
|
|
190
|
-
(typeof txCreate.transactionAsset === 'string'
|
|
191
|
-
? txCreate.transactionAsset
|
|
192
|
-
: txCreate.transactionAsset?.caip19) ||
|
|
193
|
-
'',
|
|
194
|
-
amountDecimal: value?.amountDecimal ?? txCreate.transactionAmount ?? 0,
|
|
195
|
-
customer: value?.customer,
|
|
196
|
-
} as Withdrawal;
|
|
197
|
-
|
|
198
|
-
return mapToV1CreateRequest(withdrawal, txCreate, ivms101 as any);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
145
|
/**
|
|
202
146
|
* Transforms a Notabene component response into txCreate, IVMS101, and confirmRelationship request bodies
|
|
203
147
|
*
|
|
@@ -32,24 +32,6 @@ export interface ResponseToIVMS101RequestConfig extends BaseRequestConfig {
|
|
|
32
32
|
export type ResponseToTxRequestConfig = ResponseToTxCreateRequestConfig &
|
|
33
33
|
ResponseToIVMS101RequestConfig;
|
|
34
34
|
|
|
35
|
-
export interface TransactionCreateRequest {
|
|
36
|
-
transactionAsset: any;
|
|
37
|
-
transactionAmount: string;
|
|
38
|
-
beneficiaryDid?: string;
|
|
39
|
-
originatorVASPdid: string;
|
|
40
|
-
beneficiaryVASPdid?: string;
|
|
41
|
-
beneficiaryVASPname?: string;
|
|
42
|
-
beneficiaryVASPwebsite?: string;
|
|
43
|
-
transactionBlockchainInfo: {
|
|
44
|
-
origin?: string;
|
|
45
|
-
destination?: string;
|
|
46
|
-
};
|
|
47
|
-
beneficiaryProof?: any;
|
|
48
|
-
beneficiary?: any;
|
|
49
|
-
originator?: any;
|
|
50
|
-
originatorEqualsBeneficiary?: boolean;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
35
|
export interface TransactionCreateRequestV2 {
|
|
54
36
|
originator: {
|
|
55
37
|
'@id': string;
|
|
@@ -24,6 +24,14 @@ describe('MessageEventManager', () => {
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
describe('setPort', () => {
|
|
27
|
+
it('should ignore undefined port', () => {
|
|
28
|
+
expect(() =>
|
|
29
|
+
messageEventManager.setPort(undefined as unknown as MessagePort),
|
|
30
|
+
).not.toThrow();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('setPort with valid port', () => {
|
|
27
35
|
beforeEach(() => {
|
|
28
36
|
messageEventManager.setPort(mockPort);
|
|
29
37
|
});
|