Added deployed to contract and abstracted polling into web.
This commit is contained in:
parent
ebf42dc9e0
commit
b1d026b800
@ -15,6 +15,7 @@ var address_1 = require("../utils/address");
|
||||
var bytes_1 = require("../utils/bytes");
|
||||
var bignumber_1 = require("../utils/bignumber");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var web_1 = require("../utils/web");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
var allowedTransactionKeys = {
|
||||
data: true, from: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
|
||||
@ -270,6 +271,25 @@ var Contract = /** @class */ (function () {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
// @TODO: Allow timeout?
|
||||
Contract.prototype.deployed = function () {
|
||||
var _this = this;
|
||||
// If we were just deployed, we know the transaction we should occur in
|
||||
if (this.deployTransaction) {
|
||||
return this.deployTransaction.wait().then(function () {
|
||||
return _this;
|
||||
});
|
||||
}
|
||||
// Otherwise, poll for our code to be deployed
|
||||
return web_1.poll(function () {
|
||||
return _this.provider.getCode(_this.address).then(function (code) {
|
||||
if (code === '0x') {
|
||||
return undefined;
|
||||
}
|
||||
return _this;
|
||||
});
|
||||
});
|
||||
};
|
||||
// @TODO:
|
||||
// estimateFallback(overrides?: TransactionRequest): Promise<BigNumber>
|
||||
// @TODO:
|
||||
|
8
dist/ethers.d.ts
vendored
8
dist/ethers.d.ts
vendored
@ -226,6 +226,7 @@ declare module 'ethers/contracts/contract' {
|
||||
readonly deployTransaction: TransactionResponse;
|
||||
constructor(addressOrName: string, contractInterface: Contractish, signerOrProvider: Signer | Provider);
|
||||
onerror: ErrorCallback;
|
||||
deployed(): Promise<any>;
|
||||
fallback(overrides?: TransactionRequest): Promise<TransactionResponse>;
|
||||
connect(signerOrProvider: Signer | Provider): Contract;
|
||||
attach(addressOrName: string): Contract;
|
||||
@ -712,6 +713,13 @@ declare module 'ethers/utils/web' {
|
||||
};
|
||||
export type ProcessFunc = (value: any) => any;
|
||||
export function fetchJson(connection: string | ConnectionInfo, json: string, processFunc: ProcessFunc): Promise<any>;
|
||||
export type PollOptions = {
|
||||
timeout?: number;
|
||||
floor?: number;
|
||||
ceiling?: number;
|
||||
interval?: number;
|
||||
};
|
||||
export function poll(func: () => Promise<any>, options?: PollOptions): Promise<any>;
|
||||
}
|
||||
|
||||
declare module 'ethers/utils/transaction' {
|
||||
|
179
dist/ethers.js
vendored
179
dist/ethers.js
vendored
@ -8867,6 +8867,7 @@ var address_1 = require("../utils/address");
|
||||
var bytes_1 = require("../utils/bytes");
|
||||
var bignumber_1 = require("../utils/bignumber");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var web_1 = require("../utils/web");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
var allowedTransactionKeys = {
|
||||
data: true, from: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
|
||||
@ -9122,6 +9123,25 @@ var Contract = /** @class */ (function () {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
// @TODO: Allow timeout?
|
||||
Contract.prototype.deployed = function () {
|
||||
var _this = this;
|
||||
// If we were just deployed, we know the transaction we should occur in
|
||||
if (this.deployTransaction) {
|
||||
return this.deployTransaction.wait().then(function () {
|
||||
return _this;
|
||||
});
|
||||
}
|
||||
// Otherwise, poll for our code to be deployed
|
||||
return web_1.poll(function () {
|
||||
return _this.provider.getCode(_this.address).then(function (code) {
|
||||
if (code === '0x') {
|
||||
return undefined;
|
||||
}
|
||||
return _this;
|
||||
});
|
||||
});
|
||||
};
|
||||
// @TODO:
|
||||
// estimateFallback(overrides?: TransactionRequest): Promise<BigNumber>
|
||||
// @TODO:
|
||||
@ -9198,7 +9218,7 @@ var Contract = /** @class */ (function () {
|
||||
}());
|
||||
exports.Contract = Contract;
|
||||
|
||||
},{"../providers/provider":56,"../utils/abi-coder":58,"../utils/address":59,"../utils/bignumber":60,"../utils/bytes":61,"../utils/errors":62,"../utils/properties":66,"../wallet/wallet":79,"./interface":49}],48:[function(require,module,exports){
|
||||
},{"../providers/provider":56,"../utils/abi-coder":58,"../utils/address":59,"../utils/bignumber":60,"../utils/bytes":61,"../utils/errors":62,"../utils/properties":66,"../utils/web":74,"../wallet/wallet":79,"./interface":49}],48:[function(require,module,exports){
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var contract_1 = require("./contract");
|
||||
@ -10507,6 +10527,7 @@ var hash_1 = require("../utils/hash");
|
||||
var networks_1 = require("./networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var transaction_1 = require("../utils/transaction");
|
||||
var web_1 = require("../utils/web");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
;
|
||||
;
|
||||
@ -10851,31 +10872,6 @@ var formatLog = {
|
||||
function checkLog(log) {
|
||||
return check(formatLog, log);
|
||||
}
|
||||
function stallPromise(allowNullFunc, executeFunc) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var attempt = 0;
|
||||
function check() {
|
||||
executeFunc().then(function (result) {
|
||||
// If we have a result, or are allowed null then we're done
|
||||
if (result || allowNullFunc()) {
|
||||
resolve(result);
|
||||
// Otherwise, exponential back-off (up to 10s) our next request
|
||||
}
|
||||
else {
|
||||
attempt++;
|
||||
var timeout = 500 + 250 * parseInt(String(Math.random() * (1 << attempt)));
|
||||
if (timeout > 10000) {
|
||||
timeout = 10000;
|
||||
}
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
}, function (error) {
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
//////////////////////////////
|
||||
// Event Serializeing
|
||||
function recurse(object, convertFunc) {
|
||||
@ -11346,13 +11342,14 @@ var Provider = /** @class */ (function () {
|
||||
try {
|
||||
var blockHash = bytes_1.hexlify(blockHashOrBlockTag);
|
||||
if (bytes_1.hexDataLength(blockHash) === 32) {
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['b:' + blockHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockHash: blockHash }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (_this._emitted['b:' + blockHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkBlock(block);
|
||||
});
|
||||
});
|
||||
@ -11360,16 +11357,17 @@ var Provider = /** @class */ (function () {
|
||||
}
|
||||
catch (error) { }
|
||||
try {
|
||||
var blockTag = checkBlockTag(blockHashOrBlockTag);
|
||||
return stallPromise(function () {
|
||||
if (bytes_1.isHexString(blockTag)) {
|
||||
var blockNumber = parseInt(blockTag.substring(2), 16);
|
||||
return blockNumber > _this._emitted.block;
|
||||
var blockNumber_1 = -128;
|
||||
var blockTag_1 = checkBlockTag(blockHashOrBlockTag);
|
||||
if (bytes_1.isHexString(blockTag_1)) {
|
||||
blockNumber_1 = parseInt(blockTag_1.substring(2), 16);
|
||||
}
|
||||
return true;
|
||||
}, function () {
|
||||
return _this.perform('getBlock', { blockTag: blockTag }).then(function (block) {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockTag: blockTag_1 }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (blockNumber_1 > _this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return checkBlock(block);
|
||||
@ -11387,14 +11385,15 @@ var Provider = /** @class */ (function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['t:' + transactionHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransaction', params).then(function (result) {
|
||||
if (result != null) {
|
||||
result = checkTransactionResponse(result);
|
||||
if (result == null) {
|
||||
if (_this._emitted['t:' + transactionHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionResponse(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -11406,14 +11405,15 @@ var Provider = /** @class */ (function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['t:' + transactionHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransactionReceipt', params).then(function (result) {
|
||||
if (result != null) {
|
||||
result = checkTransactionReceipt(result);
|
||||
if (result == null) {
|
||||
if (_this._emitted['t:' + transactionHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionReceipt(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -11679,7 +11679,7 @@ var Provider = /** @class */ (function () {
|
||||
}());
|
||||
exports.Provider = Provider;
|
||||
|
||||
},{"../utils/address":59,"../utils/bignumber":60,"../utils/bytes":61,"../utils/errors":62,"../utils/hash":63,"../utils/properties":66,"../utils/rlp":67,"../utils/transaction":71,"../utils/utf8":73,"../wallet/wallet":79,"./networks":55}],57:[function(require,module,exports){
|
||||
},{"../utils/address":59,"../utils/bignumber":60,"../utils/bytes":61,"../utils/errors":62,"../utils/hash":63,"../utils/properties":66,"../utils/rlp":67,"../utils/transaction":71,"../utils/utf8":73,"../utils/web":74,"../wallet/wallet":79,"./networks":55}],57:[function(require,module,exports){
|
||||
'use strict';
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
@ -12041,6 +12041,18 @@ var Coder = /** @class */ (function () {
|
||||
}
|
||||
return Coder;
|
||||
}());
|
||||
// Clones the functionality of an existing Coder, but without a localName
|
||||
var CoderAnonymous = /** @class */ (function (_super) {
|
||||
__extends(CoderAnonymous, _super);
|
||||
function CoderAnonymous(coder) {
|
||||
var _this = _super.call(this, coder.coerceFunc, coder.name, coder.type, undefined, coder.dynamic) || this;
|
||||
properties_1.defineReadOnly(_this, 'coder', coder);
|
||||
return _this;
|
||||
}
|
||||
CoderAnonymous.prototype.encode = function (value) { return this.coder.encode(value); };
|
||||
CoderAnonymous.prototype.decode = function (data, offset) { return this.coder.decode(data, offset); };
|
||||
return CoderAnonymous;
|
||||
}(Coder));
|
||||
var CoderNull = /** @class */ (function (_super) {
|
||||
__extends(CoderNull, _super);
|
||||
function CoderNull(coerceFunc, localName) {
|
||||
@ -12465,7 +12477,7 @@ var CoderArray = /** @class */ (function (_super) {
|
||||
}
|
||||
var coders = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
coders.push(this.coder);
|
||||
coders.push(new CoderAnonymous(this.coder));
|
||||
}
|
||||
var result = unpack(coders, data, offset);
|
||||
result.consumed += consumed;
|
||||
@ -14329,6 +14341,71 @@ function fetchJson(connection, json, processFunc) {
|
||||
});
|
||||
}
|
||||
exports.fetchJson = fetchJson;
|
||||
function poll(func, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
if (options.floor == null) {
|
||||
options.floor = 0;
|
||||
}
|
||||
if (options.ceiling == null) {
|
||||
options.ceiling = 10000;
|
||||
}
|
||||
if (options.interval == null) {
|
||||
options.interval = 250;
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
var timer = null;
|
||||
var done = false;
|
||||
// Returns true if cancel was successful. Unsuccessful cancel means we're already done.
|
||||
var cancel = function () {
|
||||
if (done) {
|
||||
return false;
|
||||
}
|
||||
done = true;
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (options.timeout) {
|
||||
timer = setTimeout(function () {
|
||||
if (cancel()) {
|
||||
reject(new Error('timeout'));
|
||||
}
|
||||
}, options.timeout);
|
||||
}
|
||||
var attempt = 0;
|
||||
function check() {
|
||||
func().then(function (result) {
|
||||
// If we have a result, or are allowed null then we're done
|
||||
if (result !== undefined) {
|
||||
if (cancel()) {
|
||||
resolve(result);
|
||||
}
|
||||
// Otherwise, exponential back-off (up to 10s) our next request
|
||||
}
|
||||
else if (!done) {
|
||||
attempt++;
|
||||
var timeout = options.interval * parseInt(String(Math.random() * Math.pow(2, attempt)));
|
||||
if (timeout < options.floor) {
|
||||
timeout = options.floor;
|
||||
}
|
||||
if (timeout > options.ceiling) {
|
||||
timeout = options.ceiling;
|
||||
}
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
}, function (error) {
|
||||
if (cancel()) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
exports.poll = poll;
|
||||
|
||||
},{"./base64":40,"./errors":62,"./utf8":73,"xmlhttprequest":45}],75:[function(require,module,exports){
|
||||
'use strict';
|
||||
|
2
dist/ethers.min.js
vendored
2
dist/ethers.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/ethers.min.js.map
vendored
2
dist/ethers.min.js.map
vendored
File diff suppressed because one or more lines are too long
1056
package-lock.json
generated
1056
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,7 @@
|
||||
"dist-bip39": "gulp bip39-it bip39-ja bip39-ko bip39-zh",
|
||||
"dist-types": "gulp temp-types && dts-bundle --name ethers --main .tmp/index.d.ts --out ../dist/ethers.d.ts",
|
||||
"dist-version": "node -e \"let v = require('./package.json').version; require('fs').writeFileSync('./src.ts/_version.ts', 'export const version = \\\"' + v +'\\\";\\n')\"",
|
||||
"eslint": "eslint index.js contracts/*.js providers/*.js utils/*.js wallet/*.js wordlists/*.js",
|
||||
"test": "if [ \"$RUN_PHANTOMJS\" = \"1\" ]; then npm run-script test-phantomjs; else npm run-script test-node; fi",
|
||||
"test-node": "mocha tests/test-*.js",
|
||||
"test-phantomjs": "gulp minified tests && phantomjs --web-security=false ./node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js ./tests/test.html",
|
||||
@ -32,6 +33,8 @@
|
||||
"browserify": "^16.2.2",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
"dts-bundle": "^0.7.3",
|
||||
"eslint": "^5.0.1",
|
||||
"eslint-plugin-promise": "^3.8.0",
|
||||
"ethereumjs-tx": "^1.3.5",
|
||||
"ethereumjs-util": "^5.2.0",
|
||||
"gulp": "^3.9.1",
|
||||
|
@ -28,6 +28,7 @@ var hash_1 = require("../utils/hash");
|
||||
var networks_1 = require("./networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var transaction_1 = require("../utils/transaction");
|
||||
var web_1 = require("../utils/web");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
;
|
||||
;
|
||||
@ -372,31 +373,6 @@ var formatLog = {
|
||||
function checkLog(log) {
|
||||
return check(formatLog, log);
|
||||
}
|
||||
function stallPromise(allowNullFunc, executeFunc) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var attempt = 0;
|
||||
function check() {
|
||||
executeFunc().then(function (result) {
|
||||
// If we have a result, or are allowed null then we're done
|
||||
if (result || allowNullFunc()) {
|
||||
resolve(result);
|
||||
// Otherwise, exponential back-off (up to 10s) our next request
|
||||
}
|
||||
else {
|
||||
attempt++;
|
||||
var timeout = 500 + 250 * parseInt(String(Math.random() * (1 << attempt)));
|
||||
if (timeout > 10000) {
|
||||
timeout = 10000;
|
||||
}
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
}, function (error) {
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
//////////////////////////////
|
||||
// Event Serializeing
|
||||
function recurse(object, convertFunc) {
|
||||
@ -867,13 +843,14 @@ var Provider = /** @class */ (function () {
|
||||
try {
|
||||
var blockHash = bytes_1.hexlify(blockHashOrBlockTag);
|
||||
if (bytes_1.hexDataLength(blockHash) === 32) {
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['b:' + blockHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockHash: blockHash }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (_this._emitted['b:' + blockHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkBlock(block);
|
||||
});
|
||||
});
|
||||
@ -881,16 +858,17 @@ var Provider = /** @class */ (function () {
|
||||
}
|
||||
catch (error) { }
|
||||
try {
|
||||
var blockTag = checkBlockTag(blockHashOrBlockTag);
|
||||
return stallPromise(function () {
|
||||
if (bytes_1.isHexString(blockTag)) {
|
||||
var blockNumber = parseInt(blockTag.substring(2), 16);
|
||||
return blockNumber > _this._emitted.block;
|
||||
var blockNumber_1 = -128;
|
||||
var blockTag_1 = checkBlockTag(blockHashOrBlockTag);
|
||||
if (bytes_1.isHexString(blockTag_1)) {
|
||||
blockNumber_1 = parseInt(blockTag_1.substring(2), 16);
|
||||
}
|
||||
return true;
|
||||
}, function () {
|
||||
return _this.perform('getBlock', { blockTag: blockTag }).then(function (block) {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockTag: blockTag_1 }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (blockNumber_1 > _this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return checkBlock(block);
|
||||
@ -908,14 +886,15 @@ var Provider = /** @class */ (function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['t:' + transactionHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransaction', params).then(function (result) {
|
||||
if (result != null) {
|
||||
result = checkTransactionResponse(result);
|
||||
if (result == null) {
|
||||
if (_this._emitted['t:' + transactionHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionResponse(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -927,14 +906,15 @@ var Provider = /** @class */ (function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['t:' + transactionHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransactionReceipt', params).then(function (result) {
|
||||
if (result != null) {
|
||||
result = checkTransactionReceipt(result);
|
||||
if (result == null) {
|
||||
if (_this._emitted['t:' + transactionHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionReceipt(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -11,6 +11,7 @@ import { hexDataLength, hexDataSlice, isHexString } from '../utils/bytes';
|
||||
import { ParamType } from '../utils/abi-coder';
|
||||
import { BigNumber, ConstantZero } from '../utils/bignumber';
|
||||
import { defineReadOnly, shallowCopy } from '../utils/properties';
|
||||
import { poll } from '../utils/web';
|
||||
|
||||
import * as errors from '../utils/errors';
|
||||
|
||||
@ -330,6 +331,24 @@ export class Contract {
|
||||
this._onerror = callback;
|
||||
}
|
||||
|
||||
// @TODO: Allow timeout?
|
||||
deployed() {
|
||||
// If we were just deployed, we know the transaction we should occur in
|
||||
if (this.deployTransaction) {
|
||||
return this.deployTransaction.wait().then(() => {
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise, poll for our code to be deployed
|
||||
return poll(() => {
|
||||
return this.provider.getCode(this.address).then((code) => {
|
||||
if (code === '0x') { return undefined; }
|
||||
return this;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// @TODO:
|
||||
// estimateFallback(overrides?: TransactionRequest): Promise<BigNumber>
|
||||
|
||||
|
@ -109,7 +109,7 @@ export class JsonRpcSigner extends Signer {
|
||||
}
|
||||
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
|
||||
let tx = shallowCopy(transaction);
|
||||
let tx: TransactionRequest = shallowCopy(transaction);
|
||||
|
||||
if (tx.from == null) {
|
||||
tx.from = this.getAddress().then((address) => {
|
||||
|
@ -13,6 +13,7 @@ import { hashMessage, namehash } from '../utils/hash';
|
||||
import { getNetwork, Network, Networkish } from './networks';
|
||||
import { defineReadOnly, resolveProperties, shallowCopy } from '../utils/properties';
|
||||
import { parse as parseTransaction, serialize as serializeTransaction, SignDigestFunc, Transaction } from '../utils/transaction';
|
||||
import { poll } from '../utils/web';
|
||||
|
||||
import * as errors from '../utils/errors';
|
||||
|
||||
@ -505,35 +506,6 @@ function checkLog(log: any): any {
|
||||
return check(formatLog, log);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Defer Promises
|
||||
|
||||
type AllowNullFunc = () => boolean;
|
||||
type ExecuteFunc = () => Promise<any>
|
||||
function stallPromise(allowNullFunc: AllowNullFunc, executeFunc: ExecuteFunc): Promise<any> {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var attempt = 0;
|
||||
function check() {
|
||||
executeFunc().then(function(result) {
|
||||
// If we have a result, or are allowed null then we're done
|
||||
if (result || allowNullFunc()) {
|
||||
resolve(result);
|
||||
|
||||
// Otherwise, exponential back-off (up to 10s) our next request
|
||||
} else {
|
||||
attempt++;
|
||||
var timeout = 500 + 250 * parseInt(String(Math.random() * (1 << attempt)));
|
||||
if (timeout > 10000) { timeout = 10000; }
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
}, function(error) {
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Event Serializeing
|
||||
|
||||
@ -1037,28 +1009,37 @@ export class Provider {
|
||||
try {
|
||||
var blockHash = hexlify(blockHashOrBlockTag);
|
||||
if (hexDataLength(blockHash) === 32) {
|
||||
return stallPromise(() => {
|
||||
return (this._emitted['b:' + blockHash.toLowerCase()] == null);
|
||||
}, () => {
|
||||
return this.perform('getBlock', {blockHash: blockHash}).then((block) => {
|
||||
if (block == null) { return null; }
|
||||
return poll(() => {
|
||||
return this.perform('getBlock', { blockHash: blockHash }).then((block) => {
|
||||
if (block == null) {
|
||||
if (this._emitted['b:' + blockHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkBlock(block);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
} catch (error) { }
|
||||
|
||||
try {
|
||||
var blockTag = checkBlockTag(blockHashOrBlockTag);
|
||||
return stallPromise(() => {
|
||||
let blockNumber = -128;
|
||||
|
||||
let blockTag = checkBlockTag(blockHashOrBlockTag);
|
||||
if (isHexString(blockTag)) {
|
||||
var blockNumber = parseInt(blockTag.substring(2), 16);
|
||||
return blockNumber > this._emitted.block;
|
||||
blockNumber = parseInt(blockTag.substring(2), 16);
|
||||
}
|
||||
return true;
|
||||
}, () => {
|
||||
|
||||
return poll(() => {
|
||||
return this.perform('getBlock', { blockTag: blockTag }).then((block) => {
|
||||
if (block == null) { return null; }
|
||||
if (block == null) {
|
||||
if (blockNumber > this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return checkBlock(block);
|
||||
});
|
||||
});
|
||||
@ -1073,12 +1054,15 @@ export class Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
return stallPromise(() => {
|
||||
return (this._emitted['t:' + transactionHash.toLowerCase()] == null);
|
||||
}, () => {
|
||||
return poll(() => {
|
||||
return this.perform('getTransaction', params).then((result) => {
|
||||
if (result != null) { result = checkTransactionResponse(result); }
|
||||
return result;
|
||||
if (result == null) {
|
||||
if (this._emitted['t:' + transactionHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionResponse(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1089,12 +1073,15 @@ export class Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
return stallPromise(() => {
|
||||
return (this._emitted['t:' + transactionHash.toLowerCase()] == null);
|
||||
}, () => {
|
||||
return poll(() => {
|
||||
return this.perform('getTransactionReceipt', params).then((result) => {
|
||||
if (result != null) { result = checkTransactionReceipt(result); }
|
||||
return result;
|
||||
if (result == null) {
|
||||
if (this._emitted['t:' + transactionHash.toLowerCase()] == null) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionReceipt(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -120,3 +120,61 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
|
||||
});
|
||||
}
|
||||
|
||||
export type PollOptions = {
|
||||
timeout?: number,
|
||||
floor?: number,
|
||||
ceiling?: number,
|
||||
interval?: number
|
||||
};
|
||||
|
||||
export function poll(func: () => Promise<any>, options?: PollOptions): Promise<any> {
|
||||
if (!options) { options = {}; }
|
||||
if (options.floor == null) { options.floor = 0; }
|
||||
if (options.ceiling == null) { options.ceiling = 10000; }
|
||||
if (options.interval == null) { options.interval = 250; }
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
||||
let timer: any = null;
|
||||
let done: boolean = false;
|
||||
|
||||
// Returns true if cancel was successful. Unsuccessful cancel means we're already done.
|
||||
let cancel = (): boolean => {
|
||||
if (done) { return false; }
|
||||
done = true;
|
||||
if (timer) { clearTimeout(timer); }
|
||||
return true;
|
||||
};
|
||||
|
||||
if (options.timeout) {
|
||||
timer = setTimeout(() => {
|
||||
if (cancel()) { reject(new Error('timeout')); }
|
||||
}, options.timeout)
|
||||
}
|
||||
|
||||
let attempt = 0;
|
||||
function check() {
|
||||
func().then(function(result) {
|
||||
|
||||
// If we have a result, or are allowed null then we're done
|
||||
if (result !== undefined) {
|
||||
if (cancel()) { resolve(result); }
|
||||
|
||||
// Otherwise, exponential back-off (up to 10s) our next request
|
||||
} else if (!done) {
|
||||
attempt++;
|
||||
|
||||
let timeout = options.interval * parseInt(String(Math.random() * Math.pow(2, attempt)));
|
||||
if (timeout < options.floor) { timeout = options.floor; }
|
||||
if (timeout > options.ceiling) { timeout = options.ceiling; }
|
||||
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
}, function(error) {
|
||||
if (cancel()) { reject(error); }
|
||||
});
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -286,6 +286,18 @@ var Coder = /** @class */ (function () {
|
||||
}
|
||||
return Coder;
|
||||
}());
|
||||
// Clones the functionality of an existing Coder, but without a localName
|
||||
var CoderAnonymous = /** @class */ (function (_super) {
|
||||
__extends(CoderAnonymous, _super);
|
||||
function CoderAnonymous(coder) {
|
||||
var _this = _super.call(this, coder.coerceFunc, coder.name, coder.type, undefined, coder.dynamic) || this;
|
||||
properties_1.defineReadOnly(_this, 'coder', coder);
|
||||
return _this;
|
||||
}
|
||||
CoderAnonymous.prototype.encode = function (value) { return this.coder.encode(value); };
|
||||
CoderAnonymous.prototype.decode = function (data, offset) { return this.coder.decode(data, offset); };
|
||||
return CoderAnonymous;
|
||||
}(Coder));
|
||||
var CoderNull = /** @class */ (function (_super) {
|
||||
__extends(CoderNull, _super);
|
||||
function CoderNull(coerceFunc, localName) {
|
||||
@ -710,7 +722,7 @@ var CoderArray = /** @class */ (function (_super) {
|
||||
}
|
||||
var coders = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
coders.push(this.coder);
|
||||
coders.push(new CoderAnonymous(this.coder));
|
||||
}
|
||||
var result = unpack(coders, data, offset);
|
||||
result.consumed += consumed;
|
||||
|
65
utils/web.js
65
utils/web.js
@ -102,3 +102,68 @@ function fetchJson(connection, json, processFunc) {
|
||||
});
|
||||
}
|
||||
exports.fetchJson = fetchJson;
|
||||
function poll(func, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
if (options.floor == null) {
|
||||
options.floor = 0;
|
||||
}
|
||||
if (options.ceiling == null) {
|
||||
options.ceiling = 10000;
|
||||
}
|
||||
if (options.interval == null) {
|
||||
options.interval = 250;
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
var timer = null;
|
||||
var done = false;
|
||||
// Returns true if cancel was successful. Unsuccessful cancel means we're already done.
|
||||
var cancel = function () {
|
||||
if (done) {
|
||||
return false;
|
||||
}
|
||||
done = true;
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (options.timeout) {
|
||||
timer = setTimeout(function () {
|
||||
if (cancel()) {
|
||||
reject(new Error('timeout'));
|
||||
}
|
||||
}, options.timeout);
|
||||
}
|
||||
var attempt = 0;
|
||||
function check() {
|
||||
func().then(function (result) {
|
||||
// If we have a result, or are allowed null then we're done
|
||||
if (result !== undefined) {
|
||||
if (cancel()) {
|
||||
resolve(result);
|
||||
}
|
||||
// Otherwise, exponential back-off (up to 10s) our next request
|
||||
}
|
||||
else if (!done) {
|
||||
attempt++;
|
||||
var timeout = options.interval * parseInt(String(Math.random() * Math.pow(2, attempt)));
|
||||
if (timeout < options.floor) {
|
||||
timeout = options.floor;
|
||||
}
|
||||
if (timeout > options.ceiling) {
|
||||
timeout = options.ceiling;
|
||||
}
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
}, function (error) {
|
||||
if (cancel()) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
exports.poll = poll;
|
||||
|
Loading…
Reference in New Issue
Block a user