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

refactor: support getDataBatch of 5.0.0 ERC725 release #294

Merged
merged 11 commits into from
Jul 14, 2023
18 changes: 17 additions & 1 deletion src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,17 @@ export const ERC725Y_INTERFACE_IDS = {
// - getData(bytes32[])
// - setData(bytes32[],bytes[])
'3.0': '0x714df77c',
// version 5.0.0 removed function overloading
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
// interface functions:
// - getData(bytes32)
// - setData(bytes32,bytes)
// - getDataBatch(bytes32[])
// - setDataBatch(bytes32[],bytes[])
'5.0': '0x629aa694',
};

export enum ERC725_VERSION {
ERC725_BATCH = 'ERC725_BATCH', // https://github.com/ERC725Alliance/ERC725/pull/209
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
ERC725 = 'ERC725', // https://github.com/ERC725Alliance/ERC725/commit/cca7f98cdf243f1ebf1c0a3ae89b1e46931481b0
ERC725_LEGACY = 'ERC725_LEGACY',
NOT_ERC725 = 'NOT_ERC725',
Expand All @@ -52,13 +60,21 @@ export const METHODS: Record<Method, MethodData> = {
returnEncoding: Encoding.BYTES,
},
[Method.GET_DATA]: {
// https://github.com/ERC725Alliance/erc725/blob/main/docs/ERC-725.md#erc725y
// 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
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
sig: '0xdedff9c6',
gas: numberToHex(2000000),
gasPrice: numberToHex(100000000),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we will need to make it dynamic at some point no? cc @CallumGrindle @magalimorin18

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats this being used for? The lib doesn't send any transactions does it?

value: numberToHex(0),
returnEncoding: Encoding.BYTES_ARRAY,
},
[Method.OWNER]: {
sig: '0x8da5cb5b',
gas: numberToHex(2000000),
Expand Down
50 changes: 50 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,56 @@ describe('Running @erc725/erc725.js tests...', () => {
});
});

describe('Getting data (using new getDataBatch) in schema by provider [e2e] - luksoTestnet', () => {
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
const web3 = new Web3('https://rpc.testnet.lukso.network');
const ERC725_BATCH_CONTRACT_ADDRESS =
'0x4b30900F119E11D2A8CAe18176c4f9840E586Cc4';

const e2eSchema: any = [
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
{
name: 'LSP3Profile',
key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5',
keyType: 'Singleton',
valueContent: 'JSONURL',
valueType: 'bytes',
},
{
name: 'LSP1UniversalReceiverDelegate',
key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47',
keyType: 'Singleton',
valueContent: 'Address',
valueType: 'address',
},
];

const e2eResults = [
{
name: 'LSP3Profile',
key: '0x5ef83ad9559033e6e941db7d7c495acdce616347d28e90c7ce47cbfcfcad3bc5',
value: {
hashFunction: 'keccak256(utf8)',
hash: '0x70546a2accab18748420b63c63b5af4cf710848ae83afc0c51dd8ad17fb5e8b3',
url: 'ipfs://QmecrGejUQVXpW4zS948pNvcnQrJ1KiAoM6bdfrVcWZsn5',
},
},
{
name: 'LSP1UniversalReceiverDelegate',
key: '0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47',
value: '0x36e4Eb6Ee168EF54B1E8e850ACBE51045214B313',
},
];

it('with web3.currentProvider [ERC725Y_BATCH]', async () => {
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
const erc725 = new ERC725(
e2eSchema,
ERC725_BATCH_CONTRACT_ADDRESS,
web3.currentProvider,
);
const result = await erc725.getData();
assert.deepStrictEqual(result, e2eResults);
});
});

describe('Get/fetch edge cases [mock]', () => {
it('should return null if the JSONURL is not set [fetchData]', async () => {
const provider = new HttpProvider(
Expand Down
52 changes: 52 additions & 0 deletions src/provider/providerWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ export class ProviderWrapper {
}

async getErc725YVersion(address: string): Promise<ERC725_VERSION> {
const isErc725YBatch = await this.supportsInterface(
address,
ERC725Y_INTERFACE_IDS['5.0'],
);

if (isErc725YBatch) {
return ERC725_VERSION.ERC725_BATCH;
}
YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved

const isErc725Y = await this.supportsInterface(
address,
ERC725Y_INTERFACE_IDS['3.0'],
Expand Down Expand Up @@ -197,6 +206,8 @@ export class ProviderWrapper {
}

switch (erc725Version) {
case ERC725_VERSION.ERC725_BATCH:
return this._getAllDataBatch(address, keyHashes);
case ERC725_VERSION.ERC725:
return this._getAllData(address, keyHashes);
case ERC725_VERSION.ERC725_LEGACY:
Expand All @@ -206,6 +217,47 @@ export class ProviderWrapper {
}
}

private async _getAllDataBatch(
address: string,
keyHashes: string[],
): Promise<GetDataReturn[]> {
if (this.type === ProviderTypes.ETHEREUM) {
const encodedResults = await this.callContract(
constructJSONRPC(
address,
Method.GET_DATA_BATCH,
abiCoder.encodeParameter('bytes32[]', keyHashes),
),
);

const decodedValues = decodeResult(Method.GET_DATA_BATCH, encodedResults);

return keyHashes.map<GetDataReturn>((keyHash, index) => ({
key: keyHash,
value: decodedValues ? decodedValues[index] : decodedValues,
}));
}

const payload: JsonRpc[] = [
constructJSONRPC(
address,
Method.GET_DATA_BATCH,
abiCoder.encodeParameter('bytes32[]', keyHashes),
),
];

const results: any = await this.callContract(payload);
const decodedValues = decodeResult(
Method.GET_DATA_BATCH,
results[0].result,
);

return keyHashes.map<GetDataReturn>((key, index) => ({
key,
value: decodedValues ? decodedValues[index] : decodedValues,
}));
}

YamenMerhi marked this conversation as resolved.
Show resolved Hide resolved
private async _getAllData(
address: string,
keyHashes: string[],
Expand Down
1 change: 1 addition & 0 deletions src/types/Method.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export enum Method {
GET_DATA_LEGACY = 'getDataLegacy', // For legacy ERC725 with interface id: 0x2bd57b73 NOTE: I had to add Legacy at the end so the map keys stays unique
GET_DATA = 'getData', // For latest ERC725 with interface id: 0x5a988c0f
GET_DATA_BATCH = 'getDataBatch',
OWNER = 'owner',
SUPPORTS_INTERFACE = 'supportsInterface', // https://eips.ethereum.org/EIPS/eip-165
IS_VALID_SIGNATURE = 'isValidSignature', // https://eips.ethereum.org/EIPS/eip-1271
Expand Down