@volr/sdk-core 0.1.64 → 0.1.66

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/dist/index.d.cts CHANGED
@@ -30,6 +30,25 @@ type AesGcmParams = {
30
30
  /** Additional Authenticated Data (optional) */
31
31
  aad?: Uint8Array;
32
32
  };
33
+ /**
34
+ * Generate a unique 12-byte nonce for AES-GCM
35
+ *
36
+ * Format: [4 bytes timestamp] + [8 bytes random]
37
+ *
38
+ * This hybrid approach provides:
39
+ * 1. Timestamp component: Reduces collision probability across different times
40
+ * 2. Random component: Reduces collision probability at the same time
41
+ *
42
+ * Collision analysis:
43
+ * - With purely random 96-bit nonces: 2^32 encryptions before 50% collision probability
44
+ * - With timestamp + 64-bit random: Collisions require same second + same random (2^64 per second)
45
+ *
46
+ * Note: This is belt-and-suspenders - in practice, master seeds are encrypted
47
+ * only once per enrollment, so collisions are extremely unlikely either way.
48
+ *
49
+ * @returns 12-byte Uint8Array nonce
50
+ */
51
+ declare function generateNonce(): Uint8Array;
33
52
  /**
34
53
  * AES-256-GCM encryption
35
54
  *
@@ -1262,6 +1281,14 @@ type PasskeyProviderOptions = {
1262
1281
  };
1263
1282
  /** Additional Authenticated Data for unwrapping */
1264
1283
  aad?: Uint8Array;
1284
+ /**
1285
+ * Session TTL in milliseconds.
1286
+ * - 0 (default): No caching - requires WebAuthn authentication for every signature (most secure)
1287
+ * - >0: Cache private key in memory for this duration (less secure, better UX)
1288
+ *
1289
+ * @default 0
1290
+ */
1291
+ sessionTtlMs?: number;
1265
1292
  };
1266
1293
  /**
1267
1294
  * Create passkey provider
@@ -1341,4 +1368,4 @@ type SelectSignerContext = {
1341
1368
  */
1342
1369
  declare function selectSigner(ctx: SelectSignerContext): Promise<SignerPort>;
1343
1370
 
1344
- export { type AesGcmParams, type AuthorizationTuple, type Call, ChainNotAddedError, DEFAULT_EVM_PATH, DOMAIN, type DeriveArgs, EIP1193ErrorCode, type EIP1193Provider, EIP712_DOMAIN, ERR_AAD_MISMATCH, ERR_CHAIN_MISMATCH, ERR_CRYPTO_FAIL, ERR_INVALID_PARAM, ERR_LOW_ENTROPY, ERR_NONCE_SIZE, type EvmKeypair, type ExtendedRPCClient, ExternalWalletSigner, type KeyStorageType, type Sig$1 as LegacySig, type MasterKeyProvider, type MasterSeed, type MasterSeedHandle, type MpcTransport, PasskeyP256Signer, type PasskeyProviderOptions, type PasskeyProviderPort, type PrecheckInput, type PrecheckQuote, type PrfInput, type RelayInput, type RelayMode, type RelayResult, RequestPendingError, type RpcLike, Secp256k1SoftwareSigner, type SelectSignerContext, type SessionAuth, type Sig, type SignerContext, type SignerKind, type SignerPort, TYPES, type TypedDataInput, UnauthorizedError, UnsupportedMethodError, type UploadBlobOptions, type UploadViaPresignOptions, UserRejectedError, VolrError, WalletError, type WalletProviderPort, type WrapKey, WrongNetworkError, ZERO_ADDRESS, ZERO_HASH, aesGcmDecrypt, aesGcmEncrypt, buildSignedBatchMessage, computeCallsHash, createMasterKeyProvider, createMpcProvider, createPasskeyProvider, deriveEvmKey, deriveWrapKey, evmSign, evmVerify, getAuthNonce, getRandomBytes, hkdfSha256, normalizeWalletError, sealMasterSeed, selectSigner, selectSigner$1 as selectSignerLegacy, signAuthorization, signSession, toChecksumAddress, unsealMasterSeed, uploadBlob, uploadBlobViaPresign, zeroize };
1371
+ export { type AesGcmParams, type AuthorizationTuple, type Call, ChainNotAddedError, DEFAULT_EVM_PATH, DOMAIN, type DeriveArgs, EIP1193ErrorCode, type EIP1193Provider, EIP712_DOMAIN, ERR_AAD_MISMATCH, ERR_CHAIN_MISMATCH, ERR_CRYPTO_FAIL, ERR_INVALID_PARAM, ERR_LOW_ENTROPY, ERR_NONCE_SIZE, type EvmKeypair, type ExtendedRPCClient, ExternalWalletSigner, type KeyStorageType, type Sig$1 as LegacySig, type MasterKeyProvider, type MasterSeed, type MasterSeedHandle, type MpcTransport, PasskeyP256Signer, type PasskeyProviderOptions, type PasskeyProviderPort, type PrecheckInput, type PrecheckQuote, type PrfInput, type RelayInput, type RelayMode, type RelayResult, RequestPendingError, type RpcLike, Secp256k1SoftwareSigner, type SelectSignerContext, type SessionAuth, type Sig, type SignerContext, type SignerKind, type SignerPort, TYPES, type TypedDataInput, UnauthorizedError, UnsupportedMethodError, type UploadBlobOptions, type UploadViaPresignOptions, UserRejectedError, VolrError, WalletError, type WalletProviderPort, type WrapKey, WrongNetworkError, ZERO_ADDRESS, ZERO_HASH, aesGcmDecrypt, aesGcmEncrypt, buildSignedBatchMessage, computeCallsHash, createMasterKeyProvider, createMpcProvider, createPasskeyProvider, deriveEvmKey, deriveWrapKey, evmSign, evmVerify, generateNonce, getAuthNonce, getRandomBytes, hkdfSha256, normalizeWalletError, sealMasterSeed, selectSigner, selectSigner$1 as selectSignerLegacy, signAuthorization, signSession, toChecksumAddress, unsealMasterSeed, uploadBlob, uploadBlobViaPresign, zeroize };
package/dist/index.d.ts CHANGED
@@ -30,6 +30,25 @@ type AesGcmParams = {
30
30
  /** Additional Authenticated Data (optional) */
31
31
  aad?: Uint8Array;
32
32
  };
33
+ /**
34
+ * Generate a unique 12-byte nonce for AES-GCM
35
+ *
36
+ * Format: [4 bytes timestamp] + [8 bytes random]
37
+ *
38
+ * This hybrid approach provides:
39
+ * 1. Timestamp component: Reduces collision probability across different times
40
+ * 2. Random component: Reduces collision probability at the same time
41
+ *
42
+ * Collision analysis:
43
+ * - With purely random 96-bit nonces: 2^32 encryptions before 50% collision probability
44
+ * - With timestamp + 64-bit random: Collisions require same second + same random (2^64 per second)
45
+ *
46
+ * Note: This is belt-and-suspenders - in practice, master seeds are encrypted
47
+ * only once per enrollment, so collisions are extremely unlikely either way.
48
+ *
49
+ * @returns 12-byte Uint8Array nonce
50
+ */
51
+ declare function generateNonce(): Uint8Array;
33
52
  /**
34
53
  * AES-256-GCM encryption
35
54
  *
@@ -1262,6 +1281,14 @@ type PasskeyProviderOptions = {
1262
1281
  };
1263
1282
  /** Additional Authenticated Data for unwrapping */
1264
1283
  aad?: Uint8Array;
1284
+ /**
1285
+ * Session TTL in milliseconds.
1286
+ * - 0 (default): No caching - requires WebAuthn authentication for every signature (most secure)
1287
+ * - >0: Cache private key in memory for this duration (less secure, better UX)
1288
+ *
1289
+ * @default 0
1290
+ */
1291
+ sessionTtlMs?: number;
1265
1292
  };
1266
1293
  /**
1267
1294
  * Create passkey provider
@@ -1341,4 +1368,4 @@ type SelectSignerContext = {
1341
1368
  */
1342
1369
  declare function selectSigner(ctx: SelectSignerContext): Promise<SignerPort>;
1343
1370
 
1344
- export { type AesGcmParams, type AuthorizationTuple, type Call, ChainNotAddedError, DEFAULT_EVM_PATH, DOMAIN, type DeriveArgs, EIP1193ErrorCode, type EIP1193Provider, EIP712_DOMAIN, ERR_AAD_MISMATCH, ERR_CHAIN_MISMATCH, ERR_CRYPTO_FAIL, ERR_INVALID_PARAM, ERR_LOW_ENTROPY, ERR_NONCE_SIZE, type EvmKeypair, type ExtendedRPCClient, ExternalWalletSigner, type KeyStorageType, type Sig$1 as LegacySig, type MasterKeyProvider, type MasterSeed, type MasterSeedHandle, type MpcTransport, PasskeyP256Signer, type PasskeyProviderOptions, type PasskeyProviderPort, type PrecheckInput, type PrecheckQuote, type PrfInput, type RelayInput, type RelayMode, type RelayResult, RequestPendingError, type RpcLike, Secp256k1SoftwareSigner, type SelectSignerContext, type SessionAuth, type Sig, type SignerContext, type SignerKind, type SignerPort, TYPES, type TypedDataInput, UnauthorizedError, UnsupportedMethodError, type UploadBlobOptions, type UploadViaPresignOptions, UserRejectedError, VolrError, WalletError, type WalletProviderPort, type WrapKey, WrongNetworkError, ZERO_ADDRESS, ZERO_HASH, aesGcmDecrypt, aesGcmEncrypt, buildSignedBatchMessage, computeCallsHash, createMasterKeyProvider, createMpcProvider, createPasskeyProvider, deriveEvmKey, deriveWrapKey, evmSign, evmVerify, getAuthNonce, getRandomBytes, hkdfSha256, normalizeWalletError, sealMasterSeed, selectSigner, selectSigner$1 as selectSignerLegacy, signAuthorization, signSession, toChecksumAddress, unsealMasterSeed, uploadBlob, uploadBlobViaPresign, zeroize };
1371
+ export { type AesGcmParams, type AuthorizationTuple, type Call, ChainNotAddedError, DEFAULT_EVM_PATH, DOMAIN, type DeriveArgs, EIP1193ErrorCode, type EIP1193Provider, EIP712_DOMAIN, ERR_AAD_MISMATCH, ERR_CHAIN_MISMATCH, ERR_CRYPTO_FAIL, ERR_INVALID_PARAM, ERR_LOW_ENTROPY, ERR_NONCE_SIZE, type EvmKeypair, type ExtendedRPCClient, ExternalWalletSigner, type KeyStorageType, type Sig$1 as LegacySig, type MasterKeyProvider, type MasterSeed, type MasterSeedHandle, type MpcTransport, PasskeyP256Signer, type PasskeyProviderOptions, type PasskeyProviderPort, type PrecheckInput, type PrecheckQuote, type PrfInput, type RelayInput, type RelayMode, type RelayResult, RequestPendingError, type RpcLike, Secp256k1SoftwareSigner, type SelectSignerContext, type SessionAuth, type Sig, type SignerContext, type SignerKind, type SignerPort, TYPES, type TypedDataInput, UnauthorizedError, UnsupportedMethodError, type UploadBlobOptions, type UploadViaPresignOptions, UserRejectedError, VolrError, WalletError, type WalletProviderPort, type WrapKey, WrongNetworkError, ZERO_ADDRESS, ZERO_HASH, aesGcmDecrypt, aesGcmEncrypt, buildSignedBatchMessage, computeCallsHash, createMasterKeyProvider, createMpcProvider, createPasskeyProvider, deriveEvmKey, deriveWrapKey, evmSign, evmVerify, generateNonce, getAuthNonce, getRandomBytes, hkdfSha256, normalizeWalletError, sealMasterSeed, selectSigner, selectSigner$1 as selectSignerLegacy, signAuthorization, signSession, toChecksumAddress, unsealMasterSeed, uploadBlob, uploadBlobViaPresign, zeroize };
package/dist/index.js CHANGED
@@ -73,6 +73,15 @@ function getRandomBytes(len) {
73
73
  }
74
74
 
75
75
  // src/core/crypto/aes-gcm.ts
76
+ function generateNonce() {
77
+ const nonce = new Uint8Array(12);
78
+ const timestamp = Math.floor(Date.now() / 1e3);
79
+ const view = new DataView(nonce.buffer);
80
+ view.setUint32(0, timestamp, false);
81
+ const random = getRandomBytes(8);
82
+ nonce.set(random, 4);
83
+ return nonce;
84
+ }
76
85
  function getSubtleCrypto() {
77
86
  if (typeof crypto !== "undefined" && crypto.subtle) {
78
87
  return crypto.subtle;
@@ -93,7 +102,7 @@ async function aesGcmEncrypt(plain, params) {
93
102
  if (key.length !== 32) {
94
103
  throw new Error(`${ERR_INVALID_PARAM}: key must be 32 bytes, got ${key.length}`);
95
104
  }
96
- const nonce = providedNonce || getRandomBytes(12);
105
+ const nonce = providedNonce || generateNonce();
97
106
  if (nonce.length !== 12) {
98
107
  throw new Error(`${ERR_NONCE_SIZE}: nonce must be 12 bytes, got ${nonce.length}`);
99
108
  }
@@ -1050,62 +1059,79 @@ async function getAuthNonce(client, from, mode) {
1050
1059
  }
1051
1060
  function createPasskeyProvider(passkey, options) {
1052
1061
  let unwrappedKeypair = null;
1053
- const ensureSession = async (opts) => {
1054
- if (opts?.force && unwrappedKeypair) {
1055
- console.log("[PasskeyProvider] force=true: zeroizing existing session");
1062
+ const sessionTtlMs = options.sessionTtlMs ?? 0;
1063
+ let sessionExpiresAt = null;
1064
+ let lockTimer = null;
1065
+ const isSessionExpired = () => {
1066
+ if (sessionTtlMs === 0) return true;
1067
+ if (!sessionExpiresAt) return true;
1068
+ return Date.now() >= sessionExpiresAt;
1069
+ };
1070
+ const resetSessionTimer = () => {
1071
+ if (sessionTtlMs <= 0) return;
1072
+ if (lockTimer) {
1073
+ clearTimeout(lockTimer);
1074
+ lockTimer = null;
1075
+ }
1076
+ sessionExpiresAt = Date.now() + sessionTtlMs;
1077
+ lockTimer = setTimeout(async () => {
1078
+ console.log("[PasskeyProvider] Session expired, auto-locking");
1079
+ await lock();
1080
+ }, sessionTtlMs);
1081
+ };
1082
+ const lock = async () => {
1083
+ if (lockTimer) {
1084
+ clearTimeout(lockTimer);
1085
+ lockTimer = null;
1086
+ }
1087
+ sessionExpiresAt = null;
1088
+ if (unwrappedKeypair) {
1089
+ console.log("[PasskeyProvider] lock(): zeroizing sensitive data from memory");
1056
1090
  zeroize(unwrappedKeypair.privateKey);
1057
1091
  zeroize(unwrappedKeypair.publicKey);
1058
1092
  unwrappedKeypair = null;
1059
1093
  }
1060
- if (unwrappedKeypair) {
1094
+ };
1095
+ const ensureSession = async (opts) => {
1096
+ if (opts?.force && unwrappedKeypair) {
1097
+ console.log("[PasskeyProvider] force=true: zeroizing existing session");
1098
+ await lock();
1099
+ }
1100
+ if (unwrappedKeypair && !isSessionExpired()) {
1101
+ resetSessionTimer();
1061
1102
  return;
1062
1103
  }
1063
- if (opts?.interactive || opts?.force) {
1064
- console.log("[PasskeyProvider] interactive mode: triggering WebAuthn prompt");
1065
- const prfSalt = deriveWrapKey(options.prfInput);
1066
- const { prfOutput } = await passkey.authenticate({
1067
- salt: prfSalt,
1068
- credentialId: options.prfInput.credentialId
1069
- });
1070
- const wrapKey = prfOutput;
1071
- const aad = options.aad || new TextEncoder().encode("volr/master-seed/v1");
1072
- const masterSeed = await unsealMasterSeed(
1073
- options.encryptedBlob.cipher,
1074
- wrapKey,
1075
- aad,
1076
- options.encryptedBlob.nonce
1077
- );
1078
- const keypair = deriveEvmKey({ masterSeed });
1079
- unwrappedKeypair = {
1080
- privateKey: keypair.privateKey,
1081
- publicKey: keypair.publicKey,
1082
- address: keypair.address
1083
- };
1084
- zeroize(masterSeed);
1085
- zeroize(wrapKey);
1086
- zeroize(prfSalt);
1087
- } else {
1088
- console.warn("[PasskeyProvider] Non-interactive mode: using deterministic wrap key (insecure for TTL=0)");
1089
- const wrapKey = deriveWrapKey(options.prfInput);
1090
- const aad = options.aad || new TextEncoder().encode("volr/master-seed/v1");
1091
- const masterSeed = await unsealMasterSeed(
1092
- options.encryptedBlob.cipher,
1093
- wrapKey,
1094
- aad,
1095
- options.encryptedBlob.nonce
1096
- );
1097
- const keypair = deriveEvmKey({ masterSeed });
1098
- unwrappedKeypair = {
1099
- privateKey: keypair.privateKey,
1100
- publicKey: keypair.publicKey,
1101
- address: keypair.address
1102
- };
1103
- zeroize(masterSeed);
1104
- zeroize(wrapKey);
1104
+ if (unwrappedKeypair && isSessionExpired()) {
1105
+ console.log("[PasskeyProvider] Session expired, re-authenticating");
1106
+ await lock();
1105
1107
  }
1108
+ console.log("[PasskeyProvider] Triggering WebAuthn prompt for hardware-backed authentication");
1109
+ const prfSalt = deriveWrapKey(options.prfInput);
1110
+ const { prfOutput } = await passkey.authenticate({
1111
+ salt: prfSalt,
1112
+ credentialId: options.prfInput.credentialId
1113
+ });
1114
+ const wrapKey = prfOutput;
1115
+ const aad = options.aad || new TextEncoder().encode("volr/master-seed/v1");
1116
+ const masterSeed = await unsealMasterSeed(
1117
+ options.encryptedBlob.cipher,
1118
+ wrapKey,
1119
+ aad,
1120
+ options.encryptedBlob.nonce
1121
+ );
1122
+ const keypair = deriveEvmKey({ masterSeed });
1123
+ unwrappedKeypair = {
1124
+ privateKey: keypair.privateKey,
1125
+ publicKey: keypair.publicKey,
1126
+ address: keypair.address
1127
+ };
1128
+ zeroize(masterSeed);
1129
+ zeroize(wrapKey);
1130
+ zeroize(prfSalt);
1131
+ resetSessionTimer();
1106
1132
  };
1107
1133
  const getAddress = async () => {
1108
- await ensureSession();
1134
+ await ensureSession({ });
1109
1135
  if (!unwrappedKeypair) {
1110
1136
  throw new Error(`${ERR_INVALID_PARAM}: Session not established`);
1111
1137
  }
@@ -1115,11 +1141,15 @@ function createPasskeyProvider(passkey, options) {
1115
1141
  if (hash32.length !== 32) {
1116
1142
  throw new Error(`${ERR_INVALID_PARAM}: Message hash must be 32 bytes, got ${hash32.length}`);
1117
1143
  }
1118
- await ensureSession();
1144
+ const shouldForceFresh = sessionTtlMs === 0;
1145
+ await ensureSession({ force: shouldForceFresh });
1119
1146
  if (!unwrappedKeypair) {
1120
1147
  throw new Error(`${ERR_INVALID_PARAM}: Session not established`);
1121
1148
  }
1122
1149
  const sig = evmSign(unwrappedKeypair.privateKey, hash32);
1150
+ if (shouldForceFresh) {
1151
+ await lock();
1152
+ }
1123
1153
  return {
1124
1154
  r: sig.r,
1125
1155
  s: sig.s,
@@ -1127,7 +1157,8 @@ function createPasskeyProvider(passkey, options) {
1127
1157
  };
1128
1158
  };
1129
1159
  const signTypedData = async (input) => {
1130
- await ensureSession();
1160
+ const shouldForceFresh = sessionTtlMs === 0;
1161
+ await ensureSession({ force: shouldForceFresh });
1131
1162
  if (!unwrappedKeypair) {
1132
1163
  throw new Error(`${ERR_INVALID_PARAM}: Session not established`);
1133
1164
  }
@@ -1143,7 +1174,10 @@ function createPasskeyProvider(passkey, options) {
1143
1174
  for (let i = 0; i < 32; i++) {
1144
1175
  msgHashBytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
1145
1176
  }
1146
- const sig = await signMessage(msgHashBytes);
1177
+ const sig = evmSign(unwrappedKeypair.privateKey, msgHashBytes);
1178
+ if (shouldForceFresh) {
1179
+ await lock();
1180
+ }
1147
1181
  const v = sig.yParity + 27;
1148
1182
  const rHex = Array.from(sig.r).map((b) => b.toString(16).padStart(2, "0")).join("");
1149
1183
  const sHex = Array.from(sig.s).map((b) => b.toString(16).padStart(2, "0")).join("");
@@ -1151,20 +1185,12 @@ function createPasskeyProvider(passkey, options) {
1151
1185
  return `0x${rHex}${sHex}${vHex}`;
1152
1186
  };
1153
1187
  const getPublicKey = async () => {
1154
- await ensureSession();
1188
+ await ensureSession({ });
1155
1189
  if (!unwrappedKeypair) {
1156
1190
  throw new Error(`${ERR_INVALID_PARAM}: Session not established`);
1157
1191
  }
1158
1192
  return new Uint8Array(unwrappedKeypair.publicKey);
1159
1193
  };
1160
- const lock = async () => {
1161
- if (unwrappedKeypair) {
1162
- console.log("[PasskeyProvider] lock(): zeroizing sensitive data from memory");
1163
- zeroize(unwrappedKeypair.privateKey);
1164
- zeroize(unwrappedKeypair.publicKey);
1165
- unwrappedKeypair = null;
1166
- }
1167
- };
1168
1194
  return {
1169
1195
  keyStorageType: "passkey",
1170
1196
  ensureSession,
@@ -1283,6 +1309,6 @@ async function selectSigner2(ctx) {
1283
1309
  );
1284
1310
  }
1285
1311
 
1286
- export { ChainNotAddedError, DEFAULT_EVM_PATH, DOMAIN, EIP1193ErrorCode, EIP712_DOMAIN, ERR_AAD_MISMATCH, ERR_CHAIN_MISMATCH, ERR_CRYPTO_FAIL, ERR_INVALID_PARAM, ERR_LOW_ENTROPY, ERR_NONCE_SIZE, ExternalWalletSigner, PasskeyP256Signer, RequestPendingError, Secp256k1SoftwareSigner, TYPES, UnauthorizedError, UnsupportedMethodError, UserRejectedError, VolrError, WalletError, WrongNetworkError, ZERO_ADDRESS, ZERO_HASH, aesGcmDecrypt, aesGcmEncrypt, buildSignedBatchMessage, computeCallsHash, createMasterKeyProvider, createMpcProvider, createPasskeyProvider, deriveEvmKey, deriveWrapKey, evmSign, evmVerify, getAuthNonce, getRandomBytes, hkdfSha256, normalizeWalletError, sealMasterSeed, selectSigner, selectSigner2 as selectSignerLegacy, signAuthorization, signSession, toChecksumAddress, unsealMasterSeed, uploadBlob, uploadBlobViaPresign, zeroize };
1312
+ export { ChainNotAddedError, DEFAULT_EVM_PATH, DOMAIN, EIP1193ErrorCode, EIP712_DOMAIN, ERR_AAD_MISMATCH, ERR_CHAIN_MISMATCH, ERR_CRYPTO_FAIL, ERR_INVALID_PARAM, ERR_LOW_ENTROPY, ERR_NONCE_SIZE, ExternalWalletSigner, PasskeyP256Signer, RequestPendingError, Secp256k1SoftwareSigner, TYPES, UnauthorizedError, UnsupportedMethodError, UserRejectedError, VolrError, WalletError, WrongNetworkError, ZERO_ADDRESS, ZERO_HASH, aesGcmDecrypt, aesGcmEncrypt, buildSignedBatchMessage, computeCallsHash, createMasterKeyProvider, createMpcProvider, createPasskeyProvider, deriveEvmKey, deriveWrapKey, evmSign, evmVerify, generateNonce, getAuthNonce, getRandomBytes, hkdfSha256, normalizeWalletError, sealMasterSeed, selectSigner, selectSigner2 as selectSignerLegacy, signAuthorization, signSession, toChecksumAddress, unsealMasterSeed, uploadBlob, uploadBlobViaPresign, zeroize };
1287
1313
  //# sourceMappingURL=index.js.map
1288
1314
  //# sourceMappingURL=index.js.map