Skip to content

Commit e7fa699

Browse files
authored
Merge pull request #240 from rsksmart/feat/DV-1376-update-contract-data-tools
update contract data tools
2 parents 499e8ab + 99e5dfb commit e7fa699

File tree

8 files changed

+1246
-221
lines changed

8 files changed

+1246
-221
lines changed

src/lib/NativeContracts.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getLatestBridgeMethods } from '@rsksmart/rsk-contract-parser'
12
import { isAddress } from './utils'
23

34
export const nativeContracts = {
@@ -6,9 +7,42 @@ export const nativeContracts = {
67
}
78

89
export const getNativeContractAddress = contractName => nativeContracts[contractName]
10+
911
export const getNativeContractName = address => Object.keys(nativeContracts).find(name => nativeContracts[name] === address)
12+
1013
export const isNativeContract = address => !!getNativeContractName(address)
11-
export const NativeContracts = Object.freeze({ getNativeContractAddress, getNativeContractName, isNativeContract })
14+
15+
export const getNativeContractMethods = address => {
16+
if (address === nativeContracts.bridge) {
17+
return getLatestBridgeMethods()
18+
}
19+
20+
if (address === nativeContracts.remasc) {
21+
return []
22+
}
23+
24+
return []
25+
}
26+
27+
export const getNativeContractInterfaces = (address) => {
28+
if (address === nativeContracts.bridge) {
29+
return []
30+
}
31+
32+
if (address === nativeContracts.remasc) {
33+
return []
34+
}
35+
36+
return []
37+
}
38+
39+
export const NativeContracts = Object.freeze({
40+
getNativeContractAddress,
41+
getNativeContractName,
42+
isNativeContract,
43+
getNativeContractMethods,
44+
getNativeContractInterfaces
45+
})
1246

1347
export function validateNativeContracts () {
1448
for (let contract in nativeContracts) {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import fs from 'fs'
2+
import path from 'path'
3+
import { getLatestBlockNumber, getContractData, parseArguments } from '../utils.js'
4+
5+
const toolName = process.argv[1].split('/').pop()
6+
7+
function printUsageAndExit () {
8+
console.log(`Usage: npx babel-node src/tools/contracts/${toolName} [options]`)
9+
console.log(`Options:`)
10+
console.log(` --address <string> The contract address to fetch data for (required)`)
11+
console.log(` --block <number> Block number to fetch data at (default: latest block)`)
12+
console.log(` --save Save results to file (optional)`)
13+
console.log(`Examples:`)
14+
console.log(` npx babel-node src/tools/contracts/${toolName} --address 0x123...`)
15+
console.log(` npx babel-node src/tools/contracts/${toolName} --address 0x123... --block 5000000`)
16+
console.log(` npx babel-node src/tools/contracts/${toolName} --address 0x123... --save`)
17+
process.exit(1)
18+
}
19+
20+
async function main () {
21+
const validOptions = {
22+
'--address': { name: 'address', type: 'string', default: null, required: true },
23+
'--block': { name: 'blockNumber', type: 'number', default: null, min: 0 },
24+
'--save': { name: 'save', type: 'boolean', default: false }
25+
}
26+
27+
let options
28+
try {
29+
options = parseArguments(validOptions)
30+
} catch (error) {
31+
console.log(`Error: ${error.message}`)
32+
printUsageAndExit()
33+
}
34+
35+
try {
36+
// Normalize address
37+
const normalizedAddress = options.address.toLowerCase()
38+
39+
console.log(`${toolName}`)
40+
console.log(`Fetching data for contract: ${normalizedAddress}`)
41+
42+
// Get block number if not provided
43+
let targetBlockNumber = options.blockNumber
44+
if (!targetBlockNumber) {
45+
targetBlockNumber = await getLatestBlockNumber()
46+
console.log(`Using latest block: ${targetBlockNumber}`)
47+
} else {
48+
console.log(`Using specified block: ${targetBlockNumber}`)
49+
}
50+
51+
const contractData = await getContractData(normalizedAddress, targetBlockNumber)
52+
53+
const result = {
54+
blockNumber: targetBlockNumber,
55+
contractData
56+
}
57+
58+
console.log('\n=== RESULT ===')
59+
console.dir(result, { depth: null })
60+
console.log(`\nFetch time: ${contractData.fetchTimeMs}ms`)
61+
62+
// Save result to file if --save flag is provided
63+
if (options.save) {
64+
const fileName = `contract-data-${normalizedAddress}-${Date.now()}.json`
65+
const resultFilePath = path.join(__dirname, fileName)
66+
fs.writeFileSync(resultFilePath, JSON.stringify(result, null, 2))
67+
console.log(`\nResults saved to: ${fileName}`)
68+
}
69+
70+
process.exit(0)
71+
} catch (error) {
72+
console.log(`[${toolName}]: Error fetching contract data`)
73+
console.error(error)
74+
process.exit(1)
75+
}
76+
}
77+
78+
main()
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import fs from 'fs'
2+
import path from 'path'
3+
import { getLatestBlockNumber, fetchPaginatedContracts, getContractData, parseArguments } from '../utils.js'
4+
5+
const toolName = process.argv[1].split('/').pop()
6+
const resultFileName = `contracts-data-${Date.now()}.json`
7+
const resultFilePath = path.join(__dirname, resultFileName)
8+
9+
function printUsageAndExit () {
10+
console.log(`Usage: npx babel-node src/tools/contracts/${toolName} [options]`)
11+
console.log(`Options:`)
12+
console.log(` --pageSize <number> Number of contracts to process per page (default: 50)`)
13+
console.log(` --limit <number> Maximum number of contracts to process (default: 0 = no limit)`)
14+
console.log(` --save Save results to file (optional)`)
15+
console.log(`Examples:`)
16+
console.log(` npx babel-node src/tools/contracts/${toolName}`)
17+
console.log(` npx babel-node src/tools/contracts/${toolName} --pageSize 25`)
18+
console.log(` npx babel-node src/tools/contracts/${toolName} --pageSize 25 --limit 100`)
19+
console.log(` npx babel-node src/tools/contracts/${toolName} --save`)
20+
process.exit(1)
21+
}
22+
23+
async function getContractsData ({ pageSize = 50, limit = 0, save = false } = {}) {
24+
try {
25+
const latestBlockNumber = await getLatestBlockNumber()
26+
console.log(`Processing contracts at block ${latestBlockNumber}`)
27+
28+
const results = {
29+
totalContracts: 0,
30+
processedContracts: 0,
31+
successfulFetches: 0,
32+
failedFetches: 0,
33+
errors: {},
34+
contracts: {}
35+
}
36+
37+
let cursor = null
38+
let pageCount = 0
39+
let totalProcessed = 0
40+
41+
do {
42+
pageCount++
43+
const { contracts, next } = await fetchPaginatedContracts(pageSize, cursor)
44+
45+
if (contracts.length === 0) {
46+
console.log('No more contracts to process')
47+
break
48+
}
49+
50+
console.log(`Processing page ${pageCount} (${contracts.length} contracts)...`)
51+
52+
for (const contract of contracts) {
53+
if (limit > 0 && totalProcessed >= limit) {
54+
console.log(`Reached limit of ${limit} contracts`)
55+
break
56+
}
57+
58+
const contractAddress = contract.address
59+
results.totalContracts++
60+
totalProcessed++
61+
62+
try {
63+
const contractData = await getContractData(contractAddress, latestBlockNumber)
64+
65+
if (!contractData) {
66+
results.failedFetches++
67+
results.errors[contractAddress] = 'Failed to fetch contract data'
68+
continue
69+
}
70+
71+
results.successfulFetches++
72+
results.contracts[contractAddress] = contractData
73+
console.log(`Contract ${contractAddress} fetched (${contractData.fetchTimeMs}ms).`)
74+
} catch (error) {
75+
results.failedFetches++
76+
results.errors[contractAddress] = error.message
77+
console.log(`Contract ${contractAddress} fetch failed. Error: ${error.message}`)
78+
}
79+
80+
results.processedContracts++
81+
}
82+
83+
// Save current page progress if --save flag is provided
84+
if (save) {
85+
fs.writeFileSync(resultFilePath, JSON.stringify(results, null, 2))
86+
console.log(`Page ${pageCount} completed. Progress saved to ${resultFileName}`)
87+
} else {
88+
console.log(`Page ${pageCount} completed.`)
89+
}
90+
91+
if (limit > 0 && totalProcessed >= limit) {
92+
break
93+
}
94+
95+
cursor = next
96+
} while (cursor)
97+
98+
return results
99+
} catch (error) {
100+
console.error('Error during contract data fetch:', error.message)
101+
throw error
102+
}
103+
}
104+
105+
async function main () {
106+
const validOptions = {
107+
'--pageSize': { name: 'pageSize', type: 'number', default: 50, min: 1 },
108+
'--limit': { name: 'limit', type: 'number', default: 0, min: 0 },
109+
'--save': { name: 'save', type: 'boolean', default: false }
110+
}
111+
112+
let options
113+
try {
114+
options = parseArguments(validOptions)
115+
} catch (error) {
116+
console.log(`Error: ${error.message}`)
117+
printUsageAndExit()
118+
}
119+
120+
try {
121+
console.log(`${toolName}`)
122+
console.log(`Page size: ${options.pageSize}`)
123+
if (options.limit > 0) {
124+
console.log(`Limit: ${options.limit} contracts`)
125+
}
126+
console.log('Depending on the page size and limit, this tool could take a while to complete.')
127+
if (options.save) {
128+
console.log(`Results will be saved to: ${resultFileName}`)
129+
}
130+
console.log('Starting...')
131+
132+
const result = await getContractsData({ pageSize: options.pageSize, limit: options.limit, save: options.save })
133+
134+
console.log(`\n=== RESULTS ===`)
135+
console.log(`Total: ${result.totalContracts}`)
136+
console.log(`Processed: ${result.processedContracts}`)
137+
console.log(`Successful: ${result.successfulFetches}`)
138+
console.log(`Failed: ${result.failedFetches}`)
139+
140+
if (Object.keys(result.errors).length > 0) {
141+
console.log(`\nErrors: ${Object.keys(result.errors).length}`)
142+
}
143+
144+
if (options.save) {
145+
console.log(`Final results saved to: ${resultFileName}`)
146+
}
147+
148+
process.exit(0)
149+
} catch (error) {
150+
console.log(`[${toolName}]: Error fetching contract data`)
151+
console.error(error)
152+
process.exit(1)
153+
}
154+
}
155+
156+
main()
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import fs from 'fs'
2+
import path from 'path'
3+
import { getLatestBlockNumber, getContractData, updateContractData, parseArguments } from '../utils.js'
4+
5+
const toolName = process.argv[1].split('/').pop()
6+
7+
function printUsageAndExit () {
8+
console.log(`Usage: npx babel-node src/tools/contracts/${toolName} [options]`)
9+
console.log(`Options:`)
10+
console.log(` --address <string> The contract address to update data for (required)`)
11+
console.log(` --block <number> Block number to update data at (default: latest block)`)
12+
console.log(` --save Save results to file (optional)`)
13+
console.log(`Examples:`)
14+
console.log(` npx babel-node src/tools/contracts/${toolName} --address 0x123...`)
15+
console.log(` npx babel-node src/tools/contracts/${toolName} --address 0x123... --block 5000000`)
16+
console.log(` npx babel-node src/tools/contracts/${toolName} --address 0x123... --save`)
17+
process.exit(1)
18+
}
19+
20+
async function main () {
21+
const validOptions = {
22+
'--address': { name: 'address', type: 'string', default: null, required: true },
23+
'--block': { name: 'blockNumber', type: 'number', default: null, min: 0 },
24+
'--save': { name: 'save', type: 'boolean', default: false }
25+
}
26+
27+
let options
28+
try {
29+
options = parseArguments(validOptions)
30+
} catch (error) {
31+
console.log(`Error: ${error.message}`)
32+
printUsageAndExit()
33+
}
34+
35+
try {
36+
// Normalize address
37+
const normalizedAddress = options.address.toLowerCase()
38+
39+
console.log(`${toolName}`)
40+
console.log(`Updating data for contract: ${normalizedAddress}`)
41+
42+
// Get block number if not provided
43+
let targetBlockNumber = options.blockNumber
44+
if (!targetBlockNumber) {
45+
targetBlockNumber = await getLatestBlockNumber()
46+
console.log(`Using latest block: ${targetBlockNumber}`)
47+
} else {
48+
console.log(`Using specified block: ${targetBlockNumber}`)
49+
}
50+
51+
const contractData = await getContractData(normalizedAddress, targetBlockNumber)
52+
53+
if (!contractData) {
54+
throw new Error('Failed to fetch contract data')
55+
}
56+
57+
await updateContractData(contractData)
58+
59+
const result = {
60+
blockNumber: targetBlockNumber,
61+
contractData
62+
}
63+
64+
console.log('\n=== RESULT ===')
65+
console.dir(result, { depth: null })
66+
console.log(`\nFetch time: ${contractData.fetchTimeMs}ms, Update time: ${contractData.updateTimeMs}ms`)
67+
68+
// Save result to file if --save flag is provided
69+
if (options.save) {
70+
const fileName = `contract-update-${normalizedAddress}-${Date.now()}.json`
71+
const resultFilePath = path.join(__dirname, fileName)
72+
fs.writeFileSync(resultFilePath, JSON.stringify(result, null, 2))
73+
console.log(`\nResults saved to: ${fileName}`)
74+
}
75+
76+
process.exit(0)
77+
} catch (error) {
78+
console.log(`[${toolName}]: Error updating contract data`)
79+
console.error(error)
80+
process.exit(1)
81+
}
82+
}
83+
84+
main()

0 commit comments

Comments
 (0)