diff --git a/local-tests/setup/networkContext.json b/local-tests/setup/networkContext.json index 9d9305c7e..8468bca27 100644 --- a/local-tests/setup/networkContext.json +++ b/local-tests/setup/networkContext.json @@ -11518,5 +11518,574 @@ } ], "name": "ContractResolver" + }, + "CloneNet": { + "address": "0x1f4233b6C5b84978c458FA66412E4ae6d0561104", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotAddFunctionToDiamondThatAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "_selectors", + "type": "bytes4[]" + } + ], + "name": "CannotAddSelectorsToZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotRemoveFunctionThatDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotRemoveImmutableFunction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceFunctionThatDoesNotExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "_selectors", + "type": "bytes4[]" + } + ], + "name": "CannotReplaceFunctionsFromFacetWithZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_selector", + "type": "bytes4" + } + ], + "name": "CannotReplaceImmutableFunction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_action", + "type": "uint8" + } + ], + "name": "IncorrectFacetCutAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_initializationContractAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "InitializationFunctionReverted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "_message", + "type": "string" + } + ], + "name": "NoBytecodeAtAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facetAddress", + "type": "address" + } + ], + "name": "NoSelectorsProvidedForFacetForCut", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "address", + "name": "_contractOwner", + "type": "address" + } + ], + "name": "NotContractOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facetAddress", + "type": "address" + } + ], + "name": "RemoveFacetAddressMustBeZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamond.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamond.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "_init", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamond.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamond.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "_init", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "diamondCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "internalType": "address", + "name": "facetAddress_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "facetAddresses_", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "_facetFunctionSelectors", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondLoupe.Facet[]", + "name": "facets_", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "CallerNotOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "stakingContractAddress", + "type": "address" + } + ], + "name": "adminAddActiveStakingContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "stakingContractAddress", + "type": "address" + } + ], + "name": "adminRemoveActiveStakingContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveStakingContracts", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllActiveUnkickedValidatorStructsAndCounts", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "stakingContractAddress", + "type": "address" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "epochLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "retries", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timeout", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + } + ], + "internalType": "struct LibStakingStorage.Epoch", + "name": "epoch", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "currentValidatorCountForConsensus", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "ip", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ipv6", + "type": "uint128" + }, + { + "internalType": "uint32", + "name": "port", + "type": "uint32" + }, + { + "internalType": "address", + "name": "nodeAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "senderPubKey", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiverPubKey", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastActiveEpoch", + "type": "uint256" + } + ], + "internalType": "struct LibStakingStorage.Validator[]", + "name": "activeUnkickedValidators", + "type": "tuple[]" + } + ], + "internalType": "struct LibStakingStorage.StakingAggregateDetails", + "name": "details", + "type": "tuple" + } + ], + "internalType": "struct LibStakingStorage.KeyedStakingAggregateDetails[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numActiveStakingContracts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] } } diff --git a/local-tests/setup/tinny-config.ts b/local-tests/setup/tinny-config.ts index 296e55dd9..566dea46a 100644 --- a/local-tests/setup/tinny-config.ts +++ b/local-tests/setup/tinny-config.ts @@ -23,6 +23,8 @@ export interface ProcessEnvs { */ NETWORK: LIT_NETWORK_VALUES; + NETWORK_TYPE: 'mainnet' | 'cloneNet' | 'random'; + /** * The number of milliseconds to wait between each request. */ diff --git a/local-tests/setup/tinny-environment.ts b/local-tests/setup/tinny-environment.ts index 7163ca6d8..1558cf1cc 100644 --- a/local-tests/setup/tinny-environment.ts +++ b/local-tests/setup/tinny-environment.ts @@ -50,6 +50,10 @@ export class TinnyEnvironment { TIME_TO_RELEASE_KEY: parseInt(process.env['TIME_TO_RELEASE_KEY']) || 10000, RUN_IN_BAND: process.env['RUN_IN_BAND'] === 'true', RUN_IN_BAND_INTERVAL: parseInt(process.env['RUN_IN_BAND_INTERVAL']) || 5000, + NETWORK_TYPE: (process.env['NETWORK_TYPE'] || '') as + | 'mainnet' + | 'cloneNet' + | 'random', // Available Accounts // ================== @@ -242,18 +246,27 @@ export class TinnyEnvironment { debug: this.processEnvs.DEBUG, checkNodeAttestation: false, // disable node attestation check for local testing contractContext: networkContext, + ...(this.processEnvs.NETWORK_TYPE !== 'random' && { + networkType: this.processEnvs.NETWORK_TYPE || 'mainnet', + }), }); } else if (centralisation === 'decentralised') { this.litNodeClient = new LitNodeClient({ litNetwork: this.network, checkNodeAttestation: true, debug: this.processEnvs.DEBUG, + ...(this.processEnvs.NETWORK_TYPE !== 'random' && { + networkType: this.processEnvs.NETWORK_TYPE || 'mainnet', + }), }); } else if (centralisation === 'centralised') { this.litNodeClient = new LitNodeClient({ litNetwork: this.network, checkNodeAttestation: false, debug: this.processEnvs.DEBUG, + ...(this.processEnvs.NETWORK_TYPE !== 'random' && { + networkType: this.processEnvs.NETWORK_TYPE || 'mainnet', + }), }); } else { throw new Error(`Network not supported: "${this.network}"`); diff --git a/package.json b/package.json index 549915363..d4cd13773 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@cosmjs/stargate": "0.30.1", "@dotenvx/dotenvx": "^1.6.4", "@lit-protocol/accs-schemas": "^0.0.19", - "@lit-protocol/contracts": "^0.0.63", + "@lit-protocol/contracts": "feature-clonenet", "@metamask/eth-sig-util": "5.0.2", "@mysten/sui.js": "^0.37.1", "@openagenda/verror": "^3.1.4", diff --git a/packages/access-control-conditions/package.json b/packages/access-control-conditions/package.json index 75a476f26..6cfae0583 100644 --- a/packages/access-control-conditions/package.json +++ b/packages/access-control-conditions/package.json @@ -21,7 +21,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/auth-browser/package.json b/packages/auth-browser/package.json index bb68c1dc9..6c5db8616 100644 --- a/packages/auth-browser/package.json +++ b/packages/auth-browser/package.json @@ -30,7 +30,5 @@ "tags": [ "browser" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/auth-helpers/package.json b/packages/auth-helpers/package.json index 7f1b726aa..3a22aa7a9 100644 --- a/packages/auth-helpers/package.json +++ b/packages/auth-helpers/package.json @@ -25,7 +25,5 @@ "crypto": false, "stream": false }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/constants/package.json b/packages/constants/package.json index 1ab0dcdc1..f7fd45e34 100644 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -20,7 +20,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/contracts-sdk/package.json b/packages/contracts-sdk/package.json index e049160dd..53a88ed4a 100644 --- a/packages/contracts-sdk/package.json +++ b/packages/contracts-sdk/package.json @@ -25,7 +25,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/contracts-sdk/src/lib/contracts-sdk.ts b/packages/contracts-sdk/src/lib/contracts-sdk.ts index 8561fbbd2..d2b2329ec 100644 --- a/packages/contracts-sdk/src/lib/contracts-sdk.ts +++ b/packages/contracts-sdk/src/lib/contracts-sdk.ts @@ -1,11 +1,12 @@ /* eslint-disable import/order */ -import { isBrowser, isNode } from '@lit-protocol/misc'; +import { isBrowser, isNode, log } from '@lit-protocol/misc'; import { ContractName, CreateCustomAuthMethodRequest, EpochInfo, GasLimitParam, LIT_NETWORKS_KEYS, + LitContract, LitContractContext, LitContractResolverContext, MintCapacityCreditsContext, @@ -620,23 +621,28 @@ export class LitContracts { }; /** - * Retrieves the Staking contract instance based on the provided network, context, and RPC URL. - * If a context is provided, it determines if a contract resolver is used for bootstrapping contracts. - * If a resolver address is present in the context, it retrieves the Staking contract from the contract resolver instance. - * Otherwise, it retrieves the Staking contract using the contract address and ABI from the contract context. - * Throws an error if required contract data is missing or if the Staking contract cannot be obtained. + * Retrieves a contract instance based on the provided network, contract name, context, and RPC URL. * - * @param network - The network key. - * @param context - The contract context or contract resolver context. - * @param rpcUrl - The RPC URL. - * @returns The Staking contract instance. - * @throws Error if required contract data is missing or if the Staking contract cannot be obtained. + * This method handles three scenarios: + * 1. No context provided - Resolves contract data from network context + * 2. Context without resolver - Uses contract data directly from context + * 3. Context with resolver - Retrieves contract data from a contract resolver + * + * @param network - The network key identifying which network to connect to + * @param contractName - The name of the contract to instantiate + * @param context - Optional contract context containing contract data or resolver info + * @param rpcUrl - Optional RPC URL to override the default network RPC + * @param contractAddress - Optional contract address to override the resolved address + * @returns A typed contract instance + * @throws InitError if required contract data is missing or cannot be resolved */ - public static async getStakingContract( + public static async getContractInstance( network: LIT_NETWORKS_KEYS, + contractName: string, context?: LitContractContext | LitContractResolverContext, - rpcUrl?: string - ) { + rpcUrl?: string, + contractAddress?: string + ): Promise { let provider: ethers.providers.StaticJsonRpcProvider; const _rpcUrl = rpcUrl || RPC_URL_BY_NETWORK[network]; @@ -651,82 +657,80 @@ export class LitContracts { } if (!context) { - const contractData = await LitContracts._resolveContractContext( - network - //context - ); + const contractData = await LitContracts._resolveContractContext(network); - const stakingContract = contractData.find( - (item: { name: string }) => item.name === 'Staking' + const contractInfo = contractData.find( + (item: { name: string }) => item.name === contractName ); - const { address, abi } = stakingContract!; - // Validate the required data - if (!address || !abi) { + if (!contractInfo || !contractInfo.address || !contractInfo.abi) { throw new InitError( { info: { - address, - abi, + contractName, network, }, }, - '❌ Required contract data is missing' + `❌ Required contract data for ${contractName} is missing` ); } - return new ethers.Contract(address, abi, provider); + return new ethers.Contract( + contractInfo.address, + contractInfo.abi, + provider + ) as T; } else { - // if we have contract context then we determine if there exists a `resolverAddress` - // if there is a resolver address we assume we are using a contract resolver for bootstrapping of contracts if (!context.resolverAddress) { - const stakingContract = (context as LitContractContext).Staking; + const contractContext = (context as LitContractContext)[contractName]; - if (!stakingContract.address) { + if (!contractContext?.address) { throw new InitError( { info: { - stakingContract, + contractName, context, }, }, - '❌ Could not get staking contract address from contract context' + `❌ Could not get ${contractName} address from contract context` ); } + return new ethers.Contract( - stakingContract.address, - stakingContract.abi ?? StakingData.abi, + contractAddress || contractContext.address, + contractContext.abi, provider - ); + ) as T; } else { const contractContext = await LitContracts._getContractsFromResolver( context as LitContractResolverContext, provider, - ['Staking'] + [contractName as ContractName] ); - if (!contractContext.Staking.address) { + + const resolvedContract = contractContext[contractName]; + + if (!resolvedContract?.address) { throw new InitError( { info: { - contractContext, + contractName, context, }, }, - '❌ Could not get Staking Contract from contract resolver instance' + `❌ Could not get ${contractName} from contract resolver instance` ); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore data is callable as an array type - const stakingABI = NETWORK_CONTEXT_BY_NETWORK[network].data.find( - (data: any) => { - return data.name === 'Staking'; - } - ); + + const contractABI = NETWORK_CONTEXT_BY_NETWORK[network].data.find( + (data: any) => data.name === contractName + )?.contracts?.[0]?.ABI; + return new ethers.Contract( - contractContext.Staking.address, - contractContext.Staking.abi ?? stakingABI?.contracts[0].ABI, + contractAddress || resolvedContract.address, + resolvedContract.abi ?? contractABI, provider - ); + ) as T; } } } @@ -923,6 +927,11 @@ export class LitContracts { addresses.Multisender.address = contract.address; addresses.Multisender.abi = contract?.abi ?? MultisenderData.abi; break; + case 'CloneNet': + addresses.CloneNet = {}; + addresses.CloneNet.address = contract.address; + addresses.CloneNet.abi = contract?.abi; + break; } } @@ -951,8 +960,9 @@ export class LitContracts { context?: LitContractContext | LitContractResolverContext, rpcUrl?: string ) => { - const contract = await LitContracts.getStakingContract( + const contract = await LitContracts.getContractInstance( network, + 'Staking', context, rpcUrl ); @@ -981,8 +991,9 @@ export class LitContracts { rpcUrl?: string, nodeProtocol?: typeof HTTP | typeof HTTPS | null ): Promise => { - const contract = await LitContracts.getStakingContract( + const contract = await LitContracts.getContractInstance( network, + 'Staking', context, rpcUrl ); @@ -1057,6 +1068,111 @@ export class LitContracts { return networks; }; + public static async _getAllActiveUnkickedValidatorStructsAndCounts( + network: LIT_NETWORKS_KEYS, + context?: LitContractContext | LitContractResolverContext, + rpcUrl?: string, + nodeProtocol?: typeof HTTP | typeof HTTPS | null + ) { + const cloneNetContract = await LitContracts.getContractInstance( + network, + 'CloneNet', + context, + rpcUrl + ); + + const allThings = await cloneNetContract[ + 'getAllActiveUnkickedValidatorStructsAndCounts' + ](); + + // First get all the active staking contract addresses. + const activeStakingContractAddresses = allThings.map( + (item: any) => item[0] + ); + + if (activeStakingContractAddresses.length < 2) { + throw new Error('❌ Not enough active staking contracts'); + } + + // Then, for each active staking contract, get the epoch, current validator count, and active unkicked validator structs. + const stakingAggregateDetails = []; + + for (let i = 0; i < activeStakingContractAddresses.length; i++) { + const stakingContractAddress = activeStakingContractAddresses[i]; + + const contractInfo = allThings.find( + (item: any) => item.stakingContractAddress === stakingContractAddress + ); + + const epochInfo = contractInfo.details.epoch; + const minNodeCount = + contractInfo.details.currentValidatorCountForConsensus; + + const typedEpochInfo: EpochInfo = { + epochLength: ethers.BigNumber.from(epochInfo.epochLength).toNumber(), + number: ethers.BigNumber.from(epochInfo.number).toNumber(), + endTime: ethers.BigNumber.from(epochInfo.endTime).toNumber(), + retries: ethers.BigNumber.from(epochInfo.retries).toNumber(), + timeout: ethers.BigNumber.from(epochInfo.timeout).toNumber(), + }; + + const minNodeCountInt = ethers.BigNumber.from(minNodeCount).toNumber(); + + if (!minNodeCountInt) { + throw new Error('❌ Minimum validator count is not set'); + } + + if ( + contractInfo.details.activeUnkickedValidators.length < minNodeCountInt + ) { + throw new Error( + `❌ Active validator set does not meet the threshold. Required: ${minNodeCountInt} but got: ${contractInfo.details.activeUnkickedValidators.length}` + ); + } + const activeValidatorStructs: ValidatorStruct[] = + contractInfo.details.activeUnkickedValidators.map((item: any) => { + return { + ip: item[0], + ipv6: item[1], + port: item[2], + nodeAddress: item[3], + reward: item[4], + seconderPubkey: item[5], + receiverPubkey: item[6], + }; + }); + + const networks = activeValidatorStructs.map((item: ValidatorStruct) => { + // Convert the integer IP to a string format + const ip = intToIP(item.ip); + const port = item.port; + + // Determine the protocol to use based on various conditions + const protocol = + // If nodeProtocol is defined, use it + nodeProtocol || + // If port is 443, use HTTPS, otherwise use network-specific HTTP + (port === 443 ? HTTPS : HTTP_BY_NETWORK[network]) || + // Fallback to HTTP if no other conditions are met + HTTP; + + const url = `${protocol}${ip}:${port}`; + + LitContracts.logger.debug("Validator's URL:", url); + + return url; + }); + + stakingAggregateDetails.push({ + stakingContract: stakingContract, + epochInfo: typedEpochInfo, + minNodeCount: minNodeCountInt, + bootstrapUrls: networks, + }); + } + return stakingAggregateDetails; + } + /** * Retrieves the connection information for a given network. * @@ -1075,19 +1191,51 @@ export class LitContracts { networkContext, rpcUrl, nodeProtocol, + networkType, }: { litNetwork: LIT_NETWORKS_KEYS; networkContext?: LitContractContext | LitContractResolverContext; rpcUrl?: string; nodeProtocol?: typeof HTTP | typeof HTTPS | null; + networkType?: 'mainnet' | 'cloneNet'; }): Promise<{ - stakingContract: ethers.Contract; epochInfo: EpochInfo; minNodeCount: number; bootstrapUrls: string[]; }> => { - const stakingContract = await LitContracts.getStakingContract( + console.log('networkType:', networkType); + + if (litNetwork === 'datil-test') { + const connectionInfoWithCloneNet = + await LitContracts._getAllActiveUnkickedValidatorStructsAndCounts( + litNetwork, + networkContext, + rpcUrl + ); + + const cloneNetInfo = connectionInfoWithCloneNet[0]; + const mainNetInfo = connectionInfoWithCloneNet[1]; + + // Randomly select network type if not specified + if (!networkType) { + networkType = + Math.floor(Math.random() * 100) % 2 === 0 ? 'mainnet' : 'cloneNet'; + log('Randomly selected network type:', networkType); + } + + log('Selected network type:', networkType); + + // Return info based on network type + if (networkType === 'mainnet') { + return mainNetInfo; + } else { + return cloneNetInfo; + } + } + + const stakingContract = await LitContracts.getContractInstance( litNetwork, + 'Staking', networkContext, rpcUrl ); @@ -1152,7 +1300,6 @@ export class LitContracts { }); return { - stakingContract, epochInfo: typedEpochInfo, minNodeCount: minNodeCountInt, bootstrapUrls: networks, @@ -1189,11 +1336,13 @@ export class LitContracts { } // Normalize the data to the LitContractContext type - return data.data.map((c: any) => ({ + const normalisedData = data.data.map((c: any) => ({ address: c.contracts[0].address_hash, abi: c.contracts[0].ABI, name: c.name, })); + + return normalisedData; } /** diff --git a/packages/core/package.json b/packages/core/package.json index ab992376b..88b5bc964 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -24,7 +24,5 @@ }, "tags": [ "universal" - ], - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + ] } diff --git a/packages/core/src/lib/lit-core.ts b/packages/core/src/lib/lit-core.ts index d32c7b1ab..c00c0f679 100644 --- a/packages/core/src/lib/lit-core.ts +++ b/packages/core/src/lib/lit-core.ts @@ -112,6 +112,7 @@ export type LitNodeClientConfigWithDefaults = Required< bootstrapUrls: string[]; } & { nodeProtocol?: typeof HTTP | typeof HTTPS | null; + networkType?: 'mainnet' | 'cloneNet'; }; // On epoch change, we wait this many seconds for the nodes to update to the new epoch before using the new epoch # @@ -145,6 +146,7 @@ export class LitCore { minNodeCount: 2, // Default value, should be replaced bootstrapUrls: [], // Default value, should be replaced nodeProtocol: null, + networkType: undefined, }; connectedNodes = new Set(); serverKeys: Record = {}; @@ -246,18 +248,28 @@ export class LitCore { * @returns An object containing the validator data. * @throws Error if minNodeCount is not provided, is less than or equal to 0, or if bootstrapUrls are not available. */ - private async _getValidatorData(): Promise<{ + private async _getValidatorData( + networkType: 'mainnet' | 'cloneNet' + ): Promise<{ stakingContract: ethers.Contract; epochInfo: EpochInfo; minNodeCount: number; bootstrapUrls: string[]; }> { - const { stakingContract, epochInfo, minNodeCount, bootstrapUrls } = + const stakingContract = await LitContracts.getContractInstance( + this.config.litNetwork, + 'Staking', + this.config.contractContext, + this.config.rpcUrl + ); + + const { epochInfo, minNodeCount, bootstrapUrls } = await LitContracts.getConnectionInfo({ litNetwork: this.config.litNetwork, networkContext: this.config.contractContext, rpcUrl: this.config.rpcUrl, nodeProtocol: this.config.nodeProtocol, + networkType, }); // Validate minNodeCount @@ -291,13 +303,22 @@ export class LitCore { }; } + private _getNetworkType = (): 'mainnet' | 'cloneNet' => { + const networkType = + this.config.networkType || Math.floor(Math.random() * 100) % 2 === 0 + ? 'mainnet' + : 'cloneNet'; + + return networkType; + }; + // ========== Scoped Class Helpers ========== private async _handleStakingContractStateChange( state: STAKING_STATES_VALUES ) { log(`New state detected: "${state}"`); - const validatorData = await this._getValidatorData(); + const validatorData = await this._getValidatorData(this._getNetworkType()); if (state === STAKING_STATES.Active) { // We always want to track the most recent epoch number on _all_ networks @@ -519,7 +540,7 @@ export class LitCore { // Re-use staking contract instance from previous connect() executions that succeeded to improve performance // noinspection ES6MissingAwait - intentionally not `awaiting` so we can run this in parallel below - const validatorData = await this._getValidatorData(); + const validatorData = await this._getValidatorData(this._getNetworkType()); this._stakingContract = validatorData.stakingContract; this.config.minNodeCount = validatorData.minNodeCount; @@ -952,7 +973,9 @@ export class LitCore { 'epochinfo not found. Not a problem, fetching current epoch state from staking contract' ); try { - const validatorData = await this._getValidatorData(); + const validatorData = await this._getValidatorData( + this._getNetworkType() + ); epochInfo = validatorData.epochInfo; } catch (error) { throw new UnknownError( diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 1b38d2d53..af0fe8b07 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -21,7 +21,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 16ecac0d0..d3c7aa5c8 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -25,7 +25,5 @@ "crypto": false, "stream": false }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/lit-auth-client/package.json b/packages/lit-auth-client/package.json index 08cdca053..ccb4671f2 100644 --- a/packages/lit-auth-client/package.json +++ b/packages/lit-auth-client/package.json @@ -28,7 +28,5 @@ "peerDependencies": { "@simplewebauthn/browser": "^7.2.0", "@simplewebauthn/typescript-types": "^7.0.0" - }, - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + } } diff --git a/packages/lit-node-client-nodejs/package.json b/packages/lit-node-client-nodejs/package.json index bdc31645e..aa4af9796 100644 --- a/packages/lit-node-client-nodejs/package.json +++ b/packages/lit-node-client-nodejs/package.json @@ -24,7 +24,5 @@ "tags": [ "nodejs" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/lit-node-client/package.json b/packages/lit-node-client/package.json index 8b91624b5..424246d68 100644 --- a/packages/lit-node-client/package.json +++ b/packages/lit-node-client/package.json @@ -28,7 +28,5 @@ "crypto": false, "stream": false }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/logger/package.json b/packages/logger/package.json index 22f2be0c5..056645dad 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -8,7 +8,5 @@ "publishConfig": { "access": "public", "directory": "../../dist/packages/logger" - }, - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + } } diff --git a/packages/misc-browser/package.json b/packages/misc-browser/package.json index b077484d2..a2f801989 100644 --- a/packages/misc-browser/package.json +++ b/packages/misc-browser/package.json @@ -21,7 +21,5 @@ "tags": [ "browser" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/misc/package.json b/packages/misc/package.json index e7268b0fd..b180d109f 100644 --- a/packages/misc/package.json +++ b/packages/misc/package.json @@ -21,7 +21,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/nacl/package.json b/packages/nacl/package.json index 5f0b433a1..dcbbd1d08 100644 --- a/packages/nacl/package.json +++ b/packages/nacl/package.json @@ -21,7 +21,5 @@ "access": "public", "directory": "../../dist/packages/nacl" }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/pkp-base/package.json b/packages/pkp-base/package.json index 992e3b585..8c08ef14d 100644 --- a/packages/pkp-base/package.json +++ b/packages/pkp-base/package.json @@ -24,7 +24,5 @@ }, "tags": [ "universal" - ], - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + ] } diff --git a/packages/pkp-cosmos/package.json b/packages/pkp-cosmos/package.json index 4bfe481c5..d82ca4a2b 100644 --- a/packages/pkp-cosmos/package.json +++ b/packages/pkp-cosmos/package.json @@ -24,7 +24,5 @@ }, "tags": [ "universal" - ], - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + ] } diff --git a/packages/pkp-ethers/package.json b/packages/pkp-ethers/package.json index 8facbc9b2..b42e3849a 100644 --- a/packages/pkp-ethers/package.json +++ b/packages/pkp-ethers/package.json @@ -20,7 +20,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/pkp-sui/package.json b/packages/pkp-sui/package.json index dfb4c6fbe..e7eb83c6e 100644 --- a/packages/pkp-sui/package.json +++ b/packages/pkp-sui/package.json @@ -24,7 +24,5 @@ }, "tags": [ "universal" - ], - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + ] } diff --git a/packages/pkp-walletconnect/package.json b/packages/pkp-walletconnect/package.json index b3271f8f0..e3b3780e5 100644 --- a/packages/pkp-walletconnect/package.json +++ b/packages/pkp-walletconnect/package.json @@ -31,7 +31,5 @@ }, "tags": [ "universal" - ], - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + ] } diff --git a/packages/types/package.json b/packages/types/package.json index 2d9edf51e..f4ab9e4de 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -23,7 +23,5 @@ "buildOptions": { "genReact": false }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/types/src/lib/interfaces.ts b/packages/types/src/lib/interfaces.ts index 24f4def9e..222c268fe 100644 --- a/packages/types/src/lib/interfaces.ts +++ b/packages/types/src/lib/interfaces.ts @@ -187,6 +187,7 @@ export interface LitNodeClientConfig { storageProvider?: StorageProvider; defaultAuthCallback?: (authSigParams: AuthCallbackParams) => Promise; rpcUrl?: string; + networkType?: 'mainnet' | 'cloneNet'; } export type CustomNetwork = Pick< diff --git a/packages/types/src/lib/types.ts b/packages/types/src/lib/types.ts index 2f6c56b7c..3bfef4841 100644 --- a/packages/types/src/lib/types.ts +++ b/packages/types/src/lib/types.ts @@ -201,6 +201,7 @@ export interface ExclusiveLitContractContext { RateLimitNFT: LitContract; Staking: LitContract; StakingBalances: LitContract; + CloneNet: LitContract; } export interface LitContractContext extends ExclusiveLitContractContext { [index: string]: string | any; diff --git a/packages/uint8arrays/package.json b/packages/uint8arrays/package.json index c2d1126b1..d4afcf31e 100644 --- a/packages/uint8arrays/package.json +++ b/packages/uint8arrays/package.json @@ -21,7 +21,5 @@ "tags": [ "universal" ], - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/wasm/package.json b/packages/wasm/package.json index 572442a70..41e5b33f6 100644 --- a/packages/wasm/package.json +++ b/packages/wasm/package.json @@ -28,7 +28,5 @@ "rust:build": "wasm-pack build ./rust --target web --release --out-name wasm-internal && yarn rust:postbuild", "rust:postbuild": "node scripts/copyWasmBinary.mjs && rm -rf src/pkg && mkdir src/pkg && mv rust/pkg/wasm-internal.js src/pkg && mv rust/pkg/wasm-internal.d.ts src/pkg", "rust:build:debug": "wasm-pack build ./rust --target web --dev --out-name wasm-internal && yarn rust:postbuild" - }, - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + } } diff --git a/packages/wrapped-keys-lit-actions/package.json b/packages/wrapped-keys-lit-actions/package.json index f63c57b31..d18943ed3 100644 --- a/packages/wrapped-keys-lit-actions/package.json +++ b/packages/wrapped-keys-lit-actions/package.json @@ -26,7 +26,5 @@ "scripts": { "generate-lit-actions": "yarn node ./esbuild.config.js" }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/packages/wrapped-keys/package.json b/packages/wrapped-keys/package.json index 1fd777ef1..efeaef6c0 100644 --- a/packages/wrapped-keys/package.json +++ b/packages/wrapped-keys/package.json @@ -23,7 +23,5 @@ "buildOptions": { "genReact": false }, - "version": "7.0.0", - "main": "./dist/src/index.js", - "typings": "./dist/src/index.d.ts" + "version": "7.0.0" } diff --git a/yarn.lock b/yarn.lock index 452aa24cc..73f9772e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3042,10 +3042,10 @@ dependencies: ajv "^8.12.0" -"@lit-protocol/contracts@^0.0.63": - version "0.0.63" - resolved "https://registry.yarnpkg.com/@lit-protocol/contracts/-/contracts-0.0.63.tgz#8700c37df9d2422e9c97aa27871fb64de6186f6c" - integrity sha512-CAorNt72ybIY/g//dDeR837izNGuYQR99XwPSK2X2AJ6c+aZX1kdXCrOnxsbY40BzFrOk/dIFo+ymJ9E3qh48w== +"@lit-protocol/contracts@feature-clonenet": + version "0.0.74-local-publish" + resolved "https://registry.yarnpkg.com/@lit-protocol/contracts/-/contracts-0.0.74-local-publish.tgz#72041c70713678a4227552a4bbdcc5015cee9004" + integrity sha512-r2rbmN9zGII9N3VggqIx4QCqOcpVbsZZAbs/4sHTkQIZK/QR51TQ+0Woei/sCE3hL/hnky0NWty14icJ0dko9w== "@ljharb/resumer@~0.0.1": version "0.0.1" @@ -6866,7 +6866,7 @@ argv-formatter@~1.0.0: resolved "https://registry.yarnpkg.com/argv-formatter/-/argv-formatter-1.0.0.tgz#a0ca0cbc29a5b73e836eebe1cbf6c5e0e4eb82f9" integrity sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw== -aria-query@5.1.3: +aria-query@5.1.3, aria-query@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== @@ -7176,7 +7176,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axe-core@^4.10.0: +axe-core@^4.10.0, axe-core@^4.9.1: version "4.10.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== @@ -7218,6 +7218,13 @@ axobject-query@^4.1.0: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== +axobject-query@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" + integrity sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg== + dependencies: + deep-equal "^2.0.5" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -11085,7 +11092,7 @@ es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-iterator-helpers@^1.1.0: +es-iterator-helpers@^1.0.19, es-iterator-helpers@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz#2f1a3ab998b30cb2d10b195b587c6d9ebdebf152" integrity sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q== @@ -21986,7 +21993,7 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.includes@^2.0.1: +string.prototype.includes@^2.0.0, string.prototype.includes@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==