@idos-network/credentials 1.2.0 → 2.2.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/README.md +289 -85
- package/assets/idos-credential-subject-edd-v1.json +10 -0
- package/assets/idos-credential-subject-v1.json +1 -1
- package/assets/idos-credential-subject-v2.json +1 -1
- package/assets/idos-credential-subject-v3.json +83 -0
- package/assets/idos-credentials-v1.json +2 -2
- package/assets/idos-credentials-v2.json +10 -0
- package/dist/index-0NqXMjNk.d.mts +395 -0
- package/dist/index-0NqXMjNk.d.mts.map +1 -0
- package/dist/index-WW372Tf5.d.mts +57 -0
- package/dist/index-WW372Tf5.d.mts.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/loader-Cg6hs1-P.mjs +2 -0
- package/dist/loader-Cg6hs1-P.mjs.map +1 -0
- package/dist/parser/index.d.mts +19 -0
- package/dist/parser/index.d.mts.map +1 -0
- package/dist/parser/index.mjs +2 -0
- package/dist/parser/index.mjs.map +1 -0
- package/dist/schemas/index.d.mts +2 -0
- package/dist/schemas/index.mjs +1 -0
- package/dist/schemas-BVGuUlPe.mjs +2 -0
- package/dist/schemas-BVGuUlPe.mjs.map +1 -0
- package/dist/types/index.d.mts +2 -135
- package/dist/types/index.mjs +1 -63
- package/dist/utils/index.d.mts +38 -22
- package/dist/utils/index.d.mts.map +1 -1
- package/dist/utils/index.mjs +1 -123
- package/dist/utils/index.mjs.map +1 -1
- package/dist/verifier/index.d.mts +8 -0
- package/dist/verifier/index.d.mts.map +1 -0
- package/dist/verifier/index.mjs +2 -0
- package/dist/verifier/index.mjs.map +1 -0
- package/package.json +31 -15
- package/src/parser/index.test.ts +266 -0
- package/src/parser/index.ts +69 -0
- package/src/schemas/EddV1/index.test.ts +40 -0
- package/src/schemas/EddV1/index.ts +53 -0
- package/src/schemas/Envelope.ts +37 -0
- package/src/schemas/FaceIdV1/index.test.ts +26 -0
- package/src/schemas/FaceIdV1/index.ts +33 -0
- package/src/schemas/KycV1/IdDocument.ts +41 -0
- package/src/schemas/KycV1/ResidentialAddress.ts +56 -0
- package/src/schemas/KycV1/Subject.ts +86 -0
- package/src/schemas/KycV1/index.test.ts +156 -0
- package/src/schemas/KycV1/index.ts +40 -0
- package/src/schemas/KycV2/Subject.ts +67 -0
- package/src/schemas/KycV2/index.test.ts +162 -0
- package/src/schemas/KycV2/index.ts +45 -0
- package/src/schemas/KycV3/Biometric.ts +14 -0
- package/src/schemas/KycV3/Contact.ts +13 -0
- package/src/schemas/KycV3/EDD.ts +32 -0
- package/src/schemas/KycV3/IdDocument.ts +92 -0
- package/src/schemas/KycV3/Onboarding.ts +36 -0
- package/src/schemas/KycV3/Person.ts +105 -0
- package/src/schemas/KycV3/ResidentialAddress.ts +73 -0
- package/src/schemas/KycV3/Screening.ts +27 -0
- package/src/schemas/KycV3/SourceOfWealth.ts +44 -0
- package/src/schemas/KycV3/Subject.ts +54 -0
- package/src/schemas/KycV3/index.test.ts +682 -0
- package/src/schemas/KycV3/index.ts +108 -0
- package/src/schemas/VerifiableCredential.ts +232 -0
- package/src/schemas/enums.ts +126 -0
- package/src/schemas/index.ts +14 -0
- package/src/schemas/integration.test.ts +251 -0
- package/src/schemas/types.ts +11 -0
- package/src/schemas/utils.ts +274 -0
- package/src/types/credentials.ts +18 -249
- package/src/utils/{utils.test.ts → index.test.ts} +59 -67
- package/src/utils/index.ts +129 -137
- package/src/utils/issuer.ts +42 -0
- package/src/{builder → utils}/loader.ts +22 -17
- package/src/verifier/index.test.ts +149 -0
- package/src/{builder/verifier.ts → verifier/index.ts} +4 -8
- package/types/internals.d.ts +11 -6
- package/dist/builder/index.d.mts +0 -20
- package/dist/builder/index.d.mts.map +0 -1
- package/dist/builder/index.mjs +0 -619
- package/dist/builder/index.mjs.map +0 -1
- package/dist/types/index.d.mts.map +0 -1
- package/dist/types/index.mjs.map +0 -1
- package/src/builder/builder.test.ts +0 -407
- package/src/builder/index.ts +0 -122
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PublicNotes } from "../types";
|
|
2
|
+
|
|
3
|
+
import { CONTEXT_IDOS_CREDENTIAL_V2, CONTEXT_IDOS_CREDENTIAL_V2_SUBJECT } from "../../utils/loader";
|
|
4
|
+
import { EnvelopeV2 } from "../Envelope";
|
|
5
|
+
import { VerifiableCredentialBase } from "../VerifiableCredential";
|
|
6
|
+
import { Subject } from "./Subject";
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* v2 derives its level the same way as v1; what changed is the subject context and the
|
|
10
|
+
* envelope, which gained `kycLevel` and the issuance dates — declared in v2's own,
|
|
11
|
+
* separately protected envelope context.
|
|
12
|
+
*/
|
|
13
|
+
export class KycV2 extends VerifiableCredentialBase<EnvelopeV2, Subject> {
|
|
14
|
+
static readonly envelopeContext: string = CONTEXT_IDOS_CREDENTIAL_V2;
|
|
15
|
+
static readonly subjectContext: string = CONTEXT_IDOS_CREDENTIAL_V2_SUBJECT;
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
super(EnvelopeV2, Subject);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override level(): string {
|
|
22
|
+
const { residentialAddress, selfieFile, email, phoneNumber } = this.subject;
|
|
23
|
+
|
|
24
|
+
// A complete address proof is the sign of plus.
|
|
25
|
+
const base =
|
|
26
|
+
residentialAddress?.proofFile &&
|
|
27
|
+
residentialAddress.city &&
|
|
28
|
+
residentialAddress.proofCategory &&
|
|
29
|
+
residentialAddress.country
|
|
30
|
+
? "plus"
|
|
31
|
+
: "basic";
|
|
32
|
+
|
|
33
|
+
const addons = [
|
|
34
|
+
selfieFile && "liveness",
|
|
35
|
+
email && "email",
|
|
36
|
+
phoneNumber && "phoneNumber",
|
|
37
|
+
].filter(Boolean);
|
|
38
|
+
|
|
39
|
+
return [base, ...addons].join("+");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
override publicNotes(): PublicNotes {
|
|
43
|
+
return { type: "kyc", level: this.level() };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IsNumber, IsOptional } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { Base85FileField } from "../utils";
|
|
4
|
+
|
|
5
|
+
export class Biometric {
|
|
6
|
+
/* The person's selfie image. */
|
|
7
|
+
@Base85FileField()
|
|
8
|
+
selfieFile: Buffer;
|
|
9
|
+
|
|
10
|
+
/* A score indicating whether the selfie/liveness photo matches the document photo. */
|
|
11
|
+
@IsOptional()
|
|
12
|
+
@IsNumber()
|
|
13
|
+
selfieMatch?: number;
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IsEmail, IsOptional, IsString } from "class-validator";
|
|
2
|
+
|
|
3
|
+
export class Contact {
|
|
4
|
+
/* The person's email address. */
|
|
5
|
+
@IsOptional()
|
|
6
|
+
@IsEmail()
|
|
7
|
+
email?: string;
|
|
8
|
+
|
|
9
|
+
/* The person's phone number. */
|
|
10
|
+
@IsOptional()
|
|
11
|
+
@IsString()
|
|
12
|
+
phoneNumber?: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { IsIn, IsMimeType, IsOptional, IsString } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { Occupations, type Occupation } from "../enums";
|
|
4
|
+
import { Base85FileField, RequiredWhen } from "../utils";
|
|
5
|
+
|
|
6
|
+
export class EDD {
|
|
7
|
+
/* The person's occupation or job title. */
|
|
8
|
+
@IsOptional()
|
|
9
|
+
@IsIn(Occupations)
|
|
10
|
+
occupation?: Occupation;
|
|
11
|
+
|
|
12
|
+
/* The origin of money used in transactions (e.g. salary, business income, savings). */
|
|
13
|
+
@IsOptional()
|
|
14
|
+
@IsString()
|
|
15
|
+
sourceOfFundsCategory?: string;
|
|
16
|
+
|
|
17
|
+
/* A file containing proof of the person's source of funds. */
|
|
18
|
+
@IsOptional()
|
|
19
|
+
@Base85FileField()
|
|
20
|
+
sourceOfFundsProofFile?: Buffer;
|
|
21
|
+
|
|
22
|
+
/* Type of the document provided as proof of the person's source of funds. */
|
|
23
|
+
@RequiredWhen((edd: EDD) => !!edd.sourceOfFundsProofFile)
|
|
24
|
+
@IsString()
|
|
25
|
+
@IsMimeType()
|
|
26
|
+
sourceOfFundsProofFileType?: string;
|
|
27
|
+
|
|
28
|
+
/* Name of the document provided as proof of the person's source of funds. */
|
|
29
|
+
@RequiredWhen((edd: EDD) => !!edd.sourceOfFundsProofFile)
|
|
30
|
+
@IsString()
|
|
31
|
+
sourceOfFundsProofFileName?: string;
|
|
32
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { IsIn, IsOptional, IsISO31661Alpha2, Length, IsString, IsMimeType } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { IDDocumentTypes, type IDDocumentType } from "../enums";
|
|
4
|
+
import { Base85FileField, IsoDateField, RequiredWhen } from "../utils";
|
|
5
|
+
|
|
6
|
+
export class IdDocument {
|
|
7
|
+
/* The type of identity document used for verification (e.g. PASSPORT, ID_CARD, DRIVERS). */
|
|
8
|
+
@IsIn(IDDocumentTypes)
|
|
9
|
+
type: IDDocumentType;
|
|
10
|
+
|
|
11
|
+
/* The unique number on the identity document (e.g. passport number, ID card number). */
|
|
12
|
+
@Length(1, 255)
|
|
13
|
+
number: string;
|
|
14
|
+
|
|
15
|
+
/* The country of issuance of the identity document. */
|
|
16
|
+
@IsISO31661Alpha2()
|
|
17
|
+
country: string;
|
|
18
|
+
|
|
19
|
+
/* The date the identity document expires or ceases to be valid. */
|
|
20
|
+
@IsOptional()
|
|
21
|
+
@IsoDateField()
|
|
22
|
+
dateOfExpiry?: Date;
|
|
23
|
+
|
|
24
|
+
/* The date the identity document was issued. */
|
|
25
|
+
@IsOptional()
|
|
26
|
+
@IsoDateField()
|
|
27
|
+
dateOfIssue?: Date;
|
|
28
|
+
|
|
29
|
+
/* The authority that issued the document (e.g. DVLA, Bundesdruckerei). */
|
|
30
|
+
@IsOptional()
|
|
31
|
+
@Length(1, 255)
|
|
32
|
+
issuingAuthority?: string;
|
|
33
|
+
|
|
34
|
+
/* The file containing the front of the identity document. */
|
|
35
|
+
@Base85FileField()
|
|
36
|
+
frontFile: Buffer;
|
|
37
|
+
|
|
38
|
+
/* Type of the document provided as front of the identity document. */
|
|
39
|
+
@IsString()
|
|
40
|
+
@IsMimeType()
|
|
41
|
+
frontFileType: string;
|
|
42
|
+
|
|
43
|
+
/* Name of the document provided as front of the identity document. */
|
|
44
|
+
@IsString()
|
|
45
|
+
frontFileName: string;
|
|
46
|
+
|
|
47
|
+
/* The file containing the back of the identity document. */
|
|
48
|
+
@IsOptional()
|
|
49
|
+
@Base85FileField()
|
|
50
|
+
backFile?: Buffer;
|
|
51
|
+
|
|
52
|
+
/* Type of the document provided as back of the identity document. */
|
|
53
|
+
@RequiredWhen((idDocument: IdDocument) => !!idDocument.backFile)
|
|
54
|
+
@IsString()
|
|
55
|
+
@IsMimeType()
|
|
56
|
+
backFileType?: string;
|
|
57
|
+
|
|
58
|
+
/* Name of the document provided as back of the identity document. */
|
|
59
|
+
@RequiredWhen((idDocument: IdDocument) => !!idDocument.backFile)
|
|
60
|
+
@IsString()
|
|
61
|
+
backFileName?: string;
|
|
62
|
+
|
|
63
|
+
/* The Machine-Readable Zone (MRZ) line from the document. Includes mrzLine2 and mrzLine3. */
|
|
64
|
+
@IsOptional()
|
|
65
|
+
@Length(1, 255)
|
|
66
|
+
mrzLine1?: string;
|
|
67
|
+
|
|
68
|
+
/* A title or honorific on the identity document (e.g. Dr, Mr, Ms, Prof). */
|
|
69
|
+
@IsOptional()
|
|
70
|
+
@Length(1, 255)
|
|
71
|
+
title?: string;
|
|
72
|
+
|
|
73
|
+
/* An extended expiry date when the document's validity has been officially extended. */
|
|
74
|
+
@IsOptional()
|
|
75
|
+
@IsoDateField()
|
|
76
|
+
extendedValidUntil?: Date;
|
|
77
|
+
|
|
78
|
+
/* A secondary personal identification number on the document (e.g. DNI in Spain, CRP in Brazil). */
|
|
79
|
+
@IsOptional()
|
|
80
|
+
@Length(1, 255)
|
|
81
|
+
additionalNumber?: string;
|
|
82
|
+
|
|
83
|
+
/* The person's ethnicity as indicated on the document — only present on some national documents. */
|
|
84
|
+
@IsOptional()
|
|
85
|
+
@Length(1, 255)
|
|
86
|
+
ethnicity?: string;
|
|
87
|
+
|
|
88
|
+
/* The state or province that issued the document (e.g. US state driver's licenses). */
|
|
89
|
+
@IsOptional()
|
|
90
|
+
@Length(1, 255)
|
|
91
|
+
issuingSubdivision?: string;
|
|
92
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { IsIn } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Currencies,
|
|
5
|
+
EmploymentStatuses,
|
|
6
|
+
ExpectedMonthlyTransactionCounts,
|
|
7
|
+
ExpectedMonthlyTransactionVolumes,
|
|
8
|
+
IntendedUses,
|
|
9
|
+
type Currency,
|
|
10
|
+
type EmploymentStatus,
|
|
11
|
+
type ExpectedMonthlyTransactionCount,
|
|
12
|
+
type ExpectedMonthlyTransactionVolume,
|
|
13
|
+
type IntendedUse,
|
|
14
|
+
} from "../enums";
|
|
15
|
+
|
|
16
|
+
export class Onboarding {
|
|
17
|
+
/* Intended use of the credentials. */
|
|
18
|
+
@IsIn(IntendedUses)
|
|
19
|
+
intendedUse: IntendedUse;
|
|
20
|
+
|
|
21
|
+
/* The person's employment status (e.g. EMPLOYED, RETIRED). */
|
|
22
|
+
@IsIn(EmploymentStatuses)
|
|
23
|
+
employmentStatus: EmploymentStatus;
|
|
24
|
+
|
|
25
|
+
/* The person's expected monthly transaction count, as a band. */
|
|
26
|
+
@IsIn(ExpectedMonthlyTransactionCounts)
|
|
27
|
+
expectedMonthlyTransactionCount: ExpectedMonthlyTransactionCount;
|
|
28
|
+
|
|
29
|
+
/* The person's expected monthly transaction volume, as a band. */
|
|
30
|
+
@IsIn(ExpectedMonthlyTransactionVolumes)
|
|
31
|
+
expectedMonthlyTransactionVolume: ExpectedMonthlyTransactionVolume;
|
|
32
|
+
|
|
33
|
+
/* The currency of the person's expected monthly transaction volume. */
|
|
34
|
+
@IsIn(Currencies)
|
|
35
|
+
expectedMonthlyTransactionVolumeCurrency: Currency;
|
|
36
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { IsBoolean, IsIn, IsOptional, IsString, IsISO31661Alpha2 } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { Genders, type Gender } from "../enums";
|
|
4
|
+
import { IsoDateField, RequiredWhen } from "../utils";
|
|
5
|
+
|
|
6
|
+
export class Person {
|
|
7
|
+
/* The person's first/given name(s) as on their identity document. */
|
|
8
|
+
@RequiredWhen((person: Person) => !person.familyName)
|
|
9
|
+
@IsString()
|
|
10
|
+
firstName?: string;
|
|
11
|
+
|
|
12
|
+
/* The person's family/last name as on their identity document. */
|
|
13
|
+
@IsOptional()
|
|
14
|
+
@IsString()
|
|
15
|
+
familyName?: string;
|
|
16
|
+
|
|
17
|
+
/* The person's middle name(s). */
|
|
18
|
+
@IsOptional()
|
|
19
|
+
@IsString()
|
|
20
|
+
middleName?: string;
|
|
21
|
+
|
|
22
|
+
/* The person's father's name / patronymic — required in some jurisdictions (e.g. Greece). */
|
|
23
|
+
@IsOptional()
|
|
24
|
+
@IsString()
|
|
25
|
+
fatherName?: string;
|
|
26
|
+
|
|
27
|
+
/* The person's maiden name (family name before marriage). */
|
|
28
|
+
@IsOptional()
|
|
29
|
+
@IsString()
|
|
30
|
+
maidenName?: string;
|
|
31
|
+
|
|
32
|
+
/* The person's mother's birth name — required in some jurisdictions (e.g. Hungary). */
|
|
33
|
+
@IsOptional()
|
|
34
|
+
@IsString()
|
|
35
|
+
motherName?: string;
|
|
36
|
+
|
|
37
|
+
/* The person's gender (M, F, or OTHER). */
|
|
38
|
+
@IsOptional()
|
|
39
|
+
@IsIn(Genders)
|
|
40
|
+
gender?: Gender;
|
|
41
|
+
|
|
42
|
+
/* The person's nationality country code (ISO 3166-1 alpha-2). */
|
|
43
|
+
@RequiredWhen((person: Person) => !person.stateless && !person.secondNationality)
|
|
44
|
+
@IsISO31661Alpha2()
|
|
45
|
+
nationality?: string;
|
|
46
|
+
|
|
47
|
+
/* A second nationality held by the person, if applicable (ISO 3166-1 alpha-2). */
|
|
48
|
+
@IsOptional()
|
|
49
|
+
@IsISO31661Alpha2()
|
|
50
|
+
secondNationality?: string;
|
|
51
|
+
|
|
52
|
+
/* The person's date of birth. */
|
|
53
|
+
@IsoDateField()
|
|
54
|
+
dateOfBirth: Date;
|
|
55
|
+
|
|
56
|
+
/* The city/country where the person was born. */
|
|
57
|
+
@IsOptional()
|
|
58
|
+
@IsString()
|
|
59
|
+
placeOfBirth?: string;
|
|
60
|
+
|
|
61
|
+
/* The state, region or territory within a country where the person was born. */
|
|
62
|
+
@IsOptional()
|
|
63
|
+
@IsString()
|
|
64
|
+
regionOfBirth?: string;
|
|
65
|
+
|
|
66
|
+
/* Whether the person is stateless (holds no nationality). */
|
|
67
|
+
@IsOptional()
|
|
68
|
+
@IsBoolean()
|
|
69
|
+
stateless?: boolean;
|
|
70
|
+
|
|
71
|
+
/* Whether the person holds refugee status. */
|
|
72
|
+
@IsOptional()
|
|
73
|
+
@IsBoolean()
|
|
74
|
+
refugeeStatus?: boolean;
|
|
75
|
+
|
|
76
|
+
/* Whether the person holds subsidiary protection status (below refugee status). */
|
|
77
|
+
@IsOptional()
|
|
78
|
+
@IsBoolean()
|
|
79
|
+
subsidiaryProtectionStatus?: boolean;
|
|
80
|
+
|
|
81
|
+
/* A national identification number (e.g. DNI in Spain, PESEL in Poland) — distinct from the document number. */
|
|
82
|
+
@IsOptional()
|
|
83
|
+
@IsString()
|
|
84
|
+
nationalIdNumber?: string;
|
|
85
|
+
|
|
86
|
+
/* The person's Tax Identification Number (TIN/VAT number) as issued by a tax authority. */
|
|
87
|
+
@IsOptional()
|
|
88
|
+
@IsString()
|
|
89
|
+
taxIdNumber?: string;
|
|
90
|
+
|
|
91
|
+
/* The country that issued the person's Tax Identification Number. */
|
|
92
|
+
@IsOptional()
|
|
93
|
+
@IsISO31661Alpha2()
|
|
94
|
+
taxIdIssuingCountry?: string;
|
|
95
|
+
|
|
96
|
+
/* Country where the person is tax-resident. May differ from the TIN-issuing country. */
|
|
97
|
+
@IsOptional()
|
|
98
|
+
@IsISO31661Alpha2()
|
|
99
|
+
taxResidenceCountry?: string;
|
|
100
|
+
|
|
101
|
+
/* The person's Social Security Number (US). */
|
|
102
|
+
@IsOptional()
|
|
103
|
+
@IsString()
|
|
104
|
+
ssn?: string;
|
|
105
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { IsOptional, IsString, IsISO31661Alpha2, IsMimeType, IsEnum } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { ResidentialAddressSources, type ResidentialAddressSource } from "../enums";
|
|
4
|
+
import { Base85FileField, IsoDateField, RequiredWhen } from "../utils";
|
|
5
|
+
|
|
6
|
+
export class ResidentialAddress {
|
|
7
|
+
/* How the address was obtained: typed in, autocompleted, from GPS, an external database, or read from an identity or proof-of-address document. */
|
|
8
|
+
@IsEnum(ResidentialAddressSources)
|
|
9
|
+
source: ResidentialAddressSource;
|
|
10
|
+
|
|
11
|
+
/* Street address. */
|
|
12
|
+
@IsString()
|
|
13
|
+
street: string;
|
|
14
|
+
|
|
15
|
+
/* House number. */
|
|
16
|
+
@IsOptional()
|
|
17
|
+
@IsString()
|
|
18
|
+
houseNumber?: string;
|
|
19
|
+
|
|
20
|
+
/* Additional address information (e.g. apartment number). */
|
|
21
|
+
@IsOptional()
|
|
22
|
+
@IsString()
|
|
23
|
+
additionalAddressInfo?: string;
|
|
24
|
+
|
|
25
|
+
/* Region (e.g. state, province). */
|
|
26
|
+
@IsOptional()
|
|
27
|
+
@IsString()
|
|
28
|
+
region?: string;
|
|
29
|
+
|
|
30
|
+
/* Locality (e.g. city, town). */
|
|
31
|
+
@IsString()
|
|
32
|
+
city: string;
|
|
33
|
+
|
|
34
|
+
/* Postal code. */
|
|
35
|
+
@IsOptional()
|
|
36
|
+
@IsString()
|
|
37
|
+
postalCode?: string;
|
|
38
|
+
|
|
39
|
+
/* Country (ISO 3166-1 alpha-2). */
|
|
40
|
+
@IsISO31661Alpha2()
|
|
41
|
+
country: string;
|
|
42
|
+
|
|
43
|
+
/* Type of document provided to verify the address (e.g. utility bill, bank statement). */
|
|
44
|
+
@RequiredWhen((address: ResidentialAddress) => address.source === "PROOF_OF_ADDRESS")
|
|
45
|
+
@IsString()
|
|
46
|
+
proofCategory?: string;
|
|
47
|
+
|
|
48
|
+
/* Date the address proof document was issued. */
|
|
49
|
+
@IsOptional()
|
|
50
|
+
@IsoDateField()
|
|
51
|
+
proofDateOfIssue?: Date;
|
|
52
|
+
|
|
53
|
+
/* The document provided as address proof. */
|
|
54
|
+
@RequiredWhen((address: ResidentialAddress) => address.source === "PROOF_OF_ADDRESS")
|
|
55
|
+
@Base85FileField()
|
|
56
|
+
proofFile?: Buffer;
|
|
57
|
+
|
|
58
|
+
/* Type of the document provided as address proof. */
|
|
59
|
+
@RequiredWhen((address: ResidentialAddress) => address.source === "PROOF_OF_ADDRESS")
|
|
60
|
+
@IsString()
|
|
61
|
+
@IsMimeType()
|
|
62
|
+
proofFileType?: string;
|
|
63
|
+
|
|
64
|
+
/* Name of the document provided as address proof. */
|
|
65
|
+
@RequiredWhen((address: ResidentialAddress) => address.source === "PROOF_OF_ADDRESS")
|
|
66
|
+
@IsString()
|
|
67
|
+
proofFileName?: string;
|
|
68
|
+
|
|
69
|
+
/* Country code derived from the IP address used when the applicant registered. */
|
|
70
|
+
@IsOptional()
|
|
71
|
+
@IsISO31661Alpha2()
|
|
72
|
+
ipCountry?: string;
|
|
73
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IsIn, IsNumber, IsOptional, Max, Min } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { ScreeningResults, type ScreeningResult } from "../enums";
|
|
4
|
+
|
|
5
|
+
export class Screening {
|
|
6
|
+
/* Whether the person appears on any sanctions lists (e.g. CLEAR, NOT_CHECKED). */
|
|
7
|
+
@IsIn(ScreeningResults)
|
|
8
|
+
sanctionsCheckResult: ScreeningResult;
|
|
9
|
+
|
|
10
|
+
/* A confidence score (0–100) for the sanctions screening result. */
|
|
11
|
+
@IsOptional()
|
|
12
|
+
@IsNumber()
|
|
13
|
+
@Min(0)
|
|
14
|
+
@Max(100)
|
|
15
|
+
sanctionsConfidenceScore?: number;
|
|
16
|
+
|
|
17
|
+
/* The result of the PEP (Politically Exposed Person) screening check. */
|
|
18
|
+
@IsIn(ScreeningResults)
|
|
19
|
+
pepCheckResult: ScreeningResult;
|
|
20
|
+
|
|
21
|
+
/* A confidence score (0–100) for the PEP screening result. */
|
|
22
|
+
@IsOptional()
|
|
23
|
+
@IsNumber()
|
|
24
|
+
@Min(0)
|
|
25
|
+
@Max(100)
|
|
26
|
+
pepConfidenceScore?: number;
|
|
27
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { IsIn, IsOptional } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ApproximateNetWorths,
|
|
5
|
+
Currencies,
|
|
6
|
+
SourceOfWealthTypes,
|
|
7
|
+
YearlyGrossIncomes,
|
|
8
|
+
type ApproximateNetWorth,
|
|
9
|
+
type Currency,
|
|
10
|
+
type SourceOfWealthType,
|
|
11
|
+
type YearlyGrossIncome,
|
|
12
|
+
} from "../enums";
|
|
13
|
+
import { Base85FileField, RequiredWith } from "../utils";
|
|
14
|
+
|
|
15
|
+
export class SourceOfWealth {
|
|
16
|
+
/* The category of wealth source declared by the person (e.g. SALARY, INVESTMENTS). */
|
|
17
|
+
@IsIn(SourceOfWealthTypes)
|
|
18
|
+
type: SourceOfWealthType;
|
|
19
|
+
|
|
20
|
+
/* The person's yearly gross income, as a band. */
|
|
21
|
+
@IsOptional()
|
|
22
|
+
@IsIn(YearlyGrossIncomes)
|
|
23
|
+
yearlyGrossIncome?: YearlyGrossIncome;
|
|
24
|
+
|
|
25
|
+
/* The currency of the person's yearly gross income. */
|
|
26
|
+
@RequiredWith("yearlyGrossIncome")
|
|
27
|
+
@IsIn(Currencies)
|
|
28
|
+
yearlyGrossIncomeCurrency?: Currency;
|
|
29
|
+
|
|
30
|
+
/* The person's approximate net worth, as a band. */
|
|
31
|
+
@IsOptional()
|
|
32
|
+
@IsIn(ApproximateNetWorths)
|
|
33
|
+
approximateNetWorth?: ApproximateNetWorth;
|
|
34
|
+
|
|
35
|
+
/* The currency of the person's approximate net worth. */
|
|
36
|
+
@RequiredWith("approximateNetWorth")
|
|
37
|
+
@IsIn(Currencies)
|
|
38
|
+
approximateNetWorthCurrency?: Currency;
|
|
39
|
+
|
|
40
|
+
/* A file containing proof of the person's source of wealth. */
|
|
41
|
+
@IsOptional()
|
|
42
|
+
@Base85FileField()
|
|
43
|
+
sourceOfWealthProofFile?: Buffer;
|
|
44
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { IsDefined, IsOptional, IsString } from "class-validator";
|
|
2
|
+
|
|
3
|
+
import { Section } from "../utils";
|
|
4
|
+
import { Biometric } from "./Biometric";
|
|
5
|
+
import { Contact } from "./Contact";
|
|
6
|
+
import { EDD } from "./EDD";
|
|
7
|
+
import { IdDocument } from "./IdDocument";
|
|
8
|
+
import { Onboarding } from "./Onboarding";
|
|
9
|
+
import { Person } from "./Person";
|
|
10
|
+
import { ResidentialAddress } from "./ResidentialAddress";
|
|
11
|
+
import { Screening } from "./Screening";
|
|
12
|
+
import { SourceOfWealth } from "./SourceOfWealth";
|
|
13
|
+
|
|
14
|
+
/** The credential subject: the sections that get flattened onto the wire. */
|
|
15
|
+
export class Subject {
|
|
16
|
+
@IsString()
|
|
17
|
+
id: string;
|
|
18
|
+
|
|
19
|
+
@Section(() => Person)
|
|
20
|
+
@IsDefined()
|
|
21
|
+
person: Person;
|
|
22
|
+
|
|
23
|
+
@Section(() => IdDocument)
|
|
24
|
+
@IsOptional()
|
|
25
|
+
idDocument?: IdDocument;
|
|
26
|
+
|
|
27
|
+
@Section(() => Contact)
|
|
28
|
+
@IsOptional()
|
|
29
|
+
contact?: Contact;
|
|
30
|
+
|
|
31
|
+
@Section(() => Biometric)
|
|
32
|
+
@IsOptional()
|
|
33
|
+
biometric?: Biometric;
|
|
34
|
+
|
|
35
|
+
@Section(() => ResidentialAddress)
|
|
36
|
+
@IsOptional()
|
|
37
|
+
residentialAddress?: ResidentialAddress;
|
|
38
|
+
|
|
39
|
+
@Section(() => Screening)
|
|
40
|
+
@IsOptional()
|
|
41
|
+
screening?: Screening;
|
|
42
|
+
|
|
43
|
+
@Section(() => EDD)
|
|
44
|
+
@IsOptional()
|
|
45
|
+
edd?: EDD;
|
|
46
|
+
|
|
47
|
+
@Section(() => SourceOfWealth)
|
|
48
|
+
@IsOptional()
|
|
49
|
+
sourceOfWealth?: SourceOfWealth;
|
|
50
|
+
|
|
51
|
+
@Section(() => Onboarding)
|
|
52
|
+
@IsOptional()
|
|
53
|
+
onboarding?: Onboarding;
|
|
54
|
+
}
|