├── .versions ├── README.md ├── blocks.js └── package.js /.versions: -------------------------------------------------------------------------------- 1 | allow-deny@1.1.0 2 | babel-compiler@7.0.5 3 | babel-runtime@1.2.2 4 | base64@1.0.10 5 | binary-heap@1.0.10 6 | boilerplate-generator@1.4.0 7 | callback-hook@1.1.0 8 | check@1.3.0 9 | ddp@1.4.0 10 | ddp-client@2.3.2 11 | ddp-common@1.4.0 12 | ddp-server@2.1.2 13 | diff-sequence@1.1.0 14 | dynamic-import@0.3.0 15 | ecmascript@0.10.5 16 | ecmascript-runtime@0.5.0 17 | ecmascript-runtime-client@0.6.2 18 | ecmascript-runtime-server@0.5.0 19 | ejson@1.1.0 20 | ethereum:blocks@1.0.0 21 | ethereum:web3@1.0.0-beta.33 22 | geojson-utils@1.0.10 23 | http@1.4.0 24 | id-map@1.1.0 25 | logging@1.1.19 26 | meteor@1.8.2 27 | minimongo@1.4.3 28 | modules@0.11.5 29 | modules-runtime@0.9.2 30 | mongo@1.4.2 31 | mongo-dev-server@1.1.0 32 | mongo-id@1.0.7 33 | npm-mongo@2.2.34 34 | ordered-dict@1.1.0 35 | promise@0.10.2 36 | random@1.1.0 37 | reload@1.2.0 38 | retry@1.1.0 39 | routepolicy@1.0.13 40 | socket-stream-client@0.1.0 41 | tracker@1.1.3 42 | underscore@1.0.10 43 | url@1.2.0 44 | webapp@1.5.0 45 | webapp-hashing@1.0.9 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ethereum blocks 2 | 3 | Provides you with an `EthBlocks` collection, which stores the last 50 blocks. 4 | 5 | You can query blocks like any other Meteor collection. 6 | 7 | ## Installation 8 | 9 | $ meteor add ethereum:blocks 10 | 11 | ## Usage 12 | 13 | Initialize Blocks on the start of your application, as soon as you have a ethereum connection: 14 | 15 | ```js 16 | EthBlocks.init(); 17 | ``` 18 | 19 | ### Last block 20 | 21 | To get the latest block use: 22 | 23 | ```js 24 | EthBlocks.latest; 25 | ``` 26 | 27 | Note this property is reactive, so it will re-run your reactive functions, e.g. when used in template helpers. 28 | 29 | In case you want to update the latest block you can change properties as follows: 30 | 31 | ```js 32 | EthBlocks.latest = { hash: "12345" }; 33 | ``` 34 | 35 | This would only change the hash property of the latest block, but leave all other properties as is. 36 | 37 | ### Current gas price 38 | 39 | Additionally all blocks get the current gasprice add: 40 | 41 | ```js 42 | EthBlocks.latest.gasPrice; // '1136672632018' (wei) 43 | ``` 44 | 45 | ### Detecting forks 46 | 47 | You can call `Blocks.detectFork(callback)` to detect chain re-organisation (forks), while your applications is running. 48 | This detection, is checking the new incoming blocks `parentHash`, with the last known block you have. 49 | 50 | **Note** The fork detection can currently be wrong, when you're importing blocks, as they can come in different orders. 51 | 52 | ```js 53 | EthBlocks.detectFork(function(oldBlock, newBlock) { 54 | // this callback will be fired with the old block we knew and the new block. 55 | }); 56 | ``` 57 | 58 | Note you can call `EthBlocks.detectFork(cb)` mutliple times, to add multiple callbacks. 59 | 60 | ### Clear all stored blocks 61 | 62 | If you switch to a chain, which has a lower block number EthBlocks will reset your interally cache of the last 50 blocks. 63 | If you want to do that manually call: 64 | 65 | ```js 66 | EthBlocks.clear(); 67 | ``` 68 | -------------------------------------------------------------------------------- /blocks.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @module Ethereum:blocks 4 | */ 5 | 6 | /** 7 | The EthBlocks collection, with some ethereum additions. 8 | 9 | @class EthBlocks 10 | @constructor 11 | */ 12 | 13 | EthBlocks = new Mongo.Collection("ethereum_blocks", { connection: null }); 14 | 15 | // if(typeof PersistentMinimongo !== 'undefined') 16 | // new PersistentMinimongo(EthBlocks); 17 | 18 | /** 19 | Gives you reactively the lates block. 20 | 21 | @property latest 22 | */ 23 | Object.defineProperty(EthBlocks, "latest", { 24 | get: function() { 25 | return EthBlocks.findOne({}, { sort: { number: -1 } }) || {}; 26 | }, 27 | set: function(values) { 28 | var block = EthBlocks.findOne({}, { sort: { number: -1 } }) || {}; 29 | values = values || {}; 30 | EthBlocks.update(block._id, { $set: values }); 31 | } 32 | }); 33 | 34 | /** 35 | Stores all the callbacks 36 | 37 | @property _forkCallbacks 38 | */ 39 | EthBlocks._forkCallbacks = []; 40 | 41 | /** 42 | Start looking for new blocks 43 | 44 | @method init 45 | */ 46 | EthBlocks.init = function() { 47 | if (typeof web3 === "undefined") { 48 | console.warn( 49 | "EthBlocks couldn't find web3, please make sure to instantiate a web3 object before calling EthBlocks.init()" 50 | ); 51 | return; 52 | } 53 | 54 | // clear current block list 55 | EthBlocks.clear(); 56 | 57 | Tracker.nonreactive(function() { 58 | observeLatestBlocks(); 59 | }); 60 | }; 61 | 62 | /** 63 | Add callbacks to detect forks 64 | 65 | @method detectFork 66 | */ 67 | EthBlocks.detectFork = function(cb) { 68 | EthBlocks._forkCallbacks.push(cb); 69 | }; 70 | 71 | /** 72 | Clear all blocks 73 | 74 | @method clear 75 | */ 76 | EthBlocks.clear = function() { 77 | _.each(EthBlocks.find({}).fetch(), function(block) { 78 | EthBlocks.remove(block._id); 79 | }); 80 | }; 81 | 82 | /** 83 | The global block subscription instance. 84 | 85 | @property subscription 86 | */ 87 | var subscription = null; 88 | 89 | /** 90 | Update the block info and adds additional properties. 91 | 92 | @method updateBlock 93 | @param {Object} block 94 | */ 95 | function updateBlock(block) { 96 | // reset the chain, if the current blocknumber is 100 blocks less 97 | if (block.number + 10 < EthBlocks.latest.number) EthBlocks.clear(); 98 | 99 | block.difficulty = block.difficulty.toString(10); 100 | block.totalDifficulty = block.totalDifficulty.toString(10); 101 | 102 | web3.eth.getGasPrice(function(e, gasPrice) { 103 | if (!e) { 104 | block.gasPrice = gasPrice.toString(10); 105 | EthBlocks.upsert( 106 | "bl_" + block.hash.replace("0x", "").substr(0, 20), 107 | block 108 | ); 109 | } 110 | }); 111 | } 112 | 113 | /** 114 | Observe the latest blocks and store them in the Blocks collection. 115 | Additionally cap the collection to 50 blocks 116 | 117 | @method observeLatestBlocks 118 | */ 119 | function observeLatestBlocks() { 120 | // get the latest block immediately 121 | web3.eth.getBlock("latest", function(e, block) { 122 | if (!e) { 123 | updateBlock(block); 124 | } 125 | }); 126 | 127 | // GET the latest blockchain information 128 | subscription = web3.eth.subscribe("newBlockHeaders", function(error, result) { 129 | checkLatestBlocks(error, result ? result.hash : null); 130 | }); 131 | } 132 | 133 | /** 134 | The observeLatestBlocks callback used in the block subscription. 135 | 136 | @method checkLatestBlocks 137 | */ 138 | var checkLatestBlocks = function(e, hash) { 139 | if (!e) { 140 | web3.eth.getBlock(hash, function(e, block) { 141 | if (!e) { 142 | var oldBlock = EthBlocks.latest; 143 | 144 | // console.log('BLOCK', block.number); 145 | 146 | // if(!oldBlock) 147 | // console.log('No previous block found: '+ --block.number); 148 | 149 | // CHECK for FORK 150 | if (oldBlock && oldBlock.hash !== block.parentHash) { 151 | // console.log('FORK detected from Block #'+ oldBlock.number + ' -> #'+ block.number +'!'); 152 | 153 | _.each(EthBlocks._forkCallbacks, function(cb) { 154 | if (_.isFunction(cb)) cb(oldBlock, block); 155 | }); 156 | } 157 | 158 | updateBlock(block); 159 | 160 | // drop the 50th block 161 | var blocks = EthBlocks.find({}, { sort: { number: -1 } }).fetch(); 162 | if (blocks.length >= 5) { 163 | var count = 0; 164 | _.each(blocks, function(bl) { 165 | count++; 166 | if (count >= 5) EthBlocks.remove({ _id: bl._id }); 167 | }); 168 | } 169 | } 170 | }); 171 | } 172 | }; 173 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: "ethereum:blocks", 3 | summary: "Provides informations about the current and last 50 blocks", 4 | version: "1.1.0", 5 | git: "http://github.com/ethereum/meteor-package-blocks" 6 | }); 7 | 8 | Package.onUse(function(api) { 9 | api.versionsFrom("1.0"); 10 | api.use("underscore", ["client", "server"]); 11 | api.use("mongo", ["client", "server"]); 12 | 13 | // api.use('frozeman:persistent-minimongo@0.1.3', 'client'); 14 | api.use("ethereum:web3@1.0.0-beta.33", ["client", "server"]); 15 | 16 | api.export(["EthBlocks"], ["client", "server"]); 17 | 18 | api.addFiles("blocks.js", ["client", "server"]); 19 | }); 20 | 21 | // Package.onTest(function(api) { 22 | // api.use('tinytest'); 23 | // api.use('ethereum:blocks'); 24 | // api.addFiles('blocks-tests.js'); 25 | // }); 26 | --------------------------------------------------------------------------------