@dynamic-labs/ethereum-aa-zksync 4.18.6 → 4.18.8

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/CHANGELOG.md CHANGED
@@ -1,4 +1,31 @@
1
1
 
2
+ ### [4.18.8](https://github.com/dynamic-labs/dynamic-auth/compare/v4.18.7...v4.18.8) (2025-05-22)
3
+
4
+ ### Bug Fixes
5
+
6
+ * allow closing widget right after login ([#8760](https://github.com/dynamic-labs/dynamic-auth/issues/8760)) ([a9afff0](https://github.com/dynamic-labs/dynamic-auth/commit/a9afff0ab2a685853b39aed88e10bf1e700e4c8c))
7
+ * user wallets turning empty when linking new wallets ([#8775](https://github.com/dynamic-labs/dynamic-auth/issues/8775)) ([04215f5](https://github.com/dynamic-labs/dynamic-auth/commit/04215f5307e16ec4e1a7ff235a0d7df2340c3447))
8
+
9
+ ### [4.18.7](https://github.com/dynamic-labs/dynamic-auth/compare/v4.18.6...v4.18.7) (2025-05-21)
10
+
11
+
12
+ ### Features
13
+
14
+ * add zero dev kernel migration to v3.3 ([#8747](https://github.com/dynamic-labs/dynamic-auth/issues/8747)) ([ce10ef8](https://github.com/dynamic-labs/dynamic-auth/commit/ce10ef85d12452c2c21758c909f1e28f9fa5fbae))
15
+ * bump [@dynamic-labs-wallet](https://github.com/dynamic-labs-wallet) to v0.0.74 ([#8746](https://github.com/dynamic-labs/dynamic-auth/issues/8746)) ([98e3a0b](https://github.com/dynamic-labs/dynamic-auth/commit/98e3a0b845e7d6c34a2c748597198825713f4bcf))
16
+ * support kernel versio 0.3.2 and 0.3.3 ([#8738](https://github.com/dynamic-labs/dynamic-auth/issues/8738)) ([1115830](https://github.com/dynamic-labs/dynamic-auth/commit/1115830966318960d39a497c8b29188d9d9a447f))
17
+ * v3 solana confirmation ui ([#8731](https://github.com/dynamic-labs/dynamic-auth/issues/8731)) ([cfa5ba0](https://github.com/dynamic-labs/dynamic-auth/commit/cfa5ba07a946b847e60388c80afbd8aa233e9ebf))
18
+ * v3 svm send balance ([#8726](https://github.com/dynamic-labs/dynamic-auth/issues/8726)) ([236ec48](https://github.com/dynamic-labs/dynamic-auth/commit/236ec4843152f4b720aa7332e650db68c2d111b2))
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **alex/qntm-3201:** send empty data field when using zksync sendbalance ([#8733](https://github.com/dynamic-labs/dynamic-auth/issues/8733)) ([4c42035](https://github.com/dynamic-labs/dynamic-auth/commit/4c420350cf7404ac80db8b552594233a3de9fb57))
24
+ * allow for continuing signing if zksync account exists while attempting to deploy ([#8736](https://github.com/dynamic-labs/dynamic-auth/issues/8736)) ([1ff82e4](https://github.com/dynamic-labs/dynamic-auth/commit/1ff82e418e14300b9dec662fba517c5533c1caac))
25
+ * api kernel version on react native extension ([#8754](https://github.com/dynamic-labs/dynamic-auth/issues/8754)) ([c2f0bb4](https://github.com/dynamic-labs/dynamic-auth/commit/c2f0bb4ac86214f4e3bbdac5cf4b481a7a304449))
26
+ * CTRL wallet eip6963 detection ([#8727](https://github.com/dynamic-labs/dynamic-auth/issues/8727)) ([194334f](https://github.com/dynamic-labs/dynamic-auth/commit/194334f7fd541917d9a7f6b452145a47cf7ae853))
27
+ * **QNTM-3249:** fix mobile layout alignment in send view ([#8740](https://github.com/dynamic-labs/dynamic-auth/issues/8740)) ([7d8e02c](https://github.com/dynamic-labs/dynamic-auth/commit/7d8e02c11830f547b6fcfbc7b518ee3f045df41a))
28
+
2
29
  ### [4.18.6](https://github.com/dynamic-labs/dynamic-auth/compare/v4.18.5...v4.18.6) (2025-05-16)
3
30
 
4
31
 
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.18.6";
6
+ var version = "4.18.8";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "4.18.6";
2
+ var version = "4.18.8";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/ethereum-aa-zksync",
3
- "version": "4.18.6",
3
+ "version": "4.18.8",
4
4
  "description": "Core package for Ethereum Account Abstraction utilities and types",
5
5
  "author": "Dynamic Labs, Inc.",
6
6
  "license": "MIT",
@@ -18,15 +18,15 @@
18
18
  },
19
19
  "homepage": "https://www.dynamic.xyz/",
20
20
  "dependencies": {
21
- "@dynamic-labs/sdk-api-core": "0.0.669",
21
+ "@dynamic-labs/sdk-api-core": "0.0.672",
22
22
  "zksync-sso": "0.1.0",
23
- "@dynamic-labs/assert-package-version": "4.18.6",
24
- "@dynamic-labs/ethereum-aa-core": "4.18.6",
25
- "@dynamic-labs/ethereum-core": "4.18.6",
26
- "@dynamic-labs/types": "4.18.6",
27
- "@dynamic-labs/utils": "4.18.6",
28
- "@dynamic-labs/wallet-book": "4.18.6",
29
- "@dynamic-labs/wallet-connector-core": "4.18.6"
23
+ "@dynamic-labs/assert-package-version": "4.18.8",
24
+ "@dynamic-labs/ethereum-aa-core": "4.18.8",
25
+ "@dynamic-labs/ethereum-core": "4.18.8",
26
+ "@dynamic-labs/types": "4.18.8",
27
+ "@dynamic-labs/utils": "4.18.8",
28
+ "@dynamic-labs/wallet-book": "4.18.8",
29
+ "@dynamic-labs/wallet-connector-core": "4.18.8"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "viem": "^2.21.60"
@@ -6,17 +6,21 @@ Object.defineProperty(exports, '__esModule', { value: true });
6
6
  var _tslib = require('../../_virtual/_tslib.cjs');
7
7
  var viem = require('viem');
8
8
  var zksync = require('viem/zksync');
9
+ var abi = require('zksync-sso/abi');
9
10
  var passkey = require('zksync-sso/client/passkey');
10
11
  var utils$1 = require('zksync-sso/utils');
11
12
  var client = require('zksync-sso/client');
12
13
  var ecdsa = require('zksync-sso/client/ecdsa');
14
+ var accounts = require('viem/accounts');
13
15
  var ethereumCore = require('@dynamic-labs/ethereum-core');
14
16
  var utils = require('@dynamic-labs/utils');
17
+ var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
15
18
  var ethereumAaCore = require('@dynamic-labs/ethereum-aa-core');
16
19
  var getSalt = require('../utils/getSalt.cjs');
17
20
  var passkeys = require('../utils/passkeys.cjs');
18
21
  var deployment = require('../utils/deployment.cjs');
19
22
  var network = require('../utils/network.cjs');
23
+ var session = require('../utils/session.cjs');
20
24
 
21
25
  class ZKsyncConnector extends ethereumAaCore.AccountAbstractionBaseConnector {
22
26
  constructor(props) {
@@ -315,33 +319,18 @@ class ZKsyncConnector extends ethereumAaCore.AccountAbstractionBaseConnector {
315
319
  }
316
320
  deploySmartAccount(_a) {
317
321
  return _tslib.__awaiter(this, arguments, void 0, function* ({ withPaymaster, }) {
322
+ var _b, _c;
318
323
  if (!this.chainId) {
319
324
  throw new Error('Chain ID is not initialized');
320
325
  }
321
- if (!this.eoaConnector) {
326
+ if (!this.eoaConnector || !this.eoaAddress) {
322
327
  throw new Error('EOA connector is not initialized');
323
328
  }
324
- yield network.ensureEoaConnectorNetwork(this.eoaConnector, this.chainId);
325
- if (withPaymaster && this.paymasterAddress) {
326
- yield this.deploySmartAccountWithPaymaster();
327
- }
328
- else {
329
- yield this.deploySmartAccountWithoutPaymaster();
330
- }
331
- });
332
- }
333
- deploySmartAccountWithPaymaster() {
334
- return _tslib.__awaiter(this, void 0, void 0, function* () {
335
- if (!this.paymasterAddress) {
336
- throw new Error('Paymaster address is not initialized');
337
- }
338
329
  if (!this.smartAccountAddress) {
339
330
  throw new Error('Smart account address is not initialized');
340
331
  }
341
- if (!this.eoaAddress) {
342
- throw new Error('EOA address is not initialized');
343
- }
344
- const paymaster = this.paymasterAddress;
332
+ yield network.ensureEoaConnectorNetwork(this.eoaConnector, this.chainId);
333
+ const deployWithPaymaster = withPaymaster && this.paymasterAddress;
345
334
  const publicClient = yield this.getTypedPublicClient();
346
335
  const walletClient = yield this.getTypedWalletClient();
347
336
  const deploymentParams = yield deployment.getDeploymentParameters({
@@ -351,36 +340,23 @@ class ZKsyncConnector extends ethereumAaCore.AccountAbstractionBaseConnector {
351
340
  saltText: this.saltText,
352
341
  sessionKeyAddress: this.sessionKeyAddress,
353
342
  });
354
- const { request } = yield deployment.simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, false);
355
- const paymasterInput = zksync.getGeneralPaymasterInput({
356
- innerInput: new Uint8Array(),
357
- });
358
- const requestWithPaymaster = Object.assign(Object.assign({}, request), { paymaster,
359
- paymasterInput });
360
- yield deployment.executeAccountDeployment(walletClient, publicClient, requestWithPaymaster, this.smartAccountAddress);
361
- this._isSmartAccountDeployed = true;
362
- });
363
- }
364
- /**
365
- * Deploys a new smart account contract
366
- * @throws {ZkSyncConnectorError} If deployment fails
367
- * @testable This method can be mocked in tests
368
- */
369
- deploySmartAccountWithoutPaymaster() {
370
- return _tslib.__awaiter(this, void 0, void 0, function* () {
371
- if (!this.eoaConnector) {
372
- throw new Error('EOA connector is not initialized');
343
+ try {
344
+ let { request } = yield deployment.simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, !deployWithPaymaster);
345
+ if (deployWithPaymaster) {
346
+ const paymasterInput = zksync.getGeneralPaymasterInput({
347
+ innerInput: new Uint8Array(),
348
+ });
349
+ request = Object.assign(Object.assign({}, request), { paymaster: this.paymasterAddress, paymasterInput });
350
+ }
351
+ yield deployment.executeAccountDeployment(walletClient, publicClient, request, this.smartAccountAddress);
373
352
  }
374
- if (!this.smartAccountAddress) {
375
- throw new Error('Smart account address is not initialized');
353
+ catch (error) {
354
+ // If the account already exists, we don't want to throw an error and continue
355
+ if (((_c = (_b = error === null || error === void 0 ? void 0 : error.cause) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.errorName) !== 'ACCOUNT_ALREADY_EXISTS') {
356
+ throw error;
357
+ }
376
358
  }
377
- const walletClient = yield this.getTypedWalletClient();
378
- const publicClient = yield this.getTypedPublicClient();
379
- const deploymentParams = yield this.getDeploymentParameters();
380
- // Simulate the contract deployment first
381
- const { request } = yield deployment.simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, false);
382
- // Execute the deployment transaction
383
- yield deployment.executeAccountDeployment(walletClient, publicClient, request, this.smartAccountAddress);
359
+ this._isSmartAccountDeployed = true;
384
360
  });
385
361
  }
386
362
  /**
@@ -489,6 +465,106 @@ class ZKsyncConnector extends ethereumAaCore.AccountAbstractionBaseConnector {
489
465
  return isDeployed;
490
466
  });
491
467
  }
468
+ getSmartAccountCreationBlock() {
469
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
470
+ if (!this.smartAccountAddress) {
471
+ throw new Error('Smart account address is not initialized');
472
+ }
473
+ // check cache first
474
+ const cachedBlock = utils.StorageService.getItem(`smart-account-creation-block-${this.smartAccountAddress}`);
475
+ if (cachedBlock) {
476
+ return Number(cachedBlock);
477
+ }
478
+ const publicClient = yield this.getPublicClient();
479
+ try {
480
+ const createAccountLogs = yield publicClient.getContractEvents({
481
+ abi: abi.AAFactoryAbi,
482
+ address: this.factoryAddress,
483
+ args: {
484
+ accountAddress: this.smartAccountAddress,
485
+ },
486
+ eventName: 'AccountCreated',
487
+ fromBlock: BigInt(0),
488
+ });
489
+ if (createAccountLogs.length === 0) {
490
+ return 0;
491
+ }
492
+ // cache the block number
493
+ utils.StorageService.setItem(`smart-account-creation-block-${this.smartAccountAddress}`, createAccountLogs[0].blockNumber.toString());
494
+ return Number(createAccountLogs[0].blockNumber);
495
+ }
496
+ catch (error) {
497
+ walletConnectorCore.logger.error('[ZKsyncConnector] Error getting smart account creation block: ', error);
498
+ return 0;
499
+ }
500
+ });
501
+ }
502
+ listSessions() {
503
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
504
+ if (!this.smartAccount) {
505
+ throw new Error('Smart account is not initialized');
506
+ }
507
+ if (!this._isSmartAccountDeployed) {
508
+ return [];
509
+ }
510
+ const smartAccountCreationBlock = yield this.getSmartAccountCreationBlock();
511
+ const publicClient = yield this.getPublicClient();
512
+ try {
513
+ // Get all created session information
514
+ const createSessionLogs = (yield publicClient.getContractEvents({
515
+ abi: abi.SessionKeyValidatorAbi,
516
+ address: this.sessionKeyAddress,
517
+ args: {
518
+ account: this.smartAccountAddress,
519
+ },
520
+ eventName: 'SessionCreated',
521
+ // only get sessions from the block when the smart account was created
522
+ fromBlock: BigInt(smartAccountCreationBlock),
523
+ })).filter((log) => log.args.sessionSpec && log.args.sessionHash);
524
+ // Get all revoked session hashes
525
+ const revokedSessionHashes = (yield publicClient.getContractEvents({
526
+ abi: abi.SessionKeyValidatorAbi,
527
+ address: this.sessionKeyAddress,
528
+ args: {
529
+ account: this.smartAccountAddress,
530
+ },
531
+ eventName: 'SessionRevoked',
532
+ // only get sessions from the block when the smart account was created
533
+ fromBlock: BigInt(smartAccountCreationBlock),
534
+ }))
535
+ .filter((log) => log.args.sessionHash)
536
+ .map((log) => log.args.sessionHash);
537
+ const activeSessions = createSessionLogs
538
+ .filter((log) => log.args.sessionHash &&
539
+ // filter out the sessions that have been revoked
540
+ !revokedSessionHashes.includes(log.args.sessionHash))
541
+ .map((log) => ({
542
+ blockNumber: log.blockNumber,
543
+ session: log.args.sessionSpec,
544
+ sessionId: log.args.sessionHash,
545
+ timestamp: new Date(
546
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
547
+ parseInt(log.blockTimestamp, 16) * 1000).getTime(),
548
+ transactionHash: log.transactionHash,
549
+ }))
550
+ .sort((a, b) => {
551
+ if (a.blockNumber < b.blockNumber)
552
+ return 1;
553
+ if (a.blockNumber > b.blockNumber)
554
+ return -1;
555
+ return 0;
556
+ });
557
+ return activeSessions.map((session$1) => {
558
+ var _a;
559
+ return (Object.assign(Object.assign({}, session$1), { origin: (_a = session.retrieveSessionFromStorage(session$1.sessionId)) === null || _a === void 0 ? void 0 : _a.origin }));
560
+ });
561
+ }
562
+ catch (error) {
563
+ walletConnectorCore.logger.error('[ZKsyncConnector] Error listing sessions: ', error);
564
+ return [];
565
+ }
566
+ });
567
+ }
492
568
  getAddress() {
493
569
  return _tslib.__awaiter(this, void 0, void 0, function* () {
494
570
  var _a;
@@ -499,6 +575,59 @@ class ZKsyncConnector extends ethereumAaCore.AccountAbstractionBaseConnector {
499
575
  return this.smartAccountAddress;
500
576
  });
501
577
  }
578
+ revokeSession(sessionId) {
579
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
580
+ if (!this.smartAccount) {
581
+ throw new Error('Smart account is not initialized');
582
+ }
583
+ const params = {
584
+ sessionId,
585
+ };
586
+ if (this.paymasterAddress) {
587
+ params.paymaster = {
588
+ address: this.paymasterAddress,
589
+ paymasterInput: zksync.getGeneralPaymasterInput({
590
+ innerInput: new Uint8Array(),
591
+ }),
592
+ };
593
+ }
594
+ yield this.smartAccount.revokeSession(params);
595
+ utils.StorageService.removeItem(`zksync-session-${sessionId}`);
596
+ });
597
+ }
598
+ createSession(_a) {
599
+ return _tslib.__awaiter(this, arguments, void 0, function* ({ sessionConfig, origin, }) {
600
+ if (!this.smartAccount) {
601
+ throw new Error('Smart account is not initialized');
602
+ }
603
+ const safeSessionConfig = session.enforceSessionConfigRestrictions(sessionConfig);
604
+ const privateKey = accounts.generatePrivateKey();
605
+ const signer = accounts.privateKeyToAccount(privateKey);
606
+ const params = {
607
+ sessionConfig: Object.assign(Object.assign({}, safeSessionConfig), { signer: signer.address }),
608
+ };
609
+ if (this.paymasterAddress) {
610
+ params.paymaster = {
611
+ address: this.paymasterAddress,
612
+ paymasterInput: zksync.getGeneralPaymasterInput({
613
+ innerInput: new Uint8Array(),
614
+ }),
615
+ };
616
+ }
617
+ yield this.smartAccount.createSession(params);
618
+ const sessionHash = session.getSessionHash(params.sessionConfig);
619
+ const serializedSessionConfig = session.stringifySessionConfig(params.sessionConfig);
620
+ const originURI = origin
621
+ ? new URL(origin).hostname
622
+ : utils.PlatformService.getHostname();
623
+ utils.StorageService.setItem(`zksync-session-${sessionHash}`, {
624
+ origin: originURI,
625
+ sessionConfig: serializedSessionConfig,
626
+ sessionKey: privateKey,
627
+ });
628
+ return { expiresAt: safeSessionConfig.expiresAt, sessionId: sessionHash };
629
+ });
630
+ }
502
631
  validateActiveWallet(expectedAddress) {
503
632
  return _tslib.__awaiter(this, void 0, void 0, function* () {
504
633
  const currentAddress = yield this.getAddress();
@@ -3,6 +3,7 @@ import { ZksyncSsoPasskeyClient } from 'zksync-sso/client/passkey';
3
3
  import { SessionConfig } from 'zksync-sso/utils';
4
4
  import { ZksyncSsoSessionClient } from 'zksync-sso/client';
5
5
  import { ZksyncSsoEcdsaClient } from 'zksync-sso/client/ecdsa';
6
+ import { CreateSessionArgs, RevokeSessionArgs } from 'node_modules/zksync-sso/dist/_types/client/session/actions/session';
6
7
  import { EthereumWallet, RegisterEvmProvidersConfig } from '@dynamic-labs/ethereum-core';
7
8
  import { ProjectSettings, Provider, ProviderEnum } from '@dynamic-labs/sdk-api-core';
8
9
  import { EvmNetwork, GenericNetwork, WalletUiUtils } from '@dynamic-labs/types';
@@ -10,6 +11,7 @@ import { WalletBookSchema } from '@dynamic-labs/wallet-book';
10
11
  import { Chain, IAccountAbstractionWalletConnector, InternalWalletConnector, WalletConnector } from '@dynamic-labs/wallet-connector-core';
11
12
  import { AccountAbstractionBaseConnector, AccountAbstractionConnectorProps } from '@dynamic-labs/ethereum-aa-core';
12
13
  import { DeploymentParams } from '../utils';
14
+ import { SessionInformation, SessionConfigWithoutSigner } from '../types';
13
15
  type ZKsyncConnectorProps = AccountAbstractionConnectorProps & {
14
16
  apiProviders: {
15
17
  [key in ProviderEnum]?: Provider;
@@ -16528,8 +16530,8 @@ export declare class ZKsyncConnector extends AccountAbstractionBaseConnector imp
16528
16530
  sourceId?: number | undefined;
16529
16531
  testnet?: boolean | undefined;
16530
16532
  } & import("viem").ChainConfig<import("viem").ChainFormatters | undefined, Record<string, unknown> | undefined>, Account, chainOverride_9>) => Promise<`0x${string}`>;
16531
- createSession: (args: Omit<import("node_modules/zksync-sso/dist/_types/client/session/actions/session").CreateSessionArgs, "contracts">) => Promise<import("node_modules/zksync-sso/dist/_types/client/session/actions/session").CreateSessionReturnType>;
16532
- revokeSession: (args: Omit<import("node_modules/zksync-sso/dist/_types/client/session/actions/session").RevokeSessionArgs, "contracts">) => Promise<import("node_modules/zksync-sso/dist/_types/client/session/actions/session").RevokeSessionReturnType>;
16533
+ createSession: (args: Omit<CreateSessionArgs, "contracts">) => Promise<import("node_modules/zksync-sso/dist/_types/client/session/actions/session").CreateSessionReturnType>;
16534
+ revokeSession: (args: Omit<RevokeSessionArgs, "contracts">) => Promise<import("node_modules/zksync-sso/dist/_types/client/session/actions/session").RevokeSessionReturnType>;
16533
16535
  extend: <const client extends {
16534
16536
  [x: string]: unknown;
16535
16537
  account?: undefined;
@@ -17668,13 +17670,6 @@ export declare class ZKsyncConnector extends AccountAbstractionBaseConnector imp
17668
17670
  deploySmartAccount({ withPaymaster, }: {
17669
17671
  withPaymaster: boolean;
17670
17672
  }): Promise<void>;
17671
- private deploySmartAccountWithPaymaster;
17672
- /**
17673
- * Deploys a new smart account contract
17674
- * @throws {ZkSyncConnectorError} If deployment fails
17675
- * @testable This method can be mocked in tests
17676
- */
17677
- private deploySmartAccountWithoutPaymaster;
17678
17673
  /**
17679
17674
  * Gets typed public client from EOA connector
17680
17675
  * @throws {ZkSyncConnectorError} If public client cannot be obtained
@@ -17700,7 +17695,17 @@ export declare class ZKsyncConnector extends AccountAbstractionBaseConnector imp
17700
17695
  * @returns Promise that resolves when the check is complete
17701
17696
  */
17702
17697
  protected checkIsDeployed(): Promise<boolean>;
17698
+ private getSmartAccountCreationBlock;
17699
+ listSessions(): Promise<SessionInformation[]>;
17703
17700
  getAddress(): Promise<string | undefined>;
17701
+ revokeSession(sessionId: `0x${string}`): Promise<void>;
17702
+ createSession({ sessionConfig, origin, }: {
17703
+ sessionConfig: SessionConfigWithoutSigner;
17704
+ origin?: string;
17705
+ }): Promise<{
17706
+ expiresAt: bigint;
17707
+ sessionId: `0x${string}`;
17708
+ }>;
17704
17709
  validateActiveWallet(expectedAddress: string): Promise<void>;
17705
17710
  isSmartAccountDeployed(refetch?: boolean): Promise<boolean>;
17706
17711
  }
@@ -2,17 +2,21 @@
2
2
  import { __awaiter } from '../../_virtual/_tslib.js';
3
3
  import { createWalletClient, custom, publicActions, createPublicClient, http, walletActions, toHex } from 'viem';
4
4
  import { getGeneralPaymasterInput, eip712WalletActions } from 'viem/zksync';
5
+ import { AAFactoryAbi, SessionKeyValidatorAbi } from 'zksync-sso/abi';
5
6
  import { createZksyncPasskeyClient, registerNewPasskey } from 'zksync-sso/client/passkey';
6
7
  import { encodeModuleData } from 'zksync-sso/utils';
7
8
  import { createZksyncSessionClient } from 'zksync-sso/client';
8
9
  import { createZksyncEcdsaClient, zksyncSsoEcdsaWalletActions } from 'zksync-sso/client/ecdsa';
10
+ import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
9
11
  import { EthereumWallet, chainsMap, confirmationTransport, getOrMapViemChain } from '@dynamic-labs/ethereum-core';
10
- import { parseEvmNetworks, DeferredPromise, StorageService, DynamicError } from '@dynamic-labs/utils';
12
+ import { parseEvmNetworks, DeferredPromise, StorageService, PlatformService, DynamicError } from '@dynamic-labs/utils';
13
+ import { logger } from '@dynamic-labs/wallet-connector-core';
11
14
  import { AccountAbstractionBaseConnector } from '@dynamic-labs/ethereum-aa-core';
12
15
  import { getSalt } from '../utils/getSalt.js';
13
16
  import { getEncodedPasskeyModuleData } from '../utils/passkeys.js';
14
17
  import { getDeploymentParameters, simulateAccountDeployment, executeAccountDeployment } from '../utils/deployment.js';
15
18
  import { ensureEoaConnectorNetwork } from '../utils/network.js';
19
+ import { retrieveSessionFromStorage, enforceSessionConfigRestrictions, getSessionHash, stringifySessionConfig } from '../utils/session.js';
16
20
 
17
21
  class ZKsyncConnector extends AccountAbstractionBaseConnector {
18
22
  constructor(props) {
@@ -311,33 +315,18 @@ class ZKsyncConnector extends AccountAbstractionBaseConnector {
311
315
  }
312
316
  deploySmartAccount(_a) {
313
317
  return __awaiter(this, arguments, void 0, function* ({ withPaymaster, }) {
318
+ var _b, _c;
314
319
  if (!this.chainId) {
315
320
  throw new Error('Chain ID is not initialized');
316
321
  }
317
- if (!this.eoaConnector) {
322
+ if (!this.eoaConnector || !this.eoaAddress) {
318
323
  throw new Error('EOA connector is not initialized');
319
324
  }
320
- yield ensureEoaConnectorNetwork(this.eoaConnector, this.chainId);
321
- if (withPaymaster && this.paymasterAddress) {
322
- yield this.deploySmartAccountWithPaymaster();
323
- }
324
- else {
325
- yield this.deploySmartAccountWithoutPaymaster();
326
- }
327
- });
328
- }
329
- deploySmartAccountWithPaymaster() {
330
- return __awaiter(this, void 0, void 0, function* () {
331
- if (!this.paymasterAddress) {
332
- throw new Error('Paymaster address is not initialized');
333
- }
334
325
  if (!this.smartAccountAddress) {
335
326
  throw new Error('Smart account address is not initialized');
336
327
  }
337
- if (!this.eoaAddress) {
338
- throw new Error('EOA address is not initialized');
339
- }
340
- const paymaster = this.paymasterAddress;
328
+ yield ensureEoaConnectorNetwork(this.eoaConnector, this.chainId);
329
+ const deployWithPaymaster = withPaymaster && this.paymasterAddress;
341
330
  const publicClient = yield this.getTypedPublicClient();
342
331
  const walletClient = yield this.getTypedWalletClient();
343
332
  const deploymentParams = yield getDeploymentParameters({
@@ -347,36 +336,23 @@ class ZKsyncConnector extends AccountAbstractionBaseConnector {
347
336
  saltText: this.saltText,
348
337
  sessionKeyAddress: this.sessionKeyAddress,
349
338
  });
350
- const { request } = yield simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, false);
351
- const paymasterInput = getGeneralPaymasterInput({
352
- innerInput: new Uint8Array(),
353
- });
354
- const requestWithPaymaster = Object.assign(Object.assign({}, request), { paymaster,
355
- paymasterInput });
356
- yield executeAccountDeployment(walletClient, publicClient, requestWithPaymaster, this.smartAccountAddress);
357
- this._isSmartAccountDeployed = true;
358
- });
359
- }
360
- /**
361
- * Deploys a new smart account contract
362
- * @throws {ZkSyncConnectorError} If deployment fails
363
- * @testable This method can be mocked in tests
364
- */
365
- deploySmartAccountWithoutPaymaster() {
366
- return __awaiter(this, void 0, void 0, function* () {
367
- if (!this.eoaConnector) {
368
- throw new Error('EOA connector is not initialized');
339
+ try {
340
+ let { request } = yield simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, !deployWithPaymaster);
341
+ if (deployWithPaymaster) {
342
+ const paymasterInput = getGeneralPaymasterInput({
343
+ innerInput: new Uint8Array(),
344
+ });
345
+ request = Object.assign(Object.assign({}, request), { paymaster: this.paymasterAddress, paymasterInput });
346
+ }
347
+ yield executeAccountDeployment(walletClient, publicClient, request, this.smartAccountAddress);
369
348
  }
370
- if (!this.smartAccountAddress) {
371
- throw new Error('Smart account address is not initialized');
349
+ catch (error) {
350
+ // If the account already exists, we don't want to throw an error and continue
351
+ if (((_c = (_b = error === null || error === void 0 ? void 0 : error.cause) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.errorName) !== 'ACCOUNT_ALREADY_EXISTS') {
352
+ throw error;
353
+ }
372
354
  }
373
- const walletClient = yield this.getTypedWalletClient();
374
- const publicClient = yield this.getTypedPublicClient();
375
- const deploymentParams = yield this.getDeploymentParameters();
376
- // Simulate the contract deployment first
377
- const { request } = yield simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, false);
378
- // Execute the deployment transaction
379
- yield executeAccountDeployment(walletClient, publicClient, request, this.smartAccountAddress);
355
+ this._isSmartAccountDeployed = true;
380
356
  });
381
357
  }
382
358
  /**
@@ -485,6 +461,106 @@ class ZKsyncConnector extends AccountAbstractionBaseConnector {
485
461
  return isDeployed;
486
462
  });
487
463
  }
464
+ getSmartAccountCreationBlock() {
465
+ return __awaiter(this, void 0, void 0, function* () {
466
+ if (!this.smartAccountAddress) {
467
+ throw new Error('Smart account address is not initialized');
468
+ }
469
+ // check cache first
470
+ const cachedBlock = StorageService.getItem(`smart-account-creation-block-${this.smartAccountAddress}`);
471
+ if (cachedBlock) {
472
+ return Number(cachedBlock);
473
+ }
474
+ const publicClient = yield this.getPublicClient();
475
+ try {
476
+ const createAccountLogs = yield publicClient.getContractEvents({
477
+ abi: AAFactoryAbi,
478
+ address: this.factoryAddress,
479
+ args: {
480
+ accountAddress: this.smartAccountAddress,
481
+ },
482
+ eventName: 'AccountCreated',
483
+ fromBlock: BigInt(0),
484
+ });
485
+ if (createAccountLogs.length === 0) {
486
+ return 0;
487
+ }
488
+ // cache the block number
489
+ StorageService.setItem(`smart-account-creation-block-${this.smartAccountAddress}`, createAccountLogs[0].blockNumber.toString());
490
+ return Number(createAccountLogs[0].blockNumber);
491
+ }
492
+ catch (error) {
493
+ logger.error('[ZKsyncConnector] Error getting smart account creation block: ', error);
494
+ return 0;
495
+ }
496
+ });
497
+ }
498
+ listSessions() {
499
+ return __awaiter(this, void 0, void 0, function* () {
500
+ if (!this.smartAccount) {
501
+ throw new Error('Smart account is not initialized');
502
+ }
503
+ if (!this._isSmartAccountDeployed) {
504
+ return [];
505
+ }
506
+ const smartAccountCreationBlock = yield this.getSmartAccountCreationBlock();
507
+ const publicClient = yield this.getPublicClient();
508
+ try {
509
+ // Get all created session information
510
+ const createSessionLogs = (yield publicClient.getContractEvents({
511
+ abi: SessionKeyValidatorAbi,
512
+ address: this.sessionKeyAddress,
513
+ args: {
514
+ account: this.smartAccountAddress,
515
+ },
516
+ eventName: 'SessionCreated',
517
+ // only get sessions from the block when the smart account was created
518
+ fromBlock: BigInt(smartAccountCreationBlock),
519
+ })).filter((log) => log.args.sessionSpec && log.args.sessionHash);
520
+ // Get all revoked session hashes
521
+ const revokedSessionHashes = (yield publicClient.getContractEvents({
522
+ abi: SessionKeyValidatorAbi,
523
+ address: this.sessionKeyAddress,
524
+ args: {
525
+ account: this.smartAccountAddress,
526
+ },
527
+ eventName: 'SessionRevoked',
528
+ // only get sessions from the block when the smart account was created
529
+ fromBlock: BigInt(smartAccountCreationBlock),
530
+ }))
531
+ .filter((log) => log.args.sessionHash)
532
+ .map((log) => log.args.sessionHash);
533
+ const activeSessions = createSessionLogs
534
+ .filter((log) => log.args.sessionHash &&
535
+ // filter out the sessions that have been revoked
536
+ !revokedSessionHashes.includes(log.args.sessionHash))
537
+ .map((log) => ({
538
+ blockNumber: log.blockNumber,
539
+ session: log.args.sessionSpec,
540
+ sessionId: log.args.sessionHash,
541
+ timestamp: new Date(
542
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
543
+ parseInt(log.blockTimestamp, 16) * 1000).getTime(),
544
+ transactionHash: log.transactionHash,
545
+ }))
546
+ .sort((a, b) => {
547
+ if (a.blockNumber < b.blockNumber)
548
+ return 1;
549
+ if (a.blockNumber > b.blockNumber)
550
+ return -1;
551
+ return 0;
552
+ });
553
+ return activeSessions.map((session) => {
554
+ var _a;
555
+ return (Object.assign(Object.assign({}, session), { origin: (_a = retrieveSessionFromStorage(session.sessionId)) === null || _a === void 0 ? void 0 : _a.origin }));
556
+ });
557
+ }
558
+ catch (error) {
559
+ logger.error('[ZKsyncConnector] Error listing sessions: ', error);
560
+ return [];
561
+ }
562
+ });
563
+ }
488
564
  getAddress() {
489
565
  return __awaiter(this, void 0, void 0, function* () {
490
566
  var _a;
@@ -495,6 +571,59 @@ class ZKsyncConnector extends AccountAbstractionBaseConnector {
495
571
  return this.smartAccountAddress;
496
572
  });
497
573
  }
574
+ revokeSession(sessionId) {
575
+ return __awaiter(this, void 0, void 0, function* () {
576
+ if (!this.smartAccount) {
577
+ throw new Error('Smart account is not initialized');
578
+ }
579
+ const params = {
580
+ sessionId,
581
+ };
582
+ if (this.paymasterAddress) {
583
+ params.paymaster = {
584
+ address: this.paymasterAddress,
585
+ paymasterInput: getGeneralPaymasterInput({
586
+ innerInput: new Uint8Array(),
587
+ }),
588
+ };
589
+ }
590
+ yield this.smartAccount.revokeSession(params);
591
+ StorageService.removeItem(`zksync-session-${sessionId}`);
592
+ });
593
+ }
594
+ createSession(_a) {
595
+ return __awaiter(this, arguments, void 0, function* ({ sessionConfig, origin, }) {
596
+ if (!this.smartAccount) {
597
+ throw new Error('Smart account is not initialized');
598
+ }
599
+ const safeSessionConfig = enforceSessionConfigRestrictions(sessionConfig);
600
+ const privateKey = generatePrivateKey();
601
+ const signer = privateKeyToAccount(privateKey);
602
+ const params = {
603
+ sessionConfig: Object.assign(Object.assign({}, safeSessionConfig), { signer: signer.address }),
604
+ };
605
+ if (this.paymasterAddress) {
606
+ params.paymaster = {
607
+ address: this.paymasterAddress,
608
+ paymasterInput: getGeneralPaymasterInput({
609
+ innerInput: new Uint8Array(),
610
+ }),
611
+ };
612
+ }
613
+ yield this.smartAccount.createSession(params);
614
+ const sessionHash = getSessionHash(params.sessionConfig);
615
+ const serializedSessionConfig = stringifySessionConfig(params.sessionConfig);
616
+ const originURI = origin
617
+ ? new URL(origin).hostname
618
+ : PlatformService.getHostname();
619
+ StorageService.setItem(`zksync-session-${sessionHash}`, {
620
+ origin: originURI,
621
+ sessionConfig: serializedSessionConfig,
622
+ sessionKey: privateKey,
623
+ });
624
+ return { expiresAt: safeSessionConfig.expiresAt, sessionId: sessionHash };
625
+ });
626
+ }
498
627
  validateActiveWallet(expectedAddress) {
499
628
  return __awaiter(this, void 0, void 0, function* () {
500
629
  const currentAddress = yield this.getAddress();
package/src/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  import { WalletConnectorConstructor } from '@dynamic-labs/wallet-connector-core';
2
2
  export { isZKsyncConnector } from './utils';
3
+ export { type SessionInformation } from './types';
3
4
  export declare const ZKsyncSmartWalletConnectors: (props: any) => WalletConnectorConstructor[];
@@ -1,8 +1,34 @@
1
+ import { SessionConfig } from 'zksync-sso/utils';
1
2
  import { GenericNetwork, WalletUiUtils } from '@dynamic-labs/types';
2
3
  import { WalletBookSchema } from '@dynamic-labs/wallet-book';
3
4
  import { InternalWalletConnector } from '@dynamic-labs/wallet-connector-core';
5
+ export type SessionConfigWithoutSigner = Omit<SessionConfig, 'signer'>;
6
+ export type ConvertBigIntToString<T> = T extends bigint ? string : T extends Array<infer U> ? Array<ConvertBigIntToString<U>> : T extends object ? {
7
+ [K in keyof T]: ConvertBigIntToString<T[K]>;
8
+ } : T;
9
+ export type SessionConfigJSON = ConvertBigIntToString<SessionConfig>;
4
10
  export type AccountAbstractionConnectorProps = {
5
11
  walletUiUtils: WalletUiUtils<InternalWalletConnector>;
6
12
  walletBook: WalletBookSchema;
7
13
  evmNetworks: GenericNetwork[];
8
14
  };
15
+ export type SessionInformation = {
16
+ blockNumber: bigint;
17
+ session: SessionConfig;
18
+ sessionId: string;
19
+ timestamp: number;
20
+ transactionHash: string;
21
+ origin?: string;
22
+ };
23
+ export type ChainSessionInformation = {
24
+ blockNumber: bigint;
25
+ session: SessionConfig;
26
+ sessionId: `0x${string}`;
27
+ timestamp: number;
28
+ transactionHash: `0x${string}`;
29
+ };
30
+ export type SessionStorageItem = {
31
+ origin?: string;
32
+ sessionConfig: SessionConfigJSON;
33
+ sessionKey: string;
34
+ };
@@ -3,3 +3,4 @@ export * from './passkeys';
3
3
  export * from './deployment';
4
4
  export * from './network';
5
5
  export * from './isZKsyncConnector';
6
+ export * from './session';
@@ -0,0 +1,52 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var viem = require('viem');
7
+ var utils = require('zksync-sso/utils');
8
+ var utils$1 = require('@dynamic-labs/utils');
9
+
10
+ const DEFAULT_EXPIRATION_TIME = 86400; // 1 day
11
+ const enforceSessionConfigRestrictions = (sessionConfig) => {
12
+ const now = Math.floor(Date.now() / 1000);
13
+ const maxExpirationTime = now + DEFAULT_EXPIRATION_TIME;
14
+ if (!sessionConfig.expiresAt ||
15
+ Number(sessionConfig.expiresAt) > maxExpirationTime) {
16
+ sessionConfig.expiresAt = BigInt(maxExpirationTime);
17
+ }
18
+ return sessionConfig;
19
+ };
20
+ const getSessionHash = (sessionConfig) => {
21
+ const sessionHash = utils.encodeSession(sessionConfig);
22
+ return viem.keccak256(sessionHash);
23
+ };
24
+ const parseSessionConfigJSON = (sessionConfig) => {
25
+ const serializeLimit = (limit) => ({
26
+ limit: BigInt(limit.limit),
27
+ limitType: limit.limitType,
28
+ period: BigInt(limit.period),
29
+ });
30
+ return Object.assign(Object.assign({}, sessionConfig), { callPolicies: sessionConfig.callPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { constraints: policy.constraints.map((constraint) => (Object.assign(Object.assign({}, constraint), { index: BigInt(constraint.index), limit: serializeLimit(constraint.limit) }))), maxValuePerUse: BigInt(policy.maxValuePerUse), valueLimit: serializeLimit(policy.valueLimit) }))), expiresAt: BigInt(sessionConfig.expiresAt), feeLimit: serializeLimit(sessionConfig.feeLimit), transferPolicies: sessionConfig.transferPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { maxValuePerUse: BigInt(policy.maxValuePerUse), valueLimit: serializeLimit(policy.valueLimit) }))) });
31
+ };
32
+ const stringifySessionConfig = (sessionConfig) => {
33
+ const stringifyLimit = (limit) => ({
34
+ limit: limit.limit.toString(),
35
+ limitType: limit.limitType,
36
+ period: limit.period.toString(),
37
+ });
38
+ return Object.assign(Object.assign({}, sessionConfig), { callPolicies: sessionConfig.callPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { constraints: policy.constraints.map((constraint) => (Object.assign(Object.assign({}, constraint), { index: constraint.index.toString(), limit: stringifyLimit(constraint.limit) }))), maxValuePerUse: policy.maxValuePerUse.toString(), valueLimit: stringifyLimit(policy.valueLimit) }))), expiresAt: sessionConfig.expiresAt.toString(), feeLimit: stringifyLimit(sessionConfig.feeLimit), transferPolicies: sessionConfig.transferPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { maxValuePerUse: policy.maxValuePerUse.toString(), valueLimit: stringifyLimit(policy.valueLimit) }))) });
39
+ };
40
+ const retrieveSessionFromStorage = (sessionId) => {
41
+ const session = utils$1.StorageService.getItem(`zksync-session-${sessionId}`);
42
+ if (!session) {
43
+ return undefined;
44
+ }
45
+ return Object.assign(Object.assign({}, session), { sessionConfig: parseSessionConfigJSON(session.sessionConfig) });
46
+ };
47
+
48
+ exports.enforceSessionConfigRestrictions = enforceSessionConfigRestrictions;
49
+ exports.getSessionHash = getSessionHash;
50
+ exports.parseSessionConfigJSON = parseSessionConfigJSON;
51
+ exports.retrieveSessionFromStorage = retrieveSessionFromStorage;
52
+ exports.stringifySessionConfig = stringifySessionConfig;
@@ -0,0 +1,11 @@
1
+ import { SessionConfig } from 'zksync-sso/utils';
2
+ import { SessionConfigJSON, SessionConfigWithoutSigner } from '../types';
3
+ export declare const enforceSessionConfigRestrictions: (sessionConfig: SessionConfigWithoutSigner) => SessionConfigWithoutSigner;
4
+ export declare const getSessionHash: (sessionConfig: SessionConfig) => `0x${string}`;
5
+ export declare const parseSessionConfigJSON: (sessionConfig: SessionConfigJSON) => SessionConfig;
6
+ export declare const stringifySessionConfig: (sessionConfig: SessionConfig) => SessionConfigJSON;
7
+ export declare const retrieveSessionFromStorage: (sessionId: string) => {
8
+ sessionConfig: SessionConfig;
9
+ origin?: string | undefined;
10
+ sessionKey: string;
11
+ } | undefined;
@@ -0,0 +1,44 @@
1
+ 'use client'
2
+ import { keccak256 } from 'viem';
3
+ import { encodeSession } from 'zksync-sso/utils';
4
+ import { StorageService } from '@dynamic-labs/utils';
5
+
6
+ const DEFAULT_EXPIRATION_TIME = 86400; // 1 day
7
+ const enforceSessionConfigRestrictions = (sessionConfig) => {
8
+ const now = Math.floor(Date.now() / 1000);
9
+ const maxExpirationTime = now + DEFAULT_EXPIRATION_TIME;
10
+ if (!sessionConfig.expiresAt ||
11
+ Number(sessionConfig.expiresAt) > maxExpirationTime) {
12
+ sessionConfig.expiresAt = BigInt(maxExpirationTime);
13
+ }
14
+ return sessionConfig;
15
+ };
16
+ const getSessionHash = (sessionConfig) => {
17
+ const sessionHash = encodeSession(sessionConfig);
18
+ return keccak256(sessionHash);
19
+ };
20
+ const parseSessionConfigJSON = (sessionConfig) => {
21
+ const serializeLimit = (limit) => ({
22
+ limit: BigInt(limit.limit),
23
+ limitType: limit.limitType,
24
+ period: BigInt(limit.period),
25
+ });
26
+ return Object.assign(Object.assign({}, sessionConfig), { callPolicies: sessionConfig.callPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { constraints: policy.constraints.map((constraint) => (Object.assign(Object.assign({}, constraint), { index: BigInt(constraint.index), limit: serializeLimit(constraint.limit) }))), maxValuePerUse: BigInt(policy.maxValuePerUse), valueLimit: serializeLimit(policy.valueLimit) }))), expiresAt: BigInt(sessionConfig.expiresAt), feeLimit: serializeLimit(sessionConfig.feeLimit), transferPolicies: sessionConfig.transferPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { maxValuePerUse: BigInt(policy.maxValuePerUse), valueLimit: serializeLimit(policy.valueLimit) }))) });
27
+ };
28
+ const stringifySessionConfig = (sessionConfig) => {
29
+ const stringifyLimit = (limit) => ({
30
+ limit: limit.limit.toString(),
31
+ limitType: limit.limitType,
32
+ period: limit.period.toString(),
33
+ });
34
+ return Object.assign(Object.assign({}, sessionConfig), { callPolicies: sessionConfig.callPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { constraints: policy.constraints.map((constraint) => (Object.assign(Object.assign({}, constraint), { index: constraint.index.toString(), limit: stringifyLimit(constraint.limit) }))), maxValuePerUse: policy.maxValuePerUse.toString(), valueLimit: stringifyLimit(policy.valueLimit) }))), expiresAt: sessionConfig.expiresAt.toString(), feeLimit: stringifyLimit(sessionConfig.feeLimit), transferPolicies: sessionConfig.transferPolicies.map((policy) => (Object.assign(Object.assign({}, policy), { maxValuePerUse: policy.maxValuePerUse.toString(), valueLimit: stringifyLimit(policy.valueLimit) }))) });
35
+ };
36
+ const retrieveSessionFromStorage = (sessionId) => {
37
+ const session = StorageService.getItem(`zksync-session-${sessionId}`);
38
+ if (!session) {
39
+ return undefined;
40
+ }
41
+ return Object.assign(Object.assign({}, session), { sessionConfig: parseSessionConfigJSON(session.sessionConfig) });
42
+ };
43
+
44
+ export { enforceSessionConfigRestrictions, getSessionHash, parseSessionConfigJSON, retrieveSessionFromStorage, stringifySessionConfig };