@openfort/openfort-js 0.8.18 → 0.8.19

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.cjs CHANGED
@@ -3339,7 +3339,7 @@ class KeyPair extends signingKey.SigningKey {
3339
3339
  }
3340
3340
  }
3341
3341
 
3342
- const VERSION = '0.8.18';
3342
+ const VERSION = '0.8.19';
3343
3343
 
3344
3344
  var Event;
3345
3345
  (function (Event) {
@@ -3350,6 +3350,8 @@ var Event;
3350
3350
  Event["AUTHENTICATION_UPDATED"] = "authentication-updated";
3351
3351
  Event["SIGN"] = "sign";
3352
3352
  Event["SET_RECOVERY_METHOD"] = "set-recovery-method";
3353
+ Event["SWITCH_CHAIN"] = "switch-chain";
3354
+ Event["CHAIN_SWITCHED"] = "chain-switched";
3353
3355
  Event["EXPORT"] = "export";
3354
3356
  Event["SIGNED"] = "signed";
3355
3357
  Event["LOGOUT"] = "logout";
@@ -3419,6 +3421,17 @@ class SignRequest {
3419
3421
  this.requestConfiguration = requestConfiguration;
3420
3422
  }
3421
3423
  }
3424
+ class SwitchChainRequest {
3425
+ uuid;
3426
+ action = Event.SWITCH_CHAIN;
3427
+ chainId;
3428
+ requestConfiguration;
3429
+ constructor(uuid, chainId, requestConfiguration) {
3430
+ this.uuid = uuid;
3431
+ this.chainId = chainId;
3432
+ this.requestConfiguration = requestConfiguration;
3433
+ }
3434
+ }
3422
3435
  class ExportPrivateKeyRequest {
3423
3436
  uuid;
3424
3437
  action = Event.EXPORT;
@@ -3489,6 +3502,27 @@ class ConfigureResponse {
3489
3502
  this.version = null;
3490
3503
  }
3491
3504
  }
3505
+ class SwitchChainResponse {
3506
+ uuid;
3507
+ success;
3508
+ deviceID;
3509
+ address;
3510
+ chainId;
3511
+ accountType;
3512
+ ownerAddress;
3513
+ version;
3514
+ action = Event.CHAIN_SWITCHED;
3515
+ constructor(uuid, deviceID, accountType, chainId, address, ownerAddress) {
3516
+ this.success = true;
3517
+ this.deviceID = deviceID;
3518
+ this.uuid = uuid;
3519
+ this.accountType = accountType;
3520
+ this.chainId = chainId;
3521
+ this.address = address;
3522
+ this.ownerAddress = ownerAddress;
3523
+ this.version = null;
3524
+ }
3525
+ }
3492
3526
  class UpdateAuthenticationResponse {
3493
3527
  uuid;
3494
3528
  success;
@@ -3659,6 +3693,7 @@ class IframeManager {
3659
3693
  [Event.AUTHENTICATION_UPDATED]: UpdateAuthenticationResponse,
3660
3694
  [Event.CURRENT_DEVICE]: GetCurrentDeviceResponse,
3661
3695
  [Event.SIGNED]: SignResponse,
3696
+ [Event.CHAIN_SWITCHED]: SwitchChainResponse,
3662
3697
  [Event.LOGGED_OUT]: LogoutResponse,
3663
3698
  [Event.SET_RECOVERY_METHOD]: SetRecoveryMethodResponse,
3664
3699
  [Event.EXPORT]: ExportPrivateKeyResponse,
@@ -3756,6 +3791,33 @@ class IframeManager {
3756
3791
  sessionStorage.setItem('iframe-version', response.version ?? 'undefined');
3757
3792
  return response.signature;
3758
3793
  }
3794
+ async switchChain(iframeConfiguration, chainId) {
3795
+ await this.waitForIframeLoad();
3796
+ const uuid = this.generateShortUUID();
3797
+ const requestConfiguration = {
3798
+ thirdPartyProvider: iframeConfiguration.thirdPartyProvider ?? undefined,
3799
+ thirdPartyTokenType: iframeConfiguration.thirdPartyTokenType ?? undefined,
3800
+ token: iframeConfiguration.accessToken ?? undefined,
3801
+ publishableKey: this.sdkConfiguration.baseConfiguration.publishableKey,
3802
+ openfortURL: this.sdkConfiguration.backendUrl,
3803
+ };
3804
+ const request = new SwitchChainRequest(uuid, chainId, requestConfiguration);
3805
+ this.iframe?.contentWindow?.postMessage(request, '*');
3806
+ let response;
3807
+ try {
3808
+ response = await this.waitForResponse(uuid);
3809
+ }
3810
+ catch (e) {
3811
+ console.log('switchChain', e);
3812
+ if (e instanceof NotConfiguredError) {
3813
+ await this.configure(iframeConfiguration);
3814
+ return this.switchChain(iframeConfiguration, chainId);
3815
+ }
3816
+ throw e;
3817
+ }
3818
+ sessionStorage.setItem('iframe-version', response.version ?? 'undefined');
3819
+ return response;
3820
+ }
3759
3821
  async export(iframeConfiguration) {
3760
3822
  await this.waitForIframeLoad();
3761
3823
  const uuid = this.generateShortUUID();
@@ -4004,6 +4066,30 @@ class Recovery {
4004
4066
  }
4005
4067
  }
4006
4068
 
4069
+ class Account {
4070
+ type;
4071
+ address;
4072
+ ownerAddress;
4073
+ chainId;
4074
+ constructor(type, address, chainId, ownerAddress) {
4075
+ this.type = type;
4076
+ this.address = address;
4077
+ this.chainId = chainId;
4078
+ this.ownerAddress = ownerAddress;
4079
+ }
4080
+ static fromStorage(storage) {
4081
+ const account = storage.get(StorageKeys.ACCOUNT);
4082
+ if (!account) {
4083
+ return null;
4084
+ }
4085
+ const accountObj = JSON.parse(account);
4086
+ return new Account(accountObj.type, accountObj.address, accountObj.chainId, accountObj.ownerAddress);
4087
+ }
4088
+ save(storage) {
4089
+ storage.save(StorageKeys.ACCOUNT, JSON.stringify(this));
4090
+ }
4091
+ }
4092
+
4007
4093
  class EmbeddedSigner {
4008
4094
  iframeManager;
4009
4095
  iframeConfiguration;
@@ -4019,6 +4105,12 @@ class EmbeddedSigner {
4019
4105
  async export() {
4020
4106
  return await this.iframeManager.export(this.iframeConfiguration);
4021
4107
  }
4108
+ async switchChain({ chainId }) {
4109
+ const deviceAccount = await this.iframeManager
4110
+ .switchChain(this.iframeConfiguration, chainId);
4111
+ new Account(deviceAccount.accountType, deviceAccount.address, deviceAccount.chainId, deviceAccount.ownerAddress).save(this.storage);
4112
+ SignerManager.storage.save(StorageKeys.SIGNER, JSON.stringify(deviceAccount));
4113
+ }
4022
4114
  async setEmbeddedRecovery({ recoveryMethod, recoveryPassword, encryptionSession }) {
4023
4115
  await this.iframeManager
4024
4116
  .setEmbeddedRecovery(this.iframeConfiguration, recoveryMethod, recoveryPassword, encryptionSession);
@@ -4088,6 +4180,10 @@ class SessionSigner {
4088
4180
  updateAuthentication() {
4089
4181
  return Promise.resolve();
4090
4182
  }
4183
+ // eslint-disable-next-line class-methods-use-this
4184
+ switchChain() {
4185
+ return Promise.resolve();
4186
+ }
4091
4187
  async export() {
4092
4188
  return this.sessionKey.getPrivateKey();
4093
4189
  }
@@ -4097,30 +4193,6 @@ class SessionSigner {
4097
4193
  }
4098
4194
  }
4099
4195
 
4100
- class Account {
4101
- type;
4102
- address;
4103
- ownerAddress;
4104
- chainId;
4105
- constructor(type, address, chainId, ownerAddress) {
4106
- this.type = type;
4107
- this.address = address;
4108
- this.chainId = chainId;
4109
- this.ownerAddress = ownerAddress;
4110
- }
4111
- static fromStorage(storage) {
4112
- const account = storage.get(StorageKeys.ACCOUNT);
4113
- if (!account) {
4114
- return null;
4115
- }
4116
- const accountObj = JSON.parse(account);
4117
- return new Account(accountObj.type, accountObj.address, accountObj.chainId, accountObj.ownerAddress);
4118
- }
4119
- save(storage) {
4120
- storage.save(StorageKeys.ACCOUNT, JSON.stringify(this));
4121
- }
4122
- }
4123
-
4124
4196
  let iframeManagerSingleton = null;
4125
4197
  class SignerManager {
4126
4198
  static storage = new LocalStorage();
@@ -4880,6 +4952,7 @@ var BackendTransactionStatus;
4880
4952
  var ProviderEvent;
4881
4953
  (function (ProviderEvent) {
4882
4954
  ProviderEvent["ACCOUNTS_CHANGED"] = "accountsChanged";
4955
+ ProviderEvent["ACCOUNTS_CONNECT"] = "connect";
4883
4956
  })(ProviderEvent || (ProviderEvent = {}));
4884
4957
 
4885
4958
  /**
@@ -4948,7 +5021,14 @@ const sendTransaction = async ({ params, signer, account, authentication, backen
4948
5021
  const openfortTransaction = await buildOpenfortTransactions$4(params, backendClient, account, authentication, policyId);
4949
5022
  let response;
4950
5023
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
4951
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
5024
+ let signature;
5025
+ // zkSyncSepolia and Sophon test need a different signature
5026
+ if ([300, 531050104].includes(account.chainId)) {
5027
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
5028
+ }
5029
+ else {
5030
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
5031
+ }
4952
5032
  const openfortSignatureResponse = (await backendClient.transactionIntentsApi.signature({
4953
5033
  id: openfortTransaction.id,
4954
5034
  signatureRequest: { signature },
@@ -5476,12 +5556,9 @@ const chain$i = {
5476
5556
  networkId: 11155111,
5477
5557
  redFlags: [],
5478
5558
  rpc: [
5479
- 'https://rpc.sepolia.org',
5480
- 'https://rpc2.sepolia.org',
5481
- 'https://rpc-sepolia.rockx.com',
5559
+ 'https://ethereum-sepolia-rpc.publicnode.com',
5482
5560
  'https://rpc.sepolia.ethpandaops.io',
5483
5561
  'https://sepolia.gateway.tenderly.co',
5484
- 'https://ethereum-sepolia.publicnode.com',
5485
5562
  ],
5486
5563
  shortName: 'sep',
5487
5564
  slug: 'sepolia',
@@ -6451,6 +6528,7 @@ const buildOpenfortTransactions$3 = async (params, backendApiClients, account, a
6451
6528
  const formattedPermissions = param.permissions.map(formatPermissionRequest);
6452
6529
  const whitelist = formattedPermissions.filter((p) => p.type === 'contract-call'
6453
6530
  || p.type === 'erc20-token-transfer').map((p) => p.data.address);
6531
+ const limit = formattedPermissions[0].policies.find((p) => p.type === 'usage-limit')?.data?.limit;
6454
6532
  if (param.signer && param.signer.type === 'keys') {
6455
6533
  throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
6456
6534
  }
@@ -6458,7 +6536,7 @@ const buildOpenfortTransactions$3 = async (params, backendApiClients, account, a
6458
6536
  if (!sessionAddress) {
6459
6537
  throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
6460
6538
  }
6461
- const sessionRequest = formatSessionRequest$1(sessionAddress, account.chainId, now, expiry, policyId, false, whitelist, authentication.player);
6539
+ const sessionRequest = formatSessionRequest$1(sessionAddress, account.chainId, now, expiry, policyId, false, whitelist, authentication.player, limit);
6462
6540
  const transactionResponse = await backendApiClients.sessionsApi.createSession({
6463
6541
  createSessionRequest: sessionRequest,
6464
6542
  }, {
@@ -6497,7 +6575,14 @@ const registerSession = async ({ params, signer, account, authentication, backen
6497
6575
  const openfortTransaction = await buildOpenfortTransactions$3(params, backendClient, account, authentication, policyId);
6498
6576
  let response;
6499
6577
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
6500
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6578
+ let signature;
6579
+ // zkSyncSepolia and Sophon test need a different signature
6580
+ if ([300, 531050104].includes(account.chainId)) {
6581
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
6582
+ }
6583
+ else {
6584
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6585
+ }
6501
6586
  const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
6502
6587
  id: openfortTransaction.id,
6503
6588
  signatureRequest: { signature },
@@ -6547,7 +6632,14 @@ const revokeSession = async ({ params, signer, account, authentication, backendC
6547
6632
  const openfortTransaction = await buildOpenfortTransactions$2(params, backendClient, account, authentication, policyId);
6548
6633
  let response;
6549
6634
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
6550
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6635
+ let signature;
6636
+ // zkSyncSepolia and Sophon test need a different signature
6637
+ if ([300, 531050104].includes(account.chainId)) {
6638
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
6639
+ }
6640
+ else {
6641
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6642
+ }
6551
6643
  const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
6552
6644
  id: openfortTransaction.id,
6553
6645
  signatureRequest: { signature },
@@ -6601,7 +6693,14 @@ const sendCalls = async ({ params, signer, account, authentication, backendClien
6601
6693
  const openfortTransaction = await buildOpenfortTransactions$1(params[0].calls, backendClient, account, authentication, policy);
6602
6694
  let response;
6603
6695
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
6604
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6696
+ let signature;
6697
+ // zkSyncSepolia and Sophon test need a different signature
6698
+ if ([300, 531050104].includes(account.chainId)) {
6699
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
6700
+ }
6701
+ else {
6702
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6703
+ }
6605
6704
  const openfortSignatureResponse = (await backendClient.transactionIntentsApi.signature({
6606
6705
  id: openfortTransaction.id,
6607
6706
  signatureRequest: { signature },
@@ -6660,16 +6759,38 @@ const getCallStatus = async ({ params, authentication, backendClient, }) => {
6660
6759
  };
6661
6760
  };
6662
6761
 
6762
+ const personalSign = async ({ params, signer, account, }) => {
6763
+ const message = params[0];
6764
+ const fromAddress = params[1];
6765
+ if (!fromAddress || !message) {
6766
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'personal_sign requires an address and a message');
6767
+ }
6768
+ if (fromAddress.toLowerCase() !== account.address.toLowerCase()) {
6769
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'personal_sign requires the signer to be the from address');
6770
+ }
6771
+ const signature = await signer.sign(message, false, true);
6772
+ return signature;
6773
+ };
6774
+
6663
6775
  class EvmProvider {
6664
6776
  #storage;
6665
6777
  #policyId;
6778
+ /**
6779
+ * Updates the policy ID for the provider
6780
+ * @param newPolicyId - The new policy ID to use
6781
+ */
6782
+ updatePolicy(newPolicy) {
6783
+ this.#policyId = newPolicy;
6784
+ }
6785
+ #validateAndRefreshSession;
6666
6786
  #eventEmitter;
6667
6787
  #rpcProvider; // Used for read
6668
6788
  #backendApiClients;
6669
6789
  isOpenfort = true;
6670
- constructor({ storage, backendApiClients, openfortEventEmitter, policyId, }) {
6790
+ constructor({ storage, backendApiClients, openfortEventEmitter, policyId, validateAndRefreshSession, }) {
6671
6791
  this.#storage = storage;
6672
6792
  this.#policyId = policyId;
6793
+ this.#validateAndRefreshSession = validateAndRefreshSession;
6673
6794
  this.#backendApiClients = backendApiClients;
6674
6795
  const account = Account.fromStorage(this.#storage);
6675
6796
  const chainId = account?.chainId || 8453;
@@ -6699,6 +6820,7 @@ class EvmProvider {
6699
6820
  case 'eth_requestAccounts': {
6700
6821
  let account = Account.fromStorage(this.#storage);
6701
6822
  if (account) {
6823
+ this.#eventEmitter.emit(ProviderEvent.ACCOUNTS_CONNECT, { chainId: bytes.hexlify(account.chainId) });
6702
6824
  return [account.address];
6703
6825
  }
6704
6826
  const signer = SignerManager.fromStorage();
@@ -6720,6 +6842,8 @@ class EvmProvider {
6720
6842
  if (!account || !signer || !authentication) {
6721
6843
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6722
6844
  }
6845
+ this.#validateAndRefreshSession();
6846
+ console.log(`eth_sendTransaction ${this.#policyId}`);
6723
6847
  return await sendTransaction({
6724
6848
  params: request.params || [],
6725
6849
  signer,
@@ -6736,6 +6860,7 @@ class EvmProvider {
6736
6860
  if (!account || !signer) {
6737
6861
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6738
6862
  }
6863
+ this.#validateAndRefreshSession();
6739
6864
  return await signTypedDataV4({
6740
6865
  method: request.method,
6741
6866
  params: request.params || [],
@@ -6744,6 +6869,19 @@ class EvmProvider {
6744
6869
  rpcProvider: this.#rpcProvider,
6745
6870
  });
6746
6871
  }
6872
+ case 'personal_sign': {
6873
+ const account = Account.fromStorage(this.#storage);
6874
+ const signer = SignerManager.fromStorage();
6875
+ if (!account || !signer) {
6876
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6877
+ }
6878
+ this.#validateAndRefreshSession();
6879
+ return await personalSign({
6880
+ params: request.params || [],
6881
+ signer,
6882
+ account,
6883
+ });
6884
+ }
6747
6885
  case 'eth_chainId': {
6748
6886
  // Call detect network to fetch the chainId so to take advantage of
6749
6887
  // the caching layer provided by StaticJsonRpcProvider.
@@ -6754,6 +6892,25 @@ class EvmProvider {
6754
6892
  const { chainId } = await this.#rpcProvider.detectNetwork();
6755
6893
  return bytes.hexlify(chainId);
6756
6894
  }
6895
+ case 'wallet_switchEthereumChain': {
6896
+ const signer = SignerManager.fromStorage();
6897
+ if (!signer) {
6898
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - must be authenticated and configured with a signer');
6899
+ }
6900
+ if (!request.params || !Array.isArray(request.params) || request.params.length === 0) {
6901
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid parameters for wallet_switchEthereumChain');
6902
+ }
6903
+ this.#validateAndRefreshSession();
6904
+ try {
6905
+ const chainIdNumber = parseInt(request.params[0].chainId, 16);
6906
+ await signer.switchChain({ chainId: chainIdNumber });
6907
+ this.#rpcProvider = new providers.StaticJsonRpcProvider(chainMap[chainIdNumber].rpc[0]);
6908
+ }
6909
+ catch (error) {
6910
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to switch chain');
6911
+ }
6912
+ return null;
6913
+ }
6757
6914
  case 'wallet_addEthereumChain': {
6758
6915
  const signer = SignerManager.fromStorage();
6759
6916
  if (!signer) {
@@ -6775,6 +6932,7 @@ class EvmProvider {
6775
6932
  if (!account || !signer || !authentication) {
6776
6933
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6777
6934
  }
6935
+ this.#validateAndRefreshSession();
6778
6936
  return await getCallStatus({
6779
6937
  params: (request.params || {}),
6780
6938
  authentication,
@@ -6789,6 +6947,7 @@ class EvmProvider {
6789
6947
  if (!account || !signer || !authentication) {
6790
6948
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6791
6949
  }
6950
+ this.#validateAndRefreshSession();
6792
6951
  return await sendCalls({
6793
6952
  params: request.params || [],
6794
6953
  signer,
@@ -6805,6 +6964,7 @@ class EvmProvider {
6805
6964
  if (!account || !signer || !authentication) {
6806
6965
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6807
6966
  }
6967
+ this.#validateAndRefreshSession();
6808
6968
  return await registerSession({
6809
6969
  params: (request.params || []),
6810
6970
  signer,
@@ -6822,6 +6982,7 @@ class EvmProvider {
6822
6982
  if (!account || !signer || !authentication) {
6823
6983
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6824
6984
  }
6985
+ this.#validateAndRefreshSession();
6825
6986
  return await revokeSession({
6826
6987
  params: (request.params || {}),
6827
6988
  signer,
@@ -6843,6 +7004,9 @@ class EvmProvider {
6843
7004
  paymasterService: {
6844
7005
  supported: true,
6845
7006
  },
7007
+ atomicBatch: {
7008
+ supported: true,
7009
+ },
6846
7010
  },
6847
7011
  };
6848
7012
  return capabilities;
@@ -6983,6 +7147,7 @@ function announceProvider(detail) {
6983
7147
 
6984
7148
  class Openfort {
6985
7149
  storage;
7150
+ provider = null;
6986
7151
  constructor(sdkConfiguration) {
6987
7152
  this.storage = new LocalStorage();
6988
7153
  const configuration = new Configuration(sdkConfiguration.baseConfiguration.publishableKey, sdkConfiguration.overrides?.backendUrl || 'https://api.openfort.xyz', sdkConfiguration.shieldConfiguration?.shieldPublishableKey || '', sdkConfiguration.shieldConfiguration?.shieldEncryptionKey || '', sdkConfiguration.overrides?.shieldUrl || 'https://shield.openfort.xyz', sdkConfiguration.overrides?.iframeUrl || 'https://embedded.openfort.xyz', sdkConfiguration.shieldConfiguration?.debug || false);
@@ -7011,20 +7176,26 @@ class Openfort {
7011
7176
  const authentication = Authentication.fromStorage(this.storage);
7012
7177
  const signer = SignerManager.fromStorage();
7013
7178
  const account = Account.fromStorage(this.storage);
7014
- const provider = new EvmProvider({
7015
- storage: this.storage,
7016
- openfortEventEmitter: new TypedEventEmitter(),
7017
- signer: signer || undefined,
7018
- account: account || undefined,
7019
- authentication: authentication || undefined,
7020
- backendApiClients: this.backendApiClients,
7021
- policyId: options.policy,
7022
- });
7023
- announceProvider({
7024
- info: { ...openfortProviderInfo, ...options.providerInfo },
7025
- provider,
7026
- });
7027
- return provider;
7179
+ if (!this.provider) {
7180
+ this.provider = new EvmProvider({
7181
+ storage: this.storage,
7182
+ openfortEventEmitter: new TypedEventEmitter(),
7183
+ signer: signer || undefined,
7184
+ account: account || undefined,
7185
+ authentication: authentication || undefined,
7186
+ backendApiClients: this.backendApiClients,
7187
+ policyId: options.policy,
7188
+ validateAndRefreshSession: this.validateAndRefreshToken.bind(this),
7189
+ });
7190
+ announceProvider({
7191
+ info: { ...openfortProviderInfo, ...options.providerInfo },
7192
+ provider: this.provider,
7193
+ });
7194
+ }
7195
+ else if (this.provider && options.policy) {
7196
+ this.provider.updatePolicy(options.policy);
7197
+ }
7198
+ return this.provider;
7028
7199
  }
7029
7200
  /**
7030
7201
  * Configures a session key and returns the session key details.
package/dist/index.d.ts CHANGED
@@ -577,6 +577,7 @@ type Provider = {
577
577
 
578
578
  declare class Openfort {
579
579
  private readonly storage;
580
+ private provider;
580
581
  constructor(sdkConfiguration: OpenfortSDKConfiguration);
581
582
  /**
582
583
  * Logs the user out by flushing the signer and removing credentials.
package/dist/index.js CHANGED
@@ -3316,7 +3316,7 @@ class KeyPair extends SigningKey {
3316
3316
  }
3317
3317
  }
3318
3318
 
3319
- const VERSION = '0.8.18';
3319
+ const VERSION = '0.8.19';
3320
3320
 
3321
3321
  var Event;
3322
3322
  (function (Event) {
@@ -3327,6 +3327,8 @@ var Event;
3327
3327
  Event["AUTHENTICATION_UPDATED"] = "authentication-updated";
3328
3328
  Event["SIGN"] = "sign";
3329
3329
  Event["SET_RECOVERY_METHOD"] = "set-recovery-method";
3330
+ Event["SWITCH_CHAIN"] = "switch-chain";
3331
+ Event["CHAIN_SWITCHED"] = "chain-switched";
3330
3332
  Event["EXPORT"] = "export";
3331
3333
  Event["SIGNED"] = "signed";
3332
3334
  Event["LOGOUT"] = "logout";
@@ -3396,6 +3398,17 @@ class SignRequest {
3396
3398
  this.requestConfiguration = requestConfiguration;
3397
3399
  }
3398
3400
  }
3401
+ class SwitchChainRequest {
3402
+ uuid;
3403
+ action = Event.SWITCH_CHAIN;
3404
+ chainId;
3405
+ requestConfiguration;
3406
+ constructor(uuid, chainId, requestConfiguration) {
3407
+ this.uuid = uuid;
3408
+ this.chainId = chainId;
3409
+ this.requestConfiguration = requestConfiguration;
3410
+ }
3411
+ }
3399
3412
  class ExportPrivateKeyRequest {
3400
3413
  uuid;
3401
3414
  action = Event.EXPORT;
@@ -3466,6 +3479,27 @@ class ConfigureResponse {
3466
3479
  this.version = null;
3467
3480
  }
3468
3481
  }
3482
+ class SwitchChainResponse {
3483
+ uuid;
3484
+ success;
3485
+ deviceID;
3486
+ address;
3487
+ chainId;
3488
+ accountType;
3489
+ ownerAddress;
3490
+ version;
3491
+ action = Event.CHAIN_SWITCHED;
3492
+ constructor(uuid, deviceID, accountType, chainId, address, ownerAddress) {
3493
+ this.success = true;
3494
+ this.deviceID = deviceID;
3495
+ this.uuid = uuid;
3496
+ this.accountType = accountType;
3497
+ this.chainId = chainId;
3498
+ this.address = address;
3499
+ this.ownerAddress = ownerAddress;
3500
+ this.version = null;
3501
+ }
3502
+ }
3469
3503
  class UpdateAuthenticationResponse {
3470
3504
  uuid;
3471
3505
  success;
@@ -3636,6 +3670,7 @@ class IframeManager {
3636
3670
  [Event.AUTHENTICATION_UPDATED]: UpdateAuthenticationResponse,
3637
3671
  [Event.CURRENT_DEVICE]: GetCurrentDeviceResponse,
3638
3672
  [Event.SIGNED]: SignResponse,
3673
+ [Event.CHAIN_SWITCHED]: SwitchChainResponse,
3639
3674
  [Event.LOGGED_OUT]: LogoutResponse,
3640
3675
  [Event.SET_RECOVERY_METHOD]: SetRecoveryMethodResponse,
3641
3676
  [Event.EXPORT]: ExportPrivateKeyResponse,
@@ -3733,6 +3768,33 @@ class IframeManager {
3733
3768
  sessionStorage.setItem('iframe-version', response.version ?? 'undefined');
3734
3769
  return response.signature;
3735
3770
  }
3771
+ async switchChain(iframeConfiguration, chainId) {
3772
+ await this.waitForIframeLoad();
3773
+ const uuid = this.generateShortUUID();
3774
+ const requestConfiguration = {
3775
+ thirdPartyProvider: iframeConfiguration.thirdPartyProvider ?? undefined,
3776
+ thirdPartyTokenType: iframeConfiguration.thirdPartyTokenType ?? undefined,
3777
+ token: iframeConfiguration.accessToken ?? undefined,
3778
+ publishableKey: this.sdkConfiguration.baseConfiguration.publishableKey,
3779
+ openfortURL: this.sdkConfiguration.backendUrl,
3780
+ };
3781
+ const request = new SwitchChainRequest(uuid, chainId, requestConfiguration);
3782
+ this.iframe?.contentWindow?.postMessage(request, '*');
3783
+ let response;
3784
+ try {
3785
+ response = await this.waitForResponse(uuid);
3786
+ }
3787
+ catch (e) {
3788
+ console.log('switchChain', e);
3789
+ if (e instanceof NotConfiguredError) {
3790
+ await this.configure(iframeConfiguration);
3791
+ return this.switchChain(iframeConfiguration, chainId);
3792
+ }
3793
+ throw e;
3794
+ }
3795
+ sessionStorage.setItem('iframe-version', response.version ?? 'undefined');
3796
+ return response;
3797
+ }
3736
3798
  async export(iframeConfiguration) {
3737
3799
  await this.waitForIframeLoad();
3738
3800
  const uuid = this.generateShortUUID();
@@ -3981,6 +4043,30 @@ class Recovery {
3981
4043
  }
3982
4044
  }
3983
4045
 
4046
+ class Account {
4047
+ type;
4048
+ address;
4049
+ ownerAddress;
4050
+ chainId;
4051
+ constructor(type, address, chainId, ownerAddress) {
4052
+ this.type = type;
4053
+ this.address = address;
4054
+ this.chainId = chainId;
4055
+ this.ownerAddress = ownerAddress;
4056
+ }
4057
+ static fromStorage(storage) {
4058
+ const account = storage.get(StorageKeys.ACCOUNT);
4059
+ if (!account) {
4060
+ return null;
4061
+ }
4062
+ const accountObj = JSON.parse(account);
4063
+ return new Account(accountObj.type, accountObj.address, accountObj.chainId, accountObj.ownerAddress);
4064
+ }
4065
+ save(storage) {
4066
+ storage.save(StorageKeys.ACCOUNT, JSON.stringify(this));
4067
+ }
4068
+ }
4069
+
3984
4070
  class EmbeddedSigner {
3985
4071
  iframeManager;
3986
4072
  iframeConfiguration;
@@ -3996,6 +4082,12 @@ class EmbeddedSigner {
3996
4082
  async export() {
3997
4083
  return await this.iframeManager.export(this.iframeConfiguration);
3998
4084
  }
4085
+ async switchChain({ chainId }) {
4086
+ const deviceAccount = await this.iframeManager
4087
+ .switchChain(this.iframeConfiguration, chainId);
4088
+ new Account(deviceAccount.accountType, deviceAccount.address, deviceAccount.chainId, deviceAccount.ownerAddress).save(this.storage);
4089
+ SignerManager.storage.save(StorageKeys.SIGNER, JSON.stringify(deviceAccount));
4090
+ }
3999
4091
  async setEmbeddedRecovery({ recoveryMethod, recoveryPassword, encryptionSession }) {
4000
4092
  await this.iframeManager
4001
4093
  .setEmbeddedRecovery(this.iframeConfiguration, recoveryMethod, recoveryPassword, encryptionSession);
@@ -4065,6 +4157,10 @@ class SessionSigner {
4065
4157
  updateAuthentication() {
4066
4158
  return Promise.resolve();
4067
4159
  }
4160
+ // eslint-disable-next-line class-methods-use-this
4161
+ switchChain() {
4162
+ return Promise.resolve();
4163
+ }
4068
4164
  async export() {
4069
4165
  return this.sessionKey.getPrivateKey();
4070
4166
  }
@@ -4074,30 +4170,6 @@ class SessionSigner {
4074
4170
  }
4075
4171
  }
4076
4172
 
4077
- class Account {
4078
- type;
4079
- address;
4080
- ownerAddress;
4081
- chainId;
4082
- constructor(type, address, chainId, ownerAddress) {
4083
- this.type = type;
4084
- this.address = address;
4085
- this.chainId = chainId;
4086
- this.ownerAddress = ownerAddress;
4087
- }
4088
- static fromStorage(storage) {
4089
- const account = storage.get(StorageKeys.ACCOUNT);
4090
- if (!account) {
4091
- return null;
4092
- }
4093
- const accountObj = JSON.parse(account);
4094
- return new Account(accountObj.type, accountObj.address, accountObj.chainId, accountObj.ownerAddress);
4095
- }
4096
- save(storage) {
4097
- storage.save(StorageKeys.ACCOUNT, JSON.stringify(this));
4098
- }
4099
- }
4100
-
4101
4173
  let iframeManagerSingleton = null;
4102
4174
  class SignerManager {
4103
4175
  static storage = new LocalStorage();
@@ -4857,6 +4929,7 @@ var BackendTransactionStatus;
4857
4929
  var ProviderEvent;
4858
4930
  (function (ProviderEvent) {
4859
4931
  ProviderEvent["ACCOUNTS_CHANGED"] = "accountsChanged";
4932
+ ProviderEvent["ACCOUNTS_CONNECT"] = "connect";
4860
4933
  })(ProviderEvent || (ProviderEvent = {}));
4861
4934
 
4862
4935
  /**
@@ -4925,7 +4998,14 @@ const sendTransaction = async ({ params, signer, account, authentication, backen
4925
4998
  const openfortTransaction = await buildOpenfortTransactions$4(params, backendClient, account, authentication, policyId);
4926
4999
  let response;
4927
5000
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
4928
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
5001
+ let signature;
5002
+ // zkSyncSepolia and Sophon test need a different signature
5003
+ if ([300, 531050104].includes(account.chainId)) {
5004
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
5005
+ }
5006
+ else {
5007
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
5008
+ }
4929
5009
  const openfortSignatureResponse = (await backendClient.transactionIntentsApi.signature({
4930
5010
  id: openfortTransaction.id,
4931
5011
  signatureRequest: { signature },
@@ -5453,12 +5533,9 @@ const chain$i = {
5453
5533
  networkId: 11155111,
5454
5534
  redFlags: [],
5455
5535
  rpc: [
5456
- 'https://rpc.sepolia.org',
5457
- 'https://rpc2.sepolia.org',
5458
- 'https://rpc-sepolia.rockx.com',
5536
+ 'https://ethereum-sepolia-rpc.publicnode.com',
5459
5537
  'https://rpc.sepolia.ethpandaops.io',
5460
5538
  'https://sepolia.gateway.tenderly.co',
5461
- 'https://ethereum-sepolia.publicnode.com',
5462
5539
  ],
5463
5540
  shortName: 'sep',
5464
5541
  slug: 'sepolia',
@@ -6428,6 +6505,7 @@ const buildOpenfortTransactions$3 = async (params, backendApiClients, account, a
6428
6505
  const formattedPermissions = param.permissions.map(formatPermissionRequest);
6429
6506
  const whitelist = formattedPermissions.filter((p) => p.type === 'contract-call'
6430
6507
  || p.type === 'erc20-token-transfer').map((p) => p.data.address);
6508
+ const limit = formattedPermissions[0].policies.find((p) => p.type === 'usage-limit')?.data?.limit;
6431
6509
  if (param.signer && param.signer.type === 'keys') {
6432
6510
  throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
6433
6511
  }
@@ -6435,7 +6513,7 @@ const buildOpenfortTransactions$3 = async (params, backendApiClients, account, a
6435
6513
  if (!sessionAddress) {
6436
6514
  throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
6437
6515
  }
6438
- const sessionRequest = formatSessionRequest$1(sessionAddress, account.chainId, now, expiry, policyId, false, whitelist, authentication.player);
6516
+ const sessionRequest = formatSessionRequest$1(sessionAddress, account.chainId, now, expiry, policyId, false, whitelist, authentication.player, limit);
6439
6517
  const transactionResponse = await backendApiClients.sessionsApi.createSession({
6440
6518
  createSessionRequest: sessionRequest,
6441
6519
  }, {
@@ -6474,7 +6552,14 @@ const registerSession = async ({ params, signer, account, authentication, backen
6474
6552
  const openfortTransaction = await buildOpenfortTransactions$3(params, backendClient, account, authentication, policyId);
6475
6553
  let response;
6476
6554
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
6477
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6555
+ let signature;
6556
+ // zkSyncSepolia and Sophon test need a different signature
6557
+ if ([300, 531050104].includes(account.chainId)) {
6558
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
6559
+ }
6560
+ else {
6561
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6562
+ }
6478
6563
  const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
6479
6564
  id: openfortTransaction.id,
6480
6565
  signatureRequest: { signature },
@@ -6524,7 +6609,14 @@ const revokeSession = async ({ params, signer, account, authentication, backendC
6524
6609
  const openfortTransaction = await buildOpenfortTransactions$2(params, backendClient, account, authentication, policyId);
6525
6610
  let response;
6526
6611
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
6527
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6612
+ let signature;
6613
+ // zkSyncSepolia and Sophon test need a different signature
6614
+ if ([300, 531050104].includes(account.chainId)) {
6615
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
6616
+ }
6617
+ else {
6618
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6619
+ }
6528
6620
  const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
6529
6621
  id: openfortTransaction.id,
6530
6622
  signatureRequest: { signature },
@@ -6578,7 +6670,14 @@ const sendCalls = async ({ params, signer, account, authentication, backendClien
6578
6670
  const openfortTransaction = await buildOpenfortTransactions$1(params[0].calls, backendClient, account, authentication, policy);
6579
6671
  let response;
6580
6672
  if (openfortTransaction?.nextAction?.payload?.signableHash) {
6581
- const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6673
+ let signature;
6674
+ // zkSyncSepolia and Sophon test need a different signature
6675
+ if ([300, 531050104].includes(account.chainId)) {
6676
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash, false, false);
6677
+ }
6678
+ else {
6679
+ signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
6680
+ }
6582
6681
  const openfortSignatureResponse = (await backendClient.transactionIntentsApi.signature({
6583
6682
  id: openfortTransaction.id,
6584
6683
  signatureRequest: { signature },
@@ -6637,16 +6736,38 @@ const getCallStatus = async ({ params, authentication, backendClient, }) => {
6637
6736
  };
6638
6737
  };
6639
6738
 
6739
+ const personalSign = async ({ params, signer, account, }) => {
6740
+ const message = params[0];
6741
+ const fromAddress = params[1];
6742
+ if (!fromAddress || !message) {
6743
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'personal_sign requires an address and a message');
6744
+ }
6745
+ if (fromAddress.toLowerCase() !== account.address.toLowerCase()) {
6746
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'personal_sign requires the signer to be the from address');
6747
+ }
6748
+ const signature = await signer.sign(message, false, true);
6749
+ return signature;
6750
+ };
6751
+
6640
6752
  class EvmProvider {
6641
6753
  #storage;
6642
6754
  #policyId;
6755
+ /**
6756
+ * Updates the policy ID for the provider
6757
+ * @param newPolicyId - The new policy ID to use
6758
+ */
6759
+ updatePolicy(newPolicy) {
6760
+ this.#policyId = newPolicy;
6761
+ }
6762
+ #validateAndRefreshSession;
6643
6763
  #eventEmitter;
6644
6764
  #rpcProvider; // Used for read
6645
6765
  #backendApiClients;
6646
6766
  isOpenfort = true;
6647
- constructor({ storage, backendApiClients, openfortEventEmitter, policyId, }) {
6767
+ constructor({ storage, backendApiClients, openfortEventEmitter, policyId, validateAndRefreshSession, }) {
6648
6768
  this.#storage = storage;
6649
6769
  this.#policyId = policyId;
6770
+ this.#validateAndRefreshSession = validateAndRefreshSession;
6650
6771
  this.#backendApiClients = backendApiClients;
6651
6772
  const account = Account.fromStorage(this.#storage);
6652
6773
  const chainId = account?.chainId || 8453;
@@ -6676,6 +6797,7 @@ class EvmProvider {
6676
6797
  case 'eth_requestAccounts': {
6677
6798
  let account = Account.fromStorage(this.#storage);
6678
6799
  if (account) {
6800
+ this.#eventEmitter.emit(ProviderEvent.ACCOUNTS_CONNECT, { chainId: hexlify(account.chainId) });
6679
6801
  return [account.address];
6680
6802
  }
6681
6803
  const signer = SignerManager.fromStorage();
@@ -6697,6 +6819,8 @@ class EvmProvider {
6697
6819
  if (!account || !signer || !authentication) {
6698
6820
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6699
6821
  }
6822
+ this.#validateAndRefreshSession();
6823
+ console.log(`eth_sendTransaction ${this.#policyId}`);
6700
6824
  return await sendTransaction({
6701
6825
  params: request.params || [],
6702
6826
  signer,
@@ -6713,6 +6837,7 @@ class EvmProvider {
6713
6837
  if (!account || !signer) {
6714
6838
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6715
6839
  }
6840
+ this.#validateAndRefreshSession();
6716
6841
  return await signTypedDataV4({
6717
6842
  method: request.method,
6718
6843
  params: request.params || [],
@@ -6721,6 +6846,19 @@ class EvmProvider {
6721
6846
  rpcProvider: this.#rpcProvider,
6722
6847
  });
6723
6848
  }
6849
+ case 'personal_sign': {
6850
+ const account = Account.fromStorage(this.#storage);
6851
+ const signer = SignerManager.fromStorage();
6852
+ if (!account || !signer) {
6853
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6854
+ }
6855
+ this.#validateAndRefreshSession();
6856
+ return await personalSign({
6857
+ params: request.params || [],
6858
+ signer,
6859
+ account,
6860
+ });
6861
+ }
6724
6862
  case 'eth_chainId': {
6725
6863
  // Call detect network to fetch the chainId so to take advantage of
6726
6864
  // the caching layer provided by StaticJsonRpcProvider.
@@ -6731,6 +6869,25 @@ class EvmProvider {
6731
6869
  const { chainId } = await this.#rpcProvider.detectNetwork();
6732
6870
  return hexlify(chainId);
6733
6871
  }
6872
+ case 'wallet_switchEthereumChain': {
6873
+ const signer = SignerManager.fromStorage();
6874
+ if (!signer) {
6875
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - must be authenticated and configured with a signer');
6876
+ }
6877
+ if (!request.params || !Array.isArray(request.params) || request.params.length === 0) {
6878
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid parameters for wallet_switchEthereumChain');
6879
+ }
6880
+ this.#validateAndRefreshSession();
6881
+ try {
6882
+ const chainIdNumber = parseInt(request.params[0].chainId, 16);
6883
+ await signer.switchChain({ chainId: chainIdNumber });
6884
+ this.#rpcProvider = new StaticJsonRpcProvider(chainMap[chainIdNumber].rpc[0]);
6885
+ }
6886
+ catch (error) {
6887
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to switch chain');
6888
+ }
6889
+ return null;
6890
+ }
6734
6891
  case 'wallet_addEthereumChain': {
6735
6892
  const signer = SignerManager.fromStorage();
6736
6893
  if (!signer) {
@@ -6752,6 +6909,7 @@ class EvmProvider {
6752
6909
  if (!account || !signer || !authentication) {
6753
6910
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6754
6911
  }
6912
+ this.#validateAndRefreshSession();
6755
6913
  return await getCallStatus({
6756
6914
  params: (request.params || {}),
6757
6915
  authentication,
@@ -6766,6 +6924,7 @@ class EvmProvider {
6766
6924
  if (!account || !signer || !authentication) {
6767
6925
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6768
6926
  }
6927
+ this.#validateAndRefreshSession();
6769
6928
  return await sendCalls({
6770
6929
  params: request.params || [],
6771
6930
  signer,
@@ -6782,6 +6941,7 @@ class EvmProvider {
6782
6941
  if (!account || !signer || !authentication) {
6783
6942
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6784
6943
  }
6944
+ this.#validateAndRefreshSession();
6785
6945
  return await registerSession({
6786
6946
  params: (request.params || []),
6787
6947
  signer,
@@ -6799,6 +6959,7 @@ class EvmProvider {
6799
6959
  if (!account || !signer || !authentication) {
6800
6960
  throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
6801
6961
  }
6962
+ this.#validateAndRefreshSession();
6802
6963
  return await revokeSession({
6803
6964
  params: (request.params || {}),
6804
6965
  signer,
@@ -6820,6 +6981,9 @@ class EvmProvider {
6820
6981
  paymasterService: {
6821
6982
  supported: true,
6822
6983
  },
6984
+ atomicBatch: {
6985
+ supported: true,
6986
+ },
6823
6987
  },
6824
6988
  };
6825
6989
  return capabilities;
@@ -6960,6 +7124,7 @@ function announceProvider(detail) {
6960
7124
 
6961
7125
  class Openfort {
6962
7126
  storage;
7127
+ provider = null;
6963
7128
  constructor(sdkConfiguration) {
6964
7129
  this.storage = new LocalStorage();
6965
7130
  const configuration = new Configuration(sdkConfiguration.baseConfiguration.publishableKey, sdkConfiguration.overrides?.backendUrl || 'https://api.openfort.xyz', sdkConfiguration.shieldConfiguration?.shieldPublishableKey || '', sdkConfiguration.shieldConfiguration?.shieldEncryptionKey || '', sdkConfiguration.overrides?.shieldUrl || 'https://shield.openfort.xyz', sdkConfiguration.overrides?.iframeUrl || 'https://embedded.openfort.xyz', sdkConfiguration.shieldConfiguration?.debug || false);
@@ -6988,20 +7153,26 @@ class Openfort {
6988
7153
  const authentication = Authentication.fromStorage(this.storage);
6989
7154
  const signer = SignerManager.fromStorage();
6990
7155
  const account = Account.fromStorage(this.storage);
6991
- const provider = new EvmProvider({
6992
- storage: this.storage,
6993
- openfortEventEmitter: new TypedEventEmitter(),
6994
- signer: signer || undefined,
6995
- account: account || undefined,
6996
- authentication: authentication || undefined,
6997
- backendApiClients: this.backendApiClients,
6998
- policyId: options.policy,
6999
- });
7000
- announceProvider({
7001
- info: { ...openfortProviderInfo, ...options.providerInfo },
7002
- provider,
7003
- });
7004
- return provider;
7156
+ if (!this.provider) {
7157
+ this.provider = new EvmProvider({
7158
+ storage: this.storage,
7159
+ openfortEventEmitter: new TypedEventEmitter(),
7160
+ signer: signer || undefined,
7161
+ account: account || undefined,
7162
+ authentication: authentication || undefined,
7163
+ backendApiClients: this.backendApiClients,
7164
+ policyId: options.policy,
7165
+ validateAndRefreshSession: this.validateAndRefreshToken.bind(this),
7166
+ });
7167
+ announceProvider({
7168
+ info: { ...openfortProviderInfo, ...options.providerInfo },
7169
+ provider: this.provider,
7170
+ });
7171
+ }
7172
+ else if (this.provider && options.policy) {
7173
+ this.provider.updatePolicy(options.policy);
7174
+ }
7175
+ return this.provider;
7005
7176
  }
7006
7177
  /**
7007
7178
  * Configures a session key and returns the session key details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfort/openfort-js",
3
- "version": "0.8.18",
3
+ "version": "0.8.19",
4
4
  "author": "Openfort (https://www.openfort.xyz)",
5
5
  "bugs": "https://github.com/openfort-xyz/openfort-js/issues",
6
6
  "repository": "openfort-xyz/openfort-js.git",