├── .coveralls.yml ├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── bower.json ├── docs └── index.md ├── gulpfile.js ├── index.js ├── lib ├── index.js ├── insight.js └── models │ ├── addressinfo.js │ └── index.js ├── package.json └── test ├── index.html ├── insight.js ├── mocha.opts └── models ├── addressinfo.js └── sampleAddressFromInsight.json /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: hweI3rqbeyC86f0Tku7G1jQyQQyn0ML2b -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[a-z] 2 | coverage 3 | node_modules 4 | bitcore-explorers.js 5 | bitcore-explorers.min.js 6 | 7 | lib/errors/index.js 8 | npm-debug.log 9 | 10 | bower_components 11 | report 12 | .DS_Store 13 | tests.js 14 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.). 3 | "browser": true, // Standard browser globals e.g. `window`, `document`. 4 | "camelcase": false, // Permit only camelcase for `var` and `object indexes`. 5 | "curly": true, // Require {} for every new block or scope. 6 | "devel": false, // Allow development statements e.g. `console.log();`. 7 | "eqeqeq": true, // Require triple equals i.e. `===`. 8 | "esnext": true, // Allow ES.next specific features such as `const` and `let`. 9 | "freeze": true, // Forbid overwriting prototypes of native objects such as Array, Date and so on. 10 | "immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` 11 | "indent": 2, // Specify indentation spacing 12 | "latedef": true, // Prohibit variable use before definition. 13 | "newcap": false, // Require capitalization of all constructor functions e.g. `new F()`. 14 | "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. 15 | "node": true, // Enable globals available when code is running inside of the NodeJS runtime environment. 16 | "noempty": true, // Prohibit use of empty blocks. 17 | "nonew": true, // Prohibits the use of constructor functions for side-effects 18 | "quotmark": "single", // Define quotes to string values. 19 | "regexp": true, // Prohibit `.` and `[^...]` in regular expressions. 20 | "smarttabs": false, // Supress warnings about mixed tabs and spaces 21 | "strict": true, // Require `use strict` pragma in every file. 22 | "trailing": true, // Prohibit trailing whitespaces. 23 | "undef": true, // Require all non-global variables be declared before they are used. 24 | "unused": true, // Warn unused variables. 25 | 26 | "maxparams": 4, // Maximum number of parameters for a function 27 | "maxstatements": 15, // Maximum number of statements in a function 28 | "maxcomplexity": 6, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity) 29 | "maxdepth": 4, // Maximum depth of nested control structures 30 | "maxlen": 120, // Maximum number of cols in a line 31 | "multistr": true, // Allow use of multiline EOL escaping 32 | 33 | "predef": [ // Extra globals. 34 | "after", 35 | "afterEach", 36 | "before", 37 | "beforeEach", 38 | "define", 39 | "describe", 40 | "exports", 41 | "it", 42 | "module", 43 | "require" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_install: 5 | - export DISPLAY=:99.0 6 | - sh -e /etc/init.d/xvfb start 7 | install: 8 | - npm install 9 | after_script: 10 | - gulp coveralls 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 BitPay 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bitcore explorers 2 | # Blockchain APIs for bitcore 3 | 4 | [![NPM Package](https://img.shields.io/npm/v/bitcore-explorers.svg?style=flat-square)](https://www.npmjs.org/package/bitcore-explorers) 5 | [![Build Status](https://img.shields.io/travis/bitpay/bitcore-explorers.svg?branch=master&style=flat-square)](https://travis-ci.org/bitpay/bitcore-explorers) 6 | [![Coverage Status](https://img.shields.io/coveralls/bitpay/bitcore-explorers.svg?style=flat-square)](https://coveralls.io/r/bitpay/bitcore-explorers) 7 | 8 | A module for [bitcore](https://github.com/bitpay/bitcore) that implements HTTP requests to different Web APIs to query the state of the blockchain. 9 | 10 | ## Getting started 11 | 12 | Be careful! When using this module, the information retrieved from remote servers may be compromised and not reflect the actual state of the blockchain. 13 | 14 | ```sh 15 | npm install bitcore-explorers 16 | bower install bitcore-explorers 17 | ``` 18 | 19 | At the moment, only Insight is supported, and only getting the UTXOs for an address and broadcasting a transaction. 20 | 21 | ```javascript 22 | var explorers = require('bitcore-explorers'); 23 | var insight = new explorers.Insight(); 24 | 25 | insight.getUtxos('1Bitcoin...', function(err, utxos) { 26 | if (err) { 27 | // Handle errors... 28 | } else { 29 | // Maybe use the UTXOs to create a transaction 30 | } 31 | }); 32 | ``` 33 | 34 | ## Contributing 35 | 36 | See [CONTRIBUTING.md](https://github.com/bitpay/bitcore/blob/master/CONTRIBUTING.md) on the main bitcore repo for information about how to contribute. 37 | 38 | ## License 39 | 40 | Code released under [the MIT license](https://github.com/bitpay/bitcore/blob/master/LICENSE). 41 | 42 | Copyright 2013-2015 BitPay, Inc. Bitcore is a trademark maintained by BitPay, Inc. 43 | 44 | [bitcore]: http://github.com/bitpay/bitcore-explorers 45 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitcore-explorers", 3 | "main": "/bitcore-explorers.min.js", 4 | "version": "1.0.1", 5 | "homepage": "https://github.com/bitpay/bitcore-explorers", 6 | "authors": [ 7 | "BitPay" 8 | ], 9 | "description": "Module to query blockchain apis for Bitcore.", 10 | "moduleType": [ 11 | "globals" 12 | ], 13 | "keywords": [ 14 | "bitcoin", 15 | "bitcore", 16 | "btc", 17 | "satoshi", 18 | "insight" 19 | ], 20 | "license": "MIT", 21 | "ignore": [ 22 | "**/.*", 23 | "index.js", 24 | "gulpfile.js", 25 | "README.md", 26 | "node_modules", 27 | "bower_components", 28 | "test" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Explorers 2 | The `bitcore-explorers` module provides a convenient interface to retrieve unspent transaction outputs and broadcast transactions to the Bitcoin network via blockchain explorers. 3 | 4 | ## Installation 5 | Explorers is implemented as a separate module. 6 | 7 | For node projects: 8 | 9 | ``` 10 | npm install bitcore-explorers --save 11 | ``` 12 | 13 | For client-side projects: 14 | 15 | ``` 16 | bower install bitcore-explorers --save 17 | ``` 18 | 19 | ## Insight 20 | ### Description 21 | `Insight` is a simple agent to perform queries to an Insight blockchain explorer. The default servers are `https://insight.bitpay.com` and `https://test-insight.bitpay.com`, hosted by BitPay Inc. You can (and we strongly suggest you do) run your own insight server. For more information, head to [https://github.com/bitpay/insight-api](https://github.com/bitpay/insight-api) 22 | 23 | There are currently two methods implemented: `getUnspentUtxos` and `broadcast`. The API will grow as features are requested. 24 | 25 | #### Retrieving Unspent UTXOs for an Address (or set of) 26 | 27 | ```javascript 28 | var Insight = require('bitcore-explorers').Insight; 29 | var insight = new Insight(); 30 | 31 | insight.getUnspentUtxos('1Bitcoin...', function(err, utxos) { 32 | if (err) { 33 | // Handle errors... 34 | } else { 35 | // Maybe use the UTXOs to create a transaction 36 | } 37 | }); 38 | ``` 39 | 40 | #### Broadcasting a Transaction 41 | 42 | ```javascript 43 | var insight = new Insight(); 44 | insight.broadcast(tx, function(err, returnedTxId) { 45 | if (err) { 46 | // Handle errors... 47 | } else { 48 | // Mark the transaction as broadcasted 49 | } 50 | }); 51 | ``` 52 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var build = require('bitcore-build'); 4 | 5 | build('explorers'); 6 | 7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib'); 2 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | models: require('./models'), 3 | Insight: require('./insight'), 4 | bitcore: require('bitcore-lib'), 5 | }; 6 | -------------------------------------------------------------------------------- /lib/insight.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var request = require('request'); 4 | 5 | var bitcore = require('bitcore-lib'); 6 | var _ = bitcore.deps._; 7 | 8 | var $ = bitcore.util.preconditions; 9 | var Address = bitcore.Address; 10 | var JSUtil = bitcore.util.js; 11 | var Networks = bitcore.Networks; 12 | var Transaction = bitcore.Transaction; 13 | var UnspentOutput = Transaction.UnspentOutput; 14 | var AddressInfo = require('./models/addressinfo'); 15 | 16 | 17 | /** 18 | * Allows the retrieval of information regarding the state of the blockchain 19 | * (and broadcasting of transactions) from/to a trusted Insight server. 20 | * @param {string=} url the url of the Insight server 21 | * @param {Network=} network whether to use livenet or testnet 22 | * @constructor 23 | */ 24 | function Insight(url, network) { 25 | if (!url && !network) { 26 | return new Insight(Networks.defaultNetwork); 27 | } 28 | if (Networks.get(url)) { 29 | network = Networks.get(url); 30 | if (network === Networks.livenet) { 31 | url = 'https://insight.bitpay.com'; 32 | } else { 33 | url = 'https://test-insight.bitpay.com'; 34 | } 35 | } 36 | JSUtil.defineImmutable(this, { 37 | url: url, 38 | network: Networks.get(network) || Networks.defaultNetwork 39 | }); 40 | this.request = request; 41 | return this; 42 | } 43 | 44 | /** 45 | * @callback Insight.GetTransactionCallback 46 | * @param {Error} err 47 | * @param {Object} transaction 48 | */ 49 | 50 | /** 51 | * Get transaction by txid 52 | * @param {string} txid 53 | * @param {GetTransactionCallback} callback 54 | */ 55 | Insight.prototype.getTransaction = function(txid, callback) { 56 | $.checkArgument(_.isFunction(callback)); 57 | $.checkArgument(_.isString(txid)); 58 | $.checkArgument(txid.length === 64); 59 | 60 | this.requestGet('/api/tx/' + txid, function(err, res, body) { 61 | if (err || res.statusCode !== 200) { 62 | return callback(err || res); 63 | } 64 | var tx = JSON.parse(body); 65 | 66 | return callback(null, tx); 67 | }); 68 | }; 69 | 70 | /** 71 | * @callback Insight.GetUtxosCallback 72 | * @param {Error} err 73 | * @param {Array.UnspentOutput} utxos 74 | */ 75 | 76 | /** 77 | * Retrieve a list of unspent outputs associated with an address or set of addresses 78 | * @param {Address|string|Array.Address|Array.string} addresses 79 | * @param {GetUtxosCallback} callback 80 | */ 81 | Insight.prototype.getUtxos = function(addresses, callback) { 82 | $.checkArgument(_.isFunction(callback)); 83 | if (!_.isArray(addresses)) { 84 | addresses = [addresses]; 85 | } 86 | addresses = _.map(addresses, function(address) { 87 | return new Address(address); 88 | }); 89 | 90 | this.requestPost('/api/addrs/utxo', { 91 | addrs: _.map(addresses, function(address) { 92 | return address.toString(); 93 | }).join(',') 94 | }, function(err, res, unspent) { 95 | if (err || res.statusCode !== 200) { 96 | return callback(err || res); 97 | } 98 | try { 99 | unspent = _.map(unspent, UnspentOutput); 100 | } catch (ex) { 101 | if (ex instanceof bitcore.errors.InvalidArgument) { 102 | return callback(ex); 103 | } 104 | } 105 | 106 | return callback(null, unspent); 107 | }); 108 | }; 109 | 110 | /** 111 | * @callback Insight.BroadcastCallback 112 | * @param {Error} err 113 | * @param {string} txid 114 | */ 115 | 116 | /** 117 | * Broadcast a transaction to the bitcoin network 118 | * @param {transaction|string} transaction 119 | * @param {BroadcastCallback} callback 120 | */ 121 | Insight.prototype.broadcast = function(transaction, callback) { 122 | $.checkArgument(JSUtil.isHexa(transaction) || transaction instanceof Transaction); 123 | $.checkArgument(_.isFunction(callback)); 124 | if (transaction instanceof Transaction) { 125 | transaction = transaction.serialize(); 126 | } 127 | 128 | this.requestPost('/api/tx/send', { 129 | rawtx: transaction 130 | }, function(err, res, body) { 131 | if (err || res.statusCode !== 200) { 132 | return callback(err || body); 133 | } 134 | return callback(null, body ? body.txid : null); 135 | }); 136 | }; 137 | 138 | /** 139 | * @callback Insight.AddressCallback 140 | * @param {Error} err 141 | * @param {AddressInfo} info 142 | */ 143 | 144 | /** 145 | * Retrieve information about an address 146 | * @param {Address|string} address 147 | * @param {AddressCallback} callback 148 | */ 149 | Insight.prototype.address = function(address, callback) { 150 | $.checkArgument(_.isFunction(callback)); 151 | address = new Address(address); 152 | 153 | this.requestGet('/api/addr/' + address.toString(), function(err, res, body) { 154 | if (err || res.statusCode !== 200) { 155 | return callback(err || body); 156 | } 157 | var info; 158 | try { 159 | info = AddressInfo.fromInsight(body); 160 | } catch (e) { 161 | if (e instanceof SyntaxError) { 162 | return callback(e); 163 | } 164 | throw e; 165 | } 166 | return callback(null, info); 167 | }); 168 | }; 169 | 170 | /** 171 | * Internal function to make a post request to the server 172 | * @param {string} path 173 | * @param {?} data 174 | * @param {function} callback 175 | * @private 176 | */ 177 | Insight.prototype.requestPost = function(path, data, callback) { 178 | $.checkArgument(_.isString(path)); 179 | $.checkArgument(_.isFunction(callback)); 180 | this.request({ 181 | method: 'POST', 182 | url: this.url + path, 183 | json: data 184 | }, callback); 185 | }; 186 | 187 | /** 188 | * Internal function to make a get request with no params to the server 189 | * @param {string} path 190 | * @param {function} callback 191 | * @private 192 | */ 193 | Insight.prototype.requestGet = function(path, callback) { 194 | $.checkArgument(_.isString(path)); 195 | $.checkArgument(_.isFunction(callback)); 196 | this.request({ 197 | method: 'GET', 198 | url: this.url + path 199 | }, callback); 200 | }; 201 | 202 | module.exports = Insight; 203 | -------------------------------------------------------------------------------- /lib/models/addressinfo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var bitcore = require('bitcore-lib'); 4 | 5 | var _ = bitcore.deps._; 6 | var $ = bitcore.util.preconditions; 7 | var Address = bitcore.Address; 8 | var JSUtil = bitcore.util.js; 9 | 10 | function AddressInfo(param) { 11 | if (!(this instanceof AddressInfo)) { 12 | return new AddressInfo(param); 13 | } 14 | if (param instanceof AddressInfo) { 15 | return param; 16 | } 17 | 18 | $.checkArgument(param.address instanceof Address); 19 | $.checkArgument(_.isNumber(param.balance)); 20 | $.checkArgument(_.isNumber(param.totalSent)); 21 | $.checkArgument(_.isNumber(param.totalReceived)); 22 | $.checkArgument(_.isNumber(param.unconfirmedBalance)); 23 | $.checkArgument(_.isArray(param.transactionIds)); 24 | $.checkArgument(_.all(_.map(param.transactionIds, JSUtil.isHexa))); 25 | 26 | JSUtil.defineImmutable(this, param); 27 | } 28 | 29 | AddressInfo.fromInsight = function(param) { 30 | if (_.isString(param)) { 31 | param = JSON.parse(param); 32 | } 33 | return new AddressInfo({ 34 | address: new Address(param.addrStr), 35 | balance: param.balanceSat, 36 | totalReceived: param.totalReceivedSat, 37 | totalSent: param.totalSentSat, 38 | unconfirmedBalance: param.unconfirmedBalanceSat, 39 | transactionIds: param.transactions 40 | }); 41 | }; 42 | 43 | module.exports = AddressInfo; 44 | -------------------------------------------------------------------------------- /lib/models/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | AddressInfo: require('./addressinfo') 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitcore-explorers", 3 | "version": "1.0.1", 4 | "description": "Module to query blockchain apis for Bitcore.", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "gulp test", 11 | "coverage": "gulp coverage" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/bitpay/bitcore-explorers.git" 16 | }, 17 | "keywords": [ 18 | "bitcoin", 19 | "bitcore", 20 | "insight" 21 | ], 22 | "author": "BitPay", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/bitpay/bitcore-explorers/issues" 26 | }, 27 | "browser": { 28 | "request": "browser-request" 29 | }, 30 | "homepage": "https://github.com/bitpay/bitcore-explorers", 31 | "devDependencies": { 32 | "bitcore-build": "git://github.com/bitpay/bitcore-build.git", 33 | "brfs": "^1.2.0", 34 | "browserify": "^8.1.1", 35 | "chai": "^2.0.0", 36 | "gulp": "^3.8.10", 37 | "sinon": "^1.12.2" 38 | }, 39 | "dependencies": { 40 | "bitcore-lib": "^0.13.14", 41 | "browser-request": "^0.3.3", 42 | "request": "^2.51.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/insight.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | var should = require('chai').should(); 5 | var expect = require('chai').expect; 6 | var bitcore = require('bitcore-lib'); 7 | var explorers = require('../'); 8 | 9 | var Insight = explorers.Insight; 10 | var Address = bitcore.Address; 11 | var Transaction = bitcore.Transaction; 12 | var AddressInfo = explorers.models.AddressInfo; 13 | var Networks = bitcore.Networks; 14 | 15 | describe('Insight', function() { 16 | 17 | describe('instantiation', function() { 18 | it('can be created without any parameters', function() { 19 | var insight = new Insight(); 20 | should.exist(insight.url); 21 | should.exist(insight.network); 22 | if (insight.network === Networks.livenet) { 23 | insight.url.should.equal('https://insight.bitpay.com'); 24 | } else if (insight.network === Networks.testnet) { 25 | insight.url.should.equal('https://test-insight.bitpay.com'); 26 | } 27 | }); 28 | it('can be created providing just a network', function() { 29 | var insight = new Insight(Networks.testnet); 30 | insight.url.should.equal('https://test-insight.bitpay.com'); 31 | insight.network.should.equal(Networks.testnet); 32 | }); 33 | it('can be created with a custom url', function() { 34 | var url = 'https://localhost:1234'; 35 | var insight = new Insight(url); 36 | insight.url.should.equal(url); 37 | }); 38 | it('can be created with a custom url and network', function() { 39 | var url = 'https://localhost:1234'; 40 | var insight = new Insight(url, Networks.testnet); 41 | insight.url.should.equal(url); 42 | insight.network.should.equal(Networks.testnet); 43 | }); 44 | it('defaults to defaultNetwork on a custom url', function() { 45 | var insight = new Insight('https://localhost:1234'); 46 | insight.network.should.equal(Networks.defaultNetwork); 47 | }); 48 | }); 49 | 50 | describe('getting unspent utxos', function() { 51 | var insight = new Insight(); 52 | var address = '371mZyMp4t6uVtcEr4DAAbTZyby9Lvia72'; 53 | beforeEach(function() { 54 | insight.requestPost = sinon.stub(); 55 | insight.requestPost.onFirstCall().callsArgWith(2, null, { 56 | statusCode: 200 57 | }); 58 | }); 59 | it('can receive an address', function(callback) { 60 | insight.getUtxos(new Address(address), callback); 61 | }); 62 | it('can receive a address as a string', function(callback) { 63 | insight.getUtxos(address, callback); 64 | }); 65 | it('can receive an array of addresses', function(callback) { 66 | insight.getUtxos([address, new Address(address)], callback); 67 | }); 68 | it('errors if server is not available', function(callback) { 69 | insight.requestPost.onFirstCall().callsArgWith(2, 'Unable to connect'); 70 | insight.getUtxos(address, function(error) { 71 | expect(error).to.equal('Unable to connect'); 72 | callback(); 73 | }); 74 | }); 75 | it('errors if server returns errorcode', function(callback) { 76 | insight.requestPost.onFirstCall().callsArgWith(2, null, { 77 | statusCode: 400 78 | }); 79 | insight.getUtxos(address, function(error) { 80 | expect(error).to.deep.equal({ 81 | statusCode: 400 82 | }); 83 | callback(); 84 | }); 85 | }); 86 | it('errors if server returns invalid data', function(callback) { 87 | var invalidUtxo = { 88 | address: '2MvQs7cJe49fbukkTLwhSYnV3hSXe6Bu8tb', 89 | txid: '7d1eea0c7bed061a6ce1b49d57ef385621766e765bc3ed48bde04d816a4c3ea8', 90 | vout: 1, 91 | ts: 1428103500, 92 | amount: 0.000198, 93 | confirmations: 6, 94 | confirmationsFromCache: true 95 | }; 96 | insight.requestPost.onFirstCall().callsArgWith(2, null, { 97 | statusCode: 200 98 | }, [invalidUtxo]); 99 | insight.getUtxos(address, function(error, unspent) { 100 | expect(error).to.exist; 101 | expect(error.name).to.equal('bitcore.ErrorInvalidArgument'); 102 | expect(error.toString()).to.contain('scriptPubKey'); 103 | callback(); 104 | }); 105 | }); 106 | }); 107 | 108 | describe('broadcasting a transaction', function() { 109 | var insight = new Insight(); 110 | beforeEach(function() { 111 | insight.requestPost = sinon.stub(); 112 | insight.requestPost.onFirstCall().callsArgWith(2, null, { 113 | statusCode: 200 114 | }); 115 | }); 116 | it('accepts a raw transaction', function(callback) { 117 | insight.broadcast(rawTx, callback); 118 | }); 119 | it('accepts a transaction model', function(callback) { 120 | var tx = new Transaction() 121 | .from({ 122 | "txid": "e42447187db5a29d6db161661e4bc66d61c3e499690fe5ea47f87b79ca573986", 123 | "vout": 1, 124 | "address": "mgBCJAsvzgT2qNNeXsoECg2uPKrUsZ76up", 125 | "scriptPubKey": "76a914073b7eae2823efa349e3b9155b8a735526463a0f88ac", 126 | "amount": 0.01080000 127 | }) 128 | .to("mn9new5vPYWuVN5m3gUBujfKh1uPQvR9mf", 500000) 129 | .change("mw5ctwgEaNRbxkM4JhXH3rp5AyGvTWDZCD") 130 | .sign("cSQUuwwJBAg6tYQhzqqLWW115D1s5KFZDyhCF2ffrnukZxMK6rNZ"); 131 | insight.broadcast(tx, callback); 132 | }); 133 | it('errors if server is not available', function(callback) { 134 | insight.requestPost.onFirstCall().callsArgWith(2, 'Unable to connect'); 135 | insight.broadcast(rawTx, function(error) { 136 | expect(error).to.equal('Unable to connect'); 137 | callback(); 138 | }); 139 | }); 140 | it('errors if server returns errorcode', function(callback) { 141 | insight.requestPost.onFirstCall().callsArgWith(2, null, { 142 | statusCode: 400 143 | }, 'error'); 144 | insight.broadcast(rawTx, function(error) { 145 | expect(error).to.equal('error'); 146 | callback(); 147 | }); 148 | }); 149 | }); 150 | describe('requestPost', function() { 151 | var insight = new Insight(); 152 | insight.request = sinon.stub(); 153 | insight.request.onFirstCall().callsArgWith(1); 154 | it('works', function(cb) { 155 | insight.requestPost('some/path', {}, cb); 156 | }); 157 | }); 158 | 159 | describe('get information about an address', function() { 160 | var insight = new Insight(); 161 | var data = require('./models/sampleAddressFromInsight.json'); 162 | beforeEach(function() { 163 | insight.requestGet = sinon.stub(); 164 | insight.requestGet.onFirstCall().callsArgWith(1, null, { 165 | statusCode: 200 166 | }, JSON.stringify(data)); 167 | }); 168 | it('makes the request as expected', function(cb) { 169 | insight.address('mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5', function(err, addressInfo) { 170 | (addressInfo instanceof AddressInfo).should.equal(true); 171 | cb(); 172 | }); 173 | }); 174 | it('calls with error on parse error', function(cb) { 175 | insight.requestGet.onFirstCall().callsArgWith(1, null, { 176 | statusCode: 200 177 | }, 'malformed json'); 178 | insight.address('mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5', function(err) { 179 | should.exist(err); 180 | err.toString().should.contain('SyntaxError'); 181 | cb(); 182 | }); 183 | }); 184 | }); 185 | }); 186 | 187 | var rawTx = '01000000015884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4000000006a473044022013fa3089327b50263029265572ae1b022a91d10ac80eb4f32f291c914533670b02200d8a5ed5f62634a7e1a0dc9188a3cc460a986267ae4d58faf50c79105431327501210223078d2942df62c45621d209fab84ea9a7a23346201b7727b9b45a29c4e76f5effffffff0150690f00000000001976a9147821c0a3768aa9d1a37e16cf76002aef5373f1a888ac00000000'; 188 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --recursive 2 | --timeout 5000 3 | -------------------------------------------------------------------------------- /test/models/addressinfo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var should = require('chai').should(); 4 | 5 | var explorers = require('../../'); 6 | var AddressInfo = explorers.models.AddressInfo; 7 | 8 | describe('AddressInfo', function() { 9 | 10 | describe('instantiation', function() { 11 | 12 | var data = require('./sampleAddressFromInsight.json'); 13 | var addressInfo = AddressInfo.fromInsight(data); 14 | 15 | 16 | it('works with both strings and objects', function() { 17 | AddressInfo.fromInsight(JSON.stringify(data)).should.deep.equal(addressInfo); 18 | }); 19 | 20 | it('parses correctly a sample response on Insight for address mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5', function() { 21 | should.exist(addressInfo); 22 | addressInfo.address.toString().should.equal('mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5'); 23 | addressInfo.balance.should.equal(552461906422); 24 | addressInfo.totalSent.should.equal(663303268631); 25 | addressInfo.totalReceived.should.equal(1215765175053); 26 | addressInfo.unconfirmedBalance.should.equal(100000000000); 27 | addressInfo.transactionIds.length.should.equal(444); 28 | }); 29 | 30 | it('returns the same instance if an AddressInfo is provided', function() { 31 | (new AddressInfo(addressInfo)).should.equal(addressInfo); 32 | }); 33 | 34 | it('can be instantiated without new', function() { 35 | (AddressInfo(addressInfo)).should.equal(addressInfo); 36 | }); 37 | 38 | }); 39 | 40 | }); 41 | -------------------------------------------------------------------------------- /test/models/sampleAddressFromInsight.json: -------------------------------------------------------------------------------- 1 | {"addrStr":"mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5","balance":5524.61906422,"balanceSat":552461906422,"totalReceived":12157.65175053,"totalReceivedSat":1215765175053,"totalSent":6633.03268631,"totalSentSat":663303268631,"unconfirmedBalance":1000.00000000,"unconfirmedBalanceSat":100000000000,"unconfirmedTxApperances":0,"txApperances":444,"transactions":["511db530da494a1b7f39955d4a486416e746b643977e0bc17738de9c50b63996","c6b5368c5a256141894972fbd02377b3894aa0df7c35fab5e0eca90de064fdc1","158e1f9c3f8ec44e88052cadef74e8eb99fbad5697d0b005ba48c933f7d96816","7f6191c0f4e3040901ef0d5d6e76af4f16423061ca1347524c86205e35d904d9","c589be71a5da50783968b7c41cd1f12fcc92785654efb67a0c51285caad069da","2c2e20f976b98a0ca76c57eca3653699b60c1bd9503cc9cc2fb755164a679a26","59bc81733ff0eaf2b106a70a655e22d2cdeff80ada27b937693993bf0c22e9ea","7da38b66fb5e8582c8be85abecfd744a6de89e738dd5f3aaa0270b218ec424eb","393d51119cdfbf0a308c0bbde2d4c63546c0961022bad1503c4bbaed0638c837","4518868741817ae6757fd98de27693b51fad100e89e5206b9bbf798aeebb804c","c58bce14de1e3016504babd8bbe8175207d75074134a2548a71743fa3e56c58d","6e69ec4a97515a8fd424f123a5fc1fdfd3c3adcd741292cbc09c09a2cc433bea","0e15f2498362050e5ceb6157d0fbf820fdcaf936e447207d433ee7701d7b99c2","a3789e113041db907a1217ddb5c3aaf0eff905cc3d913e68d977e1ab4d19acea","80b460922faf0ad1e8b8a55533654c9a9f3039bfff0fff2bcf8536b8adf95939","16e5d7c5edcc56d0c4fde9795c2476c691c631a8f2828426c23c8796de9a5982","781a62a311587441fb41a975a711d40bd9187f0f89d183b50551e8b55cc51c22","7d821653895b8832722351e688a63b23513002dbaa34ae341571a2991fb18841","209f97873265652b83922921148cad92d7e048c6822e4864e984753e04181470","156c417794257f19b2e4e1edd71633fe8251fd6e60ec71f13af1900153a45728","887a9a8b5e67f8a2e1ec5e5f481d9222e7b203bdef45298c55c8ec26b3e373c2","fea3e182aa9aaf5b4222f2f046ed6066f07a6eed81a297f047aab13a62dc6110","c1301463cc1f07ed6289ae3b569fe0a7911167a5b914beddf829a9485a949d4a","3b32a082f0690ebfcae31628987559456bd316da5b62510992c0eadc1c4a7a80","1ef1d895fb1f9258cc854559a8690ee4bcd04038bc68cb8b4cd1e6e4bd7cd586","74a4646c0156b23c9da9e1a3f4f48c51b1ba1d8d033d1ef9f56fdb4634ea89dd","712e095b880341ea734528671483f9b533d49f15e66d79245b47389c1ab2fc2e","84dcb4e893c738b174c80a7723a2f49da8985031a17c613915d4425ad015e470","58f65e176b9ae982aa3700fcfd775cdefa40f64c7eb29f17251c9bc1a0a109a1","c17555c5354418f38db2fabcf5c9da91e0ac47e8a489ed8b37e0bb58d8546ad7","b19425ff60106c9a3a52ed12f993d78bcc5d8bb173c23129e1209aac18a50934","4bccb4f2c004c18ff43a52a0b5b6603fe798d07cb64327586ab64400c3809fe7","9986c0599bb904dcaaffa20b66021de71948d876b90abe07635974acb802d329","6ec9045265beb87f39aad9f6ad59f61e33e1a338bf5dad5b88326f86849ee332","52656148090873f8d60e2c32926439f732fe853d8a6fdf00f4b51802c9eea738","e514c933528529c655223c807c56a2b95e6654b4743289ee786ee8f52f740279","6848a322c576a0241549429e08c85206c13be6ecc676f7b1b19fb104061482e6","454b459520922620b3a8efc3838666e15816127f46a9f67c23569a58a12ab783","1b430f3b78ee3b08c0d39301e7d66c66b503fabdaae852d599707e156da44d41","838a5469b432b795522c35d5d85c0cb8e393bc5c8c91d3487186f1651d175394","09027a1690fc703d76d1ce828e35ba0da0a6cc09dd9fb284f43ecd2af2c5fb59","655a015ff507298d7045e857cdfc82c5b0ed28bd2ea732c76f76dc0886c940d2","4fdd75f81adde3d522fcbb977fc6bb9dedd9665afc77df2b4b1d98aeabf7bfa0","fa2ec6a72ffb8afe3188245b8eedd3a44c5bbe78153226c263bcfde4a71e0904","8efe0ab4111a199955daa36508bbe73b4867458c4f091951e5d52eba26d9a755","bf40b31784a51fa618b55eedbfa6f02bf79240eb49604fb3982c0d53e8db0695","39593b054bbf94bd39638c72a80b75a11425ea3c40cf687940553b1f35b340ac","08ab81e1ed4c0e3aeb6cc86a67852f99ca11963dcdffb301a98c526a8a25f99f","a4112d6a583d61420662baca858478b3d51fcfe15fac557ac06f7baabb83d26b","5ba00244310bd137ab2bd2184a4baf74daf436383d4e67523bea0cabaf94bed2","97ceb1ed50a4bf7281cd2b9c5dbfc8a9267ba709a30f52061b8fd6e8fe573e99","bcc05b694e52466f6baf171cdf4a106be2a175c33fe969d816386d59eb5623be","030d6461bcc321e20e478fa9ef3517fb5cccf2072b9e694e8c8bf53c559c9fc7","a3e94f98c08ed5599d263d64ce5b8a30b1fc65250699f0dc06720812ec9e6b0a","21b4b18968d890bd74ea37fc94c3e4ed74a84992b2bcc3199b201caa827fc2da","67e7d45111e285555b4b1be78d89b81f407b38099bfb7dfdc0797eeb2a57463f","2feac84f773a0814f396d8f4bb7643bb32cc051c659aca9b09c34f5729aeda67","768e16d90f493e9fcab8894694b41f6b552d951fdbdaa27c37ea6c2a9d8e1a75","0329b651c7ba07ac5ef99f7ff310695fe601519a49f18aec2a099b0d627e5a36","d3eae477f6f21eb968ec254ed8d6b85060c1ae3dd07a7e75f00a603217d65a0d","4264872d8e71b4f46c9edb38a1188731c26dc3deb7e9fc4e95811e09d9fbac58","d7b9d4bf9722913ccde3966a9fdc56fffb7a501744ab861ddd4ca1e063f21970","b11b5333a20c99e7a2b660338c54d6a994b6bdcea3396336df77e036846e281c","da2d54ce5fdfa9cd5c7fd9f712fd774655088e244e4f0ffa2f80207eacc089b0","bdcc17ea62e3136283fb6f94f78b7389b19a497ed04252ec5d161f7a0ffe50e8","1e3320baffca554af79b6441bd1cd48b1d4c8fc9eab62e32cb453c85dd09f3f3","3a40bc19c5057030ca577bf6f46c98f10e3b18c6cf23493d811095f5c6105a5e","c18b8739e9469cbade06872e8c186468a843e89d28ff9134073c0af50dfcc948","3b3d833439a60ac64df917d2072480195cf21606b5cd9890c150327feb0c3c82","6d71295f60ad13203e49d2b1caa4af840e2b0a03f3b7355981ae6dd2a6f29b46","e2344a35c7cacec06a90d803b97b4f7c180b99a0e77cdb310971b2e5f054a30f","61d4467664a7c949fa3cc6c4c253c4c2ba7b1d0cea2fdb26915090ac437d13b7","050cc567019e4f1dea1d2acfacec8a821bdaaf4944e34310634bc5d40513be12","3aa9be20e8349ef78eb028c42580f3cfdf2cd5ef79b2ed93dd6e3394e0c2ff3d","4760900171bcc47e836e2bac3a756ac207c04591c806d3b2c451edfc62881eb0","2d102da423cc60326082d0baff82fbead76ddea4b282109bdee0ad698b1a99d5","b9b682cce12b8e019eea68238bd150e93012c2472c1596322f821a0952c9fa2f","9ce8c197ebee2913959a77d8dea48ed2f4bdf2bac00b348648a806ebe2e2fb90","f24fd3f18b3576d5240a171b61c09a5682eda1ab1a678501e0f1654725634cb6","6905eaf50cf3f2bed6e31bb4e7b4f3bfa594a541b45aa333f540d78b2461c1f2","7bda07c1052684d9d63c85c890a8e68cf957c707e1769c30974a3b910d5cb753","e9f06ac3ee860ac3e62c477eba59c87bf2ed4ffc996d78936d18b60091b63d75","5ded326ec03b29b538d1cf35093189011430cd1be5ae85c3a0242e4dc7ee0d37","3df1a50e2e5d8525f04bd21a66bad824364a975449fa24fd5c2537d0f713919b","5f4dfbe7e62b885e18c1fb17e924d10d8aa5ac64fe485d0d900ff751e6f67993","6d48324fba090bcdd757b323f0c35ae40870568e02e57d968d06d6421717cab7","e8d00d8cc744381233dbc95e2d657345084dfb6df785b81285183f4c89b678d4","186c598548232f5ff57b41fd178288935b08ccbcb8f2720e809791415123d4ba","7a748364255c5b64979d9d3da35ea0fbef0114e0d7f96fccd5bea76f6d19f06b","d6e077324201a5616781c02359fdc3fc95f6badfddaec3ec5b457d5a31d660ae","d85f5265618fb694c3ea3ca6f73eba93df8a644bc1c7286cec2fbc2fbf7d895e","19b8383f48e2a4e0f33a704468b4ab2d8d1dde8966f9d2f6a73777a175cc6b01","8044b88c8e80ac9bbf5c8363364ad570949a816598374676e9fbdcc02827bfe2","bb91b988f36c0ca29406d65c4833d42b7a12d0e383ad0f3915a95727e5ace4db","daf3aa58119a6f3eaa9a16e0b9bf45dcad10dc8ff05d22aeeeecc38ee3d77748","77cc88b79f2772db652cc311b9558c1ef03a10dd9168081d9a31f1d18f9a26a9","5bc4d7dc7e9f25ee97bb029733829c69fa8f9c7310c443c7e9c1922ceb037eea","ee899a182bbb75e98ef14d83489e631dd66a8c5059dc8255692dd8ca9efba01f","560ff7a7aa98f0d046abf44a1474d04dd293eec5a9b3f0c12a586c6e0f29a36e","bc27f31caae86750b126d9b09e969362b85b7c15f41421387d682064544bf7e7","18769e9064c78f6c28d1e3e540971b59f667470185f8d9904425e4a3da2f57f4","5e4569458b11b0df6468306333b824e8fb339c4559e42f0125a9b38762494293","27fed98ada935be24a9f37dcc86cba677b50091aebf33a00fc3cebef44b5acbc","b48a2d7f8c9172170afec67688458d1c497c236199c4671083db6e3939f0198a","d61c1ef4bc15f2e9c5f8d931c0c07b5e2a90d2f78957e1f6e75e4d15308e7c1f","7829d1fd94cb1916e59cf53ead6075a3daf7a6589565b4cbaf41a426622a20ae","d5604b3547582e2f912ef00b40267ed7e018de2b2a7f343d63d7188206910e87","d56c22950ad2924f404b5b0baa6e49b0df1aaf09d1947842aed9d0178958eb9d","86d40716fc3ba3dce3d67cdbf8fc771963aae9b395ec7c7b5d6c9ec72a398cbb","4e54343c5f4a8515ff97ea072d331cd89dedc9c3a2c1be647e59cd7bb12823a3","d5176771a7394ad59c815aee606125a14110aab0c2b0582b13abc04e82748248","2b6a70d33b7098107ed7bf524c38e76cc7011f32b55e0cb7b4ba8114cc67bd68","d9ca9710fcc3fe057c30e01fff4e6513839b471104ace6ed4c2f552747ff58c9","0426eed2e46251ff060e1935340e99ef62fbd1063b4f79593a9cdbd5ce209757","23b8d0580ddce122d29699402aabe9783e3ff8ec024d3eed7041273e87dc7a03","0964bedc33c3ccfc3dee84688097c3e6b16acc0610d2059a35c85b8e453e2ab9","78900260fd01c5d1518886ba0d2c1cc0c265b00f8c6a92801ae15893e764ed6f","a0dc03a870e589ea51e3d3a8aed0d34f4f1ae6844acad26dae48fe523b26e764","ddb2297f7da0e7cccee5b0d47c10727cfe0ec8a1dd36d7136e85b135d30c4215","3fe86abce7a9fb7139e9509d88a4bb02775ae25e0c96ed3c846bce0e5e107f30","0ba78ada77352628708f25898f5151a31ad53927f5552e71acc301a53079ec67","be52ff5a745c7b407f937bce8fc68beda307317f59f4c1d188ec523b8ddfad37","bfa7993a7c225b9d067cad7270060c9380d52a9a1995630bdcbf196407cc4f95","68436a1394645f79d95f1355a7d6cb532f844a32875b6d89a20d4d6c12f20f67","d108b7a37a1924121923179995f8f5d636b8656ad417d956f467008da8d41c86","a84b4cfa9705f72d0cb7e88381b2002a7026fd43d70decbf190bf9690317c2fa","fa696de1582b28db9cd536d66aa722ec5173ce7dd7993479479ff66fdea4e90c","9363bca9b0283dd70a95977fff1aeca6bb9f1ccbccf3aa1d6240fbba1faaac01","9dc8fa80834ba2de353509ee3770757b43c199b5ccba8eee6a7041e51b1bb0c7","ded4cbc9c52fd5599b6a93f89a79cde9aeb5a7f8f56732bb67ae9554325b3666","e9f4ff5e9b993632422129a72af51ec4698508639830af96fbeea0aec2482aaf","a04bf5ba5e42d537354fa8d059acdabf16372fb36ec8aeae7d1252a8214db4c7","2cd6a1cb26880276fbc9851396f1bd8081cb2b9107ff6921e8fd65ed2df3df79","a1481de9aba6f61a91da0504ecc3a1f3c18c8ba3f8e98bef034679f741a4aeeb","bdfa4e234acf755ee90ff20b4d918cd361b8867e7310107baf740c6c744c82ff","8bea41f573bccb7b648bc0b1bbfeba8a96da05b1d819ff4a33d39fbcd334ecfd","4efe00ba9919f42f16dc11cd2729161eaa064d96f42f143faabbf14e62554d89","ac2dfc259902fe430a79b84b51d32aa0bc7933e10695963fafde8d2da2711302","d0b7e087040f67ef9bd9f21ccf53d1b5410400351d949cabf127caf28a6e7add","5ee18638245ee139f1f471ec2007f987c08273d0dde2e3f0f4c82fdc4c8d732d","a9f40fbaecd2b28a05405e28b95566d7b3bd8ac38a2853debd72517f2994c6fc","d9e0fca6ca6e8bc1fd4a8021075314cf61919d4faf0f9723a1f17f8eac20c6a1","0070fced3b9089a1a22d966083e205287e782341c78a30d97408549efd383274","f6d6932689abd29fd13f35544c45d738e1b94b71e09de250c35ea16296fc42ca","91224a219196a3f6e6f40ad2137b13fe54109e57aaed7527ea34aa903e6b8313","c684bd97844a44b382bcc655e8c2459fc97de4bf34645bd6dcf6764478338805","a2a2ffa7e89197ecdff0c4dbe7bfe92884d136549f0312e36122fdf19c22aece","23c40a3744ebb4f4fb96ee20bae680af3816fceeb13816a0cc9bb812e801ee02","daf03d666047ca0b5340b4a0027f8562b7c5bac87dca3727093b5393176a541a","1e8ffd8463872586d2035846d51947f71ebed45c6d2733bcb9a1b58c685b9b5c","1c840de063b0f290931e3545cf3501da2ee951d142cf59344d67d57f34c345e4","39df68a9afcaf1a190d77130fb5d7bb71fb1c72de3ba6f72ef0268e3b49ceee5","4123255b7678e37c168b9e929927760bc5d9363b0c78ec61a7b4a78b2a07adab","fd057d32da78086b1d355996d4c8bc4aa94cda91521fbebfab5e639ba6d1c509","7b007aeace2299d27b6bb6c24d0a8040d6a87e4c2601216c34d226462b75f915","7302b83b0413f2c7082dd2d450c8aa366fd0be35a00aa77ab0168281999ae049","c2a1a48653108b32bfb46d7c750840e88ac6465bc33b7500bdbc284988e66c1a","cb3760529c2684c32047a2fddf0e2534c9241e5d72011aac4a8982e0c7b46df3","a41dade9c045cdc9ce8b3a4feb16f5831cad0a8dec5c737b862f8cdfe319ce29","f6e80d4fd1a2377406856c67d0cee5ac7e5120993ff97e617ca9aac33b4c6b1e","f030cd713355c36b3c646175feb789531f051972c437d8c0e567f02440aa92c3","0d2c778ed9976b52792c941cac126bda37d3b1453082022d5e36ac401be3b249","dbfecb57f1effc5e29198e2c3bdba8552f7b9486867961f9c9b0167b0b3ae1d1","f5a1dec0a2687efd54ee1e79bfd5d053f5b5d5de8a220a038e381b3251469cec","871eb3b20a55ad43b85ba06777fa0181b02f036f78dd2b5a02e9aa0ed55aa821","f1fdeb7ced28f697c97b6a3ed7cc1946e1fc5e062ad8c17d05c88b1767b91b2a","51b07c87b5fe1fd8185cf30eb04a48338cc0a4698a3b2b3ce6be8a0f6eb6ecc3","08f9290c7737851c5ad113def89d1469b627b5a9c1ab7f85451e139bfdebf412","7f5f2033f87821f7b4aa00b69559533ec95bb3c4d74761d7495b3658d3e3899f","ea4481e236b0bd6d207330a3efbbc69f9ea17e2601cf1efcad768e58c65653e5","c970c66502d45d8121b8b522b9f750fcb99ca1d912df835b01e44c92b0eaabab","0f150febc1c6b89514be20c3ecd84226f0e380510d12dcec6702cc5c1a700da2","d31e6af79198439caaffecb4b84e00d9db35848e76551b63efbdac1a59785361","151c88abe7820ce85a1bbe4a519ad575cdea6e82243397e2059556d2912838d1","22d19b585943a1450ee11b85c838638ba29807012096d5e6a6573370fd514c95","fdcfc714e48594cc901bf0586ff4546ba976c1bd3c183b97d0be05c95e477dcf","29c22a3169502e76b6e02ca3260e3e2f33820ee750e6fd37203769beb96feded","3a4af7755d3061ecced2f3707c2623534104f08aa73a52ca243d7ddecf5fe86d","0a2b70eae5365c1cf4d53da64d2097b8dc0d5b9a2f4a02fdcde2c55fa416a5c5","12bde9db97154ae08eb8282c8a4359c45665877af292d98a2f4270272479f95e","4308929605272056beac03f9ad2d3c7b2f8d34fc17c6fca440e57db011b1a357","b2674e52cbaddfd2a400d444f99a3f82f0976f22ae2069a363076c81f9ceb1ae","cdc5db0505cd9f51a4a36cf8c93445d80ef5ea2cfc9d8bca103881721427ec79","673c71f9568769f4e62badf7e5a5a963133185442ca20bb799c5c990dbc272dc","18319610b4843b59f121d9b307b31d37ad817922ca1cf66ceb63cbb198a2731e","b1588b9b429df44a0e36b72948213c16c229e40e7f6dede6a68646be7b528791","c67e260ac445b34092aeddbe5d87d0d6304765d1083a4d927bb80115954c267a","310288116eb5255f892d027b5b28d3fe5b25ca6bc7311e94605f6a56463edb08","e935918033ef8972fc6f109cd8c84ef3b6dcd4b1d2aea04b70e4d8dbdd99ea46","cb0d55c37acc57f759255193673e13858b5ab3d8fdfa7ee8b25f9964bdaa11e3","732cb12893240f7f71b8bb8f4171540e53eff9c9c35271d00032dd037051673c","7bc26c1f3b4ab5ca57677593d28d13bff468a658f4d5efc379c1612554cf668e","503444162c119d646fb1eb24fca3f5330bb1ab00dda6147b1c0c7a0155b3a0e6","4a4b5c8d464a77814ed35a37e2a28e821d467a803761427c057f67823309b725","79fc5fab06471384776847afd1dadaadbe74275c9344361a0f8728965ecc6ce0","c0014eee416352a99d7ee6fe0c3832b10a1089a69c51c103d6fb0a16eb4e2754","f8c9207f952045d7377d844bf738563543a2cc2c4b2b7c9d6d605ef4825d90a3","fd3ef3465b20bad29bac5f065534b562587a837182341ce60167533a1aa2774b","aab89c9074cab80908f6ad693db65db7727b7939723a0c0d2d18019d9ebd9452","8821b504fef5fab3f6ab32cafbb4c13fa76675ed99bb05e95f3521b4667b69de","3e5514320aa8131d34d4d141919ce519af7d6563b587c89e9b7dba4241546a8f","dbd4265eec3ac8b1bc945854daafe0bbcfbe16ce00d1ef637c9391a280a8d917","f2c293980ae5b2b8f0252dcb73754bc954db5acd34ac647d58d8b50f98244da7","6edd0240a0cdeced5285ec3eb220da2d3d90090ca1e48ad535cf89bf8ab70be5","4c0f8137881d49aa24104c5ac03fea0578dfdec610bee91ec0d50653adfb8aa6","3f6e175bd976d538bfb159349d51af462c44191ea15b06a6001f1ff3c48976c9","7dfcfa51839b2816982682ffe0b99d541de78275dbd84c2f88684d863d9649a4","1574a24920c6a59e0a187bfd9b4c2b628225a89972a201168ba86191a74eb33c","91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5","5c79f2e6761f06f7d30f2e6a5d4309eea994a123045426561a25fc89096b5ac1","340bc6830e30e23e42acf7f5e9758f9f0756200f7e36b0cfe8970c9c94c7689f","05e8ddf8df855e605d5f795b5b26274ad1c11f8eb2ef9072d4e9bebd7afcc108","650f8e44b8b32204a59ab835bec1589f56249e675bf7f1158b92aeefa63b73e4","50c725d734ab1407fc8fb8f4c7d74bfef4375aaa6835b6b32fe5c808e5b06143","b4e0f56c70b16a127b7c1c37180b269cd8ccf58fa48f23bbd18cf151fa4374f5","618464d905687e06d7c02c2a45f81c2114bd8670cb4fbc365a98834637a62d8f","3a4fed5de8de8c31c0d7a4cf053ace752e1ee3b5dd350fffee98426712b51351","e45ecc95854bbe74816eb8e1fa876d0b351086ec2d184f93371f5212bf846d7a","9dc9f3596477bfe6aab853b478c2b9897a1a6d3c7c276ef7a3c6606e5179e355","1e8a3cd1371ae9908236e9ad527054cfa7d9942162d94d451aead27c9cbea0db","888d61ba48d86e20f9804cc169f8061299d28fddae1e7be45fb2dcb347fb96fe","5543a13fcc09b7111e5e76250434a50181f58a1ef71013b6cafa0ff3aff1e33b","4a045d398d13b54def3ac2ad120ebbcc89f79a9f513eca026380b4787c792eec","20092ea970797f057794c961c95326087dfd6762ebffd4f326f513c46c9e697c","757aa100cab6ba8732a2571c4c4ae9c7b2b8140cd2132f733f1578558a7fe9e2","ba78226e1c5a3616a125911a055cc9105b048f306afaed7e444a22ab18ff4ac9","099a829a856562bf7c0ce40503c8173b9c1488dd48f91a8835fbe9f66ee661a2","b9b17aa05934aa7c5123d92285edd189d5192c6a643a59d959447431e8db6eaf","206c6565310a5275a3e173cdff1679b051d84e8bbf5236c16526113a93378c02","ccf41ce1c24d08f3a4dcbd58cda12fadeb81b1b512a7be666f2d996228964edb","28d411de336e49c355e6d112ca118bede298e04092389bfcafe71d68b31c1d5f","38ac349b443e4d3df8edb6378b0137743648d7c6f8f4c8a525989e31f1d29e7a","594ffd03673adc4442881797eeb2ca25a699bf4994bd061e18b61622b0b7e708","45e86c61ec33aab1a4ac59e5de2a81995dcf412bd9342192c14e5cc6e9caf636","622903b4a5234cf65cc6a648685160efbc3d9e2a9534d86a9f3a2c7270a548fb","29b9b39ad99def73d6cdb3cd542e68c0e811149e0d771a85e45e2df953fcf049","b9cd8e96d61ff9575a022525ae205decd6558cb25ca3e738ccaa4d8fea7fd495","e3d84021904bfb67981da6d4cc79b58ba34cd46da2953ecb242a6d4559b0aef7","6e6faeff78f6629b18c4bc3e26eb1a32439e8e78013afe0c27f34c9db4d5937c","b028458b22ac975e62e47754fd6845d479d427cd7aff916ba258bf35fcd7552c","6930d3a40fc029a80a184cbadb2077618357089c9ad393e7c8476d10eaedaddd","7fb6d6da7f10d94dda97d712871ee5e23738b3aedcc695651a1e86b0cd605af2","ad78b1f427776358394cec415b4a8b862da051c4bc191d96843b4b3c4dc5f17d","c85948a8255d5b6f93209ec9b6601b62850494928b60bd38c257aa1114b7f45e","6db8b0e0129182a96020f569e6b7a707fb5874d6e01a9c0696d52e44144b81ed","1eb7ee069069634023c1580d86db87c6a36511a4599ac1894a2c8446d2a22038","cd65807d991b3e4392676cbf645077a6d5915ea4934c0acdf8d8502074839245","e724bc5c0785c70efd901e78336a9936cc07b734c68a4538d3dc8324e661ce4c","0d5707aaa5b4f38973ee9f098be37eca84ea97cc361bf1245b7ce0126cc0cdc4","37cf54c3ee477491f696a80184ee5133a0502446ccfeb03f8a5a02d1a723b7d1","3093e89aaf15192923af7dbe407ff8010649434e7ce57ec16ffed79211c889db","66dd87f91e6d44303a929f5e62d4068f30b520b891c07079f05cb01ce3c97589","05c1aa784ddac307467dc67b53c078a2e5d5d2de791e73bb44bd041de50aa924","1832f582eab4e0c39481e47ade55d6744ce87cbbed27cc8f72c0e9923c46781f","61b4c6ad64b354fa0594cabd61718e0d1f00678c135a179fb35dfa6759fec958","e4b33819950c52305e55684701b93219b1ea5e87e2111c7c32cb6e116e685d12","0427623c15809c2359d4c355cd7484a74800f0fb30ed6b5fb9e929bd7565c0f8","0f0f71b10b5b6717d87c8fd9685f7460fecadaedce00d7180e2130e1aab456db","c319612c0e2b08f653fc51f4348e4faba2080ceff6b3df123b0a554c78f49bf3","818230d2e0f209b4f218811334eebe595073cf751f2a396decdf5149b47cb3b8","ffeb9526fd4771e737e4c3412b14516b18f6a453d5ecbdc66d9de2d912de7e46","ca6fedfe822cefc13f142fbbb450130552f78ae04a7eb41cddc4b54e9c3b1574","a168ed7764ce58d7bf65fa74ae97b34f4914556cd9002e1a098822825b518bd7","a6766fc5dca8b6e0a7201f3a4c3c155fce71923c00b0bd868a6501e604f09e48","843f69324f458d586480c46b70ff2f38c3758b68910c582c484823ed021114b3","6a93136ef13666f5627630ae9122bf67cca41e6576cf6a5c99bec7b44dfb2a49","30665faac3fbbe611c0ac72b10d5212760fb9f3be582c322e9c8d380a2c1aa6a","a4bde17c8df7095230896d98d44f1e1659166d40b5daacbda5aa44f1ac5d2b27","124b068027300d0bf353fe48b49d7cd9722df9919d3cd1b26d1bea7d3fce82d8","fc77a75a5ad3ec1022c7184fc1549304aa266af08a1c7e6d8d4e7140f0e67579","663861a81fac8b5866764e3c4da3d9c447329f72e0d7d15ee00c4e0a1a665e61","538eb0045873382b2e5c0cbe8c201a93951e5d6c17e7e0bdd55a3aa63b87f9a7","4317408436f801c7cbb848796e40923adb3cccacd48383ab9efb51e55f2a317d","c5011dde3168de0b40dbe448e898f80124a8118847a5a71bee9cf6400c5775b6","dd4041c7a6152cfea984474398d52df59f53a4adcf286a027d875aba412ef570","92b38548090292cd423690544077192e77910ef0b64cb5cd03101cfbf6ecbc2a","8ed4f781303123da6a8e2692f43ea35bb19c0939fd364a38500abbd1d4910db9","05396f690bc768cc83bcacb494f14b10314c916b7731fb2b5c8da78409b27d74","94af4d6dc25a309b84e9ddced689e0fd489e377173a31f33052925597bbbabd4","c7b3639032b5e4a998f2df1da82f87e9f659ca455efa421d245f4a60f6669e53","badbb25dcbcb7291e70e31cafeec58ab98271db4a0fba765f2770de1eb0a3c8b","ed8523083d02b8c9ef67fff281053139201a4515942e7ed5feabb4455802e5fd","86b094ed480bb7a2084c3b95710207ad2d0ad5143a9714ecdfefee8953a00a40","dd714c5ffe0a9e631c0f5ed0e5fdc4eab0c856372d81d45e7b195cf8bff4c834","4ef0605e64cc0c0c05d75c1348f5be923da6637fa3bea1cc0cd88baa024374a9","2833b6639ef0a533111ec0db1e768d335343bcad7b0cff10a28bcfeffd96cc1e","25682e17b29ac85d2a58b7d9284fc7729df5f31f4174de05f6264e632cef6602","70b578bb3a7460cf3a639bb763dab0d39ff57c5fc8a395f32b5eda7b7b98f41a","16a1ba6e75f649953fa505261497de889758ae172bbc877f7a4ced70a3e34b56","3d9edf909b25b15a03fe09b9295caa505216e9adf15149ad41baacb1e1d67b1b","08a2c14d10057a84de3a0ec29f6e33f5d6f14c0578fa3e56948803d3b44b880b","01fb058e181928e72ab307c151eaf1c086cef03623c0a1986c6765463646118e","0cde19c63934870456f4795307e5e329dd3ae0bab0a5610cc8694c99d5a12a9d","e83d16b29a3946af54ea005e29cf47e0205da222a680d64433de00ffbd795e0d","9f0f716b3cf8efdc3a8bec7329482d92204fff90f965b6b96362be1c00bfa8e9","bff6130ea0aa6fe0f7c5067651e629fa2405c6d5adb44454d4f45c0162697811","7db7f549ba9db050fce83088cb0b76fa11696af663f4e44e63e33401852bad28","e4656a67cacd7a594feaba72e6bcb5fcd145d1ce4dced46848f6615668d1db2f","6cf25b22a72cd8ede91458a576eab2b6d6195701dd6762f3ccb9c0eb24b88d46","4c5f138958ceee581a019536f6ba36920bb084ec2bb33de846bcc99064147caa","5bb30deae28dc12b91e1bc1cdf2fced33d9782461b2471a024c453f9f6dfb193","d4f577e5dd6fe60d112efef08cbc1b64d9d12b9b792de7060e9d965af7ddcd67","12eaf069901abc39cfcafd6283ab1f27834915162a8ea9531346e4df17befbfa","290e8fa5e3178f266abb1044325a93dede7e26ec99779cf340770cc715c34892","57d65ce5320dc617e65df7a18007ebe4e89fb7658ad6ff7f93e554480563eaf2","42526ebe256cce06d0b902babecf6809a2d7c1cfcf457db1803ea231fb583b8e","521d04e36df20cc790e7db086e84f263bc02eec5f400d913abadd27bf263a8d5","4a78406bedc346257226364602c2603667518bd567b6546adaa05684333f795a","4234f86886f50cc18b776ea46ff8f0117079ece90e8d52db75a942cb4ec93bd2","7dde5b9f6cc8525c66cb884b82b2ac3935acf4bd04348d11cac796276b305bf5","4eaea6e6af5548066a782fa35ef12a47cbe6c280542bdc75efa732e3bec3435c","db89d7c831589c67ddda87ff5f5ffaf017f42e0fd4e4ef25766b4a372e99b963","8b13a84501cb67bfc8c0815b7e1ad32677d53aaa51d48723632cc8a9e1c63637","713c121440b9602168108f593841bb2ba31aa2bf453f28d77bdaef5b3274f0d0","85948746e916f55cabe5425e3520bc6f8e2ed1d671fdeff207cc6f67ee50a9e2","7d130d65247b2aabaef2c23365355cd7766f3d69490e085e835c12b7917a2ef1","6f9b79eddcdd70a3e6e8fa9adc9f6584a45da91a4de000ad99aac5f104f2d314","f4bdfacfca13412fc8353bfbe509abdfa65726cc0e5ae5371e059a004e828870","fc670ec5ffd16164b32543e37d985289ef558de6cda29aae46ce9c64b3eaf251","6d687da47e86129a3badb5fb805a488172e25d6efffa5a0ea677c67acd07bef3","85e0533e2abcd4ac57add3eac5e2fef0bb4431cb3699fccc5f696715d2c95d0e","3f1c0817e70035dc4f90feee99df200643294e2ec0f22bb6f68f6e85886cdca9","4ba0c18f6ca3f574dca69a0f83b5b60c8bbbbc0d8a4b955cff6c09f7d8cc7f7d","f0c788025b04600d723b69d0c10129c49d64b75941850e646a6520d13311cf43","b52d76976fee481b33098e3375eb35f6b6852175d3dd2fa6ef94c101c8dbd820","c4a9a9b16d919c5fed092bf92b2e7e2fdf7f17ac40874bb5bfd627d924881038","77b4dc1cf7bd9e0e0fe23848dd69b49b19fc12cd0f6bf5b263b0d8e2abae7efa","5fb75bc529706832eb861b20f6f91217ded7c910fb5937d88a87efe535a6b978","9069287ccb9cbd33633acbc4eea195357d8427f258b0bebc11a253918ac3ce88","2a14cf150cbca7cdf407b720a922942938ecf920bae54cd89b42ddfda809e65f","7ae62fea963b74f07fca986c966fee71a55176f78129f0edc236f4c612b18203","09a41471ac6ed6afc7695676e4854c4e09c3f0a0e0a0d156a6639966432c5e5c","8bb0e9b4f54acdf4b595c3bfcb503d3399502658f3963e4e6185a9573f02ad3d","98a25f662753685e7ae32f496bf9d1f4acc1666b5dd4e9906c8c0f685da0807b","4f403376c1452dbf36a1978f5fd1d52b686db7e0d2f666d3b2b05a15bd1ba432","379b5abe4aa7ab727ccb370c1fad21f5340564a5fbaf7f97802e493779c52eb8","88d85e4a2192c118a8e66ade1a13366a82043d46b986c556a627d932a6137fdb","c14e5c25858d47f4187cdcf60ba57a525d7de5bd35deeac930d5ea10ad8369a8","98e33762674981a02499d9c8869b13e19d3600da016e51b4d09dd11099a89273","e12f226065adc2265fcd94ccb2f1d55073329f48b4d05ade176411d3f8401221","0834cdb1127b0f4fef46367ecdf926455c2492bfa19b39dc22f3c5a7627a1932","2bd782e8adf784a3fbdc160d2ae054b34730784b37dcd86b11776422d6d6d152","576f62da6cd87b79880b02da082119c2e84c40a97da928deae513f050707e1ec","7a7590fbb320f1bd6837d0fe1f07e242194358794382ba0f543483558d580c6b","d064dffa8157ed363afdb389fdf9cab200bd51936e68bae30fe6399b1eb7d6d7","8540283bde661e496c751fee620a081b3f0206647293b50d8d4322b068174acc","0bfa8bc0692c8a512d43afe7de02e25e092ec3a092b42aa7278677b4c68ffc31","f3d7695df020aff0421e6d790f160e24526b7fe05b99f51aaf23e3b876e0811c","2b8f2905dd667a82eb1cad1237d4b3bad17ee4e206bf9ad7be2cd13b6a7bd051","425022ba0507ec0abc60298830e753605e7b6da7931cc3d34ed9174eeb5bbbbc","9630a1ebffe1d8d4f6c8c30e937bca3b94c32c5cd699712b39ff2731e31474e6","13680234ccdb0579362cd6a1727b7f72d9304014a69a6b64646b6cacf7d8fe71","c4d87d63534197129cea41f1c4cb3eac0921ef2798dfaa1690e0469399694f40","ed9731b4946bed9dd17704a1864de065ff6751a1ab8074059338df833f330518","79677763b5cc8880ad04203c48661e889d02d2fc842c912a131b835e1a54f53a","10d52cb88430a370935a94f5a0a31cbc69007d0f94d61082b83703206e390457","bbff530de9b4265f17ad47c48e0998fcb2bcf6e603b4f5f2ad8185ad98123a40","f71e1ffa179ae5be523934473c2bfb89e8844db47f33f89d05d2ff62ad8be8ee","4821fab81643f924041bb7fb9615a872bb71ba983bb98c41674de5699eac0761","7a69318e53cccff133cd10f3165ae01fbf72a705e2e0998e96b653170a07c44a","fbd13d8a090ed9040eccdd2384813d43937b6e4aeaf14cb11720f4f396992400","88c7b4c940bf45e24ffd3cf99a40594ca0278294f1c518f49f1422c63f41977b","cc27076c9ba8d6104e2846e6b35121f0640d9ec337083aeb9b0e4b27bb306dd6","75cad0ea2b5ffe7b0ce0d6ef0d4a38ca20df66a95ac8d85deadecb4a0d761ba8","39886afec55cd4193e6c6752ed93c2769e2497b44c01f0a40370fa6dbb400b48","f738cd8928f8e838ff34f62d76609c79e8785d55a9d3a0e905615df18872c112","c39c3bcf275150ff3f60ab29f7ec6d0167a21695d722ef161c65a53a5336669b","e735e601b425fe122a45bf3cc3d9762be083275555ed665f51ab7f7096889eb8","c38385613855414eefefd0384e1141ef9084fa24d630b57f3939f89e02a06698","0aa75ef831ce668e9c26467e761f2bca010dbab0f35f0bd2bab7039557c93a6a","58f5505cbfa7c6e7d2d15fe65d558c890574c0d4fa567191d4357ad60f6dbfec","8b1f1baa93d29fb46f0c9ba0690d39b7c2d480679a8635d6d7cef12a87cbee02","17ce3bc58234d43711d80ad2df0c57091fc3a2e124dea9b9e0a797ed3a9393ac","b59dc130ab8178e6aed911a91333ac0abd3574e7d54abd36f4dfa30349cb05af","86df7641385c2986d93a4476ad0b5ed19e8af79c096c866f45089f19843061fe","36a711ab10d25f262b7e946aeed6e14142e1b999d42efa910311952067ef0518","60aca792c9f2feb8398ce907b8d798ab05b0b7c2fdf372cec18c5e0a85acb731","a8d7d4242d5a6e3fdcc74651d17e6ca3dd6134393b40bef8e5fcad78d15e5132","a8cdec1de97884de92d8451bb07223d34007221081584a46e68700465d4cb375","19a9f90d8ec564318828e16c92e9038b71e181fa2f975ef31fd4281f865769b4","b489bc0e51ba3a7e82753996608a02ffc78fba692e4e903d73b7aa36665d04a2","2955a4b042cb2c96423b5d6603a268b87ba27485d36fe36bcdbd3729a49d4b71","1ba9269ba1885f5b77cada8d40790c94c4264dea2a03618db4c1a58e6bb38798","16f2eddfca314c74a0243e643c0ffb9fb53fed185f82400f704d55ba3a484cfe","675a88d8f68d28ea0047eda8dd967bde1a16685520ee38f762c5c2c9e96a8f13","5907abdb3b6c1e108403575ba71d0957c365994280ea7937c75027fd647e9572","6bd49ee46dd82c244d61f82729dd92a70dcd8894f7b42982f6f2c8ec108c4cfe","0c48b81bc1389f6d546a7d6162f935fbb21f353148f5a9c0fb0cd1f3f505b6f9","29d7f7b9b05b13af08323a1e4bdcdb2b22717c73bc3423545c9d68e763594b7e","6950ade214487c96350b5ebece962d1f838e4382790e8ad5c0ab1a7cc601ba41","0a61590c7548bd4f6a0df1575b268057e5e3e295a44eaeeb1dfbd01332c585ed","7a8124547d1f981c724800841245c3be6c7fb70ee00649c4827c2171209d8a37","22482c5aa44d0c535d2a259123568cd865ee31158b83c3a4eac1dbc737edb13e","db5cdd1442b5dba68056c1310323f48ecf9b5870d63671ac2583c3bc46b8ff06","c11877520e0da3607fce62dd6c8f7801e0d367589d74e69f55c6c49cdf3e1f10","670bfc59e56a6245754e472b4bbdecd726bb590e760f164a904650dd13515db6","30e9baea243c0a50c3d8319590613b206d0b5b57da40a8ce7a86bf8539b1a77d","8171af99e86f3ec5ea7443bccefbd73d2e382f46896893d8041a391b48a5dc9c","af4c10e0c95790744b8acc4cd3b44028236768f7d2fba97c7e59c139b62f56d2","440e2112cceda1e7905d414fd43771f0df84aa13790c1d72107133a944f36fb7","a269248e9414ab1919956137807b12540967444cbace0c984a5db05180e3b280","b37654ec77b8d07fb36267da7d00ea803e69d4ae9ef7542ad370f5077132b240","8e4e6c6c2002b971168ed02513f4e8cde18862cfbc2b2671914be9b9a57f5394","096540da2eebd75e2366953afa9b28a8e152c55e5a998489f638d8db897be7f0","4836ea18a4453916cd020f3bd6e4fccfe149fe5bfe667b7ff606dfcdeef780b4","56c33ee4e6d346f08a5dc15d24e20f18a5c9afe1274be6ac68dad87de589ad09","1411f62d1f0a6b0682e12a4fe71c22c0b817f350ce8d62f3a82b3dccdfb28578","2669d2a9078781811260df12ac8c69f8f10940d1b4e7b43016141ebaa5fcd3b4","37a1058daac4a91136f670882cf1646bfed1c28d5b955ef0bb28008f0e2e9d12","b6a4e32b3a9663b1095409037ec1c0fffa4bcafec1053444ae63663d3741b3f3","4cd9b6a5ec78a0b7c856a040c973cd89c7576b82c523db2497445fef448232f3","3d2b2fdd972b36a590e0dff3a8a3cc14d1f5227fd385a311d6477449cfd8593b","36f37668b5ce0c89ac18dcca96dbb291ca60e200b992d3cd3744dfb6c948d6f7","62ac4d55f4ea4555eefe97cedd1496876a77e985f5356e42bcf475fb99a5b880","3e11645b71f527c5c95abbc7590c8d71f5f85f3e7d2af0afb4ce2c1ffce8751a","b78cdad220d7b76c36e08a036ea5014859e4d35f5a136604f6e34b5a8a902945","0eda34fae6c9ac181f06ae2e0567728e0e680387f79e2cbaf3016e6f5cced091","3368a69ebbecd9647a51ac753a18db8119da8320343d4acf06b357c9838c6e13","6bdc9e53acf4a5d689074bbbe2b72708ed18161ce5b55c99db96edcbc0a27fa8","d7165979b231fb146a7d4f71f02cc528ef8e2dbc1936c50758e28d2988b711f9","297ca4943d35c9a82c0cf236993bd1f91e4edd6164e008373d80112c62ce325b","86834ebd73e7a79cc9549e775cf3691660d0578cfc498e8f901eb75bddf92c11","e321f4fddb107a3f853294e0ca14888c150e42470f069c8fb450d6d5ccf07bf8","c318ebdbbd6c4cb2e859fe5acda0f829d977f87306dafdd4f1b89b2de1f1a278","5257a2ac4a332586c836dd40fc97a4cc3376b18409935cf9640a981fd35e8b90","b12f039096a1db0456a8908e313c7fe0102f5232811624f06786fc4bc304bebf","d593fd84799eb024eb57d51eaf9a72a75e95cdd1084ea452946c78ca39acb875","91fe844b16647904bb079c11016c225bfb53d19d3dd23d6d89ba16c3935aecdf","cb271059b186c7e21e721af4edf9668378d46ce45ff75e663409ce781826ff98","a5ad19606ef9e538cc172aeb27219d1e492c84edf8426ef0469ac4a5961a34cb","66945be17108a0b7d55cc6e8f2423a26bac927e683e524a3144dcab419290f79","b5e6cb0cd17526a394343b1a2007e199d6d9ed0e3b37612abd8ed52b36a6fb23","73a6d2b56bba58dabb86fb6be5358c52be178028b7dc592110a44f2a20b3eaea","84792f135b293cf4056ec8fbc2ff9e10aaed8468fe0c8fd5ec8861d886011501","ef4daf92f7aa39500755abc41b6c904af891e77b038e852af6d69087880eb31e","5286e339f1db9706c074fa9562c2d9e77e61e872b4f70d132b2a7a3d742e3583","793b96262b397fadb4b391e57fca295ad5f14961cfa466965b32a58342792e33","6c4faf799121ab49837f82797e4a31b515e469416cb1725abfa098c9a470e2a9","bd474f24754c25a388972fa51a5bf6f65131413bbcee5e9a3fa61827b9d27191","61211d10c17fd44d40262f33a741c1e53d7c504f569fb4323909c57b7c9d6d84","2d8fda602a4fc611fe63fe1a4a1ebbae4b36b4ce6167bbbe43365f208e5a9199","847b3b3c29e3b59cb2b798acbcc091c222ad17c3e984bfab89785039f5d5f088","609732aada2b42ca6c706db2973f42efb5241c587ab8158a9c4d8822e2386c97","2816834ee88fc1c5d2f36f27d8cc4f53b2fb0cc9d72dd5562c8f1dee8aa902ce"]} 2 | --------------------------------------------------------------------------------