@keetanetwork/anchor 0.0.71 → 0.0.73

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.
Files changed (37) hide show
  1. package/lib/resolver.d.ts +4 -0
  2. package/lib/resolver.d.ts.map +1 -1
  3. package/lib/resolver.js +23 -8
  4. package/lib/resolver.js.map +1 -1
  5. package/npm-shrinkwrap.json +2 -2
  6. package/package.json +1 -1
  7. package/services/asset-movement/common.generated.js +10866 -10866
  8. package/services/asset-movement/common.generated.js.map +1 -1
  9. package/services/asset-movement/lib/data/addresses/bank-account/ae.d.ts +4 -0
  10. package/services/asset-movement/lib/data/addresses/bank-account/ae.d.ts.map +1 -0
  11. package/services/asset-movement/lib/data/addresses/bank-account/{uae.js → ae.js} +3 -3
  12. package/services/asset-movement/lib/data/addresses/bank-account/ae.js.map +1 -0
  13. package/services/asset-movement/lib/data/addresses/bank-account/index.generated.d.ts +2 -2
  14. package/services/asset-movement/lib/data/addresses/bank-account/index.generated.d.ts.map +1 -1
  15. package/services/asset-movement/lib/data/addresses/bank-account/index.generated.js +2 -2
  16. package/services/asset-movement/lib/data/addresses/bank-account/index.generated.js.map +1 -1
  17. package/services/asset-movement/lib/data/addresses/types.generated.d.ts +126 -126
  18. package/services/asset-movement/lib/data/addresses/types.generated.d.ts.map +1 -1
  19. package/services/asset-movement/lib/data/addresses/types.generated.js +122 -122
  20. package/services/asset-movement/lib/data/addresses/types.generated.js.map +1 -1
  21. package/services/asset-movement/lib/location.generated.js +3 -3
  22. package/services/kyc/client.d.ts +18 -1
  23. package/services/kyc/client.d.ts.map +1 -1
  24. package/services/kyc/client.js +71 -3
  25. package/services/kyc/client.js.map +1 -1
  26. package/services/kyc/common.d.ts +28 -0
  27. package/services/kyc/common.d.ts.map +1 -1
  28. package/services/kyc/common.js +14 -0
  29. package/services/kyc/common.js.map +1 -1
  30. package/services/kyc/server.d.ts +13 -1
  31. package/services/kyc/server.d.ts.map +1 -1
  32. package/services/kyc/server.js +49 -7
  33. package/services/kyc/server.js.map +1 -1
  34. package/services/storage/clients/contacts.generated.js +746 -746
  35. package/services/asset-movement/lib/data/addresses/bank-account/uae.d.ts +0 -4
  36. package/services/asset-movement/lib/data/addresses/bank-account/uae.d.ts.map +0 -1
  37. package/services/asset-movement/lib/data/addresses/bank-account/uae.js.map +0 -1
@@ -2,7 +2,8 @@ import { KeetaNet } from '../../client/index.js';
2
2
  import * as CurrencyInfo from '@keetanetwork/currency-info';
3
3
  import type * as KeetaAnchorHTTPServer from '../../lib/http-server/index.js';
4
4
  import type { KeetaAnchorMetadataServerConfig } from '../../lib/anchor-metadata-server.js';
5
- import type { KeetaKYCAnchorCreateVerificationRequest, KeetaKYCAnchorCreateVerificationResponse, KeetaKYCAnchorGetCertificateResponse } from './common.ts';
5
+ import type { KeetaKYCAnchorCreateVerificationRequest, KeetaKYCAnchorCreateVerificationResponse, KeetaKYCAnchorGetCertificateResponse, KeetaKYCAnchorGetVerificationStatusResponse } from './common.ts';
6
+ import type { Account } from '@keetanetwork/keetanet-client/lib/account.js';
6
7
  import type * as Signing from '../../lib/utils/signing.js';
7
8
  import type { ServiceMetadata } from '../../lib/resolver.ts';
8
9
  import { KeetaAnchorMetadataServer } from '../../lib/anchor-metadata-server.js';
@@ -98,6 +99,17 @@ export interface KeetaAnchorKYCServerConfig extends KeetaAnchorMetadataServerCon
98
99
  getCertificates: (verificationID: string) => Promise<Extract<KeetaKYCAnchorGetCertificateResponse, {
99
100
  ok: true;
100
101
  }>['results']>;
102
+ /**
103
+ * Retrieve the verification status for a verification.
104
+ *
105
+ * If the verification ID is unknown, the implementation should
106
+ * throw a `VerificationNotFound` error.
107
+ */
108
+ getVerificationStatus: (verificationID: string, requester: {
109
+ account: Account;
110
+ }) => Promise<Pick<Extract<KeetaKYCAnchorGetVerificationStatusResponse, {
111
+ ok: true;
112
+ }>, 'status' | 'requiresManualVerification'>>;
101
113
  /**
102
114
  * Country codes that this KYC provider can service (default is all country codes)
103
115
  */
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/services/kyc/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,YAAY,MAAM,6BAA6B,CAAC;AAE5D,OAAO,KAAK,KAAK,qBAAqB,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,qCAAqC,CAAC;AAI3F,OAAO,KAAK,EACX,uCAAuC,EACvC,wCAAwC,EACxC,oCAAoC,EACpC,MAAM,aAAa,CAAC;AAQrB,OAAO,KAAK,KAAK,OAAO,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAIhF;;;;GAIG;AACH,KAAK,eAAe,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AAEvF,MAAM,WAAW,0BAA2B,SAAQ,+BAA+B;IAClF;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;IAErD;;OAEG;IACH,MAAM,EAAE;QAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,QAAQ,CAAC,UAAU,CAAC;IAE9I;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACH,GAAG,EAAE;QACJ;;;;;;;;;;;;WAYG;QACH,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,uCAAuC,KAAK,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,GAAG,SAAS,CAAC,CAAC;QAEnJ;;;;;;;;;;;WAWG;QACH,eAAe,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,oCAAoC,EAAE;YAAE,EAAE,EAAE,IAAI,CAAC;SAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAE9H;;WAEG;QACH,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,GAAG,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC;KACtE,CAAA;IAED;;OAEG;IACH,EAAE,EAAE,eAAe,CAAC;IAEpB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC;IAEhC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAE/D;;OAEG;IACH,MAAM,CAAC,EAAE,qBAAqB,CAAC,MAAM,CAAC;CACtC;AAED,qBAAa,2BAA4B,SAAQ,yBAAyB,CAAC,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,0BAA0B,CAAE,YAAW,QAAQ,CAAC,0BAA0B,CAAC;;IAC9M,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC,CAAC;IACvE,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,QAAQ,CAAC,EAAE,EAAE,0BAA0B,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,EAAE,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,0BAA0B,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACnF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAGvD,MAAM,EAAE,0BAA0B;cAsB9B,UAAU,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC;cAwJrF,oBAAoB,IAAI,OAAO,CAAC,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CAexG"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/services/kyc/server.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import * as CurrencyInfo from '@keetanetwork/currency-info';
3
3
  import { KeetaAnchorUserError } from '../../lib/error.js';
4
4
  import { assertCreateVerificationRequest, assertCreateVerificationResponse } from './common.generated.js';
5
5
  import { verifySignedData } from './common.js';
6
+ import { parseSignatureFromURL } from '../../lib/http-server/common.js';
6
7
  import { KeetaAnchorMetadataServer } from '../../lib/anchor-metadata-server.js';
7
8
  const kycProviderURLUndefined = 'NO_KYC_PROVIDER_URL:87f0175c-4d0a-4029-a4f3-ba93ef725654';
8
9
  ;
@@ -137,6 +138,45 @@ export class KeetaNetKYCAnchorHTTPServer extends KeetaAnchorMetadataServer {
137
138
  output: JSON.stringify(response)
138
139
  });
139
140
  };
141
+ /**
142
+ * Get the verification status.
143
+ */
144
+ routes['GET /api/getVerificationStatus/:verificationID'] = async function (params, _ignore_body, _ignore_headers, requestUrl) {
145
+ const verificationID = params.get('verificationID');
146
+ if (verificationID === undefined) {
147
+ throw (new KeetaAnchorUserError('No verification ID provided'));
148
+ }
149
+ const parsed = parseSignatureFromURL(requestUrl);
150
+ const signedField = parsed.signedField;
151
+ const account = parsed.account;
152
+ if (!signedField || !account) {
153
+ throw (new KeetaAnchorUserError('Missing signature'));
154
+ }
155
+ let valid;
156
+ try {
157
+ valid = await verifySignedData({
158
+ account: account.publicKeyString.get(),
159
+ signed: signedField
160
+ });
161
+ }
162
+ catch {
163
+ valid = false;
164
+ }
165
+ if (!valid) {
166
+ throw (new KeetaAnchorUserError('Invalid signature'));
167
+ }
168
+ const result = await config.kyc.getVerificationStatus(verificationID, { account });
169
+ const response = {
170
+ ok: true,
171
+ status: result.status
172
+ };
173
+ if (result.requiresManualVerification !== undefined) {
174
+ response.requiresManualVerification = result.requiresManualVerification;
175
+ }
176
+ return ({
177
+ output: JSON.stringify(response)
178
+ });
179
+ };
140
180
  /**
141
181
  * Check if the KYC provider can
142
182
  * service a more specific locality
@@ -165,18 +205,20 @@ export class KeetaNetKYCAnchorHTTPServer extends KeetaAnchorMetadataServer {
165
205
  });
166
206
  }
167
207
  async buildServiceMetadata() {
208
+ const operations = {
209
+ // checkLocality: (new URL('/api/checkLocality', this.url)).toString(),
210
+ // getEstimate: (new URL('/api/createEstimate', this.url)).toString(),
211
+ // notifyPayment: (new URL('/api/notifyPayment/{id}', this.url)).toString(),
212
+ createVerification: (new URL('/api/createVerification', this.url)).toString(),
213
+ getCertificates: (new URL('/api/getCertificates', this.url)).toString() + '/{id}',
214
+ getVerificationStatus: (new URL('/api/getVerificationStatus', this.url)).toString() + '/{id}'
215
+ };
168
216
  return ({
169
217
  ca: this.ca.toPEM(),
170
218
  countryCodes: this.#countryCodes?.map(function (country) {
171
219
  return (country.code);
172
220
  }) ?? [],
173
- operations: {
174
- // checkLocality: (new URL('/api/checkLocality', this.url)).toString(),
175
- // getEstimate: (new URL('/api/createEstimate', this.url)).toString(),
176
- // notifyPayment: (new URL('/api/notifyPayment/{id}', this.url)).toString(),
177
- createVerification: (new URL('/api/createVerification', this.url)).toString(),
178
- getCertificates: (new URL('/api/getCertificates', this.url)).toString() + '/{id}'
179
- }
221
+ operations
180
222
  });
181
223
  }
182
224
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/services/kyc/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeetaNet } from '../../client/index.js';\nimport * as CurrencyInfo from '@keetanetwork/currency-info';\n\nimport type * as KeetaAnchorHTTPServer from '../../lib/http-server/index.js';\nimport type { KeetaAnchorMetadataServerConfig } from '../../lib/anchor-metadata-server.js';\nimport {\n\tKeetaAnchorUserError\n} from '../../lib/error.js';\nimport type {\n\tKeetaKYCAnchorCreateVerificationRequest,\n\tKeetaKYCAnchorCreateVerificationResponse,\n\tKeetaKYCAnchorGetCertificateResponse\n} from './common.ts';\nimport {\n\tassertCreateVerificationRequest,\n\tassertCreateVerificationResponse\n} from './common.generated.js';\nimport {\n\tverifySignedData\n} from './common.js';\nimport type * as Signing from '../../lib/utils/signing.js';\nimport type { ServiceMetadata } from '../../lib/resolver.ts';\nimport { KeetaAnchorMetadataServer } from '../../lib/anchor-metadata-server.js';\n\nconst kycProviderURLUndefined = 'NO_KYC_PROVIDER_URL:87f0175c-4d0a-4029-a4f3-ba93ef725654';\n\n/**\n * The Base certificate type, from the KeetaNet Client\n *\n * The KYC Certificate type is a subclass of this, so it will also work\n */\ntype BaseCertificate = InstanceType<typeof KeetaNet.lib.Utils.Certificate.Certificate>;\n\nexport interface KeetaAnchorKYCServerConfig extends KeetaAnchorMetadataServerConfig {\n\t/**\n\t * The data to use for the index page (optional)\n\t */\n\thomepage?: string | (() => Promise<string> | string);\n\n\t/**\n\t * The network client to use for submitting blocks\n\t */\n\tclient: { client: KeetaNet.Client; network: bigint; networkAlias: typeof KeetaNet.Client.Config.networksArray[number] } | KeetaNet.UserClient;\n\n\t/**\n\t * Configuration for the KYC Anchor\n\t *\n\t * The flow for a KYC Anchor is as follows:\n\t * 1. Client requests a new verification with a country code and\n\t * account from the KYC Anchor Server\n\t * 2. KYC Anchor Server responds with a verification ID and a URL\n\t * to the KYC provider's web URL, including the verification ID\n\t * 3. Client visits the KYC provider's web URL to complete the\n\t * verification\n\t * 4. KYC provider notifies the Anchor server that the\n\t * verification is complete\n\t * 5. Client requests the certificate for the verification ID\n\t * (polling) from the KYC Anchor Server\n\t * 6. KYC Anchor Server responds with the certificate(s) for the\n\t * verification ID (if complete, pending if still in progress,\n\t * an error if failed)\n\t * 7. Client installs the certificate(s) in their wallet using\n\t * the KeetaNet Client library\n\t *\n\t *\n\t * +-------------------+ +---------------------+ +------------------+\n\t * | Client | | KYC Anchor Server | | KYC Provider |\n\t * +-------------------+ +---------------------+ +------------------+\n\t * | | |\n\t * (1) Create Verification | |\n\t * countryCode, account ---------------------->| |\n\t * | | |\n\t * | (2) Create verification |\n\t * |----------------------------------- verificationID, providerURL |\n\t * | | |\n\t * (3) Open providerURL (with verificationID)------------------------------------>|\n\t * | | |\n\t * | | (4) Notify\n\t * | |<-------- verificationID, verificationStatus, certificates?\n\t * | |\n\t * (5) Poll certificate for verificationID --->|\n\t * | |\n\t * |<-------------------------- (6) Pending / Certificate(s) / Error\n\t * | (repeat #5 until complete)\n\t * |\n\t * (7) Install certificate(s) in wallet using KeetaNet Client library\n\t */\n\tkyc: {\n\t\t/**\n\t\t * Notification that a verification has been started (optional)\n\t\t *\n\t\t * This method can be used to notify the KYC provider that\n\t\t * a verification has been started. It can return additional\n\t\t * information about the verification, such as the web URL\n\t\t * where the user can complete the verification.\n\t\t *\n\t\t * If this method is not provided, the server will generate\n\t\t * a random verification ID and use the `kycProviderURL` from\n\t\t * the server configuration, replacing `{id}` with the\n\t\t * verification ID.\n\t\t */\n\t\tverificationStarted?: (request: KeetaKYCAnchorCreateVerificationRequest) => Promise<Partial<KeetaKYCAnchorCreateVerificationResponse> | undefined>;\n\n\t\t/**\n\t\t * Retrieve the certificate for a verification\n\t\t *\n\t\t * This should return the certificate(s) for the\n\t\t * verification ID. If the verification is still\n\t\t * in progress, it should throw an `CertificateNotFound`\n\t\t * error.\n\t\t * If the verification has failed permanently, it should\n\t\t * throw a `KeetaAnchorUserError` with an appropriate\n\t\t * error message or `VerificationNotFound` if the\n\t\t * verification ID is not found.\n\t\t */\n\t\tgetCertificates: (verificationID: string) => Promise<Extract<KeetaKYCAnchorGetCertificateResponse, { ok: true; }>['results']>;\n\n\t\t/**\n\t\t * Country codes that this KYC provider can service (default is all country codes)\n\t\t */\n\t\tcountryCodes?: (CurrencyInfo.Country | CurrencyInfo.ISOCountryCode)[];\n\t}\n\n\t/**\n\t * The certificate to use for signing certificates\n\t */\n\tca: BaseCertificate;\n\n\t/**\n\t * The account to use for signing certificates\n\t */\n\tsigner: Signing.SignableAccount;\n\n\t/**\n\t * URL for the KYC Provider (optional)\n\t *\n\t * This is the URL that clients will be directed to in order to\n\t * complete the KYC verification process. It is optional because\n\t * the `kyc.verificationStarted` method can also return a `webURL`.\n\t * If both are provided, the URL from `kyc.verificationStarted` takes\n\t * precedence.\n\t */\n\tkycProviderURL?: string | ((verificationID: string) => string);\n\n\t/**\n\t * Additional routes to add to the server (optional)\n\t */\n\troutes?: KeetaAnchorHTTPServer.Routes;\n};\n\nexport class KeetaNetKYCAnchorHTTPServer extends KeetaAnchorMetadataServer<NonNullable<ServiceMetadata['services']['kyc']>[string], KeetaAnchorKYCServerConfig> implements Required<KeetaAnchorKYCServerConfig> {\n\treadonly homepage: NonNullable<KeetaAnchorKYCServerConfig['homepage']>;\n\treadonly client: KeetaAnchorKYCServerConfig['client'];\n\treadonly signer: NonNullable<KeetaAnchorKYCServerConfig['signer']>;\n\treadonly ca: KeetaAnchorKYCServerConfig['ca'];\n\treadonly kyc: KeetaAnchorKYCServerConfig['kyc'];\n\treadonly kycProviderURL: NonNullable<KeetaAnchorKYCServerConfig['kycProviderURL']>;\n\treadonly routes: NonNullable<KeetaAnchorKYCServerConfig['routes']>;\n\treadonly #countryCodes?: CurrencyInfo.Country[] | undefined;\n\n\tconstructor(config: KeetaAnchorKYCServerConfig) {\n\t\tsuper(config);\n\n\t\tthis.homepage = config.homepage ?? '';\n\t\tthis.client = config.client;\n\t\tthis.signer = config.signer;\n\t\tthis.ca = config.ca;\n\t\tthis.kyc = config.kyc;\n\t\tthis.routes = config.routes ?? {};\n\t\tthis.kycProviderURL = config.kycProviderURL ?? kycProviderURLUndefined;\n\n\t\tif (config.kyc.countryCodes) {\n\t\t\tthis.#countryCodes = config.kyc.countryCodes.map(function(inputCode) {\n\t\t\t\tif (CurrencyInfo.Country.isCountryCode(inputCode)) {\n\t\t\t\t\treturn(new CurrencyInfo.Country(inputCode));\n\t\t\t\t}\n\n\t\t\t\treturn(inputCode);\n\t\t\t});\n\t\t}\n\t}\n\n\tprotected async initRoutes(config: KeetaAnchorKYCServerConfig): Promise<KeetaAnchorHTTPServer.Routes> {\n\t\tconst routes: KeetaAnchorHTTPServer.Routes = {};\n\n\t\t/**\n\t\t * If a homepage is provided, setup the route for it\n\t\t */\n\t\tif ('homepage' in config) {\n\t\t\troutes['GET /'] = async function() {\n\t\t\t\tlet homepageData: string;\n\t\t\t\tif (typeof config.homepage === 'string') {\n\t\t\t\t\thomepageData = config.homepage;\n\t\t\t\t} else {\n\t\t\t\t\tif (!config.homepage) {\n\t\t\t\t\t\tthrow(new Error('internal error: No homepage function provided'));\n\t\t\t\t\t}\n\n\t\t\t\t\thomepageData = await config.homepage();\n\t\t\t\t}\n\n\t\t\t\treturn({\n\t\t\t\t\toutput: homepageData,\n\t\t\t\t\tcontentType: 'text/html'\n\t\t\t\t});\n\t\t\t};\n\t\t}\n\n\t\t/**\n\t\t * Begin the KYC verification process\n\t\t * with this KYC provider\n\t\t */\n\t\troutes['POST /api/createVerification'] = async function(_ignore_params, bodyInput) {\n\t\t\tif (bodyInput === null || typeof bodyInput !== 'object' || !('request' in bodyInput)) {\n\t\t\t\tthrow(new KeetaAnchorUserError('Invalid request'));\n\t\t\t}\n\n\t\t\tconst body = assertCreateVerificationRequest(bodyInput.request);\n\t\t\tconst valid = await verifySignedData(body);\n\t\t\tif (!valid) {\n\t\t\t\tthrow(new KeetaAnchorUserError('Invalid signature'));\n\t\t\t}\n\n\t\t\t/* XXX:TODO: Validate that the nonce is unique (within a reasonable time frame) */\n\n\t\t\tlet response: Partial<KeetaKYCAnchorCreateVerificationResponse> | undefined = {};\n\t\t\tif (config.kyc.verificationStarted) {\n\t\t\t\tresponse = await config.kyc.verificationStarted(body);\n\t\t\t}\n\n\t\t\tresponse ??= {};\n\n\t\t\tif (response?.ok === false) {\n\t\t\t\tthrow(new KeetaAnchorUserError(response.error ?? 'Unknown error'));\n\t\t\t}\n\n\t\t\tresponse.ok = true;\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow(new Error('internal error: invalid response'));\n\t\t\t}\n\t\t\tresponse.id ??= crypto.randomUUID();\n\n\t\t\tlet defaultWebURL: string;\n\t\t\tif (typeof config.kycProviderURL === 'string') {\n\t\t\t\tdefaultWebURL = config.kycProviderURL.replace('{id}', encodeURIComponent(response.id));\n\t\t\t} else if (config.kycProviderURL !== undefined) {\n\t\t\t\tdefaultWebURL = config.kycProviderURL(response.id);\n\t\t\t} else {\n\t\t\t\tdefaultWebURL = kycProviderURLUndefined;\n\t\t\t}\n\t\t\tresponse.webURL ??= defaultWebURL;\n\n\t\t\tif (!response.webURL || response.webURL === kycProviderURLUndefined) {\n\t\t\t\tthrow(new KeetaAnchorUserError('No webURL provided -- cannot proceed with verification'));\n\t\t\t}\n\n\t\t\tresponse.expectedCost = {\n\t\t\t\tmin: '0',\n\t\t\t\tmax: '0',\n\t\t\t\ttoken: KeetaNet.lib.Account.generateBaseAddresses(config.client.network).baseToken.publicKeyString.get(),\n\t\t\t\t...response.expectedCost\n\t\t\t};\n\n\t\t\tconst responseValidated = assertCreateVerificationResponse(response);\n\n\t\t\treturn({\n\t\t\t\toutput: JSON.stringify(responseValidated)\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Request an estimate for a KYC\n\t\t * verification (optional)\n\t\t *\n\t\t * XXX:TODO\n\t\t */\n\t\t// if (false) {\n\t\t// \troutes['POST /api/createEstimate'] = async function(_ignore_params, _ignore_body) {\n\t\t// \t\tthrow(new Error('not implemented'));\n\t\t// \t};\n\t\t// }\n\n\t\t/**\n\t\t * Get the certificate for the\n\t\t * KYC verification\n\t\t */\n\t\troutes['GET /api/getCertificates/:verificationID'] = async function(params) {\n\t\t\tconst verificationID = params.get('verificationID');\n\t\t\tif (verificationID === undefined) {\n\t\t\t\tthrow(new KeetaAnchorUserError('No verification ID provided'));\n\t\t\t}\n\n\t\t\tconst certificates = await config.kyc.getCertificates(verificationID);\n\n\t\t\tconst response: KeetaKYCAnchorGetCertificateResponse = {\n\t\t\t\tok: true,\n\t\t\t\tresults: certificates\n\t\t\t};\n\n\t\t\treturn({\n\t\t\t\toutput: JSON.stringify(response)\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Check if the KYC provider can\n\t\t * service a more specific locality\n\t\t * (optional)\n\t\t *\n\t\t * XXX:TODO\n\t\t */\n\t\t// if (false) {\n\t\t// \troutes['GET /api/checkLocality'] = async function(_ignore_params, _ignore_body) {\n\t\t// \t\tthrow(new Error('not implemented'));\n\t\t// \t};\n\t\t// }\n\n\t\t/**\n\t\t * Notification that payment has been received for the KYC verification\n\t\t *\n\t\t * XXX:TODO\n\t\t */\n\t\t// if (false) {\n\t\t// \troutes['POST /api/notifyPayment/:verificationID'] = async function(_ignore_params, _ignore_body) {\n\t\t// \t\tthrow(new Error('not implemented'));\n\t\t// \t};\n\t\t// }\n\n\t\treturn({\n\t\t\t...config.routes,\n\t\t\t...routes\n\t\t});\n\t}\n\n\tprotected async buildServiceMetadata(): Promise<NonNullable<ServiceMetadata['services']['kyc']>[string]> {\n\t\treturn({\n\t\t\tca: this.ca.toPEM(),\n\t\t\tcountryCodes: this.#countryCodes?.map(function(country) {\n\t\t\t\treturn(country.code);\n\t\t\t}) ?? [],\n\t\t\toperations: {\n\t\t\t\t// checkLocality: (new URL('/api/checkLocality', this.url)).toString(),\n\t\t\t\t// getEstimate: (new URL('/api/createEstimate', this.url)).toString(),\n\t\t\t\t// notifyPayment: (new URL('/api/notifyPayment/{id}', this.url)).toString(),\n\t\t\t\tcreateVerification: (new URL('/api/createVerification', this.url)).toString(),\n\t\t\t\tgetCertificates: (new URL('/api/getCertificates', this.url)).toString() + '/{id}'\n\t\t\t}\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/services/kyc/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,YAAY,MAAM,6BAA6B,CAAC;AAI5D,OAAO,EACN,oBAAoB,EACpB,MAAM,oBAAoB,CAAC;AAO5B,OAAO,EACN,+BAA+B,EAC/B,gCAAgC,EAChC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,gBAAgB,EAChB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAEhF,MAAM,uBAAuB,GAAG,0DAA0D,CAAC;AAoI1F,CAAC;AAEF,MAAM,OAAO,2BAA4B,SAAQ,yBAA8G;IACrJ,QAAQ,CAAsD;IAC9D,MAAM,CAAuC;IAC7C,MAAM,CAAoD;IAC1D,EAAE,CAAmC;IACrC,GAAG,CAAoC;IACvC,cAAc,CAA4D;IAC1E,MAAM,CAAoD;IAC1D,aAAa,CAAsC;IAE5D,YAAY,MAAkC;QAC7C,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACpB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,uBAAuB,CAAC;QAEvE,IAAI,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC7B,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAS,SAAS;gBAClE,IAAI,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;oBACnD,OAAM,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC7C,CAAC;gBAED,OAAM,CAAC,SAAS,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAES,KAAK,CAAC,UAAU,CAAC,MAAkC;QAC5D,MAAM,MAAM,GAAiC,EAAE,CAAC;QAEhD;;WAEG;QACH,IAAI,UAAU,IAAI,MAAM,EAAE,CAAC;YAC1B,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK;gBACtB,IAAI,YAAoB,CAAC;gBACzB,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBACzC,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;wBACtB,MAAK,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAC;oBACnE,CAAC;oBAED,YAAY,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACxC,CAAC;gBAED,OAAM,CAAC;oBACN,MAAM,EAAE,YAAY;oBACpB,WAAW,EAAE,WAAW;iBACxB,CAAC,CAAC;YACJ,CAAC,CAAC;QACH,CAAC;QAED;;;WAGG;QACH,MAAM,CAAC,8BAA8B,CAAC,GAAG,KAAK,WAAU,cAAc,EAAE,SAAS;YAChF,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,EAAE,CAAC;gBACtF,MAAK,CAAC,IAAI,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACpD,CAAC;YAED,MAAM,IAAI,GAAG,+BAA+B,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAChE,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACZ,MAAK,CAAC,IAAI,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACtD,CAAC;YAED,kFAAkF;YAElF,IAAI,QAAQ,GAAkE,EAAE,CAAC;YACjF,IAAI,MAAM,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;gBACpC,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;YACvD,CAAC;YAED,QAAQ,KAAK,EAAE,CAAC;YAEhB,IAAI,QAAQ,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;gBAC5B,MAAK,CAAC,IAAI,oBAAoB,CAAC,QAAQ,CAAC,KAAK,IAAI,eAAe,CAAC,CAAC,CAAC;YACpE,CAAC;YAED,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAClB,MAAK,CAAC,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;YACtD,CAAC;YACD,QAAQ,CAAC,EAAE,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;YAEpC,IAAI,aAAqB,CAAC;YAC1B,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;gBAC/C,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;YACxF,CAAC;iBAAM,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBAChD,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACP,aAAa,GAAG,uBAAuB,CAAC;YACzC,CAAC;YACD,QAAQ,CAAC,MAAM,KAAK,aAAa,CAAC;YAElC,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,uBAAuB,EAAE,CAAC;gBACrE,MAAK,CAAC,IAAI,oBAAoB,CAAC,wDAAwD,CAAC,CAAC,CAAC;YAC3F,CAAC;YAED,QAAQ,CAAC,YAAY,GAAG;gBACvB,GAAG,EAAE,GAAG;gBACR,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE;gBACxG,GAAG,QAAQ,CAAC,YAAY;aACxB,CAAC;YAEF,MAAM,iBAAiB,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;YAErE,OAAM,CAAC;gBACN,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;aACzC,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF;;;;;WAKG;QACH,eAAe;QACf,uFAAuF;QACvF,yCAAyC;QACzC,MAAM;QACN,IAAI;QAEJ;;;WAGG;QACH,MAAM,CAAC,0CAA0C,CAAC,GAAG,KAAK,WAAU,MAAM;YACzE,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACpD,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAK,CAAC,IAAI,oBAAoB,CAAC,6BAA6B,CAAC,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;YAEtE,MAAM,QAAQ,GAAyC;gBACtD,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,YAAY;aACrB,CAAC;YAEF,OAAM,CAAC;gBACN,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAChC,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF;;WAEG;QACH,MAAM,CAAC,gDAAgD,CAAC,GAAG,KAAK,WAAU,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU;YAC1H,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACpD,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAK,CAAC,IAAI,oBAAoB,CAAC,6BAA6B,CAAC,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACjD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;YACvC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;YAC/B,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC9B,MAAK,CAAC,IAAI,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACtD,CAAC;YAED,IAAI,KAAc,CAAC;YACnB,IAAI,CAAC;gBACJ,KAAK,GAAG,MAAM,gBAAgB,CAAC;oBAC9B,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,EAAE;oBACtC,MAAM,EAAE,WAAW;iBACnB,CAAC,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACR,KAAK,GAAG,KAAK,CAAC;YACf,CAAC;YAED,IAAI,CAAC,KAAK,EAAE,CAAC;gBACZ,MAAK,CAAC,IAAI,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACtD,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;YACnF,MAAM,QAAQ,GAAgD;gBAC7D,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,MAAM,CAAC,MAAM;aACrB,CAAC;YACF,IAAI,MAAM,CAAC,0BAA0B,KAAK,SAAS,EAAE,CAAC;gBACrD,QAAQ,CAAC,0BAA0B,GAAG,MAAM,CAAC,0BAA0B,CAAC;YACzE,CAAC;YAED,OAAM,CAAC;gBACN,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAChC,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF;;;;;;WAMG;QACH,eAAe;QACf,qFAAqF;QACrF,yCAAyC;QACzC,MAAM;QACN,IAAI;QAEJ;;;;WAIG;QACH,eAAe;QACf,sGAAsG;QACtG,yCAAyC;QACzC,MAAM;QACN,IAAI;QAEJ,OAAM,CAAC;YACN,GAAG,MAAM,CAAC,MAAM;YAChB,GAAG,MAAM;SACT,CAAC,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,oBAAoB;QACnC,MAAM,UAAU,GAA0E;YACzF,uEAAuE;YACvE,sEAAsE;YACtE,4EAA4E;YAC5E,kBAAkB,EAAE,CAAC,IAAI,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE;YAC7E,eAAe,EAAE,CAAC,IAAI,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,OAAO;YACjF,qBAAqB,EAAE,CAAC,IAAI,GAAG,CAAC,4BAA4B,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,OAAO;SAC7F,CAAC;QAEF,OAAM,CAAC;YACN,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;YACnB,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,UAAS,OAAO;gBACrD,OAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC,CAAC,IAAI,EAAE;YACR,UAAU;SACV,CAAC,CAAC;IACJ,CAAC;CACD","sourcesContent":["import { KeetaNet } from '../../client/index.js';\nimport * as CurrencyInfo from '@keetanetwork/currency-info';\n\nimport type * as KeetaAnchorHTTPServer from '../../lib/http-server/index.js';\nimport type { KeetaAnchorMetadataServerConfig } from '../../lib/anchor-metadata-server.js';\nimport {\n\tKeetaAnchorUserError\n} from '../../lib/error.js';\nimport type {\n\tKeetaKYCAnchorCreateVerificationRequest,\n\tKeetaKYCAnchorCreateVerificationResponse,\n\tKeetaKYCAnchorGetCertificateResponse,\n\tKeetaKYCAnchorGetVerificationStatusResponse\n} from './common.ts';\nimport {\n\tassertCreateVerificationRequest,\n\tassertCreateVerificationResponse\n} from './common.generated.js';\nimport {\n\tverifySignedData\n} from './common.js';\nimport type { Account } from '@keetanetwork/keetanet-client/lib/account.js';\nimport type * as Signing from '../../lib/utils/signing.js';\nimport type { ServiceMetadata } from '../../lib/resolver.ts';\nimport { parseSignatureFromURL } from '../../lib/http-server/common.js';\nimport { KeetaAnchorMetadataServer } from '../../lib/anchor-metadata-server.js';\n\nconst kycProviderURLUndefined = 'NO_KYC_PROVIDER_URL:87f0175c-4d0a-4029-a4f3-ba93ef725654';\n\n/**\n * The Base certificate type, from the KeetaNet Client\n *\n * The KYC Certificate type is a subclass of this, so it will also work\n */\ntype BaseCertificate = InstanceType<typeof KeetaNet.lib.Utils.Certificate.Certificate>;\n\nexport interface KeetaAnchorKYCServerConfig extends KeetaAnchorMetadataServerConfig {\n\t/**\n\t * The data to use for the index page (optional)\n\t */\n\thomepage?: string | (() => Promise<string> | string);\n\n\t/**\n\t * The network client to use for submitting blocks\n\t */\n\tclient: { client: KeetaNet.Client; network: bigint; networkAlias: typeof KeetaNet.Client.Config.networksArray[number] } | KeetaNet.UserClient;\n\n\t/**\n\t * Configuration for the KYC Anchor\n\t *\n\t * The flow for a KYC Anchor is as follows:\n\t * 1. Client requests a new verification with a country code and\n\t * account from the KYC Anchor Server\n\t * 2. KYC Anchor Server responds with a verification ID and a URL\n\t * to the KYC provider's web URL, including the verification ID\n\t * 3. Client visits the KYC provider's web URL to complete the\n\t * verification\n\t * 4. KYC provider notifies the Anchor server that the\n\t * verification is complete\n\t * 5. Client requests the certificate for the verification ID\n\t * (polling) from the KYC Anchor Server\n\t * 6. KYC Anchor Server responds with the certificate(s) for the\n\t * verification ID (if complete, pending if still in progress,\n\t * an error if failed)\n\t * 7. Client installs the certificate(s) in their wallet using\n\t * the KeetaNet Client library\n\t *\n\t *\n\t * +-------------------+ +---------------------+ +------------------+\n\t * | Client | | KYC Anchor Server | | KYC Provider |\n\t * +-------------------+ +---------------------+ +------------------+\n\t * | | |\n\t * (1) Create Verification | |\n\t * countryCode, account ---------------------->| |\n\t * | | |\n\t * | (2) Create verification |\n\t * |----------------------------------- verificationID, providerURL |\n\t * | | |\n\t * (3) Open providerURL (with verificationID)------------------------------------>|\n\t * | | |\n\t * | | (4) Notify\n\t * | |<-------- verificationID, verificationStatus, certificates?\n\t * | |\n\t * (5) Poll certificate for verificationID --->|\n\t * | |\n\t * |<-------------------------- (6) Pending / Certificate(s) / Error\n\t * | (repeat #5 until complete)\n\t * |\n\t * (7) Install certificate(s) in wallet using KeetaNet Client library\n\t */\n\tkyc: {\n\t\t/**\n\t\t * Notification that a verification has been started (optional)\n\t\t *\n\t\t * This method can be used to notify the KYC provider that\n\t\t * a verification has been started. It can return additional\n\t\t * information about the verification, such as the web URL\n\t\t * where the user can complete the verification.\n\t\t *\n\t\t * If this method is not provided, the server will generate\n\t\t * a random verification ID and use the `kycProviderURL` from\n\t\t * the server configuration, replacing `{id}` with the\n\t\t * verification ID.\n\t\t */\n\t\tverificationStarted?: (request: KeetaKYCAnchorCreateVerificationRequest) => Promise<Partial<KeetaKYCAnchorCreateVerificationResponse> | undefined>;\n\n\t\t/**\n\t\t * Retrieve the certificate for a verification\n\t\t *\n\t\t * This should return the certificate(s) for the\n\t\t * verification ID. If the verification is still\n\t\t * in progress, it should throw an `CertificateNotFound`\n\t\t * error.\n\t\t * If the verification has failed permanently, it should\n\t\t * throw a `KeetaAnchorUserError` with an appropriate\n\t\t * error message or `VerificationNotFound` if the\n\t\t * verification ID is not found.\n\t\t */\n\t\tgetCertificates: (verificationID: string) => Promise<Extract<KeetaKYCAnchorGetCertificateResponse, { ok: true; }>['results']>;\n\n\t\t/**\n\t\t * Retrieve the verification status for a verification.\n\t\t *\n\t\t * If the verification ID is unknown, the implementation should\n\t\t * throw a `VerificationNotFound` error.\n\t\t */\n\t\tgetVerificationStatus: (verificationID: string, requester: { account: Account }) => Promise<Pick<Extract<KeetaKYCAnchorGetVerificationStatusResponse, { ok: true; }>, 'status' | 'requiresManualVerification'>>;\n\n\t\t/**\n\t\t * Country codes that this KYC provider can service (default is all country codes)\n\t\t */\n\t\tcountryCodes?: (CurrencyInfo.Country | CurrencyInfo.ISOCountryCode)[];\n\t}\n\n\t/**\n\t * The certificate to use for signing certificates\n\t */\n\tca: BaseCertificate;\n\n\t/**\n\t * The account to use for signing certificates\n\t */\n\tsigner: Signing.SignableAccount;\n\n\t/**\n\t * URL for the KYC Provider (optional)\n\t *\n\t * This is the URL that clients will be directed to in order to\n\t * complete the KYC verification process. It is optional because\n\t * the `kyc.verificationStarted` method can also return a `webURL`.\n\t * If both are provided, the URL from `kyc.verificationStarted` takes\n\t * precedence.\n\t */\n\tkycProviderURL?: string | ((verificationID: string) => string);\n\n\t/**\n\t * Additional routes to add to the server (optional)\n\t */\n\troutes?: KeetaAnchorHTTPServer.Routes;\n};\n\nexport class KeetaNetKYCAnchorHTTPServer extends KeetaAnchorMetadataServer<NonNullable<ServiceMetadata['services']['kyc']>[string], KeetaAnchorKYCServerConfig> implements Required<KeetaAnchorKYCServerConfig> {\n\treadonly homepage: NonNullable<KeetaAnchorKYCServerConfig['homepage']>;\n\treadonly client: KeetaAnchorKYCServerConfig['client'];\n\treadonly signer: NonNullable<KeetaAnchorKYCServerConfig['signer']>;\n\treadonly ca: KeetaAnchorKYCServerConfig['ca'];\n\treadonly kyc: KeetaAnchorKYCServerConfig['kyc'];\n\treadonly kycProviderURL: NonNullable<KeetaAnchorKYCServerConfig['kycProviderURL']>;\n\treadonly routes: NonNullable<KeetaAnchorKYCServerConfig['routes']>;\n\treadonly #countryCodes?: CurrencyInfo.Country[] | undefined;\n\n\tconstructor(config: KeetaAnchorKYCServerConfig) {\n\t\tsuper(config);\n\n\t\tthis.homepage = config.homepage ?? '';\n\t\tthis.client = config.client;\n\t\tthis.signer = config.signer;\n\t\tthis.ca = config.ca;\n\t\tthis.kyc = config.kyc;\n\t\tthis.routes = config.routes ?? {};\n\t\tthis.kycProviderURL = config.kycProviderURL ?? kycProviderURLUndefined;\n\n\t\tif (config.kyc.countryCodes) {\n\t\t\tthis.#countryCodes = config.kyc.countryCodes.map(function(inputCode) {\n\t\t\t\tif (CurrencyInfo.Country.isCountryCode(inputCode)) {\n\t\t\t\t\treturn(new CurrencyInfo.Country(inputCode));\n\t\t\t\t}\n\n\t\t\t\treturn(inputCode);\n\t\t\t});\n\t\t}\n\t}\n\n\tprotected async initRoutes(config: KeetaAnchorKYCServerConfig): Promise<KeetaAnchorHTTPServer.Routes> {\n\t\tconst routes: KeetaAnchorHTTPServer.Routes = {};\n\n\t\t/**\n\t\t * If a homepage is provided, setup the route for it\n\t\t */\n\t\tif ('homepage' in config) {\n\t\t\troutes['GET /'] = async function() {\n\t\t\t\tlet homepageData: string;\n\t\t\t\tif (typeof config.homepage === 'string') {\n\t\t\t\t\thomepageData = config.homepage;\n\t\t\t\t} else {\n\t\t\t\t\tif (!config.homepage) {\n\t\t\t\t\t\tthrow(new Error('internal error: No homepage function provided'));\n\t\t\t\t\t}\n\n\t\t\t\t\thomepageData = await config.homepage();\n\t\t\t\t}\n\n\t\t\t\treturn({\n\t\t\t\t\toutput: homepageData,\n\t\t\t\t\tcontentType: 'text/html'\n\t\t\t\t});\n\t\t\t};\n\t\t}\n\n\t\t/**\n\t\t * Begin the KYC verification process\n\t\t * with this KYC provider\n\t\t */\n\t\troutes['POST /api/createVerification'] = async function(_ignore_params, bodyInput) {\n\t\t\tif (bodyInput === null || typeof bodyInput !== 'object' || !('request' in bodyInput)) {\n\t\t\t\tthrow(new KeetaAnchorUserError('Invalid request'));\n\t\t\t}\n\n\t\t\tconst body = assertCreateVerificationRequest(bodyInput.request);\n\t\t\tconst valid = await verifySignedData(body);\n\t\t\tif (!valid) {\n\t\t\t\tthrow(new KeetaAnchorUserError('Invalid signature'));\n\t\t\t}\n\n\t\t\t/* XXX:TODO: Validate that the nonce is unique (within a reasonable time frame) */\n\n\t\t\tlet response: Partial<KeetaKYCAnchorCreateVerificationResponse> | undefined = {};\n\t\t\tif (config.kyc.verificationStarted) {\n\t\t\t\tresponse = await config.kyc.verificationStarted(body);\n\t\t\t}\n\n\t\t\tresponse ??= {};\n\n\t\t\tif (response?.ok === false) {\n\t\t\t\tthrow(new KeetaAnchorUserError(response.error ?? 'Unknown error'));\n\t\t\t}\n\n\t\t\tresponse.ok = true;\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow(new Error('internal error: invalid response'));\n\t\t\t}\n\t\t\tresponse.id ??= crypto.randomUUID();\n\n\t\t\tlet defaultWebURL: string;\n\t\t\tif (typeof config.kycProviderURL === 'string') {\n\t\t\t\tdefaultWebURL = config.kycProviderURL.replace('{id}', encodeURIComponent(response.id));\n\t\t\t} else if (config.kycProviderURL !== undefined) {\n\t\t\t\tdefaultWebURL = config.kycProviderURL(response.id);\n\t\t\t} else {\n\t\t\t\tdefaultWebURL = kycProviderURLUndefined;\n\t\t\t}\n\t\t\tresponse.webURL ??= defaultWebURL;\n\n\t\t\tif (!response.webURL || response.webURL === kycProviderURLUndefined) {\n\t\t\t\tthrow(new KeetaAnchorUserError('No webURL provided -- cannot proceed with verification'));\n\t\t\t}\n\n\t\t\tresponse.expectedCost = {\n\t\t\t\tmin: '0',\n\t\t\t\tmax: '0',\n\t\t\t\ttoken: KeetaNet.lib.Account.generateBaseAddresses(config.client.network).baseToken.publicKeyString.get(),\n\t\t\t\t...response.expectedCost\n\t\t\t};\n\n\t\t\tconst responseValidated = assertCreateVerificationResponse(response);\n\n\t\t\treturn({\n\t\t\t\toutput: JSON.stringify(responseValidated)\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Request an estimate for a KYC\n\t\t * verification (optional)\n\t\t *\n\t\t * XXX:TODO\n\t\t */\n\t\t// if (false) {\n\t\t// \troutes['POST /api/createEstimate'] = async function(_ignore_params, _ignore_body) {\n\t\t// \t\tthrow(new Error('not implemented'));\n\t\t// \t};\n\t\t// }\n\n\t\t/**\n\t\t * Get the certificate for the\n\t\t * KYC verification\n\t\t */\n\t\troutes['GET /api/getCertificates/:verificationID'] = async function(params) {\n\t\t\tconst verificationID = params.get('verificationID');\n\t\t\tif (verificationID === undefined) {\n\t\t\t\tthrow(new KeetaAnchorUserError('No verification ID provided'));\n\t\t\t}\n\n\t\t\tconst certificates = await config.kyc.getCertificates(verificationID);\n\n\t\t\tconst response: KeetaKYCAnchorGetCertificateResponse = {\n\t\t\t\tok: true,\n\t\t\t\tresults: certificates\n\t\t\t};\n\n\t\t\treturn({\n\t\t\t\toutput: JSON.stringify(response)\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Get the verification status.\n\t\t */\n\t\troutes['GET /api/getVerificationStatus/:verificationID'] = async function(params, _ignore_body, _ignore_headers, requestUrl) {\n\t\t\tconst verificationID = params.get('verificationID');\n\t\t\tif (verificationID === undefined) {\n\t\t\t\tthrow(new KeetaAnchorUserError('No verification ID provided'));\n\t\t\t}\n\n\t\t\tconst parsed = parseSignatureFromURL(requestUrl);\n\t\t\tconst signedField = parsed.signedField;\n\t\t\tconst account = parsed.account;\n\t\t\tif (!signedField || !account) {\n\t\t\t\tthrow(new KeetaAnchorUserError('Missing signature'));\n\t\t\t}\n\n\t\t\tlet valid: boolean;\n\t\t\ttry {\n\t\t\t\tvalid = await verifySignedData({\n\t\t\t\t\taccount: account.publicKeyString.get(),\n\t\t\t\t\tsigned: signedField\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tvalid = false;\n\t\t\t}\n\n\t\t\tif (!valid) {\n\t\t\t\tthrow(new KeetaAnchorUserError('Invalid signature'));\n\t\t\t}\n\n\t\t\tconst result = await config.kyc.getVerificationStatus(verificationID, { account });\n\t\t\tconst response: KeetaKYCAnchorGetVerificationStatusResponse = {\n\t\t\t\tok: true,\n\t\t\t\tstatus: result.status\n\t\t\t};\n\t\t\tif (result.requiresManualVerification !== undefined) {\n\t\t\t\tresponse.requiresManualVerification = result.requiresManualVerification;\n\t\t\t}\n\n\t\t\treturn({\n\t\t\t\toutput: JSON.stringify(response)\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Check if the KYC provider can\n\t\t * service a more specific locality\n\t\t * (optional)\n\t\t *\n\t\t * XXX:TODO\n\t\t */\n\t\t// if (false) {\n\t\t// \troutes['GET /api/checkLocality'] = async function(_ignore_params, _ignore_body) {\n\t\t// \t\tthrow(new Error('not implemented'));\n\t\t// \t};\n\t\t// }\n\n\t\t/**\n\t\t * Notification that payment has been received for the KYC verification\n\t\t *\n\t\t * XXX:TODO\n\t\t */\n\t\t// if (false) {\n\t\t// \troutes['POST /api/notifyPayment/:verificationID'] = async function(_ignore_params, _ignore_body) {\n\t\t// \t\tthrow(new Error('not implemented'));\n\t\t// \t};\n\t\t// }\n\n\t\treturn({\n\t\t\t...config.routes,\n\t\t\t...routes\n\t\t});\n\t}\n\n\tprotected async buildServiceMetadata(): Promise<NonNullable<ServiceMetadata['services']['kyc']>[string]> {\n\t\tconst operations: NonNullable<ServiceMetadata['services']['kyc']>[string]['operations'] = {\n\t\t\t// checkLocality: (new URL('/api/checkLocality', this.url)).toString(),\n\t\t\t// getEstimate: (new URL('/api/createEstimate', this.url)).toString(),\n\t\t\t// notifyPayment: (new URL('/api/notifyPayment/{id}', this.url)).toString(),\n\t\t\tcreateVerification: (new URL('/api/createVerification', this.url)).toString(),\n\t\t\tgetCertificates: (new URL('/api/getCertificates', this.url)).toString() + '/{id}',\n\t\t\tgetVerificationStatus: (new URL('/api/getVerificationStatus', this.url)).toString() + '/{id}'\n\t\t};\n\n\t\treturn({\n\t\t\tca: this.ca.toPEM(),\n\t\t\tcountryCodes: this.#countryCodes?.map(function(country) {\n\t\t\t\treturn(country.code);\n\t\t\t}) ?? [],\n\t\t\toperations\n\t\t});\n\t}\n}\n"]}