From 3e166f15fc17c16cf13001e93a184019880dd8b8 Mon Sep 17 00:00:00 2001 From: liana Date: Wed, 14 Jan 2015 13:52:03 +0100 Subject: [PATCH 01/34] - added functionality to set values to 0 when deleting structure(not for mapping) - added unit test Made some changes after Christian`s review on pull request - remove/edit comments - BoolType and ContractType return VoidType after delete - fixed constructor_arguments test - fixed set to 0 when deleting variable from stack - changed test case to test that --- libsolidity/ExpressionCompiler.cpp | 89 ++++++++++++++++++++++-------- libsolidity/ExpressionCompiler.h | 10 ++-- libsolidity/Types.cpp | 27 ++++++--- libsolidity/Types.h | 13 +---- test/SolidityEndToEndTest.cpp | 62 +++++++++++++++++++++ 5 files changed, 155 insertions(+), 46 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 1c02f4f32..c8b7f3508 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -94,13 +94,8 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) m_context << eth::Instruction::NOT; break; case Token::DELETE: // delete - // @todo semantics change for complex types solAssert(m_currentLValue.isValid(), "LValue not retrieved."); - - m_context << u256(0); - if (m_currentLValue.storesReferenceOnStack()) - m_context << eth::Instruction::SWAP1; - m_currentLValue.storeValue(_unaryOperation); + m_currentLValue.setToZero(_unaryOperation); m_currentLValue.reset(); break; case Token::INC: // ++ (pre- or postfix) @@ -696,9 +691,14 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, unsigned _baseStackOffset): - m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset), - m_stackSize(_dataType.getSizeOnStack()) + m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset) { + //@todo change the type cast for arrays + solAssert(_dataType.getStorageSize() <= numeric_limits::max(), "The storage size of " +_dataType.toString() + " should fit in unsigned"); + if (m_type == STORAGE) + m_size = unsigned(_dataType.getStorageSize()); + else + m_size = unsigned(_dataType.getSizeOnStack()); } void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bool _remove) const @@ -711,7 +711,7 @@ void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bo if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation()) << errinfo_comment("Stack too deep.")); - for (unsigned i = 0; i < m_stackSize; ++i) + for (unsigned i = 0; i < m_size; ++i) *m_context << eth::dupInstruction(stackPos + 1); break; } @@ -720,14 +720,14 @@ void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bo break; // no distinction between value and reference for non-value types if (!_remove) *m_context << eth::Instruction::DUP1; - if (m_stackSize == 1) + if (m_size == 1) *m_context << eth::Instruction::SLOAD; else - for (unsigned i = 0; i < m_stackSize; ++i) + for (unsigned i = 0; i < m_size; ++i) { *m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD << eth::Instruction::SWAP1; - if (i + 1 < m_stackSize) - *m_context << u256(1) << eth::Instruction::ADD; + if (i + 1 < m_size) + *m_context << u256(1) << eth::Instruction::ADD; else *m_context << eth::Instruction::POP; } @@ -751,12 +751,12 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool { case STACK: { - unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)) - m_stackSize + 1; + unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)) - m_size + 1; if (stackDiff > 16) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation()) << errinfo_comment("Stack too deep.")); else if (stackDiff > 0) - for (unsigned i = 0; i < m_stackSize; ++i) + for (unsigned i = 0; i < m_size; ++i) *m_context << eth::swapInstruction(stackDiff) << eth::Instruction::POP; if (!_move) retrieveValue(_expression); @@ -768,17 +768,17 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool // stack layout: value value ... value ref if (!_move) // copy values { - if (m_stackSize + 1 > 16) + if (m_size + 1 > 16) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation()) << errinfo_comment("Stack too deep.")); - for (unsigned i = 0; i < m_stackSize; ++i) - *m_context << eth::dupInstruction(m_stackSize + 1) << eth::Instruction::SWAP1; + for (unsigned i = 0; i < m_size; ++i) + *m_context << eth::dupInstruction(m_size + 1) << eth::Instruction::SWAP1; } - if (m_stackSize > 0) // store high index value first - *m_context << u256(m_stackSize - 1) << eth::Instruction::ADD; - for (unsigned i = 0; i < m_stackSize; ++i) + if (m_size > 0) // store high index value first + *m_context << u256(m_size - 1) << eth::Instruction::ADD; + for (unsigned i = 0; i < m_size; ++i) { - if (i + 1 >= m_stackSize) + if (i + 1 >= m_size) *m_context << eth::Instruction::SSTORE; else // v v ... v v r+x @@ -800,6 +800,47 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool } } +void ExpressionCompiler::LValue::setToZero(Expression const& _expression) const +{ + switch (m_type) + { + case STACK: + { + unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)); + if (stackDiff > 16) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Stack too deep.")); + else if (stackDiff > 0) + for (unsigned i = 0; i < m_size; ++i) + *m_context << u256(0) << eth::swapInstruction(m_size - i) << eth::Instruction::POP; + break; + } + case LValue::STORAGE: + if (m_size == 0) + *m_context << eth::Instruction::POP; + for (unsigned i = 0; i < m_size; ++i) + { + if (i + 1 >= m_size) + *m_context << u256(0) << eth::Instruction::SWAP1 << eth::Instruction::SSTORE; + else + *m_context << u256(0) << eth::Instruction::DUP2 << eth::Instruction::SSTORE + << u256(1) << eth::Instruction::ADD; + } + break; + case LValue::MEMORY: + if (!_expression.getType()->isValueType()) + break; // no distinction between value and reference for non-value types + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Location type not yet implemented.")); + break; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Unsupported location type.")); + break; + } + +} + void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(Expression const& _expression) { if (!_expression.lvalueRequested()) @@ -811,15 +852,17 @@ void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(Expression co void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, Declaration const& _declaration) { - m_stackSize = _identifier.getType()->getSizeOnStack(); if (m_context->isLocalVariable(&_declaration)) { m_type = STACK; + m_size = _identifier.getType()->getSizeOnStack(); m_baseStackOffset = m_context->getBaseStackOffsetOfVariable(_declaration); } else if (m_context->isStateVariable(&_declaration)) { m_type = STORAGE; + solAssert(_identifier.getType()->getStorageSize() <= numeric_limits::max(), "The storage size of " + _identifier.getType()->toString() + " should fit in unsigned"); + m_size = unsigned(_identifier.getType()->getStorageSize()); *m_context << m_context->getStorageLocationOfVariable(_declaration); } else diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 98f58c854..665ee3c9c 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -119,7 +119,7 @@ private: /// Set type according to the declaration and retrieve the reference. /// @a _expression is the current expression void fromIdentifier(Identifier const& _identifier, Declaration const& _declaration); - void reset() { m_type = NONE; m_baseStackOffset = 0; } + void reset() { m_type = NONE; m_baseStackOffset = 0; m_size = 0; } bool isValid() const { return m_type != NONE; } bool isInOnStack() const { return m_type == STACK; } @@ -138,7 +138,9 @@ private: /// Also removes the stored value from the stack if @a _move is /// true. @a _expression is the current expression, used for error reporting. void storeValue(Expression const& _expression, bool _move = false) const; - + /// Stores zero in the lvalue. + /// @a _expression is the current expression, used for error reporting. + void setToZero(Expression const& _expression) const; /// Convenience function to convert the stored reference to a value and reset type to NONE if /// the reference was not requested by @a _expression. void retrieveValueIfLValueNotRequested(Expression const& _expression); @@ -149,8 +151,8 @@ private: /// If m_type is STACK, this is base stack offset (@see /// CompilerContext::getBaseStackOffsetOfVariable) of a local variable. unsigned m_baseStackOffset = 0; - /// Size of the value of this lvalue on the stack. - unsigned m_stackSize = 0; + /// Size of the value of this lvalue on the stack or the storage. + unsigned m_size = 0; }; bool m_optimize; diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 7ca1dc6d5..079e79b8f 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -147,7 +147,7 @@ TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const { // "delete" is ok for all integer types if (_operator == Token::DELETE) - return shared_from_this(); + return make_shared(); // no further unary operators for addresses else if (isAddress()) return TypePointer(); @@ -408,6 +408,13 @@ u256 BoolType::literalValue(Literal const* _literal) const BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Bool type constructed from non-boolean literal.")); } +TypePointer BoolType::unaryOperatorResult(Token::Value _operator) const +{ + if (_operator == Token::DELETE) + return make_shared(); + return (_operator == Token::NOT) ? shared_from_this() : TypePointer(); +} + TypePointer BoolType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const { if (getCategory() != _other->getCategory()) @@ -432,6 +439,11 @@ bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const return isImplicitlyConvertibleTo(_convertTo) || _convertTo.getCategory() == Category::INTEGER; } +TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const +{ + return _operator == Token::DELETE ? make_shared() : TypePointer(); +} + bool ContractType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) @@ -440,14 +452,6 @@ bool ContractType::operator==(Type const& _other) const return other.m_contract == m_contract; } -u256 ContractType::getStorageSize() const -{ - u256 size = 0; - for (ASTPointer const& variable: m_contract.getStateVariables()) - size += variable->getType()->getStorageSize(); - return max(1, size); -} - string ContractType::toString() const { return "contract " + m_contract.getName(); @@ -491,6 +495,11 @@ u256 ContractType::getFunctionIdentifier(string const& _functionName) const return Invalid256; } +TypePointer StructType::unaryOperatorResult(Token::Value _operator) const +{ + return _operator == Token::DELETE ? make_shared() : TypePointer(); +} + bool StructType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 1ccdd706a..3d9b45e2d 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -259,10 +259,7 @@ public: BoolType() {} virtual Category getCategory() const { return Category::BOOL; } virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token::Value _operator) const override - { - return (_operator == Token::NOT || _operator == Token::DELETE) ? shared_from_this() : TypePointer(); - } + virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; virtual unsigned getCalldataEncodedSize() const { return 1; } @@ -284,8 +281,8 @@ public: virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; /// Contracts can be converted to themselves and to integers. virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual bool operator==(Type const& _other) const override; - virtual u256 getStorageSize() const override; virtual bool isValueType() const override { return true; } virtual std::string toString() const override; @@ -315,11 +312,7 @@ class StructType: public Type public: virtual Category getCategory() const override { return Category::STRUCT; } StructType(StructDefinition const& _struct): m_struct(_struct) {} - virtual TypePointer unaryOperatorResult(Token::Value _operator) const override - { - return _operator == Token::DELETE ? shared_from_this() : TypePointer(); - } - + virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual bool operator==(Type const& _other) const override; virtual u256 getStorageSize() const override; virtual bool canLiveOutsideStorage() const override; diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 9543497a7..a733c2c43 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -772,6 +772,67 @@ BOOST_AUTO_TEST_CASE(struct_reference) BOOST_CHECK(callContractFunction("check()") == encodeArgs(true)); } +BOOST_AUTO_TEST_CASE(deleteStruct) +{ + char const* sourceCode = R"( + contract test { + struct topStruct { + nestedStruct nstr; + emptyStruct empty; + uint topValue; + mapping (uint => uint) topMapping; + } + uint toDelete; + topStruct str; + struct nestedStruct { + uint nestedValue; + mapping (uint => bool) nestedMapping; + } + struct emptyStruct{ + } + function test(){ + toDelete = 5; + str.topValue = 1; + str.topMapping[0] = 1; + str.topMapping[1] = 2; + + str.nstr.nestedValue = 2; + str.nstr.nestedMapping[0] = true; + str.nstr.nestedMapping[1] = false; + uint v = 5; + delete v; + delete str; + delete toDelete; + } + function getToDelete() returns (uint res){ + res = toDelete; + } + function getTopValue() returns(uint topValue){ + topValue = str.topValue; + } + function getNestedValue() returns(uint nestedValue){ + nestedValue = str.nstr.nestedValue; + } + function getTopMapping(uint index) returns(uint ret) { + ret = str.topMapping[index]; + } + function getNestedMapping(uint index) returns(bool ret) { + return str.nstr.nestedMapping[index]; + } + })"; + + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("getNestedValue()") == encodeArgs(0)); + // mapping values should be the same + BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 0) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("getTopMapping(uint256)", 1) == encodeArgs(2)); + BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 0) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("getNestedMapping(uint256)", 1) == encodeArgs(false)); +} + BOOST_AUTO_TEST_CASE(constructor) { char const* sourceCode = "contract test {\n" @@ -1243,6 +1304,7 @@ BOOST_AUTO_TEST_CASE(constructor_arguments) contract Helper { string3 name; bool flag; + function Helper(string3 x, bool f) { name = x; flag = f; From 1a6dbeff6e86d65cae6d7db366cbaa4182eaff7f Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 15 Jan 2015 17:25:50 +0100 Subject: [PATCH 02/34] Squashed 'libjsqrc/ethereumjs/' changes from ab745d3..ec74fc0 ec74fc0 gulp 46b932c negative integers support f85f77f fixed typos 6a4b4f3 fixed readme d0473d6 gulp 70bf1a5 fixed typos bacc5aa methodExists and propertyExists are now separated tests 472ad43 more comments 603c790 next part of abi.js parsers tests and fixes b0a9bbf next part of abi.js docs 6b2ec23 formatting bool tests and fixes ed1cb9e simplifid abi.js methods 17f2f12 gulp 12bdb5f providers documentation 8d1f96c few comments 422dc05 ProviderManager separated to providermanager.js file 9a8f45e Filter separated to filter.js file 8b7d4b0 beginning of comments in web3 ee167e5 test for parsing multiple methods description 4056c04 tests... 1428dce web3.contract -> web3.eth.contract f3b71a7 removed unused line 380d986 tests in progress, fixed utf characters conversion in toAscii 9e0de57 mocha test reporter f6ff1f1 mocha reporter name starts with lower case letter 7595a5d removed padding calculation from ethereum.js, padding is always 32 9a9987a Merge commit 'a1023a5dffee7c06e8b75a21f5c9b8826e820942' into develop 5582901 Various fixes to ethereum.js and client web API stuff. ded221f Merge commit 'ab745d3b0eb89d67db1ed953020c665be3d072ed' into develop git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: ec74fc05d438806ece64fe34b0f28c8f45f5167e --- README.md | 8 +- dist/ethereum.js | 724 +++++++++++++++++++++++++++-------------- dist/ethereum.js.map | 22 +- dist/ethereum.min.js | 2 +- example/contract.html | 2 +- index.js | 2 +- lib/abi.js | 209 ++++++------ lib/autoprovider.js | 13 + lib/contract.js | 29 +- lib/filter.js | 89 +++++ lib/httprpc.js | 32 ++ lib/providermanager.js | 122 +++++++ lib/qt.js | 12 + lib/web3.js | 180 +++------- lib/websocket.js | 24 +- test/abi.parsers.js | 550 +++++++++++++++++++++++++++++-- test/db.methods.js | 10 +- test/eth.methods.js | 52 ++- test/mocha.opts | 2 +- test/shh.methods.js | 12 +- test/utils.js | 8 +- test/web3.methods.js | 14 +- 22 files changed, 1549 insertions(+), 569 deletions(-) create mode 100644 lib/filter.js create mode 100644 lib/providermanager.js diff --git a/README.md b/README.md index f18d382bd..bb6967ce0 100644 --- a/README.md +++ b/README.md @@ -66,16 +66,16 @@ sudo apt-get install npm sudo apt-get install nodejs-legacy ``` -## Building +### Building (gulp) -```bash (gulp) +```bash npm run-script build ``` -### Testing +### Testing (mocha) -```bash (mocha) +```bash npm test ``` diff --git a/dist/ethereum.js b/dist/ethereum.js index cf2492997..f4e0e6eac 100644 --- a/dist/ethereum.js +++ b/dist/ethereum.js @@ -36,6 +36,10 @@ var decToHex = function (dec) { return parseInt(dec).toString(16); }; +/// Finds first index of array element matching pattern +/// @param array +/// @param callback pattern +/// @returns index of element var findIndex = function (array, callback) { var end = false; var i = 0; @@ -45,94 +49,96 @@ var findIndex = function (array, callback) { return end ? i - 1 : -1; }; +/// @returns a function that is used as a pattern for 'findIndex' var findMethodIndex = function (json, methodName) { return findIndex(json, function (method) { return method.name === methodName; }); }; -var padLeft = function (string, chars) { - return new Array(chars - string.length + 1).join("0") + string; +/// @param string string to be padded +/// @param number of characters that result string should have +/// @param sign, by default 0 +/// @returns right aligned string +var padLeft = function (string, chars, sign) { + return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; }; -var calcBitPadding = function (type, expected) { - var value = type.slice(expected.length); - if (value === "") { - return 32; - } - return parseInt(value) / 8; -}; - -var calcBytePadding = function (type, expected) { - var value = type.slice(expected.length); - if (value === "") { - return 32; - } - return parseInt(value); +/// @param expected type prefix (string) +/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false +var prefixedType = function (prefix) { + return function (type) { + return type.indexOf(prefix) === 0; + }; }; -var calcRealPadding = function (type, expected) { - var value = type.slice(expected.length); - if (value === "") { - return 32; - } - var sizes = value.split('x'); - for (var padding = 0, i = 0; i < sizes; i++) { - padding += (sizes[i] / 8); - } - return padding; +/// @param expected type name (string) +/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false +var namedType = function (name) { + return function (type) { + return name === type; + }; }; +/// Setups input formatters for solidity types +/// @returns an array of input formatters var setupInputTypes = function () { - var prefixedType = function (prefix, calcPadding) { - return function (type, value) { - var expected = prefix; - if (type.indexOf(expected) !== 0) { - return false; + /// Formats input value to byte representation of int + /// @returns right-aligned byte representation of int + var formatInt = function (value) { + var padding = 32 * 2; + if (typeof value === 'number') { + if (value < 0) { + + // two's complement + // TODO: fix big numbers support + value = ((value) >>> 0).toString(16); + return padLeft(value, padding, 'f'); } + value = value.toString(16); - var padding = calcPadding(type, expected); - if (typeof value === "number") - value = value.toString(16); - else if (typeof value === "string") - value = web3.toHex(value); - else if (value.indexOf('0x') === 0) - value = value.substr(2); - else - value = (+value).toString(16); - return padLeft(value, padding * 2); - }; + } + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else if (typeof value === 'string') + value = value.toHex(value); + else + value = (+value).toString(16); + return padLeft(value, padding); }; - var namedType = function (name, padding, formatter) { - return function (type, value) { - if (type !== name) { - return false; - } - - return padLeft(formatter ? formatter(value) : value, padding * 2); - }; + /// Formats input value to byte representation of string + /// @returns left-algined byte representation of string + var formatString = function (value) { + return web3.fromAscii(value, 32).substr(2); }; + /// Formats input value to byte representation of bool + /// @returns right-aligned byte representation bool var formatBool = function (value) { - return value ? '0x1' : '0x0'; + return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); }; return [ - prefixedType('uint', calcBitPadding), - prefixedType('int', calcBitPadding), - prefixedType('hash', calcBitPadding), - prefixedType('string', calcBytePadding), - prefixedType('real', calcRealPadding), - prefixedType('ureal', calcRealPadding), - namedType('address', 20), - namedType('bool', 1, formatBool), + { type: prefixedType('uint'), format: formatInt }, + { type: prefixedType('int'), format: formatInt }, + { type: prefixedType('hash'), format: formatInt }, + { type: prefixedType('string'), format: formatString }, + { type: prefixedType('real'), format: formatInt }, + { type: prefixedType('ureal'), format: formatInt }, + { type: namedType('address'), format: formatInt }, + { type: namedType('bool'), format: formatBool } ]; }; var inputTypes = setupInputTypes(); +/// Formats input params to bytes +/// @param contract json abi +/// @param name of the method that we want to use +/// @param array of params that will be formatted to bytes +/// @returns bytes representation of input params var toAbiInput = function (json, methodName, params) { var bytes = ""; var index = findMethodIndex(json, methodName); @@ -142,70 +148,72 @@ var toAbiInput = function (json, methodName, params) { } var method = json[index]; + var padding = 32 * 2; for (var i = 0; i < method.inputs.length; i++) { - var found = false; - for (var j = 0; j < inputTypes.length && !found; j++) { - found = inputTypes[j](method.inputs[i].type, params[i]); + var typeMatch = false; + for (var j = 0; j < inputTypes.length && !typeMatch; j++) { + typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]); } - if (!found) { - console.error('unsupported json type: ' + method.inputs[i].type); + if (!typeMatch) { + console.error('input parser does not support type: ' + method.inputs[i].type); } - bytes += found; + + var formatter = inputTypes[j - 1].format; + bytes += (formatter ? formatter(params[i]) : params[i]); } return bytes; }; +/// Setups output formaters for solidity types +/// @returns an array of output formatters var setupOutputTypes = function () { - var prefixedType = function (prefix, calcPadding) { - return function (type) { - var expected = prefix; - if (type.indexOf(expected) !== 0) { - return -1; - } - - var padding = calcPadding(type, expected); - return padding * 2; - }; - }; - - var namedType = function (name, padding) { - return function (type) { - return name === type ? padding * 2 : -1; - }; - }; - + /// Formats input right-aligned input bytes to int + /// @returns right-aligned input bytes formatted to int var formatInt = function (value) { return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); }; + /// @returns right-aligned input bytes formatted to hex var formatHash = function (value) { return "0x" + value; }; + /// @returns right-aligned input bytes formatted to bool var formatBool = function (value) { - return value === '1' ? true : false; + return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; }; + /// @returns left-aligned input bytes formatted to ascii string var formatString = function (value) { return web3.toAscii(value); }; + /// @returns right-aligned input bytes formatted to address + var formatAddress = function (value) { + return "0x" + value.slice(value.length - 40, value.length); + }; + return [ - { padding: prefixedType('uint', calcBitPadding), format: formatInt }, - { padding: prefixedType('int', calcBitPadding), format: formatInt }, - { padding: prefixedType('hash', calcBitPadding), format: formatHash }, - { padding: prefixedType('string', calcBytePadding), format: formatString }, - { padding: prefixedType('real', calcRealPadding), format: formatInt }, - { padding: prefixedType('ureal', calcRealPadding), format: formatInt }, - { padding: namedType('address', 20) }, - { padding: namedType('bool', 1), format: formatBool } + { type: prefixedType('uint'), format: formatInt }, + { type: prefixedType('int'), format: formatInt }, + { type: prefixedType('hash'), format: formatHash }, + { type: prefixedType('string'), format: formatString }, + { type: prefixedType('real'), format: formatInt }, + { type: prefixedType('ureal'), format: formatInt }, + { type: namedType('address'), format: formatAddress }, + { type: namedType('bool'), format: formatBool } ]; }; var outputTypes = setupOutputTypes(); +/// Formats output bytes back to param list +/// @param contract json abi +/// @param name of the method that we want to use +/// @param bytes representtion of output +/// @returns array of output params var fromAbiOutput = function (json, methodName, output) { var index = findMethodIndex(json, methodName); @@ -217,14 +225,16 @@ var fromAbiOutput = function (json, methodName, output) { var result = []; var method = json[index]; + var padding = 32 * 2; for (var i = 0; i < method.outputs.length; i++) { - var padding = -1; - for (var j = 0; j < outputTypes.length && padding === -1; j++) { - padding = outputTypes[j].padding(method.outputs[i].type); + var typeMatch = false; + for (var j = 0; j < outputTypes.length && !typeMatch; j++) { + typeMatch = outputTypes[j].type(method.outputs[i].type); } - if (padding === -1) { + if (!typeMatch) { // not found output parsing + console.error('output parser does not support type: ' + method.outputs[i].type); continue; } var res = output.slice(0, padding); @@ -236,6 +246,8 @@ var fromAbiOutput = function (json, methodName, output) { return result; }; +/// @param json abi for contract +/// @returns input parser object for given json abi var inputParser = function (json) { var parser = {}; json.forEach(function (method) { @@ -248,6 +260,8 @@ var inputParser = function (json) { return parser; }; +/// @param json abi for contract +/// @returns output parser for given json abi var outputParser = function (json) { var parser = {}; json.forEach(function (method) { @@ -259,6 +273,9 @@ var outputParser = function (json) { return parser; }; +/// @param json abi for contract +/// @param method name for which we want to get method signature +/// @returns (promise) contract method signature for method with given name var methodSignature = function (json, name) { var method = json[findMethodIndex(json, name)]; var result = name + '('; @@ -314,6 +331,16 @@ if ("build" !== 'build') {/* var web3 = require('./web3'); // jshint ignore:line */} +/** + * AutoProvider object prototype is implementing 'provider protocol' + * Automatically tries to setup correct provider(Qt, WebSockets or HttpRpc) + * First it checkes if we are ethereum browser (if navigator.qt object is available) + * if yes, we are using QtProvider + * if no, we check if it is possible to establish websockets connection with ethereum (ws://localhost:40404/eth is default) + * if it's not possible, we are using httprpc provider (http://localhost:8080) + * The constructor allows you to specify uris on which we are trying to connect over http or websockets + * You can do that by passing objects with fields httrpc and websockets + */ var AutoProvider = function (userOptions) { if (web3.haveProvider()) { return; @@ -362,6 +389,8 @@ var AutoProvider = function (userOptions) { }; }; +/// Sends message forward to the provider, that is being used +/// if provider is not yet set, enqueues the message AutoProvider.prototype.send = function (payload) { if (this.provider) { this.provider.send(payload); @@ -370,6 +399,7 @@ AutoProvider.prototype.send = function (payload) { this.sendQueue.push(payload); }; +/// On incoming message sends the message to the provider that is currently being used Object.defineProperty(AutoProvider.prototype, 'onmessage', { set: function (handler) { if (this.provider) { @@ -412,9 +442,29 @@ if ("build" !== 'build') {/* var abi = require('./abi'); -// method signature length in bytes +/// method signature length in bytes var ETH_METHOD_SIGNATURE_LENGTH = 4; +/** + * This method should be called when we want to call / transact some solidity method from javascript + * it returns an object which has same methods available as solidity contract description + * usage example: + * + * var abi = [{ + * name: 'myMethod', + * inputs: [{ name: 'a', type: 'string' }], + * outputs: [{name: 'd', type: 'string' }] + * }]; // contract abi + * + * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object + * + * myContract.myMethod('this is test string param for call').call(); // myMethod call + * myContract.myMethod('this is test string param for transact').transact() // myMethod transact + * + * @param address - address of the contract, which should be called + * @param desc - abi json description of the contract, which is being created + * @returns contract object + */ var contract = function (address, desc) { var inputParser = abi.inputParser(desc); var outputParser = abi.outputParser(desc); @@ -442,8 +492,10 @@ var contract = function (address, desc) { transact: function (extra) { extra = extra || {}; extra.to = address; - extra.data = parsed; - return web3.eth.transact(extra).then(onSuccess); + return abi.methodSignature(desc, method.name).then(function (signature) { + extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed; + return web3.eth.transact(extra).then(onSuccess); + }); } }; }; @@ -454,6 +506,7 @@ var contract = function (address, desc) { module.exports = contract; + },{"./abi":1}],4:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -471,6 +524,97 @@ module.exports = contract; You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ +/** @file filter.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * Gav Wood + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var web3 = require('./web3'); // jshint ignore:line +*/} + +/// should be used when we want to watch something +/// it's using inner polling mechanism and is notified about changes +var Filter = function(options, impl) { + this.impl = impl; + this.callbacks = []; + + var self = this; + this.promise = impl.newFilter(options); + this.promise.then(function (id) { + self.id = id; + web3.on(impl.changed, id, self.trigger.bind(self)); + web3.provider.startPolling({call: impl.changed, args: [id]}, id); + }); +}; + +/// alias for changed* +Filter.prototype.arrived = function(callback) { + this.changed(callback); +}; + +/// gets called when there is new eth/shh message +Filter.prototype.changed = function(callback) { + var self = this; + this.promise.then(function(id) { + self.callbacks.push(callback); + }); +}; + +/// trigger calling new message from people +Filter.prototype.trigger = function(messages) { + for(var i = 0; i < this.callbacks.length; i++) { + this.callbacks[i].call(this, messages); + } +}; + +/// should be called to uninstall current filter +Filter.prototype.uninstall = function() { + var self = this; + this.promise.then(function (id) { + self.impl.uninstallFilter(id); + web3.provider.stopPolling(id); + web3.off(impl.changed, id); + }); +}; + +/// should be called to manually trigger getting latest messages from the client +Filter.prototype.messages = function() { + var self = this; + return this.promise.then(function (id) { + return self.impl.getMessages(id); + }); +}; + +/// alias for messages +Filter.prototype.logs = function () { + return this.messages(); +}; + +module.exports = Filter; + +},{}],5:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ /** @file httprpc.js * @authors: * Marek Kotewicz @@ -483,11 +627,21 @@ if ("build" !== 'build') {/* var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line */} +/** + * HttpRpcProvider object prototype is implementing 'provider protocol' + * Should be used when we want to connect to ethereum backend over http && jsonrpc + * It's compatible with cpp client + * The contructor allows to specify host uri + * This provider is using in-browser polling mechanism + */ var HttpRpcProvider = function (host) { this.handlers = []; this.host = host; }; +/// Transforms inner message to proper jsonrpc object +/// @param inner message object +/// @returns jsonrpc object function formatJsonRpcObject(object) { return { jsonrpc: '2.0', @@ -497,6 +651,9 @@ function formatJsonRpcObject(object) { }; } +/// Transforms jsonrpc object to inner message +/// @param incoming jsonrpc message +/// @returns inner message object function formatJsonRpcMessage(message) { var object = JSON.parse(message); @@ -507,6 +664,10 @@ function formatJsonRpcMessage(message) { }; } +/// Prototype object method +/// Asynchronously sends request to server +/// @param payload is inner message object +/// @param cb is callback which is being called when response is comes back HttpRpcProvider.prototype.sendRequest = function (payload, cb) { var data = formatJsonRpcObject(payload); @@ -520,6 +681,11 @@ HttpRpcProvider.prototype.sendRequest = function (payload, cb) { }; }; +/// Prototype object method +/// Should be called when we want to send single api request to server +/// Asynchronous +/// On response it passes message to handlers +/// @param payload is inner message object HttpRpcProvider.prototype.send = function (payload) { var self = this; this.sendRequest(payload, function (request) { @@ -529,6 +695,13 @@ HttpRpcProvider.prototype.send = function (payload) { }); }; +/// Prototype object method +/// Should be called only for polling requests +/// Asynchronous +/// On response it passege message to handlers, but only if message's result is true or not empty array +/// Otherwise response is being silently ignored +/// @param payload is inner message object +/// @id is id of poll that we are calling HttpRpcProvider.prototype.poll = function (payload, id) { var self = this; this.sendRequest(payload, function (request) { @@ -542,6 +715,8 @@ HttpRpcProvider.prototype.poll = function (payload, id) { }); }; +/// Prototype object property +/// Should be used to set message handlers for this provider Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { set: function (handler) { this.handlers.push(handler); @@ -550,7 +725,132 @@ Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { module.exports = HttpRpcProvider; -},{}],5:[function(require,module,exports){ + +},{}],6:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file providermanager.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * Gav Wood + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if ("build" !== 'build') {/* + var web3 = require('./web3'); // jshint ignore:line +*/} + +/** + * Provider manager object prototype + * It's responsible for passing messages to providers + * If no provider is set it's responsible for queuing requests + * It's also responsible for polling the ethereum node for incoming messages + * Default poll timeout is 12 seconds + * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling, + * and provider manager polling mechanism is not used + */ +var ProviderManager = function() { + this.queued = []; + this.polls = []; + this.ready = false; + this.provider = undefined; + this.id = 1; + + var self = this; + var poll = function () { + if (self.provider && self.provider.poll) { + self.polls.forEach(function (data) { + data.data._id = self.id; + self.id++; + self.provider.poll(data.data, data.id); + }); + } + setTimeout(poll, 12000); + }; + poll(); +}; + +/// sends outgoing requests, if provider is not available, enqueue the request +ProviderManager.prototype.send = function(data, cb) { + data._id = this.id; + if (cb) { + web3._callbacks[data._id] = cb; + } + + data.args = data.args || []; + this.id++; + + if(this.provider !== undefined) { + this.provider.send(data); + } else { + console.warn("provider is not set"); + this.queued.push(data); + } +}; + +/// setups provider, which will be used for sending messages +ProviderManager.prototype.set = function(provider) { + if(this.provider !== undefined && this.provider.unload !== undefined) { + this.provider.unload(); + } + + this.provider = provider; + this.ready = true; +}; + +/// resends queued messages +ProviderManager.prototype.sendQueued = function() { + for(var i = 0; this.queued.length; i++) { + // Resend + this.send(this.queued[i]); + } +}; + +/// @returns true if the provider i properly set +ProviderManager.prototype.installed = function() { + return this.provider !== undefined; +}; + +/// this method is only used, when we do not have native qt bindings and have to do polling on our own +/// should be callled, on start watching for eth/shh changes +ProviderManager.prototype.startPolling = function (data, pollId) { + if (!this.provider || !this.provider.poll) { + return; + } + this.polls.push({data: data, id: pollId}); +}; + +/// should be called to stop polling for certain watch changes +ProviderManager.prototype.stopPolling = function (pollId) { + for (var i = this.polls.length; i--;) { + var poll = this.polls[i]; + if (poll.id === pollId) { + this.polls.splice(i, 1); + } + } +}; + +module.exports = ProviderManager; + + +},{}],7:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -574,6 +874,11 @@ module.exports = HttpRpcProvider; * @date 2014 */ +/** + * QtProvider object prototype is implementing 'provider protocol' + * Should be used inside ethereum browser. It's compatible with cpp and go clients. + * It uses navigator.qt object to pass the messages to native bindings + */ var QtProvider = function() { this.handlers = []; @@ -585,10 +890,17 @@ var QtProvider = function() { }; }; +/// Prototype object method +/// Should be called when we want to send single api request to native bindings +/// Asynchronous +/// Response will be received by navigator.qt.onmessage method and passed to handlers +/// @param payload is inner message object QtProvider.prototype.send = function(payload) { navigator.qt.postMessage(JSON.stringify(payload)); }; +/// Prototype object property +/// Should be used to set message handlers for this provider Object.defineProperty(QtProvider.prototype, "onmessage", { set: function(handler) { this.handlers.push(handler); @@ -597,7 +909,7 @@ Object.defineProperty(QtProvider.prototype, "onmessage", { module.exports = QtProvider; -},{}],6:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -614,7 +926,7 @@ module.exports = QtProvider; You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** @file main.js +/** @file web3.js * @authors: * Jeffrey Wilcke * Marek Kotewicz @@ -623,6 +935,12 @@ module.exports = QtProvider; * @date 2014 */ +var Filter = require('./filter'); +var ProviderManager = require('./providermanager'); + +/// Recursively resolves all promises in given object and replaces the resolved values with promises +/// @param any object/array/promise/anything else.. +/// @returns (resolves) object with replaced promises with their result function flattenPromise (obj) { if (obj instanceof Promise) { return Promise.resolve(obj); @@ -662,12 +980,14 @@ function flattenPromise (obj) { return Promise.resolve(obj); } +/// @returns an array of objects describing web3 api methods var web3Methods = function () { return [ { name: 'sha3', call: 'web3_sha3' } ]; }; +/// @returns an array of objects describing web3.eth api methods var ethMethods = function () { var blockCall = function (args) { return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; @@ -701,6 +1021,7 @@ var ethMethods = function () { return methods; }; +/// @returns an array of objects describing web3.eth api properties var ethProperties = function () { return [ { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, @@ -715,6 +1036,7 @@ var ethProperties = function () { ]; }; +/// @returns an array of objects describing web3.db api methods var dbMethods = function () { return [ { name: 'put', call: 'db_put' }, @@ -724,6 +1046,7 @@ var dbMethods = function () { ]; }; +/// @returns an array of objects describing web3.shh api methods var shhMethods = function () { return [ { name: 'post', call: 'shh_post' }, @@ -734,6 +1057,7 @@ var shhMethods = function () { ]; }; +/// @returns an array of objects describing web3.eth.watch api methods var ethWatchMethods = function () { var newFilter = function (args) { return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; @@ -746,6 +1070,7 @@ var ethWatchMethods = function () { ]; }; +/// @returns an array of objects describing web3.shh.watch api methods var shhWatchMethods = function () { return [ { name: 'newFilter', call: 'shh_newFilter' }, @@ -754,6 +1079,8 @@ var shhWatchMethods = function () { ]; }; +/// creates methods in a given object based on method description on input +/// setups api calls for these methods var setupMethods = function (obj, methods) { methods.forEach(function (method) { obj[method.name] = function () { @@ -777,6 +1104,8 @@ var setupMethods = function (obj, methods) { }); }; +/// creates properties in a given object based on properties description on input +/// setups api calls for these properties var setupProperties = function (obj, properties) { properties.forEach(function (property) { var proto = {}; @@ -821,7 +1150,7 @@ var decToHex = function (dec) { return parseInt(dec).toString(16); }; - +/// setups web3 object, and it's in-browser executed methods var web3 = { _callbacks: {}, _events: {}, @@ -837,6 +1166,7 @@ var web3 = { return hex; }, + /// @returns ascii string representation of hex value prefixed with 0x toAscii: function(hex) { // Find termination var str = ""; @@ -844,17 +1174,18 @@ var web3 = { if (hex.substring(0, 2) === '0x') i = 2; for(; i < l; i+=2) { - var code = hex.charCodeAt(i); + var code = parseInt(hex.substr(i, 2), 16); if(code === 0) { break; } - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + str += String.fromCharCode(code); } return str; }, + /// @returns hex representation (prefixed by 0x) of ascii string fromAscii: function(str, pad) { pad = pad === undefined ? 0 : pad; var hex = this.toHex(str); @@ -863,14 +1194,17 @@ var web3 = { return "0x" + hex; }, + /// @returns decimal representaton of hex value prefixed by 0x toDecimal: function (val) { return hexToDec(val.substring(2)); }, + /// @returns hex representation (prefixed by 0x) of decimal value fromDecimal: function (val) { return "0x" + decToHex(val); }, + /// used to transform value/string to eth string toEth: function(str) { var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; var unit = 0; @@ -894,24 +1228,24 @@ var web3 = { return s + ' ' + units[unit]; }, + /// eth object prototype eth: { - prototype: Object(), // jshint ignore:line watch: function (params) { return new Filter(params, ethWatch); } }, - db: { - prototype: Object() // jshint ignore:line - }, + /// db object prototype + db: {}, + /// shh object prototype shh: { - prototype: Object(), // jshint ignore:line watch: function (params) { return new Filter(params, shhWatch); } }, + /// used by filter to register callback with given id on: function(event, id, cb) { if(web3._events[event] === undefined) { web3._events[event] = {}; @@ -921,6 +1255,7 @@ var web3 = { return this; }, + /// used by filter to unregister callback with given id off: function(event, id) { if(web3._events[event] !== undefined) { delete web3._events[event][id]; @@ -929,6 +1264,7 @@ var web3 = { return this; }, + /// used to trigger callback registered by filter trigger: function(event, id, data) { var callbacks = web3._events[event]; if (!callbacks || !callbacks[id]) { @@ -936,9 +1272,15 @@ var web3 = { } var cb = callbacks[id]; cb(data); + }, + + /// @returns true if provider is installed + haveProvider: function() { + return !!web3.provider.provider; } }; +/// setups all api methods setupMethods(web3, web3Methods()); setupMethods(web3.eth, ethMethods()); setupProperties(web3.eth, ethProperties()); @@ -948,85 +1290,14 @@ setupMethods(web3.shh, shhMethods()); var ethWatch = { changed: 'eth_changed' }; + setupMethods(ethWatch, ethWatchMethods()); + var shhWatch = { changed: 'shh_changed' }; -setupMethods(shhWatch, shhWatchMethods()); - -var ProviderManager = function() { - this.queued = []; - this.polls = []; - this.ready = false; - this.provider = undefined; - this.id = 1; - - var self = this; - var poll = function () { - if (self.provider && self.provider.poll) { - self.polls.forEach(function (data) { - data.data._id = self.id; - self.id++; - self.provider.poll(data.data, data.id); - }); - } - setTimeout(poll, 12000); - }; - poll(); -}; - -ProviderManager.prototype.send = function(data, cb) { - data._id = this.id; - if (cb) { - web3._callbacks[data._id] = cb; - } - - data.args = data.args || []; - this.id++; - - if(this.provider !== undefined) { - this.provider.send(data); - } else { - console.warn("provider is not set"); - this.queued.push(data); - } -}; - -ProviderManager.prototype.set = function(provider) { - if(this.provider !== undefined && this.provider.unload !== undefined) { - this.provider.unload(); - } - - this.provider = provider; - this.ready = true; -}; - -ProviderManager.prototype.sendQueued = function() { - for(var i = 0; this.queued.length; i++) { - // Resend - this.send(this.queued[i]); - } -}; - -ProviderManager.prototype.installed = function() { - return this.provider !== undefined; -}; - -ProviderManager.prototype.startPolling = function (data, pollId) { - if (!this.provider || !this.provider.poll) { - return; - } - this.polls.push({data: data, id: pollId}); -}; -ProviderManager.prototype.stopPolling = function (pollId) { - for (var i = this.polls.length; i--;) { - var poll = this.polls[i]; - if (poll.id === pollId) { - this.polls.splice(i, 1); - } - } -}; +setupMethods(shhWatch, shhWatchMethods()); web3.provider = new ProviderManager(); @@ -1036,60 +1307,7 @@ web3.setProvider = function(provider) { web3.provider.sendQueued(); }; -web3.haveProvider = function() { - return !!web3.provider.provider; -}; - -var Filter = function(options, impl) { - this.impl = impl; - this.callbacks = []; - - var self = this; - this.promise = impl.newFilter(options); - this.promise.then(function (id) { - self.id = id; - web3.on(impl.changed, id, self.trigger.bind(self)); - web3.provider.startPolling({call: impl.changed, args: [id]}, id); - }); -}; - -Filter.prototype.arrived = function(callback) { - this.changed(callback); -}; - -Filter.prototype.changed = function(callback) { - var self = this; - this.promise.then(function(id) { - self.callbacks.push(callback); - }); -}; - -Filter.prototype.trigger = function(messages) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); - } -}; - -Filter.prototype.uninstall = function() { - var self = this; - this.promise.then(function (id) { - self.impl.uninstallFilter(id); - web3.provider.stopPolling(id); - web3.off(impl.changed, id); - }); -}; - -Filter.prototype.messages = function() { - var self = this; - return this.promise.then(function (id) { - return self.impl.getMessages(id); - }); -}; - -Filter.prototype.logs = function () { - return this.messages(); -}; - +/// callled when there is new incoming message function messageHandler(data) { if(data._event !== undefined) { web3.trigger(data._event, data._id, data.data); @@ -1108,7 +1326,7 @@ function messageHandler(data) { if (typeof(module) !== "undefined") module.exports = web3; -},{}],7:[function(require,module,exports){ +},{"./filter":4,"./providermanager":6}],9:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1138,9 +1356,17 @@ if ("build" !== 'build') {/* var WebSocket = require('ws'); // jshint ignore:line */} +/** + * WebSocketProvider object prototype is implementing 'provider protocol' + * Should be used when we want to connect to ethereum backend over websockets + * It's compatible with go client + * The constructor allows to specify host uri + */ var WebSocketProvider = function(host) { + // onmessage handlers this.handlers = []; + // queue will be filled with messages if send is invoked before the ws is ready this.queued = []; this.ready = false; @@ -1157,15 +1383,20 @@ var WebSocketProvider = function(host) { this.ws.onopen = function() { self.ready = true; - for(var i = 0; i < self.queued.length; i++) { + for (var i = 0; i < self.queued.length; i++) { // Resend self.send(self.queued[i]); } }; }; +/// Prototype object method +/// Should be called when we want to send single api request to server +/// Asynchronous, it's using websockets +/// Response for the call will be received by ws.onmessage +/// @param payload is inner message object WebSocketProvider.prototype.send = function(payload) { - if(this.ready) { + if (this.ready) { var data = JSON.stringify(payload); this.ws.send(data); @@ -1174,13 +1405,20 @@ WebSocketProvider.prototype.send = function(payload) { } }; +/// Prototype object method +/// Should be called to add handlers WebSocketProvider.prototype.onMessage = function(handler) { this.handlers.push(handler); }; +/// Prototype object method +/// Should be called to close websockets connection WebSocketProvider.prototype.unload = function() { this.ws.close(); }; + +/// Prototype object property +/// Should be used to set message handlers for this provider Object.defineProperty(WebSocketProvider.prototype, "onmessage", { set: function(provider) { this.onMessage(provider); } }); @@ -1194,11 +1432,11 @@ web3.providers.WebSocketProvider = require('./lib/websocket'); web3.providers.HttpRpcProvider = require('./lib/httprpc'); web3.providers.QtProvider = require('./lib/qt'); web3.providers.AutoProvider = require('./lib/autoprovider'); -web3.contract = require('./lib/contract'); +web3.eth.contract = require('./lib/contract'); module.exports = web3; -},{"./lib/autoprovider":2,"./lib/contract":3,"./lib/httprpc":4,"./lib/qt":5,"./lib/web3":6,"./lib/websocket":7}]},{},["web3"]) +},{"./lib/autoprovider":2,"./lib/contract":3,"./lib/httprpc":5,"./lib/qt":7,"./lib/web3":8,"./lib/websocket":9}]},{},["web3"]) //# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/dist/ethereum.js.map b/dist/ethereum.js.map index e875a0408..fd3768b15 100644 --- a/dist/ethereum.js.map +++ b/dist/ethereum.js.map @@ -5,25 +5,29 @@ "lib/abi.js", "lib/autoprovider.js", "lib/contract.js", + "lib/filter.js", "lib/httprpc.js", + "lib/providermanager.js", "lib/qt.js", "lib/web3.js", "lib/websocket.js", "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7fA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\nvar padLeft = function (string, chars) {\n return new Array(chars - string.length + 1).join(\"0\") + string;\n};\n\nvar calcBitPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value) / 8;\n};\n\nvar calcBytePadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value);\n};\n\nvar calcRealPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n var sizes = value.split('x');\n for (var padding = 0, i = 0; i < sizes; i++) {\n padding += (sizes[i] / 8);\n }\n return padding;\n};\n\nvar setupInputTypes = function () {\n \n var prefixedType = function (prefix, calcPadding) {\n return function (type, value) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return false;\n }\n\n var padding = calcPadding(type, expected);\n if (typeof value === \"number\")\n value = value.toString(16);\n else if (typeof value === \"string\")\n value = web3.toHex(value); \n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else\n value = (+value).toString(16);\n return padLeft(value, padding * 2);\n };\n };\n\n var namedType = function (name, padding, formatter) {\n return function (type, value) {\n if (type !== name) {\n return false;\n }\n\n return padLeft(formatter ? formatter(value) : value, padding * 2);\n };\n };\n\n var formatBool = function (value) {\n return value ? '0x1' : '0x0';\n };\n\n return [\n prefixedType('uint', calcBitPadding),\n prefixedType('int', calcBitPadding),\n prefixedType('hash', calcBitPadding),\n prefixedType('string', calcBytePadding),\n prefixedType('real', calcRealPadding),\n prefixedType('ureal', calcRealPadding),\n namedType('address', 20),\n namedType('bool', 1, formatBool),\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n var method = json[index];\n\n for (var i = 0; i < method.inputs.length; i++) {\n var found = false;\n for (var j = 0; j < inputTypes.length && !found; j++) {\n found = inputTypes[j](method.inputs[i].type, params[i]);\n }\n if (!found) {\n console.error('unsupported json type: ' + method.inputs[i].type);\n }\n bytes += found;\n }\n return bytes;\n};\n\nvar setupOutputTypes = function () {\n\n var prefixedType = function (prefix, calcPadding) {\n return function (type) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return -1;\n }\n\n var padding = calcPadding(type, expected);\n return padding * 2;\n };\n };\n\n var namedType = function (name, padding) {\n return function (type) {\n return name === type ? padding * 2 : -1;\n };\n };\n\n var formatInt = function (value) {\n return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);\n };\n\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n var formatBool = function (value) {\n return value === '1' ? true : false;\n };\n\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n return [\n { padding: prefixedType('uint', calcBitPadding), format: formatInt },\n { padding: prefixedType('int', calcBitPadding), format: formatInt },\n { padding: prefixedType('hash', calcBitPadding), format: formatHash },\n { padding: prefixedType('string', calcBytePadding), format: formatString },\n { padding: prefixedType('real', calcRealPadding), format: formatInt },\n { padding: prefixedType('ureal', calcRealPadding), format: formatInt },\n { padding: namedType('address', 20) },\n { padding: namedType('bool', 1), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n for (var i = 0; i < method.outputs.length; i++) {\n var padding = -1;\n for (var j = 0; j < outputTypes.length && padding === -1; j++) {\n padding = outputTypes[j].padding(method.outputs[i].type);\n }\n\n if (padding === -1) {\n // not found output parsing\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\nvar methodSignature = function (json, name) {\n var method = json[findMethodIndex(json, name)];\n var result = name + '(';\n var inputTypes = method.inputs.map(function (inp) {\n return inp.type;\n });\n result += inputTypes.join(',');\n result += ')';\n\n return web3.sha3(web3.fromAscii(result));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file autoprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n/*\n * @brief if qt object is available, uses QtProvider,\n * if not tries to connect over websockets\n * if it fails, it uses HttpRpcProvider\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar AutoProvider = function (userOptions) {\n if (web3.haveProvider()) {\n return;\n }\n\n // before we determine what provider we are, we have to cache request\n this.sendQueue = [];\n this.onmessageQueue = [];\n\n if (navigator.qt) {\n this.provider = new web3.providers.QtProvider();\n return;\n }\n\n userOptions = userOptions || {};\n var options = {\n httprpc: userOptions.httprpc || 'http://localhost:8080',\n websockets: userOptions.websockets || 'ws://localhost:40404/eth'\n };\n\n var self = this;\n var closeWithSuccess = function (success) {\n ws.close();\n if (success) {\n self.provider = new web3.providers.WebSocketProvider(options.websockets);\n } else {\n self.provider = new web3.providers.HttpRpcProvider(options.httprpc);\n self.poll = self.provider.poll.bind(self.provider);\n }\n self.sendQueue.forEach(function (payload) {\n self.provider(payload);\n });\n self.onmessageQueue.forEach(function (handler) {\n self.provider.onmessage = handler;\n });\n };\n\n var ws = new WebSocket(options.websockets);\n\n ws.onopen = function() {\n closeWithSuccess(true);\n };\n\n ws.onerror = function() {\n closeWithSuccess(false);\n };\n};\n\nAutoProvider.prototype.send = function (payload) {\n if (this.provider) {\n this.provider.send(payload);\n return;\n }\n this.sendQueue.push(payload);\n};\n\nObject.defineProperty(AutoProvider.prototype, 'onmessage', {\n set: function (handler) {\n if (this.provider) {\n this.provider.onmessage = handler;\n return;\n }\n this.onmessageQueue.push(handler);\n }\n});\n\nmodule.exports = AutoProvider;\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar abi = require('./abi');\n\n// method signature length in bytes\nvar ETH_METHOD_SIGNATURE_LENGTH = 4;\n\nvar contract = function (address, desc) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var contract = {};\n\n desc.forEach(function (method) {\n contract[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n var parsed = inputParser[method.name].apply(null, params);\n\n var onSuccess = function (result) {\n return outputParser[method.name](result);\n };\n\n return {\n call: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.call(extra).then(onSuccess);\n });\n },\n transact: function (extra) {\n extra = extra || {};\n extra.to = address;\n extra.data = parsed;\n return web3.eth.transact(extra).then(onSuccess);\n }\n };\n };\n });\n\n return contract;\n};\n\nmodule.exports = contract;\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httprpc.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpRpcProvider = function (host) {\n this.handlers = [];\n this.host = host;\n};\n\nfunction formatJsonRpcObject(object) {\n return {\n jsonrpc: '2.0',\n method: object.call,\n params: object.args,\n id: object._id\n };\n}\n\nfunction formatJsonRpcMessage(message) {\n var object = JSON.parse(message);\n\n return {\n _id: object.id,\n data: object.result,\n error: object.error\n };\n}\n\nHttpRpcProvider.prototype.sendRequest = function (payload, cb) {\n var data = formatJsonRpcObject(payload);\n\n var request = new XMLHttpRequest();\n request.open(\"POST\", this.host, true);\n request.send(JSON.stringify(data));\n request.onreadystatechange = function () {\n if (request.readyState === 4 && cb) {\n cb(request);\n }\n };\n};\n\nHttpRpcProvider.prototype.send = function (payload) {\n var self = this;\n this.sendRequest(payload, function (request) {\n self.handlers.forEach(function (handler) {\n handler.call(self, formatJsonRpcMessage(request.responseText));\n });\n });\n};\n\nHttpRpcProvider.prototype.poll = function (payload, id) {\n var self = this;\n this.sendRequest(payload, function (request) {\n var parsed = JSON.parse(request.responseText);\n if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) {\n return;\n }\n self.handlers.forEach(function (handler) {\n handler.call(self, {_event: payload.call, _id: id, data: parsed.result});\n });\n });\n};\n\nObject.defineProperty(HttpRpcProvider.prototype, \"onmessage\", {\n set: function (handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = HttpRpcProvider;\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file qt.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * @date 2014\n */\n\nvar QtProvider = function() {\n this.handlers = [];\n\n var self = this;\n navigator.qt.onmessage = function (message) {\n self.handlers.forEach(function (handler) {\n handler.call(self, JSON.parse(message.data));\n });\n };\n};\n\nQtProvider.prototype.send = function(payload) {\n navigator.qt.postMessage(JSON.stringify(payload));\n};\n\nObject.defineProperty(QtProvider.prototype, \"onmessage\", {\n set: function(handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = QtProvider;\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file main.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\nfunction flattenPromise (obj) {\n if (obj instanceof Promise) {\n return Promise.resolve(obj);\n }\n\n if (obj instanceof Array) {\n return new Promise(function (resolve) {\n var promises = obj.map(function (o) {\n return flattenPromise(o);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < obj.length; i++) {\n obj[i] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n if (obj instanceof Object) {\n return new Promise(function (resolve) {\n var keys = Object.keys(obj);\n var promises = keys.map(function (key) {\n return flattenPromise(obj[key]);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < keys.length; i++) {\n obj[keys[i]] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n return Promise.resolve(obj);\n}\n\nvar web3Methods = function () {\n return [\n { name: 'sha3', call: 'web3_sha3' }\n ];\n};\n\nvar ethMethods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var methods = [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' }\n ];\n return methods;\n};\n\nvar ethProperties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'account', getter: 'eth_account' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\n ];\n};\n\nvar dbMethods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\n};\n\nvar shhMethods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\n};\n\nvar ethWatchMethods = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\nvar shhWatchMethods = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessage', call: 'shh_getMessages' }\n ];\n};\n\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n obj[method.name] = function () {\n return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {\n var call = typeof method.call === \"function\" ? method.call(args) : method.call;\n return {call: call, args: args};\n }).then(function (request) {\n return new Promise(function (resolve, reject) {\n web3.provider.send(request, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function(err) {\n console.error(err);\n });\n };\n });\n};\n\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var proto = {};\n proto.get = function () {\n return new Promise(function(resolve, reject) {\n web3.provider.send({call: property.getter}, function(err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n };\n if (property.setter) {\n proto.set = function (val) {\n return flattenPromise([val]).then(function (args) {\n return new Promise(function (resolve) {\n web3.provider.send({call: property.setter, args: args}, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function (err) {\n console.error(err);\n });\n };\n }\n Object.defineProperty(obj, property.name, proto);\n });\n};\n\n// TODO: import from a dependency, don't duplicate.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n\nvar web3 = {\n _callbacks: {},\n _events: {},\n providers: {},\n\n toHex: function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n },\n\n toAscii: function(hex) {\n // Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x')\n i = 2;\n for(; i < l; i+=2) {\n var code = hex.charCodeAt(i);\n if(code === 0) {\n break;\n }\n\n str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));\n }\n\n return str;\n },\n\n fromAscii: function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = this.toHex(str);\n while(hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n },\n\n toDecimal: function (val) {\n return hexToDec(val.substring(2));\n },\n\n fromDecimal: function (val) {\n return \"0x\" + decToHex(val);\n },\n\n toEth: function(str) {\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ];\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n },\n\n eth: {\n prototype: Object(), // jshint ignore:line\n watch: function (params) {\n return new Filter(params, ethWatch);\n }\n },\n\n db: {\n prototype: Object() // jshint ignore:line\n },\n\n shh: {\n prototype: Object(), // jshint ignore:line\n watch: function (params) {\n return new Filter(params, shhWatch);\n }\n },\n\n on: function(event, id, cb) {\n if(web3._events[event] === undefined) {\n web3._events[event] = {};\n }\n\n web3._events[event][id] = cb;\n return this;\n },\n\n off: function(event, id) {\n if(web3._events[event] !== undefined) {\n delete web3._events[event][id];\n }\n\n return this;\n },\n\n trigger: function(event, id, data) {\n var callbacks = web3._events[event];\n if (!callbacks || !callbacks[id]) {\n return;\n }\n var cb = callbacks[id];\n cb(data);\n }\n};\n\nsetupMethods(web3, web3Methods());\nsetupMethods(web3.eth, ethMethods());\nsetupProperties(web3.eth, ethProperties());\nsetupMethods(web3.db, dbMethods());\nsetupMethods(web3.shh, shhMethods());\n\nvar ethWatch = {\n changed: 'eth_changed'\n};\nsetupMethods(ethWatch, ethWatchMethods());\nvar shhWatch = {\n changed: 'shh_changed'\n};\nsetupMethods(shhWatch, shhWatchMethods());\n\nvar ProviderManager = function() {\n this.queued = [];\n this.polls = [];\n this.ready = false;\n this.provider = undefined;\n this.id = 1;\n\n var self = this;\n var poll = function () {\n if (self.provider && self.provider.poll) {\n self.polls.forEach(function (data) {\n data.data._id = self.id;\n self.id++;\n self.provider.poll(data.data, data.id);\n });\n }\n setTimeout(poll, 12000);\n };\n poll();\n};\n\nProviderManager.prototype.send = function(data, cb) {\n data._id = this.id;\n if (cb) {\n web3._callbacks[data._id] = cb;\n }\n\n data.args = data.args || [];\n this.id++;\n\n if(this.provider !== undefined) {\n this.provider.send(data);\n } else {\n console.warn(\"provider is not set\");\n this.queued.push(data);\n }\n};\n\nProviderManager.prototype.set = function(provider) {\n if(this.provider !== undefined && this.provider.unload !== undefined) {\n this.provider.unload();\n }\n\n this.provider = provider;\n this.ready = true;\n};\n\nProviderManager.prototype.sendQueued = function() {\n for(var i = 0; this.queued.length; i++) {\n // Resend\n this.send(this.queued[i]);\n }\n};\n\nProviderManager.prototype.installed = function() {\n return this.provider !== undefined;\n};\n\nProviderManager.prototype.startPolling = function (data, pollId) {\n if (!this.provider || !this.provider.poll) {\n return;\n }\n this.polls.push({data: data, id: pollId});\n};\n\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nweb3.provider = new ProviderManager();\n\nweb3.setProvider = function(provider) {\n provider.onmessage = messageHandler;\n web3.provider.set(provider);\n web3.provider.sendQueued();\n};\n\nweb3.haveProvider = function() {\n return !!web3.provider.provider;\n};\n\nvar Filter = function(options, impl) {\n this.impl = impl;\n this.callbacks = [];\n\n var self = this;\n this.promise = impl.newFilter(options);\n this.promise.then(function (id) {\n self.id = id;\n web3.on(impl.changed, id, self.trigger.bind(self));\n web3.provider.startPolling({call: impl.changed, args: [id]}, id);\n });\n};\n\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\n\nFilter.prototype.changed = function(callback) {\n var self = this;\n this.promise.then(function(id) {\n self.callbacks.push(callback);\n });\n};\n\nFilter.prototype.trigger = function(messages) {\n for(var i = 0; i < this.callbacks.length; i++) {\n this.callbacks[i].call(this, messages);\n }\n};\n\nFilter.prototype.uninstall = function() {\n var self = this;\n this.promise.then(function (id) {\n self.impl.uninstallFilter(id);\n web3.provider.stopPolling(id);\n web3.off(impl.changed, id);\n });\n};\n\nFilter.prototype.messages = function() {\n var self = this;\n return this.promise.then(function (id) {\n return self.impl.getMessages(id);\n });\n};\n\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nfunction messageHandler(data) {\n if(data._event !== undefined) {\n web3.trigger(data._event, data._id, data.data);\n return;\n }\n\n if(data._id) {\n var cb = web3._callbacks[data._id];\n if (cb) {\n cb.call(this, data.error, data.data);\n delete web3._callbacks[data._id];\n }\n }\n}\n\nif (typeof(module) !== \"undefined\")\n module.exports = web3;\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file websocket.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n*/}\n\nvar WebSocketProvider = function(host) {\n // onmessage handlers\n this.handlers = [];\n // queue will be filled with messages if send is invoked before the ws is ready\n this.queued = [];\n this.ready = false;\n\n this.ws = new WebSocket(host);\n\n var self = this;\n this.ws.onmessage = function(event) {\n for(var i = 0; i < self.handlers.length; i++) {\n self.handlers[i].call(self, JSON.parse(event.data), event);\n }\n };\n\n this.ws.onopen = function() {\n self.ready = true;\n\n for(var i = 0; i < self.queued.length; i++) {\n // Resend\n self.send(self.queued[i]);\n }\n };\n};\n\nWebSocketProvider.prototype.send = function(payload) {\n if(this.ready) {\n var data = JSON.stringify(payload);\n\n this.ws.send(data);\n } else {\n this.queued.push(payload);\n }\n};\n\nWebSocketProvider.prototype.onMessage = function(handler) {\n this.handlers.push(handler);\n};\n\nWebSocketProvider.prototype.unload = function() {\n this.ws.close();\n};\nObject.defineProperty(WebSocketProvider.prototype, \"onmessage\", {\n set: function(provider) { this.onMessage(provider); }\n});\n\nif (typeof(module) !== \"undefined\")\n module.exports = WebSocketProvider;\n", - "var web3 = require('./lib/web3');\nweb3.providers.WebSocketProvider = require('./lib/websocket');\nweb3.providers.HttpRpcProvider = require('./lib/httprpc');\nweb3.providers.QtProvider = require('./lib/qt');\nweb3.providers.AutoProvider = require('./lib/autoprovider');\nweb3.contract = require('./lib/contract');\n\nmodule.exports = web3;\n" + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n/// Finds first index of array element matching pattern\n/// @param array\n/// @param callback pattern\n/// @returns index of element\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/// @returns a function that is used as a pattern for 'findIndex'\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\n/// @param string string to be padded\n/// @param number of characters that result string should have\n/// @param sign, by default 0\n/// @returns right aligned string\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/// @param expected type prefix (string)\n/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false\nvar prefixedType = function (prefix) {\n return function (type) {\n return type.indexOf(prefix) === 0;\n };\n};\n\n/// @param expected type name (string)\n/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false\nvar namedType = function (name) {\n return function (type) {\n return name === type;\n };\n};\n\n/// Setups input formatters for solidity types\n/// @returns an array of input formatters \nvar setupInputTypes = function () {\n \n /// Formats input value to byte representation of int\n /// @returns right-aligned byte representation of int\n var formatInt = function (value) {\n var padding = 32 * 2;\n if (typeof value === 'number') {\n if (value < 0) {\n \n // two's complement\n // TODO: fix big numbers support\n value = ((value) >>> 0).toString(16);\n return padLeft(value, padding, 'f');\n }\n value = value.toString(16);\n\n }\n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else if (typeof value === 'string')\n value = value.toHex(value);\n else\n value = (+value).toString(16);\n return padLeft(value, padding);\n };\n\n /// Formats input value to byte representation of string\n /// @returns left-algined byte representation of string\n var formatString = function (value) {\n return web3.fromAscii(value, 32).substr(2);\n };\n\n /// Formats input value to byte representation of bool\n /// @returns right-aligned byte representation bool\n var formatBool = function (value) {\n return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n };\n\n return [\n { type: prefixedType('uint'), format: formatInt },\n { type: prefixedType('int'), format: formatInt },\n { type: prefixedType('hash'), format: formatInt },\n { type: prefixedType('string'), format: formatString }, \n { type: prefixedType('real'), format: formatInt },\n { type: prefixedType('ureal'), format: formatInt },\n { type: namedType('address'), format: formatInt },\n { type: namedType('bool'), format: formatBool }\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\n/// Formats input params to bytes\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n var method = json[index];\n var padding = 32 * 2;\n\n for (var i = 0; i < method.inputs.length; i++) {\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n console.error('input parser does not support type: ' + method.inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n bytes += (formatter ? formatter(params[i]) : params[i]);\n }\n return bytes;\n};\n\n/// Setups output formaters for solidity types\n/// @returns an array of output formatters\nvar setupOutputTypes = function () {\n\n /// Formats input right-aligned input bytes to int\n /// @returns right-aligned input bytes formatted to int\n var formatInt = function (value) {\n return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);\n };\n\n /// @returns right-aligned input bytes formatted to hex\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n /// @returns right-aligned input bytes formatted to bool\n var formatBool = function (value) {\n return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n };\n\n /// @returns left-aligned input bytes formatted to ascii string\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n /// @returns right-aligned input bytes formatted to address\n var formatAddress = function (value) {\n return \"0x\" + value.slice(value.length - 40, value.length);\n };\n\n return [\n { type: prefixedType('uint'), format: formatInt },\n { type: prefixedType('int'), format: formatInt },\n { type: prefixedType('hash'), format: formatHash },\n { type: prefixedType('string'), format: formatString },\n { type: prefixedType('real'), format: formatInt },\n { type: prefixedType('ureal'), format: formatInt },\n { type: namedType('address'), format: formatAddress },\n { type: namedType('bool'), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\n/// Formats output bytes back to param list\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param bytes representtion of output \n/// @returns array of output params \nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n var padding = 32 * 2;\n for (var i = 0; i < method.outputs.length; i++) {\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(method.outputs[i].type);\n }\n\n if (!typeMatch) {\n // not found output parsing\n console.error('output parser does not support type: ' + method.outputs[i].type);\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @returns output parser for given json abi\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @param method name for which we want to get method signature\n/// @returns (promise) contract method signature for method with given name\nvar methodSignature = function (json, name) {\n var method = json[findMethodIndex(json, name)];\n var result = name + '(';\n var inputTypes = method.inputs.map(function (inp) {\n return inp.type;\n });\n result += inputTypes.join(',');\n result += ')';\n\n return web3.sha3(web3.fromAscii(result));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file autoprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n/*\n * @brief if qt object is available, uses QtProvider,\n * if not tries to connect over websockets\n * if it fails, it uses HttpRpcProvider\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n/**\n * AutoProvider object prototype is implementing 'provider protocol'\n * Automatically tries to setup correct provider(Qt, WebSockets or HttpRpc)\n * First it checkes if we are ethereum browser (if navigator.qt object is available)\n * if yes, we are using QtProvider\n * if no, we check if it is possible to establish websockets connection with ethereum (ws://localhost:40404/eth is default)\n * if it's not possible, we are using httprpc provider (http://localhost:8080)\n * The constructor allows you to specify uris on which we are trying to connect over http or websockets\n * You can do that by passing objects with fields httrpc and websockets\n */\nvar AutoProvider = function (userOptions) {\n if (web3.haveProvider()) {\n return;\n }\n\n // before we determine what provider we are, we have to cache request\n this.sendQueue = [];\n this.onmessageQueue = [];\n\n if (navigator.qt) {\n this.provider = new web3.providers.QtProvider();\n return;\n }\n\n userOptions = userOptions || {};\n var options = {\n httprpc: userOptions.httprpc || 'http://localhost:8080',\n websockets: userOptions.websockets || 'ws://localhost:40404/eth'\n };\n\n var self = this;\n var closeWithSuccess = function (success) {\n ws.close();\n if (success) {\n self.provider = new web3.providers.WebSocketProvider(options.websockets);\n } else {\n self.provider = new web3.providers.HttpRpcProvider(options.httprpc);\n self.poll = self.provider.poll.bind(self.provider);\n }\n self.sendQueue.forEach(function (payload) {\n self.provider(payload);\n });\n self.onmessageQueue.forEach(function (handler) {\n self.provider.onmessage = handler;\n });\n };\n\n var ws = new WebSocket(options.websockets);\n\n ws.onopen = function() {\n closeWithSuccess(true);\n };\n\n ws.onerror = function() {\n closeWithSuccess(false);\n };\n};\n\n/// Sends message forward to the provider, that is being used\n/// if provider is not yet set, enqueues the message\nAutoProvider.prototype.send = function (payload) {\n if (this.provider) {\n this.provider.send(payload);\n return;\n }\n this.sendQueue.push(payload);\n};\n\n/// On incoming message sends the message to the provider that is currently being used\nObject.defineProperty(AutoProvider.prototype, 'onmessage', {\n set: function (handler) {\n if (this.provider) {\n this.provider.onmessage = handler;\n return;\n }\n this.onmessageQueue.push(handler);\n }\n});\n\nmodule.exports = AutoProvider;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar abi = require('./abi');\n\n/// method signature length in bytes\nvar ETH_METHOD_SIGNATURE_LENGTH = 4;\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object\n *\n * myContract.myMethod('this is test string param for call').call(); // myMethod call\n * myContract.myMethod('this is test string param for transact').transact() // myMethod transact\n *\n * @param address - address of the contract, which should be called\n * @param desc - abi json description of the contract, which is being created\n * @returns contract object\n */\nvar contract = function (address, desc) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var contract = {};\n\n desc.forEach(function (method) {\n contract[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n var parsed = inputParser[method.name].apply(null, params);\n\n var onSuccess = function (result) {\n return outputParser[method.name](result);\n };\n\n return {\n call: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.call(extra).then(onSuccess);\n });\n },\n transact: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.transact(extra).then(onSuccess);\n });\n }\n };\n };\n });\n\n return contract;\n};\n\nmodule.exports = contract;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n/// should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\nvar Filter = function(options, impl) {\n this.impl = impl;\n this.callbacks = [];\n\n var self = this;\n this.promise = impl.newFilter(options);\n this.promise.then(function (id) {\n self.id = id;\n web3.on(impl.changed, id, self.trigger.bind(self));\n web3.provider.startPolling({call: impl.changed, args: [id]}, id);\n });\n};\n\n/// alias for changed*\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\n\n/// gets called when there is new eth/shh message\nFilter.prototype.changed = function(callback) {\n var self = this;\n this.promise.then(function(id) {\n self.callbacks.push(callback);\n });\n};\n\n/// trigger calling new message from people\nFilter.prototype.trigger = function(messages) {\n for(var i = 0; i < this.callbacks.length; i++) {\n this.callbacks[i].call(this, messages);\n }\n};\n\n/// should be called to uninstall current filter\nFilter.prototype.uninstall = function() {\n var self = this;\n this.promise.then(function (id) {\n self.impl.uninstallFilter(id);\n web3.provider.stopPolling(id);\n web3.off(impl.changed, id);\n });\n};\n\n/// should be called to manually trigger getting latest messages from the client\nFilter.prototype.messages = function() {\n var self = this;\n return this.promise.then(function (id) {\n return self.impl.getMessages(id);\n });\n};\n\n/// alias for messages\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nmodule.exports = Filter;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httprpc.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\n/**\n * HttpRpcProvider object prototype is implementing 'provider protocol'\n * Should be used when we want to connect to ethereum backend over http && jsonrpc\n * It's compatible with cpp client\n * The contructor allows to specify host uri\n * This provider is using in-browser polling mechanism\n */\nvar HttpRpcProvider = function (host) {\n this.handlers = [];\n this.host = host;\n};\n\n/// Transforms inner message to proper jsonrpc object\n/// @param inner message object\n/// @returns jsonrpc object\nfunction formatJsonRpcObject(object) {\n return {\n jsonrpc: '2.0',\n method: object.call,\n params: object.args,\n id: object._id\n };\n}\n\n/// Transforms jsonrpc object to inner message\n/// @param incoming jsonrpc message \n/// @returns inner message object\nfunction formatJsonRpcMessage(message) {\n var object = JSON.parse(message);\n\n return {\n _id: object.id,\n data: object.result,\n error: object.error\n };\n}\n\n/// Prototype object method \n/// Asynchronously sends request to server\n/// @param payload is inner message object\n/// @param cb is callback which is being called when response is comes back\nHttpRpcProvider.prototype.sendRequest = function (payload, cb) {\n var data = formatJsonRpcObject(payload);\n\n var request = new XMLHttpRequest();\n request.open(\"POST\", this.host, true);\n request.send(JSON.stringify(data));\n request.onreadystatechange = function () {\n if (request.readyState === 4 && cb) {\n cb(request);\n }\n };\n};\n\n/// Prototype object method\n/// Should be called when we want to send single api request to server\n/// Asynchronous\n/// On response it passes message to handlers\n/// @param payload is inner message object\nHttpRpcProvider.prototype.send = function (payload) {\n var self = this;\n this.sendRequest(payload, function (request) {\n self.handlers.forEach(function (handler) {\n handler.call(self, formatJsonRpcMessage(request.responseText));\n });\n });\n};\n\n/// Prototype object method\n/// Should be called only for polling requests\n/// Asynchronous\n/// On response it passege message to handlers, but only if message's result is true or not empty array\n/// Otherwise response is being silently ignored\n/// @param payload is inner message object\n/// @id is id of poll that we are calling\nHttpRpcProvider.prototype.poll = function (payload, id) {\n var self = this;\n this.sendRequest(payload, function (request) {\n var parsed = JSON.parse(request.responseText);\n if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) {\n return;\n }\n self.handlers.forEach(function (handler) {\n handler.call(self, {_event: payload.call, _id: id, data: parsed.result});\n });\n });\n};\n\n/// Prototype object property\n/// Should be used to set message handlers for this provider\nObject.defineProperty(HttpRpcProvider.prototype, \"onmessage\", {\n set: function (handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = HttpRpcProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file providermanager.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n/**\n * Provider manager object prototype\n * It's responsible for passing messages to providers\n * If no provider is set it's responsible for queuing requests\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 12 seconds\n * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,\n * and provider manager polling mechanism is not used\n */\nvar ProviderManager = function() {\n this.queued = [];\n this.polls = [];\n this.ready = false;\n this.provider = undefined;\n this.id = 1;\n\n var self = this;\n var poll = function () {\n if (self.provider && self.provider.poll) {\n self.polls.forEach(function (data) {\n data.data._id = self.id;\n self.id++;\n self.provider.poll(data.data, data.id);\n });\n }\n setTimeout(poll, 12000);\n };\n poll();\n};\n\n/// sends outgoing requests, if provider is not available, enqueue the request\nProviderManager.prototype.send = function(data, cb) {\n data._id = this.id;\n if (cb) {\n web3._callbacks[data._id] = cb;\n }\n\n data.args = data.args || [];\n this.id++;\n\n if(this.provider !== undefined) {\n this.provider.send(data);\n } else {\n console.warn(\"provider is not set\");\n this.queued.push(data);\n }\n};\n\n/// setups provider, which will be used for sending messages\nProviderManager.prototype.set = function(provider) {\n if(this.provider !== undefined && this.provider.unload !== undefined) {\n this.provider.unload();\n }\n\n this.provider = provider;\n this.ready = true;\n};\n\n/// resends queued messages\nProviderManager.prototype.sendQueued = function() {\n for(var i = 0; this.queued.length; i++) {\n // Resend\n this.send(this.queued[i]);\n }\n};\n\n/// @returns true if the provider i properly set\nProviderManager.prototype.installed = function() {\n return this.provider !== undefined;\n};\n\n/// this method is only used, when we do not have native qt bindings and have to do polling on our own\n/// should be callled, on start watching for eth/shh changes\nProviderManager.prototype.startPolling = function (data, pollId) {\n if (!this.provider || !this.provider.poll) {\n return;\n }\n this.polls.push({data: data, id: pollId});\n};\n\n/// should be called to stop polling for certain watch changes\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nmodule.exports = ProviderManager;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file qt.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * @date 2014\n */\n\n/**\n * QtProvider object prototype is implementing 'provider protocol'\n * Should be used inside ethereum browser. It's compatible with cpp and go clients.\n * It uses navigator.qt object to pass the messages to native bindings\n */\nvar QtProvider = function() {\n this.handlers = [];\n\n var self = this;\n navigator.qt.onmessage = function (message) {\n self.handlers.forEach(function (handler) {\n handler.call(self, JSON.parse(message.data));\n });\n };\n};\n\n/// Prototype object method\n/// Should be called when we want to send single api request to native bindings\n/// Asynchronous\n/// Response will be received by navigator.qt.onmessage method and passed to handlers\n/// @param payload is inner message object\nQtProvider.prototype.send = function(payload) {\n navigator.qt.postMessage(JSON.stringify(payload));\n};\n\n/// Prototype object property\n/// Should be used to set message handlers for this provider\nObject.defineProperty(QtProvider.prototype, \"onmessage\", {\n set: function(handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = QtProvider;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\nvar Filter = require('./filter');\nvar ProviderManager = require('./providermanager');\n\n/// Recursively resolves all promises in given object and replaces the resolved values with promises\n/// @param any object/array/promise/anything else..\n/// @returns (resolves) object with replaced promises with their result \nfunction flattenPromise (obj) {\n if (obj instanceof Promise) {\n return Promise.resolve(obj);\n }\n\n if (obj instanceof Array) {\n return new Promise(function (resolve) {\n var promises = obj.map(function (o) {\n return flattenPromise(o);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < obj.length; i++) {\n obj[i] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n if (obj instanceof Object) {\n return new Promise(function (resolve) {\n var keys = Object.keys(obj);\n var promises = keys.map(function (key) {\n return flattenPromise(obj[key]);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < keys.length; i++) {\n obj[keys[i]] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n return Promise.resolve(obj);\n}\n\n/// @returns an array of objects describing web3 api methods\nvar web3Methods = function () {\n return [\n { name: 'sha3', call: 'web3_sha3' }\n ];\n};\n\n/// @returns an array of objects describing web3.eth api methods\nvar ethMethods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var methods = [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' }\n ];\n return methods;\n};\n\n/// @returns an array of objects describing web3.eth api properties\nvar ethProperties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'account', getter: 'eth_account' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\n ];\n};\n\n/// @returns an array of objects describing web3.db api methods\nvar dbMethods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh api methods\nvar shhMethods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\n};\n\n/// @returns an array of objects describing web3.eth.watch api methods\nvar ethWatchMethods = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shhWatchMethods = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessage', call: 'shh_getMessages' }\n ];\n};\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n obj[method.name] = function () {\n return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {\n var call = typeof method.call === \"function\" ? method.call(args) : method.call;\n return {call: call, args: args};\n }).then(function (request) {\n return new Promise(function (resolve, reject) {\n web3.provider.send(request, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function(err) {\n console.error(err);\n });\n };\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var proto = {};\n proto.get = function () {\n return new Promise(function(resolve, reject) {\n web3.provider.send({call: property.getter}, function(err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n };\n if (property.setter) {\n proto.set = function (val) {\n return flattenPromise([val]).then(function (args) {\n return new Promise(function (resolve) {\n web3.provider.send({call: property.setter, args: args}, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function (err) {\n console.error(err);\n });\n };\n }\n Object.defineProperty(obj, property.name, proto);\n });\n};\n\n// TODO: import from a dependency, don't duplicate.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {\n _callbacks: {},\n _events: {},\n providers: {},\n\n toHex: function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n },\n\n /// @returns ascii string representation of hex value prefixed with 0x\n toAscii: function(hex) {\n // Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x')\n i = 2;\n for(; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if(code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n },\n\n /// @returns hex representation (prefixed by 0x) of ascii string\n fromAscii: function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = this.toHex(str);\n while(hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n },\n\n /// @returns decimal representaton of hex value prefixed by 0x\n toDecimal: function (val) {\n return hexToDec(val.substring(2));\n },\n\n /// @returns hex representation (prefixed by 0x) of decimal value\n fromDecimal: function (val) {\n return \"0x\" + decToHex(val);\n },\n\n /// used to transform value/string to eth string\n toEth: function(str) {\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ];\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n },\n\n /// eth object prototype\n eth: {\n watch: function (params) {\n return new Filter(params, ethWatch);\n }\n },\n\n /// db object prototype\n db: {},\n\n /// shh object prototype\n shh: {\n watch: function (params) {\n return new Filter(params, shhWatch);\n }\n },\n\n /// used by filter to register callback with given id\n on: function(event, id, cb) {\n if(web3._events[event] === undefined) {\n web3._events[event] = {};\n }\n\n web3._events[event][id] = cb;\n return this;\n },\n\n /// used by filter to unregister callback with given id\n off: function(event, id) {\n if(web3._events[event] !== undefined) {\n delete web3._events[event][id];\n }\n\n return this;\n },\n\n /// used to trigger callback registered by filter\n trigger: function(event, id, data) {\n var callbacks = web3._events[event];\n if (!callbacks || !callbacks[id]) {\n return;\n }\n var cb = callbacks[id];\n cb(data);\n },\n\n /// @returns true if provider is installed\n haveProvider: function() {\n return !!web3.provider.provider;\n }\n};\n\n/// setups all api methods\nsetupMethods(web3, web3Methods());\nsetupMethods(web3.eth, ethMethods());\nsetupProperties(web3.eth, ethProperties());\nsetupMethods(web3.db, dbMethods());\nsetupMethods(web3.shh, shhMethods());\n\nvar ethWatch = {\n changed: 'eth_changed'\n};\n\nsetupMethods(ethWatch, ethWatchMethods());\n\nvar shhWatch = {\n changed: 'shh_changed'\n};\n\nsetupMethods(shhWatch, shhWatchMethods());\n\nweb3.provider = new ProviderManager();\n\nweb3.setProvider = function(provider) {\n provider.onmessage = messageHandler;\n web3.provider.set(provider);\n web3.provider.sendQueued();\n};\n\n/// callled when there is new incoming message\nfunction messageHandler(data) {\n if(data._event !== undefined) {\n web3.trigger(data._event, data._id, data.data);\n return;\n }\n\n if(data._id) {\n var cb = web3._callbacks[data._id];\n if (cb) {\n cb.call(this, data.error, data.data);\n delete web3._callbacks[data._id];\n }\n }\n}\n\nif (typeof(module) !== \"undefined\")\n module.exports = web3;\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file websocket.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n*/}\n\n/**\n * WebSocketProvider object prototype is implementing 'provider protocol'\n * Should be used when we want to connect to ethereum backend over websockets\n * It's compatible with go client\n * The constructor allows to specify host uri\n */\nvar WebSocketProvider = function(host) {\n\n // onmessage handlers\n this.handlers = [];\n\n // queue will be filled with messages if send is invoked before the ws is ready\n this.queued = [];\n this.ready = false;\n\n this.ws = new WebSocket(host);\n\n var self = this;\n this.ws.onmessage = function(event) {\n for(var i = 0; i < self.handlers.length; i++) {\n self.handlers[i].call(self, JSON.parse(event.data), event);\n }\n };\n\n this.ws.onopen = function() {\n self.ready = true;\n\n for (var i = 0; i < self.queued.length; i++) {\n // Resend\n self.send(self.queued[i]);\n }\n };\n};\n\n/// Prototype object method\n/// Should be called when we want to send single api request to server\n/// Asynchronous, it's using websockets\n/// Response for the call will be received by ws.onmessage\n/// @param payload is inner message object\nWebSocketProvider.prototype.send = function(payload) {\n if (this.ready) {\n var data = JSON.stringify(payload);\n\n this.ws.send(data);\n } else {\n this.queued.push(payload);\n }\n};\n\n/// Prototype object method\n/// Should be called to add handlers\nWebSocketProvider.prototype.onMessage = function(handler) {\n this.handlers.push(handler);\n};\n\n/// Prototype object method\n/// Should be called to close websockets connection\nWebSocketProvider.prototype.unload = function() {\n this.ws.close();\n};\n\n/// Prototype object property\n/// Should be used to set message handlers for this provider\nObject.defineProperty(WebSocketProvider.prototype, \"onmessage\", {\n set: function(provider) { this.onMessage(provider); }\n});\n\nif (typeof(module) !== \"undefined\")\n module.exports = WebSocketProvider;\n", + "var web3 = require('./lib/web3');\nweb3.providers.WebSocketProvider = require('./lib/websocket');\nweb3.providers.HttpRpcProvider = require('./lib/httprpc');\nweb3.providers.QtProvider = require('./lib/qt');\nweb3.providers.AutoProvider = require('./lib/autoprovider');\nweb3.eth.contract = require('./lib/contract');\n\nmodule.exports = web3;\n" ] } \ No newline at end of file diff --git a/dist/ethereum.min.js b/dist/ethereum.min.js index a0054b65e..f142507ee 100644 --- a/dist/ethereum.min.js +++ b/dist/ethereum.min.js @@ -1 +1 @@ -require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ai;i++)o+=r[i]/8;return o},c=function(){var t=function(t,e){return function(n,r){var o=t;if(0!==n.indexOf(o))return!1;var a=e(n,o);return r="number"==typeof r?r.toString(16):"string"==typeof r?web3.toHex(r):0===r.indexOf("0x")?r.substr(2):(+r).toString(16),i(r,2*a)}},e=function(t,e,n){return function(r,o){return r!==t?!1:i(n?n(o):o,2*e)}},n=function(t){return t?"0x1":"0x0"};return[t("uint",a),t("int",a),t("hash",a),t("string",s),t("real",u),t("ureal",u),e("address",20),e("bool",1,n)]},l=c(),h=function(t,e,n){var r="",i=o(t,e);if(-1!==i){for(var a=t[i],s=0;sn;n+=2){var o=t.charCodeAt(n);if(0===o)break;e+=String.fromCharCode(parseInt(t.substr(n,2),16))}return e},fromAscii:function(t,e){e=void 0===e?0:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return p(t.substring(2))},fromDecimal:function(t){return"0x"+d(t)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e>3e3&&nt)return t=(t>>>0).toString(16),i(t,e,"f");t=t.toString(16)}else t=0===t.indexOf("0x")?t.substr(2):"string"==typeof t?t.toHex(t):(+t).toString(16);return i(t,e)},e=function(t){return web3.fromAscii(t,32).substr(2)},n=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")};return[{type:a("uint"),format:t},{type:a("int"),format:t},{type:a("hash"),format:t},{type:a("string"),format:e},{type:a("real"),format:t},{type:a("ureal"),format:t},{type:s("address"),format:t},{type:s("bool"),format:n}]},c=u(),l=function(t,e,n){var r="",i=o(t,e);if(-1!==i){for(var a=t[i],s=0;sn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},fromAscii:function(t,e){e=void 0===e?0:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return v(t.substring(2))},fromDecimal:function(t){return"0x"+g(t)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e>3e3&&n>> 0).toString(16); + return padLeft(value, padding, 'f'); } + value = value.toString(16); - var padding = calcPadding(type, expected); - if (typeof value === "number") - value = value.toString(16); - else if (typeof value === "string") - value = web3.toHex(value); - else if (value.indexOf('0x') === 0) - value = value.substr(2); - else - value = (+value).toString(16); - return padLeft(value, padding * 2); - }; + } + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else if (typeof value === 'string') + value = value.toHex(value); + else + value = (+value).toString(16); + return padLeft(value, padding); }; - var namedType = function (name, padding, formatter) { - return function (type, value) { - if (type !== name) { - return false; - } - - return padLeft(formatter ? formatter(value) : value, padding * 2); - }; + /// Formats input value to byte representation of string + /// @returns left-algined byte representation of string + var formatString = function (value) { + return web3.fromAscii(value, 32).substr(2); }; + /// Formats input value to byte representation of bool + /// @returns right-aligned byte representation bool var formatBool = function (value) { - return value ? '0x1' : '0x0'; + return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); }; return [ - prefixedType('uint', calcBitPadding), - prefixedType('int', calcBitPadding), - prefixedType('hash', calcBitPadding), - prefixedType('string', calcBytePadding), - prefixedType('real', calcRealPadding), - prefixedType('ureal', calcRealPadding), - namedType('address', 20), - namedType('bool', 1, formatBool), + { type: prefixedType('uint'), format: formatInt }, + { type: prefixedType('int'), format: formatInt }, + { type: prefixedType('hash'), format: formatInt }, + { type: prefixedType('string'), format: formatString }, + { type: prefixedType('real'), format: formatInt }, + { type: prefixedType('ureal'), format: formatInt }, + { type: namedType('address'), format: formatInt }, + { type: namedType('bool'), format: formatBool } ]; }; var inputTypes = setupInputTypes(); +/// Formats input params to bytes +/// @param contract json abi +/// @param name of the method that we want to use +/// @param array of params that will be formatted to bytes +/// @returns bytes representation of input params var toAbiInput = function (json, methodName, params) { var bytes = ""; var index = findMethodIndex(json, methodName); @@ -141,70 +147,72 @@ var toAbiInput = function (json, methodName, params) { } var method = json[index]; + var padding = 32 * 2; for (var i = 0; i < method.inputs.length; i++) { - var found = false; - for (var j = 0; j < inputTypes.length && !found; j++) { - found = inputTypes[j](method.inputs[i].type, params[i]); + var typeMatch = false; + for (var j = 0; j < inputTypes.length && !typeMatch; j++) { + typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]); } - if (!found) { - console.error('unsupported json type: ' + method.inputs[i].type); + if (!typeMatch) { + console.error('input parser does not support type: ' + method.inputs[i].type); } - bytes += found; + + var formatter = inputTypes[j - 1].format; + bytes += (formatter ? formatter(params[i]) : params[i]); } return bytes; }; +/// Setups output formaters for solidity types +/// @returns an array of output formatters var setupOutputTypes = function () { - var prefixedType = function (prefix, calcPadding) { - return function (type) { - var expected = prefix; - if (type.indexOf(expected) !== 0) { - return -1; - } - - var padding = calcPadding(type, expected); - return padding * 2; - }; - }; - - var namedType = function (name, padding) { - return function (type) { - return name === type ? padding * 2 : -1; - }; - }; - + /// Formats input right-aligned input bytes to int + /// @returns right-aligned input bytes formatted to int var formatInt = function (value) { return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); }; + /// @returns right-aligned input bytes formatted to hex var formatHash = function (value) { return "0x" + value; }; + /// @returns right-aligned input bytes formatted to bool var formatBool = function (value) { - return value === '1' ? true : false; + return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; }; + /// @returns left-aligned input bytes formatted to ascii string var formatString = function (value) { return web3.toAscii(value); }; + /// @returns right-aligned input bytes formatted to address + var formatAddress = function (value) { + return "0x" + value.slice(value.length - 40, value.length); + }; + return [ - { padding: prefixedType('uint', calcBitPadding), format: formatInt }, - { padding: prefixedType('int', calcBitPadding), format: formatInt }, - { padding: prefixedType('hash', calcBitPadding), format: formatHash }, - { padding: prefixedType('string', calcBytePadding), format: formatString }, - { padding: prefixedType('real', calcRealPadding), format: formatInt }, - { padding: prefixedType('ureal', calcRealPadding), format: formatInt }, - { padding: namedType('address', 20) }, - { padding: namedType('bool', 1), format: formatBool } + { type: prefixedType('uint'), format: formatInt }, + { type: prefixedType('int'), format: formatInt }, + { type: prefixedType('hash'), format: formatHash }, + { type: prefixedType('string'), format: formatString }, + { type: prefixedType('real'), format: formatInt }, + { type: prefixedType('ureal'), format: formatInt }, + { type: namedType('address'), format: formatAddress }, + { type: namedType('bool'), format: formatBool } ]; }; var outputTypes = setupOutputTypes(); +/// Formats output bytes back to param list +/// @param contract json abi +/// @param name of the method that we want to use +/// @param bytes representtion of output +/// @returns array of output params var fromAbiOutput = function (json, methodName, output) { var index = findMethodIndex(json, methodName); @@ -216,14 +224,16 @@ var fromAbiOutput = function (json, methodName, output) { var result = []; var method = json[index]; + var padding = 32 * 2; for (var i = 0; i < method.outputs.length; i++) { - var padding = -1; - for (var j = 0; j < outputTypes.length && padding === -1; j++) { - padding = outputTypes[j].padding(method.outputs[i].type); + var typeMatch = false; + for (var j = 0; j < outputTypes.length && !typeMatch; j++) { + typeMatch = outputTypes[j].type(method.outputs[i].type); } - if (padding === -1) { + if (!typeMatch) { // not found output parsing + console.error('output parser does not support type: ' + method.outputs[i].type); continue; } var res = output.slice(0, padding); @@ -235,6 +245,8 @@ var fromAbiOutput = function (json, methodName, output) { return result; }; +/// @param json abi for contract +/// @returns input parser object for given json abi var inputParser = function (json) { var parser = {}; json.forEach(function (method) { @@ -247,6 +259,8 @@ var inputParser = function (json) { return parser; }; +/// @param json abi for contract +/// @returns output parser for given json abi var outputParser = function (json) { var parser = {}; json.forEach(function (method) { @@ -258,6 +272,9 @@ var outputParser = function (json) { return parser; }; +/// @param json abi for contract +/// @param method name for which we want to get method signature +/// @returns (promise) contract method signature for method with given name var methodSignature = function (json, name) { var method = json[findMethodIndex(json, name)]; var result = name + '('; diff --git a/lib/autoprovider.js b/lib/autoprovider.js index 113873674..a2c265ccb 100644 --- a/lib/autoprovider.js +++ b/lib/autoprovider.js @@ -33,6 +33,16 @@ if (process.env.NODE_ENV !== 'build') { var web3 = require('./web3'); // jshint ignore:line } +/** + * AutoProvider object prototype is implementing 'provider protocol' + * Automatically tries to setup correct provider(Qt, WebSockets or HttpRpc) + * First it checkes if we are ethereum browser (if navigator.qt object is available) + * if yes, we are using QtProvider + * if no, we check if it is possible to establish websockets connection with ethereum (ws://localhost:40404/eth is default) + * if it's not possible, we are using httprpc provider (http://localhost:8080) + * The constructor allows you to specify uris on which we are trying to connect over http or websockets + * You can do that by passing objects with fields httrpc and websockets + */ var AutoProvider = function (userOptions) { if (web3.haveProvider()) { return; @@ -81,6 +91,8 @@ var AutoProvider = function (userOptions) { }; }; +/// Sends message forward to the provider, that is being used +/// if provider is not yet set, enqueues the message AutoProvider.prototype.send = function (payload) { if (this.provider) { this.provider.send(payload); @@ -89,6 +101,7 @@ AutoProvider.prototype.send = function (payload) { this.sendQueue.push(payload); }; +/// On incoming message sends the message to the provider that is currently being used Object.defineProperty(AutoProvider.prototype, 'onmessage', { set: function (handler) { if (this.provider) { diff --git a/lib/contract.js b/lib/contract.js index 4cb202255..52ce08705 100644 --- a/lib/contract.js +++ b/lib/contract.js @@ -27,9 +27,29 @@ if (process.env.NODE_ENV !== 'build') { var abi = require('./abi'); -// method signature length in bytes +/// method signature length in bytes var ETH_METHOD_SIGNATURE_LENGTH = 4; +/** + * This method should be called when we want to call / transact some solidity method from javascript + * it returns an object which has same methods available as solidity contract description + * usage example: + * + * var abi = [{ + * name: 'myMethod', + * inputs: [{ name: 'a', type: 'string' }], + * outputs: [{name: 'd', type: 'string' }] + * }]; // contract abi + * + * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object + * + * myContract.myMethod('this is test string param for call').call(); // myMethod call + * myContract.myMethod('this is test string param for transact').transact() // myMethod transact + * + * @param address - address of the contract, which should be called + * @param desc - abi json description of the contract, which is being created + * @returns contract object + */ var contract = function (address, desc) { var inputParser = abi.inputParser(desc); var outputParser = abi.outputParser(desc); @@ -57,8 +77,10 @@ var contract = function (address, desc) { transact: function (extra) { extra = extra || {}; extra.to = address; - extra.data = parsed; - return web3.eth.transact(extra).then(onSuccess); + return abi.methodSignature(desc, method.name).then(function (signature) { + extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed; + return web3.eth.transact(extra).then(onSuccess); + }); } }; }; @@ -68,3 +90,4 @@ var contract = function (address, desc) { }; module.exports = contract; + diff --git a/lib/filter.js b/lib/filter.js new file mode 100644 index 000000000..47f5a070c --- /dev/null +++ b/lib/filter.js @@ -0,0 +1,89 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file filter.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * Gav Wood + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var web3 = require('./web3'); // jshint ignore:line +} + +/// should be used when we want to watch something +/// it's using inner polling mechanism and is notified about changes +var Filter = function(options, impl) { + this.impl = impl; + this.callbacks = []; + + var self = this; + this.promise = impl.newFilter(options); + this.promise.then(function (id) { + self.id = id; + web3.on(impl.changed, id, self.trigger.bind(self)); + web3.provider.startPolling({call: impl.changed, args: [id]}, id); + }); +}; + +/// alias for changed* +Filter.prototype.arrived = function(callback) { + this.changed(callback); +}; + +/// gets called when there is new eth/shh message +Filter.prototype.changed = function(callback) { + var self = this; + this.promise.then(function(id) { + self.callbacks.push(callback); + }); +}; + +/// trigger calling new message from people +Filter.prototype.trigger = function(messages) { + for(var i = 0; i < this.callbacks.length; i++) { + this.callbacks[i].call(this, messages); + } +}; + +/// should be called to uninstall current filter +Filter.prototype.uninstall = function() { + var self = this; + this.promise.then(function (id) { + self.impl.uninstallFilter(id); + web3.provider.stopPolling(id); + web3.off(impl.changed, id); + }); +}; + +/// should be called to manually trigger getting latest messages from the client +Filter.prototype.messages = function() { + var self = this; + return this.promise.then(function (id) { + return self.impl.getMessages(id); + }); +}; + +/// alias for messages +Filter.prototype.logs = function () { + return this.messages(); +}; + +module.exports = Filter; diff --git a/lib/httprpc.js b/lib/httprpc.js index d315201f1..de3ae8478 100644 --- a/lib/httprpc.js +++ b/lib/httprpc.js @@ -26,11 +26,21 @@ if (process.env.NODE_ENV !== 'build') { var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line } +/** + * HttpRpcProvider object prototype is implementing 'provider protocol' + * Should be used when we want to connect to ethereum backend over http && jsonrpc + * It's compatible with cpp client + * The contructor allows to specify host uri + * This provider is using in-browser polling mechanism + */ var HttpRpcProvider = function (host) { this.handlers = []; this.host = host; }; +/// Transforms inner message to proper jsonrpc object +/// @param inner message object +/// @returns jsonrpc object function formatJsonRpcObject(object) { return { jsonrpc: '2.0', @@ -40,6 +50,9 @@ function formatJsonRpcObject(object) { }; } +/// Transforms jsonrpc object to inner message +/// @param incoming jsonrpc message +/// @returns inner message object function formatJsonRpcMessage(message) { var object = JSON.parse(message); @@ -50,6 +63,10 @@ function formatJsonRpcMessage(message) { }; } +/// Prototype object method +/// Asynchronously sends request to server +/// @param payload is inner message object +/// @param cb is callback which is being called when response is comes back HttpRpcProvider.prototype.sendRequest = function (payload, cb) { var data = formatJsonRpcObject(payload); @@ -63,6 +80,11 @@ HttpRpcProvider.prototype.sendRequest = function (payload, cb) { }; }; +/// Prototype object method +/// Should be called when we want to send single api request to server +/// Asynchronous +/// On response it passes message to handlers +/// @param payload is inner message object HttpRpcProvider.prototype.send = function (payload) { var self = this; this.sendRequest(payload, function (request) { @@ -72,6 +94,13 @@ HttpRpcProvider.prototype.send = function (payload) { }); }; +/// Prototype object method +/// Should be called only for polling requests +/// Asynchronous +/// On response it passege message to handlers, but only if message's result is true or not empty array +/// Otherwise response is being silently ignored +/// @param payload is inner message object +/// @id is id of poll that we are calling HttpRpcProvider.prototype.poll = function (payload, id) { var self = this; this.sendRequest(payload, function (request) { @@ -85,6 +114,8 @@ HttpRpcProvider.prototype.poll = function (payload, id) { }); }; +/// Prototype object property +/// Should be used to set message handlers for this provider Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { set: function (handler) { this.handlers.push(handler); @@ -92,3 +123,4 @@ Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { }); module.exports = HttpRpcProvider; + diff --git a/lib/providermanager.js b/lib/providermanager.js new file mode 100644 index 000000000..00266154d --- /dev/null +++ b/lib/providermanager.js @@ -0,0 +1,122 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file providermanager.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * Gav Wood + * @date 2014 + */ + +// TODO: is these line is supposed to be here? +if (process.env.NODE_ENV !== 'build') { + var web3 = require('./web3'); // jshint ignore:line +} + +/** + * Provider manager object prototype + * It's responsible for passing messages to providers + * If no provider is set it's responsible for queuing requests + * It's also responsible for polling the ethereum node for incoming messages + * Default poll timeout is 12 seconds + * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling, + * and provider manager polling mechanism is not used + */ +var ProviderManager = function() { + this.queued = []; + this.polls = []; + this.ready = false; + this.provider = undefined; + this.id = 1; + + var self = this; + var poll = function () { + if (self.provider && self.provider.poll) { + self.polls.forEach(function (data) { + data.data._id = self.id; + self.id++; + self.provider.poll(data.data, data.id); + }); + } + setTimeout(poll, 12000); + }; + poll(); +}; + +/// sends outgoing requests, if provider is not available, enqueue the request +ProviderManager.prototype.send = function(data, cb) { + data._id = this.id; + if (cb) { + web3._callbacks[data._id] = cb; + } + + data.args = data.args || []; + this.id++; + + if(this.provider !== undefined) { + this.provider.send(data); + } else { + console.warn("provider is not set"); + this.queued.push(data); + } +}; + +/// setups provider, which will be used for sending messages +ProviderManager.prototype.set = function(provider) { + if(this.provider !== undefined && this.provider.unload !== undefined) { + this.provider.unload(); + } + + this.provider = provider; + this.ready = true; +}; + +/// resends queued messages +ProviderManager.prototype.sendQueued = function() { + for(var i = 0; this.queued.length; i++) { + // Resend + this.send(this.queued[i]); + } +}; + +/// @returns true if the provider i properly set +ProviderManager.prototype.installed = function() { + return this.provider !== undefined; +}; + +/// this method is only used, when we do not have native qt bindings and have to do polling on our own +/// should be callled, on start watching for eth/shh changes +ProviderManager.prototype.startPolling = function (data, pollId) { + if (!this.provider || !this.provider.poll) { + return; + } + this.polls.push({data: data, id: pollId}); +}; + +/// should be called to stop polling for certain watch changes +ProviderManager.prototype.stopPolling = function (pollId) { + for (var i = this.polls.length; i--;) { + var poll = this.polls[i]; + if (poll.id === pollId) { + this.polls.splice(i, 1); + } + } +}; + +module.exports = ProviderManager; + diff --git a/lib/qt.js b/lib/qt.js index f02239547..1b3a9547b 100644 --- a/lib/qt.js +++ b/lib/qt.js @@ -21,6 +21,11 @@ * @date 2014 */ +/** + * QtProvider object prototype is implementing 'provider protocol' + * Should be used inside ethereum browser. It's compatible with cpp and go clients. + * It uses navigator.qt object to pass the messages to native bindings + */ var QtProvider = function() { this.handlers = []; @@ -32,10 +37,17 @@ var QtProvider = function() { }; }; +/// Prototype object method +/// Should be called when we want to send single api request to native bindings +/// Asynchronous +/// Response will be received by navigator.qt.onmessage method and passed to handlers +/// @param payload is inner message object QtProvider.prototype.send = function(payload) { navigator.qt.postMessage(JSON.stringify(payload)); }; +/// Prototype object property +/// Should be used to set message handlers for this provider Object.defineProperty(QtProvider.prototype, "onmessage", { set: function(handler) { this.handlers.push(handler); diff --git a/lib/web3.js b/lib/web3.js index 4220114f9..25c2901a8 100644 --- a/lib/web3.js +++ b/lib/web3.js @@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** @file main.js +/** @file web3.js * @authors: * Jeffrey Wilcke * Marek Kotewicz @@ -23,6 +23,12 @@ * @date 2014 */ +var Filter = require('./filter'); +var ProviderManager = require('./providermanager'); + +/// Recursively resolves all promises in given object and replaces the resolved values with promises +/// @param any object/array/promise/anything else.. +/// @returns (resolves) object with replaced promises with their result function flattenPromise (obj) { if (obj instanceof Promise) { return Promise.resolve(obj); @@ -62,12 +68,14 @@ function flattenPromise (obj) { return Promise.resolve(obj); } +/// @returns an array of objects describing web3 api methods var web3Methods = function () { return [ { name: 'sha3', call: 'web3_sha3' } ]; }; +/// @returns an array of objects describing web3.eth api methods var ethMethods = function () { var blockCall = function (args) { return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; @@ -101,6 +109,7 @@ var ethMethods = function () { return methods; }; +/// @returns an array of objects describing web3.eth api properties var ethProperties = function () { return [ { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, @@ -115,6 +124,7 @@ var ethProperties = function () { ]; }; +/// @returns an array of objects describing web3.db api methods var dbMethods = function () { return [ { name: 'put', call: 'db_put' }, @@ -124,6 +134,7 @@ var dbMethods = function () { ]; }; +/// @returns an array of objects describing web3.shh api methods var shhMethods = function () { return [ { name: 'post', call: 'shh_post' }, @@ -134,6 +145,7 @@ var shhMethods = function () { ]; }; +/// @returns an array of objects describing web3.eth.watch api methods var ethWatchMethods = function () { var newFilter = function (args) { return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; @@ -146,6 +158,7 @@ var ethWatchMethods = function () { ]; }; +/// @returns an array of objects describing web3.shh.watch api methods var shhWatchMethods = function () { return [ { name: 'newFilter', call: 'shh_newFilter' }, @@ -154,6 +167,8 @@ var shhWatchMethods = function () { ]; }; +/// creates methods in a given object based on method description on input +/// setups api calls for these methods var setupMethods = function (obj, methods) { methods.forEach(function (method) { obj[method.name] = function () { @@ -177,6 +192,8 @@ var setupMethods = function (obj, methods) { }); }; +/// creates properties in a given object based on properties description on input +/// setups api calls for these properties var setupProperties = function (obj, properties) { properties.forEach(function (property) { var proto = {}; @@ -221,7 +238,7 @@ var decToHex = function (dec) { return parseInt(dec).toString(16); }; - +/// setups web3 object, and it's in-browser executed methods var web3 = { _callbacks: {}, _events: {}, @@ -237,6 +254,7 @@ var web3 = { return hex; }, + /// @returns ascii string representation of hex value prefixed with 0x toAscii: function(hex) { // Find termination var str = ""; @@ -244,17 +262,18 @@ var web3 = { if (hex.substring(0, 2) === '0x') i = 2; for(; i < l; i+=2) { - var code = hex.charCodeAt(i); + var code = parseInt(hex.substr(i, 2), 16); if(code === 0) { break; } - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + str += String.fromCharCode(code); } return str; }, + /// @returns hex representation (prefixed by 0x) of ascii string fromAscii: function(str, pad) { pad = pad === undefined ? 0 : pad; var hex = this.toHex(str); @@ -263,14 +282,17 @@ var web3 = { return "0x" + hex; }, + /// @returns decimal representaton of hex value prefixed by 0x toDecimal: function (val) { return hexToDec(val.substring(2)); }, + /// @returns hex representation (prefixed by 0x) of decimal value fromDecimal: function (val) { return "0x" + decToHex(val); }, + /// used to transform value/string to eth string toEth: function(str) { var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; var unit = 0; @@ -294,24 +316,24 @@ var web3 = { return s + ' ' + units[unit]; }, + /// eth object prototype eth: { - prototype: Object(), // jshint ignore:line watch: function (params) { return new Filter(params, ethWatch); } }, - db: { - prototype: Object() // jshint ignore:line - }, + /// db object prototype + db: {}, + /// shh object prototype shh: { - prototype: Object(), // jshint ignore:line watch: function (params) { return new Filter(params, shhWatch); } }, + /// used by filter to register callback with given id on: function(event, id, cb) { if(web3._events[event] === undefined) { web3._events[event] = {}; @@ -321,6 +343,7 @@ var web3 = { return this; }, + /// used by filter to unregister callback with given id off: function(event, id) { if(web3._events[event] !== undefined) { delete web3._events[event][id]; @@ -329,6 +352,7 @@ var web3 = { return this; }, + /// used to trigger callback registered by filter trigger: function(event, id, data) { var callbacks = web3._events[event]; if (!callbacks || !callbacks[id]) { @@ -336,9 +360,15 @@ var web3 = { } var cb = callbacks[id]; cb(data); + }, + + /// @returns true if provider is installed + haveProvider: function() { + return !!web3.provider.provider; } }; +/// setups all api methods setupMethods(web3, web3Methods()); setupMethods(web3.eth, ethMethods()); setupProperties(web3.eth, ethProperties()); @@ -348,85 +378,14 @@ setupMethods(web3.shh, shhMethods()); var ethWatch = { changed: 'eth_changed' }; + setupMethods(ethWatch, ethWatchMethods()); + var shhWatch = { changed: 'shh_changed' }; -setupMethods(shhWatch, shhWatchMethods()); - -var ProviderManager = function() { - this.queued = []; - this.polls = []; - this.ready = false; - this.provider = undefined; - this.id = 1; - - var self = this; - var poll = function () { - if (self.provider && self.provider.poll) { - self.polls.forEach(function (data) { - data.data._id = self.id; - self.id++; - self.provider.poll(data.data, data.id); - }); - } - setTimeout(poll, 12000); - }; - poll(); -}; - -ProviderManager.prototype.send = function(data, cb) { - data._id = this.id; - if (cb) { - web3._callbacks[data._id] = cb; - } - - data.args = data.args || []; - this.id++; - - if(this.provider !== undefined) { - this.provider.send(data); - } else { - console.warn("provider is not set"); - this.queued.push(data); - } -}; - -ProviderManager.prototype.set = function(provider) { - if(this.provider !== undefined && this.provider.unload !== undefined) { - this.provider.unload(); - } - - this.provider = provider; - this.ready = true; -}; - -ProviderManager.prototype.sendQueued = function() { - for(var i = 0; this.queued.length; i++) { - // Resend - this.send(this.queued[i]); - } -}; - -ProviderManager.prototype.installed = function() { - return this.provider !== undefined; -}; - -ProviderManager.prototype.startPolling = function (data, pollId) { - if (!this.provider || !this.provider.poll) { - return; - } - this.polls.push({data: data, id: pollId}); -}; -ProviderManager.prototype.stopPolling = function (pollId) { - for (var i = this.polls.length; i--;) { - var poll = this.polls[i]; - if (poll.id === pollId) { - this.polls.splice(i, 1); - } - } -}; +setupMethods(shhWatch, shhWatchMethods()); web3.provider = new ProviderManager(); @@ -436,60 +395,7 @@ web3.setProvider = function(provider) { web3.provider.sendQueued(); }; -web3.haveProvider = function() { - return !!web3.provider.provider; -}; - -var Filter = function(options, impl) { - this.impl = impl; - this.callbacks = []; - - var self = this; - this.promise = impl.newFilter(options); - this.promise.then(function (id) { - self.id = id; - web3.on(impl.changed, id, self.trigger.bind(self)); - web3.provider.startPolling({call: impl.changed, args: [id]}, id); - }); -}; - -Filter.prototype.arrived = function(callback) { - this.changed(callback); -}; - -Filter.prototype.changed = function(callback) { - var self = this; - this.promise.then(function(id) { - self.callbacks.push(callback); - }); -}; - -Filter.prototype.trigger = function(messages) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); - } -}; - -Filter.prototype.uninstall = function() { - var self = this; - this.promise.then(function (id) { - self.impl.uninstallFilter(id); - web3.provider.stopPolling(id); - web3.off(impl.changed, id); - }); -}; - -Filter.prototype.messages = function() { - var self = this; - return this.promise.then(function (id) { - return self.impl.getMessages(id); - }); -}; - -Filter.prototype.logs = function () { - return this.messages(); -}; - +/// callled when there is new incoming message function messageHandler(data) { if(data._event !== undefined) { web3.trigger(data._event, data._id, data.data); diff --git a/lib/websocket.js b/lib/websocket.js index 5b40075e4..e8663ecf5 100644 --- a/lib/websocket.js +++ b/lib/websocket.js @@ -27,9 +27,17 @@ if (process.env.NODE_ENV !== 'build') { var WebSocket = require('ws'); // jshint ignore:line } +/** + * WebSocketProvider object prototype is implementing 'provider protocol' + * Should be used when we want to connect to ethereum backend over websockets + * It's compatible with go client + * The constructor allows to specify host uri + */ var WebSocketProvider = function(host) { + // onmessage handlers this.handlers = []; + // queue will be filled with messages if send is invoked before the ws is ready this.queued = []; this.ready = false; @@ -46,15 +54,20 @@ var WebSocketProvider = function(host) { this.ws.onopen = function() { self.ready = true; - for(var i = 0; i < self.queued.length; i++) { + for (var i = 0; i < self.queued.length; i++) { // Resend self.send(self.queued[i]); } }; }; +/// Prototype object method +/// Should be called when we want to send single api request to server +/// Asynchronous, it's using websockets +/// Response for the call will be received by ws.onmessage +/// @param payload is inner message object WebSocketProvider.prototype.send = function(payload) { - if(this.ready) { + if (this.ready) { var data = JSON.stringify(payload); this.ws.send(data); @@ -63,13 +76,20 @@ WebSocketProvider.prototype.send = function(payload) { } }; +/// Prototype object method +/// Should be called to add handlers WebSocketProvider.prototype.onMessage = function(handler) { this.handlers.push(handler); }; +/// Prototype object method +/// Should be called to close websockets connection WebSocketProvider.prototype.unload = function() { this.ws.close(); }; + +/// Prototype object property +/// Should be used to set message handlers for this provider Object.defineProperty(WebSocketProvider.prototype, "onmessage", { set: function(provider) { this.onMessage(provider); } }); diff --git a/test/abi.parsers.js b/test/abi.parsers.js index 06a77fb86..925324461 100644 --- a/test/abi.parsers.js +++ b/test/abi.parsers.js @@ -1,37 +1,547 @@ var assert = require('assert'); var abi = require('../lib/abi.js'); +var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; + +var description = [{ + "name": "test", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] +}]; describe('abi', function() { describe('inputParser', function() { - it('should parse ...', function() { - - var desc = [{ - "name": "multiply", - "inputs": [ - { - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] + it('should parse input uint', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + + }); + + it('should parse input uint128', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint128" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + + }); + + it('should parse input uint256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "uint256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + + }); + + it('should parse input int', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + + }); + + it('should parse input int128', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int128" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + + }); + + it('should parse input int256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); + assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); + + }); + + it('should parse input bool', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: 'bool' } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test(true), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test(false), "0000000000000000000000000000000000000000000000000000000000000000"); + + }); + + it('should parse input hash', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + it('should parse input hash256', function() { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash256" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + + it('should parse input hash160', function() { + // given + var d = clone(description); + + d[0].inputs = [ + { type: "hash160" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + }); + + it('should parse input address', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "address" } + ]; + + // when + var parser = abi.inputParser(d) + + // then + assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); + + }); + + it('should parse input string', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "string" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.test('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000"); + assert.equal(parser.test('world'), "776f726c64000000000000000000000000000000000000000000000000000000"); + }); + + it('should use proper method name', function () { + + // given + var d = clone(description); + d[0].name = 'helloworld'; + d[0].inputs = [ + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001"); + + }); + + it('should parse multiple methods', function () { + + // given + var d = [{ + name: "test", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + inputs: [{ type: "string" }], + outputs: [{ type: "string" }] }]; - var iParser = abi.inputParser(desc); - assert.equal(iParser.multiply(1), "0x000000000000000000000000000000000000000000000000000000000000000001"); + // when + var parser = abi.inputParser(d); + + //then + assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); + assert.equal(parser.test2('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000"); }); }); - describe('outputParser', function() { - it('parse ...', function() { + it('should parse output string', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: "string" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], 'hello'); + assert.equal(parser.test("0x776f726c64000000000000000000000000000000000000000000000000000000")[0], 'world'); }); + + it('should parse output uint', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output uint256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output uint128', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'uint128' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output int', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output int256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output int128', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'int128' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); + }); + + it('should parse output hash', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + }); + + it('should parse output hash256', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash256' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + }); + + it('should parse output hash160', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'hash160' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1") + // TODO shouldnt' the expected hash be shorter? + }); + + it('should parse output address', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'address' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], "0x407d73d8a49eeb85d32cf465507dd71d507100c1") + }); + + it('should parse output bool', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: 'bool' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000001")[0], true); + assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000000")[0], false); + + + }); + + it('should parse multiple output strings', function() { + + // given + var d = clone(description); + + d[0].outputs = [ + { type: "string" }, + { type: "string" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[0], 'hello'); + assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[1], 'world'); + + }); + + it('should use proper method name', function () { + + // given + var d = clone(description); + d[0].name = 'helloworld'; + d[0].outputs = [ + { type: "int" } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + + }); + + + it('should parse multiple methods', function () { + + // given + var d = [{ + name: "test", + inputs: [{ type: "int" }], + outputs: [{ type: "int" }] + },{ + name: "test2", + inputs: [{ type: "string" }], + outputs: [{ type: "string" }] + }]; + + // when + var parser = abi.outputParser(d); + + //then + assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); + assert.equal(parser.test2("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], "hello"); + + }); + }); }); diff --git a/test/db.methods.js b/test/db.methods.js index b4abfc4d7..662f4e7cc 100644 --- a/test/db.methods.js +++ b/test/db.methods.js @@ -7,12 +7,10 @@ web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); describe('web3', function() { describe('db', function() { - it('should have all methods implemented', function() { - u.methodExists(web3.db, 'put'); - u.methodExists(web3.db, 'get'); - u.methodExists(web3.db, 'putString'); - u.methodExists(web3.db, 'getString'); - }); + u.methodExists(web3.db, 'put'); + u.methodExists(web3.db, 'get'); + u.methodExists(web3.db, 'putString'); + u.methodExists(web3.db, 'getString'); }); }); diff --git a/test/eth.methods.js b/test/eth.methods.js index 7190b27d2..892db0d8b 100644 --- a/test/eth.methods.js +++ b/test/eth.methods.js @@ -7,35 +7,31 @@ web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); describe('web3', function() { describe('eth', function() { - it('should have all methods implemented', function() { - u.methodExists(web3.eth, 'balanceAt'); - u.methodExists(web3.eth, 'stateAt'); - u.methodExists(web3.eth, 'storageAt'); - u.methodExists(web3.eth, 'countAt'); - u.methodExists(web3.eth, 'codeAt'); - u.methodExists(web3.eth, 'transact'); - u.methodExists(web3.eth, 'call'); - u.methodExists(web3.eth, 'block'); - u.methodExists(web3.eth, 'transaction'); - u.methodExists(web3.eth, 'uncle'); - u.methodExists(web3.eth, 'compilers'); - u.methodExists(web3.eth, 'lll'); - u.methodExists(web3.eth, 'solidity'); - u.methodExists(web3.eth, 'serpent'); - u.methodExists(web3.eth, 'logs'); - }); + u.methodExists(web3.eth, 'balanceAt'); + u.methodExists(web3.eth, 'stateAt'); + u.methodExists(web3.eth, 'storageAt'); + u.methodExists(web3.eth, 'countAt'); + u.methodExists(web3.eth, 'codeAt'); + u.methodExists(web3.eth, 'transact'); + u.methodExists(web3.eth, 'call'); + u.methodExists(web3.eth, 'block'); + u.methodExists(web3.eth, 'transaction'); + u.methodExists(web3.eth, 'uncle'); + u.methodExists(web3.eth, 'compilers'); + u.methodExists(web3.eth, 'lll'); + u.methodExists(web3.eth, 'solidity'); + u.methodExists(web3.eth, 'serpent'); + u.methodExists(web3.eth, 'logs'); - it('should have all properties implemented', function () { - u.propertyExists(web3.eth, 'coinbase'); - u.propertyExists(web3.eth, 'listening'); - u.propertyExists(web3.eth, 'mining'); - u.propertyExists(web3.eth, 'gasPrice'); - u.propertyExists(web3.eth, 'account'); - u.propertyExists(web3.eth, 'accounts'); - u.propertyExists(web3.eth, 'peerCount'); - u.propertyExists(web3.eth, 'defaultBlock'); - u.propertyExists(web3.eth, 'number'); - }); + u.propertyExists(web3.eth, 'coinbase'); + u.propertyExists(web3.eth, 'listening'); + u.propertyExists(web3.eth, 'mining'); + u.propertyExists(web3.eth, 'gasPrice'); + u.propertyExists(web3.eth, 'account'); + u.propertyExists(web3.eth, 'accounts'); + u.propertyExists(web3.eth, 'peerCount'); + u.propertyExists(web3.eth, 'defaultBlock'); + u.propertyExists(web3.eth, 'number'); }); }); diff --git a/test/mocha.opts b/test/mocha.opts index b2db8d5a7..c4a633d64 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,2 +1,2 @@ ---reporter Spec +--reporter spec diff --git a/test/shh.methods.js b/test/shh.methods.js index 08f573a3c..f2f56edbc 100644 --- a/test/shh.methods.js +++ b/test/shh.methods.js @@ -7,13 +7,11 @@ web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); describe('web3', function() { describe('shh', function() { - it('should have all methods implemented', function() { - u.methodExists(web3.shh, 'post'); - u.methodExists(web3.shh, 'newIdentity'); - u.methodExists(web3.shh, 'haveIdentity'); - u.methodExists(web3.shh, 'newGroup'); - u.methodExists(web3.shh, 'addToGroup'); - }); + u.methodExists(web3.shh, 'post'); + u.methodExists(web3.shh, 'newIdentity'); + u.methodExists(web3.shh, 'haveIdentity'); + u.methodExists(web3.shh, 'newGroup'); + u.methodExists(web3.shh, 'addToGroup'); }); }); diff --git a/test/utils.js b/test/utils.js index 4c508da67..8617348e4 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,11 +1,15 @@ var assert = require('assert'); var methodExists = function (object, method) { - assert.equal('function', typeof object[method], 'method ' + method + ' is not implemented'); + it('should have method ' + method + ' implemented', function() { + assert.equal('function', typeof object[method], 'method ' + method + ' is not implemented'); + }); }; var propertyExists = function (object, property) { - assert.equal('object', typeof object[property], 'property ' + property + ' is not implemented'); + it('should have property ' + property + ' implemented', function() { + assert.equal('object', typeof object[property], 'property ' + property + ' is not implemented'); + }); }; module.exports = { diff --git a/test/web3.methods.js b/test/web3.methods.js index a7e020978..5c30177e5 100644 --- a/test/web3.methods.js +++ b/test/web3.methods.js @@ -6,13 +6,11 @@ var u = require('./utils.js'); web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider describe('web3', function() { - it('should have all methods implemented', function() { - u.methodExists(web3, 'sha3'); - u.methodExists(web3, 'toAscii'); - u.methodExists(web3, 'fromAscii'); - u.methodExists(web3, 'toFixed'); - u.methodExists(web3, 'fromFixed'); - u.methodExists(web3, 'offset'); - }); + u.methodExists(web3, 'sha3'); + u.methodExists(web3, 'toAscii'); + u.methodExists(web3, 'fromAscii'); + u.methodExists(web3, 'toFixed'); + u.methodExists(web3, 'fromFixed'); + u.methodExists(web3, 'offset'); }); From d876522bc0614fea3180a54be57bcb61784b352e Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 16 Jan 2015 12:07:48 +0100 Subject: [PATCH 03/34] Squashed 'libjsqrc/ethereumjs/' changes from ec74fc0..2c36d5f 2c36d5f big integers on abi.js output, tests f1295b5 tests for bigintegers on input fbcc6d0 BigNumber support git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 2c36d5ff457952c557b467e580514b08126d7dd7 --- dist/ethereum.js | 41 ++++++++++------ dist/ethereum.js.map | 4 +- dist/ethereum.min.js | 2 +- example/balance.html | 1 + gulpfile.js | 4 +- lib/abi.js | 39 ++++++++++------ package.json | 3 +- test/abi.parsers.js | 109 ++++++++++++++++++++++++++++++++++++++++--- 8 files changed, 163 insertions(+), 40 deletions(-) diff --git a/dist/ethereum.js b/dist/ethereum.js index f4e0e6eac..0a26b832f 100644 --- a/dist/ethereum.js +++ b/dist/ethereum.js @@ -27,6 +27,8 @@ if ("build" !== 'build') {/* var web3 = require('./web3'); // jshint ignore:line */} +var BigNumber = require('bignumber.js'); + // TODO: make these be actually accurate instead of falling back onto JS's doubles. var hexToDec = function (hex) { return parseInt(hex, 16).toString(); @@ -85,24 +87,26 @@ var namedType = function (name) { var setupInputTypes = function () { /// Formats input value to byte representation of int + /// If value is negative, return it's two's complement /// @returns right-aligned byte representation of int var formatInt = function (value) { var padding = 32 * 2; - if (typeof value === 'number') { - if (value < 0) { - - // two's complement - // TODO: fix big numbers support - value = ((value) >>> 0).toString(16); - return padLeft(value, padding, 'f'); - } - value = value.toString(16); - + if (value instanceof BigNumber) { + if (value.lessThan(0)) + value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1).toString(16); + else + value = value.toString(16); + } + else if (typeof value === 'number') { + if (value < 0) + value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1).toString(16); + else + value = new BigNumber(value).toString(16); } else if (value.indexOf('0x') === 0) value = value.substr(2); else if (typeof value === 'string') - value = value.toHex(value); + value = new BigNumber(value).toString(16); else value = (+value).toString(16); return padLeft(value, padding); @@ -172,7 +176,16 @@ var setupOutputTypes = function () { /// Formats input right-aligned input bytes to int /// @returns right-aligned input bytes formatted to int var formatInt = function (value) { - return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); + // check if it's negative number + // it it is, return two's complement + if (value.substr(0, 1).toLowerCase() === 'f') { + return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1); + } + return new BigNumber(value, 16); + }; + + var formatUInt = function (value) { + return new BigNumber(value, 16); }; /// @returns right-aligned input bytes formatted to hex @@ -196,7 +209,7 @@ var setupOutputTypes = function () { }; return [ - { type: prefixedType('uint'), format: formatInt }, + { type: prefixedType('uint'), format: formatUInt }, { type: prefixedType('int'), format: formatInt }, { type: prefixedType('hash'), format: formatHash }, { type: prefixedType('string'), format: formatString }, @@ -295,7 +308,7 @@ module.exports = { }; -},{}],2:[function(require,module,exports){ +},{"bignumber.js":undefined}],2:[function(require,module,exports){ /* This file is part of ethereum.js. diff --git a/dist/ethereum.js.map b/dist/ethereum.js.map index fd3768b15..2daf9e7d4 100644 --- a/dist/ethereum.js.map +++ b/dist/ethereum.js.map @@ -14,12 +14,12 @@ "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n/// Finds first index of array element matching pattern\n/// @param array\n/// @param callback pattern\n/// @returns index of element\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/// @returns a function that is used as a pattern for 'findIndex'\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\n/// @param string string to be padded\n/// @param number of characters that result string should have\n/// @param sign, by default 0\n/// @returns right aligned string\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/// @param expected type prefix (string)\n/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false\nvar prefixedType = function (prefix) {\n return function (type) {\n return type.indexOf(prefix) === 0;\n };\n};\n\n/// @param expected type name (string)\n/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false\nvar namedType = function (name) {\n return function (type) {\n return name === type;\n };\n};\n\n/// Setups input formatters for solidity types\n/// @returns an array of input formatters \nvar setupInputTypes = function () {\n \n /// Formats input value to byte representation of int\n /// @returns right-aligned byte representation of int\n var formatInt = function (value) {\n var padding = 32 * 2;\n if (typeof value === 'number') {\n if (value < 0) {\n \n // two's complement\n // TODO: fix big numbers support\n value = ((value) >>> 0).toString(16);\n return padLeft(value, padding, 'f');\n }\n value = value.toString(16);\n\n }\n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else if (typeof value === 'string')\n value = value.toHex(value);\n else\n value = (+value).toString(16);\n return padLeft(value, padding);\n };\n\n /// Formats input value to byte representation of string\n /// @returns left-algined byte representation of string\n var formatString = function (value) {\n return web3.fromAscii(value, 32).substr(2);\n };\n\n /// Formats input value to byte representation of bool\n /// @returns right-aligned byte representation bool\n var formatBool = function (value) {\n return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n };\n\n return [\n { type: prefixedType('uint'), format: formatInt },\n { type: prefixedType('int'), format: formatInt },\n { type: prefixedType('hash'), format: formatInt },\n { type: prefixedType('string'), format: formatString }, \n { type: prefixedType('real'), format: formatInt },\n { type: prefixedType('ureal'), format: formatInt },\n { type: namedType('address'), format: formatInt },\n { type: namedType('bool'), format: formatBool }\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\n/// Formats input params to bytes\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n var method = json[index];\n var padding = 32 * 2;\n\n for (var i = 0; i < method.inputs.length; i++) {\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n console.error('input parser does not support type: ' + method.inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n bytes += (formatter ? formatter(params[i]) : params[i]);\n }\n return bytes;\n};\n\n/// Setups output formaters for solidity types\n/// @returns an array of output formatters\nvar setupOutputTypes = function () {\n\n /// Formats input right-aligned input bytes to int\n /// @returns right-aligned input bytes formatted to int\n var formatInt = function (value) {\n return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);\n };\n\n /// @returns right-aligned input bytes formatted to hex\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n /// @returns right-aligned input bytes formatted to bool\n var formatBool = function (value) {\n return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n };\n\n /// @returns left-aligned input bytes formatted to ascii string\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n /// @returns right-aligned input bytes formatted to address\n var formatAddress = function (value) {\n return \"0x\" + value.slice(value.length - 40, value.length);\n };\n\n return [\n { type: prefixedType('uint'), format: formatInt },\n { type: prefixedType('int'), format: formatInt },\n { type: prefixedType('hash'), format: formatHash },\n { type: prefixedType('string'), format: formatString },\n { type: prefixedType('real'), format: formatInt },\n { type: prefixedType('ureal'), format: formatInt },\n { type: namedType('address'), format: formatAddress },\n { type: namedType('bool'), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\n/// Formats output bytes back to param list\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param bytes representtion of output \n/// @returns array of output params \nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n var padding = 32 * 2;\n for (var i = 0; i < method.outputs.length; i++) {\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(method.outputs[i].type);\n }\n\n if (!typeMatch) {\n // not found output parsing\n console.error('output parser does not support type: ' + method.outputs[i].type);\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @returns output parser for given json abi\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @param method name for which we want to get method signature\n/// @returns (promise) contract method signature for method with given name\nvar methodSignature = function (json, name) {\n var method = json[findMethodIndex(json, name)];\n var result = name + '(';\n var inputTypes = method.inputs.map(function (inp) {\n return inp.type;\n });\n result += inputTypes.join(',');\n result += ')';\n\n return web3.sha3(web3.fromAscii(result));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar BigNumber = require('bignumber.js');\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n/// Finds first index of array element matching pattern\n/// @param array\n/// @param callback pattern\n/// @returns index of element\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/// @returns a function that is used as a pattern for 'findIndex'\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\n/// @param string string to be padded\n/// @param number of characters that result string should have\n/// @param sign, by default 0\n/// @returns right aligned string\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/// @param expected type prefix (string)\n/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false\nvar prefixedType = function (prefix) {\n return function (type) {\n return type.indexOf(prefix) === 0;\n };\n};\n\n/// @param expected type name (string)\n/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false\nvar namedType = function (name) {\n return function (type) {\n return name === type;\n };\n};\n\n/// Setups input formatters for solidity types\n/// @returns an array of input formatters \nvar setupInputTypes = function () {\n \n /// Formats input value to byte representation of int\n /// If value is negative, return it's two's complement\n /// @returns right-aligned byte representation of int\n var formatInt = function (value) {\n var padding = 32 * 2;\n if (value instanceof BigNumber) {\n if (value.lessThan(0)) \n value = new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(value).plus(1).toString(16);\n else \n value = value.toString(16);\n }\n else if (typeof value === 'number') {\n if (value < 0)\n value = new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(value).plus(1).toString(16);\n else\n value = new BigNumber(value).toString(16);\n }\n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else if (typeof value === 'string')\n value = new BigNumber(value).toString(16); \n else\n value = (+value).toString(16);\n return padLeft(value, padding);\n };\n\n /// Formats input value to byte representation of string\n /// @returns left-algined byte representation of string\n var formatString = function (value) {\n return web3.fromAscii(value, 32).substr(2);\n };\n\n /// Formats input value to byte representation of bool\n /// @returns right-aligned byte representation bool\n var formatBool = function (value) {\n return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n };\n\n return [\n { type: prefixedType('uint'), format: formatInt },\n { type: prefixedType('int'), format: formatInt },\n { type: prefixedType('hash'), format: formatInt },\n { type: prefixedType('string'), format: formatString }, \n { type: prefixedType('real'), format: formatInt },\n { type: prefixedType('ureal'), format: formatInt },\n { type: namedType('address'), format: formatInt },\n { type: namedType('bool'), format: formatBool }\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\n/// Formats input params to bytes\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n var method = json[index];\n var padding = 32 * 2;\n\n for (var i = 0; i < method.inputs.length; i++) {\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n console.error('input parser does not support type: ' + method.inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n bytes += (formatter ? formatter(params[i]) : params[i]);\n }\n return bytes;\n};\n\n/// Setups output formaters for solidity types\n/// @returns an array of output formatters\nvar setupOutputTypes = function () {\n\n /// Formats input right-aligned input bytes to int\n /// @returns right-aligned input bytes formatted to int\n var formatInt = function (value) {\n // check if it's negative number\n // it it is, return two's complement\n if (value.substr(0, 1).toLowerCase() === 'f') {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n };\n\n var formatUInt = function (value) {\n return new BigNumber(value, 16);\n };\n\n /// @returns right-aligned input bytes formatted to hex\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n /// @returns right-aligned input bytes formatted to bool\n var formatBool = function (value) {\n return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n };\n\n /// @returns left-aligned input bytes formatted to ascii string\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n /// @returns right-aligned input bytes formatted to address\n var formatAddress = function (value) {\n return \"0x\" + value.slice(value.length - 40, value.length);\n };\n\n return [\n { type: prefixedType('uint'), format: formatUInt },\n { type: prefixedType('int'), format: formatInt },\n { type: prefixedType('hash'), format: formatHash },\n { type: prefixedType('string'), format: formatString },\n { type: prefixedType('real'), format: formatInt },\n { type: prefixedType('ureal'), format: formatInt },\n { type: namedType('address'), format: formatAddress },\n { type: namedType('bool'), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\n/// Formats output bytes back to param list\n/// @param contract json abi\n/// @param name of the method that we want to use\n/// @param bytes representtion of output \n/// @returns array of output params \nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n var padding = 32 * 2;\n for (var i = 0; i < method.outputs.length; i++) {\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(method.outputs[i].type);\n }\n\n if (!typeMatch) {\n // not found output parsing\n console.error('output parser does not support type: ' + method.outputs[i].type);\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @returns output parser for given json abi\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @param method name for which we want to get method signature\n/// @returns (promise) contract method signature for method with given name\nvar methodSignature = function (json, name) {\n var method = json[findMethodIndex(json, name)];\n var result = name + '(';\n var inputTypes = method.inputs.map(function (inp) {\n return inp.type;\n });\n result += inputTypes.join(',');\n result += ')';\n\n return web3.sha3(web3.fromAscii(result));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file autoprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n/*\n * @brief if qt object is available, uses QtProvider,\n * if not tries to connect over websockets\n * if it fails, it uses HttpRpcProvider\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n/**\n * AutoProvider object prototype is implementing 'provider protocol'\n * Automatically tries to setup correct provider(Qt, WebSockets or HttpRpc)\n * First it checkes if we are ethereum browser (if navigator.qt object is available)\n * if yes, we are using QtProvider\n * if no, we check if it is possible to establish websockets connection with ethereum (ws://localhost:40404/eth is default)\n * if it's not possible, we are using httprpc provider (http://localhost:8080)\n * The constructor allows you to specify uris on which we are trying to connect over http or websockets\n * You can do that by passing objects with fields httrpc and websockets\n */\nvar AutoProvider = function (userOptions) {\n if (web3.haveProvider()) {\n return;\n }\n\n // before we determine what provider we are, we have to cache request\n this.sendQueue = [];\n this.onmessageQueue = [];\n\n if (navigator.qt) {\n this.provider = new web3.providers.QtProvider();\n return;\n }\n\n userOptions = userOptions || {};\n var options = {\n httprpc: userOptions.httprpc || 'http://localhost:8080',\n websockets: userOptions.websockets || 'ws://localhost:40404/eth'\n };\n\n var self = this;\n var closeWithSuccess = function (success) {\n ws.close();\n if (success) {\n self.provider = new web3.providers.WebSocketProvider(options.websockets);\n } else {\n self.provider = new web3.providers.HttpRpcProvider(options.httprpc);\n self.poll = self.provider.poll.bind(self.provider);\n }\n self.sendQueue.forEach(function (payload) {\n self.provider(payload);\n });\n self.onmessageQueue.forEach(function (handler) {\n self.provider.onmessage = handler;\n });\n };\n\n var ws = new WebSocket(options.websockets);\n\n ws.onopen = function() {\n closeWithSuccess(true);\n };\n\n ws.onerror = function() {\n closeWithSuccess(false);\n };\n};\n\n/// Sends message forward to the provider, that is being used\n/// if provider is not yet set, enqueues the message\nAutoProvider.prototype.send = function (payload) {\n if (this.provider) {\n this.provider.send(payload);\n return;\n }\n this.sendQueue.push(payload);\n};\n\n/// On incoming message sends the message to the provider that is currently being used\nObject.defineProperty(AutoProvider.prototype, 'onmessage', {\n set: function (handler) {\n if (this.provider) {\n this.provider.onmessage = handler;\n return;\n }\n this.onmessageQueue.push(handler);\n }\n});\n\nmodule.exports = AutoProvider;\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar abi = require('./abi');\n\n/// method signature length in bytes\nvar ETH_METHOD_SIGNATURE_LENGTH = 4;\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var myContract = web3.eth.contract('0x0123123121', abi); // creation of contract object\n *\n * myContract.myMethod('this is test string param for call').call(); // myMethod call\n * myContract.myMethod('this is test string param for transact').transact() // myMethod transact\n *\n * @param address - address of the contract, which should be called\n * @param desc - abi json description of the contract, which is being created\n * @returns contract object\n */\nvar contract = function (address, desc) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var contract = {};\n\n desc.forEach(function (method) {\n contract[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n var parsed = inputParser[method.name].apply(null, params);\n\n var onSuccess = function (result) {\n return outputParser[method.name](result);\n };\n\n return {\n call: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.call(extra).then(onSuccess);\n });\n },\n transact: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.transact(extra).then(onSuccess);\n });\n }\n };\n };\n });\n\n return contract;\n};\n\nmodule.exports = contract;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n/// should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\nvar Filter = function(options, impl) {\n this.impl = impl;\n this.callbacks = [];\n\n var self = this;\n this.promise = impl.newFilter(options);\n this.promise.then(function (id) {\n self.id = id;\n web3.on(impl.changed, id, self.trigger.bind(self));\n web3.provider.startPolling({call: impl.changed, args: [id]}, id);\n });\n};\n\n/// alias for changed*\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\n\n/// gets called when there is new eth/shh message\nFilter.prototype.changed = function(callback) {\n var self = this;\n this.promise.then(function(id) {\n self.callbacks.push(callback);\n });\n};\n\n/// trigger calling new message from people\nFilter.prototype.trigger = function(messages) {\n for(var i = 0; i < this.callbacks.length; i++) {\n this.callbacks[i].call(this, messages);\n }\n};\n\n/// should be called to uninstall current filter\nFilter.prototype.uninstall = function() {\n var self = this;\n this.promise.then(function (id) {\n self.impl.uninstallFilter(id);\n web3.provider.stopPolling(id);\n web3.off(impl.changed, id);\n });\n};\n\n/// should be called to manually trigger getting latest messages from the client\nFilter.prototype.messages = function() {\n var self = this;\n return this.promise.then(function (id) {\n return self.impl.getMessages(id);\n });\n};\n\n/// alias for messages\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nmodule.exports = Filter;\n", diff --git a/dist/ethereum.min.js b/dist/ethereum.min.js index f142507ee..5f3ecd8dc 100644 --- a/dist/ethereum.min.js +++ b/dist/ethereum.min.js @@ -1 +1 @@ -require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;at)return t=(t>>>0).toString(16),i(t,e,"f");t=t.toString(16)}else t=0===t.indexOf("0x")?t.substr(2):"string"==typeof t?t.toHex(t):(+t).toString(16);return i(t,e)},e=function(t){return web3.fromAscii(t,32).substr(2)},n=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")};return[{type:a("uint"),format:t},{type:a("int"),format:t},{type:a("hash"),format:t},{type:a("string"),format:e},{type:a("real"),format:t},{type:a("ureal"),format:t},{type:s("address"),format:t},{type:s("bool"),format:n}]},c=u(),l=function(t,e,n){var r="",i=o(t,e);if(-1!==i){for(var a=t[i],s=0;sn;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},fromAscii:function(t,e){e=void 0===e?0:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return v(t.substring(2))},fromDecimal:function(t){return"0x"+g(t)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e>3e3&&ne?new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(e).plus(1).toString(16):new n(e).toString(16):0===e.indexOf("0x")?e.substr(2):"string"==typeof e?new n(e).toString(16):(+e).toString(16),i(e,t)},t=function(e){return web3.fromAscii(e,32).substr(2)},r=function(e){return"000000000000000000000000000000000000000000000000000000000000000"+(e?"1":"0")};return[{type:f("uint"),format:e},{type:f("int"),format:e},{type:f("hash"),format:e},{type:f("string"),format:t},{type:f("real"),format:e},{type:f("ureal"),format:e},{type:s("address"),format:e},{type:s("bool"),format:r}]},u=a(),c=function(e,t,n){var r="",i=o(e,t);if(-1!==i){for(var f=e[i],s=0;sn;n+=2){var o=parseInt(e.substr(n,2),16);if(0===o)break;t+=String.fromCharCode(o)}return t},fromAscii:function(e,t){t=void 0===t?0:t;for(var n=this.toHex(e);n.length<2*t;)n+="00";return"0x"+n},toDecimal:function(e){return v(e.substring(2))},fromDecimal:function(e){return"0x"+g(e)},toEth:function(e){for(var t="string"==typeof e?0===e.indexOf("0x")?parseInt(e.substr(2),16):parseInt(e):e,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];t>3e3&&n + - + +