Skip to content

Commit ab86796

Browse files
committed
Merge branch 'main' into update_decoder_constants
2 parents 94f7a6d + 8e8b16a commit ab86796

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+10158
-1055
lines changed

jest.config.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ module.exports = {
33
preset: "ts-jest",
44
testEnvironment: "node",
55
coveragePathIgnorePatterns: ["./dist/*"],
6-
maxWorkers: 5,
7-
testTimeout: 30000,
6+
maxWorkers: 10,
7+
testTimeout: 60000,
88
};

microservices/tx/tx.routes.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
decodeTXHeadersSchema,
1212
type DecodeTXHeaders,
1313
} from "./tx.schema";
14-
import { decodeLogsfromTx, fetchTxFromHash } from "./tx.service";
14+
import { decodeLogsFromTx, fetchTxFromHash } from "./tx.service";
1515
import { type Chain } from "@covalenthq/client-sdk";
1616

1717
export const txRouter = Router();
@@ -39,7 +39,7 @@ const handleDecode = async (
3939
safe_details,
4040
...tx_metadata
4141
} = tx;
42-
const events = await decodeLogsfromTx(
42+
const events = await decodeLogsFromTx(
4343
chain_name as Chain,
4444
tx,
4545
covalentApiKey

microservices/tx/tx.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const fetchTxFromHash = async (
3535
}
3636
};
3737

38-
export const decodeLogsfromTx = async (
38+
export const decodeLogsFromTx = async (
3939
chain_name: Chain,
4040
tx: Transaction,
4141
covalentApiKey: string

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"author": "",
1515
"license": "ISC",
1616
"dependencies": {
17-
"@covalenthq/client-sdk": "^0.8.7",
17+
"@covalenthq/client-sdk": "^0.9.4",
1818
"cors": "^2.8.5",
1919
"dotenv": "^16.3.1",
2020
"enquirer": "^2.4.1",

scripts/add-config.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,13 @@ const chainNameSchema = yup
8989
const { address, is_factory, chain_name } = (await prompt([
9090
{
9191
type: "input",
92-
name: "address",
93-
message: "What is the Contract Address?",
94-
format: (value) => value.toLowerCase(),
95-
result: (value) => value.toLowerCase(),
92+
name: "chain_name",
93+
message: "What is the Chain on which the contract is deployed?",
94+
format: (value) => slugify(value),
95+
result: (value) => slugify(value),
9696
validate: async (value) => {
9797
try {
98-
await addressSchema.validate(value, {
98+
await chainNameSchema.validate(value, {
9999
abortEarly: false,
100100
});
101101
return true;
@@ -105,14 +105,14 @@ const chainNameSchema = yup
105105
},
106106
},
107107
{
108-
type: "toggle",
109-
name: "is_factory",
110-
message: "Is it a Factory Address?",
111-
enabled: "Yes",
112-
disabled: "No",
108+
type: "input",
109+
name: "address",
110+
message: "What is the Contract Address?",
111+
format: (value) => value.toLowerCase(),
112+
result: (value) => value.toLowerCase(),
113113
validate: async (value) => {
114114
try {
115-
await isFactorySchema.validate(value, {
115+
await addressSchema.validate(value, {
116116
abortEarly: false,
117117
});
118118
return true;
@@ -122,14 +122,14 @@ const chainNameSchema = yup
122122
},
123123
},
124124
{
125-
type: "input",
126-
name: "chain_name",
127-
message: "What is the Chain on which this contract is deployed?",
128-
format: (value) => slugify(value),
129-
result: (value) => slugify(value),
125+
type: "toggle",
126+
name: "is_factory",
127+
message: "Is it a Factory Address?",
128+
enabled: "Yes",
129+
disabled: "No",
130130
validate: async (value) => {
131131
try {
132-
await chainNameSchema.validate(value, {
132+
await isFactorySchema.validate(value, {
133133
abortEarly: false,
134134
});
135135
return true;

services/decoder/decoder.constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export enum DECODED_EVENT_CATEGORY {
99
BRIDGE = "Bridge",
1010
GAMING = "Gaming",
1111
SOCIAL = "Social",
12+
STAKING = "Staking",
1213
OTHERS = "Others",
1314
STAKING = "Staking",
1415
}

services/decoder/decoder.ts

+78-48
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,37 @@ import {
1313
type EventType,
1414
type DecoderConfig,
1515
type Fallbacks,
16+
type NativeDecodingFunction,
1617
} from "./decoder.types";
1718
import { encodeEventTopics, type Abi } from "viem";
1819

1920
export class GoldRushDecoder {
2021
private static configs: DecoderConfig = {};
2122
private static decoders: Decoders = {};
2223
private static fallbacks: Fallbacks = {};
24+
private static native_decoder: NativeDecodingFunction;
2325
private static decoding_functions: DecodingFunctions = [];
26+
private static fallback_functions: DecodingFunctions = [];
27+
private static fileExtension: "js" | "ts" =
28+
process.env.NODE_ENV !== "test" ? "js" : "ts";
2429

2530
public static initDecoder = () => {
2631
console.info("Initializing GoldrushDecoder Service...");
2732

2833
const protocolsDirectoryPath: string = join(__dirname, "/protocols");
2934
const protocols = readdirSync(protocolsDirectoryPath);
3035
let protocolsCount: number = 0;
36+
let configsCount: number = 0;
3137
for (const protocol of protocols) {
3238
const protocolPath = join(protocolsDirectoryPath, protocol);
3339
const files = readdirSync(protocolPath);
3440
let configFile: string | null = null,
3541
decodersFile: string | null = null;
3642
files.forEach((file) => {
37-
const fileExtension =
38-
process.env.NODE_ENV !== "test" ? "js" : "ts";
39-
if (file.endsWith(`.configs.${fileExtension}`)) {
43+
if (file.endsWith(`.configs.${this.fileExtension}`)) {
4044
configFile = file;
4145
}
42-
if (file.endsWith(`.decoders.${fileExtension}`)) {
46+
if (file.endsWith(`.decoders.${this.fileExtension}`)) {
4347
decodersFile = file;
4448
}
4549
});
@@ -54,6 +58,7 @@ export class GoldRushDecoder {
5458
this.configs[chain_name][protocol_name][address] = {
5559
is_factory: is_factory,
5660
};
61+
configsCount++;
5762
}
5863
);
5964
require(join(protocolPath, decodersFile));
@@ -62,37 +67,31 @@ export class GoldRushDecoder {
6267

6368
const fallbacksDirectoryPath: string = join(__dirname, "/fallbacks");
6469
const fallbacks = readdirSync(fallbacksDirectoryPath);
65-
let fallbacksCount: number = 0;
6670
for (const fallback of fallbacks) {
6771
const fallbackPath = join(fallbacksDirectoryPath, fallback);
6872
const files = readdirSync(fallbackPath);
6973
let fallbackFile: string | null = null;
7074
files.forEach((file) => {
71-
const fileExtension =
72-
process.env.NODE_ENV !== "test" ? "js" : "ts";
73-
if (file.endsWith(`.fallback.${fileExtension}`)) {
75+
if (file.endsWith(`.fallback.${this.fileExtension}`)) {
7476
fallbackFile = file;
7577
}
7678
});
7779
if (fallbackFile) {
78-
fallbacksCount++;
7980
require(join(fallbackPath, fallbackFile));
8081
}
8182
}
8283

83-
const decodersCount = Object.keys(this.decoding_functions).length;
84-
const configsCount = Object.values(this.configs).reduce(
85-
(chainCount, chain) => {
86-
return (
87-
chainCount +
88-
Object.values(chain).reduce((addressCount, protocol) => {
89-
return addressCount + Object.keys(protocol).length;
90-
}, 0)
91-
);
92-
},
93-
0
84+
const nativeDecoderPath: string = join(
85+
__dirname,
86+
"native",
87+
`native.decoder.${this.fileExtension}`
9488
);
89+
require(join(nativeDecoderPath));
90+
91+
const decodersCount = this.decoding_functions.length;
92+
const fallbacksCount = this.fallback_functions.length;
9593

94+
console.info("1 native decoder added");
9695
console.info(`${protocolsCount.toLocaleString()} protocols found`);
9796
console.info(`${configsCount.toLocaleString()} configs generated`);
9897
console.info(`${decodersCount.toLocaleString()} decoders generated`);
@@ -124,10 +123,16 @@ export class GoldRushDecoder {
124123
}
125124
Object.keys(this.configs[chain_name][protocol]).forEach(
126125
(address) => {
127-
this.decoders[chain_name] ??= {};
128-
this.decoders[chain_name][address] ??= {};
129-
this.decoders[chain_name][address][topic0_hash] =
130-
decoding_function_index;
126+
const lowercaseChainName =
127+
chain_name.toLowerCase() as Chain;
128+
const lowercaseAddress = address.toLowerCase();
129+
const lowercaseTopic0Hash = topic0_hash.toLowerCase();
130+
131+
this.decoders[lowercaseChainName] ??= {};
132+
this.decoders[lowercaseChainName][lowercaseAddress] ??= {};
133+
this.decoders[lowercaseChainName][lowercaseAddress][
134+
lowercaseTopic0Hash
135+
] = decoding_function_index;
131136
}
132137
);
133138
});
@@ -142,10 +147,15 @@ export class GoldRushDecoder {
142147
abi: abi,
143148
eventName: event_name,
144149
});
145-
this.decoding_functions.push(decoding_function);
146-
const decoding_function_index: number =
147-
this.decoding_functions.length - 1;
148-
this.fallbacks[topic0_hash] = decoding_function_index;
150+
const lowercaseTopic0Hash = topic0_hash.toLowerCase();
151+
this.fallback_functions.push(decoding_function);
152+
const fallback_function_index: number =
153+
this.fallback_functions.length - 1;
154+
this.fallbacks[lowercaseTopic0Hash] = fallback_function_index;
155+
};
156+
157+
public static native = (native_decoder: NativeDecodingFunction) => {
158+
this.native_decoder = native_decoder;
149159
};
150160

151161
public static decode = async (
@@ -155,26 +165,46 @@ export class GoldRushDecoder {
155165
) => {
156166
const covalent_client = new CovalentClient(covalent_api_key);
157167
const events: EventType[] = [];
158-
const logs = (tx.log_events ?? []).reverse();
159-
for (const log of logs) {
160-
const {
161-
raw_log_topics: [topic0_hash],
162-
sender_address: contract_address,
163-
// !ERROR: add factory_contract_address in the log_event(s)
164-
// factory_contract_address,
165-
} = log;
166-
const decoding_index =
167-
// !ERROR: add factory_contract_address in the log_event(s)
168-
// factory_contract_address ||
169-
this.decoders[chain_name][contract_address]?.[topic0_hash];
170-
const fallback_index = this.fallbacks[topic0_hash];
171-
if (decoding_index !== undefined || fallback_index !== undefined) {
172-
const event = await this.decoding_functions[
173-
decoding_index ?? fallback_index
174-
](log, tx, chain_name, covalent_client);
175-
events.push(event);
176-
}
168+
if (tx.value) {
169+
const nativeEvent = this.native_decoder(tx);
170+
events.push(nativeEvent);
177171
}
178-
return events;
172+
173+
const decodedEvents = await Promise.all(
174+
(tx.log_events ?? []).map((log) => {
175+
const {
176+
raw_log_topics: [topic0_hash],
177+
sender_address,
178+
sender_factory_address,
179+
} = log;
180+
const lowercaseChainName = chain_name.toLowerCase() as Chain;
181+
const lowercaseSenderAddress = sender_address?.toLowerCase();
182+
const lowercaseSenderFactoryAddress =
183+
sender_factory_address?.toLowerCase();
184+
const lowercaseTopic0Hash = topic0_hash?.toLowerCase();
185+
186+
const decoding_index =
187+
this.decoders[lowercaseChainName]?.[
188+
lowercaseSenderAddress
189+
]?.[lowercaseTopic0Hash] ??
190+
this.decoders[lowercaseChainName]?.[
191+
lowercaseSenderFactoryAddress
192+
]?.[lowercaseTopic0Hash];
193+
const fallback_index = this.fallbacks[lowercaseTopic0Hash];
194+
195+
const logFunction =
196+
decoding_index !== undefined
197+
? this.decoding_functions[decoding_index]
198+
: fallback_index !== undefined
199+
? this.fallback_functions[fallback_index]
200+
: null;
201+
202+
return logFunction
203+
? logFunction(log, tx, chain_name, covalent_client)
204+
: null;
205+
})
206+
);
207+
208+
return events.concat(decodedEvents.filter(Boolean) as EventType[]);
179209
};
180210
}

services/decoder/decoder.types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export type DecodingFunction = (
6464
covalent_client: CovalentClient
6565
) => Promise<EventType>;
6666

67+
export type NativeDecodingFunction = (tx: Transaction) => EventType;
68+
6769
export type DecoderConfig =
6870
| {
6971
[chain_name in Chain]: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[
2+
{
3+
"anonymous": false,
4+
"inputs": [
5+
{
6+
"indexed": true,
7+
"internalType": "address",
8+
"name": "owner",
9+
"type": "address"
10+
},
11+
{
12+
"indexed": true,
13+
"internalType": "address",
14+
"name": "operator",
15+
"type": "address"
16+
},
17+
{
18+
"indexed": false,
19+
"internalType": "bool",
20+
"name": "approved",
21+
"type": "bool"
22+
}
23+
],
24+
"name": "ApprovalForAll",
25+
"type": "event"
26+
}
27+
]

0 commit comments

Comments
 (0)