diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad0e08..4622d64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [2.1.2] - 2025-01-27 + +### Added Changes + +- **viemLocalAccount Support**: Added support for passing a `LocalAccount` (from viem) directly to the Transaction Kit via the `viemLocalAccount` parameter in `delegatedEoa` mode. This allows users to bypass `privateKeyToAccount` conversion when they already have a `LocalAccount` object. The `viemLocalAccount` parameter works equivalently to `privateKey` and provides the same functionality - users can provide either `privateKey` or `viemLocalAccount`, but not both. + ## [2.1.1] - 2025-01-27 ### Added Changes diff --git a/README.md b/README.md index a9f86bf..acebd6b 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ import { TransactionKit } from '@etherspot/transaction-kit'; // Initialize TransactionKit const kit = TransactionKit({ chainId: 137, // Polygon mainnet - privateKey: '0x...your-private-key...', // Required for EIP-7702 + privateKey: '0x...your-private-key...', // Required for EIP-7702 (either privateKey or viemLocalAccount) bundlerApiKey: 'your-bundler-api-key', // Optional but recommended walletMode: 'delegatedEoa', // Required for EIP-7702 }); @@ -240,7 +240,7 @@ For EIP-7702 specific functionalities: // Initialize with delegated EOA mode const kit = TransactionKit({ chainId: 137, // Polygon - privateKey: '0x...your-private-key...', + privateKey: '0x...your-private-key...', // Required for EIP-7702 (either privateKey or viemLocalAccount) bundlerApiKey: 'your-bundler-api-key', walletMode: 'delegatedEoa', }); @@ -361,6 +361,7 @@ const result = await kit.sendBatches({ authorization }); ``` Notes: + - The `authorization` must match the transaction `chainId` and Kernel v3.3 implementation. - For multi-chain batches, the `authorization` will only be applied to chain groups matching the authorization's `chainId`. - `authorization` is only supported in `delegatedEoa` mode; using it in `modular` mode will cause validation errors. @@ -436,7 +437,7 @@ Advanced EIP-7702 functionality with delegated Externally Owned Accounts: ```typescript const kit = TransactionKit({ chainId: 137, // Required: Default chain ID - privateKey: '0x...your-private-key...', // Required: EOA private key + privateKey: '0x...your-private-key...', // Required for EIP-7702 (either privateKey or viemLocalAccount) bundlerApiKey: 'your-api-key', // Optional: For better performance bundlerUrl: 'https://your-bundler-url.com', // Optional: Custom bundler URL bundlerApiKeyFormat: '?api-key=', // Optional: API key format (default: '?api-key=') @@ -445,21 +446,21 @@ const kit = TransactionKit({ }); ``` -**Note**: In delegated EOA mode, you don't need to provide a `provider` as the private key is used directly to create the account. +**Note**: In delegated EOA mode, you don't need to provide a `provider`. You can provide either a `privateKey` or a `viemLocalAccount` (a `LocalAccount` from viem) directly, but not both. The `viemLocalAccount` option is useful when you already have a `LocalAccount` object and want to bypass the `privateKey` conversion. ### Wallet Mode Comparison -| Feature | Modular Mode | Delegated EOA Mode | -| --------------------------- | ------------------------ | ---------------------------------- | -| **Account Type** | Etherspot Smart Account | EIP-7702 Delegated EOA | -| **Provider Required** | ✅ Yes (wallet provider) | ❌ No (uses private key) | -| **Private Key Required** | ❌ No | ✅ Yes | -| **Client-Side Safe** | ✅ Yes | ⚠️ Depends on private key handling | -| **Paymaster Support** | ✅ Full support | ⚠️ Not yet supported | -| **UserOp Overrides** | ✅ Supported | ⚠️ Not yet supported | -| **EIP-7702 Methods** | ❌ Not available | ✅ Yes | -| **Modular SDK Integration** | ✅ Yes | ❌ No | -| **ZeroDev Integration** | ❌ No | ✅ Yes integration | +| Feature | Modular Mode | Delegated EOA Mode | +| -------------------------------------- | ------------------------ | ---------------------------------------------- | +| **Account Type** | Etherspot Smart Account | EIP-7702 Delegated EOA | +| **Provider Required** | ✅ Yes (wallet provider) | ❌ No (uses privateKey or viemLocalAccount) | +| **Private Key/Owner Account Required** | ❌ No | ✅ Yes (either privateKey or viemLocalAccount) | +| **Client-Side Safe** | ✅ Yes | ⚠️ Depends on private key/account handling | +| **Paymaster Support** | ✅ Full support | ⚠️ Not yet supported | +| **UserOp Overrides** | ✅ Supported | ⚠️ Not yet supported | +| **EIP-7702 Methods** | ❌ Not available | ✅ Yes | +| **Modular SDK Integration** | ✅ Yes | ❌ No | +| **ZeroDev Integration** | ❌ No | ✅ Yes integration | ### Advanced Bundler Configuration @@ -512,7 +513,7 @@ if (kit.getEtherspotProvider().getWalletMode() === 'delegatedEoa') { // Get account instances (delegatedEoa mode only) const delegatedEoaAccount = await kit.getDelegatedEoaAccount(137); - const ownerAccount = await kit.getOwnerAccount(137); + const viemLocalAccount = await kit.getOwnerAccount(137); } // Get transaction hash from userOp hash (available in both modes) @@ -574,11 +575,11 @@ When calling `delegateSmartAccountToEoa({ delegateImmediately: false })`, the me ## 🔒 Security Considerations -### Private Key Handling in Delegated EOA Mode +### Private Key and Owner Account Handling in Delegated EOA Mode -When using `walletMode: 'delegatedEoa'`, you must provide a private key. Here are important security considerations: +When using `walletMode: 'delegatedEoa'`, you must provide either a `privateKey` or a `viemLocalAccount` (LocalAccount from viem). Here are important security considerations: -**⚠️ Never expose private keys in client-side code or logs!** +**⚠️ Never expose private keys or owner accounts in client-side code or logs!** ```typescript // ❌ BAD: Hardcoded private key @@ -593,7 +594,7 @@ const kit = TransactionKit({ walletMode: 'delegatedEoa', }); -// ✅ GOOD: Use secure key management +// ✅ GOOD: Use secure key management (works with both privateKey and viemLocalAccount) const kit = TransactionKit({ privateKey: await getSecurePrivateKey(), // From secure storage walletMode: 'delegatedEoa', @@ -602,12 +603,13 @@ const kit = TransactionKit({ **Best Practices:** -1. **Private Key Security**: Handle private keys securely - never hardcode them in client-side code +1. **Private Key/Owner Account Security**: Handle private keys and owner accounts securely - never hardcode them in client-side code 2. **Environment Variables**: Store private keys in environment variables, never in code 3. **Key Rotation**: Regularly rotate private keys for enhanced security -4. **Access Control**: Implement proper access controls around private key usage +4. **Access Control**: Implement proper access controls around private key and owner account usage 5. **Audit Logging**: Log all transactions for security auditing 6. **Secure Storage**: Use hardware security modules (HSM) or secure key management services for production +7. **Owner Account Usage**: When using `viemLocalAccount`, ensure the underlying private key is handled securely ### Important Limitations & Considerations @@ -615,7 +617,7 @@ const kit = TransactionKit({ - **Paymaster Support**: Currently not supported in delegated EOA mode - **UserOp Overrides**: Custom userOp overrides are not yet supported -- **Private Key Security**: Requires careful private key handling +- **Private Key/Owner Account Security**: Requires careful private key or owner account handling - **ZeroDev Dependency**: Requires `@zerodev/sdk` package #### Modular Mode Limitations diff --git a/__tests__/EtherspotProvider.test.ts b/__tests__/EtherspotProvider.test.ts index 1b4556e..9baa55e 100644 --- a/__tests__/EtherspotProvider.test.ts +++ b/__tests__/EtherspotProvider.test.ts @@ -1,10 +1,7 @@ -import { - EtherspotBundler, - ModularSdk, - WalletProviderLike, -} from '@etherspot/modular-sdk'; +import { EtherspotBundler, ModularSdk } from '@etherspot/modular-sdk'; import { isEqual } from 'lodash'; import { Chain } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; // EtherspotProvider import { EtherspotProvider } from '../lib/EtherspotProvider'; @@ -26,6 +23,8 @@ jest.mock('lodash', () => ({ isEqual: jest.fn(), })); +// Fallback type for tests (the actual type is not needed for runtime behavior here) +type WalletProviderLike = any; // Get mocked constructors const MockedModularSdk = ModularSdk as jest.MockedClass; const MockedEtherspotBundler = EtherspotBundler as jest.MockedClass< @@ -189,25 +188,35 @@ describe('EtherspotProvider', () => { } ); - const missingPrivateKeyCases = [ - { privateKey: undefined }, - { privateKey: null }, - { privateKey: '' }, - ]; + it('should throw when neither privateKey nor viemLocalAccount is provided in delegatedEoa mode', () => { + expect( + () => + new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + } as EtherspotTransactionKitConfig) + ).toThrow( + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa"' + ); + }); - test.each(missingPrivateKeyCases)( - 'should throw for missing privateKey in delegatedEoa mode: $privateKey', - ({ privateKey }) => { - expect( - () => - new EtherspotProvider({ - chainId: 1, - walletMode: 'delegatedEoa', - privateKey: privateKey as any, - }) - ).toThrow('privateKey is required when walletMode is "delegatedEoa"'); - } - ); + it('should throw when both privateKey and viemLocalAccount are provided in delegatedEoa mode', () => { + const viemLocalAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + expect( + () => + new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + viemLocalAccount, + } as EtherspotTransactionKitConfig) + ).toThrow( + 'Cannot provide both privateKey and viemLocalAccount in delegatedEoa mode' + ); + }); it('should accept valid privateKey formats in delegatedEoa mode', () => { const validPrivateKeys = [ @@ -223,10 +232,24 @@ describe('EtherspotProvider', () => { chainId: 1, walletMode: 'delegatedEoa', privateKey, - }) + } as EtherspotTransactionKitConfig) ).not.toThrow(); }); }); + + it('should accept viemLocalAccount in delegatedEoa mode', () => { + const viemLocalAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + expect( + () => + new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + viemLocalAccount, + } as EtherspotTransactionKitConfig) + ).not.toThrow(); + }); }); }); @@ -284,10 +307,12 @@ describe('EtherspotProvider', () => { }); it('should handle wallet mode changes in updateConfig', () => { - // Test switching wallet mode (no validation in updateConfig) + // Test switching wallet mode (must provide privateKey or viemLocalAccount) expect(() => { etherspotProvider.updateConfig({ walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', }); }).not.toThrow(); @@ -329,6 +354,130 @@ describe('EtherspotProvider', () => { expect(etherspotProvider.getChainId()).toBe(137); // Should remain unchanged }); + describe('updateConfig with delegatedEoa mode and viemLocalAccount', () => { + it('should update config with viemLocalAccount in delegatedEoa mode', () => { + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + } as EtherspotTransactionKitConfig); + + const newViemLocalAccount = privateKeyToAccount( + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + ); + + delegated.updateConfig({ + walletMode: 'delegatedEoa', + viemLocalAccount: newViemLocalAccount, + }); + + expect(delegated.getWalletMode()).toBe('delegatedEoa'); + }); + + it('should clear privateKey when switching to viemLocalAccount', async () => { + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + } as EtherspotTransactionKitConfig); + + const newViemLocalAccount = privateKeyToAccount( + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + ); + + delegated.updateConfig({ + walletMode: 'delegatedEoa', + viemLocalAccount: newViemLocalAccount, + }); + + // getOwnerAccount should return the new viemLocalAccount + const owner = await delegated.getOwnerAccount(); + expect(owner.address).toBe(newViemLocalAccount.address); + expect(owner).toBe(newViemLocalAccount); + }); + + it('should clear viemLocalAccount when switching to privateKey', async () => { + const initialViemLocalAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + viemLocalAccount: initialViemLocalAccount, + } as EtherspotTransactionKitConfig); + + const newPrivateKey = + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'; + + delegated.updateConfig({ + walletMode: 'delegatedEoa', + privateKey: newPrivateKey, + }); + + // getOwnerAccount should create from the new privateKey + const owner = await delegated.getOwnerAccount(); + expect(owner.address).not.toBe(initialViemLocalAccount.address); + // Address from new privateKey should be different + const expectedAccount = privateKeyToAccount(newPrivateKey); + expect(owner.address).toBe(expectedAccount.address); + }); + + it('should throw when updating to delegatedEoa mode without privateKey or viemLocalAccount', () => { + expect(() => { + etherspotProvider.updateConfig({ + walletMode: 'delegatedEoa', + }); + }).toThrow( + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa"' + ); + }); + + it('should throw when both privateKey and viemLocalAccount are provided in updateConfig', () => { + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + } as EtherspotTransactionKitConfig); + + const viemLocalAccount = privateKeyToAccount( + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' + ); + + expect(() => { + delegated.updateConfig({ + walletMode: 'delegatedEoa', + privateKey: + '0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + viemLocalAccount, + }); + }).toThrow( + 'Cannot provide both privateKey and viemLocalAccount in delegatedEoa mode' + ); + }); + + it('should throw when clearing both privateKey and viemLocalAccount', () => { + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + } as EtherspotTransactionKitConfig); + + expect(() => { + delegated.updateConfig({ + walletMode: 'delegatedEoa', + privateKey: undefined, + viemLocalAccount: undefined, + }); + }).toThrow( + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa"' + ); + }); + }); + describe('Validation errors', () => { const validationErrorCases = [ { config: { chainId: 0 }, error: 'Invalid chainId in updateConfig' }, @@ -737,7 +886,11 @@ describe('EtherspotProvider', () => { it('should return updated wallet mode after config update', () => { expect(etherspotProvider.getWalletMode()).toBe('modular'); - etherspotProvider.updateConfig({ walletMode: 'delegatedEoa' }); + etherspotProvider.updateConfig({ + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }); expect(etherspotProvider.getWalletMode()).toBe('delegatedEoa'); }); }); @@ -884,6 +1037,20 @@ describe('EtherspotProvider', () => { expect(owner.address).toBeDefined(); }); + it('should return viemLocalAccount directly when provided', async () => { + const expectedAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + viemLocalAccount: expectedAccount, + } as EtherspotTransactionKitConfig); + const owner = await delegated.getOwnerAccount(); + expect(owner.address).toBe(expectedAccount.address); + expect(owner).toBe(expectedAccount); + }); + it('should handle invalid private key format', async () => { const delegated = new EtherspotProvider({ chainId: 1, @@ -894,6 +1061,25 @@ describe('EtherspotProvider', () => { await expect(delegated.getOwnerAccount()).rejects.toThrow(); }); + it('should throw when neither viemLocalAccount nor privateKey is available', () => { + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + privateKey: + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + } as EtherspotTransactionKitConfig); + + expect(() => { + delegated.updateConfig({ + walletMode: 'delegatedEoa', + privateKey: undefined, + viemLocalAccount: undefined, + }); + }).toThrow( + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa"' + ); + }); + it('should handle concurrent calls to same method', async () => { const delegated = new EtherspotProvider({ chainId: 1, @@ -913,11 +1099,37 @@ describe('EtherspotProvider', () => { promise3, ]); - // All should return the same result (cached) - same address + // All should return the same result - same address expect(owner1.address).toBe(owner2.address); expect(owner2.address).toBe(owner3.address); expect(owner1.address).toBeDefined(); }); + + it('should handle concurrent calls with viemLocalAccount', async () => { + const expectedAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + viemLocalAccount: expectedAccount, + } as EtherspotTransactionKitConfig); + + const promise1 = delegated.getOwnerAccount(); + const promise2 = delegated.getOwnerAccount(); + const promise3 = delegated.getOwnerAccount(); + + const [owner1, owner2, owner3] = await Promise.all([ + promise1, + promise2, + promise3, + ]); + + // All should return the same account object + expect(owner1).toBe(expectedAccount); + expect(owner2).toBe(expectedAccount); + expect(owner3).toBe(expectedAccount); + }); }); describe('getPublicClient', () => { @@ -958,6 +1170,22 @@ describe('EtherspotProvider', () => { const account = await delegated.getDelegatedEoaAccount(1); expect(account).toBeDefined(); }); + + it('should create smart account using viemLocalAccount directly', async () => { + const viemLocalAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + const delegated = new EtherspotProvider({ + chainId: 1, + walletMode: 'delegatedEoa', + viemLocalAccount, + } as EtherspotTransactionKitConfig); + + const account = await delegated.getDelegatedEoaAccount(1); + expect(account).toBeDefined(); + const owner = await delegated.getOwnerAccount(); + expect(owner).toBe(viemLocalAccount); + }); }); describe('getWalletClient', () => { @@ -1177,7 +1405,7 @@ describe('EtherspotProvider', () => { it('should clear cache when wallet mode changes', async () => { await etherspotProvider.getSdk(); - // Change wallet mode + // Change wallet mode (using privateKey) etherspotProvider.updateConfig({ walletMode: 'delegatedEoa', privateKey: @@ -1189,6 +1417,24 @@ describe('EtherspotProvider', () => { "getSdk() is only available in 'modular' wallet mode. Current mode: 'delegatedEoa'" ); }); + + it('should clear cache when switching to delegatedEoa mode with viemLocalAccount', async () => { + await etherspotProvider.getSdk(); + + // Change wallet mode (using viemLocalAccount) + const viemLocalAccount = privateKeyToAccount( + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + ); + etherspotProvider.updateConfig({ + walletMode: 'delegatedEoa', + viemLocalAccount, + }); + + // Next call should throw because getSdk is not available in delegatedEoa mode + await expect(etherspotProvider.getSdk()).rejects.toThrow( + "getSdk() is only available in 'modular' wallet mode. Current mode: 'delegatedEoa'" + ); + }); }); }); @@ -1227,10 +1473,10 @@ describe('EtherspotProvider', () => { new EtherspotProvider({ chainId: 1, walletMode: 'delegatedEoa', - // No privateKey provided + // No privateKey or viemLocalAccount provided } as EtherspotTransactionKitConfig) ).toThrow( - 'privateKey is required when walletMode is "delegatedEoa". Please provide a private key in the configuration.' + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa"' ); }); }); diff --git a/lib/EtherspotProvider.ts b/lib/EtherspotProvider.ts index 145dfc2..8885455 100644 --- a/lib/EtherspotProvider.ts +++ b/lib/EtherspotProvider.ts @@ -83,7 +83,8 @@ export class EtherspotProvider { * @param config - The provider configuration. * @throws {Error} If provider is not provided in modular mode. * @throws {Error} If chainId is invalid. - * @throws {Error} If privateKey is missing in delegatedEoa mode. + * @throws {Error} If neither privateKey nor viemLocalAccount is provided in delegatedEoa mode. + * @throws {Error} If both privateKey and viemLocalAccount are provided in delegatedEoa mode. */ constructor(config: EtherspotTransactionKitConfig) { // Validate chainId (required for all modes) @@ -96,6 +97,10 @@ export class EtherspotProvider { // Security: Separate sensitive and public data this.#privateConfig = { privateKey: 'privateKey' in config ? config.privateKey : undefined, + viemLocalAccount: + 'viemLocalAccount' in config + ? (config as any).viemLocalAccount + : undefined, bundlerApiKey: 'bundlerApiKey' in config ? config.bundlerApiKey : undefined, bundlerApiKeyFormat: @@ -125,14 +130,24 @@ export class EtherspotProvider { ); } } else if (config.walletMode === 'delegatedEoa') { - // DelegatedEoa mode requires privateKey + // DelegatedEoa mode requires either privateKey or viemLocalAccount (but not both) const delegatedEoaConfig = config as Extract< EtherspotTransactionKitConfig, { walletMode: 'delegatedEoa' } >; - if (!delegatedEoaConfig.privateKey) { + const hasPrivateKey = !!delegatedEoaConfig.privateKey; + const hasViemLocalAccount = !!(delegatedEoaConfig as any) + .viemLocalAccount; + + if (!hasPrivateKey && !hasViemLocalAccount) { + throw new Error( + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa". Please provide a private key or a LocalAccount (viemLocalAccount) in the configuration.' + ); + } + + if (hasPrivateKey && hasViemLocalAccount) { throw new Error( - 'privateKey is required when walletMode is "delegatedEoa". Please provide a private key in the configuration.' + 'Cannot provide both privateKey and viemLocalAccount in delegatedEoa mode. Please provide either privateKey or viemLocalAccount, but not both.' ); } } @@ -157,11 +172,14 @@ export class EtherspotProvider { return { chainId: delegatedEoaConfig.chainId, privateKey: delegatedEoaConfig.privateKey, + // Store viemLocalAccount address as string for comparison (not in DelegatedEoaModeConfig type) + viemLocalAccountAddress: (delegatedEoaConfig as any).viemLocalAccount + ?.address, bundlerUrl: delegatedEoaConfig.bundlerUrl, bundlerApiKey: delegatedEoaConfig.bundlerApiKey, bundlerApiKeyFormat: delegatedEoaConfig.bundlerApiKeyFormat, walletMode: 'delegatedEoa', - }; + } as DelegatedEoaModeConfig & { ownerAccountAddress?: string }; } /** @@ -195,13 +213,58 @@ export class EtherspotProvider { newConfig.walletMode && newConfig.walletMode !== this.#publicConfig.walletMode; + // Validate delegatedEoa mode requirements if we'll be in that mode after update + const finalWalletMode = + newConfig.walletMode ?? this.#publicConfig.walletMode; + + if (finalWalletMode === 'delegatedEoa') { + // Calculate what will exist after update (accounting for clearing logic): + // - If setting privateKey, viemLocalAccount will be cleared + // - If setting viemLocalAccount, privateKey will be cleared + // - If setting neither, both keep their current values + const willHavePrivateKey = + 'privateKey' in newConfig + ? !!newConfig.privateKey + : 'viemLocalAccount' in (newConfig as any) + ? false // Will be cleared when viemLocalAccount is set + : !!this.#privateConfig.privateKey; + + const willHaveViemLocalAccount = + 'viemLocalAccount' in (newConfig as any) + ? !!(newConfig as any).viemLocalAccount + : 'privateKey' in newConfig + ? false // Will be cleared when privateKey is set + : !!this.#privateConfig.viemLocalAccount; + + if (!willHavePrivateKey && !willHaveViemLocalAccount) { + throw new Error( + 'Either privateKey or viemLocalAccount is required when walletMode is "delegatedEoa". Please provide a private key or a LocalAccount (viemLocalAccount) in the configuration.' + ); + } + + if (willHavePrivateKey && willHaveViemLocalAccount) { + throw new Error( + 'Cannot provide both privateKey and viemLocalAccount in delegatedEoa mode. Please provide either privateKey or viemLocalAccount, but not both.' + ); + } + } + // Security: Update both private and public configs separately + // When switching between privateKey and viemLocalAccount, clear the opposite field this.#privateConfig = { ...this.#privateConfig, privateKey: 'privateKey' in newConfig ? newConfig.privateKey - : this.#privateConfig.privateKey, + : 'viemLocalAccount' in (newConfig as any) + ? undefined // Clear privateKey if viemLocalAccount is being set + : this.#privateConfig.privateKey, + viemLocalAccount: + 'viemLocalAccount' in (newConfig as any) + ? (newConfig as any).viemLocalAccount + : 'privateKey' in newConfig + ? undefined // Clear viemLocalAccount if privateKey is being set + : this.#privateConfig.viemLocalAccount, bundlerApiKey: 'bundlerApiKey' in newConfig ? newConfig.bundlerApiKey @@ -483,15 +546,16 @@ export class EtherspotProvider { } /** - * Gets the owner account (EOA) from the private key in config (delegatedEoa mode). + * Gets the owner account (EOA) from the config (delegatedEoa mode). + * Returns the viemLocalAccount directly if provided, otherwise creates it from privateKey. * * @param chainId - (Optional) The chain ID. - * @returns A promise that resolves to the owner account created from the private key. - * @throws {Error} If wallet mode is not 'delegatedEoa' or private key is not available. + * @returns A promise that resolves to the owner account. + * @throws {Error} If wallet mode is not 'delegatedEoa' or neither viemLocalAccount nor privateKey is available. * * @remarks * - Only available in delegatedEoa wallet mode. - * - Creates a new account instance each time (no caching needed for simple account creation). + * - Returns the viemLocalAccount directly if provided in config, otherwise creates from privateKey. * - This is the same account used internally in getDelegatedEoaAccount(). */ async getOwnerAccount( @@ -505,10 +569,21 @@ export class EtherspotProvider { ); } + // If viemLocalAccount is provided directly, return it + if (this.#privateConfig.viemLocalAccount) { + log( + `[EtherspotProvider] getOwnerAccount(): Using provided owner account ${this.#privateConfig.viemLocalAccount.address} for chain ${chainId}`, + { ownerAddress: this.#privateConfig.viemLocalAccount.address }, + this.#publicConfig.debugMode + ); + return this.#privateConfig.viemLocalAccount; + } + + // Otherwise, create from private key if (!this.#privateConfig.privateKey) { throw new Error( - 'getOwnerAccount(): privateKey not found in config. ' + - 'Please ensure the privateKey is set in config.' + 'getOwnerAccount(): Neither viemLocalAccount nor privateKey found in config. ' + + 'Please ensure either viemLocalAccount or privateKey is set in config.' ); } @@ -516,7 +591,7 @@ export class EtherspotProvider { const owner = privateKeyToAccount(this.#privateConfig.privateKey as Hex); log( - `[EtherspotProvider] getOwnerAccount(): Created owner account ${owner.address} for chain ${chainId}`, + `[EtherspotProvider] getOwnerAccount(): Created owner account ${owner.address} from privateKey for chain ${chainId}`, { ownerAddress: owner.address }, this.#publicConfig.debugMode ); diff --git a/lib/interfaces/index.ts b/lib/interfaces/index.ts index e546ef8..091c772 100644 --- a/lib/interfaces/index.ts +++ b/lib/interfaces/index.ts @@ -4,7 +4,11 @@ import { PaymasterApi, WalletProviderLike, } from '@etherspot/modular-sdk'; -import { type PublicActions, type WalletActions } from 'viem'; +import { + type LocalAccount, + type PublicActions, + type WalletActions, +} from 'viem'; import { type BundlerClient } from 'viem/account-abstraction'; import { SignAuthorizationReturnType } from 'viem/accounts'; @@ -24,6 +28,7 @@ export type WalletMode = 'modular' | 'delegatedEoa'; // Security: Private config interface for sensitive data export interface PrivateConfig { privateKey?: string; + viemLocalAccount?: LocalAccount; bundlerApiKey?: string; bundlerApiKeyFormat?: string; } @@ -46,7 +51,7 @@ export interface ModularModeConfig { walletMode?: 'modular'; } -// delegatedEoa mode specific config - requires a private key for EIP-7702 operations +// delegatedEoa mode specific config - requires either a private key or viemLocalAccount (LocalAccount) for EIP-7702 operations export interface DelegatedEoaModeConfig { chainId: number; bundlerApiKey?: string; @@ -54,7 +59,9 @@ export interface DelegatedEoaModeConfig { bundlerApiKeyFormat?: string; debugMode?: boolean; walletMode: 'delegatedEoa'; - privateKey: string; + // Either privateKey or viemLocalAccount must be provided (but not both) + privateKey?: string; + viemLocalAccount?: LocalAccount; } // EtherspotTransactionKitConfig diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 37bb114..28ecb91 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -78,7 +78,12 @@ export const log = (message: string, data?: any, debugMode?: boolean): void => { * Sensitive keys specific to TransactionKit configuration. * ONLY the critical security-sensitive keys that must never leak. */ -const SENSITIVE_KEYS = ['privateKey', 'bundlerApiKey', 'bundlerApiKeyFormat']; +const SENSITIVE_KEYS = [ + 'privateKey', + 'viemLocalAccount', + 'bundlerApiKey', + 'bundlerApiKeyFormat', +]; /** * Sanitizes any object by recursively sanitizing all properties and nested objects. diff --git a/package-lock.json b/package-lock.json index 02ae9a9..44e8996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@etherspot/transaction-kit", - "version": "2.1.1", + "version": "2.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@etherspot/transaction-kit", - "version": "2.1.1", + "version": "2.1.2", "license": "MIT", "dependencies": { "@etherspot/eip1271-verification-util": "0.1.2", @@ -98,6 +98,7 @@ "integrity": "sha512-D58mjF+Y+89UfbMJpV57UTCg+JRQIFgvROPfH7mmIfBcoFVMkwiiiJyzPyW3onN9kg9noDg7MVyI+Yt64bnfQQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", @@ -3305,7 +3306,6 @@ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -4573,7 +4573,6 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -4585,7 +4584,6 @@ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4742,6 +4740,7 @@ "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -4776,6 +4775,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -5317,7 +5317,6 @@ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -5328,24 +5327,21 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", @@ -5353,7 +5349,6 @@ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -5365,8 +5360,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", @@ -5374,7 +5368,6 @@ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5388,7 +5381,6 @@ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -5399,7 +5391,6 @@ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -5409,8 +5400,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", @@ -5418,7 +5408,6 @@ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5436,7 +5425,6 @@ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -5451,7 +5439,6 @@ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5465,7 +5452,6 @@ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -5481,7 +5467,6 @@ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -5492,16 +5477,14 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/@zerodev/sdk": { "version": "5.5.3", @@ -5562,6 +5545,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5586,7 +5570,6 @@ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.13.0" }, @@ -5641,6 +5624,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5658,7 +5642,6 @@ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -5677,7 +5660,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5694,8 +5676,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ajv-keywords": { "version": "3.5.2", @@ -5788,7 +5769,6 @@ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">= 0.4" } @@ -5849,7 +5829,6 @@ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5931,7 +5910,6 @@ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5988,8 +5966,7 @@ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/async-function": { "version": "1.0.0", @@ -6053,7 +6030,6 @@ "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==", "dev": true, "license": "MPL-2.0", - "peer": true, "engines": { "node": ">=4" } @@ -6064,7 +6040,6 @@ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">= 0.4" } @@ -6476,6 +6451,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -6676,7 +6652,6 @@ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.0" } @@ -7002,8 +6977,7 @@ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true, - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/dashdash": { "version": "1.14.1", @@ -7546,7 +7520,6 @@ "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -7574,8 +7547,7 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -7689,6 +7661,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -7802,6 +7775,7 @@ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -7891,6 +7865,7 @@ "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", @@ -7971,7 +7946,6 @@ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", @@ -8002,7 +7976,6 @@ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8013,8 +7986,7 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { "version": "3.1.2", @@ -8022,7 +7994,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8067,7 +8038,6 @@ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -8115,7 +8085,6 @@ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8127,7 +8096,6 @@ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -8141,7 +8109,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8155,7 +8122,6 @@ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9048,8 +9014,7 @@ "url": "https://opencollective.com/fastify" } ], - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/fastq": { "version": "1.19.1", @@ -9533,8 +9498,7 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.12", @@ -9896,7 +9860,8 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/ieee754": { "version": "1.2.1", @@ -10715,7 +10680,6 @@ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", @@ -10950,6 +10914,7 @@ "integrity": "sha512-G46nKgiez2Gy4zvYNhayfMEAFlVHhWfncqvqS6yCd0i+a4NsSUD2WtrKSaYQrYiLQaupHXxCRi8xxVL2M9PbhA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/environment": "^29.3.1", "@jest/fake-timers": "^29.3.1", @@ -11635,7 +11600,6 @@ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -11695,8 +11659,7 @@ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", @@ -11704,7 +11667,6 @@ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "language-subtag-registry": "^0.3.20" }, @@ -11755,7 +11717,6 @@ "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.11.5" }, @@ -11825,7 +11786,6 @@ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -12080,8 +12040,7 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/node-fetch": { "version": "2.7.0", @@ -12754,6 +12713,7 @@ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -12831,7 +12791,6 @@ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -12843,8 +12802,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/psl": { "version": "1.15.0", @@ -12957,7 +12915,6 @@ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -13233,7 +13190,6 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13388,6 +13344,7 @@ "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -13613,7 +13570,6 @@ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "randombytes": "^2.1.0" } @@ -14003,7 +13959,6 @@ "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -14019,7 +13974,6 @@ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -14048,7 +14002,6 @@ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14263,7 +14216,6 @@ "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -14283,7 +14235,6 @@ "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -14337,7 +14288,6 @@ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -14351,7 +14301,6 @@ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -14366,8 +14315,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "4.3.3", @@ -14375,7 +14323,6 @@ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -14396,7 +14343,6 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -14412,8 +14358,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/terser/node_modules/source-map-support": { "version": "0.5.21", @@ -14421,7 +14366,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -14751,6 +14695,7 @@ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15095,6 +15040,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", @@ -15191,7 +15137,6 @@ "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -15216,7 +15161,6 @@ "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -15266,7 +15210,6 @@ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.13.0" } @@ -15295,7 +15238,6 @@ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -15309,7 +15251,6 @@ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -15324,7 +15265,6 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=4.0" } @@ -15334,8 +15274,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/webpack/node_modules/schema-utils": { "version": "4.3.3", @@ -15343,7 +15282,6 @@ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -15622,6 +15560,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=8.3.0" }, diff --git a/package.json b/package.json index 07c1aed..b450ff5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@etherspot/transaction-kit", "description": "Framework-agnostic Etherspot Transaction Kit", - "version": "2.1.1", + "version": "2.1.2", "main": "dist/cjs/index.js", "scripts": { "rollup:build": "NODE_OPTIONS=--max-old-space-size=8192 rollup -c --bundleConfigAsCjs",