diff --git a/examples/erlang-bridge/package.json b/examples/erlang-bridge/package.json index 643e58f6..215804bc 100644 --- a/examples/erlang-bridge/package.json +++ b/examples/erlang-bridge/package.json @@ -9,6 +9,6 @@ }, "dependencies": { "@lidofinance/lido-ethereum-sdk": "workspace:*", - "viem": "^2.0.6" + "viem": "^2.21.9" } } diff --git a/examples/rewards/package.json b/examples/rewards/package.json index cc2d9170..59a39c71 100644 --- a/examples/rewards/package.json +++ b/examples/rewards/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@lidofinance/lido-ethereum-sdk": "workspace:*", - "viem": "^2.0.6" + "viem": "^2.21.9" }, "devDependencies": { "rimraf": "^5.0.5", diff --git a/packages/lido-pulse/package.json b/packages/lido-pulse/package.json index dd752956..3dc086ec 100644 --- a/packages/lido-pulse/package.json +++ b/packages/lido-pulse/package.json @@ -53,7 +53,7 @@ "fastify": "^4.28.1", "fastify-plugin": "^4.5.1", "reflect-metadata": "^0.2.2", - "viem": "^2.0.6" + "viem": "^2.21.9" }, "devDependencies": { "@types/node": "^20.14.10", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index da82685f..7ecb6639 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -71,6 +71,11 @@ "default": "./dist/cjs/shares/index.js", "types": "./dist/types/shares/index.d.ts" }, + "./l2": { + "import": "./dist/esm/l2/index.js", + "default": "./dist/cjs/l2/index.js", + "types": "./dist/types/l2/index.d.ts" + }, "./package.json": "./package.json" }, "typesVersions": { @@ -104,6 +109,9 @@ ], "shares": [ "./dist/types/shares/index.d.ts" + ], + "l2": [ + "./dist/types/l2/index.d.ts" ] } }, @@ -145,8 +153,10 @@ "dependencies": { "@ethersproject/bytes": "^5.7.0", "graphql": "^16.8.1", - "graphql-request": "^6.1.0", - "viem": "^2.0.6" + "graphql-request": "^6.1.0" + }, + "peerDependencies": { + "viem": "^2.21" }, "devDependencies": { "@jest/globals": "^29.7.0", diff --git a/packages/sdk/src/common/constants.ts b/packages/sdk/src/common/constants.ts index b81e29a9..d96e60f6 100644 --- a/packages/sdk/src/common/constants.ts +++ b/packages/sdk/src/common/constants.ts @@ -1,11 +1,18 @@ import { type Address, type Chain } from 'viem'; -import { goerli, mainnet, holesky, sepolia } from 'viem/chains'; +import { + goerli, + mainnet, + holesky, + sepolia, + optimismSepolia, +} from 'viem/chains'; export enum CHAINS { Goerli = 5, Mainnet = 1, Holesky = 17000, Sepolia = 11155111, + OptimismSepolia = 11155420, } export const APPROX_BLOCKS_BY_DAY = 7600n; @@ -15,6 +22,7 @@ export const SUPPORTED_CHAINS: CHAINS[] = [ CHAINS.Mainnet, CHAINS.Holesky, CHAINS.Sepolia, + CHAINS.OptimismSepolia, ]; export const SUBMIT_EXTRA_GAS_TRANSACTION_RATIO = 1.05; @@ -22,12 +30,13 @@ export const GAS_TRANSACTION_RATIO_PRECISION = 10 ** 7; export const ESTIMATE_ACCOUNT = '0x87c0e047F4e4D3e289A56a36570D4CB957A37Ef1'; export const LIDO_LOCATOR_BY_CHAIN: { - [key in CHAINS]: Address; + [key in CHAINS]: Address | null; } = { [CHAINS.Mainnet]: '0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb', [CHAINS.Goerli]: '0x1eDf09b5023DC86737b59dE68a8130De878984f5', [CHAINS.Holesky]: '0x28FAB2059C713A7F9D8c86Db49f9bb0e96Af1ef8', [CHAINS.Sepolia]: '0x8f6254332f69557A72b0DA2D5F0Bc07d4CA991E7', + [CHAINS.OptimismSepolia]: null, }; export const SUBRGRAPH_ID_BY_CHAIN: { @@ -37,6 +46,7 @@ export const SUBRGRAPH_ID_BY_CHAIN: { [CHAINS.Goerli]: 'QmeDfGTuNbSoZ71zi3Ch4WNRbzALfiFPnJMYUFPinLiFNa', [CHAINS.Holesky]: null, [CHAINS.Sepolia]: null, + [CHAINS.OptimismSepolia]: null, }; export const EARLIEST_TOKEN_REBASED_EVENT: { @@ -46,6 +56,7 @@ export const EARLIEST_TOKEN_REBASED_EVENT: { [CHAINS.Goerli]: 8712039n, [CHAINS.Holesky]: 52174n, [CHAINS.Sepolia]: 5434668n, + [CHAINS.OptimismSepolia]: 0n, } as const; export const LIDO_TOKENS = { @@ -73,6 +84,21 @@ export const enum LIDO_CONTRACT_NAMES { wsteth = 'wsteth', } +export const enum LIDO_L2_CONTRACT_NAMES { + wsteth = 'wsteth', + steth = 'steth', +} + +export const LIDO_L2_CONTRACT_ADDRESSES: Record< + number, + Record +> = { + [CHAINS.OptimismSepolia]: { + wsteth: '0x24B47cd3A74f1799b32B2de11073764Cb1bb318B', + steth: '0xf49d208b5c7b10415c7beafe9e656f2df9edfe3b', + }, +} as const; + export const CONTRACTS_BY_TOKENS = { [LIDO_TOKENS.steth]: LIDO_CONTRACT_NAMES.lido, [LIDO_TOKENS.wsteth]: LIDO_CONTRACT_NAMES.wsteth, @@ -110,6 +136,7 @@ export const VIEM_CHAINS: { [key in CHAINS]: Chain } = { [CHAINS.Goerli]: goerli, [CHAINS.Holesky]: holesky, [CHAINS.Sepolia]: sepolia, + [CHAINS.OptimismSepolia]: optimismSepolia, }; export const WQ_API_URLS: { [key in CHAINS]: string | null } = { @@ -117,4 +144,5 @@ export const WQ_API_URLS: { [key in CHAINS]: string | null } = { [CHAINS.Goerli]: 'https://wq-api.testnet.fi', [CHAINS.Holesky]: 'https://wq-api-holesky.testnet.fi', [CHAINS.Sepolia]: null, + [CHAINS.OptimismSepolia]: null, }; diff --git a/packages/sdk/src/core/abi/wq.ts b/packages/sdk/src/core/abi/wq.ts index d24e641b..ad0503f0 100644 --- a/packages/sdk/src/core/abi/wq.ts +++ b/packages/sdk/src/core/abi/wq.ts @@ -1,4 +1,4 @@ -export const wqAbi = [ +export const wqWstethAddressAbi = [ { inputs: [], name: 'WSTETH', diff --git a/packages/sdk/src/core/core.ts b/packages/sdk/src/core/core.ts index c471b65c..cb73b325 100644 --- a/packages/sdk/src/core/core.ts +++ b/packages/sdk/src/core/core.ts @@ -37,10 +37,12 @@ import { SUBRGRAPH_ID_BY_CHAIN, APPROX_SECONDS_PER_BLOCK, NOOP, + LIDO_L2_CONTRACT_NAMES, + LIDO_L2_CONTRACT_ADDRESSES, } from '../common/constants.js'; import { LidoLocatorAbi } from './abi/lidoLocator.js'; -import { wqAbi } from './abi/wq.js'; +import { wqWstethAddressAbi } from './abi/wq.js'; import type { LidoSDKCoreProps, PermitSignature, @@ -57,6 +59,7 @@ import type { import { TransactionCallbackStage } from './types.js'; import { permitAbi } from './abi/permit.js'; import { LidoSDKCacheable } from '../common/class-primitives/cacheable.js'; +import { readContract } from 'viem/actions'; export default class LidoSDKCore extends LidoSDKCacheable { public static readonly INFINITY_DEADLINE_VALUE = maxUint256; @@ -170,7 +173,13 @@ export default class LidoSDKCore extends LidoSDKCacheable { @Logger('Contracts:') @Cache(30 * 60 * 1000, ['chain.id']) public contractAddressLidoLocator(): Address { - return LIDO_LOCATOR_BY_CHAIN[this.chain.id as CHAINS]; + const locator = LIDO_LOCATOR_BY_CHAIN[this.chain.id as CHAINS]; + invariant( + locator, + `Lido Ethereum Contacts are not supported on ${this.chain.name}(${this.chain.id})`, + ERROR_CODE.NOT_SUPPORTED, + ); + return locator; } @Logger('Contracts:') @@ -186,18 +195,6 @@ export default class LidoSDKCore extends LidoSDKCacheable { }); } - @Logger('Contracts:') - @Cache(30 * 60 * 1000, ['chain.id']) - private getContractWQ( - address: Address, - ): GetContractReturnType { - return getContract({ - address, - abi: wqAbi, - client: this.rpcProvider, - }); - } - // PERMIT @Logger('Permit:') public async signPermit(props: SignPermitProps): Promise { @@ -360,7 +357,7 @@ export default class LidoSDKCore extends LidoSDKCacheable { // eth_getCode returns hex string of bytecode at address // for accounts it's "0x" // for contract it's potentially very long hex (can't be safely&quickly parsed) - const result = await this.rpcProvider.getBytecode({ address: address }); + const result = await this.rpcProvider.getCode({ address: address }); return result ? result !== '0x' : false; } @@ -377,8 +374,12 @@ export default class LidoSDKCore extends LidoSDKCacheable { const lidoLocator = this.getContractLidoLocator(); if (contract === 'wsteth') { const withdrawalQueue = await lidoLocator.read.withdrawalQueue(); - const contract = this.getContractWQ(withdrawalQueue); - const wstethAddress = await contract.read.WSTETH(); + + const wstethAddress = await readContract(this.rpcProvider, { + abi: wqWstethAddressAbi, + address: withdrawalQueue, + functionName: 'WSTETH', + }); return wstethAddress; } else { @@ -386,6 +387,24 @@ export default class LidoSDKCore extends LidoSDKCacheable { } } + @Logger('Utils:') + @Cache(30 * 60 * 1000, ['chain.id']) + public getL2ContractAddress(contract: LIDO_L2_CONTRACT_NAMES): Address { + const chainConfig = LIDO_L2_CONTRACT_ADDRESSES[this.chain.id]; + invariant( + chainConfig, + `Lido L2 contracts are not supported for ${this.chain.name}(${this.chain.id})`, + ERROR_CODE.NOT_SUPPORTED, + ); + const address = chainConfig[contract]; + invariant( + address, + `Lido L2 on ${this.chain.name}(${this.chain.id}) does not have ${contract} contract`, + ERROR_CODE.NOT_SUPPORTED, + ); + return address; + } + @Logger('Utils:') @Cache(30 * 60 * 1000, ['chain.id']) public getSubgraphId(): string | null { diff --git a/packages/sdk/src/erc20/erc20.ts b/packages/sdk/src/erc20/erc20.ts index 135a2328..52f0c58d 100644 --- a/packages/sdk/src/erc20/erc20.ts +++ b/packages/sdk/src/erc20/erc20.ts @@ -121,7 +121,9 @@ export abstract class AbstractLidoSDKErc20 extends LidoSDKModule { const contract = await this.getContract(); return isTransferFrom - ? contract.simulate.transferFrom([from, to, amount], { account }) + ? contract.simulate.transferFrom([from, to, amount], { + account, + }) : contract.simulate.transfer([to, amount], { account }); } @@ -217,7 +219,9 @@ export abstract class AbstractLidoSDKErc20 extends LidoSDKModule { public async simulateApprove(props: NoCallback) { const { account, amount, to } = await this.parseProps(props); const contract = await this.getContract(); - return contract.simulate.approve([to, amount], { account }); + return contract.simulate.approve([to, amount], { + account, + }); } @Logger('Views:') @@ -239,35 +243,51 @@ export abstract class AbstractLidoSDKErc20 extends LidoSDKModule { decimals: number; domainSeparator: Hash; }> { - const contract = { address: await this.contractAddress(), abi: erc20abi }; - const [decimals, name, symbol, domainSeparator] = - await this.core.rpcProvider.multicall({ - allowFailure: false, - contracts: [ - { - ...contract, - functionName: 'decimals', - }, - { - ...contract, - functionName: 'name', - }, - { - ...contract, - functionName: 'symbol', - }, - { - ...contract, - functionName: 'DOMAIN_SEPARATOR', - }, - ] as const, - }); - return { - decimals, - name, - symbol, - domainSeparator, - }; + if (this.core.rpcProvider.multicall) { + const contract = { address: await this.contractAddress(), abi: erc20abi }; + const [decimals, name, symbol, domainSeparator] = + await this.core.rpcProvider.multicall({ + allowFailure: false, + contracts: [ + { + ...contract, + functionName: 'decimals', + }, + { + ...contract, + functionName: 'name', + }, + { + ...contract, + functionName: 'symbol', + }, + { + ...contract, + functionName: 'DOMAIN_SEPARATOR', + }, + ] as const, + }); + return { + decimals, + name, + symbol, + domainSeparator, + }; + } else { + const contract = await this.getContract(); + const [decimals, name, symbol, domainSeparator] = await Promise.all([ + contract.read.decimals(), + contract.read.name(), + contract.read.symbol(), + contract.read.DOMAIN_SEPARATOR(), + ]); + return { + decimals, + name, + symbol, + domainSeparator, + }; + } } @Logger('Views:') diff --git a/packages/sdk/src/erc20/index.ts b/packages/sdk/src/erc20/index.ts index 468bc773..17498525 100644 --- a/packages/sdk/src/erc20/index.ts +++ b/packages/sdk/src/erc20/index.ts @@ -1,3 +1,4 @@ +export { erc20abi } from './abi/erc20abi.js'; export { AbstractLidoSDKErc20 } from './erc20.js'; export { LidoSDKstETH } from './steth.js'; export { LidoSDKwstETH } from './wsteth.js'; diff --git a/packages/sdk/src/erc20/types.ts b/packages/sdk/src/erc20/types.ts index d0fa0c04..3421020d 100644 --- a/packages/sdk/src/erc20/types.ts +++ b/packages/sdk/src/erc20/types.ts @@ -9,7 +9,7 @@ import { export type InnerTransactionProps = Required; export type ParsedTransactionProps = - Omit & { + Omit & { callback: NonNullable; account: JsonRpcAccount; } & (TProps extends { amount: EtherValue } ? { amount: bigint } : object); diff --git a/packages/sdk/src/erc20/wsteth.ts b/packages/sdk/src/erc20/wsteth.ts index 75723a43..e278e34a 100644 --- a/packages/sdk/src/erc20/wsteth.ts +++ b/packages/sdk/src/erc20/wsteth.ts @@ -12,6 +12,8 @@ export class LidoSDKwstETH extends AbstractLidoSDKErc20 { return this.core.getContractAddress(LIDO_CONTRACT_NAMES.wsteth); } + @Logger('Contracts:') + @Cache(30 * 60 * 1000, ['core.chain.id']) public override async erc721Domain(): Promise<{ name: string; version: string; diff --git a/packages/sdk/src/events/index.ts b/packages/sdk/src/events/index.ts index df5449fa..86bde4bf 100644 --- a/packages/sdk/src/events/index.ts +++ b/packages/sdk/src/events/index.ts @@ -1,2 +1,3 @@ +export { StethEventsAbi } from './abi/stethEvents.js'; export { LidoSDKEvents } from './events.js'; export * from './types.js'; diff --git a/packages/sdk/src/l2/abi/brigedWsteth.ts b/packages/sdk/src/l2/abi/brigedWsteth.ts new file mode 100644 index 00000000..c54530f8 --- /dev/null +++ b/packages/sdk/src/l2/abi/brigedWsteth.ts @@ -0,0 +1,265 @@ +export const bridgedWstethAbi = [ + { inputs: [], name: 'ErrorAccountIsZeroAddress', type: 'error' }, + { inputs: [], name: 'ErrorDeadlineExpired', type: 'error' }, + { inputs: [], name: 'ErrorInvalidSignature', type: 'error' }, + { inputs: [], name: 'ErrorMetadataIsAlreadyInitialized', type: 'error' }, + { inputs: [], name: 'ErrorMetadataIsNotInitialized', type: 'error' }, + { inputs: [], name: 'ErrorNameIsEmpty', type: 'error' }, + { inputs: [], name: 'ErrorNotBridge', type: 'error' }, + { inputs: [], name: 'ErrorNotEnoughAllowance', type: 'error' }, + { inputs: [], name: 'ErrorNotEnoughBalance', type: 'error' }, + { inputs: [], name: 'ErrorSymbolIsEmpty', type: 'error' }, + { inputs: [], name: 'ErrorZeroAddressBridge', type: 'error' }, + { inputs: [], name: 'ErrorZeroDecimals', type: 'error' }, + { inputs: [], name: 'InvalidContractVersionIncrement', type: 'error' }, + { inputs: [], name: 'NonZeroContractVersionOnInit', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'expected', type: 'uint256' }, + { internalType: 'uint256', name: 'received', type: 'uint256' }, + ], + name: 'UnexpectedContractVersion', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint256', + name: 'version', + type: 'uint256', + }, + ], + name: 'ContractVersionSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + inputs: [], + name: 'DOMAIN_SEPARATOR', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: '', type: 'address' }, + { internalType: 'address', name: '', type: 'address' }, + ], + name: 'allowance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'approve', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'bridge', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'bridgeBurn', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'bridgeMint', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'eip712Domain', + outputs: [ + { internalType: 'bytes1', name: 'fields', type: 'bytes1' }, + { internalType: 'string', name: 'name', type: 'string' }, + { internalType: 'string', name: 'version', type: 'string' }, + { internalType: 'uint256', name: 'chainId', type: 'uint256' }, + { internalType: 'address', name: 'verifyingContract', type: 'address' }, + { internalType: 'bytes32', name: 'salt', type: 'bytes32' }, + { internalType: 'uint256[]', name: 'extensions', type: 'uint256[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: 'name_', type: 'string' }, + { internalType: 'string', name: 'version_', type: 'string' }, + ], + name: 'finalizeUpgrade_v2', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'getContractVersion', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: 'name_', type: 'string' }, + { internalType: 'string', name: 'symbol_', type: 'string' }, + { internalType: 'string', name: 'version_', type: 'string' }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], + name: 'nonces', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner_', type: 'address' }, + { internalType: 'address', name: 'spender_', type: 'address' }, + { internalType: 'uint256', name: 'value_', type: 'uint256' }, + { internalType: 'uint256', name: 'deadline_', type: 'uint256' }, + { internalType: 'bytes', name: 'signature_', type: 'bytes' }, + ], + name: 'permit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner_', type: 'address' }, + { internalType: 'address', name: 'spender_', type: 'address' }, + { internalType: 'uint256', name: 'value_', type: 'uint256' }, + { internalType: 'uint256', name: 'deadline_', type: 'uint256' }, + { internalType: 'uint8', name: 'v_', type: 'uint8' }, + { internalType: 'bytes32', name: 'r_', type: 'bytes32' }, + { internalType: 'bytes32', name: 's_', type: 'bytes32' }, + ], + name: 'permit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'from_', type: 'address' }, + { internalType: 'address', name: 'to_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; diff --git a/packages/sdk/src/l2/abi/rebasableL2Steth.ts b/packages/sdk/src/l2/abi/rebasableL2Steth.ts new file mode 100644 index 00000000..50a48f53 --- /dev/null +++ b/packages/sdk/src/l2/abi/rebasableL2Steth.ts @@ -0,0 +1,390 @@ +export const rebasableL2StethAbi = [ + { + inputs: [ + { internalType: 'string', name: 'name_', type: 'string' }, + { internalType: 'string', name: 'symbol_', type: 'string' }, + { internalType: 'string', name: 'version_', type: 'string' }, + { internalType: 'uint8', name: 'decimals_', type: 'uint8' }, + { internalType: 'address', name: 'tokenToWrapFrom_', type: 'address' }, + { internalType: 'address', name: 'tokenRateOracle_', type: 'address' }, + { internalType: 'address', name: 'bridge_', type: 'address' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'ErrorAccountIsZeroAddress', type: 'error' }, + { inputs: [], name: 'ErrorDeadlineExpired', type: 'error' }, + { inputs: [], name: 'ErrorInvalidSignature', type: 'error' }, + { inputs: [], name: 'ErrorNameIsEmpty', type: 'error' }, + { inputs: [], name: 'ErrorNotBridge', type: 'error' }, + { inputs: [], name: 'ErrorNotEnoughAllowance', type: 'error' }, + { inputs: [], name: 'ErrorNotEnoughBalance', type: 'error' }, + { inputs: [], name: 'ErrorSymbolIsEmpty', type: 'error' }, + { inputs: [], name: 'ErrorTransferToRebasableContract', type: 'error' }, + { inputs: [], name: 'ErrorZeroAddressL2ERC20TokenBridge', type: 'error' }, + { inputs: [], name: 'ErrorZeroAddressTokenRateOracle', type: 'error' }, + { inputs: [], name: 'ErrorZeroAddressTokenToWrapFrom', type: 'error' }, + { inputs: [], name: 'ErrorZeroDecimals', type: 'error' }, + { inputs: [], name: 'ErrorZeroSharesUnwrap', type: 'error' }, + { inputs: [], name: 'ErrorZeroSharesWrap', type: 'error' }, + { inputs: [], name: 'ErrorZeroTokensUnwrap', type: 'error' }, + { inputs: [], name: 'InvalidContractVersionIncrement', type: 'error' }, + { inputs: [], name: 'NonZeroContractVersionOnInit', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'expected', type: 'uint256' }, + { internalType: 'uint256', name: 'received', type: 'uint256' }, + ], + name: 'UnexpectedContractVersion', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint256', + name: 'version', + type: 'uint256', + }, + ], + name: 'ContractVersionSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'from', type: 'address' }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'sharesValue', + type: 'uint256', + }, + ], + name: 'TransferShares', + type: 'event', + }, + { + inputs: [], + name: 'DOMAIN_SEPARATOR', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'L2_ERC20_TOKEN_BRIDGE', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_RATE_ORACLE', + outputs: [ + { internalType: 'contract ITokenRateOracle', name: '', type: 'address' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_RATE_ORACLE_DECIMALS', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_TO_WRAP_FROM', + outputs: [{ internalType: 'contract IERC20', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner', type: 'address' }, + { internalType: 'address', name: 'spender', type: 'address' }, + ], + name: 'allowance', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'spender_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'approve', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account_', type: 'address' }], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account_', type: 'address' }, + { internalType: 'uint256', name: 'tokenAmount_', type: 'uint256' }, + ], + name: 'bridgeUnwrap', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account_', type: 'address' }, + { internalType: 'uint256', name: 'sharesAmount_', type: 'uint256' }, + ], + name: 'bridgeWrap', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'eip712Domain', + outputs: [ + { internalType: 'bytes1', name: 'fields', type: 'bytes1' }, + { internalType: 'string', name: 'name', type: 'string' }, + { internalType: 'string', name: 'version', type: 'string' }, + { internalType: 'uint256', name: 'chainId', type: 'uint256' }, + { internalType: 'address', name: 'verifyingContract', type: 'address' }, + { internalType: 'bytes32', name: 'salt', type: 'bytes32' }, + { internalType: 'uint256[]', name: 'extensions', type: 'uint256[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getContractVersion', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'tokenAmount_', type: 'uint256' }, + ], + name: 'getSharesByTokens', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'sharesAmount_', type: 'uint256' }, + ], + name: 'getTokensByShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getTotalShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'string', name: 'name_', type: 'string' }, + { internalType: 'string', name: 'symbol_', type: 'string' }, + { internalType: 'string', name: 'version_', type: 'string' }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], + name: 'nonces', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner_', type: 'address' }, + { internalType: 'address', name: 'spender_', type: 'address' }, + { internalType: 'uint256', name: 'value_', type: 'uint256' }, + { internalType: 'uint256', name: 'deadline_', type: 'uint256' }, + { internalType: 'bytes', name: 'signature_', type: 'bytes' }, + ], + name: 'permit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'owner_', type: 'address' }, + { internalType: 'address', name: 'spender_', type: 'address' }, + { internalType: 'uint256', name: 'value_', type: 'uint256' }, + { internalType: 'uint256', name: 'deadline_', type: 'uint256' }, + { internalType: 'uint8', name: 'v_', type: 'uint8' }, + { internalType: 'bytes32', name: 'r_', type: 'bytes32' }, + { internalType: 'bytes32', name: 's_', type: 'bytes32' }, + ], + name: 'permit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account_', type: 'address' }], + name: 'sharesOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'from_', type: 'address' }, + { internalType: 'address', name: 'to_', type: 'address' }, + { internalType: 'uint256', name: 'amount_', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'recipient_', type: 'address' }, + { internalType: 'uint256', name: 'sharesAmount_', type: 'uint256' }, + ], + name: 'transferShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'sender_', type: 'address' }, + { internalType: 'address', name: 'recipient_', type: 'address' }, + { internalType: 'uint256', name: 'sharesAmount_', type: 'uint256' }, + ], + name: 'transferSharesFrom', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'tokenAmount_', type: 'uint256' }, + ], + name: 'unwrap', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'sharesAmount_', type: 'uint256' }, + ], + name: 'unwrapShares', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'sharesAmount_', type: 'uint256' }, + ], + name: 'wrap', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; diff --git a/packages/sdk/src/l2/index.ts b/packages/sdk/src/l2/index.ts new file mode 100644 index 00000000..f4c8c6bd --- /dev/null +++ b/packages/sdk/src/l2/index.ts @@ -0,0 +1,11 @@ +export { bridgedWstethAbi } from './abi/brigedWsteth.js'; +export { rebasableL2StethAbi } from './abi/rebasableL2Steth.js'; +export { LidoSDKL2 } from './l2.js'; +export { LidoSDKL2Wsteth, LidoSDKL2Steth } from './tokens.js'; + +export type { + SharesTransferProps, + UnwrapResults, + WrapProps, + WrapResults, +} from './types.js'; diff --git a/packages/sdk/src/l2/l2.ts b/packages/sdk/src/l2/l2.ts new file mode 100644 index 00000000..174ee5a7 --- /dev/null +++ b/packages/sdk/src/l2/l2.ts @@ -0,0 +1,291 @@ +import { LidoSDKModule } from '../common/class-primitives/sdk-module.js'; +import type { AccountValue, LidoSDKCommonProps } from '../core/types.js'; +import { LidoSDKL2Steth, LidoSDKL2Wsteth } from './tokens.js'; + +import { + getContract, + encodeFunctionData, + decodeEventLog, + isAddressEqual, + getAbiItem, + toEventHash, + type GetContractReturnType, + type WalletClient, + type Address, + type WriteContractParameters, + type TransactionReceipt, +} from 'viem'; + +import { LIDO_L2_CONTRACT_NAMES, NOOP } from '../common/constants.js'; +import { Cache, Logger, ErrorHandler } from '../common/decorators/index.js'; + +import { rebasableL2StethAbi } from './abi/rebasableL2Steth.js'; +import { parseValue } from '../common/utils/parse-value.js'; +import { + UnwrapResults, + WrapInnerProps, + WrapProps, + WrapPropsWithoutCallback, + WrapResults, +} from './types.js'; +import { PopulatedTransaction, TransactionResult } from '../core/types.js'; +import { invariant, ERROR_CODE } from '../common/index.js'; + +export class LidoSDKL2 extends LidoSDKModule { + private static TRANSFER_SIGNATURE = toEventHash( + getAbiItem({ abi: rebasableL2StethAbi, name: 'Transfer' }), + ); + + public readonly wsteth: LidoSDKL2Wsteth; + public readonly steth: LidoSDKL2Steth; + + constructor(props: LidoSDKCommonProps) { + super(props); + this.wsteth = new LidoSDKL2Wsteth({ core: this.core }); + this.steth = new LidoSDKL2Steth({ core: this.core }); + } + + @Logger('Contracts:') + @Cache(30 * 60 * 1000, ['core.chain.id']) + public async contractAddress(): Promise
{ + return this.core.getL2ContractAddress(LIDO_L2_CONTRACT_NAMES.steth); + } + + @Logger('Contracts:') + @Cache(30 * 60 * 1000, ['core.chain.id']) + public async getContract(): Promise< + GetContractReturnType + > { + const address = await this.contractAddress(); + return getContract({ + address, + abi: rebasableL2StethAbi, + client: { + public: this.core.rpcProvider, + wallet: this.core.web3Provider as WalletClient, + }, + }); + } + + // Wrap wstETH to stETH + + @Logger('Call:') + @ErrorHandler() + public async approveWstethForWrap( + props: WrapProps, + ): Promise { + const stethAddress = await this.contractAddress(); + return this.wsteth.approve({ + ...props, + amount: props.value, + to: stethAddress, + }); + } + + @Logger('Utils:') + @ErrorHandler() + public async getWstethForWrapAllowance( + account?: AccountValue, + ): Promise { + const stethAddress = await this.contractAddress(); + return this.wsteth.allowance({ account, to: stethAddress }); + } + + @Logger('Call:') + @ErrorHandler() + public async wrapWstethToSteth( + props: WrapProps, + ): Promise> { + this.core.useWeb3Provider(); + const { account, callback, value, ...rest } = await this.parseProps(props); + const contract = await this.getContract(); + + return this.core.performTransaction({ + ...rest, + account, + callback, + getGasLimit: (options) => contract.estimateGas.wrap([value], options), + sendTransaction: (options) => contract.write.wrap([value], options), + decodeResult: (receipt) => + this.wrapWstethToStethParseEvents(receipt, account.address), + }); + } + + @Logger('Utils:') + public async wrapWstethToStethPopulateTx( + props: WrapPropsWithoutCallback, + ): Promise { + const { value, account } = await this.parseProps(props); + const address = await this.contractAddress(); + + return { + to: address, + from: account.address, + data: encodeFunctionData({ + abi: rebasableL2StethAbi, + functionName: 'wrap', + args: [value], + }), + }; + } + + @Logger('Utils:') + private async wrapWstethToStethParseEvents( + receipt: TransactionReceipt, + address: Address, + ): Promise { + let stethReceived: bigint | undefined; + let wstethWrapped: bigint | undefined; + for (const log of receipt.logs) { + // skips non-relevant events + if (log.topics[0] !== LidoSDKL2.TRANSFER_SIGNATURE) continue; + const parsedLog = decodeEventLog({ + abi: rebasableL2StethAbi, + strict: true, + eventName: 'Transfer', + data: log.data, + topics: log.topics, + }); + if (isAddressEqual(parsedLog.args.from, address)) { + wstethWrapped = parsedLog.args.value; + } else if (isAddressEqual(parsedLog.args.to, address)) { + stethReceived = parsedLog.args.value; + } + } + invariant( + stethReceived, + 'could not find Transfer event in wrap transaction', + ERROR_CODE.TRANSACTION_ERROR, + ); + invariant( + wstethWrapped, + 'could not find Transfer event in wrap transaction', + ERROR_CODE.TRANSACTION_ERROR, + ); + return { + stethReceived, + wstethWrapped, + }; + } + + @Logger('Call:') + @ErrorHandler() + public async wrapWstethToStethSimulateTx( + props: WrapPropsWithoutCallback, + ): Promise { + const { value, account } = await this.parseProps(props); + const contract = await this.getContract(); + + const { request } = await contract.simulate.wrap([value], { + account, + }); + + return request; + } + + // unwrap stETH to wstETH + + @Logger('Call:') + @ErrorHandler() + public async unwrap( + props: WrapProps, + ): Promise> { + this.core.useWeb3Provider(); + const { account, callback, value, ...rest } = await this.parseProps(props); + const contract = await this.getContract(); + + return this.core.performTransaction({ + ...rest, + account, + callback, + getGasLimit: (options) => contract.estimateGas.unwrap([value], options), + sendTransaction: (options) => contract.write.unwrap([value], options), + decodeResult: (receipt) => + this.unwrapParseEvents(receipt, account.address), + }); + } + + @Logger('Utils:') + public async unwrapPopulateTx( + props: Omit, + ): Promise { + const { value, account } = await this.parseProps(props); + const to = await this.contractAddress(); + + return { + to, + from: account.address, + data: encodeFunctionData({ + abi: rebasableL2StethAbi, + functionName: 'unwrap', + args: [value], + }), + }; + } + + @Logger('Call:') + @ErrorHandler() + public async unwrapSimulateTx( + props: Omit, + ): Promise { + const { value, account } = await this.parseProps(props); + const contract = await this.getContract(); + + const { request } = await contract.simulate.unwrap([value], { + account, + }); + + return request; + } + + @Logger('Utils:') + private async unwrapParseEvents( + receipt: TransactionReceipt, + address: Address, + ): Promise { + let stethUnwrapped: bigint | undefined; + let wstethReceived: bigint | undefined; + for (const log of receipt.logs) { + // skips non-relevant events + if (log.topics[0] !== LidoSDKL2.TRANSFER_SIGNATURE) continue; + const parsedLog = decodeEventLog({ + abi: rebasableL2StethAbi, + strict: true, + topics: log.topics, + data: log.data, + eventName: 'Transfer', + }); + if (isAddressEqual(parsedLog.args.from, address)) { + stethUnwrapped = parsedLog.args.value; + } else if (isAddressEqual(parsedLog.args.to, address)) { + wstethReceived = parsedLog.args.value; + } + } + invariant( + stethUnwrapped, + 'could not find Transfer event in unwrap transaction', + ERROR_CODE.TRANSACTION_ERROR, + ); + invariant( + wstethReceived, + 'could not find Transfer event in unwrap transaction', + ERROR_CODE.TRANSACTION_ERROR, + ); + return { + stethUnwrapped, + wstethReceived, + }; + } + + // Utils + + @Logger('Utils:') + private async parseProps(props: WrapProps): Promise { + return { + ...props, + account: await this.core.useAccount(props.account), + value: parseValue(props.value), + callback: props.callback ?? NOOP, + }; + } +} diff --git a/packages/sdk/src/l2/tokens.ts b/packages/sdk/src/l2/tokens.ts new file mode 100644 index 00000000..57e7039d --- /dev/null +++ b/packages/sdk/src/l2/tokens.ts @@ -0,0 +1,258 @@ +/* eslint-disable sonarjs/no-identical-functions */ +import { + getContract, + type GetContractReturnType, + type WalletClient, + type Address, + encodeFunctionData, + Hash, +} from 'viem'; + +import { LIDO_L2_CONTRACT_NAMES, NOOP } from '../common/constants.js'; +import { parseValue } from '../common/utils/parse-value.js'; +import { Cache, ErrorHandler, Logger } from '../common/decorators/index.js'; +import { AbstractLidoSDKErc20 } from '../erc20/erc20.js'; + +import { rebasableL2StethAbi } from './abi/rebasableL2Steth.js'; +import { bridgedWstethAbi } from './abi/brigedWsteth.js'; + +import type { + AccountValue, + EtherValue, + NoCallback, + TransactionOptions, + TransactionResult, +} from '../core/types.js'; +import type { SharesTransferProps } from './types.js'; + +export class LidoSDKL2Wsteth extends AbstractLidoSDKErc20 { + @Logger('Contracts:') + @Cache(30 * 60 * 1000, ['core.chain.id']) + public override async contractAddress(): Promise
{ + return this.core.getL2ContractAddress(LIDO_L2_CONTRACT_NAMES.wsteth); + } + + @Logger('Contracts:') + @Cache(30 * 60 * 1000, ['core.chain.id']) + public async getL2Contract(): Promise< + GetContractReturnType + > { + const address = await this.contractAddress(); + return getContract({ + address, + abi: bridgedWstethAbi, + client: { + public: this.core.rpcProvider, + wallet: this.core.web3Provider as WalletClient, + }, + }); + } + + @Cache(30 * 60 * 1000, ['core.chain.id']) + public async contractVersion(): Promise { + const contract = await this.getL2Contract(); + return contract.read.getContractVersion(); + } + + @Cache(30 * 60 * 1000, ['core.chain.id']) + public override async erc721Domain(): Promise<{ + name: string; + version: string; + chainId: bigint; + verifyingContract: `0x${string}`; + }> { + const { name } = await this.erc20Metadata(); + return { + name: name, + version: (await this.contractVersion()).toString(), + chainId: BigInt(this.core.chain.id), + verifyingContract: await this.contractAddress(), + }; + } +} + +export class LidoSDKL2Steth extends AbstractLidoSDKErc20 { + public override async contractAddress(): Promise
{ + return this.core.getL2ContractAddress(LIDO_L2_CONTRACT_NAMES.steth); + } + + @Logger('Contracts:') + @Cache(30 * 60 * 1000, ['core.chain.id']) + public async getL2Contract(): Promise< + GetContractReturnType + > { + const address = await this.contractAddress(); + return getContract({ + address, + abi: rebasableL2StethAbi, + client: { + public: this.core.rpcProvider, + wallet: this.core.web3Provider as WalletClient, + }, + }); + } + + @Cache(30 * 60 * 1000, ['core.chain.id']) + public async contractVersion(): Promise { + const contract = await this.getL2Contract(); + return contract.read.getContractVersion(); + } + + @Cache(30 * 60 * 1000, ['core.chain.id']) + public override async erc721Domain(): Promise<{ + name: string; + version: string; + chainId: bigint; + verifyingContract: Address; + fields: Hash; + salt: Hash; + extensions: readonly bigint[]; + }> { + const contract = await this.getL2Contract(); + const [ + fields, + name, + version, + chainId, + verifyingContract, + salt, + extensions, + ] = await contract.read.eip712Domain(); + return { + fields, + name, + version, + chainId, + verifyingContract, + salt, + extensions, + }; + } + + @Logger('Balances:') + @ErrorHandler() + public async balanceShares(address?: AccountValue): Promise { + const contract = await this.getL2Contract(); + const account = await this.core.useAccount(address); + return contract.read.sharesOf([account.address]); + } + + // convert + @Logger('Views:') + @ErrorHandler() + public async convertToShares(stethAmount: EtherValue): Promise { + const amount = parseValue(stethAmount); + const contract = await this.getL2Contract(); + return contract.read.getSharesByTokens([amount]); + } + + // convert + @Logger('Views:') + @ErrorHandler() + public async convertToSteth(sharesAmount: EtherValue): Promise { + const amount = parseValue(sharesAmount); + const contract = await this.getL2Contract(); + return contract.read.getTokensByShares([amount]); + } + + // convert + @Logger('Views:') + @ErrorHandler() + public async totalShares(): Promise { + const contract = await this.getL2Contract(); + return contract.read.getTotalShares(); + } + + // TransferShares + // Transfer + + @Logger('Call:') + @ErrorHandler() + public async transferShares({ + account: accountProp, + to, + amount: _amount, + callback = NOOP, + from: _from, + ...rest + }: SharesTransferProps): Promise { + this.core.useWeb3Provider(); + const account = await this.core.useAccount(accountProp); + const from = _from ?? account.address; + const amount = parseValue(_amount); + + const isTransferFrom = from !== account.address; + const contract = await this.getL2Contract(); + + const getGasLimit = async (overrides: TransactionOptions) => + isTransferFrom + ? contract.estimateGas.transferSharesFrom([from, to, amount], overrides) + : contract.estimateGas.transferShares([to, amount], overrides); + + const sendTransaction = async (overrides: TransactionOptions) => + isTransferFrom + ? contract.write.transferSharesFrom([from, to, amount], overrides) + : contract.write.transferShares([to, amount], overrides); + + return this.core.performTransaction({ + ...rest, + account, + callback, + getGasLimit, + sendTransaction, + }); + } + + @Logger('Utils:') + @ErrorHandler() + public async populateTransferShares({ + account: accountProp, + to, + amount: _amount, + from: _from, + }: NoCallback) { + const account = await this.core.useAccount(accountProp); + const amount = parseValue(_amount); + const from = _from ?? account.address; + const address = await this.contractAddress(); + const isTransferFrom = from !== account.address; + + return { + to: address, + from: account.address, + data: isTransferFrom + ? encodeFunctionData({ + abi: rebasableL2StethAbi, + functionName: 'transferSharesFrom', + args: [from, to, amount], + }) + : encodeFunctionData({ + abi: rebasableL2StethAbi, + functionName: 'transferShares', + args: [to, amount], + }), + }; + } + + @Logger('Utils:') + @ErrorHandler() + public async simulateTransferShares({ + account: _account, + to, + amount: _amount, + from: _from, + }: NoCallback) { + const amount = parseValue(_amount); + const account = await this.core.useAccount(_account); + const from = _from ?? account.address; + const contract = await this.getL2Contract(); + const isTransferFrom = from !== account.address; + return isTransferFrom + ? contract.simulate.transferSharesFrom([from, to, amount], { + account, + }) + : contract.simulate.transferShares([to, amount], { + account, + }); + } +} diff --git a/packages/sdk/src/l2/types.ts b/packages/sdk/src/l2/types.ts new file mode 100644 index 00000000..d10f2c61 --- /dev/null +++ b/packages/sdk/src/l2/types.ts @@ -0,0 +1,32 @@ +import type { Address } from 'viem'; +import type { CommonTransactionProps, EtherValue } from '../core/types.js'; +import type { FormattedTransactionRequest, JsonRpcAccount } from 'viem'; + +export type SharesTransferProps = CommonTransactionProps & { + from?: Address; + to: Address; + amount: EtherValue; +}; + +export type WrapProps = CommonTransactionProps & { + value: EtherValue; +}; + +export type WrapResults = { + stethReceived: bigint; + wstethWrapped: bigint; +}; + +export type UnwrapResults = { + stethUnwrapped: bigint; + wstethReceived: bigint; +}; + +export type WrapPropsWithoutCallback = Omit; + +export type WrapInnerProps = Omit & { + value: bigint; + account: JsonRpcAccount; +}; + +export type PopulatedTx = Omit; diff --git a/packages/sdk/src/sdk.ts b/packages/sdk/src/sdk.ts index 3caf4c52..5420c5a4 100644 --- a/packages/sdk/src/sdk.ts +++ b/packages/sdk/src/sdk.ts @@ -11,6 +11,7 @@ import { LidoSDKRewards } from './rewards/index.js'; import { LidoSDKShares } from './shares/shares.js'; import { version } from './version.js'; +import { LidoSDKL2 } from './l2/l2.js'; export class LidoSDK { readonly core: LidoSDKCore; @@ -24,6 +25,7 @@ export class LidoSDK { readonly events: LidoSDKEvents; readonly statistics: LidoSDKStatistics; readonly rewards: LidoSDKRewards; + readonly l2: LidoSDKL2; constructor(props: LidoSDKCoreProps) { // Core functionality @@ -46,5 +48,7 @@ export class LidoSDK { this.statistics = new LidoSDKStatistics({ ...props, core }); // Rewards functionality this.rewards = new LidoSDKRewards({ ...props, core }); + // L2 functionality + this.l2 = new LidoSDKL2({ ...props, core }); } } diff --git a/packages/sdk/src/shares/index.ts b/packages/sdk/src/shares/index.ts index 3861cdb8..ca4f495f 100644 --- a/packages/sdk/src/shares/index.ts +++ b/packages/sdk/src/shares/index.ts @@ -1,2 +1,3 @@ +export { stethSharesAbi } from './abi/steth-shares-abi.js'; export { LidoSDKShares } from './shares.js'; export type { SharesTransferProps } from './types.js'; diff --git a/packages/sdk/src/shares/shares.ts b/packages/sdk/src/shares/shares.ts index d3f46a00..677e0ce9 100644 --- a/packages/sdk/src/shares/shares.ts +++ b/packages/sdk/src/shares/shares.ts @@ -177,20 +177,28 @@ export class LidoSDKShares extends LidoSDKModule { address: sharesContract.address, abi: sharesContract.abi, }; - const [totalShares, totalEther] = await this.core.rpcProvider.multicall({ - allowFailure: false, - contracts: [ - { - ...contract, - functionName: 'getTotalShares', - }, - { - ...contract, - functionName: 'getTotalPooledEther', - }, - ] as const, - }); - return { totalEther, totalShares }; + if (this.core.rpcProvider.multicall) { + const [totalShares, totalEther] = await this.core.rpcProvider.multicall({ + allowFailure: false, + contracts: [ + { + ...contract, + functionName: 'getTotalShares', + }, + { + ...contract, + functionName: 'getTotalPooledEther', + }, + ] as const, + }); + return { totalEther, totalShares }; + } else { + const [totalShares, totalEther] = await Promise.all([ + sharesContract.read.getTotalShares(), + sharesContract.read.getTotalPooledEther(), + ]); + return { totalEther, totalShares }; + } } @Logger('Views:') diff --git a/packages/sdk/src/stake/index.ts b/packages/sdk/src/stake/index.ts index 61793c44..62531b9d 100644 --- a/packages/sdk/src/stake/index.ts +++ b/packages/sdk/src/stake/index.ts @@ -1,2 +1,3 @@ +export { StethAbi } from './abi/steth.js'; export { LidoSDKStake } from './stake.js'; export type { StakeProps, StakeEncodeDataProps } from './types.js'; diff --git a/packages/sdk/src/stake/types.ts b/packages/sdk/src/stake/types.ts index 11d34545..be9f00f7 100644 --- a/packages/sdk/src/stake/types.ts +++ b/packages/sdk/src/stake/types.ts @@ -7,7 +7,7 @@ export type StakeProps = CommonTransactionProps & { referralAddress?: Address; }; -export type StakeInnerProps = CommonTransactionProps & { +export type StakeInnerProps = Omit & { value: bigint; referralAddress: Address; account: JsonRpcAccount; diff --git a/packages/sdk/src/unsteth/index.ts b/packages/sdk/src/unsteth/index.ts index 4d0f8a4b..c36ca1f2 100644 --- a/packages/sdk/src/unsteth/index.ts +++ b/packages/sdk/src/unsteth/index.ts @@ -1,3 +1,4 @@ +export { unstethAbi } from './abi/unsteth-abi.js'; export { LidoSDKUnstETH } from './unsteth.js'; export type { UnstethNFT, diff --git a/packages/sdk/src/unsteth/unsteth.ts b/packages/sdk/src/unsteth/unsteth.ts index 4a0ddfaa..b540161d 100644 --- a/packages/sdk/src/unsteth/unsteth.ts +++ b/packages/sdk/src/unsteth/unsteth.ts @@ -281,36 +281,52 @@ export class LidoSDKUnstETH extends LidoSDKModule { @ErrorHandler() @Cache(30 * 60 * 1000, ['core.chain.id']) public async getContractMetadata() { - const address = await this.contractAddress(); - const common = { abi: unstethAbi, address } as const; - const [name, version, symbol, baseURI] = - await this.core.rpcProvider.multicall({ - allowFailure: false, - contracts: [ - { - ...common, - functionName: 'name', - }, - { - ...common, - functionName: 'getContractVersion', - }, - { - ...common, - functionName: 'symbol', - }, - { - ...common, - functionName: 'getBaseURI', - }, - ] as const, - }); - return { - name, - version, - symbol, - baseURI, - }; + if (this.core.rpcProvider.multicall) { + const address = await this.contractAddress(); + const common = { abi: unstethAbi, address } as const; + const [name, version, symbol, baseURI] = + await this.core.rpcProvider.multicall({ + allowFailure: false, + contracts: [ + { + ...common, + functionName: 'name', + }, + { + ...common, + functionName: 'getContractVersion', + }, + { + ...common, + functionName: 'symbol', + }, + { + ...common, + functionName: 'getBaseURI', + }, + ] as const, + }); + return { + name, + version, + symbol, + baseURI, + }; + } else { + const contract = await this.getContract(); + const [name, version, symbol, baseURI] = await Promise.all([ + contract.read.name(), + contract.read.getContractVersion(), + contract.read.symbol(), + contract.read.getBaseURI(), + ]); + return { + name, + version, + symbol, + baseURI, + }; + } } @Logger('Views:') diff --git a/packages/sdk/src/withdraw/index.ts b/packages/sdk/src/withdraw/index.ts index 5b2ce111..54a9e2e0 100644 --- a/packages/sdk/src/withdraw/index.ts +++ b/packages/sdk/src/withdraw/index.ts @@ -1,3 +1,4 @@ +export { WithdrawalQueueAbi } from './abi/withdrawalQueue.js'; export { LidoSDKWithdraw } from './withdraw.js'; export type { ClaimRequestsProps, diff --git a/packages/sdk/src/wrap/index.ts b/packages/sdk/src/wrap/index.ts index fe4d762b..8f666594 100644 --- a/packages/sdk/src/wrap/index.ts +++ b/packages/sdk/src/wrap/index.ts @@ -1,2 +1,3 @@ +export { abi as WstethABI } from './abi/wsteth.js'; export { LidoSDKWrap } from './wrap.js'; export type { WrapProps, WrapPropsWithoutCallback } from './types.js'; diff --git a/playground/components/layout/header/headerWallet.tsx b/playground/components/layout/header/headerWallet.tsx index 1bd09c0b..b4526ba8 100644 --- a/playground/components/layout/header/headerWallet.tsx +++ b/playground/components/layout/header/headerWallet.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { CHAINS, getChainColor } from '@lido-sdk/constants'; +import { getChainColor } from '@lido-sdk/constants'; import { useWeb3 } from 'reef-knot/web3-react'; import { ThemeToggler } from '@lidofinance/lido-ui'; @@ -9,15 +9,27 @@ import WalletConnect from 'components/layout/header/walletConnect'; import { HeaderWalletChainStyle } from './headerWalletStyles'; +import { useChains } from 'wagmi'; + +const tryGetColor = (chainId: number) => { + try { + return getChainColor(chainId); + } catch { + return '#FFFFFF'; + } +}; + const HeaderWallet: FC = () => { const { active, chainId } = useWeb3(); - const chainName = chainId && CHAINS[chainId]; + const chains = useChains(); + + const currentChain = chains.find((chain) => chain.id === chainId); return ( <> {chainId && ( - - {chainName} + + {currentChain?.name} )} {active ? : } diff --git a/playground/demo/core/index.tsx b/playground/demo/core/index.tsx index a8fe0408..ea916ac4 100644 --- a/playground/demo/core/index.tsx +++ b/playground/demo/core/index.tsx @@ -20,6 +20,7 @@ export const CoreDemo = () => { const dateAtTimestamp = new Date( Number(timestampSeconds) * 1000, ).toLocaleString(locale); + const getStethContract = useCallback(async () => { const address = await stake.contractAddressStETH(); setContractAddress(address); diff --git a/playground/demo/index.tsx b/playground/demo/index.tsx index 09a1dc95..9f264e0d 100644 --- a/playground/demo/index.tsx +++ b/playground/demo/index.tsx @@ -13,8 +13,13 @@ import { EventsDemo } from './events'; import { StatisticsDemo } from './statistics'; import { RewardsDemo } from './rewards'; import { ShareDemo } from './shares'; +import { useChainId } from 'wagmi'; +import { L2_CHAINS } from 'providers/web3'; +import { L2 } from './l2'; export const Demo = () => { + const chain = useChainId(); + if (L2_CHAINS.includes(chain)) return ; return ( <> diff --git a/playground/demo/l2/index.tsx b/playground/demo/l2/index.tsx new file mode 100644 index 00000000..46edd4de --- /dev/null +++ b/playground/demo/l2/index.tsx @@ -0,0 +1,12 @@ +import { StethL2Demo, WstethL2Demo } from './tokens'; +import { WrapL2Demo } from './wrap-l2'; + +export const L2 = () => { + return ( + <> + + + + + ); +}; diff --git a/playground/demo/l2/tokens.tsx b/playground/demo/l2/tokens.tsx new file mode 100644 index 00000000..618e2ed7 --- /dev/null +++ b/playground/demo/l2/tokens.tsx @@ -0,0 +1,16 @@ +import { TokenDemo } from 'demo/tokens'; +import { useLidoSDK } from 'providers/sdk'; + +export const WstethL2Demo = () => { + const { l2 } = useLidoSDK(); + return ; +}; + +export const StethL2Demo = () => { + const { l2 } = useLidoSDK(); + return ( + <> + + + ); +}; diff --git a/playground/demo/l2/wrap-l2.tsx b/playground/demo/l2/wrap-l2.tsx new file mode 100644 index 00000000..cae3862a --- /dev/null +++ b/playground/demo/l2/wrap-l2.tsx @@ -0,0 +1,124 @@ +import { Accordion } from '@lidofinance/lido-ui'; + +import { Action, renderTokenResult } from 'components/action'; +import { DEFAULT_VALUE, ValueType } from 'components/tokenInput'; +import TokenInput from 'components/tokenInput/tokenInput'; +import { useLidoSDK } from 'providers/sdk'; +import { useState } from 'react'; +import { transactionToast } from 'utils/transaction-toast'; + +const ZERO = BigInt(0); + +export const WrapL2Demo = () => { + const [wstethValue, setWstethValue] = useState(DEFAULT_VALUE); + const [stethValue, setStethValue] = useState(DEFAULT_VALUE); + + const { l2 } = useLidoSDK(); + + return ( + + l2.wsteth.balance()} + /> + l2.steth.balance()} + /> + l2.getWstethForWrapAllowance()} + /> + + l2.approveWstethForWrap({ + value: wstethValue ?? ZERO, + + callback: transactionToast, + }) + } + > + + + + l2.wrapWstethToSteth({ + value: wstethValue ?? ZERO, + + callback: transactionToast, + }) + } + /> + + l2.wrapWstethToStethPopulateTx({ + value: wstethValue ?? ZERO, + }) + } + /> + + l2.wrapWstethToStethSimulateTx({ + value: wstethValue ?? ZERO, + }) + } + /> + + + l2.unwrap({ + value: stethValue ?? ZERO, + + callback: transactionToast, + }) + } + > + + + + l2.unwrapPopulateTx({ + value: stethValue ?? ZERO, + }) + } + /> + + l2.unwrapSimulateTx({ + value: stethValue ?? ZERO, + }) + } + /> + + ); +}; diff --git a/playground/demo/tokens/index.tsx b/playground/demo/tokens/index.tsx index 8df64b0b..670ec9b1 100644 --- a/playground/demo/tokens/index.tsx +++ b/playground/demo/tokens/index.tsx @@ -25,7 +25,7 @@ export const WstethDemo = () => { return ; }; -const TokenDemo = ({ instance, name }: TokenDemoProps) => { +export const TokenDemo = ({ instance, name }: TokenDemoProps) => { const { account: web3account = '0x0' } = useWeb3(); const [transferAmountState, setTransferAmount] = useState(DEFAULT_VALUE); diff --git a/playground/package.json b/playground/package.json index c11a821a..3cab4ac1 100644 --- a/playground/package.json +++ b/playground/package.json @@ -34,8 +34,8 @@ "styled-components": "^5.3.5", "swr": "^1.3.0", "tiny-invariant": "^1.3.1", - "viem": "^2.0.6", - "wagmi": "2.11.2" + "viem": "^2.21.9", + "wagmi": "2.12.12" }, "devDependencies": { "@next/bundle-analyzer": "^13.4.19", diff --git a/playground/providers/sdk.tsx b/playground/providers/sdk.tsx index fd0dd51c..3704a598 100644 --- a/playground/providers/sdk.tsx +++ b/playground/providers/sdk.tsx @@ -2,7 +2,7 @@ import { createContext, useMemo, PropsWithChildren, useContext } from 'react'; import { LidoSDK } from '@lidofinance/lido-ethereum-sdk'; import invariant from 'tiny-invariant'; -import { useClient, useConnectorClient } from 'wagmi'; +import { usePublicClient, useWalletClient } from 'wagmi'; const context = createContext(null); @@ -13,9 +13,9 @@ export const useLidoSDK = () => { }; export const LidoSDKProvider: React.FC = ({ children }) => { - const publicClient = useClient(); + const publicClient = usePublicClient(); const chainId = publicClient?.chain.id; - const { data: walletClient } = useConnectorClient(); + const { data: walletClient } = useWalletClient(); const value = useMemo(() => { const sdk = new LidoSDK({ chainId: chainId as any, diff --git a/playground/providers/web3.tsx b/playground/providers/web3.tsx index 99c4fffc..b246f0f4 100644 --- a/playground/providers/web3.tsx +++ b/playground/providers/web3.tsx @@ -24,6 +24,8 @@ import { useThemeToggle } from '@lidofinance/lido-ui'; type ChainsList = [wagmiChains.Chain, ...wagmiChains.Chain[]]; +export const L2_CHAINS = [10, 11155420]; + const wagmiChainsArray = Object.values(wagmiChains) as any as ChainsList; const supportedChains = wagmiChainsArray.filter((chain) => @@ -63,6 +65,8 @@ const Web3Provider: FC = ({ children }) => { [CHAINS.Goerli]: getRpc(CHAINS.Goerli), [CHAINS.Holesky]: getRpc(CHAINS.Holesky), [CHAINS.Sepolia]: getRpc(CHAINS.Sepolia), + // OP sepolia + [11155420]: getRpc(11155420), }; }, [customRpc]); diff --git a/yarn.lock b/yarn.lock index b9d50ced..7bc0ac39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5097,7 +5097,8 @@ __metadata: rimraf: ^5.0.1 ts-jest: ^29.1.2 typescript: ^5.4.5 - viem: ^2.0.6 + peerDependencies: + viem: ^2.21 languageName: unknown linkType: soft @@ -5117,7 +5118,7 @@ __metadata: rimraf: ^5.0.5 ts-node: ^10.9.2 typescript: 5.1.6 - viem: ^2.0.6 + viem: ^2.21.9 languageName: unknown linkType: soft @@ -5363,9 +5364,9 @@ __metadata: languageName: node linkType: hard -"@metamask/sdk-communication-layer@npm:0.26.4": - version: 0.26.4 - resolution: "@metamask/sdk-communication-layer@npm:0.26.4" +"@metamask/sdk-communication-layer@npm:0.28.2": + version: 0.28.2 + resolution: "@metamask/sdk-communication-layer@npm:0.28.2" dependencies: bufferutil: ^4.0.8 date-fns: ^2.29.3 @@ -5378,13 +5379,13 @@ __metadata: eventemitter2: ^6.4.7 readable-stream: ^3.6.2 socket.io-client: ^4.5.1 - checksum: a355826fb3b91af1e52e6afb53590441765b4b47c06047d5e9330e90ab8c9e576f5a12a9ed72782de274632c6751326c3b7d895c5b9b0c85f2008510d2a382fb + checksum: 349103ca72018fc4077ddf3d84d3976572525cf27b17b65308c6a00710c66f06d2d3880bb611a4a6462d1fb54bc59edd6855826f78796f49d8c7cd9904742577 languageName: node linkType: hard -"@metamask/sdk-install-modal-web@npm:0.26.5": - version: 0.26.5 - resolution: "@metamask/sdk-install-modal-web@npm:0.26.5" +"@metamask/sdk-install-modal-web@npm:0.28.1": + version: 0.28.1 + resolution: "@metamask/sdk-install-modal-web@npm:0.28.1" dependencies: qr-code-styling: ^1.6.0-rc.1 peerDependencies: @@ -5399,19 +5400,20 @@ __metadata: optional: true react-native: optional: true - checksum: 3aba8d39bac0d320727b7abfcd803d843906962cea28685e946acba3f198b14d0a672ac8dfd6ec97a7d0efd4f92d00dae956af8872ca4cb2e677f91342bc58b0 + checksum: 8ee147c63927323105bdf7d76667c06618119b30b355543a74f3a08e7559448d217bdf9a4fee0900efa0fc3f5a13f6376a76b2679e0b8322f6811789868dce42 languageName: node linkType: hard -"@metamask/sdk@npm:0.26.5": - version: 0.26.5 - resolution: "@metamask/sdk@npm:0.26.5" +"@metamask/sdk@npm:0.28.4": + version: 0.28.4 + resolution: "@metamask/sdk@npm:0.28.4" dependencies: "@metamask/onboarding": ^1.0.1 "@metamask/providers": 16.1.0 - "@metamask/sdk-communication-layer": 0.26.4 - "@metamask/sdk-install-modal-web": 0.26.5 + "@metamask/sdk-communication-layer": 0.28.2 + "@metamask/sdk-install-modal-web": 0.28.1 "@types/dom-screen-wake-lock": ^1.0.0 + "@types/uuid": ^10.0.0 bowser: ^2.9.0 cross-fetch: ^4.0.0 debug: ^4.3.4 @@ -5437,7 +5439,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 63d53041a44669fd3110647a485e77e43038806c4548d86716e973c22b9f6ad019499beb9419cb8b08f243828aa3753485ba121d89169154462c90828f13f07f + checksum: 419880a65c09a340dac6ca756ef81193dbc441db6fab620a3bd610fa077b11b2dec96f4651e81aac49c266ac00dbd109ffc184e067738ded7ea325174be94f31 languageName: node linkType: hard @@ -5667,15 +5669,6 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:1.2.0, @noble/curves@npm:~1.2.0": - version: 1.2.0 - resolution: "@noble/curves@npm:1.2.0" - dependencies: - "@noble/hashes": 1.3.2 - checksum: bb798d7a66d8e43789e93bc3c2ddff91a1e19fdb79a99b86cd98f1e5eff0ee2024a2672902c2576ef3577b6f282f3b5c778bebd55761ddbb30e36bf275e83dd0 - languageName: node - linkType: hard - "@noble/curves@npm:1.3.0, @noble/curves@npm:~1.3.0": version: 1.3.0 resolution: "@noble/curves@npm:1.3.0" @@ -5694,6 +5687,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:^1.4.0": + version: 1.6.0 + resolution: "@noble/curves@npm:1.6.0" + dependencies: + "@noble/hashes": 1.5.0 + checksum: 258f3feb2a6098cf35521562ecb7d452fd728e8a008ff9f1ef435184f9d0c782ceb8f7b7fa8df3317c3be7a19f53995ee124cd05c8080b130bd42e3cb072f24d + languageName: node + linkType: hard + "@noble/curves@npm:~1.4.0": version: 1.4.2 resolution: "@noble/curves@npm:1.4.2" @@ -5703,14 +5705,7 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.3.2": - version: 1.3.2 - resolution: "@noble/hashes@npm:1.3.2" - checksum: fe23536b436539d13f90e4b9be843cc63b1b17666a07634a2b1259dded6f490be3d050249e6af98076ea8f2ea0d56f578773c2197f2aa0eeaa5fba5bc18ba474 - languageName: node - linkType: hard - -"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": +"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b @@ -5724,6 +5719,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.5.0, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.5.0": + version: 1.5.0 + resolution: "@noble/hashes@npm:1.5.0" + checksum: 9cc031d5c888c455bfeef76af649b87f75380a4511405baea633c1e4912fd84aff7b61e99716f0231d244c9cfeda1fafd7d718963e6a0c674ed705e9b1b4f76b + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -6688,7 +6690,7 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2, @scure/base@npm:~1.1.4": +"@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.4": version: 1.1.5 resolution: "@scure/base@npm:1.1.5" checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519 @@ -6702,14 +6704,10 @@ __metadata: languageName: node linkType: hard -"@scure/bip32@npm:1.3.2": - version: 1.3.2 - resolution: "@scure/bip32@npm:1.3.2" - dependencies: - "@noble/curves": ~1.2.0 - "@noble/hashes": ~1.3.2 - "@scure/base": ~1.1.2 - checksum: c5ae84fae43490853693b481531132b89e056d45c945fc8b92b9d032577f753dfd79c5a7bbcbf0a7f035951006ff0311b6cf7a389e26c9ec6335e42b20c53157 +"@scure/base@npm:~1.1.8": + version: 1.1.9 + resolution: "@scure/base@npm:1.1.9" + checksum: 120820a37dfe9dfe4cab2b7b7460552d08e67dee8057ed5354eb68d8e3440890ae983ce3bee957d2b45684950b454a2b6d71d5ee77c1fd3fddc022e2a510337f languageName: node linkType: hard @@ -6735,16 +6733,6 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:1.2.1": - version: 1.2.1 - resolution: "@scure/bip39@npm:1.2.1" - dependencies: - "@noble/hashes": ~1.3.0 - "@scure/base": ~1.1.0 - checksum: c5bd6f1328fdbeae2dcdd891825b1610225310e5e62a4942714db51066866e4f7bef242c7b06a1b9dcc8043a4a13412cf5c5df76d3b10aa9e36b82e9b6e3eeaa - languageName: node - linkType: hard - "@scure/bip39@npm:1.2.2": version: 1.2.2 resolution: "@scure/bip39@npm:1.2.2" @@ -6765,6 +6753,16 @@ __metadata: languageName: node linkType: hard +"@scure/bip39@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip39@npm:1.4.0" + dependencies: + "@noble/hashes": ~1.5.0 + "@scure/base": ~1.1.8 + checksum: 211f2c01361993bfe54c0e4949f290224381457c7f76d7cd51d6a983f3f4b6b9f85adfd0e623977d777ed80417a5fe729eb19dd34e657147810a0e58a8e7b9e0 + languageName: node + linkType: hard + "@semantic-release/commit-analyzer@npm:^10.0.0": version: 10.0.4 resolution: "@semantic-release/commit-analyzer@npm:10.0.4" @@ -8357,6 +8355,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "@types/uuid@npm:10.0.0" + checksum: e3958f8b0fe551c86c14431f5940c3470127293280830684154b91dc7eb3514aeb79fe3216968833cf79d4d1c67f580f054b5be2cd562bebf4f728913e73e944 + languageName: node + linkType: hard + "@types/ws@npm:^8.5.5": version: 8.5.10 resolution: "@types/ws@npm:8.5.10" @@ -8573,31 +8578,31 @@ __metadata: languageName: node linkType: hard -"@wagmi/connectors@npm:5.0.26": - version: 5.0.26 - resolution: "@wagmi/connectors@npm:5.0.26" +"@wagmi/connectors@npm:5.1.11": + version: 5.1.11 + resolution: "@wagmi/connectors@npm:5.1.11" dependencies: "@coinbase/wallet-sdk": 4.0.4 - "@metamask/sdk": 0.26.5 + "@metamask/sdk": 0.28.4 "@safe-global/safe-apps-provider": 0.18.3 "@safe-global/safe-apps-sdk": 9.1.0 - "@walletconnect/ethereum-provider": 2.13.0 + "@walletconnect/ethereum-provider": 2.16.1 "@walletconnect/modal": 2.6.2 cbw-sdk: "npm:@coinbase/wallet-sdk@3.9.3" peerDependencies: - "@wagmi/core": 2.12.2 + "@wagmi/core": 2.13.5 typescript: ">=5.0.4" viem: 2.x peerDependenciesMeta: typescript: optional: true - checksum: 286c641c912fb2d4620fa867d920d79f5730372ae49f26eff5484b36a1d21f03c984fcde9d85d4f2c732f2891bebc579e3d7613702b9ced8426cc7f10627c118 + checksum: c05beff4aa98dced7ba070dc2a2f9144f48026c19725c1e9fe04c843c4add0a4935de0aa8fddb8cb9d4cf2454d6504bfcfb2fa3bd6e5bb166e9b8d13eddfa087 languageName: node linkType: hard -"@wagmi/core@npm:2.12.2": - version: 2.12.2 - resolution: "@wagmi/core@npm:2.12.2" +"@wagmi/core@npm:2.13.5": + version: 2.13.5 + resolution: "@wagmi/core@npm:2.13.5" dependencies: eventemitter3: 5.0.1 mipd: 0.0.7 @@ -8611,13 +8616,13 @@ __metadata: optional: true typescript: optional: true - checksum: 06d3fde29b53474805460474158dfe7e3d6356dc11cf8f90033a9edae605cbe56839da7cbc20bb82e72d1ee68cf7b02ef493aa5d4f7041b8247017e89879b52e + checksum: e0fce057b613a36e35f43ceaaea3f300d92e37a53590d767cc4934035e0fff36dfe5c8ec64486fc78b3a11abcb10b0ac0b65f369ea0034afb5932572cb6f1187 languageName: node linkType: hard -"@walletconnect/core@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/core@npm:2.13.0" +"@walletconnect/core@npm:2.16.1": + version: 2.16.1 + resolution: "@walletconnect/core@npm:2.16.1" dependencies: "@walletconnect/heartbeat": 1.2.2 "@walletconnect/jsonrpc-provider": 1.0.14 @@ -8626,17 +8631,16 @@ __metadata: "@walletconnect/jsonrpc-ws-connection": 1.0.14 "@walletconnect/keyvaluestorage": 1.1.1 "@walletconnect/logger": 2.1.2 - "@walletconnect/relay-api": 1.0.10 + "@walletconnect/relay-api": 1.0.11 "@walletconnect/relay-auth": 1.0.4 "@walletconnect/safe-json": 1.0.2 "@walletconnect/time": 1.0.2 - "@walletconnect/types": 2.13.0 - "@walletconnect/utils": 2.13.0 + "@walletconnect/types": 2.16.1 + "@walletconnect/utils": 2.16.1 events: 3.3.0 - isomorphic-unfetch: 3.1.0 lodash.isequal: 4.5.0 uint8arrays: 3.1.0 - checksum: 6e503bdc7d678ccaeaa9d93fdc6311298d326febef87f233b80c12340178ae3eff54a3a79e19400d65298f109466c508dbef0d5710fffd09d357b7b6bec8b56f + checksum: ab658833fb845624ccb2d109c5218f5b4624b948b4a8b01bf22eb964c5e5d3cd890ee43645e196ad73d1be9a25d6a1bcd16a83893266ee1b30c9ec5377086820 languageName: node linkType: hard @@ -8649,21 +8653,21 @@ __metadata: languageName: node linkType: hard -"@walletconnect/ethereum-provider@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/ethereum-provider@npm:2.13.0" +"@walletconnect/ethereum-provider@npm:2.16.1": + version: 2.16.1 + resolution: "@walletconnect/ethereum-provider@npm:2.16.1" dependencies: "@walletconnect/jsonrpc-http-connection": 1.0.8 "@walletconnect/jsonrpc-provider": 1.0.14 "@walletconnect/jsonrpc-types": 1.0.4 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/modal": 2.6.2 - "@walletconnect/sign-client": 2.13.0 - "@walletconnect/types": 2.13.0 - "@walletconnect/universal-provider": 2.13.0 - "@walletconnect/utils": 2.13.0 + "@walletconnect/sign-client": 2.16.1 + "@walletconnect/types": 2.16.1 + "@walletconnect/universal-provider": 2.16.1 + "@walletconnect/utils": 2.16.1 events: 3.3.0 - checksum: 24356a41b72fea5125ef0e6605df4469f023141ce5de8cc92f1ae23b35215efb0ee2c1e5857f483f34eccd4a051915b64518daadc4c8a2145bf91473c2f5a7bc + checksum: f88c6e41b7718a75452795efa7a1b51f5286aa728358a6b5f477e26f9c37e6cf5df1ec69fa227fe67674be53c2871296d767becbc23fc287ca6298a12d2c4984 languageName: node linkType: hard @@ -8811,12 +8815,12 @@ __metadata: languageName: node linkType: hard -"@walletconnect/relay-api@npm:1.0.10": - version: 1.0.10 - resolution: "@walletconnect/relay-api@npm:1.0.10" +"@walletconnect/relay-api@npm:1.0.11": + version: 1.0.11 + resolution: "@walletconnect/relay-api@npm:1.0.11" dependencies: "@walletconnect/jsonrpc-types": ^1.0.2 - checksum: a332cbfdf0d3bad7046b0559653a5121a4b5a540f029cc01eeb8ef466681b10626a5a24d55668405e7c635535f35b8038d4aa5a2f0d16c8b512c41fecff2448c + checksum: 9fcddf055de01c04b9fa59035e8c6e31d523743c848d266f528009048aeadaa1b4d9b544bdcb6928e7a69f738d5f0352d1cdebbaa34b1346b937942cb5f6f144 languageName: node linkType: hard @@ -8843,20 +8847,20 @@ __metadata: languageName: node linkType: hard -"@walletconnect/sign-client@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/sign-client@npm:2.13.0" +"@walletconnect/sign-client@npm:2.16.1": + version: 2.16.1 + resolution: "@walletconnect/sign-client@npm:2.16.1" dependencies: - "@walletconnect/core": 2.13.0 + "@walletconnect/core": 2.16.1 "@walletconnect/events": 1.0.1 "@walletconnect/heartbeat": 1.2.2 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/logger": 2.1.2 "@walletconnect/time": 1.0.2 - "@walletconnect/types": 2.13.0 - "@walletconnect/utils": 2.13.0 + "@walletconnect/types": 2.16.1 + "@walletconnect/utils": 2.16.1 events: 3.3.0 - checksum: d8516d5bc7f554962651d59af36c13716da35216e78a92b4ab2632d6c2e65dccc9fda83e5ef8ceaab3195c2436cdd038ff7ed1176b25c57142f823735a5f987c + checksum: e25808e2fbfc01cff47391281e7cb050927cde2e83f5eec640e5be52c8adc9ee50bd70447a2e72defc9cad3d3e3009ef48ac7d1b694dafa5d6a62e046863b58a languageName: node linkType: hard @@ -8869,9 +8873,9 @@ __metadata: languageName: node linkType: hard -"@walletconnect/types@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/types@npm:2.13.0" +"@walletconnect/types@npm:2.16.1": + version: 2.16.1 + resolution: "@walletconnect/types@npm:2.16.1" dependencies: "@walletconnect/events": 1.0.1 "@walletconnect/heartbeat": 1.2.2 @@ -8879,46 +8883,48 @@ __metadata: "@walletconnect/keyvaluestorage": 1.1.1 "@walletconnect/logger": 2.1.2 events: 3.3.0 - checksum: 868e12449026154c5a8945359ab03c2f2dd7dd329e631fea721e8399928823b93585013784253d787daf184adb76de6bccd76525679b4c87fd830300c70275d4 + checksum: 9ea47bfb0d5db8f0e440e040d55b05b4932aa3f56e976d42290e831c39d4bc5f2d4cd400f64ca86d8a6a195e34d6370f8db878f7b339ff7cac60a12bbfd9e445 languageName: node linkType: hard -"@walletconnect/universal-provider@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/universal-provider@npm:2.13.0" +"@walletconnect/universal-provider@npm:2.16.1": + version: 2.16.1 + resolution: "@walletconnect/universal-provider@npm:2.16.1" dependencies: "@walletconnect/jsonrpc-http-connection": 1.0.8 "@walletconnect/jsonrpc-provider": 1.0.14 "@walletconnect/jsonrpc-types": 1.0.4 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/logger": 2.1.2 - "@walletconnect/sign-client": 2.13.0 - "@walletconnect/types": 2.13.0 - "@walletconnect/utils": 2.13.0 + "@walletconnect/sign-client": 2.16.1 + "@walletconnect/types": 2.16.1 + "@walletconnect/utils": 2.16.1 events: 3.3.0 - checksum: 3eb26d07bebbebe67e7f1e666d7b37cbdb6513a807262b9fd9026e8340238bc715b80f99d81127939aa53ff9f9027f903d9828e649e9f6c3c1e536c557b0840d + checksum: 2852ff1b1b06628bf08015ade517f73b743f11873f56e4358063668fd13c290adc648274cc965b34789f2c91879ec338135b42c01e466a2ef76e82ccec74400e languageName: node linkType: hard -"@walletconnect/utils@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/utils@npm:2.13.0" +"@walletconnect/utils@npm:2.16.1": + version: 2.16.1 + resolution: "@walletconnect/utils@npm:2.16.1" dependencies: "@stablelib/chacha20poly1305": 1.0.1 "@stablelib/hkdf": 1.0.1 "@stablelib/random": 1.0.2 "@stablelib/sha256": 1.0.1 "@stablelib/x25519": 1.0.3 - "@walletconnect/relay-api": 1.0.10 + "@walletconnect/relay-api": 1.0.11 + "@walletconnect/relay-auth": 1.0.4 "@walletconnect/safe-json": 1.0.2 "@walletconnect/time": 1.0.2 - "@walletconnect/types": 2.13.0 + "@walletconnect/types": 2.16.1 "@walletconnect/window-getters": 1.0.1 "@walletconnect/window-metadata": 1.0.1 detect-browser: 5.3.0 + elliptic: ^6.5.7 query-string: 7.1.3 uint8arrays: 3.1.0 - checksum: ab3c008aa72e573d67f342042e62c04e4aa779bde94f850de53f7bda31a4458665b39af2e33ae6ee6f237aa19f55cef542c75cabbe647218c02075700d2c713f + checksum: 404c5f262e020c208ab30283c1dbe23f7a4876d3d89ebb23dde95ea32deb8ada72886d64151f6a826d21774797fa44feed70d33729661aa0de4b6850b3ace0d5 languageName: node linkType: hard @@ -9148,21 +9154,6 @@ __metadata: languageName: node linkType: hard -"abitype@npm:1.0.0": - version: 1.0.0 - resolution: "abitype@npm:1.0.0" - peerDependencies: - typescript: ">=5.0.4" - zod: ^3 >=3.22.0 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - checksum: ea2c0548c3ba58c37a6de7483d63389074da498e63d803b742bbe94eb4eaa1f51a35d000c424058b2583aef56698cf07c696eb3bc4dd0303bc20c6f0826a241a - languageName: node - linkType: hard - "abitype@npm:1.0.5": version: 1.0.5 resolution: "abitype@npm:1.0.5" @@ -13016,6 +13007,21 @@ __metadata: languageName: node linkType: hard +"elliptic@npm:^6.5.7": + version: 6.5.7 + resolution: "elliptic@npm:6.5.7" + dependencies: + bn.js: ^4.11.9 + brorand: ^1.1.0 + hash.js: ^1.0.0 + hmac-drbg: ^1.0.1 + inherits: ^2.0.4 + minimalistic-assert: ^1.0.1 + minimalistic-crypto-utils: ^1.0.1 + checksum: af0ffddffdbc2fea4eeec74388cd73e62ed5a0eac6711568fb28071566319785df529c968b0bf1250ba4bc628e074b2d64c54a633e034aa6f0c6b152ceb49ab8 + languageName: node + linkType: hard + "emittery@npm:0.10.0": version: 0.10.0 resolution: "emittery@npm:0.10.0" @@ -13184,7 +13190,7 @@ __metadata: resolution: "erlang-bridge-examples@workspace:examples/erlang-bridge" dependencies: "@lidofinance/lido-ethereum-sdk": "workspace:*" - viem: ^2.0.6 + viem: ^2.21.9 languageName: unknown linkType: soft @@ -16836,25 +16842,6 @@ __metadata: languageName: node linkType: hard -"isomorphic-unfetch@npm:3.1.0": - version: 3.1.0 - resolution: "isomorphic-unfetch@npm:3.1.0" - dependencies: - node-fetch: ^2.6.1 - unfetch: ^4.2.0 - checksum: 82b92fe4ec2823a81ab0fc0d11bd94d710e6f9a940d56b3cba31896d4345ec9ffc7949f4ff31ebcae84f6b95f7ebf3474c4c7452b834eb4078ea3f2c37e459c5 - languageName: node - linkType: hard - -"isows@npm:1.0.3": - version: 1.0.3 - resolution: "isows@npm:1.0.3" - peerDependencies: - ws: "*" - checksum: 9cacd5cf59f67deb51e825580cd445ab1725ecb05a67c704050383fb772856f3cd5e7da8ad08f5a3bd2823680d77d099459d0c6a7037972a74d6429af61af440 - languageName: node - linkType: hard - "isows@npm:1.0.4": version: 1.0.4 resolution: "isows@npm:1.0.4" @@ -18096,8 +18083,8 @@ __metadata: tiny-invariant: ^1.3.1 typescript: ^5.4.5 url-loader: ^4.1.1 - viem: ^2.0.6 - wagmi: 2.11.2 + viem: ^2.21.9 + wagmi: 2.12.12 languageName: unknown linkType: soft @@ -20416,7 +20403,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12": +"node-fetch@npm:^2.6.12": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -23675,7 +23662,7 @@ __metadata: "@lidofinance/lido-ethereum-sdk": "workspace:*" rimraf: ^5.0.5 typescript: 5.1.6 - viem: ^2.0.6 + viem: ^2.21.9 languageName: unknown linkType: soft @@ -26019,13 +26006,6 @@ __metadata: languageName: node linkType: hard -"unfetch@npm:^4.2.0": - version: 4.2.0 - resolution: "unfetch@npm:4.2.0" - checksum: 6a4b2557e1d921eaa80c4425ce27a404945ec26491ed06e62598f333996a91a44c7908cb26dc7c2746d735762b13276cf4aa41829b4c8f438dde63add3045d7a - languageName: node - linkType: hard - "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -26648,54 +26628,55 @@ __metadata: languageName: node linkType: hard -"viem@npm:^2.0.6": - version: 2.7.9 - resolution: "viem@npm:2.7.9" +"viem@npm:^2.1.1": + version: 2.17.11 + resolution: "viem@npm:2.17.11" dependencies: "@adraffy/ens-normalize": 1.10.0 - "@noble/curves": 1.2.0 - "@noble/hashes": 1.3.2 - "@scure/bip32": 1.3.2 - "@scure/bip39": 1.2.1 - abitype: 1.0.0 - isows: 1.0.3 - ws: 8.13.0 + "@noble/curves": 1.4.0 + "@noble/hashes": 1.4.0 + "@scure/bip32": 1.4.0 + "@scure/bip39": 1.3.0 + abitype: 1.0.5 + isows: 1.0.4 + ws: 8.17.1 peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 71ff08ca18506a7217f1f87f44ea84ba2dcdb81f7d5a35670701aefbb05512892f4e32c80c9ca9584db119749d53576f37802290da6234fb1196d4c0c28beed5 + checksum: 7eefb347d0f717a6bc0f286ef82ecb6b52c9ff6e257205d470c3d92b4e2443cbb8a28a7fe0a49b3155a9f7c884eb9242c3cd56f3db4ab112cc0c97f591342f6d languageName: node linkType: hard -"viem@npm:^2.1.1": - version: 2.17.11 - resolution: "viem@npm:2.17.11" +"viem@npm:^2.21.9": + version: 2.21.9 + resolution: "viem@npm:2.21.9" dependencies: "@adraffy/ens-normalize": 1.10.0 "@noble/curves": 1.4.0 "@noble/hashes": 1.4.0 "@scure/bip32": 1.4.0 - "@scure/bip39": 1.3.0 + "@scure/bip39": 1.4.0 abitype: 1.0.5 isows: 1.0.4 + webauthn-p256: 0.0.5 ws: 8.17.1 peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 7eefb347d0f717a6bc0f286ef82ecb6b52c9ff6e257205d470c3d92b4e2443cbb8a28a7fe0a49b3155a9f7c884eb9242c3cd56f3db4ab112cc0c97f591342f6d + checksum: de6b9789a86cd217ce62833db80bcf3b5a6fbca3a8ef29d74083a5822c8a9c5fabcfecd050a5c5f0aa476eac02164b57a7aef3334030f93b649d4b52040f9332 languageName: node linkType: hard -"wagmi@npm:2.11.2": - version: 2.11.2 - resolution: "wagmi@npm:2.11.2" +"wagmi@npm:2.12.12": + version: 2.12.12 + resolution: "wagmi@npm:2.12.12" dependencies: - "@wagmi/connectors": 5.0.26 - "@wagmi/core": 2.12.2 + "@wagmi/connectors": 5.1.11 + "@wagmi/core": 2.13.5 use-sync-external-store: 1.2.0 peerDependencies: "@tanstack/react-query": ">=5.0.0" @@ -26705,7 +26686,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5fb5d9434261de1760dc0ba5798627e993f1e80f3ec64c351b42ee7b4f0230c6391194f2ba91dca9ed2452dfb8628215dfdbffda73238bef3cbc65c500f8c964 + checksum: b4d2f8ba66f7ff6228400c0759df0f0f0f5b282081af7b22261c5468ef0eaf676427d1319c6bd7efe14ab5c1fefcfcdf8d2ec3cc1bc68e0f23454ba8c1b85c31 languageName: node linkType: hard @@ -26777,6 +26758,16 @@ __metadata: languageName: node linkType: hard +"webauthn-p256@npm:0.0.5": + version: 0.0.5 + resolution: "webauthn-p256@npm:0.0.5" + dependencies: + "@noble/curves": ^1.4.0 + "@noble/hashes": ^1.4.0 + checksum: 2837188d1e6d947c87c5728374fb6aec96387cb766f78e7a04d5903774264feb278d68a639748f09997f591e5278796c662bb5c4e8b8286b0f22254694023584 + languageName: node + linkType: hard + "webextension-polyfill@npm:>=0.10.0 <1.0": version: 0.12.0 resolution: "webextension-polyfill@npm:0.12.0"