Skip to content

Commit

Permalink
fix: LIT-3607 - Use StaticJsonRpcProvider to reduce cost of RPC requests
Browse files Browse the repository at this point in the history
Reference issue - ethers-io/ethers.js#901
Cuts our RPC request cost approx in half by eliminating a sequential call to get `chainId` from every(!) contract call we make
  • Loading branch information
MaximusHaximus committed Jul 16, 2024
1 parent c92dc39 commit 78e85e4
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 44 deletions.
2 changes: 1 addition & 1 deletion local-tests/setup/shiva-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export class TestnetClient {
const networkContext = {
abi: JSON.parse(contractResolverAbi),
resolverAddress: contractResolverAddress,
provider: new ethers.providers.JsonRpcProvider(
provider: new ethers.providers.StaticJsonRpcProvider(
`http://${testNetConfig.rpcUrl}`
),
environment: 0, // test deployment uses env value 0 in test common
Expand Down
6 changes: 4 additions & 2 deletions local-tests/setup/tinny-person.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class TinnyPerson {
ethers.utils.keccak256([1, 2, 3, 4, 5])
);

public provider: ethers.providers.JsonRpcProvider;
public provider: ethers.providers.StaticJsonRpcProvider;

public envConfig: TinnyEnvConfig;

Expand All @@ -45,7 +45,9 @@ export class TinnyPerson {
this.envConfig = envConfig;

this.privateKey = privateKey;
this.provider = new ethers.providers.JsonRpcProvider(this.envConfig.rpc);
this.provider = new ethers.providers.StaticJsonRpcProvider(
this.envConfig.rpc
);
this.wallet = new ethers.Wallet(privateKey, this.provider);
}

Expand Down
18 changes: 10 additions & 8 deletions packages/contracts-sdk/src/lib/addresses.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { rawSecp256k1PubkeyToRawAddress } from '@cosmjs/amino';
import { Secp256k1 } from '@cosmjs/crypto';
import { toBech32 } from '@cosmjs/encoding';
import * as bitcoinjs from 'bitcoinjs-lib';
import { Contract, ethers } from 'ethers';
import { computeAddress } from 'ethers/lib/utils';
import { PKPNFTData } from '../abis/PKPNFT.sol/PKPNFTData';
import { toBech32 } from '@cosmjs/encoding';
import { Secp256k1 } from '@cosmjs/crypto';

import { rawSecp256k1PubkeyToRawAddress } from '@cosmjs/amino';
export type TokenInfo = {
import { PKPNFTData } from '../abis/PKPNFT.sol/PKPNFTData';
export interface TokenInfo {
tokenId: string;
publicKey: string;
publicKeyBuffer: Buffer;
ethAddress: string;
btcAddress: string;
cosmosAddress: string;
isNewPKP: boolean;
};
}

export const derivedAddresses = async ({
publicKey,
Expand Down Expand Up @@ -64,7 +64,9 @@ export const derivedAddresses = async ({
if (cachedPkpJSON[pkpTokenId]) {
publicKey = cachedPkpJSON[pkpTokenId];
} else {
const provider = new ethers.providers.JsonRpcProvider(defaultRPCUrl);
const provider = new ethers.providers.StaticJsonRpcProvider(
defaultRPCUrl
);

const contract = new Contract(
pkpContractAddress,
Expand All @@ -89,7 +91,7 @@ export const derivedAddresses = async ({
cachedPkpJSON[pkpTokenId] = publicKey;
localStorage.setItem(CACHE_KEY, JSON.stringify(cachedPkpJSON));
} else {
const cachedPkpJSON: { [key: string]: any } = {};
const cachedPkpJSON: Record<string, any> = {};
cachedPkpJSON[pkpTokenId] = publicKey;
localStorage.setItem(CACHE_KEY, JSON.stringify(cachedPkpJSON));
}
Expand Down
5 changes: 0 additions & 5 deletions packages/contracts-sdk/src/lib/contracts-sdk.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { LitContracts } from './contracts-sdk';
import { ethers } from 'ethers';
import { LitContract } from '../../../types/src/lib/types';

describe('contractsSdk', () => {
let litContracts: LitContracts;
let litContracts_privateKeySigner: LitContracts;

beforeEach(() => {
litContracts = new LitContracts();
Expand All @@ -29,8 +26,6 @@ describe('contractsSdk', () => {
});

it('Test that connection from custom context resolves contracts in correct mapping', async () => {
const DEFAULT_RPC = 'https://chain-rpc.litprotocol.com/http';
const provider = new ethers.providers.JsonRpcProvider(DEFAULT_RPC);
litContracts = new LitContracts({
customContext: {
Allowlist: {
Expand Down
17 changes: 9 additions & 8 deletions packages/contracts-sdk/src/lib/contracts-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const GAS_LIMIT = ethers.utils.hexlify(5000000); // Adjust as needed
// The class has a number of properties that represent the smart contract instances, such as accessControlConditionsContract, litTokenContract, pkpNftContract, etc. These smart contract instances are created by passing the contract address, ABI, and provider to the ethers.Contract constructor.
// The class also has a utils object with helper functions for converting between hexadecimal and decimal representation of numbers, as well as functions for working with multihashes and timestamps.
export class LitContracts {
provider: ethers.providers.JsonRpcProvider | any;
provider: ethers.providers.StaticJsonRpcProvider | any;
rpc: string;
rpcs: string[];
signer: ethers.Signer | ethers.Wallet;
Expand Down Expand Up @@ -180,7 +180,7 @@ export class LitContracts {

// make the constructor args optional
constructor(args?: {
provider?: ethers.providers.JsonRpcProvider | any;
provider?: ethers.providers.StaticJsonRpcProvider | any;
customContext?: LitContractContext | LitContractResolverContext;
rpcs?: string[] | any;
rpc?: string | any;
Expand Down Expand Up @@ -301,7 +301,7 @@ export class LitContracts {
// ----------------------------------------------
else if (isNode()) {
this.log("----- We're in node! -----");
this.provider = new ethers.providers.JsonRpcProvider(this.rpc);
this.provider = new ethers.providers.StaticJsonRpcProvider(this.rpc);
}

// ======================================
Expand Down Expand Up @@ -580,11 +580,12 @@ export class LitContracts {
rpcUrl?: string
) {
let provider: ethers.providers.JsonRpcProvider;
let provider: ethers.providers.StaticJsonRpcProvider;
rpcUrl = RPC_URL_BY_NETWORK[network];
if (context && 'provider' in context!) {
provider = context.provider;
} else {
provider = new ethers.providers.JsonRpcProvider(rpcUrl);
provider = new ethers.providers.StaticJsonRpcProvider(rpcUrl);
}

if (network === 'datil-dev' || network === 'datil-test') {
Expand Down Expand Up @@ -647,7 +648,7 @@ export class LitContracts {

private static async _getContractsFromResolver(
context: LitContractResolverContext,
provider: ethers.providers.JsonRpcProvider,
provider: ethers.providers.StaticJsonRpcProvider,
contractNames?: (keyof LitContractContext)[]
): Promise<LitContractContext> {
const resolverContract = new ethers.Contract(
Expand Down Expand Up @@ -766,7 +767,7 @@ export class LitContracts {

public static async getContractAddresses(
network: LIT_NETWORKS_KEYS,
provider: ethers.providers.JsonRpcProvider,
provider: ethers.providers.StaticJsonRpcProvider,
context?: LitContractContext | LitContractResolverContext
) {
let contractData;
Expand Down Expand Up @@ -1356,7 +1357,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
// if (isBrowser()) {
// provider = new ethers.providers.Web3Provider(window.ethereum, 'any');
// } else {
// provider = new ethers.providers.JsonRpcProvider(this.rpc);
// provider = new ethers.providers.StaticJsonRpcProvider(this.rpc);
// }
// const signer = new ethers.Wallet(privateKey, provider);

Expand All @@ -1369,7 +1370,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
// if (isBrowser()) {
// provider = new ethers.providers.Web3Provider(window.ethereum, 'any');
// } else {
// provider = new ethers.providers.JsonRpcProvider(this.rpc);
// provider = new ethers.providers.StaticJsonRpcProvider(this.rpc);
// }
// const signer = new ethers.Wallet(privateKey, provider);

Expand Down
11 changes: 3 additions & 8 deletions packages/core/src/lib/lit-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import {
validateUnifiedAccessControlConditionsSchema,
} from '@lit-protocol/access-control-conditions';
import {
LIT_CHAINS,
LIT_CURVE,
LIT_ENDPOINT,
LIT_ERROR,
LIT_ERROR_CODE,
LIT_NETWORKS,
LitNetwork,
RPC_URL_BY_NETWORK,
StakingStates,
version,
} from '@lit-protocol/constants';
Expand Down Expand Up @@ -439,10 +439,6 @@ export class LitCore {
*/
getLatestBlockhash = async (): Promise<string> => {
await this._syncBlockhash();
console.log(
`querying latest blockhash current value is `,
this.latestBlockhash
);
if (!this.latestBlockhash) {
throw new Error(
`latestBlockhash is not available. Received: "${this.latestBlockhash}"`
Expand Down Expand Up @@ -488,15 +484,14 @@ export class LitCore {
if (!this.config.contractContext) {
this.config.contractContext = await LitContracts.getContractAddresses(
this.config.litNetwork,
new ethers.providers.JsonRpcProvider(
this.config.rpcUrl || LIT_CHAINS['lit'].rpcUrls[0]
new ethers.providers.StaticJsonRpcProvider(
this.config.rpcUrl || RPC_URL_BY_NETWORK[this.config.litNetwork]
)
);
} else if (
!this.config.contractContext.Staking &&
!this.config.contractContext.resolverAddress
) {
console.log(this.config.contractContext);
throw new Error(
'The provided contractContext was missing the "Staking" contract`'
);
Expand Down
19 changes: 7 additions & 12 deletions packages/pkp-ethers/src/lib/pkp-ethers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
import { Wordlist } from '@ethersproject/wordlists';
import { ethers, version, Wallet } from 'ethers';

import { LIT_CHAINS } from '@lit-protocol/constants';
import { RPC_URL_BY_NETWORK } from '@lit-protocol/constants';
import { PKPBase } from '@lit-protocol/pkp-base';
import {
PKPClientHelpers,
Expand All @@ -51,7 +51,6 @@ import {
ETHSignature,
ETHTxRes,
} from './pkp-ethers-types';
import { RPC_URL_BY_NETWORK } from '@lit-protocol/constants';

const logger = new Logger(version);

Expand All @@ -68,7 +67,7 @@ export class PKPEthersWallet
readonly address!: string;
readonly _isSigner!: boolean;

rpcProvider: ethers.providers.JsonRpcProvider;
rpcProvider: ethers.providers.StaticJsonRpcProvider;
provider!: Provider;

// -- manual tx settings --
Expand All @@ -88,16 +87,12 @@ export class PKPEthersWallet
prop.rpc || RPC_URL_BY_NETWORK[prop.litNodeClient.config.litNetwork];

if (!rpcUrl) {
throw new Error('No RPC URL provided');
}

this.rpcProvider = new ethers.providers.JsonRpcProvider(rpcUrl);

if (!rpcUrl) {
throw new Error('rpcUrl is required');
throw new Error(
`No RPC URL provided, and none could be found for ${prop.litNodeClient.config.litNetwork}`
);
}

this.rpcProvider = new ethers.providers.JsonRpcProvider(rpcUrl);
this.rpcProvider = new ethers.providers.StaticJsonRpcProvider(rpcUrl);
this.provider = prop.provider ?? this.rpcProvider;

defineReadOnly(this, '_isSigner', true);
Expand All @@ -114,7 +109,7 @@ export class PKPEthersWallet
};

setRpc = async (rpc: string): Promise<void> => {
this.rpcProvider = new ethers.providers.JsonRpcProvider(rpc);
this.rpcProvider = new ethers.providers.StaticJsonRpcProvider(rpc);
};

handleRequest = async <T = ETHSignature | ETHTxRes>(
Expand Down

0 comments on commit 78e85e4

Please sign in to comment.