Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/gas param #332

Merged
merged 4 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/classes/ERC725.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -1473,6 +1474,7 @@ myErc725.supportsInterface('LSP0ERC725Account');
ERC725.supportsInterface('LSP0ERC725Account', {
address: '0x0Dc07C77985fE31996Ed612F568eb441afe5768D',
rpcUrl: 'https://rpc.testnet.lukso.network',
gas: 20_000_000,
});
// true
```
4 changes: 3 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -127,6 +128,7 @@ After the instance has been created, it is still possible to change settings thr
myERC725.options.schema = '<schema>' // change schema
myERC725.options.address '<address>' // change address
myERC725.options.ipfsGateway = '<url>' // 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
```
14 changes: 2 additions & 12 deletions src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,47 +58,35 @@ export const METHODS: Record<Method, MethodData> = {
[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,
},
Expand Down Expand Up @@ -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;
25 changes: 17 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -80,7 +81,7 @@ export { encodeData } from './lib/utils';
*
*/
export class ERC725 {
options: ERC725Options & ERC725Config;
options: ERC725Options;

/**
* Creates an instance of ERC725.
Expand All @@ -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,
};
}

Expand Down Expand Up @@ -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}`);
}
Expand Down Expand Up @@ -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<boolean>} if interface is supported.
*/
static async supportsInterface(
interfaceIdOrName: string,
options: { address: string; rpcUrl: string },
options: { address: string; rpcUrl: string; gas?: number },
): Promise<boolean> {
if (!isAddress(options.address)) {
throw new Error('Invalid address');
Expand All @@ -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,
),
});
}

Expand Down
7 changes: 5 additions & 2 deletions src/lib/provider-wrapper-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/

import * as abi from 'web3-eth-abi';
import { numberToHex } from 'web3-utils';

import {
JsonRpc,
Expand Down Expand Up @@ -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
Expand All @@ -59,7 +61,7 @@ const constructJSONRPCParams = (
{
to: address,
value: METHODS[method].value,
gas: METHODS[method].gas,
gas: numberToHex(gasInfo),
data,
},
'latest',
Expand All @@ -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,
};
}
7 changes: 4 additions & 3 deletions src/provider/providerWrapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import assert from 'assert';
import { ProviderWrapper } from './providerWrapper';

const erc725AccountAddress = '0x214be121bB52e6909c5158579b3458f8760f1b2f';
const defaultGas = 1_000_000;

describe('ProviderWrapper', () => {
describe('#getOwner', () => {
Expand All @@ -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(
Expand All @@ -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);
Expand All @@ -47,7 +48,7 @@ describe('ProviderWrapper', () => {
});
},
};
const ethSource = new ProviderWrapper(mockProvider);
const ethSource = new ProviderWrapper(mockProvider, defaultGas);

try {
await ethSource.getOwner(erc725AccountAddress);
Expand Down
32 changes: 26 additions & 6 deletions src/provider/providerWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -115,6 +117,7 @@ export class ProviderWrapper {
constructJSONRPC(
address,
Method.SUPPORTS_INTERFACE,
this.gas,
`${interfaceId}${'00000000000000000000000000000000000000000000000000000000'}`,
),
);
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -232,6 +245,7 @@ export class ProviderWrapper {
constructJSONRPC(
address,
method,
this.gas,
abiCoder.encodeParameter('bytes32[]', keyHashes),
),
);
Expand All @@ -248,6 +262,7 @@ export class ProviderWrapper {
constructJSONRPC(
address,
method,
this.gas,
abiCoder.encodeParameter('bytes32[]', keyHashes),
),
];
Expand All @@ -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),
),
);

Expand All @@ -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],
),
);
}

Expand Down
6 changes: 5 additions & 1 deletion src/types/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: `<url>/ipfs/`.<br/>
* 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;
}
2 changes: 0 additions & 2 deletions src/types/Method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ export enum Encoding {

export interface MethodData {
sig: string;
gas: string;
gasPrice: string;
value: string;
returnEncoding: Encoding;
}
Expand Down
Loading