Skip to content

Commit

Permalink
Coburn/integrate poster (#10)
Browse files Browse the repository at this point in the history
*  a little ugly stuff trying too hard to test this

* fix fixtures for posting with retries

* import web3 types, dig in ethereumjs for more robus type signature parsing

* catch to use a fallback gas price
  • Loading branch information
coburncoburn authored Jun 24, 2019
1 parent 271adab commit 632768b
Show file tree
Hide file tree
Showing 21 changed files with 338 additions and 132 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/poster/fixtures/generated/* binary
10 changes: 7 additions & 3 deletions poster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ yarn add open-oracle-poster
To run as a standalone:

```
open-oracle-poster --poster-key=0x...
TODO: make this more clear, as these are just notes from starting to integrate
# start reporter
yarn run start --private_key=0x5763aa1cb4c9cd141a1b409d92e5c5b967a28e18c70eb4cd965374ad75bff356 --script="examples/fixed.js"
yarn run start --view_address=0xa543d9701bb291E8F75CE2747A8E094bF042009A --poster_key=0x5763aa1cb4c9cd141a1b409d92e5c5b967a28e18c70eb4cd965374ad75bff356 --sources=http://localhost:3000 --view_function_name='postPrices(bytes[],bytes[],string[])' --web3_provider=http://localhost:8545
```

Otherwise, you can include the DelFi poster in an app for configuration:

```typescript
import poster from 'delfi-poster';

poster.configure(...);
poster.run();
// sources = [list of reporter urls]
poster.main();
```
1 change: 1 addition & 0 deletions poster/fixtures/generated/2ce40754482b0a537231820f6654abe7
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"id":4,"jsonrpc":"2.0","result":{"number":"0x1","hash":"0x4dd036433dde8a2e04bf49f50f7543de20e8a66566bad42359fae6ec2a816ea3","parentHash":"0x37349fdc743a38f6df50dd9007448d90a33bf3482de842966dbb062c14908038","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x8199b911ba18a09653cf8814eb171fbf100674c382d7470b5de61feaa649d622","stateRoot":"0xdf07db4b5355fa2ed211e86e551dbef36ed9c38b590a4b77eff80870e7cba300","receiptsRoot":"0x113215a2409e6e5ea52204d23f975b8eabf1e358d257783576618ffbec9b98a9","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x3e8","gasLimit":"0x6691b7","gasUsed":"0x7358","timestamp":"0x5d0ed39c","transactions":["0xc693cb5a9f8bea2fac46d003c5ebe63102704c66658b532e76a3f9a2f1272f8b"],"uncles":[]}}
21 changes: 21 additions & 0 deletions poster/fixtures/generated/2ce40754482b0a537231820f6654abe7.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"statusCode": 200,
"headers": {
"content-type": "application/json",
"date": "Sun, 23 Jun 2019 01:19:25 GMT",
"connection": "keep-alive",
"transfer-encoding": "chunked"
},
"url": "http://localhost:8545/",
"time": 6,
"request": {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive",
"Host": "localhost:8545",
"User-Agent": "Mozilla/5.0 (Darwin x64) node.js/12.4.0 v8/7.4.288.27-node.18",
"Content-Length": "79"
}
}
}
5 changes: 5 additions & 0 deletions poster/fixtures/generated/9333decc3dccc9ae33e242437f381fc2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": 83,
"jsonrpc": "2.0",
"result": "0x3d"
}
21 changes: 21 additions & 0 deletions poster/fixtures/generated/9333decc3dccc9ae33e242437f381fc2.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"statusCode": 200,
"headers": {
"content-type": "application/json",
"date": "Sun, 23 Jun 2019 01:12:50 GMT",
"connection": "keep-alive",
"transfer-encoding": "chunked"
},
"url": "http://localhost:8545/",
"time": 20,
"request": {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive",
"Host": "localhost:8545",
"User-Agent": "Mozilla/5.0 (Darwin x64) node.js/12.4.0 v8/7.4.288.27-node.18",
"Content-Length": "59"
}
}
}
1 change: 1 addition & 0 deletions poster/fixtures/generated/a679986b5a9be0e6c78da47f6cf9d678
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"id":2,"jsonrpc":"2.0","result":"0xc693cb5a9f8bea2fac46d003c5ebe63102704c66658b532e76a3f9a2f1272f8b"}
21 changes: 21 additions & 0 deletions poster/fixtures/generated/a679986b5a9be0e6c78da47f6cf9d678.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"statusCode": 200,
"headers": {
"content-type": "application/json",
"date": "Sun, 23 Jun 2019 01:19:24 GMT",
"connection": "keep-alive",
"transfer-encoding": "chunked"
},
"url": "http://localhost:8545/",
"time": 30,
"request": {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive",
"Host": "localhost:8545",
"User-Agent": "Mozilla/5.0 (Darwin x64) node.js/12.4.0 v8/7.4.288.27-node.18",
"Content-Length": "1060"
}
}
}
1 change: 1 addition & 0 deletions poster/fixtures/generated/a6b51e6cf1af8db558e61ce3b53c17e8
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"id":1,"jsonrpc":"2.0","result":"0x0"}
21 changes: 21 additions & 0 deletions poster/fixtures/generated/a6b51e6cf1af8db558e61ce3b53c17e8.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"statusCode": 200,
"headers": {
"content-type": "application/json",
"date": "Sun, 23 Jun 2019 01:19:24 GMT",
"connection": "keep-alive",
"transfer-encoding": "chunked"
},
"url": "http://localhost:8545/",
"time": 16,
"request": {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive",
"Host": "localhost:8545",
"User-Agent": "Mozilla/5.0 (Darwin x64) node.js/12.4.0 v8/7.4.288.27-node.18",
"Content-Length": "124"
}
}
}
1 change: 1 addition & 0 deletions poster/fixtures/generated/beccb3def7ec8ebb7a7ba3249a4a745a
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"id":3,"jsonrpc":"2.0","result":{"transactionHash":"0xc693cb5a9f8bea2fac46d003c5ebe63102704c66658b532e76a3f9a2f1272f8b","transactionIndex":"0x0","blockHash":"0x4dd036433dde8a2e04bf49f50f7543de20e8a66566bad42359fae6ec2a816ea3","blockNumber":"0x1","from":"0x864f667f63b8650e10a0e52910f01198dab19d69","to":"0x4fe3dd76d873caf6cbf56e442b2c808d3984df1d","gasUsed":"0x7358","cumulativeGasUsed":"0x7358","contractAddress":null,"logs":[],"status":"0x1","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","v":"0x9e","r":"0x13315249d203595fae8d58dfbad79460c5a24f395e7317b72409f0cb770caee6","s":"0x470d1bb57af3ecbd20ac13fc22dca5f023f7cc5533a17dffd03959c8f585b545"}}
21 changes: 21 additions & 0 deletions poster/fixtures/generated/beccb3def7ec8ebb7a7ba3249a4a745a.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"statusCode": 200,
"headers": {
"content-type": "application/json",
"date": "Sun, 23 Jun 2019 01:19:25 GMT",
"connection": "keep-alive",
"transfer-encoding": "chunked"
},
"url": "http://localhost:8545/",
"time": 13,
"request": {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive",
"Host": "localhost:8545",
"User-Agent": "Mozilla/5.0 (Darwin x64) node.js/12.4.0 v8/7.4.288.27-node.18",
"Content-Length": "141"
}
}
}
1 change: 1 addition & 0 deletions poster/fixtures/generated/cfc0b88c86c6856dd629d1863ba943ea
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"id":1,"jsonrpc":"2.0","result":"0x0"}
21 changes: 21 additions & 0 deletions poster/fixtures/generated/cfc0b88c86c6856dd629d1863ba943ea.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"statusCode": 200,
"headers": {
"content-type": "application/json",
"date": "Sun, 23 Jun 2019 01:17:48 GMT",
"connection": "keep-alive",
"transfer-encoding": "chunked"
},
"url": "http://localhost:8545/",
"time": 12,
"request": {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Connection": "keep-alive",
"Host": "localhost:8545",
"User-Agent": "Mozilla/5.0 (Darwin x64) node.js/12.4.0 v8/7.4.288.27-node.18",
"Content-Length": "124"
}
}
}
4 changes: 2 additions & 2 deletions poster/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"author": "Compound Labs, Inc.",
"license": "MIT",
"scripts": {
"start": "node ./.tsbuilt/poster.js",
"test": "VCR_MODE=playback node ./node_modules/jest-cli/bin/jest.js"
"start": "node ./.tsbuilt/index.js",
"test": "VCR_MODE=cache node ./node_modules/jest-cli/bin/jest.js"
},
"devDependencies": {
"@types/jest": "^24.0.13",
Expand Down
116 changes: 39 additions & 77 deletions poster/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,43 @@
import {postWithRetries} from './postWithRetries';
import fetch from 'node-fetch';
import AbiCoder from 'web3-eth-abi';

async function main () {
const viewAddress = getEnvVar("view-address");
const senderKey = getEnvVar("poster-key");
const sources = getEnvVar("sources").split(",");
const functionName = getEnvVar("view-function-name");
const web3Provider = getEnvVar("web3-provider");

const payloads = await fetchPayloads(sources);
const gasPrice = await fetchGasPrice();
const trxData = buildTrxData(payloads, functionName);

const trx = <Trx> {
data: trxData,
to: viewAddress,
gasPrice: gasPrice,
gas: 1_000_000
import {main} from './poster';
import Web3 from 'web3';
import yargs from 'yargs';

async function run() {
const argv = yargs
.option('sources', {alias: 's', description: 'sources to pull price messages from', type: 'string'})
.option('poster_key', {alias: 'k', description: 'Private key (try: `file:<file> or env:<env>`', type: 'string'})
.option('view_function_name', {alias: 'f', description: 'Function signature for the view', type: 'string'})
.option('web3_provider', {description: 'Web 3 provider', type: 'string'})
.option('view_address', {description: 'address of view', type: 'string'})
.option('timeout', {alias: 't', description: 'how many secondsto wait before retrying', type: 'number', default: 180})
.help()
.alias('help', 'h')
.demandOption(['poster_key', 'sources', 'view_function_name', 'web3_provider', 'view_address'], 'Provide all the arguments')
.argv;

const web3 = await new Web3(argv.web3_provider, undefined, {});

// posting promise will reject and retry once with higher gas after this timeout
web3.eth.transactionPollingTimeout = argv.timeout;

if (argv.web3_provider === "http://127.0.0.1:8545") {
// confirm immediately in dev
web3.eth.transactionConfirmationBlocks = 1

// monkey patch web3 since ganache does not implement eth_chainId
// https://github.com/trufflesuite/ganache-core/issues/339
// https://github.com/tcichowicz/ganache-core/commit/15d740cc5bdca86c87c3c9fd79bbce5f785b105e
const originalSend = web3.eth.currentProvider.send;
web3.eth.currentProvider.send = async function (method, parameters) {
if (method === "eth_chainId") {
return "0x" + Number(1337).toString(16)
} else {
return originalSend.call(web3.eth.currentProvider, method, parameters);
}
}
}

return postWithRetries(trx, senderKey, web3Provider);
}

async function fetchPayloads(sources : string[]) : Promise<OpenOraclePayload[]> {
let sourcePromises = sources.map(async (source) => {
let response = await fetch(source);
return response.json();
});

return await Promise.all(sourcePromises)
}

async function fetchGasPrice() : Promise<number> {
let source = "https://api.compound.finance/api/gas_prices/get_gas_price";
let response = await fetch(source);
let prices = await response.json();
let averagePrice = Number(prices["average"]["value"]);
return averagePrice;
return await main(argv.sources, argv.poster_key, argv.view_address, argv.view_function_name, web3);
}

function buildTrxData(payloads : OpenOraclePayload[], functionName : string) : string {
const types = findTypes(functionName);

let messages = payloads.map(x => x.message);
let signatures = payloads.map(x => x.signature);
let symbols = new Set(payloads.map(x => Object.keys(x.prices)))

// see https://github.com/ethereum/web3.js/blob/2.x/packages/web3-eth-abi/src/AbiCoder.js#L112
return AbiCoder.encodeFunctionSignature(functionName) +
AbiCoder
.encodeParameters(types, [messages, signatures, ...symbols])
.replace('0x', '');
}

// e.g. findTypes("postPrices(bytes[],bytes[],string[])")-> ["bytes[]","bytes[]","string[]"]
function findTypes(functionName : string) : string[] {
let start = functionName.indexOf("(") + 1;
let types = functionName
.slice(start, functionName.lastIndexOf(")"))
.split(",");
return types
}

function getEnvVar(name : string): string {
const result: string | undefined = process.env[name];

if (result) {
return result;
} else {
throw `Missing required env var: ${name}`;
}
}

export {
buildTrxData,
findTypes,
fetchGasPrice,
fetchPayloads
}
run()
9 changes: 6 additions & 3 deletions poster/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
// A payload for an open oracle view comprises 2 fields:
// 1. Abi encoded values to be written to the open oracle data contract
// 2. The attestor's signature on a hash of that message
interface OpenOraclePayload {
interface DelFiReporterPayload {
// ABI encoded values to be written to the open oracle data contract.
message: string,
encoded: string,
// The signature of the attestor to these values. The values in 'message'
// will be stored in a mapping under this signer's public address.
signature: string,
Expand All @@ -28,7 +28,6 @@ interface Trx {
gasPrice: number,
gas: number,
to: string,
chainId: string,
data: string
}

Expand All @@ -41,3 +40,7 @@ interface TrxReceipt {
[event: string]: Event
}
}

interface Event {
returnValues: { [key: string]: any }
}
Loading

0 comments on commit 632768b

Please sign in to comment.