Skip to content
This repository was archived by the owner on Jan 21, 2022. It is now read-only.
Open
53 changes: 53 additions & 0 deletions src/__tests__/erc165/erc165.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import core from '../../core';
import erc165 from '../../erc165';
import { testGraphql } from '../utils';

const { execQuery } = testGraphql({ optsOverride: { plugins: [core, erc165] } });

test('erc165: Cryptokitties supports ERC165 interface', async () => {
const query = `
{
account(address:"0x06012c8cf97BEaD5deAe237070F9587f8E7A266d") {
supportsInterface(interfaceID: "0x01ffc9a7")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We prefer strict camel casing.

Suggested change
supportsInterface(interfaceID: "0x01ffc9a7")
supportsInterface(interfaceId: "0x01ffc9a7")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I prefer too, but that's the language of the original EIP - https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md. Of course we can do interfaceId, your call.

}
}
`;

const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();
expect(result.data.account.supportsInterface).toEqual(true);
});

test('erc165: Cryptokitties supports ERC721 interface', async () => {
const query = `
{
account(address:"0x06012c8cf97BEaD5deAe237070F9587f8E7A266d") {
supportsInterface(interfaceID: "0x9a20483d")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How about we add a a field an an enum type for known interface IDs?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

as a new grapql method (like supportsInterfaceByEnum) or just at the backend?

}
}
`;

const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data.account.supportsInterface).toEqual(true);
});

test('erc165: OmiseGO does not support ERC165', async () => {
const query = `
{
account(address:"0xd26114cd6EE289AccF82350c8d8487fedB8A0C07") {
address,
supportsInterface(interfaceID: "0x01ffc9a7")
}
}
`;

const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data.account.supportsInterface).toEqual(false);
});
209 changes: 209 additions & 0 deletions src/__tests__/erc721/erc721.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import core from '../../core';
import erc165 from '../../erc165';
import erc20 from '../../erc20';
import erc721 from '../../erc721';
import { testGraphql } from '../utils';

const { execQuery } = testGraphql({ optsOverride: { plugins: [core, erc165, erc721] } });

test('erc721: nftToken balanceOf query #1', async () => {
const query = `
{
account(address: "0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab") {
nftToken {
balanceOf(owner: "0xD418c5d0c4a3D87a6c555B7aA41f13EF87485Ec6")
}
}
}
`;
const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data).toEqual({
account: {
nftToken: {
balanceOf: 0,
},
},
});
});

test('erc721: nftToken balanceOf query #2', async () => {
const query = `
{
account(address: "0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab") {
nftToken {
balanceOf(owner: "0x6f00cE7253bFD3A5A1c307b5E13814BF3433C72f")
}
}
}
`;
const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data).toEqual({
account: {
nftToken: {
balanceOf: 5,
},
},
});
});

test('erc721: nftToken ownerOf query', async () => {
const query = `
{
account(address: "0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab") {
nftToken {
ownerOf(tokenId: 143880)
}
}
}
`;
const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data).toEqual({
account: {
nftToken: {
ownerOf: '0x6f00cE7253bFD3A5A1c307b5E13814BF3433C72f',
},
},
});
});

test('erc721: nftToken getApproved query', async () => {
const query = `
{
account(address:"0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab") {
nftToken {
getApproved(tokenId: 33525)
}
}
}
`;
const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data).toEqual({
account: {
nftToken: {
getApproved: '0x0000000000000000000000000000000000000000',
},
},
});
});

test('erc721: nftToken isApprovedForAll query', async () => {
const query = `
{
account(address:"0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab") {
nftToken {
isApprovedForAll(owner: "0xb85e9bdfCA73a536BE641bB5eacBA0772eA3E61E", operator: "0xD418c5d0c4a3D87a6c555B7aA41f13EF87485Ec6")
}
}
}
`;
const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

expect(result.data).toEqual({
account: {
nftToken: {
isApprovedForAll: false,
},
},
});
});

//44

test('erc721: not decodable', async () => {
const query = `
{
block(number: 5000000) {
hash
transactionAt(index: 66) {
value
decoded {
standard
operation
... on ERC721TransferFrom {
from {
account {
address
}
}
to {
account {
address
}
}
tokenId

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cool, nice test.

}
}
}
}
}
`;

const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

const tx = result.data.block.transactionAt;
expect(tx.value).toBeGreaterThan(0);
expect(tx.decoded).toEqual(null);
});

test('erc721: decode transfer log', async () => {
const query = `
{
transaction(hash: "0x5e9e7570cde63860a7cb71542729deb6d4dd796af70bb464050ca06ec7fc4bc9") {
hash
logs{
decoded {
... on ERC721TransferEvent{
from {
account {
address
}
}
to {
account {
address
}
},
tokenId
}
}
}
}
}`;

const result = await execQuery(query);
expect(result.errors).toBeUndefined();
expect(result.data).not.toBeUndefined();

const tranferLog = result.data.transaction.logs[0];
expect(tranferLog).toEqual({
decoded: {
from: {
account: {
address: '0x0000000000000000000000000000000000000000',
},
},
to: {
account: {
address: '0xc93227eee6e77db998a1ff5b01049fec8a5694cc',
},
},
tokenId: 43820,
},
});
});
12 changes: 8 additions & 4 deletions src/abi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ We classify supported ABIs in two types:

## Supported ABIs

| Standard | Type | Entity | Specification | Comments |
| -------- | --------- | ------ | ------------- | --------------------------------------------------------------- |
| ERC20 | Entity |  Token | [link][1] | |
| ERC223 | Extension |  Token | [link][2] | Private ERC20 implementation change. No action needed in ethql. |
| Standard | Type | Entity | Specification | Comments |
| -------- | --------- | --------- | ------------- | --------------------------------------------------------------- |
| ERC20 | Entity |  Token | [link][1] | |
| ERC223 | Extension |  Token | [link][2] | Private ERC20 implementation change. No action needed in ethql. |
| ERC165 | Entity | Interface | [link][3] | |
Comment thread
leonprou marked this conversation as resolved.
| ERC721 | Entity | Token | [link][4] | |

## ethql naming scheme

Expand All @@ -28,3 +30,5 @@ logs pertaining to several standards that relate to the same entity.

[1]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
[2]: https://github.com/ethereum/EIPs/issues/223
[3]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
[4]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
21 changes: 21 additions & 0 deletions src/abi/erc165.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Watch the indentation here! Check out erc20.json.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

what plugin did you use to indentation?

{
"constant": true,
"inputs": [
{
"name": "interfaceID",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
Loading