Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1504 from hyperledger/solts-naming
Browse files Browse the repository at this point in the history
Fix contractName spelling and provide contract name on contract object
  • Loading branch information
Silas Davis authored Jul 19, 2021
2 parents dc81d35 + 4f6a1c2 commit b74c28f
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 186 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# [Hyperledger Burrow](https://github.com/hyperledger/burrow) Changelog
## [0.34.3] - 2021-07-19
### Fixed
- [JS] Fix spelling of 'contractName' in solts, add contract name to contract object.

### Added
- [JS] Added option to build.ts code generation to not fail on Solidity compiler warnings, which is now the default. Warnings are still logged to stderr


## [0.34.2] - 2021-07-09
### Fixed
- [Build] Add 0.34.1 changes!
Expand Down Expand Up @@ -799,6 +807,7 @@ This release marks the start of Eris-DB as the full permissioned blockchain node
- [Blockchain] Fix getBlocks to respect block height cap.


[0.34.3]: https://github.com/hyperledger/burrow/compare/v0.34.2...v0.34.3
[0.34.2]: https://github.com/hyperledger/burrow/compare/v0.34.1...v0.34.2
[0.34.1]: https://github.com/hyperledger/burrow/compare/v0.34.0...v0.34.1
[0.34.0]: https://github.com/hyperledger/burrow/compare/v0.33.1...v0.34.0
Expand Down
5 changes: 4 additions & 1 deletion NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### Fixed
- [Build] Add 0.34.1 changes!
- [JS] Fix spelling of 'contractName' in solts, add contract name to contract object.

### Added
- [JS] Added option to build.ts code generation to not fail on Solidity compiler warnings, which is now the default. Warnings are still logged to stderr

4 changes: 2 additions & 2 deletions js/src/contracts/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export namespace Solidity {
};
};

type Error = {
export type Error = {
sourceLocation?: {
file: string;
start: number;
Expand All @@ -63,7 +63,7 @@ export namespace Solidity {

export type OutputDescription = {
contracts: Record<string, Record<string, Contract>>;
errors: Array<Error>;
errors?: Array<Error>;
sourceList: Array<string>;
sources: Record<string, Source>;
};
Expand Down
4 changes: 2 additions & 2 deletions js/src/solts/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type Compiled = {
links: Array<string>;
};

const contractNameName = factory.createIdentifier('contactName');
const contractNameName = factory.createIdentifier('contractName');
const abiName = factory.createIdentifier('abi');

// Note: this is a very useful tool for discovering the correct Typescript factory API calls to produce a particular
Expand Down Expand Up @@ -70,7 +70,7 @@ export function newFile(contracts: Compiled[], burrowImportPath: string): ts.Nod
...deployMembers,
...eventMembers,
declareContractType(),
generateContractObject(contractNameName, methods, provider),
generateContractObject(contract.name, methods, provider),
generateEncodeObject(methods, provider, abiName),
generateDecodeObject(methods, provider, abiName),
];
Expand Down
79 changes: 45 additions & 34 deletions js/src/solts/build.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import { promises as fs } from 'fs';
import * as path from 'path';
import * as solcv5 from 'solc_v5';
import * as solcv8 from 'solc_v8';
import { promises as fs } from "fs";
import * as path from "path";
import * as solcv5 from "solc_v5";
import * as solcv8 from "solc_v8";
import {
decodeOutput,
encodeInput,
importLocalResolver,
inputDescriptionFromFiles,
Solidity,
} from '../contracts/compile';
import { Compiled, newFile, printNodes, tokenizeLinks } from './api';
Solidity
} from "../contracts/compile";
import { Compiled, newFile, printNodes, tokenizeLinks } from "./api";

const solcCompilers = {
v5: solcv5,
v8: solcv8,
v8: solcv8
} as const;

export const defaultBuildOptions = {
solcVersion: 'v5' as keyof typeof solcCompilers,
burrowImportPath: (sourceFile: string) => '@hyperledger/burrow' as string,
binPath: 'bin' as string,
abiExt: '.abi' as string,
solcVersion: "v5" as keyof typeof solcCompilers,
burrowImportPath: (sourceFile: string) => "@hyperledger/burrow" as string,
binPath: "bin" as string,
abiExt: ".abi" as string,
// Used to resolve layout in bin folder - defaults to srcPath if is passed or process.cwd() otherwise
basePath: undefined as undefined | string,
failOnWarnings: false as boolean
} as const;

export type BuildOptions = typeof defaultBuildOptions;
Expand All @@ -35,45 +36,51 @@ export type BuildOptions = typeof defaultBuildOptions;
* - Outputs the ABI files into bin to be later included in the distribution (for Vent and other ABI-consuming services)
*/
export async function build(srcPathOrFiles: string | string[], opts?: Partial<BuildOptions>): Promise<void> {
const { solcVersion, binPath, basePath, burrowImportPath, abiExt } = {
const { failOnWarnings, solcVersion, binPath, basePath, burrowImportPath, abiExt } = {
...defaultBuildOptions,
...opts,
...opts
};
const resolvedBasePath = basePath ?? (typeof srcPathOrFiles === 'string' ? srcPathOrFiles : process.cwd());
const resolvedBasePath = basePath ?? (typeof srcPathOrFiles === "string" ? srcPathOrFiles : process.cwd());
process.chdir(resolvedBasePath);
const basePathPrefix = new RegExp('^' + path.resolve(resolvedBasePath));
const basePathPrefix = new RegExp("^" + path.resolve(resolvedBasePath));
await fs.mkdir(binPath, { recursive: true });
const solidityFiles = await getSourceFilesList(srcPathOrFiles);
const inputDescription = inputDescriptionFromFiles(
// solidityFiles.map((f) => path.resolve(resolvedBasePath, f.replace(basePathPrefix, ''))),
solidityFiles,
solidityFiles
);
const input = encodeInput(inputDescription);
const solc = solcCompilers[solcVersion];

const solcOutput = solc.compile(input, { import: importLocalResolver(resolvedBasePath) });
const output = decodeOutput(solcOutput);
if (output.errors && output.errors.length > 0) {
const errors = output.errors?.filter((e) => failOnWarnings || (e.severity === "error")) || [];
if (errors.length > 0) {
throw new Error(
'Solidity compiler errors: ' + output.errors.map((err) => err.formattedMessage || err.message).join(', '),
"Solidity compiler errors:\n" + formatErrors(errors)
);
}
const warnings = output.errors?.filter((e) => e.severity === "warning") || [];

if (warnings.length) {
console.error("Solidity compiler warnings (not treated as fatal):\n" + formatErrors(warnings))
}

const plan = Object.keys(output.contracts).map((filename) => ({
source: filename,
target: filename.replace(/\.[^/.]+$/, '.abi.ts'),
target: filename.replace(/\.[^/.]+$/, ".abi.ts"),
contracts: Object.entries(output.contracts[filename]).map(([name, contract]) => ({
name,
contract,
})),
contract
}))
}));

const binPlan = plan.flatMap((f) => {
return f.contracts.map(({ name, contract }) => ({
source: f.source,
name,
filename: path.join(binPath, path.dirname(path.resolve(f.source)).replace(basePathPrefix, ''), name + abiExt),
abi: JSON.stringify(contract),
filename: path.join(binPath, path.dirname(path.resolve(f.source)).replace(basePathPrefix, ""), name + abiExt),
abi: JSON.stringify(contract)
}));
});

Expand All @@ -83,7 +90,7 @@ export async function build(srcPathOrFiles: string | string[], opts?: Partial<Bu
const dupeDescs = dupes.map(({ key, dupes }) => ({ duplicate: key, sources: dupes.map((d) => d.source) }));
throw Error(
`Duplicate contract names found (these contracts will result ABI filenames that will collide since ABIs ` +
`are flattened in '${binPath}'):\n${dupeDescs.map((d) => JSON.stringify(d)).join('\n')}`,
`are flattened in '${binPath}'):\n${dupeDescs.map((d) => JSON.stringify(d)).join("\n")}`
);
}

Expand All @@ -100,11 +107,11 @@ export async function build(srcPathOrFiles: string | string[], opts?: Partial<Bu
printNodes(
...newFile(
contracts.map(({ name, contract }) => getCompiled(name, contract)),
burrowImportPath(source),
),
),
),
),
burrowImportPath(source)
)
)
)
)
]);
}

Expand All @@ -114,7 +121,7 @@ function getCompiled(name: string, contract: Solidity.Contract): Compiled {
abi: contract.abi,
bytecode: contract.evm.bytecode.object,
deployedBytecode: contract.evm.deployedBytecode.object,
links: tokenizeLinks(contract.evm.bytecode.linkReferences),
links: tokenizeLinks(contract.evm.bytecode.linkReferences)
};
}

Expand All @@ -131,15 +138,15 @@ function findDupes<T>(list: T[], by: (t: T) => string): { key: string; dupes: T[
.filter(([_, group]) => group.length > 1)
.map(([key, dupes]) => ({
key,
dupes,
dupes
}));
}

async function getSourceFilesList(srcPathOrFiles: string | string[]): Promise<string[]> {
if (typeof srcPathOrFiles === 'string') {
if (typeof srcPathOrFiles === "string") {
const files: string[] = [];
for await (const f of walkDir(srcPathOrFiles)) {
if (path.extname(f) === '.sol') {
if (path.extname(f) === ".sol") {
files.push(f);
}
}
Expand All @@ -158,3 +165,7 @@ async function* walkDir(dir: string): AsyncGenerator<string, void, void> {
}
}
}

function formatErrors(errors: Solidity.Error[]): string {
return errors.map((err) => err.formattedMessage || err.message).join("")
}
7 changes: 4 additions & 3 deletions js/src/solts/lib/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { encodeName } from './encoder';
import {
BoundsType,
CallbackReturnType,
dataFromEvent,
topicsFromEvent,
createListener,
createListenerForFunction,
dataFromEvent,
eventSigHash,
topicsFromEvent,
} from './events';
import { errName, EventErrParameter, eventName, EventParameter, Provider } from './provider';
import { ContractMethodsList, getRealType, inputOuputsToType, Signature } from './solidity';
Expand Down Expand Up @@ -53,7 +53,7 @@ export function declareContractType(): ts.TypeAliasDeclaration {
}

export function generateContractObject(
contractNameName: ts.Identifier,
contractName: string,
abi: ContractMethodsList,
provider: Provider,
): ts.VariableStatement {
Expand Down Expand Up @@ -92,6 +92,7 @@ export function generateContractObject(
EqualsGreaterThanToken,
asConst(
factory.createObjectLiteralExpression([
factory.createPropertyAssignment('name', factory.createStringLiteral(contractName)),
factory.createShorthandPropertyAssignment(addressName),
...functionObjectProperties,
...eventObjectProperties,
Expand Down
3 changes: 2 additions & 1 deletion js/src/solts/sol/Addition.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Addition {
export const contactName = 'Addition';
export const contractName = 'Addition';
export const abi =
'[{"constant":true,"inputs":[{"internalType":"int256","name":"a","type":"int256"},{"internalType":"int256","name":"b","type":"int256"}],"name":"add","outputs":[{"internalType":"int256","name":"sum","type":"int256"}],"payable":false,"stateMutability":"pure","type":"function"}]';
export const bytecode =
Expand All @@ -55,6 +55,7 @@ export namespace Addition {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Addition',
address,
functions: {
add(
Expand Down
3 changes: 2 additions & 1 deletion js/src/solts/sol/Contains.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Contains {
export const contactName = 'Contains';
export const contractName = 'Contains';
export const abi =
'[{"constant":true,"inputs":[{"internalType":"address[]","name":"_list","type":"address[]"},{"internalType":"address","name":"_value","type":"address"}],"name":"contains","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256[]","name":"_list","type":"uint256[]"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"contains","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"}]';
export const bytecode =
Expand All @@ -55,6 +55,7 @@ export namespace Contains {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Contains',
address,
functions: {
contains(_list: string[], _value: string, call = defaultCall): Promise<[boolean]> {
Expand Down
6 changes: 4 additions & 2 deletions js/src/solts/sol/Creator.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Creator {
export const contactName = 'Creator';
export const contractName = 'Creator';
export const abi =
'[{"constant":false,"inputs":[{"internalType":"string","name":"_name","type":"string"}],"name":"create","outputs":[{"internalType":"address","name":"proxy","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]';
export const bytecode =
Expand All @@ -58,6 +58,7 @@ export namespace Creator {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Creator',
address,
functions: {
create(
Expand Down Expand Up @@ -96,7 +97,7 @@ export namespace Creator {
};
}
export namespace Proxy {
export const contactName = 'Proxy';
export const contractName = 'Proxy';
export const abi =
'[{"inputs":[{"internalType":"string","name":"_name","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[],"name":"get","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]';
export const bytecode =
Expand All @@ -123,6 +124,7 @@ export namespace Proxy {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Proxy',
address,
functions: {
get(call = defaultCall): Promise<[string]> {
Expand Down
3 changes: 2 additions & 1 deletion js/src/solts/sol/Eventer.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Eventer {
export const contactName = 'Eventer';
export const contractName = 'Eventer';
export const abi =
'[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"eventId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"intervalId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"eventAddress","type":"address"},{"indexed":false,"internalType":"string","name":"namespace","type":"string"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"},{"indexed":false,"internalType":"string","name":"metadata","type":"string"}],"name":"Init","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int256","name":"timestamp","type":"int256"},{"indexed":false,"internalType":"string","name":"place","type":"string"},{"indexed":false,"internalType":"string","name":"postalAddress","type":"string"}],"name":"MonoRampage","type":"event"},{"constant":false,"inputs":[],"name":"announce","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]';
export const bytecode =
Expand Down Expand Up @@ -102,6 +102,7 @@ export namespace Eventer {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Eventer',
address,
functions: {
announce(call = defaultCall): Promise<void> {
Expand Down
3 changes: 2 additions & 1 deletion js/src/solts/sol/MultipleReturns.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Multiple {
export const contactName = 'Multiple';
export const contractName = 'Multiple';
export const abi =
'[{"constant":true,"inputs":[],"name":"get","outputs":[{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"}],"payable":false,"stateMutability":"pure","type":"function"}]';
export const bytecode =
Expand All @@ -55,6 +55,7 @@ export namespace Multiple {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Multiple',
address,
functions: {
get(call = defaultCall): Promise<[number, number, number]> {
Expand Down
3 changes: 2 additions & 1 deletion js/src/solts/sol/Unnamed.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Unnamed {
export const contactName = 'Unnamed';
export const contractName = 'Unnamed';
export const abi =
'[{"constant":true,"inputs":[{"internalType":"int256","name":"a","type":"int256"},{"internalType":"int256","name":"","type":"int256"}],"name":"set","outputs":[{"internalType":"int256","name":"sum","type":"int256"}],"payable":false,"stateMutability":"pure","type":"function"}]';
export const bytecode =
Expand All @@ -55,6 +55,7 @@ export namespace Unnamed {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Unnamed',
address,
functions: {
set(
Expand Down
3 changes: 2 additions & 1 deletion js/src/solts/sol/storage/Storage.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function defaultCall<Output>(
return callback(returnData);
}
export namespace Storage {
export const contactName = 'Storage';
export const contractName = 'Storage';
export const abi =
'[{"inputs":[{"internalType":"int256","name":"x","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[],"name":"get","outputs":[{"internalType":"int256","name":"ret","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"int256","name":"x","type":"int256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]';
export const bytecode =
Expand All @@ -55,6 +55,7 @@ export namespace Storage {
export type Contract = ReturnType<typeof contract>;
export const contract = (client: Provider, address: string) =>
({
name: 'Storage',
address,
functions: {
get(
Expand Down
Loading

0 comments on commit b74c28f

Please sign in to comment.