@notabene/javascript-sdk 1.34.0 → 2.0.0-next.10
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 +113 -231
- package/dist/notabene.cjs +1 -0
- package/dist/notabene.d.ts +780 -0
- package/dist/notabene.js +173 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/package.json +38 -59
- package/src/__tests__/notabene.test.ts +159 -0
- package/src/arbitraries.ts +13 -0
- package/src/components/EmbeddedComponent.ts +185 -0
- package/src/components/__tests__/EmbeddedComponent.test.ts +160 -0
- package/src/ivms/types.ts +71 -28
- package/src/notabene.ts +155 -287
- package/src/types.ts +434 -67
- package/src/utils/MessageEventManager.ts +54 -0
- package/src/utils/__tests__/MessageEventManager.test.ts +95 -0
- package/src/utils/arbitraries.ts +26 -0
- package/src/utils/caip.ts +16 -0
- package/src/utils/urls.ts +15 -0
- package/.editorconfig +0 -10
- package/.envrc.template +0 -1
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -13
- package/.gitlab-ci.yml +0 -74
- package/.husky/commit-msg +0 -4
- package/.husky/pre-commit +0 -4
- package/.husky/pre-push +0 -4
- package/.nvmrc +0 -1
- package/.prettierrc +0 -4
- package/.releaserc.json +0 -16
- package/.tool-versions +0 -3
- package/.vscode/extensions.json +0 -7
- package/.vscode/settings.json +0 -11
- package/CODEOWNERS +0 -1
- package/dist/es/index.js +0 -1
- package/dist/lib/index.js +0 -376
- package/jest.config.js +0 -5
- package/public/index.html +0 -93
- package/public/js/.gitkeep +0 -0
- package/src/lib/index.ts +0 -2
- package/src/module/index.ts +0 -10
- package/src/zoidComponentProps.ts +0 -81
- package/tsconfig.json +0 -18
package/src/types.ts
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Beneficiary,
|
|
3
|
+
DateAndPlaceOfBirth,
|
|
4
|
+
IVMS101,
|
|
5
|
+
NationalIdentification,
|
|
6
|
+
Originator,
|
|
7
|
+
} from './ivms/types';
|
|
2
8
|
|
|
9
|
+
export type { IVMS101 };
|
|
10
|
+
|
|
11
|
+
export type CAIP2 = `${string}:${string}`;
|
|
12
|
+
export type CAIP10 = `${CAIP2}:${string}`;
|
|
13
|
+
export type CAIP19 = `${CAIP2}/${string}:${string}`;
|
|
14
|
+
export type CAIP220 = string;
|
|
15
|
+
|
|
16
|
+
export type DTI = string;
|
|
17
|
+
export type NotabeneAsset = string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The asset of a transaction either a Notabene asset, a CAIP-19 asset, or a DTI.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export type TransactionAsset = NotabeneAsset | CAIP19 | DTI;
|
|
26
|
+
|
|
27
|
+
export type BlockchainAddress = string;
|
|
28
|
+
export type TravelAddress = `ta${string}`;
|
|
29
|
+
export type CryptoCredential = `${string}.${string}.mastercard`;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The destination of a transaction either a blockchain address, a CAIP-19 address, or a travel address.
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export type Destination =
|
|
36
|
+
| BlockchainAddress
|
|
37
|
+
| CAIP10
|
|
38
|
+
| CryptoCredential
|
|
39
|
+
| TravelAddress;
|
|
40
|
+
export type Source = BlockchainAddress | CAIP10;
|
|
41
|
+
export type URI = string;
|
|
42
|
+
export type DID = `did:${string}:${string}`;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The theme of the Notabene SDK
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
3
48
|
export type Theme = {
|
|
4
49
|
primaryColor: string;
|
|
5
50
|
secondaryColor: string;
|
|
@@ -7,21 +52,40 @@ export type Theme = {
|
|
|
7
52
|
logo: string;
|
|
8
53
|
};
|
|
9
54
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
55
|
+
// export type TransactionType = 'VASP_2_VASP' | 'SELF_HOSTED';
|
|
56
|
+
|
|
57
|
+
// export type TransactionTypeAllowed =
|
|
58
|
+
// | 'ALL'
|
|
59
|
+
// | 'VASP_2_VASP_ONLY'
|
|
60
|
+
// | 'FIRST_PARTY_ONLY';
|
|
14
61
|
|
|
15
|
-
export type
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
62
|
+
// export type NonCustodialDeclarationType =
|
|
63
|
+
// | 'SIGNATURE'
|
|
64
|
+
// | 'DECLARATION'
|
|
65
|
+
// | 'SIGNATURE_AND_DECLARATION';
|
|
19
66
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
67
|
+
/**
|
|
68
|
+
* The type of Agent. Either a wallet or a VASP
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
24
71
|
|
|
72
|
+
export enum AgentType {
|
|
73
|
+
PRIVATE = 'WALLET',
|
|
74
|
+
VASP = 'VASP',
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Who is the agent acting on behalf of the counterparty
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export declare interface Agent {
|
|
82
|
+
did: DID;
|
|
83
|
+
type: AgentType;
|
|
84
|
+
logo?: string;
|
|
85
|
+
url?: string;
|
|
86
|
+
name?: string;
|
|
87
|
+
verified?: boolean;
|
|
88
|
+
}
|
|
25
89
|
export type OwnershipProofInput = {
|
|
26
90
|
type?: string | null;
|
|
27
91
|
proof?: string | null;
|
|
@@ -37,55 +101,177 @@ export type CountryType = {
|
|
|
37
101
|
name: string;
|
|
38
102
|
};
|
|
39
103
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
export
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
/**
|
|
105
|
+
* The type of counterparty. Either a natural person or a legal person. If the customer is the same as the counterparty then the counterparty is a self.
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
export enum PersonType {
|
|
109
|
+
NATURAL = 'natural',
|
|
110
|
+
LEGAL = 'legal',
|
|
111
|
+
SELF = 'self', // first party
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* A VASP agent acting on behalf of the counterparty
|
|
116
|
+
* @public
|
|
117
|
+
*/
|
|
118
|
+
export interface VASP extends Agent {
|
|
119
|
+
url?: string;
|
|
120
|
+
name?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* A wallet agent acting on behalf of the counterparty
|
|
124
|
+
* @public
|
|
125
|
+
*/
|
|
126
|
+
export interface Wallet extends Agent {
|
|
127
|
+
proof: OwnershipProof;
|
|
128
|
+
wallet_connect_id?: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The counterparty of a transaction.
|
|
133
|
+
* @public
|
|
134
|
+
*/
|
|
135
|
+
export interface Counterparty {
|
|
136
|
+
name?: string;
|
|
137
|
+
accountNumber?: string;
|
|
138
|
+
did?: string;
|
|
139
|
+
geographicAddress?: string;
|
|
140
|
+
type?: PersonType;
|
|
141
|
+
verified?: boolean;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* A counterparty object representing a natural person
|
|
145
|
+
* @public
|
|
146
|
+
*/
|
|
147
|
+
export interface NaturalPerson extends Counterparty {
|
|
148
|
+
type: PersonType.NATURAL;
|
|
149
|
+
nationalIdentification?: NationalIdentification;
|
|
150
|
+
dateAndPlaceOfBirth?: DateAndPlaceOfBirth;
|
|
151
|
+
name: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* A counterparty object representing a legal person
|
|
156
|
+
* @public
|
|
157
|
+
*/
|
|
158
|
+
export interface LegalPerson extends Counterparty {
|
|
159
|
+
type: PersonType.LEGAL;
|
|
160
|
+
name: string;
|
|
161
|
+
lei?: string;
|
|
162
|
+
url?: string;
|
|
163
|
+
logo?: string;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
type OriginatorFields = {
|
|
167
|
+
source?: Source;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
type BeneficiaryFields = {
|
|
171
|
+
destination?: Destination;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
type DepositRequestFields = {
|
|
175
|
+
destinations: Destination[];
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* An abstract transaction object
|
|
180
|
+
* @public
|
|
181
|
+
*/
|
|
182
|
+
export interface Transaction {
|
|
183
|
+
agent: Agent;
|
|
184
|
+
customer?: Counterparty;
|
|
185
|
+
counterparty: Counterparty;
|
|
186
|
+
asset: TransactionAsset;
|
|
187
|
+
amountDecimal: number;
|
|
188
|
+
// transactionBlockchainInfo?: TransactionBlockchainInfo;
|
|
189
|
+
customAssetPrice?: {
|
|
190
|
+
price: number;
|
|
191
|
+
currency: string;
|
|
88
192
|
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* An object representing a withdrawal transaction
|
|
197
|
+
* @public
|
|
198
|
+
*/
|
|
199
|
+
export interface Withdrawal extends BeneficiaryFields, Transaction {}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* An object representing a deposit transaction
|
|
203
|
+
* @public
|
|
204
|
+
*/
|
|
205
|
+
export interface Deposit extends OriginatorFields, Transaction {}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* An object representing a request for a deposit
|
|
209
|
+
* @public
|
|
210
|
+
*/
|
|
211
|
+
export interface DepositRequest extends DepositRequestFields, Transaction {}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Configuration options for Transaction components
|
|
215
|
+
* @public
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
export interface TransactionOptions {
|
|
219
|
+
microTransactionAddress?: BlockchainAddress;
|
|
220
|
+
proofFallbacks?: ProofTypes[];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The verification status of a transaction
|
|
225
|
+
* @public
|
|
226
|
+
*/
|
|
227
|
+
export enum Status {
|
|
228
|
+
EMPTY = 'empty',
|
|
229
|
+
VERIFY = 'verify',
|
|
230
|
+
PENDING = 'pending',
|
|
231
|
+
VERIFIED = 'verified',
|
|
232
|
+
BANNED = 'banned',
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
type V1Asset =
|
|
236
|
+
| {
|
|
237
|
+
caip19: CAIP19;
|
|
238
|
+
}
|
|
239
|
+
| string;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Transaction payload suitable for calling Notabene v1 tx/create
|
|
243
|
+
* @public
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
export type V1Transaction = {
|
|
247
|
+
transactionAsset: V1Asset;
|
|
248
|
+
transactionAmount: string;
|
|
249
|
+
originatorEqualsBeneficiary?: boolean;
|
|
250
|
+
originatorVASPdid: DID;
|
|
251
|
+
beneficiaryVASPdid: DID;
|
|
252
|
+
beneficiaryProof: OwnershipProof;
|
|
253
|
+
originator: Originator;
|
|
254
|
+
beneficiary: Beneficiary;
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* The response of a transaction
|
|
258
|
+
* @public
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
export type TransactionResponse = {
|
|
262
|
+
value: Transaction;
|
|
263
|
+
ivms: IVMS101;
|
|
264
|
+
proof?: OwnershipProof;
|
|
265
|
+
valid: boolean;
|
|
266
|
+
status: Status;
|
|
267
|
+
errors: ValidationError[];
|
|
268
|
+
txCreate?: V1Transaction;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export type ValidationError = {
|
|
272
|
+
attribute: string;
|
|
273
|
+
message: string;
|
|
274
|
+
};
|
|
89
275
|
|
|
90
276
|
export type FieldProps = {
|
|
91
277
|
forceDisplay?: boolean; // instead of beneficiaryDetails - defaults to false
|
|
@@ -104,12 +290,193 @@ export type FieldsProps = {
|
|
|
104
290
|
[name in FieldName]?: FieldProps;
|
|
105
291
|
};
|
|
106
292
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Component Message Types
|
|
295
|
+
* @internal
|
|
296
|
+
*/
|
|
297
|
+
export const enum CMType {
|
|
298
|
+
COMPLETE = 'complete',
|
|
299
|
+
RESIZE = 'resize',
|
|
300
|
+
RESULT = 'result',
|
|
301
|
+
READY = 'ready',
|
|
302
|
+
INVALID = 'invalid',
|
|
303
|
+
MODAL = 'openModal',
|
|
304
|
+
ERROR = 'error',
|
|
305
|
+
CLOSE = 'closeModal',
|
|
306
|
+
CANCEL = 'cancel',
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export type Completed = {
|
|
310
|
+
type: CMType.COMPLETE;
|
|
311
|
+
response: TransactionResponse;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
export type Result = {
|
|
315
|
+
type: CMType.RESULT;
|
|
316
|
+
reqid: RequestID;
|
|
317
|
+
response: TransactionResponse;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export type Ready = {
|
|
321
|
+
type: CMType.READY;
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
export type ResizeRequest = {
|
|
325
|
+
type: CMType.RESIZE;
|
|
326
|
+
height: number;
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
export type Error = {
|
|
330
|
+
type: CMType.ERROR;
|
|
331
|
+
message: string;
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
export type ModalRequest = {
|
|
335
|
+
type: CMType.MODAL;
|
|
336
|
+
url: string;
|
|
337
|
+
reqid: RequestID;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export type CloseModal = {
|
|
341
|
+
type: CMType.CLOSE;
|
|
342
|
+
reqid: RequestID;
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
export type Cancel = {
|
|
346
|
+
type: CMType.CANCEL;
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
export type InvalidValue = {
|
|
350
|
+
type: CMType.INVALID;
|
|
351
|
+
value: any;
|
|
352
|
+
errors: ValidationError[];
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Component Message
|
|
357
|
+
* @internal
|
|
358
|
+
*/
|
|
359
|
+
export type ComponentMessage =
|
|
360
|
+
| Completed
|
|
361
|
+
| Cancel
|
|
362
|
+
| Error
|
|
363
|
+
| Result
|
|
364
|
+
| Ready
|
|
365
|
+
| ResizeRequest
|
|
366
|
+
| ModalRequest
|
|
367
|
+
| InvalidValue
|
|
368
|
+
| CloseModal;
|
|
369
|
+
|
|
370
|
+
export type RequestID = string;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Host Message Types
|
|
374
|
+
* @internal
|
|
375
|
+
*/
|
|
376
|
+
|
|
377
|
+
export const enum HMType {
|
|
378
|
+
UPDATE = 'update',
|
|
379
|
+
REQUEST_RESPONSE = 'requestResponse',
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export type UpdateValue = {
|
|
383
|
+
type: HMType.UPDATE;
|
|
384
|
+
value: Partial<Transaction>;
|
|
110
385
|
};
|
|
111
386
|
|
|
112
|
-
|
|
113
|
-
|
|
387
|
+
export type RequestResponse = {
|
|
388
|
+
type: HMType.REQUEST_RESPONSE;
|
|
389
|
+
reqid: RequestID;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Host Messages
|
|
394
|
+
* @internal
|
|
395
|
+
*/
|
|
396
|
+
|
|
397
|
+
export type HostMessage = UpdateValue | RequestResponse;
|
|
398
|
+
|
|
399
|
+
export interface CallbackOptions {
|
|
400
|
+
callback?: URI;
|
|
401
|
+
redirectUri?: URI;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Status of the proof
|
|
406
|
+
* @public
|
|
407
|
+
*/
|
|
408
|
+
export enum ProofStatus {
|
|
409
|
+
PENDING = 'pending', // Verification is pending
|
|
410
|
+
FAILED = 'rejected', // Rejected
|
|
411
|
+
FLAGGED = 'flagged', // Flagged for manual review
|
|
412
|
+
VERIFIED = 'verified', // Verified
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* The type of Proofs supported
|
|
417
|
+
* @public
|
|
418
|
+
**/
|
|
419
|
+
export enum ProofTypes {
|
|
420
|
+
SelfDeclaration = 'self-declaration',
|
|
421
|
+
PersonalSignEIP191 = 'eip-191',
|
|
422
|
+
PersonalSignEIP712 = 'eip-712',
|
|
423
|
+
PersonalSignBIP137 = 'bip-137',
|
|
424
|
+
PersonalSignXPUB = 'xpub',
|
|
425
|
+
MicroTransfer = 'microtransfer',
|
|
426
|
+
Screenshot = 'screenshot',
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Ownership Proof
|
|
430
|
+
* @public
|
|
431
|
+
*/
|
|
432
|
+
export interface OwnershipProof {
|
|
433
|
+
type: ProofTypes;
|
|
434
|
+
status: ProofStatus;
|
|
435
|
+
did: DID;
|
|
436
|
+
address: CAIP10;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Ownership Proof using Message Signature
|
|
441
|
+
* @public
|
|
442
|
+
*/
|
|
443
|
+
export interface SignatureProof extends OwnershipProof {
|
|
444
|
+
type:
|
|
445
|
+
| ProofTypes.PersonalSignEIP191
|
|
446
|
+
| ProofTypes.PersonalSignEIP712
|
|
447
|
+
| ProofTypes.PersonalSignBIP137
|
|
448
|
+
| ProofTypes.PersonalSignXPUB;
|
|
449
|
+
proof: string;
|
|
450
|
+
attestation: string;
|
|
451
|
+
wallet_provider: string;
|
|
452
|
+
}
|
|
114
453
|
|
|
115
|
-
|
|
454
|
+
/**
|
|
455
|
+
* Ownership Proof using Self Declaration
|
|
456
|
+
* @public
|
|
457
|
+
*/
|
|
458
|
+
export interface DeclarationProof extends OwnershipProof {
|
|
459
|
+
type: ProofTypes.SelfDeclaration;
|
|
460
|
+
attestation: string;
|
|
461
|
+
confirmed: boolean;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Ownership Proof using Micro Transfer
|
|
466
|
+
* @public
|
|
467
|
+
*/
|
|
468
|
+
export interface MicroTransferProof extends OwnershipProof {
|
|
469
|
+
type: ProofTypes.MicroTransfer;
|
|
470
|
+
txhash: string;
|
|
471
|
+
chain: CAIP2;
|
|
472
|
+
amount: number;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Ownership Proof using Screenshot
|
|
477
|
+
* @public
|
|
478
|
+
*/
|
|
479
|
+
export interface ScreenshotProof extends OwnershipProof {
|
|
480
|
+
type: ProofTypes.Screenshot;
|
|
481
|
+
url: string;
|
|
482
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ComponentMessage, HostMessage } from '../types';
|
|
2
|
+
|
|
3
|
+
export type MessageCallback = (message: ComponentMessage) => void;
|
|
4
|
+
|
|
5
|
+
export class MessageEventManager {
|
|
6
|
+
private listeners: Map<string, Set<MessageCallback>> = new Map();
|
|
7
|
+
private port?: MessagePort;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this.handleMessage = this.handleMessage.bind(this);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
setPort(port: MessagePort): void {
|
|
14
|
+
this.port = port;
|
|
15
|
+
this.port.onmessage = this.handleMessage;
|
|
16
|
+
this.port.start();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
on(messageType: string, callback: MessageCallback): void {
|
|
20
|
+
if (!this.listeners.has(messageType)) {
|
|
21
|
+
this.listeners.set(messageType, new Set());
|
|
22
|
+
}
|
|
23
|
+
this.listeners.get(messageType)!.add(callback);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
off(messageType: string, callback: MessageCallback): void {
|
|
27
|
+
const callbacks = this.listeners.get(messageType);
|
|
28
|
+
if (callbacks) {
|
|
29
|
+
callbacks.delete(callback);
|
|
30
|
+
if (callbacks.size === 0) {
|
|
31
|
+
this.listeners.delete(messageType);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private handleMessage(event: MessageEvent): void {
|
|
37
|
+
console.log('received message', event.data);
|
|
38
|
+
const message = event.data;
|
|
39
|
+
if (typeof message === 'object' && message !== null && 'type' in message) {
|
|
40
|
+
const messageType = message.type as string;
|
|
41
|
+
const callbacks = this.listeners.get(messageType);
|
|
42
|
+
if (callbacks) {
|
|
43
|
+
callbacks.forEach((callback) => callback(message));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Method to send messages through the port
|
|
49
|
+
send(message: HostMessage): void {
|
|
50
|
+
if (this.port) {
|
|
51
|
+
this.port.postMessage(message);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { HMType, UpdateValue } from '../../types';
|
|
3
|
+
import { MessageEventManager } from '../MessageEventManager';
|
|
4
|
+
|
|
5
|
+
describe('MessageEventManager', () => {
|
|
6
|
+
let messageEventManager: MessageEventManager;
|
|
7
|
+
let mockPort: MessagePort;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockPort = {
|
|
11
|
+
onmessage: null,
|
|
12
|
+
postMessage: vi.fn(),
|
|
13
|
+
start: vi.fn(),
|
|
14
|
+
} as unknown as MessagePort;
|
|
15
|
+
|
|
16
|
+
messageEventManager = new MessageEventManager();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('setPort', () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
messageEventManager.setPort(mockPort);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should start the port when initialized', () => {
|
|
25
|
+
expect(mockPort.start).toHaveBeenCalled();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should subscribe and receive messages of a specific type', () => {
|
|
29
|
+
const readyHandler = vi.fn();
|
|
30
|
+
messageEventManager.on('ready', readyHandler);
|
|
31
|
+
|
|
32
|
+
const readyMessage = { type: 'ready' };
|
|
33
|
+
mockPort.onmessage!({ data: readyMessage } as MessageEvent);
|
|
34
|
+
|
|
35
|
+
expect(readyHandler).toHaveBeenCalledWith(readyMessage);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should not call handlers for different message types', () => {
|
|
39
|
+
const updateHandler = vi.fn();
|
|
40
|
+
const errorHandler = vi.fn();
|
|
41
|
+
messageEventManager.on('update', updateHandler);
|
|
42
|
+
messageEventManager.on('error', errorHandler);
|
|
43
|
+
|
|
44
|
+
const errorMessage = { type: 'error', message: 'Something went wrong' };
|
|
45
|
+
mockPort.onmessage!({ data: errorMessage } as MessageEvent);
|
|
46
|
+
|
|
47
|
+
expect(updateHandler).not.toHaveBeenCalled();
|
|
48
|
+
expect(errorHandler).toHaveBeenCalledWith(errorMessage);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should unsubscribe handlers', () => {
|
|
52
|
+
const updateHandler = vi.fn();
|
|
53
|
+
messageEventManager.on('update', updateHandler);
|
|
54
|
+
messageEventManager.off('update', updateHandler);
|
|
55
|
+
|
|
56
|
+
const updateMessage = { type: 'update', data: { foo: 'bar' } };
|
|
57
|
+
mockPort.onmessage!({ data: updateMessage } as MessageEvent);
|
|
58
|
+
|
|
59
|
+
expect(updateHandler).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should allow multiple subscribers for the same message type', () => {
|
|
63
|
+
const updateHandler1 = vi.fn();
|
|
64
|
+
const updateHandler2 = vi.fn();
|
|
65
|
+
messageEventManager.on('update', updateHandler1);
|
|
66
|
+
messageEventManager.on('update', updateHandler2);
|
|
67
|
+
|
|
68
|
+
const updateMessage = { type: 'update', data: { foo: 'bar' } };
|
|
69
|
+
mockPort.onmessage!({ data: updateMessage } as MessageEvent);
|
|
70
|
+
|
|
71
|
+
expect(updateHandler1).toHaveBeenCalledWith(updateMessage);
|
|
72
|
+
expect(updateHandler2).toHaveBeenCalledWith(updateMessage);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should send messages through the port', () => {
|
|
76
|
+
const message: UpdateValue = {
|
|
77
|
+
type: HMType.UPDATE,
|
|
78
|
+
value: { asset: 'USDC' },
|
|
79
|
+
};
|
|
80
|
+
messageEventManager.send(message);
|
|
81
|
+
|
|
82
|
+
expect(mockPort.postMessage).toHaveBeenCalledWith(message);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should ignore messages without a type', () => {
|
|
86
|
+
const handler = vi.fn();
|
|
87
|
+
messageEventManager.on('update', handler);
|
|
88
|
+
|
|
89
|
+
const invalidMessage = { data: 'no type field' };
|
|
90
|
+
mockPort.onmessage!({ data: invalidMessage } as MessageEvent);
|
|
91
|
+
|
|
92
|
+
expect(handler).not.toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fc from 'fast-check';
|
|
2
|
+
import type { CAIP10, CAIP19, CAIP2, CAIP220 } from '../types';
|
|
3
|
+
import {
|
|
4
|
+
CAIP10_MATCHER,
|
|
5
|
+
CAIP19_MATCHER,
|
|
6
|
+
CAIP220_MATCHER,
|
|
7
|
+
CAIP2_MATCHER,
|
|
8
|
+
} from './caip';
|
|
9
|
+
|
|
10
|
+
const LOCALE = new RegExp(/^[a-z]{2}(-[A-Z]{2})?$/);
|
|
11
|
+
|
|
12
|
+
// Arbitraries
|
|
13
|
+
export const arbitraryCAIP10 = (): fc.Arbitrary<CAIP10> =>
|
|
14
|
+
fc.stringMatching(CAIP10_MATCHER) as fc.Arbitrary<CAIP10>;
|
|
15
|
+
|
|
16
|
+
export const arbitraryCAIP2 = (): fc.Arbitrary<CAIP2> =>
|
|
17
|
+
fc.stringMatching(CAIP2_MATCHER) as fc.Arbitrary<CAIP2>;
|
|
18
|
+
|
|
19
|
+
export const arbitraryCAIP19 = (): fc.Arbitrary<CAIP19> =>
|
|
20
|
+
fc.stringMatching(CAIP19_MATCHER) as fc.Arbitrary<CAIP19>;
|
|
21
|
+
|
|
22
|
+
export const arbitraryCAIP220 = (): fc.Arbitrary<CAIP220> =>
|
|
23
|
+
fc.stringMatching(CAIP220_MATCHER) as fc.Arbitrary<CAIP220>;
|
|
24
|
+
|
|
25
|
+
export const arbitraryLocale = (): fc.Arbitrary<string> =>
|
|
26
|
+
fc.stringMatching(LOCALE) as fc.Arbitrary<string>;
|