diff --git a/docs/classes/ERC725.md b/docs/classes/ERC725.md index c6a41019..bf276aca 100644 --- a/docs/classes/ERC725.md +++ b/docs/classes/ERC725.md @@ -1446,6 +1446,7 @@ On non instantiated class, you should provide an `options` object. | :-------- | :----- | :------------------------------------------------------------------- | | `address` | string | Address of the smart contract to check against a certain interface. | | `rpcUrl` | string | RPC URL to connect to the network the smart contract is deployed to. | +| `gas` | number | Optional: gas parameter to use. Default: 1_000_000. | #### Returns @@ -1473,6 +1474,7 @@ myErc725.supportsInterface('LSP0ERC725Account'); ERC725.supportsInterface('LSP0ERC725Account', { address: '0x0Dc07C77985fE31996Ed612F568eb441afe5768D', rpcUrl: 'https://rpc.testnet.lukso.network', + gas: 20_000_000, }); // true ``` diff --git a/docs/getting-started.md b/docs/getting-started.md index cbe47702..e2e0a4ed 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -61,6 +61,7 @@ const address = '0x0Dc07C77985fE31996Ed612F568eb441afe5768D'; const RPC_URL = 'https://rpc.testnet.lukso.network'; const config = { ipfsGateway: 'https://YOUR-IPFS-GATEWAY/ipfs/', + gas: 20_000_000, // optional, default is 1_000_000 }; const erc725 = new ERC725(schemas, address, RPC_URL, config); @@ -110,7 +111,7 @@ await erc725.fetchData('LSP3Profile'); // downloads and verifies the linked JSON ``` :::tip Try it out -You can run the code snippit within your browser using the corresponding [StackBlitz example](https://stackblitz.com/edit/erc725js-instantiation?devtoolsheight=66&file=index.js). +You can run the code snippet within your browser using the corresponding [StackBlitz example](https://stackblitz.com/edit/erc725js-instantiation?devtoolsheight=66&file=index.js). :::note Whenever you can you should import `ERC725` via the named export. However currently we are also providing a default export. @@ -127,6 +128,7 @@ After the instance has been created, it is still possible to change settings thr myERC725.options.schema = '' // change schema myERC725.options.address '
' // change address myERC725.options.ipfsGateway = '' // used for fetchData(), default: 'https://cloudflare-ipfs.com/ipfs/' +myERC725.options.gas = 20_000_000 // change gas setting // NOTE: ERC725.provider can not be changed ``` diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 4915183d..5a9ce435 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -58,47 +58,35 @@ export const METHODS: Record = { [Method.GET_DATA_LEGACY]: { // Legacy version of ERC725Y - before v0.3.0 sig: '0x54f6127f', - gas: numberToHex(2000000), - gasPrice: numberToHex(100000000), value: numberToHex(0), returnEncoding: Encoding.BYTES, }, [Method.GET_DATA]: { // https://github.com/ERC725Alliance/ERC725/blob/v4.0.0/docs/ERC-725.md#erc725y sig: '0x4e3e6e9c', - gas: numberToHex(2000000), - gasPrice: numberToHex(100000000), value: numberToHex(0), returnEncoding: Encoding.BYTES_ARRAY, }, [Method.GET_DATA_BATCH]: { // https://github.com/ERC725Alliance/ERC725/blob/v5.1.0/docs/ERC-725.md#erc725y sig: '0xdedff9c6', - gas: numberToHex(2000000), - gasPrice: numberToHex(100000000), value: numberToHex(0), returnEncoding: Encoding.BYTES_ARRAY, }, [Method.OWNER]: { sig: '0x8da5cb5b', - gas: numberToHex(2000000), - gasPrice: numberToHex(100000000), value: numberToHex(0), returnEncoding: Encoding.ADDRESS, }, [Method.SUPPORTS_INTERFACE]: { // https://eips.ethereum.org/EIPS/eip-165 sig: '0x01ffc9a7', - gas: numberToHex(2000000), - gasPrice: numberToHex(100000000), value: numberToHex(0), returnEncoding: Encoding.BOOL, }, [Method.IS_VALID_SIGNATURE]: { // https://eips.ethereum.org/EIPS/eip-1271 sig: '0x1626ba7e', - gas: numberToHex(2000000), - gasPrice: numberToHex(100000000), value: numberToHex(0), returnEncoding: Encoding.BYTES4, }, @@ -183,3 +171,5 @@ export const LSP6_ALL_PERMISSIONS = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; export const COMPACT_BYTES_ARRAY_STRING = '[CompactBytesArray]'; + +export const DEFAULT_GAS_VALUE = 1_000_000; diff --git a/src/index.ts b/src/index.ts index 6a07e404..4d37d9be 100644 --- a/src/index.ts +++ b/src/index.ts @@ -37,6 +37,7 @@ import { isValidSignature } from './lib/isValidSignature'; import { LSP6_ALL_PERMISSIONS, LSP6_DEFAULT_PERMISSIONS, + DEFAULT_GAS_VALUE, } from './constants/constants'; import { encodeKeyName, isDynamicKeyName } from './lib/encodeKeyName'; @@ -80,7 +81,7 @@ export { encodeData } from './lib/utils'; * */ export class ERC725 { - options: ERC725Options & ERC725Config; + options: ERC725Options; /** * Creates an instance of ERC725. @@ -105,15 +106,20 @@ export class ERC725 { const defaultConfig = { ipfsGateway: 'https://cloudflare-ipfs.com/ipfs/', + gas: DEFAULT_GAS_VALUE, }; this.options = { schemas: this.validateSchemas(schemas), address, - provider: ERC725.initializeProvider(provider), + provider: ERC725.initializeProvider( + provider, + config?.gas ? config?.gas : defaultConfig.gas, + ), ipfsGateway: config?.ipfsGateway ? convertIPFSGatewayUrl(config?.ipfsGateway) : defaultConfig.ipfsGateway, + gas: config?.gas ? config?.gas : defaultConfig.gas, }; } @@ -151,20 +157,20 @@ export class ERC725 { }); } - private static initializeProvider(providerOrRpcUrl) { + private static initializeProvider(providerOrRpcUrl, gasInfo) { // do not fail on no-provider if (!providerOrRpcUrl) return undefined; // if provider is a string, assume it's a rpcUrl if (typeof providerOrRpcUrl === 'string') { - return new ProviderWrapper(new HttpProvider(providerOrRpcUrl)); + return new ProviderWrapper(new HttpProvider(providerOrRpcUrl), gasInfo); } if ( typeof providerOrRpcUrl.request === 'function' || typeof providerOrRpcUrl.send === 'function' ) - return new ProviderWrapper(providerOrRpcUrl); + return new ProviderWrapper(providerOrRpcUrl, gasInfo); throw new Error(`Incorrect or unsupported provider ${providerOrRpcUrl}`); } @@ -593,12 +599,12 @@ export class ERC725 { * supports a certain interface. * * @param {string} interfaceIdOrName Interface ID or supported interface name. - * @param options Object of address and RPC URL. + * @param options Object of address, RPC URL and optional gas. * @returns {Promise} if interface is supported. */ static async supportsInterface( interfaceIdOrName: string, - options: { address: string; rpcUrl: string }, + options: { address: string; rpcUrl: string; gas?: number }, ): Promise { if (!isAddress(options.address)) { throw new Error('Invalid address'); @@ -609,7 +615,10 @@ export class ERC725 { return supportsInterface(interfaceIdOrName, { address: options.address, - provider: this.initializeProvider(options.rpcUrl), + provider: this.initializeProvider( + options.rpcUrl, + options?.gas ? options?.gas : DEFAULT_GAS_VALUE, + ), }); } diff --git a/src/lib/provider-wrapper-utils.ts b/src/lib/provider-wrapper-utils.ts index 5f2adf67..0a0d52a0 100644 --- a/src/lib/provider-wrapper-utils.ts +++ b/src/lib/provider-wrapper-utils.ts @@ -13,6 +13,7 @@ */ import * as abi from 'web3-eth-abi'; +import { numberToHex } from 'web3-utils'; import { JsonRpc, @@ -49,6 +50,7 @@ export function decodeResult(method: Method, hexString: string) { const constructJSONRPCParams = ( address: string, method: Method, + gasInfo: number, methodParam?: string, ): JsonRpcEthereumProviderParamsWithLatest => { const data = methodParam @@ -59,7 +61,7 @@ const constructJSONRPCParams = ( { to: address, value: METHODS[method].value, - gas: METHODS[method].gas, + gas: numberToHex(gasInfo), data, }, 'latest', @@ -69,13 +71,14 @@ const constructJSONRPCParams = ( export function constructJSONRPC( address: string, method: Method, + gasInfo: number, methodParam?: string, ): JsonRpc { idCount += 1; return { jsonrpc: '2.0', method: 'eth_call', - params: constructJSONRPCParams(address, method, methodParam), + params: constructJSONRPCParams(address, method, gasInfo, methodParam), id: idCount, }; } diff --git a/src/provider/providerWrapper.test.ts b/src/provider/providerWrapper.test.ts index 91748eb3..fa655712 100644 --- a/src/provider/providerWrapper.test.ts +++ b/src/provider/providerWrapper.test.ts @@ -3,6 +3,7 @@ import assert from 'assert'; import { ProviderWrapper } from './providerWrapper'; const erc725AccountAddress = '0x214be121bB52e6909c5158579b3458f8760f1b2f'; +const defaultGas = 1_000_000; describe('ProviderWrapper', () => { describe('#getOwner', () => { @@ -15,7 +16,7 @@ describe('ProviderWrapper', () => { }); }, }; - const ethSource = new ProviderWrapper(mockProvider); + const ethSource = new ProviderWrapper(mockProvider, defaultGas); const owner = await ethSource.getOwner(erc725AccountAddress); assert.deepStrictEqual( @@ -30,7 +31,7 @@ describe('ProviderWrapper', () => { cb(new Error('some error')); }, }; - const ethSource = new ProviderWrapper(mockProvider); + const ethSource = new ProviderWrapper(mockProvider, defaultGas); try { await ethSource.getOwner(erc725AccountAddress); @@ -47,7 +48,7 @@ describe('ProviderWrapper', () => { }); }, }; - const ethSource = new ProviderWrapper(mockProvider); + const ethSource = new ProviderWrapper(mockProvider, defaultGas); try { await ethSource.getOwner(erc725AccountAddress); diff --git a/src/provider/providerWrapper.ts b/src/provider/providerWrapper.ts index 3f7026db..a3f235d1 100644 --- a/src/provider/providerWrapper.ts +++ b/src/provider/providerWrapper.ts @@ -40,18 +40,20 @@ interface GetDataReturn { export class ProviderWrapper { type: ProviderTypes; provider: any; - constructor(provider: any) { + gas: number; + constructor(provider: any, gasInfo: number) { if (typeof provider.request === 'function') { this.type = ProviderTypes.ETHEREUM; } else { this.type = ProviderTypes.WEB3; } this.provider = provider; + this.gas = gasInfo; } async getOwner(address: string) { const result = await this.callContract( - constructJSONRPC(address, Method.OWNER), + constructJSONRPC(address, Method.OWNER, this.gas), ); if (result.error) { throw result.error; @@ -115,6 +117,7 @@ export class ProviderWrapper { constructJSONRPC( address, Method.SUPPORTS_INTERFACE, + this.gas, `${interfaceId}${'00000000000000000000000000000000000000000000000000000000'}`, ), ); @@ -152,7 +155,12 @@ export class ProviderWrapper { ); const result = await this.callContract( - constructJSONRPC(address, Method.IS_VALID_SIGNATURE, encodedParams), + constructJSONRPC( + address, + Method.IS_VALID_SIGNATURE, + this.gas, + encodedParams, + ), ); if (result.error) { @@ -172,7 +180,12 @@ export class ProviderWrapper { ); const results = await this.callContract([ - constructJSONRPC(address, Method.IS_VALID_SIGNATURE, encodedParams), + constructJSONRPC( + address, + Method.IS_VALID_SIGNATURE, + this.gas, + encodedParams, + ), ]); if (results.error) { throw results.error; @@ -232,6 +245,7 @@ export class ProviderWrapper { constructJSONRPC( address, method, + this.gas, abiCoder.encodeParameter('bytes32[]', keyHashes), ), ); @@ -248,6 +262,7 @@ export class ProviderWrapper { constructJSONRPC( address, method, + this.gas, abiCoder.encodeParameter('bytes32[]', keyHashes), ), ]; @@ -270,7 +285,7 @@ export class ProviderWrapper { // But this is already legacy and it won't be used anymore.. const encodedResultsPromises = keyHashes.map((keyHash) => this.callContract( - constructJSONRPC(address, Method.GET_DATA_LEGACY, keyHash), + constructJSONRPC(address, Method.GET_DATA_LEGACY, this.gas, keyHash), ), ); @@ -287,7 +302,12 @@ export class ProviderWrapper { // But this is already legacy and it won't be used anymore.. for (let index = 0; index < keyHashes.length; index++) { payload.push( - constructJSONRPC(address, Method.GET_DATA_LEGACY, keyHashes[index]), + constructJSONRPC( + address, + Method.GET_DATA_LEGACY, + this.gas, + keyHashes[index], + ), ); } diff --git a/src/types/Config.ts b/src/types/Config.ts index 24e4ab33..dd592c49 100644 --- a/src/types/Config.ts +++ b/src/types/Config.ts @@ -5,16 +5,20 @@ export interface ERC725Config { * ```js title=Example * const config = { * ipfsGateway: 'https://ipfs.lukso.network/ipfs/' + * gas: 20_000_000 // Optional, default 0 * }; * ``` * Make sure to use the following format: `/ipfs/`.
* Another example: `https://cloudflare-ipfs.com/ipfs/` */ - ipfsGateway: string; + ipfsGateway?: string; + gas?: number; } export interface ERC725Options { schemas: ERC725JSONSchema[]; address?: string; provider?; + ipfsGateway: string; + gas: number; } diff --git a/src/types/Method.ts b/src/types/Method.ts index e28b49ab..1c794a67 100644 --- a/src/types/Method.ts +++ b/src/types/Method.ts @@ -19,8 +19,6 @@ export enum Encoding { export interface MethodData { sig: string; - gas: string; - gasPrice: string; value: string; returnEncoding: Encoding; }