@imtbl/sdk 0.27.9 → 0.27.10

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/passport.js CHANGED
@@ -2072,7 +2072,7 @@ class MultiRollupApiClients {
2072
2072
  }
2073
2073
 
2074
2074
  // eslint-disable-next-line @typescript-eslint/naming-convention
2075
- const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-0.27.9' };
2075
+ const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-0.27.10' };
2076
2076
  const createConfig = ({ basePath, headers, }) => {
2077
2077
  if (!basePath.trim()) {
2078
2078
  throw Error('basePath can not be empty');
@@ -2128,7 +2128,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
2128
2128
  chainID,
2129
2129
  coreContractAddress,
2130
2130
  registrationContractAddress,
2131
- sdkVersion: 'ts-immutable-sdk-0.27.9',
2131
+ sdkVersion: 'ts-immutable-sdk-0.27.10',
2132
2132
  });
2133
2133
  /**
2134
2134
  * Sets `sdkVersion` at the time of build
@@ -6591,6 +6591,7 @@ var PassportErrorType;
6591
6591
  PassportErrorType["SILENT_LOGIN_ERROR"] = "SILENT_LOGIN_ERROR";
6592
6592
  PassportErrorType["REFRESH_TOKEN_ERROR"] = "REFRESH_TOKEN_ERROR";
6593
6593
  PassportErrorType["USER_REGISTRATION_ERROR"] = "USER_REGISTRATION_ERROR";
6594
+ PassportErrorType["USER_NOT_REGISTERED_ERROR"] = "USER_NOT_REGISTERED_ERROR";
6594
6595
  PassportErrorType["LOGOUT_ERROR"] = "LOGOUT_ERROR";
6595
6596
  PassportErrorType["TRANSFER_ERROR"] = "TRANSFER_ERROR";
6596
6597
  PassportErrorType["CREATE_ORDER_ERROR"] = "CREATE_ORDER_ERROR";
@@ -6740,6 +6741,10 @@ class AuthManager {
6740
6741
  config;
6741
6742
  deviceCredentialsManager;
6742
6743
  logoutMode;
6744
+ /**
6745
+ * Promise that is used to prevent multiple concurrent calls to the refresh token endpoint.
6746
+ */
6747
+ refreshingPromise = null;
6743
6748
  constructor(config) {
6744
6749
  this.config = config;
6745
6750
  this.userManager = new UserManager(getAuthConfiguration(config));
@@ -6984,32 +6989,52 @@ class AuthManager {
6984
6989
  * @param forceRefresh If set to true, force an HTTP call to the OIDC server's authorization endpoint. This call will
6985
6990
  * throw an error if there's no refresh token.
6986
6991
  */
6987
- async getWebUser({ forceRefresh = false }) {
6992
+ async getAuthenticatedUser({ forceRefresh = false }) {
6988
6993
  if (forceRefresh) {
6989
- const newOidcUser = await this.userManager.signinSilent();
6990
- return newOidcUser ? AuthManager.mapOidcUserToDomainModel(newOidcUser) : null;
6994
+ return this.refreshTokenAndUpdatePromise();
6991
6995
  }
6992
6996
  const oidcUser = await this.userManager.getUser();
6993
6997
  if (!oidcUser)
6994
6998
  return null;
6995
- const tokenExpired = isTokenExpired(oidcUser);
6996
- if (!tokenExpired) {
6999
+ if (!isTokenExpired(oidcUser)) {
6997
7000
  return AuthManager.mapOidcUserToDomainModel(oidcUser);
6998
7001
  }
6999
7002
  if (oidcUser.refresh_token) {
7000
- const newOidcUser = await this.userManager.signinSilent();
7001
- if (newOidcUser) {
7002
- return AuthManager.mapOidcUserToDomainModel(newOidcUser);
7003
- }
7003
+ return this.refreshTokenAndUpdatePromise();
7004
7004
  }
7005
7005
  return null;
7006
7006
  }
7007
+ /**
7008
+ * Refreshes the token and returns the user.
7009
+ * If the token is already being refreshed, returns the existing promise.
7010
+ */
7011
+ async refreshTokenAndUpdatePromise() {
7012
+ if (this.refreshingPromise)
7013
+ return this.refreshingPromise;
7014
+ // eslint-disable-next-line no-async-promise-executor
7015
+ this.refreshingPromise = new Promise(async (resolve, reject) => {
7016
+ try {
7017
+ const newOidcUser = await this.userManager.signinSilent();
7018
+ if (newOidcUser) {
7019
+ resolve(AuthManager.mapOidcUserToDomainModel(newOidcUser));
7020
+ return;
7021
+ }
7022
+ resolve(null);
7023
+ }
7024
+ catch (err) {
7025
+ reject(err);
7026
+ }
7027
+ finally {
7028
+ this.refreshingPromise = null; // Reset the promise after completion
7029
+ }
7030
+ });
7031
+ return this.refreshingPromise;
7032
+ }
7007
7033
  async getUser({ forceRefresh } = { forceRefresh: false }) {
7008
7034
  return withPassportError(async () => {
7009
- const user = await this.getWebUser({ forceRefresh });
7010
- if (user) {
7035
+ const user = await this.getAuthenticatedUser({ forceRefresh });
7036
+ if (user)
7011
7037
  return user;
7012
- }
7013
7038
  const deviceToken = this.deviceCredentialsManager.getCredentials();
7014
7039
  if (deviceToken) {
7015
7040
  return AuthManager.mapDeviceTokenResponseToDomainUserModel(deviceToken);
@@ -7036,14 +7061,16 @@ class MagicAdapter {
7036
7061
  magicClient;
7037
7062
  constructor(config) {
7038
7063
  this.config = config;
7039
- this.magicClient = new Magic(this.config.magicPublishableApiKey, {
7040
- extensions: [new OpenIdExtension()],
7041
- network: config.network,
7042
- });
7043
- this.magicClient.preload();
7064
+ if (window) {
7065
+ this.magicClient = this.initMagicClient();
7066
+ this.magicClient.preload();
7067
+ }
7044
7068
  }
7045
7069
  async login(idToken) {
7046
7070
  return withPassportError(async () => {
7071
+ if (!this.magicClient) {
7072
+ this.magicClient = this.initMagicClient();
7073
+ }
7047
7074
  await this.magicClient.openid.loginWithOIDC({
7048
7075
  jwt: idToken,
7049
7076
  providerId: this.config.magicProviderId,
@@ -7052,10 +7079,16 @@ class MagicAdapter {
7052
7079
  }, PassportErrorType.WALLET_CONNECTION_ERROR);
7053
7080
  }
7054
7081
  async logout() {
7055
- if (this.magicClient.user) {
7082
+ if (this.magicClient?.user) {
7056
7083
  await this.magicClient.user.logout();
7057
7084
  }
7058
7085
  }
7086
+ initMagicClient() {
7087
+ return new Magic(this.config.magicPublishableApiKey, {
7088
+ extensions: [new OpenIdExtension()],
7089
+ network: this.config.network,
7090
+ });
7091
+ }
7059
7092
  }
7060
7093
 
7061
7094
  const getStarkSigner = async (signer) => withPassportError(async () => {
@@ -7142,16 +7175,13 @@ class GuardianClient {
7142
7175
  transactionAPI;
7143
7176
  messageAPI;
7144
7177
  confirmationScreen;
7145
- // TODO: ID-977, make this rollup agnostic
7146
- imxEtherAddress;
7147
7178
  crossSdkBridgeEnabled;
7148
- constructor({ accessToken, confirmationScreen, imxEtherAddress, config, }) {
7149
- const guardianConfiguration = new Configuration({ accessToken, basePath: config.imxPublicApiDomain });
7179
+ constructor({ confirmationScreen, config }) {
7180
+ const guardianConfiguration = new Configuration({ basePath: config.imxPublicApiDomain });
7150
7181
  this.confirmationScreen = confirmationScreen;
7151
- this.transactionAPI = new TransactionsApi(new Configuration(guardianConfiguration));
7152
- this.imxEtherAddress = imxEtherAddress;
7153
7182
  this.crossSdkBridgeEnabled = config.crossSdkBridgeEnabled;
7154
7183
  this.messageAPI = new MessagesApi(guardianConfiguration);
7184
+ this.transactionAPI = new TransactionsApi(guardianConfiguration);
7155
7185
  }
7156
7186
  /**
7157
7187
  * Open confirmation screen and close it automatically if the
@@ -7175,29 +7205,30 @@ class GuardianClient {
7175
7205
  withDefaultConfirmationScreenTask(task) {
7176
7206
  return this.withConfirmationScreenTask()(task);
7177
7207
  }
7178
- async validate({ payloadHash }) {
7208
+ async evaluateImxTransaction({ payloadHash, user }) {
7179
7209
  const finallyFn = () => {
7180
7210
  this.confirmationScreen.closeWindow();
7181
7211
  };
7212
+ const headers = { Authorization: `Bearer ${user.accessToken}` };
7182
7213
  const transactionRes = await retryWithDelay(async () => this.transactionAPI.getTransactionByID({
7183
7214
  transactionID: payloadHash,
7184
7215
  chainType: 'starkex',
7185
- }), { finallyFn });
7216
+ }, { headers }), { finallyFn });
7186
7217
  if (!transactionRes.data.id) {
7187
7218
  throw new Error("Transaction doesn't exists");
7188
7219
  }
7189
- const evaluateStarkexRes = await this.transactionAPI.evaluateTransaction({
7220
+ const evaluateImxRes = await this.transactionAPI.evaluateTransaction({
7190
7221
  id: payloadHash,
7191
7222
  transactionEvaluationRequest: {
7192
7223
  chainType: 'starkex',
7193
7224
  },
7194
- });
7195
- const { confirmationRequired } = evaluateStarkexRes.data;
7225
+ }, { headers });
7226
+ const { confirmationRequired } = evaluateImxRes.data;
7196
7227
  if (confirmationRequired) {
7197
7228
  if (this.crossSdkBridgeEnabled) {
7198
7229
  throw new Error(transactionRejectedCrossSdkBridgeError);
7199
7230
  }
7200
- const confirmationResult = await this.confirmationScreen.requestConfirmation(payloadHash, this.imxEtherAddress, TransactionApprovalRequestChainTypeEnum.Starkex);
7231
+ const confirmationResult = await this.confirmationScreen.requestConfirmation(payloadHash, user.imx.ethAddress, TransactionApprovalRequestChainTypeEnum.Starkex);
7201
7232
  if (!confirmationResult.confirmed) {
7202
7233
  throw new Error('Transaction rejected by user');
7203
7234
  }
@@ -7241,7 +7272,7 @@ class GuardianClient {
7241
7272
  throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, transactionRejectedCrossSdkBridgeError);
7242
7273
  }
7243
7274
  if (confirmationRequired && !!transactionId) {
7244
- const confirmationResult = await this.confirmationScreen.requestConfirmation(transactionId, this.imxEtherAddress, TransactionApprovalRequestChainTypeEnum.Evm, chainId);
7275
+ const confirmationResult = await this.confirmationScreen.requestConfirmation(transactionId, user.zkEvm.ethAddress, TransactionApprovalRequestChainTypeEnum.Evm, chainId);
7245
7276
  if (!confirmationResult.confirmed) {
7246
7277
  throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, 'Transaction rejected by user');
7247
7278
  }
@@ -7337,10 +7368,7 @@ async function createOrder({ starkSigner, user, request, ordersApi, guardianClie
7337
7368
  const { ethAddress } = user.imx;
7338
7369
  const amountSell = request.sell.type === ERC721$1 ? '1' : request.sell.amount;
7339
7370
  const amountBuy = request.buy.type === ERC721$1 ? '1' : request.buy.amount;
7340
- const headers = {
7341
- // eslint-disable-next-line @typescript-eslint/naming-convention
7342
- Authorization: `Bearer ${user.accessToken}`,
7343
- };
7371
+ const headers = { Authorization: `Bearer ${user.accessToken}` };
7344
7372
  const getSignableOrderRequestV3 = {
7345
7373
  user: ethAddress,
7346
7374
  amount_buy: amountBuy,
@@ -7354,7 +7382,8 @@ async function createOrder({ starkSigner, user, request, ordersApi, guardianClie
7354
7382
  const getSignableOrderResponse = await ordersApi.getSignableOrder({
7355
7383
  getSignableOrderRequestV3,
7356
7384
  }, { headers });
7357
- await guardianClient.validate({
7385
+ await guardianClient.evaluateImxTransaction({
7386
+ user,
7358
7387
  payloadHash: getSignableOrderResponse.data.payload_hash,
7359
7388
  });
7360
7389
  const { payload_hash: payloadHash } = getSignableOrderResponse.data;
@@ -7396,7 +7425,8 @@ async function cancelOrder({ user, starkSigner, request, ordersApi, guardianClie
7396
7425
  const getSignableCancelOrderResponse = await ordersApi.getSignableCancelOrderV3({
7397
7426
  getSignableCancelOrderRequest,
7398
7427
  }, { headers });
7399
- await guardianClient.validate({
7428
+ await guardianClient.evaluateImxTransaction({
7429
+ user,
7400
7430
  payloadHash: getSignableCancelOrderResponse.data.payload_hash,
7401
7431
  });
7402
7432
  const { payload_hash: payloadHash } = getSignableCancelOrderResponse.data;
@@ -7459,7 +7489,8 @@ async function createTrade({ request, tradesApi, user, starkSigner, guardianClie
7459
7489
  const getSignableTradeResponse = await tradesApi.getSignableTrade({
7460
7490
  getSignableTradeRequest,
7461
7491
  }, { headers });
7462
- await guardianClient.validate({
7492
+ await guardianClient.evaluateImxTransaction({
7493
+ user,
7463
7494
  payloadHash: getSignableTradeResponse.data.payload_hash,
7464
7495
  });
7465
7496
  const { payload_hash: payloadHash } = getSignableTradeResponse.data;
@@ -7506,7 +7537,8 @@ async function transfer({ request, transfersApi, starkSigner, user, guardianClie
7506
7537
  const signableResult = await transfersApi.getSignableTransferV1({
7507
7538
  getSignableTransferRequest,
7508
7539
  }, { headers });
7509
- await guardianClient.validate({
7540
+ await guardianClient.evaluateImxTransaction({
7541
+ user,
7510
7542
  payloadHash: signableResult.data.payload_hash,
7511
7543
  });
7512
7544
  const signableResultData = signableResult.data;
@@ -7553,14 +7585,12 @@ async function batchNftTransfer({ user, starkSigner, request, transfersApi, guar
7553
7585
  sender_ether_key: ethAddress,
7554
7586
  signable_requests: signableRequests,
7555
7587
  };
7556
- const headers = {
7557
- // eslint-disable-next-line @typescript-eslint/naming-convention
7558
- Authorization: `Bearer ${user.accessToken}`,
7559
- };
7588
+ const headers = { Authorization: `Bearer ${user.accessToken}` };
7560
7589
  const signableResult = await transfersApi.getSignableTransfer({
7561
7590
  getSignableTransferRequestV2,
7562
7591
  }, { headers });
7563
- await guardianClient.validate({
7592
+ await guardianClient.evaluateImxTransaction({
7593
+ user,
7564
7594
  payloadHash: signableResult.data.signable_responses[0]?.payload_hash,
7565
7595
  });
7566
7596
  const requests = await Promise.all(signableResult.data.signable_responses.map(async (resp) => {
@@ -7590,39 +7620,40 @@ async function batchNftTransfer({ user, starkSigner, request, transfersApi, guar
7590
7620
  }
7591
7621
 
7592
7622
  class PassportImxProvider {
7593
- user;
7623
+ authManager;
7594
7624
  starkSigner;
7595
7625
  immutableXClient;
7596
- confirmationScreen;
7597
7626
  guardianClient;
7598
- constructor({ user, starkSigner, immutableXClient, confirmationScreen, config, passportEventEmitter, }) {
7599
- this.user = user;
7627
+ constructor({ authManager, starkSigner, immutableXClient, confirmationScreen, config, passportEventEmitter, }) {
7628
+ this.authManager = authManager;
7600
7629
  this.starkSigner = starkSigner;
7601
7630
  this.immutableXClient = immutableXClient;
7602
- this.confirmationScreen = confirmationScreen;
7603
7631
  this.guardianClient = new GuardianClient({
7604
- accessToken: user.accessToken,
7605
7632
  confirmationScreen,
7606
- imxEtherAddress: user.imx.ethAddress,
7607
7633
  config,
7608
7634
  });
7609
7635
  passportEventEmitter.on(PassportEvents.LOGGED_OUT, this.handleLogout);
7610
7636
  }
7611
7637
  handleLogout = () => {
7612
- this.user = undefined;
7613
7638
  this.starkSigner = undefined;
7614
7639
  };
7615
- checkIsLoggedIn() {
7616
- if (this.user === undefined || this.starkSigner === undefined) {
7640
+ async getAuthenticatedUserSigner() {
7641
+ const user = await this.authManager.getUser();
7642
+ if (!user || this.starkSigner === undefined) {
7617
7643
  throw new PassportError('User has been logged out', PassportErrorType.NOT_LOGGED_IN_ERROR);
7618
7644
  }
7645
+ const isUserImx = (oidcUser) => oidcUser?.imx !== undefined;
7646
+ if (!isUserImx(user)) {
7647
+ throw new PassportError('User has not been registered with StarkEx', PassportErrorType.USER_NOT_REGISTERED_ERROR);
7648
+ }
7649
+ return { user, starkSigner: this.starkSigner };
7619
7650
  }
7620
7651
  async transfer(request) {
7621
- this.checkIsLoggedIn();
7652
+ const { user, starkSigner } = await this.getAuthenticatedUserSigner();
7622
7653
  return transfer({
7623
7654
  request,
7624
- user: this.user,
7625
- starkSigner: this.starkSigner,
7655
+ user,
7656
+ starkSigner,
7626
7657
  transfersApi: this.immutableXClient.transfersApi,
7627
7658
  guardianClient: this.guardianClient,
7628
7659
  });
@@ -7637,52 +7668,52 @@ class PassportImxProvider {
7637
7668
  isRegisteredOnchain() {
7638
7669
  throw new PassportError('Operation not supported', PassportErrorType.OPERATION_NOT_SUPPORTED_ERROR);
7639
7670
  }
7640
- createOrder(request) {
7641
- this.checkIsLoggedIn();
7671
+ async createOrder(request) {
7672
+ const { user, starkSigner } = await this.getAuthenticatedUserSigner();
7642
7673
  return createOrder({
7643
7674
  request,
7644
- user: this.user,
7645
- starkSigner: this.starkSigner,
7675
+ user,
7676
+ starkSigner,
7646
7677
  ordersApi: this.immutableXClient.ordersApi,
7647
7678
  guardianClient: this.guardianClient,
7648
7679
  });
7649
7680
  }
7650
- cancelOrder(request) {
7651
- this.checkIsLoggedIn();
7681
+ async cancelOrder(request) {
7682
+ const { user, starkSigner } = await this.getAuthenticatedUserSigner();
7652
7683
  return cancelOrder({
7653
7684
  request,
7654
- user: this.user,
7655
- starkSigner: this.starkSigner,
7685
+ user,
7686
+ starkSigner,
7656
7687
  ordersApi: this.immutableXClient.ordersApi,
7657
7688
  guardianClient: this.guardianClient,
7658
7689
  });
7659
7690
  }
7660
- createTrade(request) {
7661
- this.checkIsLoggedIn();
7691
+ async createTrade(request) {
7692
+ const { user, starkSigner } = await this.getAuthenticatedUserSigner();
7662
7693
  return createTrade({
7663
7694
  request,
7664
- user: this.user,
7665
- starkSigner: this.starkSigner,
7695
+ user,
7696
+ starkSigner,
7666
7697
  tradesApi: this.immutableXClient.tradesApi,
7667
7698
  guardianClient: this.guardianClient,
7668
7699
  });
7669
7700
  }
7670
- batchNftTransfer(request) {
7671
- this.checkIsLoggedIn();
7701
+ async batchNftTransfer(request) {
7702
+ const { user, starkSigner } = await this.getAuthenticatedUserSigner();
7672
7703
  return batchNftTransfer({
7673
7704
  request,
7674
- user: this.user,
7675
- starkSigner: this.starkSigner,
7705
+ user,
7706
+ starkSigner,
7676
7707
  transfersApi: this.immutableXClient.transfersApi,
7677
7708
  guardianClient: this.guardianClient,
7678
7709
  });
7679
7710
  }
7680
- exchangeTransfer(request) {
7681
- this.checkIsLoggedIn();
7711
+ async exchangeTransfer(request) {
7712
+ const { user, starkSigner } = await this.getAuthenticatedUserSigner();
7682
7713
  return exchangeTransfer({
7683
7714
  request,
7684
- user: this.user,
7685
- starkSigner: this.starkSigner,
7715
+ user,
7716
+ starkSigner,
7686
7717
  exchangesApi: this.immutableXClient.exchangeApi,
7687
7718
  });
7688
7719
  }
@@ -7705,9 +7736,9 @@ class PassportImxProvider {
7705
7736
  token) {
7706
7737
  throw new PassportError('Operation not supported', PassportErrorType.OPERATION_NOT_SUPPORTED_ERROR);
7707
7738
  }
7708
- getAddress() {
7709
- this.checkIsLoggedIn();
7710
- return Promise.resolve(this.user.imx.ethAddress);
7739
+ async getAddress() {
7740
+ const { user } = await this.getAuthenticatedUserSigner();
7741
+ return Promise.resolve(user.imx.ethAddress);
7711
7742
  }
7712
7743
  }
7713
7744
 
@@ -7761,9 +7792,9 @@ class PassportImxProviderFactory {
7761
7792
  const ethSigner = web3Provider.getSigner();
7762
7793
  const starkSigner = await getStarkSigner(ethSigner);
7763
7794
  if (!user.imx?.ethAddress) {
7764
- const userImx = await this.registerStarkEx(ethSigner, starkSigner, user.accessToken);
7795
+ await this.registerStarkEx(ethSigner, starkSigner, user.accessToken);
7765
7796
  return new PassportImxProvider({
7766
- user: userImx,
7797
+ authManager: this.authManager,
7767
7798
  starkSigner,
7768
7799
  immutableXClient: this.immutableXClient,
7769
7800
  confirmationScreen: this.confirmationScreen,
@@ -7772,7 +7803,7 @@ class PassportImxProviderFactory {
7772
7803
  });
7773
7804
  }
7774
7805
  return new PassportImxProvider({
7775
- user: user,
7806
+ authManager: this.authManager,
7776
7807
  starkSigner,
7777
7808
  immutableXClient: this.immutableXClient,
7778
7809
  confirmationScreen: this.confirmationScreen,
@@ -8517,9 +8548,7 @@ class ZkEvmProvider {
8517
8548
  user: this.user,
8518
8549
  });
8519
8550
  this.guardianClient = new GuardianClient({
8520
- accessToken: this.user.accessToken,
8521
8551
  confirmationScreen: this.confirmationScreen,
8522
- imxEtherAddress: this.user.zkEvm.ethAddress,
8523
8552
  config: this.config,
8524
8553
  });
8525
8554
  this.eventEmitter.emit(ProviderEvent.ACCOUNTS_CHANGED, [this.user.zkEvm.ethAddress]);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@imtbl/sdk",
3
3
  "description": "Immutable Unified SDK",
4
- "version": "0.27.9",
4
+ "version": "0.27.10",
5
5
  "author": "Immutable",
6
6
  "browser": "./dist/index.browser.js",
7
7
  "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",