winsvega
10 years ago
208 changed files with 19843 additions and 4945 deletions
@ -1,966 +0,0 @@ |
|||||
/*! |
|
||||
* @overview es6-promise - a tiny implementation of Promises/A+. |
|
||||
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) |
|
||||
* @license Licensed under MIT license |
|
||||
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
|
|
||||
* @version 2.0.0 |
|
||||
*/ |
|
||||
|
|
||||
(function() { |
|
||||
"use strict"; |
|
||||
|
|
||||
function $$utils$$objectOrFunction(x) { |
|
||||
return typeof x === 'function' || (typeof x === 'object' && x !== null); |
|
||||
} |
|
||||
|
|
||||
function $$utils$$isFunction(x) { |
|
||||
return typeof x === 'function'; |
|
||||
} |
|
||||
|
|
||||
function $$utils$$isMaybeThenable(x) { |
|
||||
return typeof x === 'object' && x !== null; |
|
||||
} |
|
||||
|
|
||||
var $$utils$$_isArray; |
|
||||
|
|
||||
if (!Array.isArray) { |
|
||||
$$utils$$_isArray = function (x) { |
|
||||
return Object.prototype.toString.call(x) === '[object Array]'; |
|
||||
}; |
|
||||
} else { |
|
||||
$$utils$$_isArray = Array.isArray; |
|
||||
} |
|
||||
|
|
||||
var $$utils$$isArray = $$utils$$_isArray; |
|
||||
var $$utils$$now = Date.now || function() { return new Date().getTime(); }; |
|
||||
function $$utils$$F() { } |
|
||||
|
|
||||
var $$utils$$o_create = (Object.create || function (o) { |
|
||||
if (arguments.length > 1) { |
|
||||
throw new Error('Second argument not supported'); |
|
||||
} |
|
||||
if (typeof o !== 'object') { |
|
||||
throw new TypeError('Argument must be an object'); |
|
||||
} |
|
||||
$$utils$$F.prototype = o; |
|
||||
return new $$utils$$F(); |
|
||||
}); |
|
||||
|
|
||||
var $$asap$$len = 0; |
|
||||
|
|
||||
var $$asap$$default = function asap(callback, arg) { |
|
||||
$$asap$$queue[$$asap$$len] = callback; |
|
||||
$$asap$$queue[$$asap$$len + 1] = arg; |
|
||||
$$asap$$len += 2; |
|
||||
if ($$asap$$len === 2) { |
|
||||
// If len is 1, that means that we need to schedule an async flush.
|
|
||||
// If additional callbacks are queued before the queue is flushed, they
|
|
||||
// will be processed by this flush that we are scheduling.
|
|
||||
$$asap$$scheduleFlush(); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var $$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {}; |
|
||||
var $$asap$$BrowserMutationObserver = $$asap$$browserGlobal.MutationObserver || $$asap$$browserGlobal.WebKitMutationObserver; |
|
||||
|
|
||||
// test for web worker but not in IE10
|
|
||||
var $$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && |
|
||||
typeof importScripts !== 'undefined' && |
|
||||
typeof MessageChannel !== 'undefined'; |
|
||||
|
|
||||
// node
|
|
||||
function $$asap$$useNextTick() { |
|
||||
return function() { |
|
||||
process.nextTick($$asap$$flush); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
function $$asap$$useMutationObserver() { |
|
||||
var iterations = 0; |
|
||||
var observer = new $$asap$$BrowserMutationObserver($$asap$$flush); |
|
||||
var node = document.createTextNode(''); |
|
||||
observer.observe(node, { characterData: true }); |
|
||||
|
|
||||
return function() { |
|
||||
node.data = (iterations = ++iterations % 2); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
// web worker
|
|
||||
function $$asap$$useMessageChannel() { |
|
||||
var channel = new MessageChannel(); |
|
||||
channel.port1.onmessage = $$asap$$flush; |
|
||||
return function () { |
|
||||
channel.port2.postMessage(0); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
function $$asap$$useSetTimeout() { |
|
||||
return function() { |
|
||||
setTimeout($$asap$$flush, 1); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
var $$asap$$queue = new Array(1000); |
|
||||
|
|
||||
function $$asap$$flush() { |
|
||||
for (var i = 0; i < $$asap$$len; i+=2) { |
|
||||
var callback = $$asap$$queue[i]; |
|
||||
var arg = $$asap$$queue[i+1]; |
|
||||
|
|
||||
callback(arg); |
|
||||
|
|
||||
$$asap$$queue[i] = undefined; |
|
||||
$$asap$$queue[i+1] = undefined; |
|
||||
} |
|
||||
|
|
||||
$$asap$$len = 0; |
|
||||
} |
|
||||
|
|
||||
var $$asap$$scheduleFlush; |
|
||||
|
|
||||
// Decide what async method to use to triggering processing of queued callbacks:
|
|
||||
if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { |
|
||||
$$asap$$scheduleFlush = $$asap$$useNextTick(); |
|
||||
} else if ($$asap$$BrowserMutationObserver) { |
|
||||
$$asap$$scheduleFlush = $$asap$$useMutationObserver(); |
|
||||
} else if ($$asap$$isWorker) { |
|
||||
$$asap$$scheduleFlush = $$asap$$useMessageChannel(); |
|
||||
} else { |
|
||||
$$asap$$scheduleFlush = $$asap$$useSetTimeout(); |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$noop() {} |
|
||||
var $$$internal$$PENDING = void 0; |
|
||||
var $$$internal$$FULFILLED = 1; |
|
||||
var $$$internal$$REJECTED = 2; |
|
||||
var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject(); |
|
||||
|
|
||||
function $$$internal$$selfFullfillment() { |
|
||||
return new TypeError("You cannot resolve a promise with itself"); |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$cannotReturnOwn() { |
|
||||
return new TypeError('A promises callback cannot return that same promise.') |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$getThen(promise) { |
|
||||
try { |
|
||||
return promise.then; |
|
||||
} catch(error) { |
|
||||
$$$internal$$GET_THEN_ERROR.error = error; |
|
||||
return $$$internal$$GET_THEN_ERROR; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { |
|
||||
try { |
|
||||
then.call(value, fulfillmentHandler, rejectionHandler); |
|
||||
} catch(e) { |
|
||||
return e; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$handleForeignThenable(promise, thenable, then) { |
|
||||
$$asap$$default(function(promise) { |
|
||||
var sealed = false; |
|
||||
var error = $$$internal$$tryThen(then, thenable, function(value) { |
|
||||
if (sealed) { return; } |
|
||||
sealed = true; |
|
||||
if (thenable !== value) { |
|
||||
$$$internal$$resolve(promise, value); |
|
||||
} else { |
|
||||
$$$internal$$fulfill(promise, value); |
|
||||
} |
|
||||
}, function(reason) { |
|
||||
if (sealed) { return; } |
|
||||
sealed = true; |
|
||||
|
|
||||
$$$internal$$reject(promise, reason); |
|
||||
}, 'Settle: ' + (promise._label || ' unknown promise')); |
|
||||
|
|
||||
if (!sealed && error) { |
|
||||
sealed = true; |
|
||||
$$$internal$$reject(promise, error); |
|
||||
} |
|
||||
}, promise); |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$handleOwnThenable(promise, thenable) { |
|
||||
if (thenable._state === $$$internal$$FULFILLED) { |
|
||||
$$$internal$$fulfill(promise, thenable._result); |
|
||||
} else if (promise._state === $$$internal$$REJECTED) { |
|
||||
$$$internal$$reject(promise, thenable._result); |
|
||||
} else { |
|
||||
$$$internal$$subscribe(thenable, undefined, function(value) { |
|
||||
$$$internal$$resolve(promise, value); |
|
||||
}, function(reason) { |
|
||||
$$$internal$$reject(promise, reason); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$handleMaybeThenable(promise, maybeThenable) { |
|
||||
if (maybeThenable.constructor === promise.constructor) { |
|
||||
$$$internal$$handleOwnThenable(promise, maybeThenable); |
|
||||
} else { |
|
||||
var then = $$$internal$$getThen(maybeThenable); |
|
||||
|
|
||||
if (then === $$$internal$$GET_THEN_ERROR) { |
|
||||
$$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error); |
|
||||
} else if (then === undefined) { |
|
||||
$$$internal$$fulfill(promise, maybeThenable); |
|
||||
} else if ($$utils$$isFunction(then)) { |
|
||||
$$$internal$$handleForeignThenable(promise, maybeThenable, then); |
|
||||
} else { |
|
||||
$$$internal$$fulfill(promise, maybeThenable); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$resolve(promise, value) { |
|
||||
if (promise === value) { |
|
||||
$$$internal$$reject(promise, $$$internal$$selfFullfillment()); |
|
||||
} else if ($$utils$$objectOrFunction(value)) { |
|
||||
$$$internal$$handleMaybeThenable(promise, value); |
|
||||
} else { |
|
||||
$$$internal$$fulfill(promise, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$publishRejection(promise) { |
|
||||
if (promise._onerror) { |
|
||||
promise._onerror(promise._result); |
|
||||
} |
|
||||
|
|
||||
$$$internal$$publish(promise); |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$fulfill(promise, value) { |
|
||||
if (promise._state !== $$$internal$$PENDING) { return; } |
|
||||
|
|
||||
promise._result = value; |
|
||||
promise._state = $$$internal$$FULFILLED; |
|
||||
|
|
||||
if (promise._subscribers.length === 0) { |
|
||||
} else { |
|
||||
$$asap$$default($$$internal$$publish, promise); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$reject(promise, reason) { |
|
||||
if (promise._state !== $$$internal$$PENDING) { return; } |
|
||||
promise._state = $$$internal$$REJECTED; |
|
||||
promise._result = reason; |
|
||||
|
|
||||
$$asap$$default($$$internal$$publishRejection, promise); |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) { |
|
||||
var subscribers = parent._subscribers; |
|
||||
var length = subscribers.length; |
|
||||
|
|
||||
parent._onerror = null; |
|
||||
|
|
||||
subscribers[length] = child; |
|
||||
subscribers[length + $$$internal$$FULFILLED] = onFulfillment; |
|
||||
subscribers[length + $$$internal$$REJECTED] = onRejection; |
|
||||
|
|
||||
if (length === 0 && parent._state) { |
|
||||
$$asap$$default($$$internal$$publish, parent); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$publish(promise) { |
|
||||
var subscribers = promise._subscribers; |
|
||||
var settled = promise._state; |
|
||||
|
|
||||
if (subscribers.length === 0) { return; } |
|
||||
|
|
||||
var child, callback, detail = promise._result; |
|
||||
|
|
||||
for (var i = 0; i < subscribers.length; i += 3) { |
|
||||
child = subscribers[i]; |
|
||||
callback = subscribers[i + settled]; |
|
||||
|
|
||||
if (child) { |
|
||||
$$$internal$$invokeCallback(settled, child, callback, detail); |
|
||||
} else { |
|
||||
callback(detail); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
promise._subscribers.length = 0; |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$ErrorObject() { |
|
||||
this.error = null; |
|
||||
} |
|
||||
|
|
||||
var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject(); |
|
||||
|
|
||||
function $$$internal$$tryCatch(callback, detail) { |
|
||||
try { |
|
||||
return callback(detail); |
|
||||
} catch(e) { |
|
||||
$$$internal$$TRY_CATCH_ERROR.error = e; |
|
||||
return $$$internal$$TRY_CATCH_ERROR; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$invokeCallback(settled, promise, callback, detail) { |
|
||||
var hasCallback = $$utils$$isFunction(callback), |
|
||||
value, error, succeeded, failed; |
|
||||
|
|
||||
if (hasCallback) { |
|
||||
value = $$$internal$$tryCatch(callback, detail); |
|
||||
|
|
||||
if (value === $$$internal$$TRY_CATCH_ERROR) { |
|
||||
failed = true; |
|
||||
error = value.error; |
|
||||
value = null; |
|
||||
} else { |
|
||||
succeeded = true; |
|
||||
} |
|
||||
|
|
||||
if (promise === value) { |
|
||||
$$$internal$$reject(promise, $$$internal$$cannotReturnOwn()); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
} else { |
|
||||
value = detail; |
|
||||
succeeded = true; |
|
||||
} |
|
||||
|
|
||||
if (promise._state !== $$$internal$$PENDING) { |
|
||||
// noop
|
|
||||
} else if (hasCallback && succeeded) { |
|
||||
$$$internal$$resolve(promise, value); |
|
||||
} else if (failed) { |
|
||||
$$$internal$$reject(promise, error); |
|
||||
} else if (settled === $$$internal$$FULFILLED) { |
|
||||
$$$internal$$fulfill(promise, value); |
|
||||
} else if (settled === $$$internal$$REJECTED) { |
|
||||
$$$internal$$reject(promise, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$internal$$initializePromise(promise, resolver) { |
|
||||
try { |
|
||||
resolver(function resolvePromise(value){ |
|
||||
$$$internal$$resolve(promise, value); |
|
||||
}, function rejectPromise(reason) { |
|
||||
$$$internal$$reject(promise, reason); |
|
||||
}); |
|
||||
} catch(e) { |
|
||||
$$$internal$$reject(promise, e); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$enumerator$$makeSettledResult(state, position, value) { |
|
||||
if (state === $$$internal$$FULFILLED) { |
|
||||
return { |
|
||||
state: 'fulfilled', |
|
||||
value: value |
|
||||
}; |
|
||||
} else { |
|
||||
return { |
|
||||
state: 'rejected', |
|
||||
reason: value |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function $$$enumerator$$Enumerator(Constructor, input, abortOnReject, label) { |
|
||||
this._instanceConstructor = Constructor; |
|
||||
this.promise = new Constructor($$$internal$$noop, label); |
|
||||
this._abortOnReject = abortOnReject; |
|
||||
|
|
||||
if (this._validateInput(input)) { |
|
||||
this._input = input; |
|
||||
this.length = input.length; |
|
||||
this._remaining = input.length; |
|
||||
|
|
||||
this._init(); |
|
||||
|
|
||||
if (this.length === 0) { |
|
||||
$$$internal$$fulfill(this.promise, this._result); |
|
||||
} else { |
|
||||
this.length = this.length || 0; |
|
||||
this._enumerate(); |
|
||||
if (this._remaining === 0) { |
|
||||
$$$internal$$fulfill(this.promise, this._result); |
|
||||
} |
|
||||
} |
|
||||
} else { |
|
||||
$$$internal$$reject(this.promise, this._validationError()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._validateInput = function(input) { |
|
||||
return $$utils$$isArray(input); |
|
||||
}; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._validationError = function() { |
|
||||
return new Error('Array Methods must be provided an Array'); |
|
||||
}; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._init = function() { |
|
||||
this._result = new Array(this.length); |
|
||||
}; |
|
||||
|
|
||||
var $$$enumerator$$default = $$$enumerator$$Enumerator; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._enumerate = function() { |
|
||||
var length = this.length; |
|
||||
var promise = this.promise; |
|
||||
var input = this._input; |
|
||||
|
|
||||
for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { |
|
||||
this._eachEntry(input[i], i); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { |
|
||||
var c = this._instanceConstructor; |
|
||||
if ($$utils$$isMaybeThenable(entry)) { |
|
||||
if (entry.constructor === c && entry._state !== $$$internal$$PENDING) { |
|
||||
entry._onerror = null; |
|
||||
this._settledAt(entry._state, i, entry._result); |
|
||||
} else { |
|
||||
this._willSettleAt(c.resolve(entry), i); |
|
||||
} |
|
||||
} else { |
|
||||
this._remaining--; |
|
||||
this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { |
|
||||
var promise = this.promise; |
|
||||
|
|
||||
if (promise._state === $$$internal$$PENDING) { |
|
||||
this._remaining--; |
|
||||
|
|
||||
if (this._abortOnReject && state === $$$internal$$REJECTED) { |
|
||||
$$$internal$$reject(promise, value); |
|
||||
} else { |
|
||||
this._result[i] = this._makeResult(state, i, value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (this._remaining === 0) { |
|
||||
$$$internal$$fulfill(promise, this._result); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) { |
|
||||
return value; |
|
||||
}; |
|
||||
|
|
||||
$$$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { |
|
||||
var enumerator = this; |
|
||||
|
|
||||
$$$internal$$subscribe(promise, undefined, function(value) { |
|
||||
enumerator._settledAt($$$internal$$FULFILLED, i, value); |
|
||||
}, function(reason) { |
|
||||
enumerator._settledAt($$$internal$$REJECTED, i, reason); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
var $$promise$all$$default = function all(entries, label) { |
|
||||
return new $$$enumerator$$default(this, entries, true /* abort on reject */, label).promise; |
|
||||
}; |
|
||||
|
|
||||
var $$promise$race$$default = function race(entries, label) { |
|
||||
/*jshint validthis:true */ |
|
||||
var Constructor = this; |
|
||||
|
|
||||
var promise = new Constructor($$$internal$$noop, label); |
|
||||
|
|
||||
if (!$$utils$$isArray(entries)) { |
|
||||
$$$internal$$reject(promise, new TypeError('You must pass an array to race.')); |
|
||||
return promise; |
|
||||
} |
|
||||
|
|
||||
var length = entries.length; |
|
||||
|
|
||||
function onFulfillment(value) { |
|
||||
$$$internal$$resolve(promise, value); |
|
||||
} |
|
||||
|
|
||||
function onRejection(reason) { |
|
||||
$$$internal$$reject(promise, reason); |
|
||||
} |
|
||||
|
|
||||
for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { |
|
||||
$$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); |
|
||||
} |
|
||||
|
|
||||
return promise; |
|
||||
}; |
|
||||
|
|
||||
var $$promise$resolve$$default = function resolve(object, label) { |
|
||||
/*jshint validthis:true */ |
|
||||
var Constructor = this; |
|
||||
|
|
||||
if (object && typeof object === 'object' && object.constructor === Constructor) { |
|
||||
return object; |
|
||||
} |
|
||||
|
|
||||
var promise = new Constructor($$$internal$$noop, label); |
|
||||
$$$internal$$resolve(promise, object); |
|
||||
return promise; |
|
||||
}; |
|
||||
|
|
||||
var $$promise$reject$$default = function reject(reason, label) { |
|
||||
/*jshint validthis:true */ |
|
||||
var Constructor = this; |
|
||||
var promise = new Constructor($$$internal$$noop, label); |
|
||||
$$$internal$$reject(promise, reason); |
|
||||
return promise; |
|
||||
}; |
|
||||
|
|
||||
var $$es6$promise$promise$$counter = 0; |
|
||||
|
|
||||
function $$es6$promise$promise$$needsResolver() { |
|
||||
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); |
|
||||
} |
|
||||
|
|
||||
function $$es6$promise$promise$$needsNew() { |
|
||||
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); |
|
||||
} |
|
||||
|
|
||||
var $$es6$promise$promise$$default = $$es6$promise$promise$$Promise; |
|
||||
|
|
||||
/** |
|
||||
Promise objects represent the eventual result of an asynchronous operation. The |
|
||||
primary way of interacting with a promise is through its `then` method, which |
|
||||
registers callbacks to receive either a promise’s eventual value or the reason |
|
||||
why the promise cannot be fulfilled. |
|
||||
|
|
||||
Terminology |
|
||||
----------- |
|
||||
|
|
||||
- `promise` is an object or function with a `then` method whose behavior conforms to this specification. |
|
||||
- `thenable` is an object or function that defines a `then` method. |
|
||||
- `value` is any legal JavaScript value (including undefined, a thenable, or a promise). |
|
||||
- `exception` is a value that is thrown using the throw statement. |
|
||||
- `reason` is a value that indicates why a promise was rejected. |
|
||||
- `settled` the final resting state of a promise, fulfilled or rejected. |
|
||||
|
|
||||
A promise can be in one of three states: pending, fulfilled, or rejected. |
|
||||
|
|
||||
Promises that are fulfilled have a fulfillment value and are in the fulfilled |
|
||||
state. Promises that are rejected have a rejection reason and are in the |
|
||||
rejected state. A fulfillment value is never a thenable. |
|
||||
|
|
||||
Promises can also be said to *resolve* a value. If this value is also a |
|
||||
promise, then the original promise's settled state will match the value's |
|
||||
settled state. So a promise that *resolves* a promise that rejects will |
|
||||
itself reject, and a promise that *resolves* a promise that fulfills will |
|
||||
itself fulfill. |
|
||||
|
|
||||
|
|
||||
Basic Usage: |
|
||||
------------ |
|
||||
|
|
||||
```js
|
|
||||
var promise = new Promise(function(resolve, reject) { |
|
||||
// on success
|
|
||||
resolve(value); |
|
||||
|
|
||||
// on failure
|
|
||||
reject(reason); |
|
||||
}); |
|
||||
|
|
||||
promise.then(function(value) { |
|
||||
// on fulfillment
|
|
||||
}, function(reason) { |
|
||||
// on rejection
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Advanced Usage: |
|
||||
--------------- |
|
||||
|
|
||||
Promises shine when abstracting away asynchronous interactions such as |
|
||||
`XMLHttpRequest`s. |
|
||||
|
|
||||
```js
|
|
||||
function getJSON(url) { |
|
||||
return new Promise(function(resolve, reject){ |
|
||||
var xhr = new XMLHttpRequest(); |
|
||||
|
|
||||
xhr.open('GET', url); |
|
||||
xhr.onreadystatechange = handler; |
|
||||
xhr.responseType = 'json'; |
|
||||
xhr.setRequestHeader('Accept', 'application/json'); |
|
||||
xhr.send(); |
|
||||
|
|
||||
function handler() { |
|
||||
if (this.readyState === this.DONE) { |
|
||||
if (this.status === 200) { |
|
||||
resolve(this.response); |
|
||||
} else { |
|
||||
reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
getJSON('/posts.json').then(function(json) { |
|
||||
// on fulfillment
|
|
||||
}, function(reason) { |
|
||||
// on rejection
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Unlike callbacks, promises are great composable primitives. |
|
||||
|
|
||||
```js
|
|
||||
Promise.all([ |
|
||||
getJSON('/posts'), |
|
||||
getJSON('/comments') |
|
||||
]).then(function(values){ |
|
||||
values[0] // => postsJSON
|
|
||||
values[1] // => commentsJSON
|
|
||||
|
|
||||
return values; |
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
@class Promise |
|
||||
@param {function} resolver |
|
||||
@param {String} label optional string for labeling the promise. |
|
||||
Useful for tooling. |
|
||||
@constructor |
|
||||
*/ |
|
||||
function $$es6$promise$promise$$Promise(resolver, label) { |
|
||||
this._id = $$es6$promise$promise$$counter++; |
|
||||
this._label = label; |
|
||||
this._state = undefined; |
|
||||
this._result = undefined; |
|
||||
this._subscribers = []; |
|
||||
|
|
||||
if ($$$internal$$noop !== resolver) { |
|
||||
if (!$$utils$$isFunction(resolver)) { |
|
||||
$$es6$promise$promise$$needsResolver(); |
|
||||
} |
|
||||
|
|
||||
if (!(this instanceof $$es6$promise$promise$$Promise)) { |
|
||||
$$es6$promise$promise$$needsNew(); |
|
||||
} |
|
||||
|
|
||||
$$$internal$$initializePromise(this, resolver); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$$es6$promise$promise$$Promise.all = $$promise$all$$default; |
|
||||
$$es6$promise$promise$$Promise.race = $$promise$race$$default; |
|
||||
$$es6$promise$promise$$Promise.resolve = $$promise$resolve$$default; |
|
||||
$$es6$promise$promise$$Promise.reject = $$promise$reject$$default; |
|
||||
|
|
||||
$$es6$promise$promise$$Promise.prototype = { |
|
||||
constructor: $$es6$promise$promise$$Promise, |
|
||||
|
|
||||
/** |
|
||||
The primary way of interacting with a promise is through its `then` method, |
|
||||
which registers callbacks to receive either a promise's eventual value or the |
|
||||
reason why the promise cannot be fulfilled. |
|
||||
|
|
||||
```js
|
|
||||
findUser().then(function(user){ |
|
||||
// user is available
|
|
||||
}, function(reason){ |
|
||||
// user is unavailable, and you are given the reason why
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Chaining |
|
||||
-------- |
|
||||
|
|
||||
The return value of `then` is itself a promise. This second, 'downstream' |
|
||||
promise is resolved with the return value of the first promise's fulfillment |
|
||||
or rejection handler, or rejected if the handler throws an exception. |
|
||||
|
|
||||
```js
|
|
||||
findUser().then(function (user) { |
|
||||
return user.name; |
|
||||
}, function (reason) { |
|
||||
return 'default name'; |
|
||||
}).then(function (userName) { |
|
||||
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
|
|
||||
// will be `'default name'`
|
|
||||
}); |
|
||||
|
|
||||
findUser().then(function (user) { |
|
||||
throw new Error('Found user, but still unhappy'); |
|
||||
}, function (reason) { |
|
||||
throw new Error('`findUser` rejected and we're unhappy'); |
|
||||
}).then(function (value) { |
|
||||
// never reached
|
|
||||
}, function (reason) { |
|
||||
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
|
|
||||
// If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
|
|
||||
}); |
|
||||
``` |
|
||||
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. |
|
||||
|
|
||||
```js
|
|
||||
findUser().then(function (user) { |
|
||||
throw new PedagogicalException('Upstream error'); |
|
||||
}).then(function (value) { |
|
||||
// never reached
|
|
||||
}).then(function (value) { |
|
||||
// never reached
|
|
||||
}, function (reason) { |
|
||||
// The `PedgagocialException` is propagated all the way down to here
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Assimilation |
|
||||
------------ |
|
||||
|
|
||||
Sometimes the value you want to propagate to a downstream promise can only be |
|
||||
retrieved asynchronously. This can be achieved by returning a promise in the |
|
||||
fulfillment or rejection handler. The downstream promise will then be pending |
|
||||
until the returned promise is settled. This is called *assimilation*. |
|
||||
|
|
||||
```js
|
|
||||
findUser().then(function (user) { |
|
||||
return findCommentsByAuthor(user); |
|
||||
}).then(function (comments) { |
|
||||
// The user's comments are now available
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
If the assimliated promise rejects, then the downstream promise will also reject. |
|
||||
|
|
||||
```js
|
|
||||
findUser().then(function (user) { |
|
||||
return findCommentsByAuthor(user); |
|
||||
}).then(function (comments) { |
|
||||
// If `findCommentsByAuthor` fulfills, we'll have the value here
|
|
||||
}, function (reason) { |
|
||||
// If `findCommentsByAuthor` rejects, we'll have the reason here
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Simple Example |
|
||||
-------------- |
|
||||
|
|
||||
Synchronous Example |
|
||||
|
|
||||
```javascript
|
|
||||
var result; |
|
||||
|
|
||||
try { |
|
||||
result = findResult(); |
|
||||
// success
|
|
||||
} catch(reason) { |
|
||||
// failure
|
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
Errback Example |
|
||||
|
|
||||
```js
|
|
||||
findResult(function(result, err){ |
|
||||
if (err) { |
|
||||
// failure
|
|
||||
} else { |
|
||||
// success
|
|
||||
} |
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Promise Example; |
|
||||
|
|
||||
```javascript
|
|
||||
findResult().then(function(result){ |
|
||||
// success
|
|
||||
}, function(reason){ |
|
||||
// failure
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Advanced Example |
|
||||
-------------- |
|
||||
|
|
||||
Synchronous Example |
|
||||
|
|
||||
```javascript
|
|
||||
var author, books; |
|
||||
|
|
||||
try { |
|
||||
author = findAuthor(); |
|
||||
books = findBooksByAuthor(author); |
|
||||
// success
|
|
||||
} catch(reason) { |
|
||||
// failure
|
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
Errback Example |
|
||||
|
|
||||
```js
|
|
||||
|
|
||||
function foundBooks(books) { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function failure(reason) { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
findAuthor(function(author, err){ |
|
||||
if (err) { |
|
||||
failure(err); |
|
||||
// failure
|
|
||||
} else { |
|
||||
try { |
|
||||
findBoooksByAuthor(author, function(books, err) { |
|
||||
if (err) { |
|
||||
failure(err); |
|
||||
} else { |
|
||||
try { |
|
||||
foundBooks(books); |
|
||||
} catch(reason) { |
|
||||
failure(reason); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} catch(error) { |
|
||||
failure(err); |
|
||||
} |
|
||||
// success
|
|
||||
} |
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
Promise Example; |
|
||||
|
|
||||
```javascript
|
|
||||
findAuthor(). |
|
||||
then(findBooksByAuthor). |
|
||||
then(function(books){ |
|
||||
// found books
|
|
||||
}).catch(function(reason){ |
|
||||
// something went wrong
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
@method then |
|
||||
@param {Function} onFulfilled |
|
||||
@param {Function} onRejected |
|
||||
@param {String} label optional string for labeling the promise. |
|
||||
Useful for tooling. |
|
||||
@return {Promise} |
|
||||
*/ |
|
||||
then: function(onFulfillment, onRejection, label) { |
|
||||
var parent = this; |
|
||||
var state = parent._state; |
|
||||
|
|
||||
if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) { |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
parent._onerror = null; |
|
||||
|
|
||||
var child = new this.constructor($$$internal$$noop, label); |
|
||||
var result = parent._result; |
|
||||
|
|
||||
if (state) { |
|
||||
var callback = arguments[state - 1]; |
|
||||
$$asap$$default(function(){ |
|
||||
$$$internal$$invokeCallback(state, child, callback, result); |
|
||||
}); |
|
||||
} else { |
|
||||
$$$internal$$subscribe(parent, child, onFulfillment, onRejection); |
|
||||
} |
|
||||
|
|
||||
return child; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same |
|
||||
as the catch block of a try/catch statement. |
|
||||
|
|
||||
```js
|
|
||||
function findAuthor(){ |
|
||||
throw new Error('couldn't find that author'); |
|
||||
} |
|
||||
|
|
||||
// synchronous
|
|
||||
try { |
|
||||
findAuthor(); |
|
||||
} catch(reason) { |
|
||||
// something went wrong
|
|
||||
} |
|
||||
|
|
||||
// async with promises
|
|
||||
findAuthor().catch(function(reason){ |
|
||||
// something went wrong
|
|
||||
}); |
|
||||
``` |
|
||||
|
|
||||
@method catch |
|
||||
@param {Function} onRejection |
|
||||
@param {String} label optional string for labeling the promise. |
|
||||
Useful for tooling. |
|
||||
@return {Promise} |
|
||||
*/ |
|
||||
'catch': function(onRejection, label) { |
|
||||
return this.then(null, onRejection, label); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var $$es6$promise$polyfill$$default = function polyfill() { |
|
||||
var local; |
|
||||
|
|
||||
if (typeof global !== 'undefined') { |
|
||||
local = global; |
|
||||
} else if (typeof window !== 'undefined' && window.document) { |
|
||||
local = window; |
|
||||
} else { |
|
||||
local = self; |
|
||||
} |
|
||||
|
|
||||
var es6PromiseSupport = |
|
||||
"Promise" in local && |
|
||||
// Some of these methods are missing from
|
|
||||
// Firefox/Chrome experimental implementations
|
|
||||
"resolve" in local.Promise && |
|
||||
"reject" in local.Promise && |
|
||||
"all" in local.Promise && |
|
||||
"race" in local.Promise && |
|
||||
// Older version of the spec had a resolver object
|
|
||||
// as the arg rather than a function
|
|
||||
(function() { |
|
||||
var resolve; |
|
||||
new local.Promise(function(r) { resolve = r; }); |
|
||||
return $$utils$$isFunction(resolve); |
|
||||
}()); |
|
||||
|
|
||||
if (!es6PromiseSupport) { |
|
||||
local.Promise = $$es6$promise$promise$$default; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var es6$promise$umd$$ES6Promise = { |
|
||||
Promise: $$es6$promise$promise$$default, |
|
||||
polyfill: $$es6$promise$polyfill$$default |
|
||||
}; |
|
||||
|
|
||||
/* global define:true module:true window: true */ |
|
||||
if (typeof define === 'function' && define['amd']) { |
|
||||
define(function() { return es6$promise$umd$$ES6Promise; }); |
|
||||
} else if (typeof module !== 'undefined' && module['exports']) { |
|
||||
module['exports'] = es6$promise$umd$$ES6Promise; |
|
||||
} else if (typeof this !== 'undefined') { |
|
||||
this['ES6Promise'] = es6$promise$umd$$ES6Promise; |
|
||||
} |
|
||||
}).call(this); |
|
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,76 @@ |
|||||
|
<!doctype> |
||||
|
<html> |
||||
|
|
||||
|
<head> |
||||
|
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script> |
||||
|
<script type="text/javascript" src="../dist/ethereum.js"></script> |
||||
|
<script type="text/javascript"> |
||||
|
|
||||
|
var web3 = require('web3'); |
||||
|
web3.setProvider(new web3.providers.HttpSyncProvider()); |
||||
|
|
||||
|
// solidity source code |
||||
|
var source = "" + |
||||
|
"contract test {\n" + |
||||
|
" function multiply(uint[] a) returns(uint d) {\n" + |
||||
|
" return a[0] + a[1];\n" + |
||||
|
" }\n" + |
||||
|
"}\n"; |
||||
|
|
||||
|
// contract description, this will be autogenerated somehow |
||||
|
var desc = [{ |
||||
|
"name": "multiply(uint256[])", |
||||
|
"type": "function", |
||||
|
"inputs": [ |
||||
|
{ |
||||
|
"name": "a", |
||||
|
"type": "uint256[]" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
var contract; |
||||
|
|
||||
|
function createExampleContract() { |
||||
|
// hide create button |
||||
|
document.getElementById('create').style.visibility = 'hidden'; |
||||
|
document.getElementById('source').innerText = source; |
||||
|
|
||||
|
// create contract |
||||
|
var address = web3.eth.transact({code: web3.eth.solidity(source)}); |
||||
|
contract = web3.eth.contract(address, desc); |
||||
|
document.getElementById('call').style.visibility = 'visible'; |
||||
|
} |
||||
|
|
||||
|
function callExampleContract() { |
||||
|
// this should be generated by ethereum |
||||
|
var param = parseInt(document.getElementById('value').value); |
||||
|
var param2 = parseInt(document.getElementById('value2').value); |
||||
|
|
||||
|
// call the contract |
||||
|
var res = contract.call().multiply([param, param2]); |
||||
|
document.getElementById('result').innerText = res.toString(10); |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
|
</head> |
||||
|
<body> |
||||
|
<h1>contract</h1> |
||||
|
<div id="source"></div> |
||||
|
<div id='create'> |
||||
|
<button type="button" onClick="createExampleContract();">create example contract</button> |
||||
|
</div> |
||||
|
<div id='call' style='visibility: hidden;'> |
||||
|
<input type="number" id="value" onkeyup='callExampleContract()'></input> |
||||
|
<input type="number" id="value2" onkeyup='callExampleContract()'></input> |
||||
|
</div> |
||||
|
<div id="result"></div> |
||||
|
</body> |
||||
|
</html> |
||||
|
|
@ -0,0 +1,120 @@ |
|||||
|
<!doctype> |
||||
|
<html> |
||||
|
<head> |
||||
|
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script> |
||||
|
<script type="text/javascript" src="../dist/ethereum.js"></script> |
||||
|
<script type="text/javascript"> |
||||
|
var web3 = require('web3'); |
||||
|
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); |
||||
|
|
||||
|
var desc = [{ |
||||
|
"type":"event", |
||||
|
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}], |
||||
|
"name":"Event" |
||||
|
}, { |
||||
|
"type":"event", |
||||
|
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}], |
||||
|
"name":"Event2" |
||||
|
}, { |
||||
|
"type":"function", |
||||
|
"inputs": [{"name":"a","type":"uint256"}], |
||||
|
"name":"foo", |
||||
|
"outputs": [] |
||||
|
}]; |
||||
|
|
||||
|
var address = '0x01'; |
||||
|
|
||||
|
var contract = web3.eth.contract(address, desc); |
||||
|
|
||||
|
function test1() { |
||||
|
// "{"topic":["0x83c9849c","0xc4d76332"],"address":"0x01"}" |
||||
|
web3.eth.watch(contract).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test2() { |
||||
|
// "{"topic":["0x83c9849c"],"address":"0x01"}" |
||||
|
web3.eth.watch(contract.Event).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test3() { |
||||
|
// "{"topic":["0x83c9849c"],"address":"0x01"}" |
||||
|
contract.Event().changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test4() { |
||||
|
// "{"topic":["0x83c9849c","0000000000000000000000000000000000000000000000000000000000000045"],"address":"0x01"}" |
||||
|
contract.Event({a: 69}).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test5() { |
||||
|
// "{"topic":["0x83c9849c",["0000000000000000000000000000000000000000000000000000000000000045","000000000000000000000000000000000000000000000000000000000000002a"]],"address":"0x01"}" |
||||
|
contract.Event({a: [69, 42]}).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test6() { |
||||
|
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}" |
||||
|
contract.Event({a: 30}, {max: 100}).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test7() { |
||||
|
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"address":"0x01"}" |
||||
|
web3.eth.watch(contract.Event, {a: 30}).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function test8() { |
||||
|
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}" |
||||
|
web3.eth.watch(contract.Event, {a: 30}, {max: 100}).changed(function (res) { |
||||
|
|
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// not valid |
||||
|
// function testX() { |
||||
|
// web3.eth.watch([contract.Event, contract.Event2]).changed(function (res) { |
||||
|
// }); |
||||
|
// }; |
||||
|
|
||||
|
</script> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div> |
||||
|
<button type="button" onClick="test1();">test1</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test2();">test2</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test3();">test3</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test4();">test4</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test5();">test5</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test6();">test6</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test7();">test7</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button type="button" onClick="test8();">test8</button> |
||||
|
</div> |
||||
|
</body> |
||||
|
</html> |
@ -1,16 +1,12 @@ |
|||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||
|
|
||||
require('es6-promise').polyfill(); |
|
||||
|
|
||||
var web3 = require("../index.js"); |
var web3 = require("../index.js"); |
||||
|
|
||||
web3.setProvider(new web3.providers.HttpRpcProvider('http://localhost:8080')); |
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); |
||||
|
|
||||
|
var coinbase = web3.eth.coinbase; |
||||
|
console.log(coinbase); |
||||
|
|
||||
|
var balance = web3.eth.balanceAt(coinbase); |
||||
|
console.log(balance); |
||||
|
|
||||
web3.eth.coinbase.then(function(result){ |
|
||||
console.log(result); |
|
||||
return web3.eth.balanceAt(result); |
|
||||
}).then(function(balance){ |
|
||||
console.log(web3.toDecimal(balance)); |
|
||||
}).catch(function(err){ |
|
||||
console.log(err); |
|
||||
}); |
|
@ -1,114 +0,0 @@ |
|||||
/* |
|
||||
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 <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file autoprovider.js |
|
||||
* @authors: |
|
||||
* Marek Kotewicz <marek@ethdev.com> |
|
||||
* Marian Oancea <marian@ethdev.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
/* |
|
||||
* @brief if qt object is available, uses QtProvider, |
|
||||
* if not tries to connect over websockets |
|
||||
* if it fails, it uses HttpRpcProvider |
|
||||
*/ |
|
||||
|
|
||||
var web3 = require('./web3'); // jshint ignore:line
|
|
||||
if (process.env.NODE_ENV !== 'build') { |
|
||||
var WebSocket = require('ws'); // 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; |
|
||||
} |
|
||||
|
|
||||
// before we determine what provider we are, we have to cache request
|
|
||||
this.sendQueue = []; |
|
||||
this.onmessageQueue = []; |
|
||||
|
|
||||
if (navigator.qt) { |
|
||||
this.provider = new web3.providers.QtProvider(); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
userOptions = userOptions || {}; |
|
||||
var options = { |
|
||||
httprpc: userOptions.httprpc || 'http://localhost:8080', |
|
||||
websockets: userOptions.websockets || 'ws://localhost:40404/eth' |
|
||||
}; |
|
||||
|
|
||||
var self = this; |
|
||||
var closeWithSuccess = function (success) { |
|
||||
ws.close(); |
|
||||
if (success) { |
|
||||
self.provider = new web3.providers.WebSocketProvider(options.websockets); |
|
||||
} else { |
|
||||
self.provider = new web3.providers.HttpRpcProvider(options.httprpc); |
|
||||
self.poll = self.provider.poll.bind(self.provider); |
|
||||
} |
|
||||
self.sendQueue.forEach(function (payload) { |
|
||||
self.provider.send(payload); |
|
||||
}); |
|
||||
self.onmessageQueue.forEach(function (handler) { |
|
||||
self.provider.onmessage = handler; |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
var ws = new WebSocket(options.websockets); |
|
||||
|
|
||||
ws.onopen = function() { |
|
||||
closeWithSuccess(true); |
|
||||
}; |
|
||||
|
|
||||
ws.onerror = function() { |
|
||||
closeWithSuccess(false); |
|
||||
}; |
|
||||
}; |
|
||||
|
|
||||
/// 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); |
|
||||
return; |
|
||||
} |
|
||||
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) { |
|
||||
this.provider.onmessage = handler; |
|
||||
return; |
|
||||
} |
|
||||
this.onmessageQueue.push(handler); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
module.exports = AutoProvider; |
|
@ -0,0 +1,33 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file const.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
/// required to define ETH_BIGNUMBER_ROUNDING_MODE
|
||||
|
if (process.env.NODE_ENV !== 'build') { |
||||
|
var BigNumber = require('bignumber.js'); // jshint ignore:line
|
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
ETH_PADDING: 32, |
||||
|
ETH_SIGNATURE_LENGTH: 4, |
||||
|
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN } |
||||
|
}; |
||||
|
|
@ -0,0 +1,69 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file event.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
var abi = require('./abi'); |
||||
|
var utils = require('./utils'); |
||||
|
|
||||
|
var inputWithName = function (inputs, name) { |
||||
|
var index = utils.findIndex(inputs, function (input) { |
||||
|
return input.name === name; |
||||
|
}); |
||||
|
|
||||
|
if (index === -1) { |
||||
|
console.error('indexed param with name ' + name + ' not found'); |
||||
|
return undefined; |
||||
|
} |
||||
|
return inputs[index]; |
||||
|
}; |
||||
|
|
||||
|
var indexedParamsToTopics = function (event, indexed) { |
||||
|
// sort keys?
|
||||
|
return Object.keys(indexed).map(function (key) { |
||||
|
var inputs = [inputWithName(event.inputs, key)]; |
||||
|
|
||||
|
var value = indexed[key]; |
||||
|
if (value instanceof Array) { |
||||
|
return value.map(function (v) { |
||||
|
return abi.formatInput(inputs, [v]); |
||||
|
}); |
||||
|
} |
||||
|
return abi.formatInput(inputs, [value]); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
var implementationOfEvent = function (address, signature, event) { |
||||
|
|
||||
|
// valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'
|
||||
|
return function (indexed, options) { |
||||
|
var o = options || {}; |
||||
|
o.address = address; |
||||
|
o.topic = []; |
||||
|
o.topic.push(signature); |
||||
|
if (indexed) { |
||||
|
o.topic = o.topic.concat(indexedParamsToTopics(event, indexed)); |
||||
|
} |
||||
|
return o; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
module.exports = implementationOfEvent; |
||||
|
|
@ -0,0 +1,154 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file formatters.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
if (process.env.NODE_ENV !== 'build') { |
||||
|
var BigNumber = require('bignumber.js'); // jshint ignore:line
|
||||
|
} |
||||
|
|
||||
|
var utils = require('./utils'); |
||||
|
var c = require('./const'); |
||||
|
|
||||
|
/// @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; |
||||
|
}; |
||||
|
|
||||
|
/// Formats input value to byte representation of int
|
||||
|
/// If value is negative, return it's two's complement
|
||||
|
/// If the value is floating point, round it down
|
||||
|
/// @returns right-aligned byte representation of int
|
||||
|
var formatInputInt = function (value) { |
||||
|
var padding = c.ETH_PADDING * 2; |
||||
|
if (value instanceof BigNumber || typeof value === 'number') { |
||||
|
if (typeof value === 'number') |
||||
|
value = new BigNumber(value); |
||||
|
BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE); |
||||
|
value = value.round(); |
||||
|
|
||||
|
if (value.lessThan(0)) |
||||
|
value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1); |
||||
|
value = value.toString(16); |
||||
|
} |
||||
|
else if (value.indexOf('0x') === 0) |
||||
|
value = value.substr(2); |
||||
|
else if (typeof value === 'string') |
||||
|
value = formatInputInt(new BigNumber(value)); |
||||
|
else |
||||
|
value = (+value).toString(16); |
||||
|
return padLeft(value, padding); |
||||
|
}; |
||||
|
|
||||
|
/// Formats input value to byte representation of string
|
||||
|
/// @returns left-algined byte representation of string
|
||||
|
var formatInputString = function (value) { |
||||
|
return utils.fromAscii(value, c.ETH_PADDING).substr(2); |
||||
|
}; |
||||
|
|
||||
|
/// Formats input value to byte representation of bool
|
||||
|
/// @returns right-aligned byte representation bool
|
||||
|
var formatInputBool = function (value) { |
||||
|
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); |
||||
|
}; |
||||
|
|
||||
|
/// Formats input value to byte representation of real
|
||||
|
/// Values are multiplied by 2^m and encoded as integers
|
||||
|
/// @returns byte representation of real
|
||||
|
var formatInputReal = function (value) { |
||||
|
return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/// Check if input value is negative
|
||||
|
/// @param value is hex format
|
||||
|
/// @returns true if it is negative, otherwise false
|
||||
|
var signedIsNegative = function (value) { |
||||
|
return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1'; |
||||
|
}; |
||||
|
|
||||
|
/// Formats input right-aligned input bytes to int
|
||||
|
/// @returns right-aligned input bytes formatted to int
|
||||
|
var formatOutputInt = function (value) { |
||||
|
value = value || "0"; |
||||
|
// check if it's negative number
|
||||
|
// it it is, return two's complement
|
||||
|
if (signedIsNegative(value)) { |
||||
|
return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1); |
||||
|
} |
||||
|
return new BigNumber(value, 16); |
||||
|
}; |
||||
|
|
||||
|
/// Formats big right-aligned input bytes to uint
|
||||
|
/// @returns right-aligned input bytes formatted to uint
|
||||
|
var formatOutputUInt = function (value) { |
||||
|
value = value || "0"; |
||||
|
return new BigNumber(value, 16); |
||||
|
}; |
||||
|
|
||||
|
/// @returns input bytes formatted to real
|
||||
|
var formatOutputReal = function (value) { |
||||
|
return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); |
||||
|
}; |
||||
|
|
||||
|
/// @returns input bytes formatted to ureal
|
||||
|
var formatOutputUReal = function (value) { |
||||
|
return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); |
||||
|
}; |
||||
|
|
||||
|
/// @returns right-aligned input bytes formatted to hex
|
||||
|
var formatOutputHash = function (value) { |
||||
|
return "0x" + value; |
||||
|
}; |
||||
|
|
||||
|
/// @returns right-aligned input bytes formatted to bool
|
||||
|
var formatOutputBool = function (value) { |
||||
|
return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; |
||||
|
}; |
||||
|
|
||||
|
/// @returns left-aligned input bytes formatted to ascii string
|
||||
|
var formatOutputString = function (value) { |
||||
|
return utils.toAscii(value); |
||||
|
}; |
||||
|
|
||||
|
/// @returns right-aligned input bytes formatted to address
|
||||
|
var formatOutputAddress = function (value) { |
||||
|
return "0x" + value.slice(value.length - 40, value.length); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
module.exports = { |
||||
|
formatInputInt: formatInputInt, |
||||
|
formatInputString: formatInputString, |
||||
|
formatInputBool: formatInputBool, |
||||
|
formatInputReal: formatInputReal, |
||||
|
formatOutputInt: formatOutputInt, |
||||
|
formatOutputUInt: formatOutputUInt, |
||||
|
formatOutputReal: formatOutputReal, |
||||
|
formatOutputUReal: formatOutputUReal, |
||||
|
formatOutputHash: formatOutputHash, |
||||
|
formatOutputBool: formatOutputBool, |
||||
|
formatOutputString: formatOutputString, |
||||
|
formatOutputAddress: formatOutputAddress |
||||
|
}; |
||||
|
|
@ -1,126 +0,0 @@ |
|||||
/* |
|
||||
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 <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file httprpc.js |
|
||||
* @authors: |
|
||||
* Marek Kotewicz <marek@ethdev.com> |
|
||||
* Marian Oancea <marian@ethdev.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
// TODO: is these line is supposed to be here?
|
|
||||
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', |
|
||||
method: object.call, |
|
||||
params: object.args, |
|
||||
id: object._id |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
/// Transforms jsonrpc object to inner message
|
|
||||
/// @param incoming jsonrpc message
|
|
||||
/// @returns inner message object
|
|
||||
function formatJsonRpcMessage(message) { |
|
||||
var object = JSON.parse(message); |
|
||||
|
|
||||
return { |
|
||||
_id: object.id, |
|
||||
data: object.result, |
|
||||
error: object.error |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
/// 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); |
|
||||
|
|
||||
var request = new XMLHttpRequest(); |
|
||||
request.open("POST", this.host, true); |
|
||||
request.send(JSON.stringify(data)); |
|
||||
request.onreadystatechange = function () { |
|
||||
if (request.readyState === 4 && cb) { |
|
||||
cb(request); |
|
||||
} |
|
||||
}; |
|
||||
}; |
|
||||
|
|
||||
/// 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) { |
|
||||
self.handlers.forEach(function (handler) { |
|
||||
handler.call(self, formatJsonRpcMessage(request.responseText)); |
|
||||
}); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
/// 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) { |
|
||||
var parsed = JSON.parse(request.responseText); |
|
||||
if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) { |
|
||||
return; |
|
||||
} |
|
||||
self.handlers.forEach(function (handler) { |
|
||||
handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); |
|
||||
}); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
/// 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); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
module.exports = HttpRpcProvider; |
|
||||
|
|
@ -0,0 +1,70 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file httpsync.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* Marian Oancea <marian@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
if (process.env.NODE_ENV !== 'build') { |
||||
|
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
|
||||
|
} |
||||
|
|
||||
|
var HttpSyncProvider = function (host) { |
||||
|
this.handlers = []; |
||||
|
this.host = host || 'http://localhost:8080'; |
||||
|
}; |
||||
|
|
||||
|
/// Transforms inner message to proper jsonrpc object
|
||||
|
/// @param inner message object
|
||||
|
/// @returns jsonrpc object
|
||||
|
function formatJsonRpcObject(object) { |
||||
|
return { |
||||
|
jsonrpc: '2.0', |
||||
|
method: object.call, |
||||
|
params: object.args, |
||||
|
id: object._id |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/// Transforms jsonrpc object to inner message
|
||||
|
/// @param incoming jsonrpc message
|
||||
|
/// @returns inner message object
|
||||
|
function formatJsonRpcMessage(message) { |
||||
|
var object = JSON.parse(message); |
||||
|
|
||||
|
return { |
||||
|
_id: object.id, |
||||
|
data: object.result, |
||||
|
error: object.error |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
HttpSyncProvider.prototype.send = function (payload) { |
||||
|
var data = formatJsonRpcObject(payload); |
||||
|
|
||||
|
var request = new XMLHttpRequest(); |
||||
|
request.open('POST', this.host, false); |
||||
|
request.send(JSON.stringify(data)); |
||||
|
|
||||
|
// check request.status
|
||||
|
return request.responseText; |
||||
|
}; |
||||
|
|
||||
|
module.exports = HttpSyncProvider; |
||||
|
|
@ -0,0 +1,18 @@ |
|||||
|
var addressName = {"0x12378912345789": "Gav", "0x57835893478594739854": "Jeff"}; |
||||
|
var nameAddress = {}; |
||||
|
|
||||
|
for (var prop in addressName) { |
||||
|
if (addressName.hasOwnProperty(prop)) { |
||||
|
nameAddress[addressName[prop]] = prop; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var local = { |
||||
|
addressBook:{ |
||||
|
byName: addressName, |
||||
|
byAddress: nameAddress |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
if (typeof(module) !== "undefined") |
||||
|
module.exports = local; |
@ -1,57 +0,0 @@ |
|||||
/* |
|
||||
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 <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file qt.js |
|
||||
* @authors: |
|
||||
* Jeffrey Wilcke <jeff@ethdev.com> |
|
||||
* Marek Kotewicz <marek@ethdev.com> |
|
||||
* @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 = []; |
|
||||
|
|
||||
var self = this; |
|
||||
navigator.qt.onmessage = function (message) { |
|
||||
self.handlers.forEach(function (handler) { |
|
||||
handler.call(self, JSON.parse(message.data)); |
|
||||
}); |
|
||||
}; |
|
||||
}; |
|
||||
|
|
||||
/// 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); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
module.exports = QtProvider; |
|
@ -0,0 +1,32 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file qtsync.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* Marian Oancea <marian@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
var QtSyncProvider = function () { |
||||
|
}; |
||||
|
|
||||
|
QtSyncProvider.prototype.send = function (payload) { |
||||
|
return navigator.qt.callMethod(JSON.stringify(payload)); |
||||
|
}; |
||||
|
|
||||
|
module.exports = QtSyncProvider; |
||||
|
|
@ -0,0 +1,79 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file types.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
var f = require('./formatters'); |
||||
|
|
||||
|
/// @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; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
/// @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 inputTypes = function () { |
||||
|
|
||||
|
return [ |
||||
|
{ type: prefixedType('uint'), format: f.formatInputInt }, |
||||
|
{ type: prefixedType('int'), format: f.formatInputInt }, |
||||
|
{ type: prefixedType('hash'), format: f.formatInputInt }, |
||||
|
{ type: prefixedType('string'), format: f.formatInputString }, |
||||
|
{ type: prefixedType('real'), format: f.formatInputReal }, |
||||
|
{ type: prefixedType('ureal'), format: f.formatInputReal }, |
||||
|
{ type: namedType('address'), format: f.formatInputInt }, |
||||
|
{ type: namedType('bool'), format: f.formatInputBool } |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
/// Setups output formaters for solidity types
|
||||
|
/// @returns an array of output formatters
|
||||
|
var outputTypes = function () { |
||||
|
|
||||
|
return [ |
||||
|
{ type: prefixedType('uint'), format: f.formatOutputUInt }, |
||||
|
{ type: prefixedType('int'), format: f.formatOutputInt }, |
||||
|
{ type: prefixedType('hash'), format: f.formatOutputHash }, |
||||
|
{ type: prefixedType('string'), format: f.formatOutputString }, |
||||
|
{ type: prefixedType('real'), format: f.formatOutputReal }, |
||||
|
{ type: prefixedType('ureal'), format: f.formatOutputUReal }, |
||||
|
{ type: namedType('address'), format: f.formatOutputAddress }, |
||||
|
{ type: namedType('bool'), format: f.formatOutputBool } |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
module.exports = { |
||||
|
prefixedType: prefixedType, |
||||
|
namedType: namedType, |
||||
|
inputTypes: inputTypes, |
||||
|
outputTypes: outputTypes |
||||
|
}; |
||||
|
|
@ -0,0 +1,113 @@ |
|||||
|
/* |
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file utils.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
/// 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; |
||||
|
for (; i < array.length && !end; i++) { |
||||
|
end = callback(array[i]); |
||||
|
} |
||||
|
return end ? i - 1 : -1; |
||||
|
}; |
||||
|
|
||||
|
/// @returns ascii string representation of hex value prefixed with 0x
|
||||
|
var toAscii = function(hex) { |
||||
|
// Find termination
|
||||
|
var str = ""; |
||||
|
var i = 0, l = hex.length; |
||||
|
if (hex.substring(0, 2) === '0x') { |
||||
|
i = 2; |
||||
|
} |
||||
|
for (; i < l; i+=2) { |
||||
|
var code = parseInt(hex.substr(i, 2), 16); |
||||
|
if (code === 0) { |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
str += String.fromCharCode(code); |
||||
|
} |
||||
|
|
||||
|
return str; |
||||
|
}; |
||||
|
|
||||
|
var toHex = function(str) { |
||||
|
var hex = ""; |
||||
|
for(var i = 0; i < str.length; i++) { |
||||
|
var n = str.charCodeAt(i).toString(16); |
||||
|
hex += n.length < 2 ? '0' + n : n; |
||||
|
} |
||||
|
|
||||
|
return hex; |
||||
|
}; |
||||
|
|
||||
|
/// @returns hex representation (prefixed by 0x) of ascii string
|
||||
|
var fromAscii = function(str, pad) { |
||||
|
pad = pad === undefined ? 0 : pad; |
||||
|
var hex = toHex(str); |
||||
|
while (hex.length < pad*2) |
||||
|
hex += "00"; |
||||
|
return "0x" + hex; |
||||
|
}; |
||||
|
|
||||
|
/// @returns display name for function/event eg. multiply(uint256) -> multiply
|
||||
|
var extractDisplayName = function (name) { |
||||
|
var length = name.indexOf('('); |
||||
|
return length !== -1 ? name.substr(0, length) : name; |
||||
|
}; |
||||
|
|
||||
|
/// @returns overloaded part of function/event name
|
||||
|
var extractTypeName = function (name) { |
||||
|
/// TODO: make it invulnerable
|
||||
|
var length = name.indexOf('('); |
||||
|
return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)) : ""; |
||||
|
}; |
||||
|
|
||||
|
/// Filters all function from input abi
|
||||
|
/// @returns abi array with filtered objects of type 'function'
|
||||
|
var filterFunctions = function (json) { |
||||
|
return json.filter(function (current) { |
||||
|
return current.type === 'function'; |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/// Filters all events form input abi
|
||||
|
/// @returns abi array with filtered objects of type 'event'
|
||||
|
var filterEvents = function (json) { |
||||
|
return json.filter(function (current) { |
||||
|
return current.type === 'event'; |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
module.exports = { |
||||
|
findIndex: findIndex, |
||||
|
toAscii: toAscii, |
||||
|
fromAscii: fromAscii, |
||||
|
extractDisplayName: extractDisplayName, |
||||
|
extractTypeName: extractTypeName, |
||||
|
filterFunctions: filterFunctions, |
||||
|
filterEvents: filterEvents |
||||
|
}; |
||||
|
|
@ -1,98 +0,0 @@ |
|||||
/* |
|
||||
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 <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file websocket.js |
|
||||
* @authors: |
|
||||
* Jeffrey Wilcke <jeff@ethdev.com> |
|
||||
* Marek Kotewicz <marek@ethdev.com> |
|
||||
* Marian Oancea <marian@ethdev.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
// TODO: is these line is supposed to be here?
|
|
||||
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; |
|
||||
|
|
||||
this.ws = new WebSocket(host); |
|
||||
|
|
||||
var self = this; |
|
||||
this.ws.onmessage = function(event) { |
|
||||
for(var i = 0; i < self.handlers.length; i++) { |
|
||||
self.handlers[i].call(self, JSON.parse(event.data), event); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
this.ws.onopen = function() { |
|
||||
self.ready = true; |
|
||||
|
|
||||
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) { |
|
||||
var data = JSON.stringify(payload); |
|
||||
|
|
||||
this.ws.send(data); |
|
||||
} else { |
|
||||
this.queued.push(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); } |
|
||||
}); |
|
||||
|
|
||||
if (typeof(module) !== "undefined") |
|
||||
module.exports = WebSocketProvider; |
|
@ -0,0 +1,201 @@ |
|||||
|
var assert = require('assert'); |
||||
|
var contract = require('../lib/contract.js'); |
||||
|
|
||||
|
describe('contract', function() { |
||||
|
it('should create simple contract with one method from abi with explicit type name', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test(uint256)", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
// when
|
||||
|
var con = contract(null, description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal('function', typeof con.test); |
||||
|
assert.equal('function', typeof con.test['uint256']); |
||||
|
}); |
||||
|
|
||||
|
it('should create simple contract with one method from abi with implicit type name', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
// when
|
||||
|
var con = contract(null, description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal('function', typeof con.test); |
||||
|
assert.equal('function', typeof con.test['uint256']); |
||||
|
}); |
||||
|
|
||||
|
it('should create contract with multiple methods', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
}, { |
||||
|
"name": "test2", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
// when
|
||||
|
var con = contract(null, description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal('function', typeof con.test); |
||||
|
assert.equal('function', typeof con.test['uint256']); |
||||
|
assert.equal('function', typeof con.test2); |
||||
|
assert.equal('function', typeof con.test2['uint256']); |
||||
|
}); |
||||
|
|
||||
|
it('should create contract with overloaded methods', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
}, { |
||||
|
"name": "test", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "string" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
// when
|
||||
|
var con = contract(null, description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal('function', typeof con.test); |
||||
|
assert.equal('function', typeof con.test['uint256']); |
||||
|
assert.equal('function', typeof con.test['string']); |
||||
|
}); |
||||
|
|
||||
|
it('should create contract with no methods', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test(uint256)", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
|
||||
|
// when
|
||||
|
var con = contract(null, description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal('undefined', typeof con.test); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
it('should create contract with one event', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test", |
||||
|
"type": "event", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
|
||||
|
// when
|
||||
|
var con = contract(null, description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal('function', typeof con.test); |
||||
|
assert.equal('function', typeof con.test['uint256']); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
@ -0,0 +1,124 @@ |
|||||
|
var assert = require('assert'); |
||||
|
var event = require('../lib/event.js'); |
||||
|
var f = require('../lib/formatters.js'); |
||||
|
|
||||
|
describe('event', function () { |
||||
|
it('should create basic filter input object', function () { |
||||
|
|
||||
|
// given
|
||||
|
var address = '0x012345'; |
||||
|
var signature = '0x987654'; |
||||
|
var e = { |
||||
|
name: 'Event', |
||||
|
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
||||
|
}; |
||||
|
|
||||
|
// when
|
||||
|
var impl = event(address, signature, e); |
||||
|
var result = impl(); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal(result.address, address); |
||||
|
assert.equal(result.topic.length, 1); |
||||
|
assert.equal(result.topic[0], signature); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
it('should create filter input object with options', function () { |
||||
|
|
||||
|
// given
|
||||
|
var address = '0x012345'; |
||||
|
var signature = '0x987654'; |
||||
|
var options = { |
||||
|
earliest: 1, |
||||
|
latest: 2, |
||||
|
offset: 3, |
||||
|
max: 4 |
||||
|
}; |
||||
|
var e = { |
||||
|
name: 'Event', |
||||
|
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
||||
|
}; |
||||
|
|
||||
|
// when
|
||||
|
var impl = event(address, signature, e); |
||||
|
var result = impl({}, options); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal(result.address, address); |
||||
|
assert.equal(result.topic.length, 1); |
||||
|
assert.equal(result.topic[0], signature); |
||||
|
assert.equal(result.earliest, options.earliest); |
||||
|
assert.equal(result.latest, options.latest); |
||||
|
assert.equal(result.offset, options.offset); |
||||
|
assert.equal(result.max, options.max); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
it('should create filter input object with indexed params', function () { |
||||
|
|
||||
|
// given
|
||||
|
var address = '0x012345'; |
||||
|
var signature = '0x987654'; |
||||
|
var options = { |
||||
|
earliest: 1, |
||||
|
latest: 2, |
||||
|
offset: 3, |
||||
|
max: 4 |
||||
|
}; |
||||
|
var e = { |
||||
|
name: 'Event', |
||||
|
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
||||
|
}; |
||||
|
|
||||
|
// when
|
||||
|
var impl = event(address, signature, e); |
||||
|
var result = impl({a: 4}, options); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal(result.address, address); |
||||
|
assert.equal(result.topic.length, 2); |
||||
|
assert.equal(result.topic[0], signature); |
||||
|
assert.equal(result.topic[1], f.formatInputInt(4)); |
||||
|
assert.equal(result.earliest, options.earliest); |
||||
|
assert.equal(result.latest, options.latest); |
||||
|
assert.equal(result.offset, options.offset); |
||||
|
assert.equal(result.max, options.max); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
it('should create filter input object with an array of indexed params', function () { |
||||
|
|
||||
|
// given
|
||||
|
var address = '0x012345'; |
||||
|
var signature = '0x987654'; |
||||
|
var options = { |
||||
|
earliest: 1, |
||||
|
latest: 2, |
||||
|
offset: 3, |
||||
|
max: 4 |
||||
|
}; |
||||
|
var e = { |
||||
|
name: 'Event', |
||||
|
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
||||
|
}; |
||||
|
|
||||
|
// when
|
||||
|
var impl = event(address, signature, e); |
||||
|
var result = impl({a: [4, 69]}, options); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal(result.address, address); |
||||
|
assert.equal(result.topic.length, 2); |
||||
|
assert.equal(result.topic[0], signature); |
||||
|
assert.equal(result.topic[1][0], f.formatInputInt(4)); |
||||
|
assert.equal(result.topic[1][1], f.formatInputInt(69)); |
||||
|
assert.equal(result.earliest, options.earliest); |
||||
|
assert.equal(result.latest, options.latest); |
||||
|
assert.equal(result.offset, options.offset); |
||||
|
assert.equal(result.max, options.max); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
@ -0,0 +1,49 @@ |
|||||
|
var assert = require('assert'); |
||||
|
var utils = require('../lib/utils.js'); |
||||
|
|
||||
|
describe('utils', function() { |
||||
|
it('should filter functions and events from input array properly', function () { |
||||
|
|
||||
|
// given
|
||||
|
var description = [{ |
||||
|
"name": "test", |
||||
|
"type": "function", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
}, { |
||||
|
"name": "test2", |
||||
|
"type": "event", |
||||
|
"inputs": [{ |
||||
|
"name": "a", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
], |
||||
|
"outputs": [ |
||||
|
{ |
||||
|
"name": "d", |
||||
|
"type": "uint256" |
||||
|
} |
||||
|
] |
||||
|
}]; |
||||
|
|
||||
|
// when
|
||||
|
var events = utils.filterEvents(description); |
||||
|
var functions = utils.filterFunctions(description); |
||||
|
|
||||
|
// then
|
||||
|
assert.equal(events.length, 1); |
||||
|
assert.equal(events[0].name, 'test2'); |
||||
|
assert.equal(functions.length, 1); |
||||
|
assert.equal(functions[0].name, 'test'); |
||||
|
|
||||
|
}); |
||||
|
}); |
@ -1,16 +1,10 @@ |
|||||
require('es6-promise').polyfill(); |
|
||||
|
|
||||
var assert = require('assert'); |
var assert = require('assert'); |
||||
var web3 = require('../index.js'); |
var web3 = require('../index.js'); |
||||
var u = require('./utils.js'); |
var u = require('./utils.js'); |
||||
web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider
|
|
||||
|
|
||||
describe('web3', function() { |
describe('web3', function() { |
||||
u.methodExists(web3, 'sha3'); |
u.methodExists(web3, 'sha3'); |
||||
u.methodExists(web3, 'toAscii'); |
u.methodExists(web3, 'toAscii'); |
||||
u.methodExists(web3, 'fromAscii'); |
u.methodExists(web3, 'fromAscii'); |
||||
u.methodExists(web3, 'toFixed'); |
|
||||
u.methodExists(web3, 'fromFixed'); |
|
||||
u.methodExists(web3, 'offset'); |
|
||||
}); |
}); |
||||
|
|
||||
|
@ -1,8 +1,8 @@ |
|||||
<RCC> |
<RCC> |
||||
<qresource prefix="/js"> |
<qresource prefix="/js"> |
||||
<file>es6-promise-2.0.0.js</file> |
|
||||
<file>bignumber.min.js</file> |
<file>bignumber.min.js</file> |
||||
<file>setup.js</file> |
<file>setup.js</file> |
||||
<file alias="webthree.js">ethereumjs/dist/ethereum.js</file> |
<file alias="webthree.js">ethereumjs/dist/ethereum.js</file> |
||||
|
<file>natspec.js</file> |
||||
</qresource> |
</qresource> |
||||
</RCC> |
</RCC> |
||||
|
@ -0,0 +1,83 @@ |
|||||
|
|
||||
|
/** |
||||
|
* This plugin exposes 'evaluateExpression' method which should be used |
||||
|
* to evaluate natspec description |
||||
|
* It should be reloaded each time we want to evaluate set of expressions |
||||
|
* Just because of security reasons |
||||
|
* TODO: make use of sync api (once it's finished) and remove unnecessary |
||||
|
* code from 'getContractMethods' |
||||
|
* TODO: unify method signature creation with abi.js (and make a separate method from it) |
||||
|
*/ |
||||
|
|
||||
|
/// Should be called to copy values from object to global context
|
||||
|
var copyToContext = function (obj, context) { |
||||
|
var keys = Object.keys(obj); |
||||
|
keys.forEach(function (key) { |
||||
|
context[key] = obj[key]; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// Function called to get all contract's storage values
|
||||
|
/// @returns hashmap with contract properties which are used
|
||||
|
var getContractProperties = function (address, abi) { |
||||
|
return {}; |
||||
|
}; |
||||
|
|
||||
|
/// Function called to get all contract's methods
|
||||
|
/// @returns hashmap with used contract's methods
|
||||
|
var getContractMethods = function (address, abi) { |
||||
|
return web3.eth.contract(address, abi); |
||||
|
}; |
||||
|
|
||||
|
/// Function called to get all contract method input variables
|
||||
|
/// @returns hashmap with all contract's method input variables
|
||||
|
var getContractInputParams = function (abi, methodName, params) { |
||||
|
var method = web3.abi.getMethodWithName(abi, methodName); |
||||
|
return method.inputs.reduce(function (acc, current, index) { |
||||
|
acc[current.name] = params[index]; |
||||
|
return acc; |
||||
|
}, {}); |
||||
|
}; |
||||
|
|
||||
|
/// Should be called to evaluate single expression
|
||||
|
/// Is internally using javascript's 'eval' method
|
||||
|
/// Should be checked if it is safe
|
||||
|
var evaluateExpression = function (expression) { |
||||
|
|
||||
|
var self = this; |
||||
|
var abi = web3._currentContractAbi; |
||||
|
var address = web3._currentContractAddress; |
||||
|
var methodName = web3._currentContractMethodName; |
||||
|
var params = web3._currentContractMethodParams; |
||||
|
|
||||
|
var storage = getContractProperties(address, abi); |
||||
|
var methods = getContractMethods(address, abi); |
||||
|
var inputParams = getContractInputParams(abi, methodName, params); |
||||
|
|
||||
|
copyToContext(storage, self); |
||||
|
copyToContext(methods, self); |
||||
|
copyToContext(inputParams, self); |
||||
|
|
||||
|
// TODO: test if it is safe
|
||||
|
var evaluatedExpression = ""; |
||||
|
|
||||
|
// match everything in `` quotes
|
||||
|
var pattern = /\`(?:\\.|[^`\\])*\`/gim |
||||
|
var match; |
||||
|
var lastIndex = 0; |
||||
|
while ((match = pattern.exec(expression)) !== null) { |
||||
|
var startIndex = pattern.lastIndex - match[0].length; |
||||
|
|
||||
|
var toEval = match[0].slice(1, match[0].length - 1); |
||||
|
|
||||
|
evaluatedExpression += expression.slice(lastIndex, startIndex); |
||||
|
evaluatedExpression += eval(toEval).toString(); |
||||
|
|
||||
|
lastIndex = pattern.lastIndex; |
||||
|
} |
||||
|
|
||||
|
evaluatedExpression += expression.slice(lastIndex); |
||||
|
|
||||
|
return evaluatedExpression; |
||||
|
}; |
||||
|
|
@ -1,104 +0,0 @@ |
|||||
|
|
||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
|
||||
it under the terms of the GNU General Public License as published by |
|
||||
the Free Software Foundation, either version 3 of the License, or |
|
||||
(at your option) any later version. |
|
||||
|
|
||||
cpp-ethereum 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 General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/**
|
|
||||
* @author Christian <c@ethdev.com> |
|
||||
* @date 2014 |
|
||||
* Callgraph of functions inside a contract. |
|
||||
*/ |
|
||||
|
|
||||
#include <libsolidity/AST.h> |
|
||||
#include <libsolidity/CallGraph.h> |
|
||||
|
|
||||
using namespace std; |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
namespace solidity |
|
||||
{ |
|
||||
|
|
||||
void CallGraph::addNode(ASTNode const& _node) |
|
||||
{ |
|
||||
_node.accept(*this); |
|
||||
} |
|
||||
|
|
||||
set<FunctionDefinition const*> const& CallGraph::getCalls() |
|
||||
{ |
|
||||
computeCallGraph(); |
|
||||
return m_functionsSeen; |
|
||||
} |
|
||||
|
|
||||
void CallGraph::computeCallGraph() |
|
||||
{ |
|
||||
while (!m_workQueue.empty()) |
|
||||
{ |
|
||||
m_workQueue.front()->accept(*this); |
|
||||
m_workQueue.pop(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
bool CallGraph::visit(Identifier const& _identifier) |
|
||||
{ |
|
||||
FunctionDefinition const* fun = dynamic_cast<FunctionDefinition const*>(_identifier.getReferencedDeclaration()); |
|
||||
if (fun) |
|
||||
{ |
|
||||
if (m_overrideResolver) |
|
||||
fun = (*m_overrideResolver)(fun->getName()); |
|
||||
solAssert(fun, "Error finding override for function " + fun->getName()); |
|
||||
addFunction(*fun); |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
bool CallGraph::visit(FunctionDefinition const& _function) |
|
||||
{ |
|
||||
addFunction(_function); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
bool CallGraph::visit(MemberAccess const& _memberAccess) |
|
||||
{ |
|
||||
// used for "BaseContract.baseContractFunction"
|
|
||||
if (_memberAccess.getExpression().getType()->getCategory() == Type::Category::TYPE) |
|
||||
{ |
|
||||
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType()); |
|
||||
if (type.getMembers().getMemberType(_memberAccess.getMemberName())) |
|
||||
{ |
|
||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*type.getActualType()) |
|
||||
.getContractDefinition(); |
|
||||
for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions()) |
|
||||
if (function->getName() == _memberAccess.getMemberName()) |
|
||||
{ |
|
||||
addFunction(*function); |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
void CallGraph::addFunction(FunctionDefinition const& _function) |
|
||||
{ |
|
||||
if (!m_functionsSeen.count(&_function)) |
|
||||
{ |
|
||||
m_functionsSeen.insert(&_function); |
|
||||
m_workQueue.push(&_function); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,64 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
|
||||
it under the terms of the GNU General Public License as published by |
|
||||
the Free Software Foundation, either version 3 of the License, or |
|
||||
(at your option) any later version. |
|
||||
|
|
||||
cpp-ethereum 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 General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/**
|
|
||||
* @author Christian <c@ethdev.com> |
|
||||
* @date 2014 |
|
||||
* Callgraph of functions inside a contract. |
|
||||
*/ |
|
||||
|
|
||||
#include <set> |
|
||||
#include <queue> |
|
||||
#include <functional> |
|
||||
#include <boost/range/iterator_range.hpp> |
|
||||
#include <libsolidity/ASTVisitor.h> |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
namespace solidity |
|
||||
{ |
|
||||
|
|
||||
/**
|
|
||||
* Can be used to compute the graph of calls (or rather references) between functions of the same |
|
||||
* contract. Current functionality is limited to computing all functions that are directly |
|
||||
* or indirectly called by some functions. |
|
||||
*/ |
|
||||
class CallGraph: private ASTConstVisitor |
|
||||
{ |
|
||||
public: |
|
||||
using OverrideResolver = std::function<FunctionDefinition const*(std::string const&)>; |
|
||||
|
|
||||
CallGraph(OverrideResolver const& _overrideResolver): m_overrideResolver(&_overrideResolver) {} |
|
||||
|
|
||||
void addNode(ASTNode const& _node); |
|
||||
|
|
||||
std::set<FunctionDefinition const*> const& getCalls(); |
|
||||
|
|
||||
private: |
|
||||
virtual bool visit(FunctionDefinition const& _function) override; |
|
||||
virtual bool visit(Identifier const& _identifier) override; |
|
||||
virtual bool visit(MemberAccess const& _memberAccess) override; |
|
||||
|
|
||||
void computeCallGraph(); |
|
||||
void addFunction(FunctionDefinition const& _function); |
|
||||
|
|
||||
OverrideResolver const* m_overrideResolver; |
|
||||
std::set<FunctionDefinition const*> m_functionsSeen; |
|
||||
std::queue<FunctionDefinition const*> m_workQueue; |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,42 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
|
||||
it under the terms of the GNU General Public License as published by |
|
||||
the Free Software Foundation, either version 3 of the License, or |
|
||||
(at your option) any later version. |
|
||||
|
|
||||
cpp-ethereum 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 General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file CorsHttpServer.cpp
|
|
||||
* @author Marek Kotewicz <marek@ethdev.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#include "CorsHttpServer.h" |
|
||||
|
|
||||
namespace jsonrpc |
|
||||
{ |
|
||||
|
|
||||
bool CorsHttpServer::SendResponse(std::string const& _response, void* _addInfo) |
|
||||
{ |
|
||||
struct mg_connection* conn = (struct mg_connection*) _addInfo; |
|
||||
if (mg_printf(conn, "HTTP/1.1 200 OK\r\n" |
|
||||
"Content-Type: application/json\r\n" |
|
||||
"Content-Length: %d\r\n" |
|
||||
"Access-Control-Allow-Origin: *\r\n" |
|
||||
"Access-Control-Allow-Headers: Content-Type\r\n" |
|
||||
"\r\n" |
|
||||
"%s",(int)_response.length(), _response.c_str()) > 0) |
|
||||
return true; |
|
||||
return false; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,35 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
|
||||
it under the terms of the GNU General Public License as published by |
|
||||
the Free Software Foundation, either version 3 of the License, or |
|
||||
(at your option) any later version. |
|
||||
|
|
||||
cpp-ethereum 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 General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file CorsHttpServer.h
|
|
||||
* @author Marek Kotewicz <marek@ethdev.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#include <jsonrpccpp/server/connectors/httpserver.h> |
|
||||
|
|
||||
namespace jsonrpc |
|
||||
{ |
|
||||
|
|
||||
class CorsHttpServer : public HttpServer |
|
||||
{ |
|
||||
public: |
|
||||
using HttpServer::HttpServer; |
|
||||
bool virtual SendResponse(std::string const& _response, void* _addInfo = NULL); |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
|
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue