Skip to content

Commit bf5ad13

Browse files
marcocastignolikuzdogan
authored andcommitted
add documentation and refactor code in server
1 parent a216de3 commit bf5ad13

File tree

3 files changed

+89
-109
lines changed

3 files changed

+89
-109
lines changed

packages/lib-sourcify/README.md

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import {
2626
ISolidityCompiler,
2727
SolidityJsonInput,
2828
SolidityOutput,
29-
} from "@ethereum-sourcify/lib-sourcify";
30-
import { useSolidityCompiler } from "@ethereum-sourcify/compilers";
31-
import * as fs from "fs";
29+
} from '@ethereum-sourcify/lib-sourcify';
30+
import { useSolidityCompiler } from '@ethereum-sourcify/compilers';
31+
import * as fs from 'fs';
3232

3333
// Step 1: Setup your compiler
3434
class Solc implements ISolidityCompiler {
@@ -43,26 +43,26 @@ class Solc implements ISolidityCompiler {
4343
async compile(
4444
version: string,
4545
solcJsonInput: SolidityJsonInput,
46-
forceEmscripten: boolean = false
46+
forceEmscripten: boolean = false,
4747
): Promise<SolidityOutput> {
4848
return await useSolidityCompiler(
4949
this.solcRepoPath, // useSolidityCompiler will automatically download and store solc here
5050
this.solJsonRepoPath, // useSolidityCompiler will automatically download and store solcjs here
5151
version,
5252
solcJsonInput,
53-
forceEmscripten
53+
forceEmscripten,
5454
);
5555
}
5656
}
5757

58-
const solc = new Solc("/path/to/solc", "/path/to/solcjs");
58+
const solc = new Solc('/path/to/solc', '/path/to/solcjs');
5959

6060
// Step 2: Prepare your standard JSON input
6161
const jsonInput = {
62-
language: "Solidity",
62+
language: 'Solidity',
6363
sources: {
64-
"Contract.sol": {
65-
content: "contract MyContract { function foo() public {} }",
64+
'Contract.sol': {
65+
content: 'contract MyContract { function foo() public {} }',
6666
},
6767
},
6868
settings: {
@@ -71,35 +71,35 @@ const jsonInput = {
7171
runs: 200,
7272
},
7373
outputSelection: {
74-
"*": [],
74+
'*': [],
7575
},
7676
},
7777
} as SolidityJsonInput;
7878

7979
// Step 3: Create a compilation
8080
const compilation = new SolidityCompilation(
8181
solc,
82-
"0.8.20", // compiler version
82+
'0.8.20', // compiler version
8383
jsonInput,
8484
{
85-
path: "Contract.sol",
86-
name: "MyContract", // The name of your contract
87-
}
85+
path: 'Contract.sol',
86+
name: 'MyContract', // The name of your contract
87+
},
8888
);
8989

9090
// Step 4: Set up a SourcifyChain instance
9191
const myChain = new SourcifyChain({
92-
name: "My EVM Chain",
92+
name: 'My EVM Chain',
9393
chainId: 1337,
94-
rpc: ["http://localhost:8545"],
94+
rpc: ['http://localhost:8545'],
9595
supported: true,
9696
});
9797

9898
// Step 5: Verify the contract
9999
const verification = new Verification(
100100
compilation,
101101
myChain,
102-
"0xc0ffee254729296a45a3885639AC7E10F9d54979"
102+
'0xc0ffee254729296a45a3885639AC7E10F9d54979',
103103
);
104104

105105
await verification.verify();
@@ -115,13 +115,16 @@ This example shows the complete verification flow for a Solidity contract using
115115
For browser usage, we recommend using [web-solc](https://github.com/gnidan/web-solc) instead of `@ethereum-sourcify/compilers`. Here's an example of how to implement the `ISolidityCompiler` interface with `web-solc`:
116116

117117
```typescript
118-
import { ISolidityCompiler, SolidityJsonInput } from "@ethereum-sourcify/lib-sourcify";
119-
import { fetchSolc } from "web-solc";
118+
import {
119+
ISolidityCompiler,
120+
SolidityJsonInput,
121+
} from '@ethereum-sourcify/lib-sourcify';
122+
import { fetchSolc } from 'web-solc';
120123

121124
class Solc implements ISolidityCompiler {
122125
async compile(
123126
version: string,
124-
solcJsonInput: SolidityJsonInput
127+
solcJsonInput: SolidityJsonInput,
125128
): Promise<any> {
126129
const { compile } = await fetchSolc(version);
127130
return await compile(solcJsonInput);
@@ -136,12 +139,10 @@ const solc = new Solc();
136139
lib-sourcify v2 consists of several key components:
137140

138141
- **Validation**: Based on a Solidity metadata.json file that describes a contract build, checks if all source files are present and valid. Fetches missing sources from IPFS if necessary.
139-
140142
- `SolidityMetadataContract`: Represents a Solidity contract with its metadata and source files
141143
- `processFiles.ts`: Utility functions for creating `SolidityMetadataContract` instances from files
142144

143145
- **Compilation**: Handles contract compilation
144-
145146
- `AbstractCompilation`: Base class for compilation
146147
- `SolidityCompilation`: Handles Solidity compilation
147148
- `VyperCompilation`: Handles Vyper compilation
@@ -177,7 +178,7 @@ import { SolidityMetadataContract } from '@ethereum-sourcify/lib-sourcify';
177178
// Set a custom IPFS gateway
178179
SolidityMetadataContract.setGlobalIpfsGateway({
179180
url: 'https://my-ipfs-gateway.com/ipfs/',
180-
headers: { 'Authorization': 'Bearer my-token' }
181+
headers: { Authorization: 'Bearer my-token' },
181182
});
182183

183184
// Get the current IPFS gateway configuration
@@ -189,7 +190,11 @@ const gateway = SolidityMetadataContract.getGlobalIpfsGateway();
189190
You can set the global log level and provide a custom logger:
190191

191192
```typescript
192-
import { setLibSourcifyLoggerLevel, setLibSourcifyLogger, getLibSourcifyLoggerLevel } from '@ethereum-sourcify/lib-sourcify';
193+
import {
194+
setLibSourcifyLoggerLevel,
195+
setLibSourcifyLogger,
196+
getLibSourcifyLoggerLevel,
197+
} from '@ethereum-sourcify/lib-sourcify';
193198

194199
// Set the log level
195200
setLibSourcifyLoggerLevel(5); // 0=errors, 1=warnings, 2=info, 5=debug, 6=silly
@@ -205,7 +210,7 @@ setLibSourcifyLogger({
205210
},
206211
log(level, msg) {
207212
// Custom logging implementation
208-
}
213+
},
209214
});
210215
```
211216

@@ -222,28 +227,31 @@ import {
222227
SolidityOutput,
223228
ISolidityCompiler,
224229
SolidityJsonInput,
225-
} from "@ethereum-sourcify/lib-sourcify";
226-
import { useSolidityCompiler } from "@ethereum-sourcify/compilers";
230+
} from '@ethereum-sourcify/lib-sourcify';
231+
import { useSolidityCompiler } from '@ethereum-sourcify/compilers';
227232

228233
class Solc implements ISolidityCompiler {
229-
constructor(private solcRepoPath: string, private solJsonRepoPath: string) {}
234+
constructor(
235+
private solcRepoPath: string,
236+
private solJsonRepoPath: string,
237+
) {}
230238

231239
async compile(
232240
version: string,
233241
solcJsonInput: SolidityJsonInput,
234-
forceEmscripten: boolean = false
242+
forceEmscripten: boolean = false,
235243
): Promise<SolidityOutput> {
236244
return await useSolidityCompiler(
237245
this.solcRepoPath,
238246
this.solJsonRepoPath,
239247
version,
240248
solcJsonInput,
241-
forceEmscripten
249+
forceEmscripten,
242250
);
243251
}
244252
}
245253

246-
const solc = new Solc("/path/to/solc/repo", "/path/to/solcjs/repo");
254+
const solc = new Solc('/path/to/solc/repo', '/path/to/solcjs/repo');
247255
```
248256

249257
### Vyper Compiler Example
@@ -359,7 +367,10 @@ const compilation = await metadataContract.createCompilation(solidityCompiler);
359367
For file-based validation:
360368

361369
```typescript
362-
import { createMetadataContractsFromFiles, PathBuffer } from '@ethereum-sourcify/lib-sourcify';
370+
import {
371+
createMetadataContractsFromFiles,
372+
PathBuffer,
373+
} from '@ethereum-sourcify/lib-sourcify';
363374

364375
const pathBuffers: PathBuffer[] = [];
365376
pathBuffers.push({
@@ -488,14 +499,45 @@ setLibSourcifyLogger({
488499
});
489500
```
490501

502+
## EtherscanUtils
503+
504+
EtherscanUtils provides utilities for importing and processing verified contracts from Etherscan APIs.
505+
506+
### Fetching Contract Data from Etherscan
507+
508+
```typescript
509+
import { EtherscanUtils } from '@ethereum-sourcify/lib-sourcify';
510+
511+
// Fetch contract source code and metadata from Etherscan
512+
const etherscanResult = await EtherscanUtils.fetchFromEtherscan(
513+
1, // chainId
514+
'0x6B175474E89094C44Da98b954EedeAC495271d0F', // contract address
515+
'YOUR_API_KEY', // optional API key
516+
);
517+
```
518+
519+
### Creating Compilations from Etherscan Results
520+
521+
```typescript
522+
// Create a compilation object directly from Etherscan data
523+
const compilation = await EtherscanUtils.getCompilationFromEtherscanResult(
524+
etherscanResult,
525+
solidityCompiler, // ISolidityCompiler instance
526+
vyperCompiler, // IVyperCompiler instance (for Vyper contracts)
527+
);
528+
529+
// Use the compilation for verification
530+
const verification = new Verification(compilation, chain, contractAddress);
531+
await verification.verify();
532+
```
533+
491534
## Migration Guide from v1 to v2
492535

493536
Version 2 of lib-sourcify brings a significant redesign of the library's architecture. Here's how to migrate from v1 to v2:
494537

495538
### Key Changes
496539

497540
1. **Class Structure Changes**:
498-
499541
- `AbstractCheckedContract` is replaced by language-specific compilation classes
500542
- `SolidityCheckedContract` functionality is now split between `SolidityMetadataContract` and `SolidityCompilation`
501543
- `VyperCheckedContract` is now represented by `VyperCompilation`

services/server/src/server/services/utils/etherscan-util.ts

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import {
22
ISolidityCompiler,
33
IVyperCompiler,
4-
SolidityJsonInput,
54
SourcifyChain,
6-
VyperJsonInput,
7-
VyperCompilation,
8-
SolidityCompilation,
95
} from "@ethereum-sourcify/lib-sourcify";
106
import { BadRequestError, NotFoundError } from "../../../common/errors";
117
import { TooManyRequests } from "../../../common/errors/TooManyRequests";
@@ -96,65 +92,19 @@ export const fetchFromEtherscan = async (
9692
}
9793
};
9894

99-
export const processSolidityResultFromEtherscan = (
100-
contractResultJson: any,
101-
throwV2Errors: boolean,
102-
) => {
103-
try {
104-
return EtherscanUtils.processSolidityResultFromEtherscan(
105-
contractResultJson,
106-
);
107-
} catch (err) {
108-
return mapLibError(err, throwV2Errors);
109-
}
110-
};
111-
112-
export const processVyperResultFromEtherscan = async (
113-
contractResultJson: any,
114-
throwV2Errors: boolean,
115-
) => {
116-
try {
117-
return await EtherscanUtils.processVyperResultFromEtherscan(
118-
contractResultJson,
119-
);
120-
} catch (err) {
121-
return mapLibError(err, throwV2Errors);
122-
}
123-
};
124-
12595
export async function getCompilationFromEtherscanResult(
12696
etherscanResult: any,
12797
solc: ISolidityCompiler,
12898
vyperCompiler: IVyperCompiler,
12999
throwV2Errors = false,
130100
) {
131-
if (EtherscanUtils.isVyperResult(etherscanResult)) {
132-
const processedResult = await processVyperResultFromEtherscan(
133-
etherscanResult,
134-
throwV2Errors,
135-
);
136-
return new VyperCompilation(
137-
vyperCompiler,
138-
processedResult.compilerVersion,
139-
processedResult.jsonInput as VyperJsonInput,
140-
{
141-
path: processedResult.contractPath,
142-
name: processedResult.contractName,
143-
},
144-
);
145-
} else {
146-
const processedResult = processSolidityResultFromEtherscan(
101+
try {
102+
return EtherscanUtils.getCompilationFromEtherscanResult(
147103
etherscanResult,
148-
throwV2Errors,
149-
);
150-
return new SolidityCompilation(
151104
solc,
152-
processedResult.compilerVersion,
153-
processedResult.jsonInput as SolidityJsonInput,
154-
{
155-
path: processedResult.contractPath,
156-
name: processedResult.contractName,
157-
},
105+
vyperCompiler,
158106
);
107+
} catch (err) {
108+
return mapLibError(err, throwV2Errors);
159109
}
160110
}

services/server/src/server/services/workers/verificationWorker.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
SourcifyChainMap,
1212
SolidityMetadataContract,
1313
useAllSourcesAndReturnCompilation,
14-
ProcessedEtherscanResult,
15-
EtherscanUtils,
1614
} from "@ethereum-sourcify/lib-sourcify";
1715
import { resolve } from "path";
1816
import { ChainRepository } from "../../../sourcify-chain-repository";
@@ -29,10 +27,7 @@ import type {
2927
VerificationWorkerInput,
3028
} from "./workerTypes";
3129
import logger, { setLogLevel } from "../../../common/logger";
32-
import {
33-
processSolidityResultFromEtherscan,
34-
processVyperResultFromEtherscan,
35-
} from "../utils/etherscan-util";
30+
import { getCompilationFromEtherscanResult } from "../utils/etherscan-util";
3631
import { asyncLocalStorage } from "../../../common/async-context";
3732

3833
export const filename = resolve(__filename);
@@ -246,25 +241,18 @@ async function _verifyFromEtherscan({
246241
address,
247242
etherscanResult,
248243
}: VerifyFromEtherscanInput): Promise<VerifyOutput> {
249-
let processedResult: ProcessedEtherscanResult;
250-
if (EtherscanUtils.isVyperResult(etherscanResult)) {
251-
processedResult = await processVyperResultFromEtherscan(
252-
etherscanResult,
253-
true,
254-
);
255-
} else {
256-
processedResult = processSolidityResultFromEtherscan(etherscanResult, true);
257-
}
244+
const compilation = await getCompilationFromEtherscanResult(
245+
etherscanResult,
246+
solc,
247+
vyper,
248+
);
258249

259250
return _verifyFromJsonInput({
260251
chainId,
261252
address,
262-
jsonInput: processedResult.jsonInput,
263-
compilerVersion: processedResult.compilerVersion,
264-
compilationTarget: {
265-
name: processedResult.contractName,
266-
path: processedResult.contractPath,
267-
},
253+
jsonInput: compilation.jsonInput,
254+
compilerVersion: compilation.compilerVersion,
255+
compilationTarget: compilation.compilationTarget,
268256
});
269257
}
270258

0 commit comments

Comments
 (0)