From 37e23ade65268b035df0ed5576614e569443a9e1 Mon Sep 17 00:00:00 2001 From: Geoffrey Hayes Date: Wed, 5 Jun 2019 21:50:33 -0700 Subject: [PATCH] Continue to build shell --- .build/test/contracts.json | 1 - .gitignore | 3 + .tsbuilt/contract.js | 19 +++++- .tsbuilt/deploy.js | 6 +- .tsbuilt/do_deploy.js | 1 - README.md | 29 +++++++-- config/development.js | 13 ++++ config/test.js | 13 ++++ contracts/View.sol | 9 +++ package.json | 11 ++-- poster/README.md | 35 +++++++++++ poster/package.json | 13 ++-- poster/src/poster.ts | 4 ++ poster/test/poster_test.ts | 5 ++ poster/tsconfig.json | 63 ++++++++++++++++++++ poster/yarn.lock | 4 ++ script/compile | 5 -- script/deploy | 0 sdk/typescript/README.md | 52 ++++++++++++++++ sdk/typescript/package.json | 4 +- sdk/typescript/src/{delfi.ts => reporter.ts} | 9 +-- sdk/typescript/test/express_test.ts | 7 +++ sdk/typescript/test/reporter_test.ts | 7 +++ sdk/typescript/tsconfig.json | 63 ++++++++++++++++++++ tests/OracleTest.js | 4 +- tests/ViewTest.js | 14 +++++ tsrc/config.ts | 18 +----- tsrc/contract.ts | 20 ++++++- tsrc/deploy.ts | 14 ++++- tsrc/test.ts | 5 +- 30 files changed, 397 insertions(+), 54 deletions(-) delete mode 100644 .build/test/contracts.json delete mode 100644 .tsbuilt/do_deploy.js create mode 100644 config/development.js create mode 100644 config/test.js create mode 100644 contracts/View.sol create mode 100644 poster/README.md create mode 100644 poster/src/poster.ts create mode 100644 poster/test/poster_test.ts create mode 100644 poster/tsconfig.json create mode 100644 poster/yarn.lock delete mode 100755 script/compile delete mode 100644 script/deploy create mode 100644 sdk/typescript/README.md rename sdk/typescript/src/{delfi.ts => reporter.ts} (91%) create mode 100644 sdk/typescript/test/express_test.ts create mode 100644 sdk/typescript/test/reporter_test.ts create mode 100644 sdk/typescript/tsconfig.json create mode 100644 tests/ViewTest.js diff --git a/.build/test/contracts.json b/.build/test/contracts.json deleted file mode 100644 index 89da2945..00000000 --- a/.build/test/contracts.json +++ /dev/null @@ -1 +0,0 @@ -{"contracts":{"contracts/Oracle.sol:Oracle":{"abi":"[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]","bin":"608060405234801561001057600080fd5b5061013c806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806306fdde0314602d575b600080fd5b60336047565b604051603e9190609f565b60405180910390f35b60408051808201909152600e81526d7a6520636f6f6c206f7261636c6560901b602082015290565b600060788260b5565b6080818560b9565b9350608e81856020860160c2565b60958160ef565b9093019392505050565b6020808252810160ae8184606f565b9392505050565b5190565b90815260200190565b60005b8381101560db57818101518382015260200160c5565b8381111560e9576000848401525b50505050565b601f01601f19169056fea365627a7a7230582025d9bc767385b3c8cd621a324dcfeb9da7bb22c684cd44e6f6e027d684762e7e6c6578706572696d656e74616cf564736f6c63430005090040"}},"version":"0.5.9+commit.c68bc34e.Darwin.appleclang"} diff --git a/.gitignore b/.gitignore index bb6fe2aa..5288d8aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *node_modules* +*.tsbuilt* +.build/test +.build/development diff --git a/.tsbuilt/contract.js b/.tsbuilt/contract.js index 8619c2e9..04ef1607 100644 --- a/.tsbuilt/contract.js +++ b/.tsbuilt/contract.js @@ -9,6 +9,8 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); const path = __importStar(require("path")); +const BUILD_FILE_NAME = 'build.json'; +const CONTRACT_FILE_NAME = 'contracts.json'; async function readFile(file, def, fn) { return new Promise((resolve, reject) => { fs.access(file, fs.constants.F_OK, (err) => { @@ -23,11 +25,19 @@ async function readFile(file, def, fn) { }); }); } +async function writeFile(file, data) { + return new Promise((resolve, reject) => { + fs.writeFile(file, data, (err) => { + return err ? reject(err) : resolve(); + }); + }); +} +exports.writeFile = writeFile; function getBuildFile(network, file) { return path.join(process.cwd(), '.build', network, file); } async function getContract(network, name) { - let contracts = await readFile(getBuildFile(network, 'contracts.json'), {}, JSON.parse); + let contracts = await readFile(getBuildFile(network, BUILD_FILE_NAME), {}, JSON.parse); let contractsObject = contracts["contracts"] || {}; let foundContract = Object.entries(contractsObject).find(([pathContractName, contract]) => { let [_, contractName] = pathContractName.split(":", 2); @@ -51,3 +61,10 @@ async function deployContract(web3, network, from, name, args) { return await contract.deploy({ data: '0x' + contractBuild.bin, arguments: args }).send({ from: from, gas: 1000000 }); } exports.deployContract = deployContract; +async function saveContract(name, contract, network) { + let file = getBuildFile(network, CONTRACT_FILE_NAME); + let curr = await readFile(file, {}, JSON.parse); + curr[name] = contract.address; + await writeFile(file, JSON.stringify(curr)); +} +exports.saveContract = saveContract; diff --git a/.tsbuilt/deploy.js b/.tsbuilt/deploy.js index 2b1a46c4..0ebb253d 100644 --- a/.tsbuilt/deploy.js +++ b/.tsbuilt/deploy.js @@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); const config_1 = require("./config"); const contract_1 = require("./contract"); (async function () { - let config = await config_1.loadConfig("development"); + let network = "development"; + let config = await config_1.loadConfig(network); let web3 = await config_1.loadWeb3(config); let account = await config_1.loadAccount(config, web3); - await contract_1.deployContract(web3, "development", account, "Oracle", []); + let contract = await contract_1.deployContract(web3, config.network, account, "Oracle", []); + await contract_1.saveContract('Oracle', contract, config.network); })(); diff --git a/.tsbuilt/do_deploy.js b/.tsbuilt/do_deploy.js deleted file mode 100644 index 3918c74e..00000000 --- a/.tsbuilt/do_deploy.js +++ /dev/null @@ -1 +0,0 @@ -"use strict"; diff --git a/README.md b/README.md index b6e20601..f8325377 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,32 @@ The Open Oracle is a standard and SDK allowing reporters to sign key-value pairs ## Contracts -First, you will need solc 0.5.9 installed. The binary package is faster, but you can use solcjs by running `yarn install`. +First, you will need solc 0.5.9 installed. The binary package is faster, but you can use solcjs by running `yarn install solcjs@0.5.9 --dev`. -... +To deploy the Open Oracle locally, you can run: -## SDK +``` +yarn run saddle:deploy development Oracle +``` -This repository contains an SDK to allow users to quickly sign data in a number of languages. We currently support: +Or you can add a view in `MyView.sol` and run: - * JavaScript / TypeScript +``` +yarn run saddle:deploy development MyView arg1 arg2 ... +``` + +To run tests: + +``` +yarn run test +``` + +## Reporter SDK + +This repository contains a set of SDKs for reporters to easily sign "reporter" data in any supported languages. We currently support the following languages: + + * [TypeScript](./sdk/typescript/README.md) / JavaScript + * [Elixir](./sdk/typescript/README.md) ## Poster @@ -21,4 +38,4 @@ The poster is a simple application that reads from a given feed (or set of feeds ## Contributing -Note: the code in this repository is held under the MIT license. Any contributors must agree to release contributed code under this same license. \ No newline at end of file +Note: the code in this repository is held under the MIT license. Any contributors must agree to release contributed code under this same license. Please submit an issue (or create a pull request) for any issues or contributions to the project. diff --git a/config/development.js b/config/development.js new file mode 100644 index 00000000..860cae20 --- /dev/null +++ b/config/development.js @@ -0,0 +1,13 @@ +const Web3 = require('web3'); + +const options = { + transactionConfirmationBlocks: 1, + transactionBlockTimeout: 5 +} + +async function loadWeb3() { + console.log("loading development web3..."); + return new Web3(Web3.givenProvider || 'http://127.0.0.1:8545', undefined, options); +} + +export default loadWeb3; diff --git a/config/test.js b/config/test.js new file mode 100644 index 00000000..e8976c32 --- /dev/null +++ b/config/test.js @@ -0,0 +1,13 @@ +const Web3 = require('web3'); + +const options = { + transactionConfirmationBlocks: 1, + transactionBlockTimeout: 5 +} + +async function loadWeb3() { + console.log("loading test web3..."); + return new Web3(ganache.provider(), undefined, options); +} + +export default loadWeb3; diff --git a/contracts/View.sol b/contracts/View.sol new file mode 100644 index 00000000..b20e234f --- /dev/null +++ b/contracts/View.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +contract View { + + function name() external pure returns (string memory) { + return "ze cool view"; + } +} diff --git a/package.json b/package.json index e99448a7..66c61eb3 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "delfi", + "name": "compound-open-oracle", "version": "1.0.0", - "description": "The Open Oracle", + "description": "The Compound Open Oracle", "main": "index.js", - "repository": "https://github.com/compound-finance/delfi", + "repository": "https://github.com/compound-finance/open-oracle", "author": "Compound Labs, Inc.", "license": "MIT", "dependencies": { @@ -14,8 +14,9 @@ "jest": "^24.8.0" }, "scripts": { - "saddle:test": "script/compile test && tsc && yarn run saddle:test:run", + "saddle:compile": "env network=${1:-\"development\"} && echo mkdir -p .build/${network} && echo solc --combined-json bin,abi --optimize contracts/*.sol > .build/${network}/build.json", "saddle:test:run": "node --async-stack-traces --stack-trace-limit=1000 ./node_modules/jest-cli/bin/jest.js", - "saddle:deploy": "./tsbuilt/do_deploy.js" + "saddle:deploy": "env network=${1:-\"development\"} && env contract=\"$2\" && shift && shift && yarn run saddle:compile && node ./.tsbuilt/deploy.js $@", + "test": "env network=${1:-\"test\"} && yarn run saddle:compile && yarn run saddle:test:run" } } diff --git a/poster/README.md b/poster/README.md new file mode 100644 index 00000000..6932bb5b --- /dev/null +++ b/poster/README.md @@ -0,0 +1,35 @@ + +## The Open Oracle Poster + +The poster is a simple application to pull prices from a set of source feeds and post them to the blockchain. The posters main job is to make sure that the requested source data is posted to the Ethereum blockchain, and thus is concerned about nonces, gas prices, etc. + +## Installation + +The DelFi poster can be run as a standalone process or as a module for configuration. To install as a global process: + +``` +yarn global add open-oracle-poster +``` + +Or, if you plan on customizing the poster, you can install in a project: + +``` +yarn add open-oracle-poster +``` + +## Running + +To run as a standalone: + +``` +open-oracle-poster --poster-key=0x... +``` + +Otherwise, you can include the DelFi poster in an app for configuration: + +```typescript +import poster from 'delfi-poster'; + +poster.configure(...); +poster.run(); +``` diff --git a/poster/package.json b/poster/package.json index 130f6896..94944992 100644 --- a/poster/package.json +++ b/poster/package.json @@ -1,9 +1,12 @@ { - "name": "delfi-poster", + "name": "open-oracle-poster", "version": "1.0.0", - "description": "A Customizable Poster for DelFi", - "main": "index.js", - "repository": "https://compound.finance/delfi", + "description": "A Customizable Poster for the Compound Open Oracle", + "main": "poster.js", + "repository": "https://compound.finance/open-oracle", "author": "Compound Labs, Inc.", - "license": "MIT" + "license": "MIT", + "scripts": { + "start": "node ./.tsbuilt/poster.js" + } } diff --git a/poster/src/poster.ts b/poster/src/poster.ts new file mode 100644 index 00000000..a31b826e --- /dev/null +++ b/poster/src/poster.ts @@ -0,0 +1,4 @@ + +(async function () { + console.log("Running Open Oracle Poster..."); +})(); diff --git a/poster/test/poster_test.ts b/poster/test/poster_test.ts new file mode 100644 index 00000000..7acf3955 --- /dev/null +++ b/poster/test/poster_test.ts @@ -0,0 +1,5 @@ +import poster from '../src/poster'; + +describe('Poster', async () => { + // TODO: Add test cases +}); diff --git a/poster/tsconfig.json b/poster/tsconfig.json new file mode 100644 index 00000000..460edc1d --- /dev/null +++ b/poster/tsconfig.json @@ -0,0 +1,63 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["esnext"], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./.tsbuilt", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "include": [ + "./src/**/*" + ] +} diff --git a/poster/yarn.lock b/poster/yarn.lock new file mode 100644 index 00000000..fb57ccd1 --- /dev/null +++ b/poster/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + diff --git a/script/compile b/script/compile deleted file mode 100755 index 0c02f3d6..00000000 --- a/script/compile +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -network="$1" -mkdir -p .build/${network} -solc --combined-json bin,abi --optimize contracts/*.sol > .build/${network}/contracts.json \ No newline at end of file diff --git a/script/deploy b/script/deploy deleted file mode 100644 index e69de29b..00000000 diff --git a/sdk/typescript/README.md b/sdk/typescript/README.md new file mode 100644 index 00000000..897bf7dc --- /dev/null +++ b/sdk/typescript/README.md @@ -0,0 +1,52 @@ + +## The Open Oracle Reporter + +The Open Oracle Reporter makes it easy to add a price feed to your application web server. + +## Installation + +The DelFi Reporter to your application, run: + +``` +yarn add open-oracle-reporter +``` + +## Usage + +Once you've installed the DelFi SDK, you can sign a DelFi feed as follows: + +```typescript +import Reporter from 'open-oracle-reporter'; + +let typeSig = Reporter.annotateType('price', 'string', 'decimal'); +let encoded = Reporter.encode(typeSig, +new Date(), {'eth': 260.0, 'zrx': 0.58}); +let signature = Reporter.sign(encoded, '0x...'); + + +``` + +For example, in an express app: + +```typescript +// See above for signing data + +express.request('/prices.json', (response) => { + response.json({ + type_signature: typeSig, + data: encoded, + signature: signature + }); +}); +``` + +You may also use the easy express adapter: + +```typescript +import Reporter from 'open-oracle-reporter'; + +async funtion fetchPrices() { + return {'eth': 260.0, 'zrx': 0.58}; +} + +express.use(Reporter.express('prices.json', '0x...', fetchPrices)); +``` diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json index 7a1d3198..2bdc9c7a 100644 --- a/sdk/typescript/package.json +++ b/sdk/typescript/package.json @@ -1,7 +1,7 @@ { - "name": "delfi-reporter", + "name": "open-oracle-reporter", "version": "1.0.0", - "description": "The DelFi Reporter", + "description": "The Open Oracle Reporter", "main": "index.js", "repository": "https://github.com/compound-finance/delfi", "author": "Compound Labs, Inc.", diff --git a/sdk/typescript/src/delfi.ts b/sdk/typescript/src/reporter.ts similarity index 91% rename from sdk/typescript/src/delfi.ts rename to sdk/typescript/src/reporter.ts index 82dc1fbb..3d0fcb07 100644 --- a/sdk/typescript/src/delfi.ts +++ b/sdk/typescript/src/reporter.ts @@ -1,5 +1,6 @@ -import * as Web3 from 'web3'; -const web3 = new Web3(); +import Web3 from 'web3'; + +const web3 = new Web3(); // This is just encoding, etc. interface TypeSignature { name: string, @@ -9,8 +10,8 @@ interface TypeSignature { magic: string }; -const Delphi = { - annotateType: (name: string, keyType: string, valueType: string): TypeAnnotation { +export const Reporter = { + annotateType: (name: string, keyType: string, valueType: string): TypeSignature { let encoder = (x) => x; let actualValueType; diff --git a/sdk/typescript/test/express_test.ts b/sdk/typescript/test/express_test.ts new file mode 100644 index 00000000..ae6cad38 --- /dev/null +++ b/sdk/typescript/test/express_test.ts @@ -0,0 +1,7 @@ +import {Reporter} from '../src/reporter'; +import express from 'express'; + +// TODO: Add integration test for express adapter +describe('integration test', async () => { + +}); diff --git a/sdk/typescript/test/reporter_test.ts b/sdk/typescript/test/reporter_test.ts new file mode 100644 index 00000000..77b81fe7 --- /dev/null +++ b/sdk/typescript/test/reporter_test.ts @@ -0,0 +1,7 @@ +import {Reporter} from '../src/reporter'; + +describe('Reporter', async () => { + it('works', async () => { + expect(Reporter).toEqual(5); + }) +}); diff --git a/sdk/typescript/tsconfig.json b/sdk/typescript/tsconfig.json new file mode 100644 index 00000000..460edc1d --- /dev/null +++ b/sdk/typescript/tsconfig.json @@ -0,0 +1,63 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["esnext"], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./.tsbuilt", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "include": [ + "./src/**/*" + ] +} diff --git a/tests/OracleTest.js b/tests/OracleTest.js index 58be9ca9..f3c370fa 100644 --- a/tests/OracleTest.js +++ b/tests/OracleTest.js @@ -1,12 +1,12 @@ describe('Oracle', () => { - it.concurrent('is a valid oracle', async () => { + it('is a valid oracle', async () => { let oracle = await saddle.deploy('Oracle', [], {from: await saddle.account}); expect(await oracle.methods.name.call()).toEqual('5'); }); - it.concurrent('is still a valid oracle', async () => { + it('is still a valid oracle', async () => { let oracle = await saddle.deploy('Oracle', [], {from: await saddle.account}); expect(await oracle.methods.name.call()).toEqual('6'); diff --git a/tests/ViewTest.js b/tests/ViewTest.js new file mode 100644 index 00000000..a312f44b --- /dev/null +++ b/tests/ViewTest.js @@ -0,0 +1,14 @@ + +describe('View', () => { + it('is a valid oracle', async () => { + let oracle = await saddle.deploy('View', [], {from: await saddle.account}); + + expect(await oracle.methods.name.call()).toEqual('55'); + }); + + it('is still a valid oracle', async () => { + let oracle = await saddle.deploy('View', [], {from: await saddle.account}); + + expect(await oracle.methods.name.call()).toEqual('66'); + }); +}); diff --git a/tsrc/config.ts b/tsrc/config.ts index fadc8c3f..668bcb5a 100644 --- a/tsrc/config.ts +++ b/tsrc/config.ts @@ -1,5 +1,7 @@ import Web3 from 'web3'; import ganache from 'ganache-core'; +import * as fs from 'fs'; +import * as path from 'path'; export interface Config { network: string @@ -12,21 +14,7 @@ export async function loadConfig(network: string): Promise { } export async function loadWeb3(config: Config): Promise { - if (config.network === 'test') { - const options = { - transactionConfirmationBlocks: 1, - transactionBlockTimeout: 5 - } - - return new Web3(ganache.provider(), undefined, options); - } else { - const options = { - transactionConfirmationBlocks: 1, - transactionBlockTimeout: 5 - } - - return new Web3(Web3.givenProvider || 'http://127.0.0.1:8545', undefined, options); - } + return await import(path.join(process.cwd(), 'config', config.network)); } export async function loadAccount(config: Config, web3: Web3): Promise { diff --git a/tsrc/contract.ts b/tsrc/contract.ts index 7b269e45..b535bf87 100644 --- a/tsrc/contract.ts +++ b/tsrc/contract.ts @@ -4,6 +4,9 @@ import * as fs from 'fs'; import * as path from 'path'; import ganache from 'ganache-core'; +const BUILD_FILE_NAME = 'build.json'; +const CONTRACT_FILE_NAME = 'contracts.json'; + interface ContractBuild { abi: string bin: string @@ -23,12 +26,20 @@ async function readFile(file: string, def: T, fn: (data: string) => T): Promi }); } +export async function writeFile(file: string, data: string): Promise { + return new Promise((resolve, reject) => { + fs.writeFile(file, data, (err) => { + return err ? reject(err) : resolve(); + }); + }); +} + function getBuildFile(network: string, file: string): string { return path.join(process.cwd(), '.build', network, file); } async function getContract(network: string, name: string): Promise { - let contracts = await readFile(getBuildFile(network, 'contracts.json'), {}, JSON.parse); + let contracts = await readFile(getBuildFile(network, BUILD_FILE_NAME), {}, JSON.parse); let contractsObject = contracts["contracts"] || {}; let foundContract = Object.entries(contractsObject).find(([pathContractName, contract]) => { @@ -55,3 +66,10 @@ export async function deployContract(web3: Web3, network: string, from: string, const contract = new web3.eth.Contract(contractAbi); return await contract.deploy({data: '0x' + contractBuild.bin, arguments: args}).send({from: from, gas: 1000000}); } + +export async function saveContract(name: string, contract: Contract, network: string): Promise { + let file = getBuildFile(network, CONTRACT_FILE_NAME); + let curr = await readFile(file, {}, JSON.parse); + curr[name] = contract.address; + await writeFile(file, JSON.stringify(curr)); +} diff --git a/tsrc/deploy.ts b/tsrc/deploy.ts index 9f077532..5a21915c 100644 --- a/tsrc/deploy.ts +++ b/tsrc/deploy.ts @@ -1,10 +1,18 @@ import {loadConfig, loadWeb3, loadAccount} from './config'; -import {deployContract} from './contract'; +import {deployContract, saveContract} from './contract'; + +// TODO: Replace with real CLI parser +let network = process.env['network']; +let contractName = process.env['contract']; +if (network.trim() === "" || contractName.trim() === "") { + throw "usage: yarn run saddle:deploy ...args" +} (async function () { - let config = await loadConfig("development"); + let config = await loadConfig(network); let web3 = await loadWeb3(config); let account = await loadAccount(config, web3); - await deployContract(web3, "development", account, "Oracle", []) + let contract = await deployContract(web3, config.network, account, contractName, process.argv); + await saveContract(contractName, contract, config.network); })(); diff --git a/tsrc/test.ts b/tsrc/test.ts index e43ea86c..8e5b6479 100644 --- a/tsrc/test.ts +++ b/tsrc/test.ts @@ -3,6 +3,9 @@ import {loadConfig, loadWeb3, loadAccount} from './config'; import {deployContract} from './contract'; import {Contract} from 'web3-eth-contract'; +// let web3; // share web3 amoung tests +// let account; // share primary account + async function configure() { let config = await loadConfig("test"); let web3 = await loadWeb3(config); @@ -24,7 +27,7 @@ async function configure() { global['beforeEach'](() => { console.log("starting test"); }); -global['beforeEach'](configure); +global['before'](configure); global['afterEach'](() => { console.log("ending test"); }); \ No newline at end of file