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

Change viem usage for EAS to get typed data #131

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
6 changes: 2 additions & 4 deletions src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,11 @@ export function decodeTransactionInput(
return transactionDescriptor;
}

export function decodeTransactionInputViem(input: Hex, abi: Abi) {
const result = decodeFunctionData({
export function decodeTransactionInputViem<TAbi extends Abi>(input: Hex, abi: TAbi) {
return decodeFunctionData({
abi,
data: input,
});

return result;
}

export function decodeLog(abi: Abi, data: Hex, topics: EventLogTopics) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[
const abi = [
Copy link
Contributor

Choose a reason for hiding this comment

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

can we leave this abi file as json? and handle types in constants?

Copy link
Collaborator Author

@datadanne datadanne Dec 14, 2023

Choose a reason for hiding this comment

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

Unfortunately not :( microsoft/TypeScript#32063

It needs to be a const type and typescript doesn't support that for json files

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, maybe we can leave abis as json, and then import as const in constants.ts ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No that doesn't work unfortunately, typescript cannot infer a const type for a json file regardless of where/how it is imported

Copy link
Contributor

Choose a reason for hiding this comment

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

okay,

{
"inputs": [
{
Expand Down Expand Up @@ -1017,4 +1017,6 @@
"stateMutability": "nonpayable",
"type": "function"
}
]
] as const;

export default abi;
2 changes: 1 addition & 1 deletion src/protocol/eas/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import EAS from './abis/EAS.json';
import EAS from './abis/EAS';
import SchemaRegistry from './abis/SchemaRegistry.json';

export const EAS_ADDRESSES = [
Expand Down
140 changes: 37 additions & 103 deletions src/protocol/eas/eas.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Abi, Hex } from 'viem';
import { Hex } from 'viem';
import { ExtractAbiFunctionNames } from 'abitype';
import { Transaction } from '../../types';
import { decodeTransactionInputViem } from '../../helpers/utils';
import { ABIs, EAS_LINKS } from './constants';
Expand Down Expand Up @@ -27,18 +28,15 @@ export const detect = (transaction: Transaction): boolean => {
}

// decode input
let decoded;
let decoded: ReturnType<typeof decodeTransactionInputViem<typeof ABIs.EAS>>;
try {
decoded = decodeTransactionInputViem(
transaction.input as Hex,
ABIs.EAS as Abi,
);
decoded = decodeTransactionInputViem(transaction.input as Hex, ABIs.EAS);
Comment on lines +31 to +33
Copy link
Collaborator Author

@datadanne datadanne Dec 14, 2023

Choose a reason for hiding this comment

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

This could be simplified so that someone that implements a detect function doesn't have to define the return type like this. A suggestion:

const decoded = tryDecodeTransactionInput(transaction.input, ABIs.EAS);
if (!decoded) return false;

} catch (err) {
return false;
}

if (!decoded || !decoded.functionName) return false;
return [
const handledFunctions: ExtractAbiFunctionNames<typeof ABIs.EAS>[] = [
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This should also be simplified into a helper function, maybe something like

return pickABIFunctionNames([
  'attest', 
  'attestByDelegation',
  '...',
], ABIs.EAS).includes(decoded.functionName);

'attest',
'attestByDelegation',
'multiAttest',
Expand All @@ -50,8 +48,10 @@ export const detect = (transaction: Transaction): boolean => {
'timestamp',
'multiTimestamp',
'revokeOffchain',
'multiRevokeOffChain',
].includes(decoded.functionName);
'multiRevokeOffchain',
];

return handledFunctions.includes(decoded.functionName);
} catch (err) {
console.error('Error in detect function:', err);
return false;
Expand All @@ -66,19 +66,14 @@ const pluralize = (word: string, n: number): string => {
export const generate = (transaction: Transaction): Transaction => {
const decoded = decodeTransactionInputViem(
transaction.input as Hex,
ABIs.EAS as Abi,
ABIs.EAS,
);

switch (decoded.functionName) {
case 'attest': {
const arg = decoded.args[0] as {
schema: string;
data: {
recipient: string;
};
};
const schema = arg?.schema;
const recipient = arg?.data?.recipient;
const arg = decoded.args[0];
const schema = arg.schema;
const recipient = arg.data.recipient;

transaction.context = {
variables: {
Expand Down Expand Up @@ -116,16 +111,10 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'attestByDelegation': {
const arg = decoded.args[0] as {
schema: string;
attester: string;
data: {
recipient: string;
};
};
const schema = arg?.schema;
const attester = arg?.attester;
const recipient = arg?.data?.recipient;
const arg = decoded.args[0];
const schema = arg.schema;
const attester = arg.attester;
const recipient = arg.data.recipient;

transaction.context = {
variables: {
Expand Down Expand Up @@ -167,18 +156,9 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'multiAttest': {
const arg = decoded.args[0] as [
{
schema: string;
data: [
{
recipient: string;
},
];
},
];
const schemas = arg?.length;
const count = arg?.map((v) => v.data).flat().length;
const arg = decoded.args[0];
const schemas = arg.length;
const count = arg.map((v) => v.data).flat().length;

transaction.context = {
variables: {
Expand Down Expand Up @@ -216,20 +196,10 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'multiAttestByDelegation': {
const arg = decoded.args[0] as [
{
schema: string;
attester: string;
data: [
{
recipient: string;
},
];
},
];
const schemas = arg?.length;
const attesters = Array.from(new Set(arg?.map((v) => v.attester))).length;
const count = arg?.map((v) => v.data).flat().length;
const arg = decoded.args[0];
const schemas = arg.length;
const attesters = Array.from(new Set(arg.map((v) => v.attester))).length;
const count = arg.map((v) => v.data).flat().length;

transaction.context = {
variables: {
Expand Down Expand Up @@ -278,10 +248,8 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'revoke': {
const arg = decoded.args[0] as {
schema: string;
};
const schema = arg?.schema;
const arg = decoded.args[0];
const schema = arg.schema;

transaction.context = {
variables: {
Expand Down Expand Up @@ -314,10 +282,7 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'revokeByDelegation': {
const arg = decoded.args[0] as {
schema: string;
revoker: string;
};
const arg = decoded.args[0];
const { schema, revoker } = arg;

transaction.context = {
Expand Down Expand Up @@ -355,18 +320,9 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'multiRevoke': {
const arg = decoded.args[0] as [
{
schema: string;
data: [
{
recipient: string;
},
];
},
];
const schemas = arg?.length;
const count = arg?.map((v) => v.data).flat().length;
const arg = decoded.args[0];
const schemas = arg.length;
const count = arg.map((v) => v.data).flat().length;

transaction.context = {
variables: {
Expand Down Expand Up @@ -406,18 +362,10 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'multiRevokeByDelegation': {
const arg = decoded.args[0] as [
{
schema: string;
revoker: string;
data: {
recipient: string;
};
},
];
const schemas = arg?.length;
const revokers = Array.from(new Set(arg?.map((v) => v.revoker))).length;
const count = arg?.map((v) => v.data).flat().length;
const arg = decoded.args[0];
const schemas = arg.length;
const revokers = Array.from(new Set(arg.map((v) => v.revoker))).length;
const count = arg.map((v) => v.data).flat().length;

transaction.context = {
variables: {
Expand Down Expand Up @@ -488,14 +436,7 @@ export const generate = (transaction: Transaction): Transaction => {
}

case 'multiTimestamp': {
const arg = decoded.args[0] as {
data: [
{
recipient: string;
},
];
};
const data = arg?.data;
const data = decoded.args[0];
transaction.context = {
variables: {
from: {
Expand Down Expand Up @@ -546,15 +487,8 @@ export const generate = (transaction: Transaction): Transaction => {
return transaction;
}

case 'multiRevokeOffChain': {
const arg = decoded.args[0] as {
data: [
{
recipient: string;
},
];
};
const data = arg?.data;
case 'multiRevokeOffchain': {
const data = decoded.args[0];
transaction.context = {
variables: {
from: {
Expand Down