@keetanetwork/anchor 0.0.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/.done +0 -0
- package/LICENSE +35 -0
- package/client/index.d.ts +10 -0
- package/client/index.d.ts.map +1 -0
- package/client/index.js +11 -0
- package/client/index.js.map +1 -0
- package/config.d.ts +10 -0
- package/config.d.ts.map +1 -0
- package/config.js +36 -0
- package/config.js.map +1 -0
- package/lib/certificates.d.ts +106 -0
- package/lib/certificates.d.ts.map +1 -0
- package/lib/certificates.js +463 -0
- package/lib/certificates.js.map +1 -0
- package/lib/encrypted-container.d.ts +106 -0
- package/lib/encrypted-container.d.ts.map +1 -0
- package/lib/encrypted-container.js +594 -0
- package/lib/encrypted-container.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +5 -0
- package/lib/index.js.map +1 -0
- package/lib/log/common.d.ts +35 -0
- package/lib/log/common.d.ts.map +1 -0
- package/lib/log/common.js +19 -0
- package/lib/log/common.js.map +1 -0
- package/lib/log/index.d.ts +59 -0
- package/lib/log/index.d.ts.map +1 -0
- package/lib/log/index.js +207 -0
- package/lib/log/index.js.map +1 -0
- package/lib/log/target_console.d.ts +13 -0
- package/lib/log/target_console.d.ts.map +1 -0
- package/lib/log/target_console.js +44 -0
- package/lib/log/target_console.js.map +1 -0
- package/lib/resolver.d.ts +308 -0
- package/lib/resolver.d.ts.map +1 -0
- package/lib/resolver.js +1429 -0
- package/lib/resolver.js.map +1 -0
- package/lib/utils/array.d.ts +10 -0
- package/lib/utils/array.d.ts.map +1 -0
- package/lib/utils/array.js +12 -0
- package/lib/utils/array.js.map +1 -0
- package/lib/utils/asn1.d.ts +13 -0
- package/lib/utils/asn1.d.ts.map +1 -0
- package/lib/utils/asn1.js +8 -0
- package/lib/utils/asn1.js.map +1 -0
- package/lib/utils/buffer.d.ts +4 -0
- package/lib/utils/buffer.d.ts.map +1 -0
- package/lib/utils/buffer.js +3 -0
- package/lib/utils/buffer.js.map +1 -0
- package/lib/utils/crypto.d.ts +4 -0
- package/lib/utils/crypto.d.ts.map +1 -0
- package/lib/utils/crypto.js +4 -0
- package/lib/utils/crypto.js.map +1 -0
- package/lib/utils/index.d.ts +5 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +5 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/json.d.ts +8 -0
- package/lib/utils/json.d.ts.map +1 -0
- package/lib/utils/json.js +164 -0
- package/lib/utils/json.js.map +1 -0
- package/lib/utils/never.d.ts +8 -0
- package/lib/utils/never.d.ts.map +1 -0
- package/lib/utils/never.js +14 -0
- package/lib/utils/never.js.map +1 -0
- package/npm-shrinkwrap.json +16517 -0
- package/package.json +42 -0
- package/services/kyc/client.d.ts +139 -0
- package/services/kyc/client.d.ts.map +1 -0
- package/services/kyc/client.js +390 -0
- package/services/kyc/client.js.map +1 -0
- package/services/kyc/common.d.ts +65 -0
- package/services/kyc/common.d.ts.map +1 -0
- package/services/kyc/common.js +2 -0
- package/services/kyc/common.js.map +1 -0
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@keetanetwork/anchor",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "KeetaNetwork Network Anchor",
|
|
5
|
+
"main": "client/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"eslint": "eslint",
|
|
8
|
+
"tsc": "tsc",
|
|
9
|
+
"vitest": "vitest",
|
|
10
|
+
"make:all": "make all",
|
|
11
|
+
"make:dist": "make dist",
|
|
12
|
+
"make:do-lint": "make do-lint",
|
|
13
|
+
"make:test": "make test",
|
|
14
|
+
"make:clean": "make clean",
|
|
15
|
+
"make:distclean": "make distclean",
|
|
16
|
+
"make:do-npm-pack": "make do-npm-pack",
|
|
17
|
+
"make:do-deploy": "make do-deploy",
|
|
18
|
+
"prepare": "ts-patch install && typia patch"
|
|
19
|
+
},
|
|
20
|
+
"author": "LFG Payments, Inc",
|
|
21
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@keetanetwork/eslint-config-typescript": "1.4.7",
|
|
25
|
+
"@keetanetwork/keetanet-node": "0.12.2",
|
|
26
|
+
"@ryoppippi/unplugin-typia": "2.6.5",
|
|
27
|
+
"@types/asn1js": "2.0.2",
|
|
28
|
+
"@types/node": "20.16.10",
|
|
29
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
30
|
+
"ts-patch": "3.3.0",
|
|
31
|
+
"typescript": "5.6.3",
|
|
32
|
+
"vitest": "3.2.4"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@keetanetwork/currency-info": "1.1.1",
|
|
36
|
+
"@keetanetwork/keetanet-client": "0.12.2",
|
|
37
|
+
"typia": "9.5.0"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": "20.18.0"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
|
|
2
|
+
import CurrencyInfo from '@keetanetwork/currency-info';
|
|
3
|
+
import { getDefaultResolver } from '../../config.js';
|
|
4
|
+
import { Certificate as KYCCertificate } from '../../lib/certificates.js';
|
|
5
|
+
import type { Client as KeetaNetClient, UserClient as KeetaNetUserClient } from '@keetanetwork/keetanet-client';
|
|
6
|
+
import type { KeetaKYCAnchorCreateVerificationRequest } from './common.ts';
|
|
7
|
+
import type { Logger } from '../../lib/log/index.ts';
|
|
8
|
+
import type Resolver from '../../lib/resolver.ts';
|
|
9
|
+
import type { ServiceMetadata } from '../../lib/resolver.ts';
|
|
10
|
+
/**
|
|
11
|
+
* The configuration options for the KYC Anchor client.
|
|
12
|
+
*/
|
|
13
|
+
export type KeetaKYCAnchorClientConfig = {
|
|
14
|
+
/**
|
|
15
|
+
* The ID of the client. This is used to identify the client in logs.
|
|
16
|
+
* If not provided, a random ID will be generated.
|
|
17
|
+
*/
|
|
18
|
+
id?: string;
|
|
19
|
+
/**
|
|
20
|
+
* The logger to use for logging messages. If not provided, no logging
|
|
21
|
+
* will be done.
|
|
22
|
+
*/
|
|
23
|
+
logger?: Logger;
|
|
24
|
+
/**
|
|
25
|
+
* The resolver to use for resolving KYC Anchor services. If not
|
|
26
|
+
* provided, a default resolver will be created using the provided
|
|
27
|
+
* client and network (if the network is also not provided and the
|
|
28
|
+
* client is not a UserClient, an error occurs).
|
|
29
|
+
*/
|
|
30
|
+
resolver?: Resolver;
|
|
31
|
+
} & Omit<NonNullable<Parameters<typeof getDefaultResolver>[1]>, 'client'>;
|
|
32
|
+
/**
|
|
33
|
+
* Any kind of X.509v3 Certificate. This may or may not be a KYC certificate.
|
|
34
|
+
*/
|
|
35
|
+
type BaseCertificate = InstanceType<typeof KeetaNetLib.Utils.Certificate.Certificate>;
|
|
36
|
+
/**
|
|
37
|
+
* The response type for the {@link KeetaKYCAnchorClient['getCertificates']()} method of the KYC Anchor client.
|
|
38
|
+
* It contains the certificate and optionally a set of intermediate certificates.
|
|
39
|
+
*/
|
|
40
|
+
type KeetaKYCAnchorClientGetCertificateResponse = ({
|
|
41
|
+
ok: true;
|
|
42
|
+
results: {
|
|
43
|
+
certificate: KYCCertificate;
|
|
44
|
+
intermediates?: Set<BaseCertificate> | undefined;
|
|
45
|
+
}[];
|
|
46
|
+
} | {
|
|
47
|
+
ok: false;
|
|
48
|
+
retryAfter: number;
|
|
49
|
+
reason: string;
|
|
50
|
+
});
|
|
51
|
+
type KeetaKYCAnchorClientCreateVerificationRequest = Omit<KeetaKYCAnchorCreateVerificationRequest, 'signed' | 'account'> & {
|
|
52
|
+
account: InstanceType<typeof KeetaNetLib.Account>;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* An opaque type that represents a provider ID.
|
|
56
|
+
*/
|
|
57
|
+
type ProviderID = string & {
|
|
58
|
+
readonly __providerID: unique symbol;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* An opaque type that represents a KYC Anchor request ID
|
|
62
|
+
*/
|
|
63
|
+
type RequestID = string & {
|
|
64
|
+
readonly __requestID: unique symbol;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* A list of operations that can be performed by the KYC Anchor service.
|
|
68
|
+
*/
|
|
69
|
+
type KeetaKYCAnchorOperations = {
|
|
70
|
+
[operation in keyof NonNullable<ServiceMetadata['services']['kyc']>[string]['operations']]?: (params?: {
|
|
71
|
+
[key: string]: string;
|
|
72
|
+
}) => URL;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The service information for a KYC Anchor service.
|
|
76
|
+
*/
|
|
77
|
+
type KeetaKYCVerificationServiceInfo = {
|
|
78
|
+
operations: {
|
|
79
|
+
[operation in keyof KeetaKYCAnchorOperations]: Promise<KeetaKYCAnchorOperations[operation]>;
|
|
80
|
+
};
|
|
81
|
+
countryCodes?: CurrencyInfo.Country[] | undefined;
|
|
82
|
+
ca: () => Promise<KYCCertificate>;
|
|
83
|
+
};
|
|
84
|
+
type KeetaKYCAnchorCommonConfig = {
|
|
85
|
+
id: ProviderID;
|
|
86
|
+
serviceInfo: KeetaKYCVerificationServiceInfo;
|
|
87
|
+
request: KeetaKYCAnchorCreateVerificationRequest;
|
|
88
|
+
client: KeetaKYCAnchorClient;
|
|
89
|
+
operations: NonNullable<Pick<KeetaKYCAnchorOperations, 'createVerification' | 'getCertificates'>>;
|
|
90
|
+
logger?: Logger | undefined;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Represents an in-progress KYC verification request.
|
|
94
|
+
*/
|
|
95
|
+
declare class KeetaKYCVerification {
|
|
96
|
+
readonly providerID: KeetaKYCAnchorCommonConfig['id'];
|
|
97
|
+
readonly id: RequestID;
|
|
98
|
+
private readonly serviceInfo;
|
|
99
|
+
private readonly request;
|
|
100
|
+
private readonly logger?;
|
|
101
|
+
private readonly client;
|
|
102
|
+
private readonly response;
|
|
103
|
+
private constructor();
|
|
104
|
+
static start(args: KeetaKYCAnchorCommonConfig): Promise<KeetaKYCVerification>;
|
|
105
|
+
get expectedCost(): typeof this.response.expectedCost;
|
|
106
|
+
get webURL(): URL;
|
|
107
|
+
getProviderIssuerCertificate(): Promise<KYCCertificate>;
|
|
108
|
+
getCertificates(): Promise<KeetaKYCAnchorClientGetCertificateResponse>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Represents the KYC operations for a specific provider
|
|
112
|
+
*/
|
|
113
|
+
declare class KeetaKYCProvider {
|
|
114
|
+
readonly id: ProviderID;
|
|
115
|
+
private readonly serviceInfo;
|
|
116
|
+
private readonly request;
|
|
117
|
+
private readonly logger?;
|
|
118
|
+
private readonly client;
|
|
119
|
+
private readonly operations;
|
|
120
|
+
private cachedCA?;
|
|
121
|
+
constructor(args: KeetaKYCAnchorCommonConfig);
|
|
122
|
+
countryCodes(): Promise<CurrencyInfo.Country[] | undefined>;
|
|
123
|
+
ca(): Promise<KYCCertificate>;
|
|
124
|
+
startVerification(): Promise<KeetaKYCVerification>;
|
|
125
|
+
}
|
|
126
|
+
declare class KeetaKYCAnchorClient {
|
|
127
|
+
readonly resolver: Resolver;
|
|
128
|
+
readonly id: string;
|
|
129
|
+
private readonly logger?;
|
|
130
|
+
constructor(client: KeetaNetClient | KeetaNetUserClient, config?: KeetaKYCAnchorClientConfig);
|
|
131
|
+
createVerification(request: KeetaKYCAnchorClientCreateVerificationRequest): Promise<KeetaKYCProvider[]>;
|
|
132
|
+
getCertificates(providerID: ProviderID, request: KeetaKYCAnchorCreateVerificationRequest & {
|
|
133
|
+
id: RequestID;
|
|
134
|
+
}): Promise<KeetaKYCAnchorClientGetCertificateResponse>;
|
|
135
|
+
getEstimate(..._ignore_args: unknown[]): Promise<never>;
|
|
136
|
+
checkLocality(..._ignore_args: unknown[]): Promise<never>;
|
|
137
|
+
}
|
|
138
|
+
export default KeetaKYCAnchorClient;
|
|
139
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/services/kyc/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
|
|
2
|
+
import CurrencyInfo from '@keetanetwork/currency-info';
|
|
3
|
+
import { createIs } from 'typia';
|
|
4
|
+
import { getDefaultResolver } from '../../config.js';
|
|
5
|
+
import { Certificate as KYCCertificate } from '../../lib/certificates.js';
|
|
6
|
+
import { Buffer } from '../../lib/utils/buffer.js';
|
|
7
|
+
import crypto from '../../lib/utils/crypto.js';
|
|
8
|
+
const PARANOID = true;
|
|
9
|
+
const isKeetaKYCAnchorCreateVerificationResponse = (() => { const _io0 = input => true === input.ok && "string" === typeof input.id && ("object" === typeof input.expectedCost && null !== input.expectedCost && _io1(input.expectedCost)) && "string" === typeof input.webURL; const _io1 = input => "string" === typeof input.min && "string" === typeof input.max && ("string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token))); const _io2 = input => false === input.ok && "string" === typeof input.error; const _iu0 = input => (() => {
|
|
10
|
+
if (true === input.ok)
|
|
11
|
+
return _io0(input);
|
|
12
|
+
else if (false === input.ok)
|
|
13
|
+
return _io2(input);
|
|
14
|
+
else
|
|
15
|
+
return false;
|
|
16
|
+
})(); return input => "object" === typeof input && null !== input && _iu0(input); })();
|
|
17
|
+
const isKeetaKYCAnchorGetCertificateResponse = (() => { const _io0 = input => true === input.ok && (Array.isArray(input.results) && input.results.every(elem => "object" === typeof elem && null !== elem && _io1(elem))); const _io1 = input => "string" === typeof input.certificate && (undefined === input.intermediates || Array.isArray(input.intermediates) && input.intermediates.every(elem => "string" === typeof elem)); const _io2 = input => false === input.ok && "string" === typeof input.error; const _iu0 = input => (() => {
|
|
18
|
+
if (true === input.ok)
|
|
19
|
+
return _io0(input);
|
|
20
|
+
else if (false === input.ok)
|
|
21
|
+
return _io2(input);
|
|
22
|
+
else
|
|
23
|
+
return false;
|
|
24
|
+
})(); return input => "object" === typeof input && null !== input && _iu0(input); })();
|
|
25
|
+
function validateURL(url) {
|
|
26
|
+
if (url === undefined || url === null) {
|
|
27
|
+
throw (new Error('Invalid URL: null or undefined'));
|
|
28
|
+
}
|
|
29
|
+
const parsedURL = new URL(url);
|
|
30
|
+
return (parsedURL);
|
|
31
|
+
}
|
|
32
|
+
async function getEndpoints(resolver, request) {
|
|
33
|
+
const response = await resolver.lookup('kyc', {
|
|
34
|
+
countryCodes: request.countryCodes
|
|
35
|
+
});
|
|
36
|
+
if (response === undefined) {
|
|
37
|
+
return (null);
|
|
38
|
+
}
|
|
39
|
+
const serviceInfoPromises = Object.entries(response).map(async function ([id, serviceInfo]) {
|
|
40
|
+
const countryCodesPromises = (await serviceInfo.countryCodes?.('array'))?.map(async function (countryCode) {
|
|
41
|
+
return (new CurrencyInfo.Country(CurrencyInfo.Country.assertCountryCode(await countryCode('string'))));
|
|
42
|
+
});
|
|
43
|
+
let countryCodes;
|
|
44
|
+
if (countryCodesPromises !== undefined) {
|
|
45
|
+
const countryCodesResults = await Promise.allSettled(countryCodesPromises);
|
|
46
|
+
countryCodes = countryCodesResults.map(function (result) {
|
|
47
|
+
if (result.status === 'fulfilled') {
|
|
48
|
+
return (result.value);
|
|
49
|
+
}
|
|
50
|
+
throw (result.reason);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const operations = await serviceInfo.operations('object');
|
|
54
|
+
const operationsFunctions = {};
|
|
55
|
+
for (const [key, operation] of Object.entries(operations)) {
|
|
56
|
+
if (operation === undefined) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
Object.defineProperty(operationsFunctions, key, {
|
|
60
|
+
get: async function () {
|
|
61
|
+
const url = await operation('string');
|
|
62
|
+
return (function (params) {
|
|
63
|
+
let substitutedURL = url;
|
|
64
|
+
for (const [paramKey, paramValue] of Object.entries(params ?? {})) {
|
|
65
|
+
substitutedURL = substitutedURL.replace(`{${paramKey}}`, encodeURIComponent(paramValue));
|
|
66
|
+
}
|
|
67
|
+
return (validateURL(substitutedURL));
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
enumerable: true,
|
|
71
|
+
configurable: true
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return ([
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
76
|
+
id,
|
|
77
|
+
{
|
|
78
|
+
countryCodes: countryCodes,
|
|
79
|
+
operations: operationsFunctions,
|
|
80
|
+
ca: async function () {
|
|
81
|
+
const certificatePEM = await serviceInfo.ca?.('string');
|
|
82
|
+
const certificate = new KYCCertificate(certificatePEM);
|
|
83
|
+
return (certificate);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
const retval = Object.fromEntries(await Promise.all(serviceInfoPromises));
|
|
89
|
+
return (retval);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Represents an in-progress KYC verification request.
|
|
93
|
+
*/
|
|
94
|
+
class KeetaKYCVerification {
|
|
95
|
+
providerID;
|
|
96
|
+
id;
|
|
97
|
+
serviceInfo;
|
|
98
|
+
request;
|
|
99
|
+
logger;
|
|
100
|
+
client;
|
|
101
|
+
response;
|
|
102
|
+
constructor(args, response) {
|
|
103
|
+
this.providerID = args.id;
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
105
|
+
this.id = response.id;
|
|
106
|
+
this.serviceInfo = args.serviceInfo;
|
|
107
|
+
this.request = args.request;
|
|
108
|
+
this.client = args.client;
|
|
109
|
+
this.logger = args.logger;
|
|
110
|
+
this.response = response;
|
|
111
|
+
this.logger?.debug(`Created KYC verification for provider ID: ${this.providerID}, request: ${JSON.stringify(args.request)}, response: ${JSON.stringify(response)}`);
|
|
112
|
+
}
|
|
113
|
+
static async start(args) {
|
|
114
|
+
args.logger?.debug(`Starting KYC verification for provider ID: ${args.id}, request: ${JSON.stringify(args.request)}`);
|
|
115
|
+
const endpoints = args.operations;
|
|
116
|
+
const createVerification = endpoints.createVerification?.();
|
|
117
|
+
if (createVerification === undefined) {
|
|
118
|
+
throw (new Error('KYC verification service does not support createVerification operation'));
|
|
119
|
+
}
|
|
120
|
+
const requestInformation = await fetch(createVerification, {
|
|
121
|
+
method: 'POST',
|
|
122
|
+
headers: {
|
|
123
|
+
'Content-Type': 'application/json',
|
|
124
|
+
'Accept': 'application/json'
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify({
|
|
127
|
+
request: args.request
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
const requestInformationJSON = await requestInformation.json();
|
|
131
|
+
if (!isKeetaKYCAnchorCreateVerificationResponse(requestInformationJSON)) {
|
|
132
|
+
throw (new Error(`Invalid response from KYC verification service: ${JSON.stringify(requestInformationJSON)}`));
|
|
133
|
+
}
|
|
134
|
+
if (!requestInformationJSON.ok) {
|
|
135
|
+
throw (new Error(`KYC verification request failed: ${requestInformationJSON.error}`));
|
|
136
|
+
}
|
|
137
|
+
args.logger?.debug(`KYC verification request successful, request ID ${requestInformationJSON.id}`);
|
|
138
|
+
return (new KeetaKYCVerification(args, requestInformationJSON));
|
|
139
|
+
}
|
|
140
|
+
get expectedCost() {
|
|
141
|
+
return (this.response.expectedCost);
|
|
142
|
+
}
|
|
143
|
+
get webURL() {
|
|
144
|
+
return (validateURL(this.response.webURL));
|
|
145
|
+
}
|
|
146
|
+
async getProviderIssuerCertificate() {
|
|
147
|
+
return (await this.serviceInfo.ca());
|
|
148
|
+
}
|
|
149
|
+
getCertificates() {
|
|
150
|
+
return (this.client.getCertificates(this.providerID, {
|
|
151
|
+
id: this.id,
|
|
152
|
+
...this.request
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Represents the KYC operations for a specific provider
|
|
158
|
+
*/
|
|
159
|
+
class KeetaKYCProvider {
|
|
160
|
+
id;
|
|
161
|
+
serviceInfo;
|
|
162
|
+
request;
|
|
163
|
+
logger;
|
|
164
|
+
client;
|
|
165
|
+
operations;
|
|
166
|
+
cachedCA;
|
|
167
|
+
constructor(args) {
|
|
168
|
+
this.id = args.id;
|
|
169
|
+
this.serviceInfo = args.serviceInfo;
|
|
170
|
+
this.request = args.request;
|
|
171
|
+
this.client = args.client;
|
|
172
|
+
this.operations = args.operations;
|
|
173
|
+
this.logger = args.logger;
|
|
174
|
+
this.logger?.debug(`Created KYC verification for provider ID: ${args.id}, request: ${JSON.stringify(args.request)}`);
|
|
175
|
+
}
|
|
176
|
+
async countryCodes() {
|
|
177
|
+
return (this.serviceInfo.countryCodes);
|
|
178
|
+
}
|
|
179
|
+
async ca() {
|
|
180
|
+
if (this.cachedCA !== undefined) {
|
|
181
|
+
return (this.cachedCA);
|
|
182
|
+
}
|
|
183
|
+
this.cachedCA = await this.serviceInfo.ca();
|
|
184
|
+
return (this.cachedCA);
|
|
185
|
+
}
|
|
186
|
+
async startVerification() {
|
|
187
|
+
return (await KeetaKYCVerification.start({
|
|
188
|
+
id: this.id,
|
|
189
|
+
serviceInfo: this.serviceInfo,
|
|
190
|
+
request: this.request,
|
|
191
|
+
client: this.client,
|
|
192
|
+
operations: this.operations,
|
|
193
|
+
logger: this.logger
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function formatSignedData(account, nonce, timestamp) {
|
|
198
|
+
nonce ??= crypto.randomUUID();
|
|
199
|
+
timestamp ??= new Date();
|
|
200
|
+
let timestampString;
|
|
201
|
+
if (typeof timestamp === 'string') {
|
|
202
|
+
timestampString = timestamp;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
timestampString = timestamp.toISOString();
|
|
206
|
+
}
|
|
207
|
+
const signature = new KeetaNetLib.Utils.ASN1.BufferStorageASN1([
|
|
208
|
+
nonce,
|
|
209
|
+
timestampString,
|
|
210
|
+
account.publicKeyAndType
|
|
211
|
+
], [
|
|
212
|
+
{ type: 'string', kind: 'utf8' },
|
|
213
|
+
{ type: 'string', kind: 'utf8' },
|
|
214
|
+
KeetaNetLib.Utils.ASN1.ValidateASN1.IsOctetString
|
|
215
|
+
]);
|
|
216
|
+
return ({
|
|
217
|
+
nonce: nonce,
|
|
218
|
+
timestamp: timestampString,
|
|
219
|
+
verificationData: signature.getDERBuffer()
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async function generateSignedData(account) {
|
|
223
|
+
const { nonce, timestamp, verificationData } = formatSignedData(account);
|
|
224
|
+
const signature = await account.sign(verificationData);
|
|
225
|
+
return ({
|
|
226
|
+
nonce: nonce,
|
|
227
|
+
timestamp: timestamp,
|
|
228
|
+
signature: signature.getBuffer().toString('base64')
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
// TODO
|
|
232
|
+
async function verifySignedData(request) {
|
|
233
|
+
const account = KeetaNetLib.Account.toAccount(request.account);
|
|
234
|
+
const nonce = request.signed.nonce;
|
|
235
|
+
const timestamp = request.signed.timestamp;
|
|
236
|
+
const signatureBuffer = Buffer.from(request.signed.signature, 'base64');
|
|
237
|
+
if (Object.keys(request.signed).length !== 3 || !nonce || !signatureBuffer || !timestamp) {
|
|
238
|
+
throw (new Error('Invalid signed data: must contain only nonce, signature, and timestamp'));
|
|
239
|
+
}
|
|
240
|
+
/* XXX:TODO: Verify that the timestamp is a valid ISO 8601 date string within a reasonable range */
|
|
241
|
+
const { verificationData } = formatSignedData(account, nonce, timestamp);
|
|
242
|
+
return (account.verify(KeetaNetLib.Utils.Helper.bufferToArrayBuffer(verificationData), KeetaNetLib.Utils.Helper.bufferToArrayBuffer(signatureBuffer)));
|
|
243
|
+
}
|
|
244
|
+
class KeetaKYCAnchorClient {
|
|
245
|
+
resolver;
|
|
246
|
+
id;
|
|
247
|
+
logger;
|
|
248
|
+
constructor(client, config = {}) {
|
|
249
|
+
this.resolver = config.resolver ?? getDefaultResolver(client, config);
|
|
250
|
+
this.id = config.id ?? crypto.randomUUID();
|
|
251
|
+
this.logger = config.logger;
|
|
252
|
+
}
|
|
253
|
+
async createVerification(request) {
|
|
254
|
+
const signedData = await generateSignedData(request.account);
|
|
255
|
+
if (PARANOID) {
|
|
256
|
+
const check = await verifySignedData({ account: request.account.publicKeyString.get(), signed: signedData });
|
|
257
|
+
if (!check) {
|
|
258
|
+
throw (new Error('Failed to verify signed data'));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const signedRequest = {
|
|
262
|
+
...request,
|
|
263
|
+
account: request.account.publicKeyString.get(),
|
|
264
|
+
signed: signedData
|
|
265
|
+
};
|
|
266
|
+
const endpoints = await getEndpoints(this.resolver, signedRequest);
|
|
267
|
+
if (endpoints === null) {
|
|
268
|
+
throw (new Error('No KYC endpoints found for the given criteria'));
|
|
269
|
+
}
|
|
270
|
+
const validEndpoints = await Promise.allSettled(Object.entries(endpoints).map(async ([id, serviceInfo]) => {
|
|
271
|
+
const endpoints = serviceInfo.operations;
|
|
272
|
+
/*
|
|
273
|
+
* Verify that we have the required operations
|
|
274
|
+
* available to perform a KYC verification.
|
|
275
|
+
*/
|
|
276
|
+
const createVerification = await endpoints.createVerification;
|
|
277
|
+
const getCertificates = await endpoints.getCertificates;
|
|
278
|
+
if (createVerification === undefined || getCertificates === undefined) {
|
|
279
|
+
this.logger?.warn(`KYC verification provider ${id} does not support required operations (createVerification, getCertificates)`);
|
|
280
|
+
return (null);
|
|
281
|
+
}
|
|
282
|
+
/*
|
|
283
|
+
* We can safely cast the ID to a ProviderID because it's a branded type
|
|
284
|
+
* for this specific type
|
|
285
|
+
*/
|
|
286
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
287
|
+
const providerID = id;
|
|
288
|
+
return (new KeetaKYCProvider({
|
|
289
|
+
id: providerID,
|
|
290
|
+
serviceInfo: serviceInfo,
|
|
291
|
+
request: signedRequest,
|
|
292
|
+
client: this,
|
|
293
|
+
logger: this.logger,
|
|
294
|
+
operations: {
|
|
295
|
+
createVerification,
|
|
296
|
+
getCertificates
|
|
297
|
+
}
|
|
298
|
+
}));
|
|
299
|
+
}));
|
|
300
|
+
/*
|
|
301
|
+
* Filter out any endpoints that were not able to be resolved
|
|
302
|
+
* or that did not have the required operations.
|
|
303
|
+
*/
|
|
304
|
+
const retval = validEndpoints.map(function (result) {
|
|
305
|
+
if (result.status !== 'fulfilled') {
|
|
306
|
+
return (null);
|
|
307
|
+
}
|
|
308
|
+
if (result.value === null) {
|
|
309
|
+
return (null);
|
|
310
|
+
}
|
|
311
|
+
return (result.value);
|
|
312
|
+
}).filter(function (result) {
|
|
313
|
+
return (result !== null);
|
|
314
|
+
});
|
|
315
|
+
if (retval.length === 0) {
|
|
316
|
+
throw (new Error('No valid KYC verification endpoints found'));
|
|
317
|
+
}
|
|
318
|
+
return (retval);
|
|
319
|
+
}
|
|
320
|
+
async getCertificates(providerID, request) {
|
|
321
|
+
const endpoints = await getEndpoints(this.resolver, request);
|
|
322
|
+
if (endpoints === null) {
|
|
323
|
+
throw (new Error('No KYC endpoints found for the given criteria'));
|
|
324
|
+
}
|
|
325
|
+
const providerEndpoints = endpoints[providerID];
|
|
326
|
+
if (providerEndpoints === undefined) {
|
|
327
|
+
throw (new Error(`No KYC endpoints found for provider ID: ${providerID}`));
|
|
328
|
+
}
|
|
329
|
+
const requestID = request.id;
|
|
330
|
+
const operations = providerEndpoints.operations;
|
|
331
|
+
const getCertificate = (await operations.getCertificates)?.({ id: requestID });
|
|
332
|
+
if (getCertificate === undefined) {
|
|
333
|
+
throw (new Error('internal error: KYC verification service does not support getCertificate operation'));
|
|
334
|
+
}
|
|
335
|
+
const response = await fetch(getCertificate, {
|
|
336
|
+
method: 'GET',
|
|
337
|
+
headers: {
|
|
338
|
+
'Accept': 'application/json'
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
/*
|
|
342
|
+
* Handle retryable errors by passing them up to the caller to
|
|
343
|
+
* retry.
|
|
344
|
+
*/
|
|
345
|
+
if (response.status === 404) {
|
|
346
|
+
return ({
|
|
347
|
+
ok: false,
|
|
348
|
+
retryAfter: 500,
|
|
349
|
+
reason: 'Certificate not found'
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/*
|
|
353
|
+
* Handle other errors as fatal errors that should not be retried.
|
|
354
|
+
*/
|
|
355
|
+
if (!response.ok) {
|
|
356
|
+
throw (new Error(`Failed to get certificate: ${response.statusText}`));
|
|
357
|
+
}
|
|
358
|
+
const responseJSON = await response.json();
|
|
359
|
+
if (!isKeetaKYCAnchorGetCertificateResponse(responseJSON)) {
|
|
360
|
+
throw (new Error(`Invalid response from KYC certificate service: ${JSON.stringify(responseJSON)}`));
|
|
361
|
+
}
|
|
362
|
+
if (!responseJSON.ok) {
|
|
363
|
+
throw (new Error(`KYC certificate request failed: ${responseJSON.error}`));
|
|
364
|
+
}
|
|
365
|
+
return ({
|
|
366
|
+
ok: true,
|
|
367
|
+
results: responseJSON.results.map(function (result) {
|
|
368
|
+
const intermediates = result.intermediates?.map(function (intermediate) {
|
|
369
|
+
return (new KeetaNetLib.Utils.Certificate.Certificate(intermediate));
|
|
370
|
+
});
|
|
371
|
+
let intermediatesSet;
|
|
372
|
+
if (intermediates !== undefined && intermediates.length > 0) {
|
|
373
|
+
intermediatesSet = new Set(intermediates);
|
|
374
|
+
}
|
|
375
|
+
return ({
|
|
376
|
+
certificate: new KYCCertificate(result.certificate),
|
|
377
|
+
intermediates: intermediatesSet
|
|
378
|
+
});
|
|
379
|
+
})
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
async getEstimate(..._ignore_args) {
|
|
383
|
+
throw (new Error('not implemented'));
|
|
384
|
+
}
|
|
385
|
+
async checkLocality(..._ignore_args) {
|
|
386
|
+
throw (new Error('not implemented'));
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
export default KeetaKYCAnchorClient;
|
|
390
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/services/kyc/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';\nimport CurrencyInfo from '@keetanetwork/currency-info';\nimport { createIs } from 'typia';\n\nimport { getDefaultResolver } from '../../config.js';\nimport { Certificate as KYCCertificate } from '../../lib/certificates.js';\n\nimport type {\n\tClient as KeetaNetClient,\n\tUserClient as KeetaNetUserClient\n} from '@keetanetwork/keetanet-client';\nimport type {\n\tKeetaKYCAnchorCreateVerificationRequest,\n\tKeetaKYCAnchorCreateVerificationResponse,\n\tKeetaKYCAnchorGetCertificateResponse\n} from './common.ts';\nimport type { Logger } from '../../lib/log/index.ts';\nimport type Resolver from '../../lib/resolver.ts';\nimport type { ServiceMetadata } from '../../lib/resolver.ts';\nimport { Buffer } from '../../lib/utils/buffer.js';\nimport crypto from '../../lib/utils/crypto.js';\n\nconst PARANOID = true;\n\n/**\n * The configuration options for the KYC Anchor client.\n */\nexport type KeetaKYCAnchorClientConfig = {\n\t/**\n\t * The ID of the client. This is used to identify the client in logs.\n\t * If not provided, a random ID will be generated.\n\t */\n\tid?: string;\n\t/**\n\t * The logger to use for logging messages. If not provided, no logging\n\t * will be done.\n\t */\n\tlogger?: Logger;\n\t/**\n\t * The resolver to use for resolving KYC Anchor services. If not\n\t * provided, a default resolver will be created using the provided\n\t * client and network (if the network is also not provided and the\n\t * client is not a UserClient, an error occurs).\n\t */\n\tresolver?: Resolver;\n} & Omit<NonNullable<Parameters<typeof getDefaultResolver>[1]>, 'client'>;\n\n/**\n * Any kind of X.509v3 Certificate. This may or may not be a KYC certificate.\n */\ntype BaseCertificate = InstanceType<typeof KeetaNetLib.Utils.Certificate.Certificate>;\n\n/**\n * The response type for the {@link KeetaKYCAnchorClient['getCertificates']()} method of the KYC Anchor client.\n * It contains the certificate and optionally a set of intermediate certificates.\n */\ntype KeetaKYCAnchorClientGetCertificateResponse = ({\n\tok: true;\n\tresults: {\n\t\tcertificate: KYCCertificate;\n\t\tintermediates?: Set<BaseCertificate> | undefined;\n\t}[]\n} | {\n\tok: false;\n\tretryAfter: number;\n\treason: string;\n});\n\ntype KeetaKYCAnchorClientCreateVerificationRequest = Omit<KeetaKYCAnchorCreateVerificationRequest, 'signed' | 'account'> & {\n\taccount: InstanceType<typeof KeetaNetLib.Account>;\n};\n\n/**\n * An opaque type that represents a provider ID.\n */\ntype ProviderID = string & {\n\treadonly __providerID: unique symbol;\n};\n\n/**\n * An opaque type that represents a KYC Anchor request ID\n */\ntype RequestID = string & {\n\treadonly __requestID: unique symbol;\n};\n\n/**\n * A list of operations that can be performed by the KYC Anchor service.\n */\ntype KeetaKYCAnchorOperations = {\n\t[operation in keyof NonNullable<ServiceMetadata['services']['kyc']>[string]['operations']]?: (params?: { [key: string]: string; }) => URL;\n};\n\n/**\n * The service information for a KYC Anchor service.\n */\ntype KeetaKYCVerificationServiceInfo = {\n\toperations: {\n\t\t[operation in keyof KeetaKYCAnchorOperations]: Promise<KeetaKYCAnchorOperations[operation]>;\n\t};\n\tcountryCodes?: CurrencyInfo.Country[] | undefined;\n\tca: () => Promise<KYCCertificate>;\n};\n\n/**\n * For each matching KYC Anchor service, this type describes the\n * operations available and the country codes that the service supports.\n */\ntype GetEndpointsResult = {\n\t[id: ProviderID]: KeetaKYCVerificationServiceInfo;\n};\n\nconst isKeetaKYCAnchorCreateVerificationResponse = createIs<KeetaKYCAnchorCreateVerificationResponse>();\nconst isKeetaKYCAnchorGetCertificateResponse = createIs<KeetaKYCAnchorGetCertificateResponse>();\n\nfunction validateURL(url: string | undefined): URL {\n\tif (url === undefined || url === null) {\n\t\tthrow(new Error('Invalid URL: null or undefined'));\n\t}\n\n\tconst parsedURL = new URL(url);\n\n\treturn(parsedURL);\n}\n\nasync function getEndpoints(resolver: Resolver, request: KeetaKYCAnchorCreateVerificationRequest): Promise<GetEndpointsResult | null> {\n\tconst response = await resolver.lookup('kyc', {\n\t\tcountryCodes: request.countryCodes\n\t});\n\n\tif (response === undefined) {\n\t\treturn(null);\n\t}\n\n\tconst serviceInfoPromises = Object.entries(response).map(async function([id, serviceInfo]): Promise<[ProviderID, KeetaKYCVerificationServiceInfo]> {\n\t\tconst countryCodesPromises = (await serviceInfo.countryCodes?.('array'))?.map(async function(countryCode) {\n\t\t\treturn(new CurrencyInfo.Country(CurrencyInfo.Country.assertCountryCode(await countryCode('string'))));\n\t\t});\n\n\t\tlet countryCodes: CurrencyInfo.Country[] | undefined;\n\t\tif (countryCodesPromises !== undefined) {\n\t\t\tconst countryCodesResults = await Promise.allSettled(countryCodesPromises);\n\t\t\tcountryCodes = countryCodesResults.map(function(result) {\n\t\t\t\tif (result.status === 'fulfilled') {\n\t\t\t\t\treturn(result.value);\n\t\t\t\t}\n\t\t\t\tthrow(result.reason);\n\t\t\t});\n\t\t}\n\n\t\tconst operations = await serviceInfo.operations('object');\n\t\tconst operationsFunctions: KeetaKYCVerificationServiceInfo['operations'] = {};\n\t\tfor (const [key, operation] of Object.entries(operations)) {\n\t\t\tif (operation === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tObject.defineProperty(operationsFunctions, key, {\n\t\t\t\tget: async function() {\n\t\t\t\t\tconst url = await operation('string');\n\t\t\t\t\treturn(function(params?: { [key: string]: string; }): URL {\n\t\t\t\t\t\tlet substitutedURL = url;\n\t\t\t\t\t\tfor (const [paramKey, paramValue] of Object.entries(params ?? {})) {\n\t\t\t\t\t\t\tsubstitutedURL = substitutedURL.replace(`{${paramKey}}`, encodeURIComponent(paramValue));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn(validateURL(substitutedURL));\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true\n\t\t\t});\n\t\t}\n\t\treturn([\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tid as ProviderID,\n\t\t\t{\n\t\t\t\tcountryCodes: countryCodes,\n\t\t\t\toperations: operationsFunctions,\n\t\t\t\tca: async function() {\n\t\t\t\t\tconst certificatePEM = await serviceInfo.ca?.('string');\n\t\t\t\t\tconst certificate = new KYCCertificate(certificatePEM);\n\n\t\t\t\t\treturn(certificate);\n\t\t\t\t}\n\t\t\t}\n\t\t]);\n\t});\n\n\tconst retval = Object.fromEntries(await Promise.all(serviceInfoPromises));\n\n\treturn(retval);\n}\n\ntype KeetaKYCAnchorCommonConfig = {\n\tid: ProviderID;\n\tserviceInfo: KeetaKYCVerificationServiceInfo;\n\trequest: KeetaKYCAnchorCreateVerificationRequest;\n\tclient: KeetaKYCAnchorClient;\n\toperations: NonNullable<Pick<KeetaKYCAnchorOperations, 'createVerification' | 'getCertificates'>>;\n\tlogger?: Logger | undefined;\n};\n\n/**\n * Represents an in-progress KYC verification request.\n */\nclass KeetaKYCVerification {\n\treadonly providerID: KeetaKYCAnchorCommonConfig['id'];\n\treadonly id: RequestID;\n\tprivate readonly serviceInfo: KeetaKYCAnchorCommonConfig['serviceInfo'];\n\tprivate readonly request: KeetaKYCAnchorCommonConfig['request'];\n\tprivate readonly logger?: KeetaKYCAnchorCommonConfig['logger'] | undefined;\n\tprivate readonly client: KeetaKYCAnchorCommonConfig['client'];\n\tprivate readonly response: Extract<KeetaKYCAnchorCreateVerificationResponse, { ok: true }>;\n\n\tprivate constructor(args: KeetaKYCAnchorCommonConfig, response: Extract<KeetaKYCAnchorCreateVerificationResponse, { ok: true }>) {\n\t\tthis.providerID = args.id;\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\tthis.id = response.id as RequestID;\n\t\tthis.serviceInfo = args.serviceInfo;\n\t\tthis.request = args.request;\n\t\tthis.client = args.client;\n\t\tthis.logger = args.logger;\n\t\tthis.response = response;\n\n\t\tthis.logger?.debug(`Created KYC verification for provider ID: ${this.providerID}, request: ${JSON.stringify(args.request)}, response: ${JSON.stringify(response)}`);\n\t}\n\n\tstatic async start(args: KeetaKYCAnchorCommonConfig): Promise<KeetaKYCVerification> {\n\t\targs.logger?.debug(`Starting KYC verification for provider ID: ${args.id}, request: ${JSON.stringify(args.request)}`);\n\n\t\tconst endpoints = args.operations;\n\t\tconst createVerification = endpoints.createVerification?.();\n\t\tif (createVerification === undefined) {\n\t\t\tthrow(new Error('KYC verification service does not support createVerification operation'));\n\t\t}\n\n\t\tconst requestInformation = await fetch(createVerification, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'Accept': 'application/json'\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\trequest: args.request\n\t\t\t})\n\t\t});\n\n\t\tconst requestInformationJSON: unknown = await requestInformation.json();\n\t\tif (!isKeetaKYCAnchorCreateVerificationResponse(requestInformationJSON)) {\n\t\t\tthrow(new Error(`Invalid response from KYC verification service: ${JSON.stringify(requestInformationJSON)}`));\n\t\t}\n\n\t\tif (!requestInformationJSON.ok) {\n\t\t\tthrow(new Error(`KYC verification request failed: ${requestInformationJSON.error}`));\n\t\t}\n\n\t\targs.logger?.debug(`KYC verification request successful, request ID ${requestInformationJSON.id}`);\n\n\t\treturn(new KeetaKYCVerification(args, requestInformationJSON));\n\n\t}\n\n\tget expectedCost(): typeof this.response.expectedCost {\n\t\treturn(this.response.expectedCost);\n\t}\n\n\tget webURL(): URL {\n\t\treturn(validateURL(this.response.webURL));\n\t}\n\n\tasync getProviderIssuerCertificate(): Promise<KYCCertificate> {\n\t\treturn(await this.serviceInfo.ca());\n\t}\n\n\tgetCertificates(): Promise<KeetaKYCAnchorClientGetCertificateResponse> {\n\t\treturn(this.client.getCertificates(this.providerID, {\n\t\t\tid: this.id,\n\t\t\t...this.request\n\t\t}));\n\t}\n}\n\n/**\n * Represents the KYC operations for a specific provider\n */\nclass KeetaKYCProvider {\n\treadonly id: ProviderID;\n\tprivate readonly serviceInfo: KeetaKYCVerificationServiceInfo;\n\tprivate readonly request: KeetaKYCAnchorCreateVerificationRequest;\n\tprivate readonly logger?: Logger | undefined;\n\tprivate readonly client: KeetaKYCAnchorClient;\n\tprivate readonly operations: NonNullable<Pick<KeetaKYCAnchorOperations, 'createVerification' | 'getCertificates'>>;\n\n\tprivate cachedCA?: KYCCertificate;\n\n\tconstructor(args: KeetaKYCAnchorCommonConfig) {\n\t\tthis.id = args.id;\n\t\tthis.serviceInfo = args.serviceInfo;\n\t\tthis.request = args.request;\n\t\tthis.client = args.client;\n\t\tthis.operations = args.operations;\n\t\tthis.logger = args.logger;\n\n\t\tthis.logger?.debug(`Created KYC verification for provider ID: ${args.id}, request: ${JSON.stringify(args.request)}`);\n\t}\n\n\tasync countryCodes(): Promise<CurrencyInfo.Country[] | undefined> {\n\t\treturn(this.serviceInfo.countryCodes);\n\t}\n\n\tasync ca(): Promise<KYCCertificate> {\n\t\tif (this.cachedCA !== undefined) {\n\t\t\treturn(this.cachedCA);\n\t\t}\n\n\t\tthis.cachedCA = await this.serviceInfo.ca();\n\n\t\treturn(this.cachedCA);\n\t}\n\n\tasync startVerification(): Promise<KeetaKYCVerification> {\n\t\treturn(await KeetaKYCVerification.start({\n\t\t\tid: this.id,\n\t\t\tserviceInfo: this.serviceInfo,\n\t\t\trequest: this.request,\n\t\t\tclient: this.client,\n\t\t\toperations: this.operations,\n\t\t\tlogger: this.logger\n\t\t}));\n\t}\n}\n\nfunction formatSignedData(account: InstanceType<typeof KeetaNetLib.Account>, nonce?: string, timestamp?: string | Date): { nonce: string; timestamp: string; verificationData: Buffer; } {\n\tnonce ??= crypto.randomUUID();\n\ttimestamp ??= new Date();\n\n\tlet timestampString: string;\n\tif (typeof timestamp === 'string') {\n\t\ttimestampString = timestamp;\n\t} else {\n\t\ttimestampString = timestamp.toISOString();\n\t}\n\n\tconst signature = new KeetaNetLib.Utils.ASN1.BufferStorageASN1([\n\t\tnonce,\n\t\ttimestampString,\n\t\taccount.publicKeyAndType\n\t], [\n\t\t{ type: 'string', kind: 'utf8' },\n\t\t{ type: 'string', kind: 'utf8' },\n\t\tKeetaNetLib.Utils.ASN1.ValidateASN1.IsOctetString\n\t]);\n\n\treturn({\n\t\tnonce: nonce,\n\t\ttimestamp: timestampString,\n\t\tverificationData: signature.getDERBuffer()\n\t});\n}\n\nasync function generateSignedData(account: InstanceType<typeof KeetaNetLib.Account>): Promise<{ nonce: string; timestamp: string; signature: string; }> {\n\tconst { nonce, timestamp, verificationData } = formatSignedData(account);\n\tconst signature = await account.sign(verificationData);\n\n\treturn({\n\t\tnonce: nonce,\n\t\ttimestamp: timestamp,\n\t\tsignature: signature.getBuffer().toString('base64')\n\t});\n}\n\n// TODO\nasync function verifySignedData(request: Pick<KeetaKYCAnchorCreateVerificationRequest, 'account' | 'signed'>): Promise<boolean> {\n\tconst account = KeetaNetLib.Account.toAccount(request.account);\n\tconst nonce = request.signed.nonce;\n\tconst timestamp = request.signed.timestamp;\n\tconst signatureBuffer = Buffer.from(request.signed.signature, 'base64');\n\tif (Object.keys(request.signed).length !== 3 || !nonce || !signatureBuffer || !timestamp) {\n\t\tthrow(new Error('Invalid signed data: must contain only nonce, signature, and timestamp'));\n\t}\n\n\t/* XXX:TODO: Verify that the timestamp is a valid ISO 8601 date string within a reasonable range */\n\n\tconst { verificationData } = formatSignedData(account, nonce, timestamp);\n\n\treturn(account.verify(KeetaNetLib.Utils.Helper.bufferToArrayBuffer(verificationData), KeetaNetLib.Utils.Helper.bufferToArrayBuffer(signatureBuffer)));\n}\n\nclass KeetaKYCAnchorClient {\n\treadonly resolver: Resolver;\n\treadonly id: string;\n\tprivate readonly logger?: Logger | undefined;\n\n\tconstructor(client: KeetaNetClient | KeetaNetUserClient, config: KeetaKYCAnchorClientConfig = {}) {\n\t\tthis.resolver = config.resolver ?? getDefaultResolver(client, config);\n\t\tthis.id = config.id ?? crypto.randomUUID();\n\t\tthis.logger = config.logger;\n\t}\n\n\tasync createVerification(request: KeetaKYCAnchorClientCreateVerificationRequest): Promise<KeetaKYCProvider[]> {\n\t\tconst signedData = await generateSignedData(request.account);\n\n\t\tif (PARANOID) {\n\t\t\tconst check = await verifySignedData({ account: request.account.publicKeyString.get(), signed: signedData });\n\t\t\tif (!check) {\n\t\t\t\tthrow(new Error('Failed to verify signed data'));\n\t\t\t}\n\t\t}\n\n\t\tconst signedRequest: KeetaKYCAnchorCreateVerificationRequest = {\n\t\t\t...request,\n\t\t\taccount: request.account.publicKeyString.get(),\n\t\t\tsigned: signedData\n\t\t};\n\n\t\tconst endpoints = await getEndpoints(this.resolver, signedRequest);\n\t\tif (endpoints === null) {\n\t\t\tthrow(new Error('No KYC endpoints found for the given criteria'));\n\t\t}\n\n\t\tconst validEndpoints = await Promise.allSettled(Object.entries(endpoints).map(async ([id, serviceInfo]) => {\n\t\t\tconst endpoints = serviceInfo.operations;\n\t\t\t/*\n\t\t\t * Verify that we have the required operations\n\t\t\t * available to perform a KYC verification.\n\t\t\t */\n\t\t\tconst createVerification = await endpoints.createVerification;\n\t\t\tconst getCertificates = await endpoints.getCertificates;\n\t\t\tif (createVerification === undefined || getCertificates === undefined) {\n\t\t\t\tthis.logger?.warn(`KYC verification provider ${id} does not support required operations (createVerification, getCertificates)`);\n\n\t\t\t\treturn(null);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * We can safely cast the ID to a ProviderID because it's a branded type\n\t\t\t * for this specific type\n\t\t\t */\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tconst providerID = id as ProviderID;\n\t\t\treturn(new KeetaKYCProvider({\n\t\t\t\tid: providerID,\n\t\t\t\tserviceInfo: serviceInfo,\n\t\t\t\trequest: signedRequest,\n\t\t\t\tclient: this,\n\t\t\t\tlogger: this.logger,\n\t\t\t\toperations: {\n\t\t\t\t\tcreateVerification,\n\t\t\t\t\tgetCertificates\n\t\t\t\t}\n\t\t\t}));\n\t\t}));\n\n\t\t/*\n\t\t * Filter out any endpoints that were not able to be resolved\n\t\t * or that did not have the required operations.\n\t\t */\n\t\tconst retval = validEndpoints.map(function(result) {\n\t\t\tif (result.status !== 'fulfilled') {\n\t\t\t\treturn(null);\n\t\t\t}\n\t\t\tif (result.value === null) {\n\t\t\t\treturn(null);\n\t\t\t}\n\t\t\treturn(result.value);\n\t\t}).filter(function(result) {\n\t\t\treturn(result !== null);\n\t\t});\n\n\t\tif (retval.length === 0) {\n\t\t\tthrow(new Error('No valid KYC verification endpoints found'));\n\t\t}\n\n\t\treturn(retval);\n\t}\n\n\tasync getCertificates(providerID: ProviderID, request: KeetaKYCAnchorCreateVerificationRequest & { id: RequestID; }): Promise<KeetaKYCAnchorClientGetCertificateResponse> {\n\t\tconst endpoints = await getEndpoints(this.resolver, request);\n\t\tif (endpoints === null) {\n\t\t\tthrow(new Error('No KYC endpoints found for the given criteria'));\n\t\t}\n\t\tconst providerEndpoints = endpoints[providerID];\n\t\tif (providerEndpoints === undefined) {\n\t\t\tthrow(new Error(`No KYC endpoints found for provider ID: ${providerID}`));\n\t\t}\n\n\t\tconst requestID = request.id;\n\t\tconst operations = providerEndpoints.operations;\n\t\tconst getCertificate = (await operations.getCertificates)?.({ id: requestID });\n\t\tif (getCertificate === undefined) {\n\t\t\tthrow(new Error('internal error: KYC verification service does not support getCertificate operation'));\n\t\t}\n\n\t\tconst response = await fetch(getCertificate, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\t'Accept': 'application/json'\n\t\t\t}\n\t\t});\n\n\t\t/*\n\t\t * Handle retryable errors by passing them up to the caller to\n\t\t * retry.\n\t\t */\n\t\tif (response.status === 404) {\n\t\t\treturn({\n\t\t\t\tok: false,\n\t\t\t\tretryAfter: 500,\n\t\t\t\treason: 'Certificate not found'\n\t\t\t});\n\t\t}\n\n\t\t/*\n\t\t * Handle other errors as fatal errors that should not be retried.\n\t\t */\n\t\tif (!response.ok) {\n\t\t\tthrow(new Error(`Failed to get certificate: ${response.statusText}`));\n\t\t}\n\n\t\tconst responseJSON: unknown = await response.json();\n\t\tif (!isKeetaKYCAnchorGetCertificateResponse(responseJSON)) {\n\t\t\tthrow(new Error(`Invalid response from KYC certificate service: ${JSON.stringify(responseJSON)}`));\n\t\t}\n\n\t\tif (!responseJSON.ok) {\n\t\t\tthrow(new Error(`KYC certificate request failed: ${responseJSON.error}`));\n\t\t}\n\n\t\treturn({\n\t\t\tok: true,\n\t\t\tresults: responseJSON.results.map(function(result) {\n\t\t\t\tconst intermediates = result.intermediates?.map(function(intermediate) {\n\t\t\t\t\treturn(new KeetaNetLib.Utils.Certificate.Certificate(intermediate));\n\t\t\t\t});\n\n\t\t\t\tlet intermediatesSet;\n\t\t\t\tif (intermediates !== undefined && intermediates.length > 0) {\n\t\t\t\t\tintermediatesSet = new Set(intermediates);\n\t\t\t\t}\n\n\t\t\t\treturn({\n\t\t\t\t\tcertificate: new KYCCertificate(result.certificate),\n\t\t\t\t\tintermediates: intermediatesSet\n\t\t\t\t});\n\t\t\t})\n\t\t});\n\t}\n\n\tasync getEstimate(..._ignore_args: unknown[]): Promise<never> {\n\t\tthrow(new Error('not implemented'));\n\t}\n\n\tasync checkLocality(..._ignore_args: unknown[]): Promise<never> {\n\t\tthrow(new Error('not implemented'));\n\t}\n}\n\nexport default KeetaKYCAnchorClient;\n"]}
|