@getpara/core-sdk 2.8.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -206,7 +206,7 @@ const _ParaCore = class _ParaCore {
206
206
  }
207
207
  });
208
208
  } catch (e) {
209
- console.error("error tracking error:", e);
209
+ this.devLog("error tracking error:", e);
210
210
  }
211
211
  throw err;
212
212
  });
@@ -234,6 +234,7 @@ const _ParaCore = class _ParaCore {
234
234
  this.updateSessionCookieFromStorage();
235
235
  this.updateLoginEncryptionKeyPairFromStorage();
236
236
  this.updateEnclaveJwtFromStorage();
237
+ this.updateIsEnclaveUserFromStorage();
237
238
  };
238
239
  this.updateAuthInfoFromStorage = () => {
239
240
  var _a;
@@ -257,6 +258,12 @@ const _ParaCore = class _ParaCore {
257
258
  this.enclaveJwt = this.localStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_JWT) || this.sessionStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_JWT) || void 0;
258
259
  this.enclaveRefreshJwt = this.localStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_REFRESH_JWT) || this.sessionStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_REFRESH_JWT) || void 0;
259
260
  };
261
+ this.updateIsEnclaveUserFromStorage = () => {
262
+ const stored = this.localStorageGetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER);
263
+ if (stored != null) {
264
+ this.isEnclaveUser = JSON.parse(stored);
265
+ }
266
+ };
260
267
  this.updateUserIdFromStorage = () => {
261
268
  this.userId = this.localStorageGetItem(constants.LOCAL_STORAGE_USER_ID) || void 0;
262
269
  };
@@ -784,7 +791,8 @@ const _ParaCore = class _ParaCore {
784
791
  isFarcasterLogin,
785
792
  isAddNewCredential,
786
793
  isSwitchWallets,
787
- isExportPrivateKey
794
+ isExportPrivateKey,
795
+ isTxReview
788
796
  ] = [
789
797
  ["createAuth", "createPassword", "createPIN"].includes(type),
790
798
  ["loginAuth", "loginPassword", "loginPIN", "loginOTP", "switchWallets", "loginExternalWallet"].includes(type),
@@ -795,7 +803,8 @@ const _ParaCore = class _ParaCore {
795
803
  type === "loginFarcaster",
796
804
  type === "addNewCredential",
797
805
  type === "switchWallets",
798
- type === "exportPrivateKey"
806
+ type === "exportPrivateKey",
807
+ type === "txReview"
799
808
  ];
800
809
  if (isOAuth && !opts.oAuthMethod) {
801
810
  throw new Error("oAuthMethod is required for oAuth portal URLs");
@@ -804,7 +813,7 @@ const _ParaCore = class _ParaCore {
804
813
  this.assertIsAuthSet();
805
814
  }
806
815
  let sessionId = opts.sessionId;
807
- if ((isLogin || isOnRamp || isTelegramLogin || isFarcasterLogin || isExportPrivateKey) && !sessionId) {
816
+ if ((isLogin || isOnRamp || isTelegramLogin || isFarcasterLogin || isExportPrivateKey || isTxReview) && !sessionId) {
808
817
  const session = yield this.touchSession(true);
809
818
  sessionId = session.sessionId;
810
819
  }
@@ -812,7 +821,7 @@ const _ParaCore = class _ParaCore {
812
821
  yield this.setLoginEncryptionKeyPair();
813
822
  }
814
823
  const shouldUseLegacyPortalUrl = opts.useLegacyUrl || !!opts.addNewCredentialPasskeyId || type === "loginAuth";
815
- const base = type === "onRamp" || isTelegramLogin ? (0, import_utils2.getPortalBaseURL)(this.ctx, isTelegramLogin, false, shouldUseLegacyPortalUrl) : yield this.getPortalURL(shouldUseLegacyPortalUrl);
824
+ const base = type === "onRamp" || isTelegramLogin ? this.ctx.portalUrlOverride || (0, import_utils2.getPortalBaseURL)(this.ctx, isTelegramLogin, false, shouldUseLegacyPortalUrl) : yield this.getPortalURL(shouldUseLegacyPortalUrl);
816
825
  let path;
817
826
  switch (type) {
818
827
  case "createPassword": {
@@ -946,7 +955,7 @@ const _ParaCore = class _ParaCore {
946
955
  }) : {}), isLogin && {
947
956
  // Prior versions won't have this param which will skip the upgrade prompt
948
957
  isBasicLoginUpgradeVersion: "true"
949
- }), isExportPrivateKey ? {
958
+ }), isExportPrivateKey || isTxReview ? {
950
959
  sessionId: thisDevice.sessionId
951
960
  } : {});
952
961
  const url = (0, import_utils2.constructUrl)({ base, path, params });
@@ -1109,6 +1118,10 @@ Need help? Visit: https://docs.getpara.com or contact support
1109
1118
  if (loginEncryptionKey && loginEncryptionKey !== "undefined") {
1110
1119
  this.loginEncryptionKeyPair = this.convertEncryptionKeyPair(JSON.parse(loginEncryptionKey));
1111
1120
  }
1121
+ const storedIsEnclaveUser = yield this.localStorageGetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER);
1122
+ if (storedIsEnclaveUser != null) {
1123
+ this.isEnclaveUser = JSON.parse(storedIsEnclaveUser);
1124
+ }
1112
1125
  import_utils2.setupListeners.bind(this)();
1113
1126
  yield this.touchSession();
1114
1127
  });
@@ -1140,7 +1153,9 @@ Need help? Visit: https://docs.getpara.com or contact support
1140
1153
  const errorStr = String(error);
1141
1154
  const errorMessage = error instanceof Error ? error.message : "";
1142
1155
  if (errorStr.includes("blocked by CORS policy") && errorStr.includes("Access-Control-Allow-Origin")) {
1143
- this.displayModalError("Request rate limit reached. Please wait a couple of minutes and try again.");
1156
+ const message = "Request rate limit reached. Please wait a couple of minutes and try again.";
1157
+ console.error(`[Para] ${message}`);
1158
+ this.displayModalError(message);
1144
1159
  return;
1145
1160
  }
1146
1161
  if (error.status === 403 && errorMessage.includes("origin not authorized")) {
@@ -1568,7 +1583,7 @@ Need help? Visit: https://docs.getpara.com or contact support
1568
1583
  */
1569
1584
  getPortalURL(isLegacy) {
1570
1585
  return __async(this, null, function* () {
1571
- return (yield this.getPartnerURL()) || (0, import_utils2.getPortalBaseURL)(this.ctx, false, false, isLegacy);
1586
+ return this.ctx.portalUrlOverride || (yield this.getPartnerURL()) || (0, import_utils2.getPortalBaseURL)(this.ctx, false, false, isLegacy);
1572
1587
  });
1573
1588
  }
1574
1589
  /**
@@ -2048,13 +2063,42 @@ Need help? Visit: https://docs.getpara.com or contact support
2048
2063
  const pregenWallets = yield this.getPregenWallets();
2049
2064
  let recoverySecret, walletIds = {};
2050
2065
  if (pregenWallets.length > 0) {
2051
- recoverySecret = yield this.claimPregenWallets();
2052
- walletIds = supportedWalletTypes.reduce((acc, { type }) => {
2053
- var _a;
2054
- return __spreadProps(__spreadValues({}, acc), {
2055
- [type]: [(_a = pregenWallets.find((w) => !!import_utils2.WalletSchemeTypeMap[w.scheme][type])) == null ? void 0 : _a.id]
2066
+ let shares = [];
2067
+ try {
2068
+ shares = yield this.ctx.enclaveClient.getPregenShares({
2069
+ userId: this.userId,
2070
+ walletIds: pregenWallets.map((w) => w.id),
2071
+ partnerId: pregenWallets[0].partnerId
2056
2072
  });
2057
- }, {});
2073
+ for (const share of shares) {
2074
+ const wallet = pregenWallets.find((w) => w.id === share.walletId);
2075
+ if (wallet) {
2076
+ this.wallets[wallet.id] = {
2077
+ id: wallet.id,
2078
+ address: wallet.address,
2079
+ scheme: wallet.scheme,
2080
+ type: wallet.type,
2081
+ partnerId: wallet.partnerId,
2082
+ isPregen: wallet.isPregen,
2083
+ pregenIdentifier: wallet.pregenIdentifier,
2084
+ pregenIdentifierType: wallet.pregenIdentifierType,
2085
+ signer: share.signer,
2086
+ createdAt: String(wallet.createdAt)
2087
+ };
2088
+ }
2089
+ }
2090
+ } catch (err) {
2091
+ console.warn("[waitForWalletCreation] Failed to fetch pregen shares:", err);
2092
+ }
2093
+ if (shares.length > 0) {
2094
+ recoverySecret = yield this.claimPregenWallets();
2095
+ walletIds = supportedWalletTypes.reduce((acc, { type }) => {
2096
+ var _a;
2097
+ return __spreadProps(__spreadValues({}, acc), {
2098
+ [type]: [(_a = pregenWallets.find((w) => !!import_utils2.WalletSchemeTypeMap[w.scheme][type])) == null ? void 0 : _a.id]
2099
+ });
2100
+ }, {});
2101
+ }
2058
2102
  }
2059
2103
  const created = yield this.createWalletPerType();
2060
2104
  recoverySecret = recoverySecret != null ? recoverySecret : created.recoverySecret;
@@ -3233,6 +3277,7 @@ Need help? Visit: https://docs.getpara.com or contact support
3233
3277
  this.accountLinkInProgress = void 0;
3234
3278
  this.userId = void 0;
3235
3279
  this.sessionCookie = void 0;
3280
+ this.isEnclaveUser = false;
3236
3281
  if (shouldDispatchLogoutEvent) {
3237
3282
  (0, import_utils2.dispatchEvent)(import_types.ParaEvent.LOGOUT_EVENT, null);
3238
3283
  }
@@ -3759,14 +3804,26 @@ getOAuthUrl_fn = function(_0) {
3759
3804
  if (!accountLinkInProgress && !this.isPortal()) {
3760
3805
  return yield this.constructPortalUrl("oAuth", { sessionId: sessionLookupId, oAuthMethod: method, appScheme });
3761
3806
  }
3762
- let portalSessionLookupId;
3763
- if (this.isPortal()) {
3764
- portalSessionLookupId = (yield this.touchSession(true)).sessionLookupId;
3765
- }
3807
+ const [portalSessionLookupId, callback] = yield Promise.all([
3808
+ this.isPortal() ? this.touchSession(true).then((s) => s.sessionLookupId) : Promise.resolve(void 0),
3809
+ !accountLinkInProgress ? this.constructPortalUrl("oAuthCallback", __spreadValues({
3810
+ sessionId: sessionLookupId,
3811
+ oAuthMethod: method,
3812
+ appScheme,
3813
+ thisDevice: {
3814
+ sessionId: sessionLookupId,
3815
+ encryptionKey
3816
+ }
3817
+ }, this.isPortal() && {
3818
+ params: portalCallbackParams,
3819
+ // Build callback for legacy portal if needed
3820
+ useLegacyUrl: typeof window !== "undefined" ? window.location.host.includes("usecapsule") : false
3821
+ })) : Promise.resolve(false)
3822
+ ]);
3766
3823
  return (0, import_utils2.constructUrl)({
3767
3824
  base: (0, import_userManagementClient.getBaseOAuthUrl)(this.ctx.env),
3768
3825
  path: `/auth/${method.toLowerCase()}`,
3769
- params: __spreadProps(__spreadValues({
3826
+ params: __spreadValues(__spreadValues({
3770
3827
  apiKey: this.ctx.apiKey,
3771
3828
  origin: typeof window !== "undefined" ? window.location.origin : void 0,
3772
3829
  sessionLookupId,
@@ -3774,21 +3831,7 @@ getOAuthUrl_fn = function(_0) {
3774
3831
  appScheme
3775
3832
  }, accountLinkInProgress ? {
3776
3833
  linkedAccountId: this.accountLinkInProgress.id
3777
- } : {}), {
3778
- callback: !accountLinkInProgress && (yield this.constructPortalUrl("oAuthCallback", __spreadValues({
3779
- sessionId: sessionLookupId,
3780
- oAuthMethod: method,
3781
- appScheme,
3782
- thisDevice: {
3783
- sessionId: sessionLookupId,
3784
- encryptionKey
3785
- }
3786
- }, this.isPortal() && {
3787
- params: portalCallbackParams,
3788
- // Build callback for legacy portal if needed
3789
- useLegacyUrl: typeof window !== "undefined" ? window.location.host.includes("usecapsule") : false
3790
- })))
3791
- })
3834
+ } : {}), callback && { callback })
3792
3835
  });
3793
3836
  });
3794
3837
  };
@@ -4060,6 +4103,7 @@ prepareDoneState_fn = function(doneState) {
4060
4103
  return __async(this, null, function* () {
4061
4104
  let isSLOPossible = doneState.authMethods.includes(import_user_management_client.AuthMethod.BASIC_LOGIN);
4062
4105
  this.isEnclaveUser = isSLOPossible;
4106
+ yield this.localStorageSetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER, JSON.stringify(isSLOPossible));
4063
4107
  return doneState;
4064
4108
  });
4065
4109
  };
@@ -4077,6 +4121,7 @@ prepareVerificationState_fn = function(_0, _1) {
4077
4121
  isSLOPossible = verifyState.signupAuthMethods.includes(import_user_management_client.AuthMethod.BASIC_LOGIN);
4078
4122
  }
4079
4123
  this.isEnclaveUser = isSLOPossible;
4124
+ yield this.localStorageSetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER, JSON.stringify(isSLOPossible));
4080
4125
  const isExternalWalletFullAuth = (_a = verifyState.externalWallet) == null ? void 0 : _a.withFullParaAuth;
4081
4126
  return __spreadValues(__spreadValues({}, verifyState), isSLOPossible || isExternalWalletFullAuth ? {
4082
4127
  loginUrl: yield this.getLoginUrl({
@@ -29,6 +29,7 @@ __export(constants_exports, {
29
29
  LOCAL_STORAGE_EXTERNAL_WALLETS: () => LOCAL_STORAGE_EXTERNAL_WALLETS,
30
30
  LOCAL_STORAGE_EXTERNAL_WALLET_USER_ID: () => LOCAL_STORAGE_EXTERNAL_WALLET_USER_ID,
31
31
  LOCAL_STORAGE_FARCASTER_USERNAME: () => LOCAL_STORAGE_FARCASTER_USERNAME,
32
+ LOCAL_STORAGE_IS_ENCLAVE_USER: () => LOCAL_STORAGE_IS_ENCLAVE_USER,
32
33
  LOCAL_STORAGE_PHONE: () => LOCAL_STORAGE_PHONE,
33
34
  LOCAL_STORAGE_SESSION_COOKIE: () => LOCAL_STORAGE_SESSION_COOKIE,
34
35
  LOCAL_STORAGE_TELEGRAM_USER_ID: () => LOCAL_STORAGE_TELEGRAM_USER_ID,
@@ -43,7 +44,7 @@ __export(constants_exports, {
43
44
  SHORT_POLLING_INTERVAL_MS: () => SHORT_POLLING_INTERVAL_MS
44
45
  });
45
46
  module.exports = __toCommonJS(constants_exports);
46
- const PARA_CORE_VERSION = "2.8.0";
47
+ const PARA_CORE_VERSION = "2.10.0";
47
48
  const PREFIX = "@CAPSULE/";
48
49
  const PARA_PREFIX = "@PARA/";
49
50
  const LOCAL_STORAGE_AUTH_INFO = `${PREFIX}authInfo`;
@@ -61,6 +62,7 @@ const LOCAL_STORAGE_CURRENT_WALLET_IDS = `${PREFIX}currentWalletIds`;
61
62
  const LOCAL_STORAGE_SESSION_COOKIE = `${PREFIX}sessionCookie`;
62
63
  const LOCAL_STORAGE_ENCLAVE_JWT = `${PREFIX}enclaveJwt`;
63
64
  const LOCAL_STORAGE_ENCLAVE_REFRESH_JWT = `${PREFIX}enclaveRefreshJwt`;
65
+ const LOCAL_STORAGE_IS_ENCLAVE_USER = `${PREFIX}isEnclaveUser`;
64
66
  const SESSION_STORAGE_LOGIN_ENCRYPTION_KEY_PAIR = `${PREFIX}loginEncryptionKeyPair`;
65
67
  const POLLING_INTERVAL_MS = 1e3;
66
68
  const SHORT_POLLING_INTERVAL_MS = 750;
@@ -81,6 +83,7 @@ const ACCOUNT_LINK_CONFLICT = "Account already linked";
81
83
  LOCAL_STORAGE_EXTERNAL_WALLETS,
82
84
  LOCAL_STORAGE_EXTERNAL_WALLET_USER_ID,
83
85
  LOCAL_STORAGE_FARCASTER_USERNAME,
86
+ LOCAL_STORAGE_IS_ENCLAVE_USER,
84
87
  LOCAL_STORAGE_PHONE,
85
88
  LOCAL_STORAGE_SESSION_COOKIE,
86
89
  LOCAL_STORAGE_TELEGRAM_USER_ID,
@@ -268,6 +268,38 @@ ${exportedAsBase64}
268
268
  }));
269
269
  });
270
270
  }
271
+ /**
272
+ * Retrieve pregen wallet shares from the enclave
273
+ * Used during login to claim REST API pregen wallets
274
+ * Client sends walletIds in encrypted payload; backend independently queries matching wallets for cross-validation
275
+ */
276
+ getPregenShares(query) {
277
+ return __async(this, null, function* () {
278
+ try {
279
+ const frontendKeyPair = yield this.generateFrontendKeyPair();
280
+ const responsePublicKeyPEM = yield this.exportPublicKeyToPEM(frontendKeyPair.publicKey);
281
+ const payload = {
282
+ userId: query.userId,
283
+ walletIds: query.walletIds,
284
+ partnerId: query.partnerId,
285
+ responsePublicKey: responsePublicKeyPEM
286
+ };
287
+ const encryptedPayload = yield this.encryptForEnclave(JSON.stringify(payload));
288
+ const encryptedPayloadStr = JSON.stringify(encryptedPayload);
289
+ const response = yield this.userManagementClient.getPregenShares(encryptedPayloadStr);
290
+ if (!response.payload) {
291
+ return [];
292
+ }
293
+ const encryptedResponse = JSON.parse(response.payload);
294
+ const decryptedData = yield this.decryptForFrontend(encryptedResponse);
295
+ return decryptedData.shares;
296
+ } catch (error) {
297
+ throw new Error(
298
+ `Failed to retrieve pregen shares for user ${query.userId}: ${error instanceof Error ? error.message : "Unknown error"}`
299
+ );
300
+ }
301
+ });
302
+ }
271
303
  persistSharesWithRetry(shares) {
272
304
  return __async(this, null, function* () {
273
305
  return yield this.persistShares(shares);
@@ -82,7 +82,10 @@ function validateCustomAsset(obj) {
82
82
  return false;
83
83
  }
84
84
  } else if (typeof network.network === "object") {
85
- if (typeof network.network.name !== "string" || !network.network.name.trim() || typeof network.network.rpcUrl !== "string" || !network.network.rpcUrl.trim() || typeof network.network.evmChainId !== "string" || !network.network.evmChainId.trim()) {
85
+ const hasLegacyRpcUrl = typeof network.network.rpcUrl === "string" && network.network.rpcUrl.trim().length > 0;
86
+ const hasNewRpcFormat = network.network.rpc && typeof network.network.rpc === "object" && Array.isArray(network.network.rpc.httpUrls) && network.network.rpc.httpUrls.length > 0 && typeof network.network.rpc.httpUrls[0] === "string" && network.network.rpc.httpUrls[0].trim().length > 0;
87
+ if (typeof network.network.name !== "string" || !network.network.name.trim() || !hasLegacyRpcUrl && !hasNewRpcFormat || // Must have either rpcUrl or rpc.httpUrls
88
+ typeof network.network.evmChainId !== "string" || !network.network.evmChainId.trim()) {
86
89
  return false;
87
90
  }
88
91
  if (network.contractAddress !== void 0 && (typeof network.contractAddress !== "string" || !network.contractAddress.trim())) {
@@ -120,7 +120,7 @@ function shortenUrl(ctx, url, isLegacy) {
120
120
  return __async(this, null, function* () {
121
121
  const compressedUrl = yield (0, import_transmissionUtils.upload)(url, ctx.client);
122
122
  return constructUrl({
123
- base: getPortalBaseURL(ctx, false, false, isLegacy),
123
+ base: ctx.portalUrlOverride || getPortalBaseURL(ctx, false, false, isLegacy),
124
124
  path: `/short/${compressedUrl}`
125
125
  });
126
126
  });
@@ -25,7 +25,7 @@ function isPortal(ctx, env) {
25
25
  var _a, _b;
26
26
  if (typeof window === "undefined") return false;
27
27
  const normalizedUrl = (_b = (_a = window.location) == null ? void 0 : _a.host) == null ? void 0 : _b.replace("usecapsule", "getpara");
28
- const isOnPortalDomain = (0, import_url.getPortalBaseURL)(env ? { env } : ctx).includes(normalizedUrl);
28
+ const isOnPortalDomain = (0, import_url.getPortalBaseURL)(env ? { env } : ctx).includes(normalizedUrl) || ((ctx == null ? void 0 : ctx.portalUrlOverride) ? ctx.portalUrlOverride.includes(normalizedUrl) : false);
29
29
  if (!isOnPortalDomain) return false;
30
30
  const isInIframe = window.parent !== window && !window.opener;
31
31
  const isInPopup = window.opener && window.parent === window;
@@ -172,7 +172,7 @@ const _ParaCore = class _ParaCore {
172
172
  }
173
173
  });
174
174
  } catch (e) {
175
- console.error("error tracking error:", e);
175
+ this.devLog("error tracking error:", e);
176
176
  }
177
177
  throw err;
178
178
  });
@@ -200,6 +200,7 @@ const _ParaCore = class _ParaCore {
200
200
  this.updateSessionCookieFromStorage();
201
201
  this.updateLoginEncryptionKeyPairFromStorage();
202
202
  this.updateEnclaveJwtFromStorage();
203
+ this.updateIsEnclaveUserFromStorage();
203
204
  };
204
205
  this.updateAuthInfoFromStorage = () => {
205
206
  var _a;
@@ -223,6 +224,12 @@ const _ParaCore = class _ParaCore {
223
224
  this.enclaveJwt = this.localStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_JWT) || this.sessionStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_JWT) || void 0;
224
225
  this.enclaveRefreshJwt = this.localStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_REFRESH_JWT) || this.sessionStorageGetItem(constants.LOCAL_STORAGE_ENCLAVE_REFRESH_JWT) || void 0;
225
226
  };
227
+ this.updateIsEnclaveUserFromStorage = () => {
228
+ const stored = this.localStorageGetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER);
229
+ if (stored != null) {
230
+ this.isEnclaveUser = JSON.parse(stored);
231
+ }
232
+ };
226
233
  this.updateUserIdFromStorage = () => {
227
234
  this.userId = this.localStorageGetItem(constants.LOCAL_STORAGE_USER_ID) || void 0;
228
235
  };
@@ -750,7 +757,8 @@ const _ParaCore = class _ParaCore {
750
757
  isFarcasterLogin,
751
758
  isAddNewCredential,
752
759
  isSwitchWallets,
753
- isExportPrivateKey
760
+ isExportPrivateKey,
761
+ isTxReview
754
762
  ] = [
755
763
  ["createAuth", "createPassword", "createPIN"].includes(type),
756
764
  ["loginAuth", "loginPassword", "loginPIN", "loginOTP", "switchWallets", "loginExternalWallet"].includes(type),
@@ -761,7 +769,8 @@ const _ParaCore = class _ParaCore {
761
769
  type === "loginFarcaster",
762
770
  type === "addNewCredential",
763
771
  type === "switchWallets",
764
- type === "exportPrivateKey"
772
+ type === "exportPrivateKey",
773
+ type === "txReview"
765
774
  ];
766
775
  if (isOAuth && !opts.oAuthMethod) {
767
776
  throw new Error("oAuthMethod is required for oAuth portal URLs");
@@ -770,7 +779,7 @@ const _ParaCore = class _ParaCore {
770
779
  this.assertIsAuthSet();
771
780
  }
772
781
  let sessionId = opts.sessionId;
773
- if ((isLogin || isOnRamp || isTelegramLogin || isFarcasterLogin || isExportPrivateKey) && !sessionId) {
782
+ if ((isLogin || isOnRamp || isTelegramLogin || isFarcasterLogin || isExportPrivateKey || isTxReview) && !sessionId) {
774
783
  const session = yield this.touchSession(true);
775
784
  sessionId = session.sessionId;
776
785
  }
@@ -778,7 +787,7 @@ const _ParaCore = class _ParaCore {
778
787
  yield this.setLoginEncryptionKeyPair();
779
788
  }
780
789
  const shouldUseLegacyPortalUrl = opts.useLegacyUrl || !!opts.addNewCredentialPasskeyId || type === "loginAuth";
781
- const base = type === "onRamp" || isTelegramLogin ? getPortalBaseURL(this.ctx, isTelegramLogin, false, shouldUseLegacyPortalUrl) : yield this.getPortalURL(shouldUseLegacyPortalUrl);
790
+ const base = type === "onRamp" || isTelegramLogin ? this.ctx.portalUrlOverride || getPortalBaseURL(this.ctx, isTelegramLogin, false, shouldUseLegacyPortalUrl) : yield this.getPortalURL(shouldUseLegacyPortalUrl);
782
791
  let path;
783
792
  switch (type) {
784
793
  case "createPassword": {
@@ -912,7 +921,7 @@ const _ParaCore = class _ParaCore {
912
921
  }) : {}), isLogin && {
913
922
  // Prior versions won't have this param which will skip the upgrade prompt
914
923
  isBasicLoginUpgradeVersion: "true"
915
- }), isExportPrivateKey ? {
924
+ }), isExportPrivateKey || isTxReview ? {
916
925
  sessionId: thisDevice.sessionId
917
926
  } : {});
918
927
  const url = constructUrl({ base, path, params });
@@ -1075,6 +1084,10 @@ Need help? Visit: https://docs.getpara.com or contact support
1075
1084
  if (loginEncryptionKey && loginEncryptionKey !== "undefined") {
1076
1085
  this.loginEncryptionKeyPair = this.convertEncryptionKeyPair(JSON.parse(loginEncryptionKey));
1077
1086
  }
1087
+ const storedIsEnclaveUser = yield this.localStorageGetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER);
1088
+ if (storedIsEnclaveUser != null) {
1089
+ this.isEnclaveUser = JSON.parse(storedIsEnclaveUser);
1090
+ }
1078
1091
  setupListeners.bind(this)();
1079
1092
  yield this.touchSession();
1080
1093
  });
@@ -1106,7 +1119,9 @@ Need help? Visit: https://docs.getpara.com or contact support
1106
1119
  const errorStr = String(error);
1107
1120
  const errorMessage = error instanceof Error ? error.message : "";
1108
1121
  if (errorStr.includes("blocked by CORS policy") && errorStr.includes("Access-Control-Allow-Origin")) {
1109
- this.displayModalError("Request rate limit reached. Please wait a couple of minutes and try again.");
1122
+ const message = "Request rate limit reached. Please wait a couple of minutes and try again.";
1123
+ console.error(`[Para] ${message}`);
1124
+ this.displayModalError(message);
1110
1125
  return;
1111
1126
  }
1112
1127
  if (error.status === 403 && errorMessage.includes("origin not authorized")) {
@@ -1534,7 +1549,7 @@ Need help? Visit: https://docs.getpara.com or contact support
1534
1549
  */
1535
1550
  getPortalURL(isLegacy) {
1536
1551
  return __async(this, null, function* () {
1537
- return (yield this.getPartnerURL()) || getPortalBaseURL(this.ctx, false, false, isLegacy);
1552
+ return this.ctx.portalUrlOverride || (yield this.getPartnerURL()) || getPortalBaseURL(this.ctx, false, false, isLegacy);
1538
1553
  });
1539
1554
  }
1540
1555
  /**
@@ -2014,13 +2029,42 @@ Need help? Visit: https://docs.getpara.com or contact support
2014
2029
  const pregenWallets = yield this.getPregenWallets();
2015
2030
  let recoverySecret, walletIds = {};
2016
2031
  if (pregenWallets.length > 0) {
2017
- recoverySecret = yield this.claimPregenWallets();
2018
- walletIds = supportedWalletTypes.reduce((acc, { type }) => {
2019
- var _a;
2020
- return __spreadProps(__spreadValues({}, acc), {
2021
- [type]: [(_a = pregenWallets.find((w) => !!WalletSchemeTypeMap[w.scheme][type])) == null ? void 0 : _a.id]
2032
+ let shares = [];
2033
+ try {
2034
+ shares = yield this.ctx.enclaveClient.getPregenShares({
2035
+ userId: this.userId,
2036
+ walletIds: pregenWallets.map((w) => w.id),
2037
+ partnerId: pregenWallets[0].partnerId
2022
2038
  });
2023
- }, {});
2039
+ for (const share of shares) {
2040
+ const wallet = pregenWallets.find((w) => w.id === share.walletId);
2041
+ if (wallet) {
2042
+ this.wallets[wallet.id] = {
2043
+ id: wallet.id,
2044
+ address: wallet.address,
2045
+ scheme: wallet.scheme,
2046
+ type: wallet.type,
2047
+ partnerId: wallet.partnerId,
2048
+ isPregen: wallet.isPregen,
2049
+ pregenIdentifier: wallet.pregenIdentifier,
2050
+ pregenIdentifierType: wallet.pregenIdentifierType,
2051
+ signer: share.signer,
2052
+ createdAt: String(wallet.createdAt)
2053
+ };
2054
+ }
2055
+ }
2056
+ } catch (err) {
2057
+ console.warn("[waitForWalletCreation] Failed to fetch pregen shares:", err);
2058
+ }
2059
+ if (shares.length > 0) {
2060
+ recoverySecret = yield this.claimPregenWallets();
2061
+ walletIds = supportedWalletTypes.reduce((acc, { type }) => {
2062
+ var _a;
2063
+ return __spreadProps(__spreadValues({}, acc), {
2064
+ [type]: [(_a = pregenWallets.find((w) => !!WalletSchemeTypeMap[w.scheme][type])) == null ? void 0 : _a.id]
2065
+ });
2066
+ }, {});
2067
+ }
2024
2068
  }
2025
2069
  const created = yield this.createWalletPerType();
2026
2070
  recoverySecret = recoverySecret != null ? recoverySecret : created.recoverySecret;
@@ -3199,6 +3243,7 @@ Need help? Visit: https://docs.getpara.com or contact support
3199
3243
  this.accountLinkInProgress = void 0;
3200
3244
  this.userId = void 0;
3201
3245
  this.sessionCookie = void 0;
3246
+ this.isEnclaveUser = false;
3202
3247
  if (shouldDispatchLogoutEvent) {
3203
3248
  dispatchEvent(ParaEvent.LOGOUT_EVENT, null);
3204
3249
  }
@@ -3725,14 +3770,26 @@ getOAuthUrl_fn = function(_0) {
3725
3770
  if (!accountLinkInProgress && !this.isPortal()) {
3726
3771
  return yield this.constructPortalUrl("oAuth", { sessionId: sessionLookupId, oAuthMethod: method, appScheme });
3727
3772
  }
3728
- let portalSessionLookupId;
3729
- if (this.isPortal()) {
3730
- portalSessionLookupId = (yield this.touchSession(true)).sessionLookupId;
3731
- }
3773
+ const [portalSessionLookupId, callback] = yield Promise.all([
3774
+ this.isPortal() ? this.touchSession(true).then((s) => s.sessionLookupId) : Promise.resolve(void 0),
3775
+ !accountLinkInProgress ? this.constructPortalUrl("oAuthCallback", __spreadValues({
3776
+ sessionId: sessionLookupId,
3777
+ oAuthMethod: method,
3778
+ appScheme,
3779
+ thisDevice: {
3780
+ sessionId: sessionLookupId,
3781
+ encryptionKey
3782
+ }
3783
+ }, this.isPortal() && {
3784
+ params: portalCallbackParams,
3785
+ // Build callback for legacy portal if needed
3786
+ useLegacyUrl: typeof window !== "undefined" ? window.location.host.includes("usecapsule") : false
3787
+ })) : Promise.resolve(false)
3788
+ ]);
3732
3789
  return constructUrl({
3733
3790
  base: getBaseOAuthUrl(this.ctx.env),
3734
3791
  path: `/auth/${method.toLowerCase()}`,
3735
- params: __spreadProps(__spreadValues({
3792
+ params: __spreadValues(__spreadValues({
3736
3793
  apiKey: this.ctx.apiKey,
3737
3794
  origin: typeof window !== "undefined" ? window.location.origin : void 0,
3738
3795
  sessionLookupId,
@@ -3740,21 +3797,7 @@ getOAuthUrl_fn = function(_0) {
3740
3797
  appScheme
3741
3798
  }, accountLinkInProgress ? {
3742
3799
  linkedAccountId: this.accountLinkInProgress.id
3743
- } : {}), {
3744
- callback: !accountLinkInProgress && (yield this.constructPortalUrl("oAuthCallback", __spreadValues({
3745
- sessionId: sessionLookupId,
3746
- oAuthMethod: method,
3747
- appScheme,
3748
- thisDevice: {
3749
- sessionId: sessionLookupId,
3750
- encryptionKey
3751
- }
3752
- }, this.isPortal() && {
3753
- params: portalCallbackParams,
3754
- // Build callback for legacy portal if needed
3755
- useLegacyUrl: typeof window !== "undefined" ? window.location.host.includes("usecapsule") : false
3756
- })))
3757
- })
3800
+ } : {}), callback && { callback })
3758
3801
  });
3759
3802
  });
3760
3803
  };
@@ -4026,6 +4069,7 @@ prepareDoneState_fn = function(doneState) {
4026
4069
  return __async(this, null, function* () {
4027
4070
  let isSLOPossible = doneState.authMethods.includes(AuthMethod.BASIC_LOGIN);
4028
4071
  this.isEnclaveUser = isSLOPossible;
4072
+ yield this.localStorageSetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER, JSON.stringify(isSLOPossible));
4029
4073
  return doneState;
4030
4074
  });
4031
4075
  };
@@ -4043,6 +4087,7 @@ prepareVerificationState_fn = function(_0, _1) {
4043
4087
  isSLOPossible = verifyState.signupAuthMethods.includes(AuthMethod.BASIC_LOGIN);
4044
4088
  }
4045
4089
  this.isEnclaveUser = isSLOPossible;
4090
+ yield this.localStorageSetItem(constants.LOCAL_STORAGE_IS_ENCLAVE_USER, JSON.stringify(isSLOPossible));
4046
4091
  const isExternalWalletFullAuth = (_a = verifyState.externalWallet) == null ? void 0 : _a.withFullParaAuth;
4047
4092
  return __spreadValues(__spreadValues({}, verifyState), isSLOPossible || isExternalWalletFullAuth ? {
4048
4093
  loginUrl: yield this.getLoginUrl({
@@ -1,5 +1,5 @@
1
1
  import "./chunk-7B52C2XE.js";
2
- const PARA_CORE_VERSION = "2.8.0";
2
+ const PARA_CORE_VERSION = "2.10.0";
3
3
  const PREFIX = "@CAPSULE/";
4
4
  const PARA_PREFIX = "@PARA/";
5
5
  const LOCAL_STORAGE_AUTH_INFO = `${PREFIX}authInfo`;
@@ -17,6 +17,7 @@ const LOCAL_STORAGE_CURRENT_WALLET_IDS = `${PREFIX}currentWalletIds`;
17
17
  const LOCAL_STORAGE_SESSION_COOKIE = `${PREFIX}sessionCookie`;
18
18
  const LOCAL_STORAGE_ENCLAVE_JWT = `${PREFIX}enclaveJwt`;
19
19
  const LOCAL_STORAGE_ENCLAVE_REFRESH_JWT = `${PREFIX}enclaveRefreshJwt`;
20
+ const LOCAL_STORAGE_IS_ENCLAVE_USER = `${PREFIX}isEnclaveUser`;
20
21
  const SESSION_STORAGE_LOGIN_ENCRYPTION_KEY_PAIR = `${PREFIX}loginEncryptionKeyPair`;
21
22
  const POLLING_INTERVAL_MS = 1e3;
22
23
  const SHORT_POLLING_INTERVAL_MS = 750;
@@ -36,6 +37,7 @@ export {
36
37
  LOCAL_STORAGE_EXTERNAL_WALLETS,
37
38
  LOCAL_STORAGE_EXTERNAL_WALLET_USER_ID,
38
39
  LOCAL_STORAGE_FARCASTER_USERNAME,
40
+ LOCAL_STORAGE_IS_ENCLAVE_USER,
39
41
  LOCAL_STORAGE_PHONE,
40
42
  LOCAL_STORAGE_SESSION_COOKIE,
41
43
  LOCAL_STORAGE_TELEGRAM_USER_ID,
@@ -229,6 +229,38 @@ ${exportedAsBase64}
229
229
  }));
230
230
  });
231
231
  }
232
+ /**
233
+ * Retrieve pregen wallet shares from the enclave
234
+ * Used during login to claim REST API pregen wallets
235
+ * Client sends walletIds in encrypted payload; backend independently queries matching wallets for cross-validation
236
+ */
237
+ getPregenShares(query) {
238
+ return __async(this, null, function* () {
239
+ try {
240
+ const frontendKeyPair = yield this.generateFrontendKeyPair();
241
+ const responsePublicKeyPEM = yield this.exportPublicKeyToPEM(frontendKeyPair.publicKey);
242
+ const payload = {
243
+ userId: query.userId,
244
+ walletIds: query.walletIds,
245
+ partnerId: query.partnerId,
246
+ responsePublicKey: responsePublicKeyPEM
247
+ };
248
+ const encryptedPayload = yield this.encryptForEnclave(JSON.stringify(payload));
249
+ const encryptedPayloadStr = JSON.stringify(encryptedPayload);
250
+ const response = yield this.userManagementClient.getPregenShares(encryptedPayloadStr);
251
+ if (!response.payload) {
252
+ return [];
253
+ }
254
+ const encryptedResponse = JSON.parse(response.payload);
255
+ const decryptedData = yield this.decryptForFrontend(encryptedResponse);
256
+ return decryptedData.shares;
257
+ } catch (error) {
258
+ throw new Error(
259
+ `Failed to retrieve pregen shares for user ${query.userId}: ${error instanceof Error ? error.message : "Unknown error"}`
260
+ );
261
+ }
262
+ });
263
+ }
232
264
  persistSharesWithRetry(shares) {
233
265
  return __async(this, null, function* () {
234
266
  return yield this.persistShares(shares);
@@ -61,7 +61,10 @@ function validateCustomAsset(obj) {
61
61
  return false;
62
62
  }
63
63
  } else if (typeof network.network === "object") {
64
- if (typeof network.network.name !== "string" || !network.network.name.trim() || typeof network.network.rpcUrl !== "string" || !network.network.rpcUrl.trim() || typeof network.network.evmChainId !== "string" || !network.network.evmChainId.trim()) {
64
+ const hasLegacyRpcUrl = typeof network.network.rpcUrl === "string" && network.network.rpcUrl.trim().length > 0;
65
+ const hasNewRpcFormat = network.network.rpc && typeof network.network.rpc === "object" && Array.isArray(network.network.rpc.httpUrls) && network.network.rpc.httpUrls.length > 0 && typeof network.network.rpc.httpUrls[0] === "string" && network.network.rpc.httpUrls[0].trim().length > 0;
66
+ if (typeof network.network.name !== "string" || !network.network.name.trim() || !hasLegacyRpcUrl && !hasNewRpcFormat || // Must have either rpcUrl or rpc.httpUrls
67
+ typeof network.network.evmChainId !== "string" || !network.network.evmChainId.trim()) {
65
68
  return false;
66
69
  }
67
70
  if (network.contractAddress !== void 0 && (typeof network.contractAddress !== "string" || !network.contractAddress.trim())) {
@@ -76,7 +76,7 @@ function shortenUrl(ctx, url, isLegacy) {
76
76
  return __async(this, null, function* () {
77
77
  const compressedUrl = yield upload(url, ctx.client);
78
78
  return constructUrl({
79
- base: getPortalBaseURL(ctx, false, false, isLegacy),
79
+ base: ctx.portalUrlOverride || getPortalBaseURL(ctx, false, false, isLegacy),
80
80
  path: `/short/${compressedUrl}`
81
81
  });
82
82
  });
@@ -4,7 +4,7 @@ function isPortal(ctx, env) {
4
4
  var _a, _b;
5
5
  if (typeof window === "undefined") return false;
6
6
  const normalizedUrl = (_b = (_a = window.location) == null ? void 0 : _a.host) == null ? void 0 : _b.replace("usecapsule", "getpara");
7
- const isOnPortalDomain = getPortalBaseURL(env ? { env } : ctx).includes(normalizedUrl);
7
+ const isOnPortalDomain = getPortalBaseURL(env ? { env } : ctx).includes(normalizedUrl) || ((ctx == null ? void 0 : ctx.portalUrlOverride) ? ctx.portalUrlOverride.includes(normalizedUrl) : false);
8
8
  if (!isOnPortalDomain) return false;
9
9
  const isInIframe = window.parent !== window && !window.opener;
10
10
  const isInPopup = window.opener && window.parent === window;
@@ -214,6 +214,7 @@ export declare abstract class ParaCore implements CoreInterface {
214
214
  private initializeFromStorage;
215
215
  private updateAuthInfoFromStorage;
216
216
  private updateEnclaveJwtFromStorage;
217
+ private updateIsEnclaveUserFromStorage;
217
218
  private updateUserIdFromStorage;
218
219
  private updateWalletsFromStorage;
219
220
  private updateWalletIdsFromStorage;
@@ -16,6 +16,7 @@ export declare const LOCAL_STORAGE_CURRENT_WALLET_IDS = "@CAPSULE/currentWalletI
16
16
  export declare const LOCAL_STORAGE_SESSION_COOKIE = "@CAPSULE/sessionCookie";
17
17
  export declare const LOCAL_STORAGE_ENCLAVE_JWT = "@CAPSULE/enclaveJwt";
18
18
  export declare const LOCAL_STORAGE_ENCLAVE_REFRESH_JWT = "@CAPSULE/enclaveRefreshJwt";
19
+ export declare const LOCAL_STORAGE_IS_ENCLAVE_USER = "@CAPSULE/isEnclaveUser";
19
20
  export declare const SESSION_STORAGE_LOGIN_ENCRYPTION_KEY_PAIR = "@CAPSULE/loginEncryptionKeyPair";
20
21
  export declare const POLLING_INTERVAL_MS = 1000;
21
22
  export declare const SHORT_POLLING_INTERVAL_MS = 750;
@@ -78,6 +78,16 @@ export declare class EnclaveClient {
78
78
  private retrieveShares;
79
79
  deleteShares(): Promise<void>;
80
80
  retrieveSharesWithRetry(query: ShareQuery[]): Promise<ShareData[]>;
81
+ /**
82
+ * Retrieve pregen wallet shares from the enclave
83
+ * Used during login to claim REST API pregen wallets
84
+ * Client sends walletIds in encrypted payload; backend independently queries matching wallets for cross-validation
85
+ */
86
+ getPregenShares(query: {
87
+ userId: string;
88
+ walletIds: string[];
89
+ partnerId: string;
90
+ }): Promise<ShareData[]>;
81
91
  persistSharesWithRetry(shares: ShareData[]): Promise<any>;
82
92
  deleteSharesWithRetry(): Promise<void>;
83
93
  }
@@ -23,6 +23,8 @@ export interface Ctx {
23
23
  wasmOverride?: ArrayBuffer;
24
24
  cosmosPrefix?: string;
25
25
  isE2E?: boolean;
26
+ portalUrlOverride?: string;
27
+ passkeyRpIdOverride?: string;
26
28
  }
27
29
  export type deprecated__NetworkProp = keyof typeof Network | Network;
28
30
  export type deprecated__OnRampProviderProp = keyof typeof OnRampProvider | OnRampProvider;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@getpara/core-sdk",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "dependencies": {
5
5
  "@celo/utils": "^8.0.2",
6
6
  "@cosmjs/encoding": "^0.32.4",
7
7
  "@ethereumjs/util": "^9.1.0",
8
- "@getpara/user-management-client": "2.8.0",
8
+ "@getpara/user-management-client": "2.10.0",
9
9
  "@noble/hashes": "^1.5.0",
10
10
  "base64url": "^3.0.1",
11
11
  "libphonenumber-js": "^1.11.7",
@@ -27,7 +27,7 @@
27
27
  "dist",
28
28
  "package.json"
29
29
  ],
30
- "gitHead": "44d3bdc9a075861613210bd0817a03ab67deed4e",
30
+ "gitHead": "8da2c51cc91f021acbc2ec7373b9ca0638fc840a",
31
31
  "main": "dist/cjs/index.js",
32
32
  "module": "dist/esm/index.js",
33
33
  "scripts": {