@dynamic-labs-sdk/client 0.17.2 → 0.17.3

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 (67) hide show
  1. package/dist/{InvalidParamError-Dc2HgrDm.esm.js → InvalidParamError-C8bqZx25.esm.js} +52 -3
  2. package/dist/InvalidParamError-C8bqZx25.esm.js.map +1 -0
  3. package/dist/{InvalidParamError-z_h8HyKL.cjs.js → InvalidParamError-DvFYOkxL.cjs.js} +58 -3
  4. package/dist/InvalidParamError-DvFYOkxL.cjs.js.map +1 -0
  5. package/dist/{NotWaasWalletAccountError-B4xS_9HL.esm.js → NotWaasWalletAccountError-C-_6uyUM.esm.js} +3 -3
  6. package/dist/{NotWaasWalletAccountError-B4xS_9HL.esm.js.map → NotWaasWalletAccountError-C-_6uyUM.esm.js.map} +1 -1
  7. package/dist/{NotWaasWalletAccountError-DsYkBFyx.cjs.js → NotWaasWalletAccountError-CHSFUjd9.cjs.js} +3 -3
  8. package/dist/{NotWaasWalletAccountError-DsYkBFyx.cjs.js.map → NotWaasWalletAccountError-CHSFUjd9.cjs.js.map} +1 -1
  9. package/dist/client/core/createCore/createCore.d.ts.map +1 -1
  10. package/dist/client/core/types/DynamicCore.d.ts +10 -0
  11. package/dist/client/core/types/DynamicCore.d.ts.map +1 -1
  12. package/dist/client/types/DynamicClientConfig.d.ts +5 -0
  13. package/dist/client/types/DynamicClientConfig.d.ts.map +1 -1
  14. package/dist/core.cjs.js +5 -5
  15. package/dist/core.esm.js +5 -5
  16. package/dist/{getNetworkProviderFromNetworkId-CllkC31J.cjs.js → getNetworkProviderFromNetworkId-DK9fnM_Y.cjs.js} +3 -3
  17. package/dist/{getNetworkProviderFromNetworkId-CllkC31J.cjs.js.map → getNetworkProviderFromNetworkId-DK9fnM_Y.cjs.js.map} +1 -1
  18. package/dist/{getNetworkProviderFromNetworkId-DO13PEvc.esm.js → getNetworkProviderFromNetworkId-n7VUDpn0.esm.js} +3 -3
  19. package/dist/{getNetworkProviderFromNetworkId-DO13PEvc.esm.js.map → getNetworkProviderFromNetworkId-n7VUDpn0.esm.js.map} +1 -1
  20. package/dist/{getSignedSessionId-DqmEBqI9.cjs.js → getSignedSessionId-B2-EYPik.cjs.js} +3 -3
  21. package/dist/{getSignedSessionId-DqmEBqI9.cjs.js.map → getSignedSessionId-B2-EYPik.cjs.js.map} +1 -1
  22. package/dist/{getSignedSessionId-BM05CMyp.esm.js → getSignedSessionId-CM3X3R5t.esm.js} +3 -3
  23. package/dist/{getSignedSessionId-BM05CMyp.esm.js.map → getSignedSessionId-CM3X3R5t.esm.js.map} +1 -1
  24. package/dist/{getVerifiedCredentialForWalletAccount-57Omjjyi.esm.js → getVerifiedCredentialForWalletAccount-Cs7AcMKQ.esm.js} +2 -2
  25. package/dist/{getVerifiedCredentialForWalletAccount-57Omjjyi.esm.js.map → getVerifiedCredentialForWalletAccount-Cs7AcMKQ.esm.js.map} +1 -1
  26. package/dist/{getVerifiedCredentialForWalletAccount-BK4IBZlH.cjs.js → getVerifiedCredentialForWalletAccount-CyLnpS2G.cjs.js} +3 -3
  27. package/dist/{getVerifiedCredentialForWalletAccount-BK4IBZlH.cjs.js.map → getVerifiedCredentialForWalletAccount-CyLnpS2G.cjs.js.map} +1 -1
  28. package/dist/index.cjs.js +80 -57
  29. package/dist/index.cjs.js.map +1 -1
  30. package/dist/index.esm.js +80 -57
  31. package/dist/index.esm.js.map +1 -1
  32. package/dist/{isMfaRequiredForAction-BS239c-s.cjs.js → isMfaRequiredForAction-BrRKwK_i.cjs.js} +2 -2
  33. package/dist/{isMfaRequiredForAction-BS239c-s.cjs.js.map → isMfaRequiredForAction-BrRKwK_i.cjs.js.map} +1 -1
  34. package/dist/{isMfaRequiredForAction-CXRaUbFE.esm.js → isMfaRequiredForAction-CM26tbT2.esm.js} +2 -2
  35. package/dist/{isMfaRequiredForAction-CXRaUbFE.esm.js.map → isMfaRequiredForAction-CM26tbT2.esm.js.map} +1 -1
  36. package/dist/modules/apiClient/apiClient.types.d.ts +7 -0
  37. package/dist/modules/apiClient/apiClient.types.d.ts.map +1 -1
  38. package/dist/modules/apiClient/constants.d.ts +2 -0
  39. package/dist/modules/apiClient/constants.d.ts.map +1 -1
  40. package/dist/modules/apiClient/createApiClient.d.ts.map +1 -1
  41. package/dist/modules/auth/getElevatedAccessToken/getElevatedAccessToken.d.ts +15 -8
  42. package/dist/modules/auth/getElevatedAccessToken/getElevatedAccessToken.d.ts.map +1 -1
  43. package/dist/modules/auth/passkeys/deletePasskey/deletePasskey.d.ts.map +1 -1
  44. package/dist/modules/auth/passkeys/serverRegisterPasskey/serverRegisterPasskey.d.ts.map +1 -1
  45. package/dist/modules/mfa/deleteMfaDevice/deleteMfaDevice.d.ts +6 -4
  46. package/dist/modules/mfa/deleteMfaDevice/deleteMfaDevice.d.ts.map +1 -1
  47. package/dist/modules/mfa/registerTotpMfaDevice/registerTotpMfaDevice.d.ts.map +1 -1
  48. package/dist/services/instrumentation/constants.d.ts +17 -0
  49. package/dist/services/instrumentation/constants.d.ts.map +1 -0
  50. package/dist/services/instrumentation/createInstrumentation/createInstrumentation.d.ts +18 -0
  51. package/dist/services/instrumentation/createInstrumentation/createInstrumentation.d.ts.map +1 -0
  52. package/dist/services/instrumentation/createInstrumentation/index.d.ts +2 -0
  53. package/dist/services/instrumentation/createInstrumentation/index.d.ts.map +1 -0
  54. package/dist/services/instrumentation/instrumentation.types.d.ts +44 -0
  55. package/dist/services/instrumentation/instrumentation.types.d.ts.map +1 -0
  56. package/dist/services/instrumentation/scrubParameters/index.d.ts +2 -0
  57. package/dist/services/instrumentation/scrubParameters/index.d.ts.map +1 -0
  58. package/dist/services/instrumentation/scrubParameters/scrubParameters.d.ts +8 -0
  59. package/dist/services/instrumentation/scrubParameters/scrubParameters.d.ts.map +1 -0
  60. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  61. package/dist/waas.cjs.js +4 -4
  62. package/dist/waas.esm.js +3 -3
  63. package/dist/waasCore.cjs.js +4 -4
  64. package/dist/waasCore.esm.js +3 -3
  65. package/package.json +2 -2
  66. package/dist/InvalidParamError-Dc2HgrDm.esm.js.map +0 -1
  67. package/dist/InvalidParamError-z_h8HyKL.cjs.js.map +0 -1
package/dist/index.esm.js CHANGED
@@ -1,10 +1,10 @@
1
- import { A as getDefaultClient, C as isCookieEnabled, D as CLIENT_SDK_NAME, E as randomString, F as name, I as version, N as BaseError, P as getCore, T as ValueMustBeDefinedError, _ as MfaRateLimitedError, a as DYNAMIC_ICONIC_SPRITE_URL, b as InvalidExternalAuthError, c as CHAINS_INFO_MAP, d as UnauthorizedError, g as SandboxMaximumThresholdReachedError, h as getNonce, j as setDefaultClient, k as NONCE_POOL_SIZE, l as fetchAndStoreNonces, o as SDK_API_CORE_VERSION, s as getChainFromVerifiedCredentialChain, t as InvalidParamError, u as createApiClient, v as MfaInvalidOtpError, w as assertDefined, x as APIError, y as LinkCredentialError } from "./InvalidParamError-Dc2HgrDm.esm.js";
2
- import { A as getBuffer, C as CannotTrackError, D as INITIALIZE_STORAGE_SYNC_TRACKER_KEY, E as GENERATE_SESSION_KEYS_TRACKER_KEY, F as createLocalStorageAdapter, I as subscribeWithSelector, L as isEqualShallow, M as createStorageKeySchema, N as createStorage, O as REFRESH_USER_STATE_FROM_COOKIE_TRACKER_KEY, T as FETCH_PROJECT_SETTINGS_TRACKER_KEY, _ as NoNetworkProvidersError, a as updateWalletProviderKeysForVerifiedCredentials, b as createLogger, c as createSignInMessageStatement, d as createVisit, f as hasExtension, g as WalletAlreadyLinkedToAnotherUserError, h as isCaptchaRequired, i as getNetworksData, j as generateSessionKeys, k as isServerSideRendering, l as formatSignInMessage, m as consumeCaptchaToken, o as verifyMessageSignatureOwnership, p as setCaptchaToken, s as removeUnverifiedWalletAccount, t as getNetworkProviderFromNetworkId, u as setUnverifiedWalletAccounts, v as createRealtimeService, w as createDeferredPromise, x as createCrossTabBroadcast, y as createIndexedDBKeychainService } from "./getNetworkProviderFromNetworkId-DO13PEvc.esm.js";
3
- import { D as onceEvent, E as onEvent, O as setCookie, S as splitWalletProviderKey, T as offEvent, _ as getWalletAccounts, b as formatWalletAccountId, c as getWalletProviders, d as DYNAMIC_AUTH_COOKIE_NAME, f as getWalletProviderFromWalletAccount, g as NoWalletProviderFoundError, i as restoreUserSharesForAllWalletAccounts, l as checkAndRaiseWalletAccountsChangedEvent, n as getWalletProviderByKey, r as updateAuthFromVerifyResponse, t as getVerifiedCredentialForWalletAccount, u as emitWalletAccountsChangedEvent, w as emitEvent, x as normalizeAddress } from "./getVerifiedCredentialForWalletAccount-57Omjjyi.esm.js";
4
- import { n as refreshAuth, t as NotWaasWalletAccountError } from "./NotWaasWalletAccountError-B4xS_9HL.esm.js";
5
- import { n as getMfaMethods, r as consumeMfaToken, t as isMfaRequiredForAction } from "./isMfaRequiredForAction-CXRaUbFE.esm.js";
1
+ import { A as NONCE_POOL_SIZE, D as randomString, E as ValueMustBeDefinedError, F as getCore, I as name, L as version, M as setDefaultClient, O as CLIENT_SDK_NAME, P as BaseError, S as getElevatedAccessToken, T as assertDefined, _ as MfaRateLimitedError, a as DYNAMIC_ICONIC_SPRITE_URL, b as InvalidExternalAuthError, c as CHAINS_INFO_MAP, d as UnauthorizedError, g as SandboxMaximumThresholdReachedError, h as getNonce, j as getDefaultClient, l as fetchAndStoreNonces, o as SDK_API_CORE_VERSION, s as getChainFromVerifiedCredentialChain, t as InvalidParamError, u as createApiClient, v as MfaInvalidOtpError, w as isCookieEnabled, x as APIError, y as LinkCredentialError } from "./InvalidParamError-C8bqZx25.esm.js";
2
+ import { A as getBuffer, C as CannotTrackError, D as INITIALIZE_STORAGE_SYNC_TRACKER_KEY, E as GENERATE_SESSION_KEYS_TRACKER_KEY, F as createLocalStorageAdapter, I as subscribeWithSelector, L as isEqualShallow, M as createStorageKeySchema, N as createStorage, O as REFRESH_USER_STATE_FROM_COOKIE_TRACKER_KEY, T as FETCH_PROJECT_SETTINGS_TRACKER_KEY, _ as NoNetworkProvidersError, a as updateWalletProviderKeysForVerifiedCredentials, b as createLogger, c as createSignInMessageStatement, d as createVisit, f as hasExtension, g as WalletAlreadyLinkedToAnotherUserError, h as isCaptchaRequired, i as getNetworksData, j as generateSessionKeys, k as isServerSideRendering, l as formatSignInMessage, m as consumeCaptchaToken, o as verifyMessageSignatureOwnership, p as setCaptchaToken, s as removeUnverifiedWalletAccount, t as getNetworkProviderFromNetworkId, u as setUnverifiedWalletAccounts, v as createRealtimeService, w as createDeferredPromise, x as createCrossTabBroadcast, y as createIndexedDBKeychainService } from "./getNetworkProviderFromNetworkId-n7VUDpn0.esm.js";
3
+ import { D as onceEvent, E as onEvent, O as setCookie, S as splitWalletProviderKey, T as offEvent, _ as getWalletAccounts, b as formatWalletAccountId, c as getWalletProviders, d as DYNAMIC_AUTH_COOKIE_NAME, f as getWalletProviderFromWalletAccount, g as NoWalletProviderFoundError, i as restoreUserSharesForAllWalletAccounts, l as checkAndRaiseWalletAccountsChangedEvent, n as getWalletProviderByKey, r as updateAuthFromVerifyResponse, t as getVerifiedCredentialForWalletAccount, u as emitWalletAccountsChangedEvent, w as emitEvent, x as normalizeAddress } from "./getVerifiedCredentialForWalletAccount-Cs7AcMKQ.esm.js";
4
+ import { n as refreshAuth, t as NotWaasWalletAccountError } from "./NotWaasWalletAccountError-C-_6uyUM.esm.js";
5
+ import { n as getMfaMethods, r as consumeMfaToken, t as isMfaRequiredForAction } from "./isMfaRequiredForAction-CM26tbT2.esm.js";
6
6
  import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
7
- import { AuthModeEnum, ExchangeKeyEnum, JwtVerifiedCredentialFormatEnum, MFAAction, MfaBackupCodeAcknowledgement, ProviderEnum, WaasBackupOptionsEnum, WalletProviderEnum } from "@dynamic-labs/sdk-api-core";
7
+ import { AuthModeEnum, ExchangeKeyEnum, JwtVerifiedCredentialFormatEnum, MFAAction, MfaBackupCodeAcknowledgement, ProviderEnum, TokenScope, WaasBackupOptionsEnum, WalletProviderEnum } from "@dynamic-labs/sdk-api-core";
8
8
  import * as z from "zod/mini";
9
9
  import EventEmitter, { EventEmitter as EventEmitter$1 } from "eventemitter3";
10
10
  import { browserSupportsWebAuthn, startAuthentication, startRegistration } from "@simplewebauthn/browser";
@@ -701,6 +701,59 @@ const createWebFetch = () => {
701
701
  return window.fetch.bind(window);
702
702
  };
703
703
 
704
+ //#endregion
705
+ //#region src/services/instrumentation/constants.ts
706
+ const DEFAULT_PII_FIELDS = [
707
+ "password",
708
+ "token",
709
+ "secret",
710
+ "privateKey",
711
+ "mnemonic",
712
+ "seed",
713
+ "email",
714
+ "phone",
715
+ "ssn",
716
+ "address",
717
+ "authorization"
718
+ ];
719
+
720
+ //#endregion
721
+ //#region src/services/instrumentation/createInstrumentation/createInstrumentation.ts
722
+ const buildPiiFields = (customFields = []) => {
723
+ const merged = [...DEFAULT_PII_FIELDS, ...customFields];
724
+ return [...new Set(merged)];
725
+ };
726
+ /**
727
+ * Creates the instrumentation service that gates event emission behind an
728
+ * enabled flag and delegates to a pluggable transport.
729
+ *
730
+ * The transport is intentionally optional at creation time — it is wired in
731
+ * later via setTransport so the SDK can initialise without one. Events logged
732
+ * before a transport is set are simply dropped.
733
+ *
734
+ * Custom piiFields are merged with and deduplicated against the defaults so
735
+ * callers only need to list additional fields, not replicate the baseline.
736
+ */
737
+ const createInstrumentation = ({ config: inputConfig } = {}) => {
738
+ let transport;
739
+ const config = {
740
+ enabled: inputConfig?.enabled ?? true,
741
+ piiFields: buildPiiFields(inputConfig?.piiFields)
742
+ };
743
+ return {
744
+ config,
745
+ log: (event) => {
746
+ if (config.enabled) transport?.log(event);
747
+ },
748
+ setEnabled: (value) => {
749
+ config.enabled = value;
750
+ },
751
+ setTransport: (t) => {
752
+ transport = t;
753
+ }
754
+ };
755
+ };
756
+
704
757
  //#endregion
705
758
  //#region src/services/navigate/createNavigationHandler/createNavigationHandler.ts
706
759
  /**
@@ -916,6 +969,8 @@ const createCore = (config) => {
916
969
  const debouncedMutex = createDebouncedMutex();
917
970
  const eventEmitter = createEventEmitter();
918
971
  const initTrack = createAsyncTrack();
972
+ const sdkSessionId = randomString({ length: 32 });
973
+ const instrumentation = createInstrumentation({ config: config.instrumentation });
919
974
  const runtimeServices = createRuntimeServices();
920
975
  const passkey = config.coreConfig?.passkey ?? createWebPasskeyService();
921
976
  const realtime = config.coreConfig?.realtime ?? createRealtimeService();
@@ -932,6 +987,7 @@ const createCore = (config) => {
932
987
  fetch,
933
988
  getApiHeaders: config.coreConfig?.getApiHeaders ?? (() => ({})),
934
989
  initTrack,
990
+ instrumentation,
935
991
  keychain,
936
992
  logger,
937
993
  metadata: {
@@ -943,6 +999,7 @@ const createCore = (config) => {
943
999
  passkey,
944
1000
  realtime,
945
1001
  runtimeServices,
1002
+ sdkSessionId,
946
1003
  state,
947
1004
  storage,
948
1005
  transformers: config.transformers,
@@ -1365,47 +1422,6 @@ const signInWithExternalJwt = async ({ externalJwt, sessionPublicKey } = {}, cli
1365
1422
  return response;
1366
1423
  };
1367
1424
 
1368
- //#endregion
1369
- //#region src/modules/auth/getElevatedAccessToken/getElevatedAccessToken.ts
1370
- /**
1371
- * Gets an elevated access token by scope.
1372
- *
1373
- * This function retrieves an elevated access token that contains the specified scope.
1374
- * Expired tokens are automatically filtered out.
1375
- *
1376
- * If the token has `singleUse: true`, it will be automatically
1377
- * consumed (removed from state) after retrieval. Otherwise, it remains in state
1378
- * for future use.
1379
- *
1380
- * @param params - The parameters object.
1381
- * @param params.scope - The scope to match (e.g., 'wallet:export').
1382
- * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
1383
- * @returns The elevated access token if found and not expired, or undefined if not found or expired.
1384
- *
1385
- * @example
1386
- * ```typescript
1387
- * const token = getElevatedAccessToken({ scope: 'wallet:export' });
1388
- * if (token) {
1389
- * // Use the token
1390
- * // Token is automatically consumed if singleUse: true
1391
- * }
1392
- * ```
1393
- */
1394
- const getElevatedAccessToken = ({ scope }, client = getDefaultClient()) => {
1395
- const core = getCore(client);
1396
- const now = /* @__PURE__ */ new Date();
1397
- const elevatedAccessTokens = core.state.get().elevatedAccessTokens || [];
1398
- const validTokens = elevatedAccessTokens.filter((token$1) => !token$1.expiresAt || token$1.expiresAt > now);
1399
- if (validTokens.length !== elevatedAccessTokens.length) core.state.set({ elevatedAccessTokens: validTokens });
1400
- const token = validTokens.find((token$1) => token$1.scopes.includes(scope));
1401
- if (!token) return;
1402
- if (token.singleUse) {
1403
- const updatedTokens = validTokens.filter((t) => t !== token);
1404
- core.state.set({ elevatedAccessTokens: updatedTokens });
1405
- }
1406
- return token.token;
1407
- };
1408
-
1409
1425
  //#endregion
1410
1426
  //#region src/modules/auth/passkeys/deletePasskey/deletePasskey.ts
1411
1427
  /**
@@ -1417,7 +1433,10 @@ const getElevatedAccessToken = ({ scope }, client = getDefaultClient()) => {
1417
1433
  */
1418
1434
  const deletePasskey = async ({ passkeyId }, client = getDefaultClient()) => {
1419
1435
  const core = getCore(client);
1420
- await createApiClient({ includeMfaToken: true }, client).deletePasskey({
1436
+ await createApiClient({
1437
+ elevatedAccessTokenScope: TokenScope.Credentialunlink,
1438
+ includeMfaToken: true
1439
+ }, client).deletePasskey({
1421
1440
  deleteUserPasskeyRequest: { passkeyId },
1422
1441
  environmentId: core.environmentId
1423
1442
  });
@@ -1450,7 +1469,7 @@ const getPasskeyRegistrationOptions = async (client) => {
1450
1469
  //#region src/modules/auth/passkeys/serverRegisterPasskey/serverRegisterPasskey.ts
1451
1470
  const serverRegisterPasskey = async ({ registration, createMfaToken }, client) => {
1452
1471
  const core = getCore(client);
1453
- return await createApiClient({}, client).registerPasskey({
1472
+ return await createApiClient({ elevatedAccessTokenScope: TokenScope.Credentiallink }, client).registerPasskey({
1454
1473
  environmentId: core.environmentId,
1455
1474
  passkeyRegisterRequest: {
1456
1475
  ...registration,
@@ -3119,23 +3138,27 @@ const createNewMfaRecoveryCodes = async (client = getDefaultClient()) => {
3119
3138
  /**
3120
3139
  * Deletes a specific MFA device from the user's account.
3121
3140
  *
3122
- * This function removes a multi-factor authentication device such as
3123
- * a TOTP authenticator from the user's registered devices.
3141
+ * When an elevated access token for `credential:unlink` is available,
3142
+ * it is sent via the `x-dyn-elevated-access-token` header and the
3143
+ * MFA auth token is not required. Otherwise, `mfaAuthToken` must be
3144
+ * provided for backward compatibility with the legacy MFA flow.
3124
3145
  *
3125
3146
  * @param params.deviceId - The unique identifier of the MFA device to delete.
3126
- * @param params.mfaAuthToken - The MFA authentication token required for device deletion.
3147
+ * @param params.mfaAuthToken - The MFA authentication token. Optional when using elevated access tokens.
3127
3148
  * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
3128
3149
  * @returns A promise that resolves when the MFA device is successfully deleted.
3129
3150
  */
3130
3151
  const deleteMfaDevice = async ({ deviceId, mfaAuthToken }, client = getDefaultClient()) => {
3131
3152
  const core = getCore(client);
3132
- const apiClient = createApiClient({}, client);
3133
3153
  assertDefined(deviceId, "deviceId is required");
3134
- assertDefined(mfaAuthToken, "mfaAuthToken is required");
3135
- return apiClient.deleteMfaDevice({
3154
+ if (!getElevatedAccessToken({
3155
+ consume: false,
3156
+ scope: TokenScope.Credentialunlink
3157
+ }, client)) assertDefined(mfaAuthToken, "mfaAuthToken is required");
3158
+ return createApiClient({ elevatedAccessTokenScope: TokenScope.Credentialunlink }, client).deleteMfaDevice({
3136
3159
  environmentId: core.environmentId,
3137
3160
  mfaDeviceId: deviceId,
3138
- xMfaAuthToken: mfaAuthToken
3161
+ xMfaAuthToken: mfaAuthToken ?? ""
3139
3162
  });
3140
3163
  };
3141
3164
 
@@ -3222,7 +3245,7 @@ const isUserMissingMfaAuth = (client = getDefaultClient()) => {
3222
3245
  */
3223
3246
  const registerTotpMfaDevice = async (client = getDefaultClient()) => {
3224
3247
  const core = getCore(client);
3225
- return createApiClient({}, client).registerTotpMfaDevice({ environmentId: core.environmentId });
3248
+ return createApiClient({ elevatedAccessTokenScope: TokenScope.Credentiallink }, client).registerTotpMfaDevice({ environmentId: core.environmentId });
3226
3249
  };
3227
3250
 
3228
3251
  //#endregion