forked from tornado-packages/ethers.js
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb6bc4cac3 | ||
|
|
ef8b9c36ef | ||
|
|
e6c943d01f | ||
|
|
31d3ee899f | ||
|
|
98143a845b | ||
|
|
bffc557be1 | ||
|
|
09208fa8fe | ||
|
|
048c571d3d | ||
|
|
24757f1064 | ||
|
|
88f2f51266 | ||
|
|
93152ef863 | ||
|
|
09b698b0a9 | ||
|
|
478aaf9619 | ||
|
|
fad902b438 | ||
|
|
7bfaf292db | ||
|
|
be0488a1a0 | ||
|
|
28a52cd485 | ||
|
|
3a19f43844 | ||
|
|
4852e837d2 | ||
|
|
fa68385cfe | ||
|
|
d54609a458 | ||
|
|
f682861e0b | ||
|
|
023a20ff47 | ||
|
|
e39cd84923 | ||
|
|
5020897f10 | ||
|
|
6ac2d923b7 | ||
|
|
6996dd86f4 | ||
|
|
493273d698 | ||
|
|
84344ac4c2 | ||
|
|
9b118af304 | ||
|
|
e39e2ed718 | ||
|
|
71f781d542 | ||
|
|
b2db10e216 | ||
|
|
3736a15714 |
2
_version.d.ts
vendored
2
_version.d.ts
vendored
@@ -1 +1 @@
|
||||
export declare const version = "4.0.2";
|
||||
export declare const version = "4.0.13";
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.version = "4.0.2";
|
||||
exports.version = "4.0.13";
|
||||
|
||||
6
contract.d.ts
vendored
6
contract.d.ts
vendored
@@ -21,6 +21,12 @@ export interface Event extends Log {
|
||||
getTransaction: () => Promise<TransactionResponse>;
|
||||
getTransactionReceipt: () => Promise<TransactionReceipt>;
|
||||
}
|
||||
export interface ContractReceipt extends TransactionReceipt {
|
||||
events?: Array<Event>;
|
||||
}
|
||||
export interface ContractTransaction extends TransactionResponse {
|
||||
wait(confirmations?: number): Promise<ContractReceipt>;
|
||||
}
|
||||
export declare class VoidSigner extends Signer {
|
||||
readonly address: string;
|
||||
constructor(address: string, provider: Provider);
|
||||
|
||||
41
contract.js
41
contract.js
@@ -106,14 +106,20 @@ function resolveAddresses(provider, value, paramType) {
|
||||
function runMethod(contract, functionName, estimateOnly) {
|
||||
var method = contract.interface.functions[functionName];
|
||||
return function () {
|
||||
var _this = this;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
var tx = {};
|
||||
var blockTag = null;
|
||||
// If 1 extra parameter was passed in, it contains overrides
|
||||
if (params.length === method.inputs.length + 1 && typeof (params[params.length - 1]) === 'object') {
|
||||
tx = properties_1.shallowCopy(params.pop());
|
||||
if (tx.blockTag != null) {
|
||||
blockTag = tx.blockTag;
|
||||
}
|
||||
delete tx.blockTag;
|
||||
// Check for unexpected keys (e.g. using "gas" instead of "gasLimit")
|
||||
for (var key in tx) {
|
||||
if (!allowedTransactionKeys[key]) {
|
||||
@@ -153,7 +159,7 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
if (tx.from == null && contract.signer) {
|
||||
tx.from = contract.signer.getAddress();
|
||||
}
|
||||
return contract.provider.call(tx).then(function (value) {
|
||||
return contract.provider.call(tx, blockTag).then(function (value) {
|
||||
if ((bytes_1.hexDataLength(value) % 32) === 4 && bytes_1.hexDataSlice(value, 0, 4) === '0x08c379a0') {
|
||||
var reason = abi_coder_1.defaultAbiCoder.decode(['string'], bytes_1.hexDataSlice(value, 4));
|
||||
errors.throwError('call revert exception', errors.CALL_EXCEPTION, {
|
||||
@@ -206,7 +212,36 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
if (tx.from != null) {
|
||||
errors.throwError('cannot override from in a transaction', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' });
|
||||
}
|
||||
return contract.signer.sendTransaction(tx);
|
||||
return contract.signer.sendTransaction(tx).then(function (tx) {
|
||||
var wait = tx.wait.bind(tx);
|
||||
tx.wait = function (confirmations) {
|
||||
return wait(confirmations).then(function (receipt) {
|
||||
receipt.events = receipt.logs.map(function (log) {
|
||||
var event = properties_1.deepCopy(log);
|
||||
var parsed = _this.interface.parseLog(log);
|
||||
if (parsed) {
|
||||
event.args = parsed.values;
|
||||
event.decode = parsed.decode;
|
||||
event.event = parsed.name;
|
||||
event.eventSignature = parsed.signature;
|
||||
}
|
||||
event.removeListener = function () { return _this.provider; };
|
||||
event.getBlock = function () {
|
||||
return _this.provider.getBlock(receipt.blockHash);
|
||||
};
|
||||
event.getTransaction = function () {
|
||||
return _this.provider.getTransaction(receipt.transactionHash);
|
||||
};
|
||||
event.getTransactionReceipt = function () {
|
||||
return Promise.resolve(receipt);
|
||||
};
|
||||
return event;
|
||||
});
|
||||
return receipt;
|
||||
});
|
||||
};
|
||||
return tx;
|
||||
});
|
||||
}
|
||||
throw new Error('invalid type - ' + method.type);
|
||||
return null;
|
||||
@@ -620,7 +655,7 @@ var ContractFactory = /** @class */ (function () {
|
||||
errors.throwError('cannot override ' + key, errors.UNSUPPORTED_OPERATION, { operation: key });
|
||||
});
|
||||
// Make sure the call matches the constructor signature
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, 'in Contract constructor');
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, ' in Contract constructor');
|
||||
// Set the data to the bytecode + the encoded constructor arguments
|
||||
tx.data = this.interface.deployFunction.encode(this.bytecode, args);
|
||||
return tx;
|
||||
|
||||
728
dist/ethers.js
vendored
728
dist/ethers.js
vendored
File diff suppressed because it is too large
Load Diff
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
49
dist/ethers.types.txt
vendored
49
dist/ethers.types.txt
vendored
@@ -17,9 +17,9 @@ declare module 'ethers/ethers' {
|
||||
import * as wordlists from 'ethers/wordlists';
|
||||
import { platform } from 'ethers/utils/shims';
|
||||
import { version } from 'ethers/_version';
|
||||
import { ContractFunction, Event, EventFilter } from 'ethers/contract';
|
||||
import { ContractFunction, ContractTransaction, Event, EventFilter } from 'ethers/contract';
|
||||
function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider;
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, Event, EventFilter };
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, ContractTransaction, Event, EventFilter };
|
||||
}
|
||||
|
||||
declare module 'ethers/contract' {
|
||||
@@ -46,6 +46,12 @@ declare module 'ethers/contract' {
|
||||
getTransaction: () => Promise<TransactionResponse>;
|
||||
getTransactionReceipt: () => Promise<TransactionReceipt>;
|
||||
}
|
||||
export interface ContractReceipt extends TransactionReceipt {
|
||||
events?: Array<Event>;
|
||||
}
|
||||
export interface ContractTransaction extends TransactionResponse {
|
||||
wait(confirmations?: number): Promise<ContractReceipt>;
|
||||
}
|
||||
export class VoidSigner extends Signer {
|
||||
readonly address: string;
|
||||
constructor(address: string, provider: Provider);
|
||||
@@ -146,7 +152,7 @@ declare module 'ethers/wallet' {
|
||||
* Static methods to create Wallet instances.
|
||||
*/
|
||||
static createRandom(options?: any): Wallet;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback?: ProgressCallback): Promise<Wallet>;
|
||||
static fromMnemonic(mnemonic: string, path?: string, wordlist?: Wordlist): Wallet;
|
||||
}
|
||||
}
|
||||
@@ -182,6 +188,7 @@ declare module 'ethers/errors' {
|
||||
export function checkNew(self: any, kind: any): void;
|
||||
export function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void;
|
||||
export function setCensorship(censorship: boolean, permanent?: boolean): void;
|
||||
export function checkNormalize(): void;
|
||||
}
|
||||
|
||||
declare module 'ethers/providers' {
|
||||
@@ -213,10 +220,11 @@ declare module 'ethers/utils' {
|
||||
import { keccak256 as solidityKeccak256, pack as solidityPack, sha256 as soliditySha256 } from 'ethers/utils/solidity';
|
||||
import { randomBytes } from 'ethers/utils/random-bytes';
|
||||
import { getNetwork } from 'ethers/utils/networks';
|
||||
import { deepCopy, defineReadOnly, resolveProperties, shallowCopy } from 'ethers/utils/properties';
|
||||
import { checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy } from 'ethers/utils/properties';
|
||||
import * as RLP from 'ethers/utils/rlp';
|
||||
import { computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage } from 'ethers/utils/secp256k1';
|
||||
import { SigningKey } from 'ethers/utils/signing-key';
|
||||
import { populateTransaction } from 'ethers/utils/transaction';
|
||||
import { parse as parseTransaction, serialize as serializeTransaction } from 'ethers/utils/transaction';
|
||||
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from 'ethers/utils/utf8';
|
||||
import { commify, formatEther, parseEther, formatUnits, parseUnits } from 'ethers/utils/units';
|
||||
@@ -232,7 +240,7 @@ declare module 'ethers/utils' {
|
||||
import { ConnectionInfo, OnceBlockable, PollOptions } from 'ethers/utils/web';
|
||||
import { EncryptOptions, ProgressCallback } from 'ethers/utils/secret-storage';
|
||||
import { Wordlist } from 'ethers/utils/wordlist';
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
}
|
||||
|
||||
declare module 'ethers/wordlists' {
|
||||
@@ -254,7 +262,7 @@ declare module 'ethers/utils/shims' {
|
||||
}
|
||||
|
||||
declare module 'ethers/_version' {
|
||||
export const version = "4.0.2";
|
||||
export const version = "4.0.13";
|
||||
}
|
||||
|
||||
declare module 'ethers/utils/bignumber' {
|
||||
@@ -406,6 +414,7 @@ declare module 'ethers/utils/transaction' {
|
||||
import { BigNumber } from 'ethers/utils/bignumber';
|
||||
import { Arrayish, Signature } from 'ethers/utils/bytes';
|
||||
import { BigNumberish } from 'ethers/utils/bignumber';
|
||||
import { Provider } from 'ethers/providers/abstract-provider';
|
||||
export type UnsignedTransaction = {
|
||||
to?: string;
|
||||
nonce?: number;
|
||||
@@ -431,6 +440,7 @@ declare module 'ethers/utils/transaction' {
|
||||
}
|
||||
export function serialize(transaction: UnsignedTransaction, signature?: Arrayish | Signature): string;
|
||||
export function parse(rawTransaction: Arrayish): Transaction;
|
||||
export function populateTransaction(transaction: any, provider: Provider, from: string | Promise<string>): Promise<Transaction>;
|
||||
}
|
||||
|
||||
declare module 'ethers/providers/abstract-provider' {
|
||||
@@ -482,6 +492,7 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
transactionHash?: string;
|
||||
logs?: Array<Log>;
|
||||
blockNumber?: number;
|
||||
confirmations?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
byzantium: boolean;
|
||||
status?: number;
|
||||
@@ -500,9 +511,10 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
confirmations: number;
|
||||
from: string;
|
||||
raw?: string;
|
||||
wait: (timeout?: number) => Promise<TransactionReceipt>;
|
||||
wait: (confirmations?: number) => Promise<TransactionReceipt>;
|
||||
}
|
||||
export type EventType = string | Array<string> | Filter;
|
||||
export type Listener = (...args: Array<any>) => void;
|
||||
@@ -515,7 +527,7 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
abstract getCode(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
abstract call(transaction: TransactionRequest): Promise<string>;
|
||||
abstract call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
abstract getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
@@ -614,6 +626,7 @@ declare module 'ethers/utils/hdnode' {
|
||||
export class HDNode {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
readonly chainCode: string;
|
||||
@@ -703,7 +716,9 @@ declare module 'ethers/providers/base-provider' {
|
||||
import { Transaction } from 'ethers/utils/transaction';
|
||||
import { Network, Networkish } from 'ethers/utils/networks';
|
||||
export class BaseProvider extends Provider {
|
||||
protected _emitted: any;
|
||||
protected _emitted: {
|
||||
[eventName: string]: number | 'pending';
|
||||
};
|
||||
/**
|
||||
* ready
|
||||
*
|
||||
@@ -721,7 +736,9 @@ declare module 'ethers/providers/base-provider' {
|
||||
readonly blockNumber: number;
|
||||
polling: boolean;
|
||||
pollingInterval: number;
|
||||
waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
_getFastBlockNumber(): Promise<number>;
|
||||
_setFastBlockNumber(blockNumber: number): void;
|
||||
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt>;
|
||||
getBlockNumber(): Promise<number>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
getBalance(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<BigNumber>;
|
||||
@@ -730,7 +747,7 @@ declare module 'ethers/providers/base-provider' {
|
||||
getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
_wrapTransaction(tx: Transaction, hash?: string): TransactionResponse;
|
||||
call(transaction: TransactionRequest): Promise<string>;
|
||||
call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
@@ -828,7 +845,11 @@ declare module 'ethers/providers/json-rpc-provider' {
|
||||
perform(method: string, params: any): Promise<any>;
|
||||
protected _startPending(): void;
|
||||
protected _stopPending(): void;
|
||||
static hexlifyTransaction(transaction: TransactionRequest): any;
|
||||
static hexlifyTransaction(transaction: TransactionRequest, allowExtra?: {
|
||||
[key: string]: boolean;
|
||||
}): {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,6 +926,7 @@ declare module 'ethers/utils/networks' {
|
||||
name: string;
|
||||
chainId: number;
|
||||
ensAddress?: string;
|
||||
_defaultProvider?: (providers: any) => any;
|
||||
};
|
||||
export type Networkish = Network | string | number;
|
||||
/**
|
||||
@@ -921,6 +943,9 @@ declare module 'ethers/utils/properties' {
|
||||
export function setType(object: any, type: string): void;
|
||||
export function isType(object: any, type: string): boolean;
|
||||
export function resolveProperties(object: any): Promise<any>;
|
||||
export function checkProperties(object: any, properties: {
|
||||
[name: string]: boolean;
|
||||
}): void;
|
||||
export function shallowCopy(object: any): any;
|
||||
export function deepCopy(object: any, frozen?: boolean): any;
|
||||
export function inheritable(parent: any): (child: any) => void;
|
||||
|
||||
1
dist/shims.js
vendored
Normal file
1
dist/shims.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
errors.d.ts
vendored
1
errors.d.ts
vendored
@@ -14,3 +14,4 @@ export declare function throwError(message: string, code: string, params: any):
|
||||
export declare function checkNew(self: any, kind: any): void;
|
||||
export declare function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void;
|
||||
export declare function setCensorship(censorship: boolean, permanent?: boolean): void;
|
||||
export declare function checkNormalize(): void;
|
||||
|
||||
11
errors.js
11
errors.js
@@ -108,3 +108,14 @@ function setCensorship(censorship, permanent) {
|
||||
_permanentCensorErrors = !!permanent;
|
||||
}
|
||||
exports.setCensorship = setCensorship;
|
||||
function checkNormalize() {
|
||||
try {
|
||||
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
||||
throw new Error('broken');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
throwError('platform missing String.prototype.normalize', exports.UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize' });
|
||||
}
|
||||
}
|
||||
exports.checkNormalize = checkNormalize;
|
||||
|
||||
4
ethers.d.ts
vendored
4
ethers.d.ts
vendored
@@ -8,6 +8,6 @@ import * as utils from './utils';
|
||||
import * as wordlists from './wordlists';
|
||||
import { platform } from './utils/shims';
|
||||
import { version } from './_version';
|
||||
import { ContractFunction, Event, EventFilter } from './contract';
|
||||
import { ContractFunction, ContractTransaction, Event, EventFilter } from './contract';
|
||||
declare function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider;
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, Event, EventFilter };
|
||||
export { Signer, Wallet, VoidSigner, getDefaultProvider, providers, Contract, ContractFactory, constants, errors, utils, wordlists, platform, version, ContractFunction, ContractTransaction, Event, EventFilter };
|
||||
|
||||
15
ethers.js
15
ethers.js
@@ -36,9 +36,16 @@ exports.version = _version_1.version;
|
||||
////////////////////////
|
||||
// Helper Functions
|
||||
function getDefaultProvider(network) {
|
||||
return new providers.FallbackProvider([
|
||||
new providers.InfuraProvider(network),
|
||||
new providers.EtherscanProvider(network),
|
||||
]);
|
||||
if (network == null) {
|
||||
network = 'homestead';
|
||||
}
|
||||
var n = utils.getNetwork(network);
|
||||
if (!n || !n._defaultProvider) {
|
||||
errors.throwError('unsupported getDefaultProvider network', errors.UNSUPPORTED_OPERATION, {
|
||||
operation: 'getDefaultProvider',
|
||||
network: network
|
||||
});
|
||||
}
|
||||
return n._defaultProvider(providers);
|
||||
}
|
||||
exports.getDefaultProvider = getDefaultProvider;
|
||||
|
||||
32
gulpfile.js
32
gulpfile.js
@@ -152,7 +152,9 @@ function taskBundle(name, options) {
|
||||
if (options.minify) {
|
||||
result = result.pipe(buffer())
|
||||
.pipe(sourcemaps.init({ loadMaps: true }))
|
||||
.pipe(uglify())
|
||||
.pipe(uglify({
|
||||
output: { ascii_only: true }
|
||||
}))
|
||||
.pipe(sourcemaps.write('./'))
|
||||
}
|
||||
|
||||
@@ -174,6 +176,30 @@ taskBundle("minified", { filename: "ethers.min.js", dest: 'dist', minify: true }
|
||||
// Creates dist/ethers.min.js
|
||||
taskBundle("minified-test", { filename: "ethers.min.js", dest: 'tests/dist', minify: true });
|
||||
|
||||
gulp.task('shims', function () {
|
||||
|
||||
var result = browserify({
|
||||
basedir: '.',
|
||||
debug: false,
|
||||
entries: [ './tests/shims/index.js' ],
|
||||
cache: { },
|
||||
packageCache: {},
|
||||
standalone: "_shims",
|
||||
insertGlobalVars: {
|
||||
process: function() { return; },
|
||||
}
|
||||
})
|
||||
.bundle()
|
||||
.pipe(source('shims.js'))
|
||||
.pipe(buffer())
|
||||
.pipe(uglify({
|
||||
output: { ascii_only: true }
|
||||
}))
|
||||
.pipe(gulp.dest('dist'));
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/*
|
||||
// Dump the TypeScript definitions to dist/types/
|
||||
gulp.task("types", function() {
|
||||
@@ -265,7 +291,9 @@ function taskLang(locale) {
|
||||
.bundle()
|
||||
.pipe(source("wordlist-" + locale + ".js"))
|
||||
.pipe(buffer())
|
||||
.pipe(uglify())
|
||||
.pipe(uglify({
|
||||
output: { ascii_only: true }
|
||||
}))
|
||||
.pipe(gulp.dest("dist"));
|
||||
});
|
||||
}
|
||||
|
||||
77
package-lock.json
generated
77
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ethers",
|
||||
"version": "4.0.1",
|
||||
"version": "4.0.13",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -69,9 +69,9 @@
|
||||
"integrity": "sha512-8TqvB0ReZWwtcd3LXq3YSrBoLyXFgBX/sBZfGye9+YS8zH7/g+i6QRIuiDmwBoTzcQ/pk89nZYTYU4c5akKkzw=="
|
||||
},
|
||||
"JSONStream": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz",
|
||||
"integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==",
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
|
||||
"integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsonparse": "^1.2.0",
|
||||
@@ -95,13 +95,10 @@
|
||||
"dev": true
|
||||
},
|
||||
"acorn-dynamic-import": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
|
||||
"integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^5.0.0"
|
||||
}
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz",
|
||||
"integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
"version": "4.1.1",
|
||||
@@ -113,16 +110,31 @@
|
||||
}
|
||||
},
|
||||
"acorn-node": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.5.2.tgz",
|
||||
"integrity": "sha512-krFKvw/d1F17AN3XZbybIUzEY4YEPNiGo05AfP3dBlfVKrMHETKpgjpuZkSF8qDNt9UkQcqj7am8yJLseklCMg==",
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz",
|
||||
"integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^5.7.1",
|
||||
"acorn-dynamic-import": "^3.0.0",
|
||||
"acorn": "^6.0.2",
|
||||
"acorn-dynamic-import": "^4.0.0",
|
||||
"acorn-walk": "^6.1.0",
|
||||
"xtend": "^4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
|
||||
"integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.0.tgz",
|
||||
"integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg==",
|
||||
"dev": true
|
||||
},
|
||||
"aes-js": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
||||
@@ -783,9 +795,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"browserify": {
|
||||
"version": "16.2.2",
|
||||
"resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.2.tgz",
|
||||
"integrity": "sha512-fMES05wq1Oukts6ksGUU2TMVHHp06LyQt0SIwbXIHm7waSrQmNBZePsU0iM/4f94zbvb/wHma+D1YrdzWYnF/A==",
|
||||
"version": "16.2.3",
|
||||
"resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz",
|
||||
"integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"JSONStream": "^1.0.3",
|
||||
@@ -927,9 +939,9 @@
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-nUJyfChH7PMJy75eRDCCKtszSEFokUNXC1hNVSe+o+VdcgvDPLs20k3v8UXI8ruRYAJiYtyRea8mYyqPxoHWDw==",
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base64-js": "^1.0.2",
|
||||
@@ -996,9 +1008,9 @@
|
||||
}
|
||||
},
|
||||
"cached-path-relative": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz",
|
||||
"integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz",
|
||||
"integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==",
|
||||
"dev": true
|
||||
},
|
||||
"caller-path": {
|
||||
@@ -5288,9 +5300,9 @@
|
||||
}
|
||||
},
|
||||
"pbkdf2": {
|
||||
"version": "3.0.16",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz",
|
||||
"integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==",
|
||||
"version": "3.0.17",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
||||
"integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"create-hash": "^1.1.2",
|
||||
@@ -5392,16 +5404,17 @@
|
||||
}
|
||||
},
|
||||
"public-encrypt": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
|
||||
"integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
|
||||
"integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.1.0",
|
||||
"browserify-rsa": "^4.0.0",
|
||||
"create-hash": "^1.1.0",
|
||||
"parse-asn1": "^5.0.0",
|
||||
"randombytes": "^2.0.1"
|
||||
"randombytes": "^2.0.1",
|
||||
"safe-buffer": "^5.1.2"
|
||||
}
|
||||
},
|
||||
"pump": {
|
||||
|
||||
10
package.json
10
package.json
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "ethers",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.13",
|
||||
"description": "Ethereum wallet library.",
|
||||
"main": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
"scripts": {
|
||||
"build": "npm run dist-version && tsc -p ./tsconfig.json",
|
||||
"auto-build": "npm run build -- -w",
|
||||
"dist": "npm run dist-version && npm run build && gulp default minified && npm run dist-types",
|
||||
"dist-test": "gulp default-test minified-test",
|
||||
"dist": "npm run dist-version && npm run build && gulp default minified shims && npm run dist-types",
|
||||
"dist-test": "gulp default-test minified-test shims",
|
||||
"dist-bip39": "gulp bip39-es bip39-fr bip39-it bip39-ja bip39-ko bip39-zh",
|
||||
"dist-types": "dts-bundle --name ethers --main ./index.d.ts --out ./dist/ethers.types.txt",
|
||||
"dist-version": "node -e \"let v = require('./package.json').version; require('fs').writeFileSync('./src.ts/_version.ts', 'export const version = \\\"' + v +'\\\";\\n')\"",
|
||||
@@ -31,7 +31,7 @@
|
||||
"xmlhttprequest": "1.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^16.2.2",
|
||||
"browserify": "^16.2.3",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
"dts-bundle": "^0.7.3",
|
||||
"eslint": "^5.0.1",
|
||||
@@ -53,7 +53,7 @@
|
||||
"vinyl-source-stream": "^2.0.0",
|
||||
"web3-providers-http": "1.0.0-beta.35"
|
||||
},
|
||||
"browser": "./dist/ethers.js",
|
||||
"browser": "./dist/ethers.min.js",
|
||||
"keywords": [
|
||||
"ethereum",
|
||||
"library",
|
||||
|
||||
6
providers/abstract-provider.d.ts
vendored
6
providers/abstract-provider.d.ts
vendored
@@ -46,6 +46,7 @@ export interface TransactionReceipt {
|
||||
transactionHash?: string;
|
||||
logs?: Array<Log>;
|
||||
blockNumber?: number;
|
||||
confirmations?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
byzantium: boolean;
|
||||
status?: number;
|
||||
@@ -64,9 +65,10 @@ export interface TransactionResponse extends Transaction {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
confirmations: number;
|
||||
from: string;
|
||||
raw?: string;
|
||||
wait: (timeout?: number) => Promise<TransactionReceipt>;
|
||||
wait: (confirmations?: number) => Promise<TransactionReceipt>;
|
||||
}
|
||||
export declare type EventType = string | Array<string> | Filter;
|
||||
export declare type Listener = (...args: Array<any>) => void;
|
||||
@@ -79,7 +81,7 @@ export declare abstract class Provider implements OnceBlockable {
|
||||
abstract getCode(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
abstract call(transaction: TransactionRequest): Promise<string>;
|
||||
abstract call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
abstract getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
|
||||
13
providers/base-provider.d.ts
vendored
13
providers/base-provider.d.ts
vendored
@@ -7,11 +7,16 @@ import { Network, Networkish } from '../utils/networks';
|
||||
export declare class BaseProvider extends Provider {
|
||||
private _network;
|
||||
private _events;
|
||||
protected _emitted: any;
|
||||
protected _emitted: {
|
||||
[eventName: string]: number | 'pending';
|
||||
};
|
||||
private _pollingInterval;
|
||||
private _poller;
|
||||
private _lastBlockNumber;
|
||||
private _balances;
|
||||
private _fastBlockNumber;
|
||||
private _fastBlockNumberPromise;
|
||||
private _fastQueryDate;
|
||||
/**
|
||||
* ready
|
||||
*
|
||||
@@ -30,7 +35,9 @@ export declare class BaseProvider extends Provider {
|
||||
readonly blockNumber: number;
|
||||
polling: boolean;
|
||||
pollingInterval: number;
|
||||
waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
_getFastBlockNumber(): Promise<number>;
|
||||
_setFastBlockNumber(blockNumber: number): void;
|
||||
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt>;
|
||||
getBlockNumber(): Promise<number>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
getBalance(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<BigNumber>;
|
||||
@@ -39,7 +46,7 @@ export declare class BaseProvider extends Provider {
|
||||
getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
_wrapTransaction(tx: Transaction, hash?: string): TransactionResponse;
|
||||
call(transaction: TransactionRequest): Promise<string>;
|
||||
call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
|
||||
@@ -79,9 +79,15 @@ function arrayOf(check) {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
function checkHash(hash) {
|
||||
if (typeof (hash) === 'string' && bytes_1.hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
function checkHash(hash, requirePrefix) {
|
||||
if (typeof (hash) === 'string') {
|
||||
// geth-etc does add a "0x" prefix on receipt.root
|
||||
if (!requirePrefix && hash.substring(0, 2) !== '0x') {
|
||||
hash = '0x' + hash;
|
||||
}
|
||||
if (bytes_1.hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
}
|
||||
}
|
||||
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
|
||||
return null;
|
||||
@@ -150,6 +156,7 @@ var formatTransaction = {
|
||||
blockHash: allowNull(checkHash, null),
|
||||
blockNumber: allowNull(checkNumber, null),
|
||||
transactionIndex: allowNull(checkNumber, null),
|
||||
confirmations: allowNull(checkNumber, null),
|
||||
from: address_1.getAddress,
|
||||
gasPrice: bignumber_1.bigNumberify,
|
||||
gasLimit: bignumber_1.bigNumberify,
|
||||
@@ -201,6 +208,10 @@ function checkTransactionResponse(transaction) {
|
||||
}
|
||||
var result = check(formatTransaction, transaction);
|
||||
var networkId = transaction.networkId;
|
||||
// geth-etc returns chainId
|
||||
if (transaction.chainId != null && networkId == null && result.v == null) {
|
||||
networkId = transaction.chainId;
|
||||
}
|
||||
if (bytes_1.isHexString(networkId)) {
|
||||
networkId = bignumber_1.bigNumberify(networkId).toNumber();
|
||||
}
|
||||
@@ -278,6 +289,7 @@ var formatTransactionReceipt = {
|
||||
transactionHash: checkHash,
|
||||
logs: arrayOf(checkTransactionReceiptLog),
|
||||
blockNumber: checkNumber,
|
||||
confirmations: allowNull(checkNumber, null),
|
||||
cumulativeGasUsed: bignumber_1.bigNumberify,
|
||||
status: allowNull(checkNumber)
|
||||
};
|
||||
@@ -373,12 +385,12 @@ function getEventTag(eventName) {
|
||||
return 'address:' + address_1.getAddress(eventName);
|
||||
}
|
||||
eventName = eventName.toLowerCase();
|
||||
if (eventName === 'block' || eventName === 'pending' || eventName === 'error') {
|
||||
return eventName;
|
||||
}
|
||||
else if (bytes_1.hexDataLength(eventName) === 32) {
|
||||
if (bytes_1.hexDataLength(eventName) === 32) {
|
||||
return 'tx:' + eventName;
|
||||
}
|
||||
if (eventName.indexOf(':') === -1) {
|
||||
return eventName;
|
||||
}
|
||||
}
|
||||
else if (Array.isArray(eventName)) {
|
||||
return 'filter::' + serializeTopics(eventName);
|
||||
@@ -388,6 +400,11 @@ function getEventTag(eventName) {
|
||||
}
|
||||
throw new Error('invalid event - ' + eventName);
|
||||
}
|
||||
//////////////////////////////
|
||||
// Helper Object
|
||||
function getTime() {
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
var BaseProvider = /** @class */ (function (_super) {
|
||||
__extends(BaseProvider, _super);
|
||||
function BaseProvider(network) {
|
||||
@@ -415,39 +432,52 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// Events being listened to
|
||||
_this._events = [];
|
||||
_this._pollingInterval = 4000;
|
||||
// We use this to track recent emitted events; for example, if we emit a "block" of 100
|
||||
// and we get a `getBlock(100)` request which would result in null, we should retry
|
||||
// until we get a response. This provides devs with a consistent view. Similarly for
|
||||
// transaction hashes.
|
||||
_this._emitted = { block: _this._lastBlockNumber };
|
||||
_this._emitted = { block: -2 };
|
||||
_this._fastQueryDate = 0;
|
||||
return _this;
|
||||
}
|
||||
BaseProvider.prototype._doPoll = function () {
|
||||
var _this = this;
|
||||
this.getBlockNumber().then(function (blockNumber) {
|
||||
_this._setFastBlockNumber(blockNumber);
|
||||
// If the block hasn't changed, meh.
|
||||
if (blockNumber === _this._lastBlockNumber) {
|
||||
return;
|
||||
}
|
||||
if (_this._lastBlockNumber === -2) {
|
||||
_this._lastBlockNumber = blockNumber - 1;
|
||||
// First polling cycle, trigger a "block" events
|
||||
if (_this._emitted.block === -2) {
|
||||
_this._emitted.block = blockNumber - 1;
|
||||
}
|
||||
// Notify all listener for each block that has passed
|
||||
for (var i = _this._lastBlockNumber + 1; i <= blockNumber; i++) {
|
||||
if (_this._emitted.block < i) {
|
||||
_this._emitted.block = i;
|
||||
for (var i = _this._emitted.block + 1; i <= blockNumber; i++) {
|
||||
_this.emit('block', i);
|
||||
}
|
||||
// The emitted block was updated, check for obsolete events
|
||||
if (_this._emitted.block !== blockNumber) {
|
||||
_this._emitted.block = blockNumber;
|
||||
Object.keys(_this._emitted).forEach(function (key) {
|
||||
// The block event does not expire
|
||||
if (key === 'block') {
|
||||
return;
|
||||
}
|
||||
// The block we were at when we emitted this event
|
||||
var eventBlockNumber = _this._emitted[key];
|
||||
// We cannot garbage collect pending transactions or blocks here
|
||||
// They should be garbage collected by the Provider when setting
|
||||
// "pending" events
|
||||
if (eventBlockNumber === 'pending') {
|
||||
return;
|
||||
}
|
||||
// Evict any transaction hashes or block hashes over 12 blocks
|
||||
// old, since they should not return null anyways
|
||||
Object.keys(_this._emitted).forEach(function (key) {
|
||||
if (key === 'block') {
|
||||
return;
|
||||
}
|
||||
if (_this._emitted[key] > i + 12) {
|
||||
delete _this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
_this.emit('block', i);
|
||||
if (blockNumber - eventBlockNumber > 12) {
|
||||
delete _this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
// First polling cycle
|
||||
if (_this._lastBlockNumber === -2) {
|
||||
_this._lastBlockNumber = blockNumber - 1;
|
||||
}
|
||||
// Sweep balances and remove addresses we no longer have events for
|
||||
var newBalances = {};
|
||||
@@ -473,25 +503,27 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
newBalances[address_2] = _this._balances[address_2];
|
||||
}
|
||||
_this.getBalance(address_2, 'latest').then(function (balance) {
|
||||
var lastBalance = this._balances[address_2];
|
||||
var lastBalance = _this._balances[address_2];
|
||||
if (lastBalance && balance.eq(lastBalance)) {
|
||||
return;
|
||||
}
|
||||
this._balances[address_2] = balance;
|
||||
this.emit(address_2, balance);
|
||||
_this._balances[address_2] = balance;
|
||||
_this.emit(address_2, balance);
|
||||
return null;
|
||||
}).catch(function (error) { _this.emit('error', error); });
|
||||
break;
|
||||
}
|
||||
case 'filter': {
|
||||
var address = comps[1];
|
||||
var topics = deserializeTopics(comps[2]);
|
||||
var filter_1 = {
|
||||
address: address,
|
||||
address: comps[1],
|
||||
fromBlock: _this._lastBlockNumber + 1,
|
||||
toBlock: blockNumber,
|
||||
topics: topics
|
||||
};
|
||||
if (!filter_1.address) {
|
||||
delete filter_1.address;
|
||||
}
|
||||
_this.getLogs(filter_1).then(function (logs) {
|
||||
if (logs.length === 0) {
|
||||
return;
|
||||
@@ -514,8 +546,10 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
this.doPoll();
|
||||
};
|
||||
BaseProvider.prototype.resetEventsBlock = function (blockNumber) {
|
||||
this._lastBlockNumber = blockNumber;
|
||||
this._doPoll();
|
||||
this._lastBlockNumber = blockNumber - 1;
|
||||
if (this.polling) {
|
||||
this._doPoll();
|
||||
}
|
||||
};
|
||||
Object.defineProperty(BaseProvider.prototype, "network", {
|
||||
get: function () {
|
||||
@@ -529,10 +563,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
};
|
||||
Object.defineProperty(BaseProvider.prototype, "blockNumber", {
|
||||
get: function () {
|
||||
if (this._lastBlockNumber < 0) {
|
||||
return null;
|
||||
}
|
||||
return this._lastBlockNumber;
|
||||
return this._fastBlockNumber;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
@@ -574,13 +605,47 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
BaseProvider.prototype._getFastBlockNumber = function () {
|
||||
var _this = this;
|
||||
var now = getTime();
|
||||
// Stale block number, request a newer value
|
||||
if ((now - this._fastQueryDate) > 2 * this._pollingInterval) {
|
||||
this._fastQueryDate = now;
|
||||
this._fastBlockNumberPromise = this.getBlockNumber().then(function (blockNumber) {
|
||||
if (_this._fastBlockNumber == null || blockNumber > _this._fastBlockNumber) {
|
||||
_this._fastBlockNumber = blockNumber;
|
||||
}
|
||||
return _this._fastBlockNumber;
|
||||
});
|
||||
}
|
||||
return this._fastBlockNumberPromise;
|
||||
};
|
||||
BaseProvider.prototype._setFastBlockNumber = function (blockNumber) {
|
||||
// Older block, maybe a stale request
|
||||
if (this._fastBlockNumber != null && blockNumber < this._fastBlockNumber) {
|
||||
return;
|
||||
}
|
||||
// Update the time we updated the blocknumber
|
||||
this._fastQueryDate = getTime();
|
||||
// Newer block number, use it
|
||||
if (this._fastBlockNumber == null || blockNumber > this._fastBlockNumber) {
|
||||
this._fastBlockNumber = blockNumber;
|
||||
this._fastBlockNumberPromise = Promise.resolve(blockNumber);
|
||||
}
|
||||
};
|
||||
// @TODO: Add .poller which must be an event emitter with a 'start', 'stop' and 'block' event;
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, timeout) {
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, confirmations) {
|
||||
var _this = this;
|
||||
if (confirmations == null) {
|
||||
confirmations = 1;
|
||||
}
|
||||
return web_1.poll(function () {
|
||||
return _this.getTransactionReceipt(transactionHash).then(function (receipt) {
|
||||
if (receipt == null) {
|
||||
if (confirmations === 0) {
|
||||
return receipt;
|
||||
}
|
||||
if (receipt == null || receipt.confirmations < confirmations) {
|
||||
return undefined;
|
||||
}
|
||||
return receipt;
|
||||
@@ -595,6 +660,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (value != result) {
|
||||
throw new Error('invalid response - getBlockNumber');
|
||||
}
|
||||
_this._setFastBlockNumber(value);
|
||||
return value;
|
||||
});
|
||||
});
|
||||
@@ -688,7 +754,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// This should be called by any subclass wrapping a TransactionResponse
|
||||
BaseProvider.prototype._wrapTransaction = function (tx, hash) {
|
||||
var _this = this;
|
||||
if (bytes_1.hexDataLength(hash) !== 32) {
|
||||
if (hash != null && bytes_1.hexDataLength(hash) !== 32) {
|
||||
throw new Error('invalid response - sendTransaction');
|
||||
}
|
||||
var result = tx;
|
||||
@@ -696,13 +762,23 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (hash != null && tx.hash !== hash) {
|
||||
errors.throwError('Transaction hash mismatch from Provider.sendTransaction.', errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash });
|
||||
}
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
// @TODO: (confirmations? number, timeout? number)
|
||||
result.wait = function () {
|
||||
return _this.waitForTransaction(hash).then(function (receipt) {
|
||||
result.wait = function (confirmations) {
|
||||
// We know this transaction *must* exist (whether it gets mined is
|
||||
// another story), so setting an emitted value forces us to
|
||||
// wait even if the node returns null for the receipt
|
||||
if (confirmations !== 0) {
|
||||
_this._emitted['t:' + tx.hash] = 'pending';
|
||||
}
|
||||
return _this.waitForTransaction(tx.hash, confirmations).then(function (receipt) {
|
||||
if (receipt == null && confirmations === 0) {
|
||||
return null;
|
||||
}
|
||||
// No longer pending, allow the polling loop to garbage collect this
|
||||
_this._emitted['t:' + tx.hash] = receipt.blockNumber;
|
||||
if (receipt.status === 0) {
|
||||
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
|
||||
transactionHash: hash,
|
||||
transactionHash: tx.hash,
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
@@ -711,13 +787,14 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
};
|
||||
return result;
|
||||
};
|
||||
BaseProvider.prototype.call = function (transaction) {
|
||||
BaseProvider.prototype.call = function (transaction, blockTag) {
|
||||
var _this = this;
|
||||
var tx = properties_1.shallowCopy(transaction);
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties(tx).then(function (tx) {
|
||||
return properties_1.resolveProperties({ blockTag: blockTag, tx: tx }).then(function (_a) {
|
||||
var blockTag = _a.blockTag, tx = _a.tx;
|
||||
return _this._resolveNames(tx, ['to', 'from']).then(function (tx) {
|
||||
var params = { transaction: checkTransactionRequest(tx) };
|
||||
var params = { blockTag: checkBlockTag(blockTag), transaction: checkTransactionRequest(tx) };
|
||||
return _this.perform('call', params).then(function (result) {
|
||||
return bytes_1.hexlify(result);
|
||||
});
|
||||
@@ -751,12 +828,12 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return properties_1.resolveProperties({ blockHashOrBlockTag: blockHashOrBlockTag }).then(function (_a) {
|
||||
var blockHashOrBlockTag = _a.blockHashOrBlockTag;
|
||||
try {
|
||||
var blockHash = bytes_1.hexlify(blockHashOrBlockTag);
|
||||
if (bytes_1.hexDataLength(blockHash) === 32) {
|
||||
var blockHash_1 = bytes_1.hexlify(blockHashOrBlockTag);
|
||||
if (bytes_1.hexDataLength(blockHash_1) === 32) {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockHash: blockHash, includeTransactions: !!includeTransactions }).then(function (block) {
|
||||
return _this.perform('getBlock', { blockHash: blockHash_1, includeTransactions: !!includeTransactions }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (_this._emitted['b:' + blockHash] == null) {
|
||||
if (_this._emitted['b:' + blockHash_1] == null) {
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
@@ -776,7 +853,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockTag: blockTag_1, includeTransactions: !!includeTransactions }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (blockNumber_1 > _this._emitted.block) {
|
||||
if (blockNumber_1 <= _this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
@@ -795,7 +872,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
var params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransaction', params).then(function (result) {
|
||||
if (result == null) {
|
||||
@@ -804,7 +881,22 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return BaseProvider.checkTransactionResponse(result);
|
||||
var tx = BaseProvider.checkTransactionResponse(result);
|
||||
if (tx.blockNumber == null) {
|
||||
tx.confirmations = 0;
|
||||
}
|
||||
else if (tx.confirmations == null) {
|
||||
return _this._getFastBlockNumber().then(function (blockNumber) {
|
||||
// Add the confirmations using the fast block number (pessimistic)
|
||||
var confirmations = (blockNumber - tx.blockNumber) + 1;
|
||||
if (confirmations <= 0) {
|
||||
confirmations = 1;
|
||||
}
|
||||
tx.confirmations = confirmations;
|
||||
return _this._wrapTransaction(tx);
|
||||
});
|
||||
}
|
||||
return _this._wrapTransaction(tx);
|
||||
});
|
||||
}, { onceBlock: _this });
|
||||
});
|
||||
@@ -815,7 +907,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
var params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransactionReceipt', params).then(function (result) {
|
||||
if (result == null) {
|
||||
@@ -824,7 +916,26 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return checkTransactionReceipt(result);
|
||||
// "geth-etc" returns receipts before they are ready
|
||||
if (result.blockHash == null) {
|
||||
return undefined;
|
||||
}
|
||||
var receipt = checkTransactionReceipt(result);
|
||||
if (receipt.blockNumber == null) {
|
||||
receipt.confirmations = 0;
|
||||
}
|
||||
else if (receipt.confirmations == null) {
|
||||
return _this._getFastBlockNumber().then(function (blockNumber) {
|
||||
// Add the confirmations using the fast block number (pessimistic)
|
||||
var confirmations = (blockNumber - receipt.blockNumber) + 1;
|
||||
if (confirmations <= 0) {
|
||||
confirmations = 1;
|
||||
}
|
||||
receipt.confirmations = confirmations;
|
||||
return receipt;
|
||||
});
|
||||
}
|
||||
return receipt;
|
||||
});
|
||||
}, { onceBlock: _this });
|
||||
});
|
||||
@@ -1019,6 +1130,9 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
result = true;
|
||||
return !(event.once);
|
||||
});
|
||||
if (this.listenerCount() === 0) {
|
||||
this.polling = false;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
BaseProvider.prototype.listenerCount = function (eventName) {
|
||||
|
||||
@@ -112,52 +112,65 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
return _this;
|
||||
}
|
||||
EtherscanProvider.prototype.perform = function (method, params) {
|
||||
//if (!params) { params = {}; }
|
||||
var _this = this;
|
||||
var url = this.baseUrl;
|
||||
var apiKey = '';
|
||||
if (this.apiKey) {
|
||||
apiKey += '&apikey=' + this.apiKey;
|
||||
}
|
||||
var get = function (url, procFunc) {
|
||||
return web_1.fetchJson(url, null, procFunc || getJsonResult).then(function (result) {
|
||||
_this.emit('debug', {
|
||||
action: 'perform',
|
||||
request: url,
|
||||
response: result,
|
||||
provider: _this
|
||||
});
|
||||
return result;
|
||||
});
|
||||
};
|
||||
switch (method) {
|
||||
case 'getBlockNumber':
|
||||
url += '/api?module=proxy&action=eth_blockNumber' + apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
case 'getGasPrice':
|
||||
url += '/api?module=proxy&action=eth_gasPrice' + apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
case 'getBalance':
|
||||
// Returns base-10 result
|
||||
url += '/api?module=account&action=balance&address=' + params.address;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return web_1.fetchJson(url, null, getResult);
|
||||
return get(url, getResult);
|
||||
case 'getTransactionCount':
|
||||
url += '/api?module=proxy&action=eth_getTransactionCount&address=' + params.address;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
case 'getCode':
|
||||
url += '/api?module=proxy&action=eth_getCode&address=' + params.address;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url, getJsonResult);
|
||||
case 'getStorageAt':
|
||||
url += '/api?module=proxy&action=eth_getStorageAt&address=' + params.address;
|
||||
url += '&position=' + params.position;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url, getJsonResult);
|
||||
case 'sendTransaction':
|
||||
url += '/api?module=proxy&action=eth_sendRawTransaction&hex=' + params.signedTransaction;
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult).catch(function (error) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "Transaction with the same hash was already imported."
|
||||
if (error.responseText.indexOf('same hash was already imported') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce."
|
||||
if (error.responseText.indexOf('another transaction with same nonce') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
return get(url).catch(function (error) {
|
||||
if (error.responseText) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "Transaction with the same hash was already imported."
|
||||
if (error.responseText.indexOf('same hash was already imported') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "Transaction gas price is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce."
|
||||
if (error.responseText.indexOf('another transaction with same nonce') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -171,33 +184,39 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
url += '&boolean=false';
|
||||
}
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
}
|
||||
throw new Error('getBlock by blockHash not implmeneted');
|
||||
case 'getTransaction':
|
||||
url += '/api?module=proxy&action=eth_getTransactionByHash&txhash=' + params.transactionHash;
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
case 'getTransactionReceipt':
|
||||
url += '/api?module=proxy&action=eth_getTransactionReceipt&txhash=' + params.transactionHash;
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
case 'call':
|
||||
return get(url);
|
||||
case 'call': {
|
||||
var transaction = getTransactionString(params.transaction);
|
||||
if (transaction) {
|
||||
transaction = '&' + transaction;
|
||||
}
|
||||
url += '/api?module=proxy&action=eth_call' + transaction;
|
||||
//url += '&tag=' + params.blockTag + apiKey;
|
||||
if (params.blockTag !== 'latest') {
|
||||
throw new Error('EtherscanProvider does not support blockTag for call');
|
||||
}
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
case 'estimateGas':
|
||||
return get(url);
|
||||
}
|
||||
case 'estimateGas': {
|
||||
var transaction = getTransactionString(params.transaction);
|
||||
if (transaction) {
|
||||
transaction = '&' + transaction;
|
||||
}
|
||||
url += '/api?module=proxy&action=eth_estimateGas&' + transaction;
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
}
|
||||
case 'getLogs':
|
||||
url += '/api?module=logs&action=getLogs';
|
||||
try {
|
||||
@@ -227,7 +246,7 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
url += apiKey;
|
||||
var self = this;
|
||||
return web_1.fetchJson(url, null, getResult).then(function (logs) {
|
||||
return get(url, getResult).then(function (logs) {
|
||||
var txs = {};
|
||||
var seq = Promise.resolve();
|
||||
logs.forEach(function (log) {
|
||||
@@ -256,7 +275,7 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
url += '/api?module=stats&action=ethprice';
|
||||
url += apiKey;
|
||||
return web_1.fetchJson(url, null, getResult).then(function (result) {
|
||||
return get(url, getResult).then(function (result) {
|
||||
return parseFloat(result.ethusd);
|
||||
});
|
||||
default:
|
||||
@@ -266,6 +285,7 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
};
|
||||
// @TODO: Allow startBlock and endBlock to be Promises
|
||||
EtherscanProvider.prototype.getHistory = function (addressOrName, startBlock, endBlock) {
|
||||
var _this = this;
|
||||
var url = this.baseUrl;
|
||||
var apiKey = '';
|
||||
if (this.apiKey) {
|
||||
@@ -283,6 +303,12 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
url += '&endblock=' + endBlock;
|
||||
url += '&sort=asc' + apiKey;
|
||||
return web_1.fetchJson(url, null, getResult).then(function (result) {
|
||||
_this.emit('debug', {
|
||||
action: 'getHistory',
|
||||
request: url,
|
||||
response: result,
|
||||
provider: _this
|
||||
});
|
||||
var output = [];
|
||||
result.forEach(function (tx) {
|
||||
['contractAddress', 'to'].forEach(function (key) {
|
||||
|
||||
@@ -40,7 +40,8 @@ function checkNetworks(networks) {
|
||||
// Matches!
|
||||
if (check.name === network.name &&
|
||||
check.chainId === network.chainId &&
|
||||
check.ensAddress === network.ensAddress) {
|
||||
((check.ensAddress === network.ensAddress) ||
|
||||
(check.ensAddress == null && network.ensAddress == null))) {
|
||||
return;
|
||||
}
|
||||
errors.throwError('provider mismatch', errors.INVALID_ARGUMENT, { arg: 'networks', value: networks });
|
||||
|
||||
6
providers/json-rpc-provider.d.ts
vendored
6
providers/json-rpc-provider.d.ts
vendored
@@ -27,5 +27,9 @@ export declare class JsonRpcProvider extends BaseProvider {
|
||||
perform(method: string, params: any): Promise<any>;
|
||||
protected _startPending(): void;
|
||||
protected _stopPending(): void;
|
||||
static hexlifyTransaction(transaction: TransactionRequest): any;
|
||||
static hexlifyTransaction(transaction: TransactionRequest, allowExtra?: {
|
||||
[key: string]: boolean;
|
||||
}): {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,13 +20,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// See: https://github.com/ethereum/wiki/wiki/JSON-RPC
|
||||
var base_provider_1 = require("./base-provider");
|
||||
var abstract_signer_1 = require("../abstract-signer");
|
||||
var errors = __importStar(require("../errors"));
|
||||
var address_1 = require("../utils/address");
|
||||
var bytes_1 = require("../utils/bytes");
|
||||
var networks_1 = require("../utils/networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var transaction_1 = require("../utils/transaction");
|
||||
var utf8_1 = require("../utils/utf8");
|
||||
var web_1 = require("../utils/web");
|
||||
var errors = __importStar(require("../errors"));
|
||||
function timer(timeout) {
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(function () {
|
||||
@@ -77,14 +78,6 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
/* May add back in the future; for now it is considered confusing. :)
|
||||
get address(): string {
|
||||
if (!this._address) {
|
||||
errors.throwError('no sync sync address available; use getAddress', errors.UNSUPPORTED_OPERATION, { operation: 'address' });
|
||||
}
|
||||
return this._address
|
||||
}
|
||||
*/
|
||||
JsonRpcSigner.prototype.getAddress = function () {
|
||||
var _this = this;
|
||||
if (this._address) {
|
||||
@@ -106,20 +99,18 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
};
|
||||
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
|
||||
var _this = this;
|
||||
var tx = properties_1.shallowCopy(transaction);
|
||||
if (tx.from == null) {
|
||||
tx.from = this.getAddress().then(function (address) {
|
||||
if (!address) {
|
||||
return null;
|
||||
}
|
||||
return address.toLowerCase();
|
||||
});
|
||||
}
|
||||
if (transaction.gasLimit == null) {
|
||||
tx.gasLimit = this.provider.estimateGas(tx);
|
||||
}
|
||||
return properties_1.resolveProperties(tx).then(function (tx) {
|
||||
return _this.provider.send('eth_sendTransaction', [JsonRpcProvider.hexlifyTransaction(tx)]).then(function (hash) {
|
||||
// Once populateTransaction resolves, the from address will be populated from getAddress
|
||||
var from = null;
|
||||
var getAddress = this.getAddress().then(function (address) {
|
||||
if (address) {
|
||||
from = address.toLowerCase();
|
||||
}
|
||||
return from;
|
||||
});
|
||||
return transaction_1.populateTransaction(transaction, this.provider, getAddress).then(function (tx) {
|
||||
var hexTx = JsonRpcProvider.hexlifyTransaction(tx);
|
||||
hexTx.from = from;
|
||||
return _this.provider.send('eth_sendTransaction', [hexTx]).then(function (hash) {
|
||||
return web_1.poll(function () {
|
||||
return _this.provider.getTransaction(hash).then(function (tx) {
|
||||
if (tx === null) {
|
||||
@@ -132,21 +123,23 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
throw error;
|
||||
});
|
||||
}, function (error) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
if (error.responseText.indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('nonce too low') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {
|
||||
transaction: tx
|
||||
});
|
||||
if (error.responseText) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
if (error.responseText.indexOf('insufficient funds') >= 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('nonce too low') >= 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') >= 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {
|
||||
transaction: tx
|
||||
});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -169,6 +162,9 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
return JsonRpcSigner;
|
||||
}(abstract_signer_1.Signer));
|
||||
exports.JsonRpcSigner = JsonRpcSigner;
|
||||
var allowedTransactionKeys = {
|
||||
chainId: true, data: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
|
||||
};
|
||||
var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
__extends(JsonRpcProvider, _super);
|
||||
function JsonRpcProvider(url, network) {
|
||||
@@ -221,13 +217,22 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
});
|
||||
};
|
||||
JsonRpcProvider.prototype.send = function (method, params) {
|
||||
var _this = this;
|
||||
var request = {
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
jsonrpc: "2.0"
|
||||
};
|
||||
return web_1.fetchJson(this.connection, JSON.stringify(request), getResult);
|
||||
return web_1.fetchJson(this.connection, JSON.stringify(request), getResult).then(function (result) {
|
||||
_this.emit('debug', {
|
||||
action: 'send',
|
||||
request: request,
|
||||
response: result,
|
||||
provider: _this
|
||||
});
|
||||
return result;
|
||||
});
|
||||
};
|
||||
JsonRpcProvider.prototype.perform = function (method, params) {
|
||||
switch (method) {
|
||||
@@ -245,17 +250,19 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
return this.send('eth_getStorageAt', [getLowerCase(params.address), params.position, params.blockTag]);
|
||||
case 'sendTransaction':
|
||||
return this.send('eth_sendRawTransaction', [params.signedTransaction]).catch(function (error) {
|
||||
// "insufficient funds for gas * price + value"
|
||||
if (error.responseText.indexOf('insufficient funds') > 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "nonce too low"
|
||||
if (error.responseText.indexOf('nonce too low') > 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "replacement transaction underpriced"
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') > 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
if (error.responseText) {
|
||||
// "insufficient funds for gas * price + value"
|
||||
if (error.responseText.indexOf('insufficient funds') > 0) {
|
||||
errors.throwError('insufficient funds', errors.INSUFFICIENT_FUNDS, {});
|
||||
}
|
||||
// "nonce too low"
|
||||
if (error.responseText.indexOf('nonce too low') > 0) {
|
||||
errors.throwError('nonce has already been used', errors.NONCE_EXPIRED, {});
|
||||
}
|
||||
// "replacement transaction underpriced"
|
||||
if (error.responseText.indexOf('replacement transaction underpriced') > 0) {
|
||||
errors.throwError('replacement fee too low', errors.REPLACEMENT_UNDERPRICED, {});
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
@@ -272,9 +279,9 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
case 'getTransactionReceipt':
|
||||
return this.send('eth_getTransactionReceipt', [params.transactionHash]);
|
||||
case 'call':
|
||||
return this.send('eth_call', [JsonRpcProvider.hexlifyTransaction(params.transaction), 'latest']);
|
||||
return this.send('eth_call', [JsonRpcProvider.hexlifyTransaction(params.transaction, { from: true }), params.blockTag]);
|
||||
case 'estimateGas':
|
||||
return this.send('eth_estimateGas', [JsonRpcProvider.hexlifyTransaction(params.transaction)]);
|
||||
return this.send('eth_estimateGas', [JsonRpcProvider.hexlifyTransaction(params.transaction, { from: true })]);
|
||||
case 'getLogs':
|
||||
if (params.filter && params.filter.address != null) {
|
||||
params.filter.address = getLowerCase(params.filter.address);
|
||||
@@ -301,6 +308,7 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
var seq = Promise.resolve();
|
||||
hashes.forEach(function (hash) {
|
||||
// @TODO: This should be garbage collected at some point... How? When?
|
||||
self._emitted['t:' + hash.toLowerCase()] = 'pending';
|
||||
seq = seq.then(function () {
|
||||
return self.getTransaction(hash).then(function (tx) {
|
||||
@@ -332,10 +340,21 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
// - gasLimit => gas
|
||||
// - All values hexlified
|
||||
// - All numeric values zero-striped
|
||||
// @TODO: Not any, a dictionary of string to strings
|
||||
JsonRpcProvider.hexlifyTransaction = function (transaction) {
|
||||
// NOTE: This allows a TransactionRequest, but all values should be resolved
|
||||
// before this is called
|
||||
JsonRpcProvider.hexlifyTransaction = function (transaction, allowExtra) {
|
||||
// Check only allowed properties are given
|
||||
var allowed = properties_1.shallowCopy(allowedTransactionKeys);
|
||||
if (allowExtra) {
|
||||
for (var key in allowExtra) {
|
||||
if (allowExtra[key]) {
|
||||
allowed[key] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
properties_1.checkProperties(transaction, allowed);
|
||||
var result = {};
|
||||
// Some nodes (INFURA ropsten; INFURA mainnet is fine) don't like extra zeros.
|
||||
// Some nodes (INFURA ropsten; INFURA mainnet is fine) don't like leading zeros.
|
||||
['gasLimit', 'gasPrice', 'nonce', 'value'].forEach(function (key) {
|
||||
if (transaction[key] == null) {
|
||||
return;
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const version = "4.0.2";
|
||||
export const version = "4.0.13";
|
||||
|
||||
@@ -16,7 +16,7 @@ import { UnsignedTransaction } from './utils/transaction';
|
||||
///////////////////////////////
|
||||
// Imported Abstracts
|
||||
|
||||
import { Provider } from './providers/abstract-provider';
|
||||
import { BlockTag, Provider } from './providers/abstract-provider';
|
||||
import { Signer } from './abstract-signer';
|
||||
|
||||
///////////////////////////////
|
||||
@@ -148,14 +148,22 @@ type RunFunction = (...params: Array<any>) => Promise<any>;
|
||||
function runMethod(contract: Contract, functionName: string, estimateOnly: boolean): RunFunction {
|
||||
let method = contract.interface.functions[functionName];
|
||||
return function(...params): Promise<any> {
|
||||
var tx: any = {}
|
||||
let tx: any = {}
|
||||
|
||||
let blockTag: BlockTag = null;
|
||||
|
||||
// If 1 extra parameter was passed in, it contains overrides
|
||||
if (params.length === method.inputs.length + 1 && typeof(params[params.length - 1]) === 'object') {
|
||||
tx = shallowCopy(params.pop());
|
||||
|
||||
if (tx.blockTag != null) {
|
||||
blockTag = tx.blockTag;
|
||||
}
|
||||
|
||||
delete tx.blockTag;
|
||||
|
||||
// Check for unexpected keys (e.g. using "gas" instead of "gasLimit")
|
||||
for (var key in tx) {
|
||||
for (let key in tx) {
|
||||
if (!allowedTransactionKeys[key]) {
|
||||
throw new Error('unknown transaction override ' + key);
|
||||
}
|
||||
@@ -202,7 +210,7 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
tx.from = contract.signer.getAddress()
|
||||
}
|
||||
|
||||
return contract.provider.call(tx).then((value) => {
|
||||
return contract.provider.call(tx, blockTag).then((value) => {
|
||||
|
||||
if ((hexDataLength(value) % 32) === 4 && hexDataSlice(value, 0, 4) === '0x08c379a0') {
|
||||
let reason = defaultAbiCoder.decode([ 'string' ], hexDataSlice(value, 4));
|
||||
@@ -791,7 +799,7 @@ export class ContractFactory {
|
||||
});
|
||||
|
||||
// Make sure the call matches the constructor signature
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, 'in Contract constructor');
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, ' in Contract constructor');
|
||||
|
||||
// Set the data to the bytecode + the encoded constructor arguments
|
||||
tx.data = this.interface.deployFunction.encode(this.bytecode, args);
|
||||
|
||||
@@ -122,3 +122,22 @@ export function setCensorship(censorship: boolean, permanent?: boolean): void {
|
||||
_censorErrors = !!censorship;
|
||||
_permanentCensorErrors = !!permanent;
|
||||
}
|
||||
|
||||
export function checkNormalize(): void {
|
||||
try {
|
||||
// Make sure all forms of normalization are supported
|
||||
["NFD", "NFC", "NFKD", "NFKC"].forEach((form) => {
|
||||
try {
|
||||
"test".normalize(form);
|
||||
} catch(error) {
|
||||
throw new Error('missing ' + form);
|
||||
}
|
||||
});
|
||||
|
||||
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
||||
throw new Error('broken implementation')
|
||||
}
|
||||
} catch (error) {
|
||||
throwError('platform missing String.prototype.normalize', UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize', form: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,15 @@ import { ContractFunction, ContractTransaction, Event, EventFilter } from './con
|
||||
// Helper Functions
|
||||
|
||||
function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider {
|
||||
return new providers.FallbackProvider([
|
||||
new providers.InfuraProvider(network),
|
||||
new providers.EtherscanProvider(network),
|
||||
]);
|
||||
if (network == null) { network = 'homestead'; }
|
||||
let n = utils.getNetwork(network);
|
||||
if (!n || !n._defaultProvider) {
|
||||
errors.throwError('unsupported getDefaultProvider network', errors.UNSUPPORTED_OPERATION, {
|
||||
operation: 'getDefaultProvider',
|
||||
network: network
|
||||
});
|
||||
}
|
||||
return n._defaultProvider(providers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ export abstract class Provider implements OnceBlockable {
|
||||
abstract getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
|
||||
abstract sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
abstract call(transaction: TransactionRequest): Promise<string>;
|
||||
abstract call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
|
||||
@@ -38,10 +38,10 @@ import { Network, Networkish } from '../utils/networks';
|
||||
|
||||
// @TODO: not any?
|
||||
function check(format: any, object: any): any {
|
||||
var result: any = {};
|
||||
for (var key in format) {
|
||||
let result: any = {};
|
||||
for (let key in format) {
|
||||
try {
|
||||
var value = format[key](object[key]);
|
||||
let value = format[key](object[key]);
|
||||
if (value !== undefined) { result[key] = value; }
|
||||
} catch (error) {
|
||||
error.checkKey = key;
|
||||
@@ -72,7 +72,7 @@ function arrayOf(check: CheckFunc): CheckFunc {
|
||||
return (function(array: any): Array<any> {
|
||||
if (!Array.isArray(array)) { throw new Error('not an array'); }
|
||||
|
||||
var result: any = [];
|
||||
let result: any = [];
|
||||
|
||||
array.forEach(function(value) {
|
||||
result.push(check(value));
|
||||
@@ -82,9 +82,13 @@ function arrayOf(check: CheckFunc): CheckFunc {
|
||||
});
|
||||
}
|
||||
|
||||
function checkHash(hash: any): string {
|
||||
if (typeof(hash) === 'string' && hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
function checkHash(hash: any, requirePrefix?: boolean): string {
|
||||
if (typeof(hash) === 'string') {
|
||||
// geth-etc does add a "0x" prefix on receipt.root
|
||||
if (!requirePrefix && hash.substring(0, 2) !== '0x') { hash = '0x' + hash; }
|
||||
if (hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
}
|
||||
}
|
||||
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
|
||||
return null;
|
||||
@@ -204,7 +208,7 @@ function checkTransactionResponse(transaction: any): TransactionResponse {
|
||||
|
||||
// Very loose providers (e.g. TestRPC) don't provide a signature or raw
|
||||
if (transaction.v && transaction.r && transaction.s) {
|
||||
var raw = [
|
||||
let raw = [
|
||||
stripZeros(hexlify(transaction.nonce)),
|
||||
stripZeros(hexlify(transaction.gasPrice)),
|
||||
stripZeros(hexlify(transaction.gasLimit)),
|
||||
@@ -220,10 +224,14 @@ function checkTransactionResponse(transaction: any): TransactionResponse {
|
||||
}
|
||||
}
|
||||
|
||||
let result = check(formatTransaction, transaction);
|
||||
|
||||
var result = check(formatTransaction, transaction);
|
||||
let networkId = transaction.networkId;
|
||||
|
||||
var networkId = transaction.networkId;
|
||||
// geth-etc returns chainId
|
||||
if (transaction.chainId != null && networkId == null && result.v == null) {
|
||||
networkId = transaction.chainId;
|
||||
}
|
||||
|
||||
if (isHexString(networkId)) {
|
||||
networkId = bigNumberify(networkId).toNumber();
|
||||
@@ -324,7 +332,7 @@ function checkTransactionReceipt(transactionReceipt: any): TransactionReceipt {
|
||||
//var status = transactionReceipt.status;
|
||||
//var root = transactionReceipt.root;
|
||||
|
||||
var result: TransactionReceipt = check(formatTransactionReceipt, transactionReceipt);
|
||||
let result: TransactionReceipt = check(formatTransactionReceipt, transactionReceipt);
|
||||
result.logs.forEach(function(entry, index) {
|
||||
if (entry.transactionLogIndex == null) {
|
||||
entry.transactionLogIndex = index;
|
||||
@@ -425,13 +433,14 @@ function getEventTag(eventName: EventType): string {
|
||||
|
||||
eventName = eventName.toLowerCase();
|
||||
|
||||
if (eventName === 'block' || eventName === 'pending' || eventName === 'error') {
|
||||
return eventName;
|
||||
|
||||
} else if (hexDataLength(eventName) === 32) {
|
||||
if (hexDataLength(eventName) === 32) {
|
||||
return 'tx:' + eventName;
|
||||
}
|
||||
|
||||
if (eventName.indexOf(':') === -1) {
|
||||
return eventName;
|
||||
}
|
||||
|
||||
} else if (Array.isArray(eventName)) {
|
||||
return 'filter::' + serializeTopics(eventName);
|
||||
|
||||
@@ -474,10 +483,21 @@ export class BaseProvider extends Provider {
|
||||
private _network: Network;
|
||||
|
||||
private _events: Array<_Event>;
|
||||
protected _emitted: any;
|
||||
|
||||
// To help mitigate the eventually conssitent nature of the blockchain
|
||||
// we keep a mapping of events we emit. If we emit an event X, we expect
|
||||
// that a user should be able to query for that event in the callback,
|
||||
// if the node returns null, we stall the response until we get back a
|
||||
// meaningful value, since we may be hitting a re-org, or a node that
|
||||
// has not indexed the event yet.
|
||||
// Events:
|
||||
// - t:{hash} - Transaction hash
|
||||
// - b:{hash} - BlockHash
|
||||
// - block - The most recent emitted block
|
||||
protected _emitted: { [ eventName: string ]: number | 'pending' };
|
||||
|
||||
private _pollingInterval: number;
|
||||
private _poller: any; // @TODO: what does TypeScript thing setInterval returns?
|
||||
private _poller: any; // @TODO: what does TypeScript think setInterval returns?
|
||||
|
||||
private _lastBlockNumber: number;
|
||||
|
||||
@@ -531,11 +551,7 @@ export class BaseProvider extends Provider {
|
||||
|
||||
this._pollingInterval = 4000;
|
||||
|
||||
// We use this to track recent emitted events; for example, if we emit a "block" of 100
|
||||
// and we get a `getBlock(100)` request which would result in null, we should retry
|
||||
// until we get a response. This provides devs with a consistent view. Similarly for
|
||||
// transaction hashes.
|
||||
this._emitted = { block: this._lastBlockNumber };
|
||||
this._emitted = { block: -2 };
|
||||
|
||||
this._fastQueryDate = 0;
|
||||
}
|
||||
@@ -547,28 +563,47 @@ export class BaseProvider extends Provider {
|
||||
// If the block hasn't changed, meh.
|
||||
if (blockNumber === this._lastBlockNumber) { return; }
|
||||
|
||||
if (this._lastBlockNumber === -2) { this._lastBlockNumber = blockNumber - 1; }
|
||||
// First polling cycle, trigger a "block" events
|
||||
if (this._emitted.block === -2) {
|
||||
this._emitted.block = blockNumber - 1;
|
||||
}
|
||||
|
||||
// Notify all listener for each block that has passed
|
||||
for (var i = this._lastBlockNumber + 1; i <= blockNumber; i++) {
|
||||
if (this._emitted.block < i) {
|
||||
this._emitted.block = i;
|
||||
|
||||
// Evict any transaction hashes or block hashes over 12 blocks
|
||||
// old, since they should not return null anyways
|
||||
Object.keys(this._emitted).forEach((key) => {
|
||||
if (key === 'block') { return; }
|
||||
|
||||
if (this._emitted[key] > i + 12) {
|
||||
delete this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
for (let i = (<number>this._emitted.block) + 1; i <= blockNumber; i++) {
|
||||
this.emit('block', i);
|
||||
}
|
||||
|
||||
// The emitted block was updated, check for obsolete events
|
||||
if ((<number>this._emitted.block) !== blockNumber) {
|
||||
this._emitted.block = blockNumber;
|
||||
|
||||
Object.keys(this._emitted).forEach((key) => {
|
||||
// The block event does not expire
|
||||
if (key === 'block') { return; }
|
||||
|
||||
// The block we were at when we emitted this event
|
||||
let eventBlockNumber = this._emitted[key];
|
||||
|
||||
// We cannot garbage collect pending transactions or blocks here
|
||||
// They should be garbage collected by the Provider when setting
|
||||
// "pending" events
|
||||
if (eventBlockNumber === 'pending') { return; }
|
||||
|
||||
// Evict any transaction hashes or block hashes over 12 blocks
|
||||
// old, since they should not return null anyways
|
||||
if (blockNumber - eventBlockNumber > 12) {
|
||||
delete this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// First polling cycle
|
||||
if (this._lastBlockNumber === -2) {
|
||||
this._lastBlockNumber = blockNumber - 1;
|
||||
}
|
||||
|
||||
// Sweep balances and remove addresses we no longer have events for
|
||||
var newBalances: any = {};
|
||||
let newBalances: any = {};
|
||||
|
||||
// Find all transaction hashes we are waiting on
|
||||
this._events.forEach((event) => {
|
||||
@@ -582,6 +617,7 @@ export class BaseProvider extends Provider {
|
||||
this.emit(hash, receipt);
|
||||
return null;
|
||||
}).catch((error: Error) => { this.emit('error', error); });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -590,25 +626,27 @@ export class BaseProvider extends Provider {
|
||||
if (this._balances[address]) {
|
||||
newBalances[address] = this._balances[address];
|
||||
}
|
||||
this.getBalance(address, 'latest').then(function(balance) {
|
||||
var lastBalance = this._balances[address];
|
||||
|
||||
this.getBalance(address, 'latest').then((balance) => {
|
||||
let lastBalance = this._balances[address];
|
||||
if (lastBalance && balance.eq(lastBalance)) { return; }
|
||||
this._balances[address] = balance;
|
||||
this.emit(address, balance);
|
||||
return null;
|
||||
}).catch((error: Error) => { this.emit('error', error); });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'filter': {
|
||||
let address = comps[1];
|
||||
let topics = deserializeTopics(comps[2]);
|
||||
let filter = {
|
||||
address: address,
|
||||
address: comps[1],
|
||||
fromBlock: this._lastBlockNumber + 1,
|
||||
toBlock: blockNumber,
|
||||
topics: topics
|
||||
}
|
||||
if (!filter.address) { delete filter.address; }
|
||||
this.getLogs(filter).then((logs) => {
|
||||
if (logs.length === 0) { return; }
|
||||
logs.forEach((log: Log) => {
|
||||
@@ -629,12 +667,13 @@ export class BaseProvider extends Provider {
|
||||
|
||||
return null;
|
||||
}).catch((error: Error) => { });
|
||||
|
||||
this.doPoll();
|
||||
}
|
||||
|
||||
resetEventsBlock(blockNumber: number): void {
|
||||
this._lastBlockNumber = blockNumber;
|
||||
this._doPoll();
|
||||
this._lastBlockNumber = blockNumber - 1;
|
||||
if (this.polling) { this._doPoll(); }
|
||||
}
|
||||
|
||||
get network(): Network {
|
||||
@@ -646,8 +685,7 @@ export class BaseProvider extends Provider {
|
||||
}
|
||||
|
||||
get blockNumber(): number {
|
||||
if (this._lastBlockNumber < 0) { return null; }
|
||||
return this._lastBlockNumber;
|
||||
return this._fastBlockNumber;
|
||||
}
|
||||
|
||||
get polling(): boolean {
|
||||
@@ -718,10 +756,13 @@ export class BaseProvider extends Provider {
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
|
||||
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt> {
|
||||
if (!confirmations) { confirmations = 1; }
|
||||
if (confirmations == null) { confirmations = 1; }
|
||||
return poll(() => {
|
||||
return this.getTransactionReceipt(transactionHash).then((receipt) => {
|
||||
if (receipt == null || receipt.confirmations < confirmations) { return undefined; }
|
||||
if (confirmations === 0) { return receipt; }
|
||||
if (receipt == null || receipt.confirmations < confirmations) {
|
||||
return undefined;
|
||||
}
|
||||
return receipt;
|
||||
});
|
||||
}, { onceBlock: this });
|
||||
@@ -751,7 +792,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(({ addressOrName, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
var params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
let params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return this.perform('getBalance', params).then((result) => {
|
||||
return bigNumberify(result);
|
||||
});
|
||||
@@ -764,7 +805,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(({ addressOrName, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
var params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
let params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return this.perform('getTransactionCount', params).then((result) => {
|
||||
return bigNumberify(result).toNumber();
|
||||
});
|
||||
@@ -777,7 +818,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(({ addressOrName, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
var params = {address: address, blockTag: checkBlockTag(blockTag)};
|
||||
let params = {address: address, blockTag: checkBlockTag(blockTag)};
|
||||
return this.perform('getCode', params).then((result) => {
|
||||
return hexlify(result);
|
||||
});
|
||||
@@ -790,7 +831,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, position: position, blockTag: blockTag }).then(({ addressOrName, position, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
var params = {
|
||||
let params = {
|
||||
address: address,
|
||||
blockTag: checkBlockTag(blockTag),
|
||||
position: hexStripZeros(hexlify(position)),
|
||||
@@ -806,7 +847,7 @@ export class BaseProvider extends Provider {
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ signedTransaction: signedTransaction }).then(({ signedTransaction }) => {
|
||||
var params = { signedTransaction: hexlify(signedTransaction) };
|
||||
let params = { signedTransaction: hexlify(signedTransaction) };
|
||||
return this.perform('sendTransaction', params).then((hash) => {
|
||||
return this._wrapTransaction(parseTransaction(signedTransaction), hash);
|
||||
}, function (error) {
|
||||
@@ -831,11 +872,22 @@ export class BaseProvider extends Provider {
|
||||
errors.throwError('Transaction hash mismatch from Provider.sendTransaction.', errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash });
|
||||
}
|
||||
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
|
||||
// @TODO: (confirmations? number, timeout? number)
|
||||
result.wait = (confirmations?: number) => {
|
||||
|
||||
// We know this transaction *must* exist (whether it gets mined is
|
||||
// another story), so setting an emitted value forces us to
|
||||
// wait even if the node returns null for the receipt
|
||||
if (confirmations !== 0) {
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
}
|
||||
|
||||
return this.waitForTransaction(tx.hash, confirmations).then((receipt) => {
|
||||
if (receipt == null && confirmations === 0) { return null; }
|
||||
|
||||
// No longer pending, allow the polling loop to garbage collect this
|
||||
this._emitted['t:' + tx.hash] = receipt.blockNumber;
|
||||
|
||||
if (receipt.status === 0) {
|
||||
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
|
||||
transactionHash: tx.hash,
|
||||
@@ -850,12 +902,12 @@ export class BaseProvider extends Provider {
|
||||
}
|
||||
|
||||
|
||||
call(transaction: TransactionRequest): Promise<string> {
|
||||
call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string> {
|
||||
let tx: TransactionRequest = shallowCopy(transaction);
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties(tx).then((tx) => {
|
||||
return resolveProperties({ blockTag: blockTag, tx: tx }).then(({ blockTag, tx }) => {
|
||||
return this._resolveNames(tx, [ 'to', 'from' ]).then((tx) => {
|
||||
var params = { transaction: checkTransactionRequest(tx) };
|
||||
let params = { blockTag: checkBlockTag(blockTag), transaction: checkTransactionRequest(tx) };
|
||||
return this.perform('call', params).then((result) => {
|
||||
return hexlify(result);
|
||||
});
|
||||
@@ -876,7 +928,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties(tx).then((tx) => {
|
||||
return this._resolveNames(tx, [ 'to', 'from' ]).then((tx) => {
|
||||
var params = { transaction: checkTransactionRequest(tx) };
|
||||
let params = { transaction: checkTransactionRequest(tx) };
|
||||
return this.perform('estimateGas', params).then((result) => {
|
||||
return bigNumberify(result);
|
||||
});
|
||||
@@ -889,7 +941,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ blockHashOrBlockTag: blockHashOrBlockTag }).then(({ blockHashOrBlockTag }) => {
|
||||
try {
|
||||
var blockHash = hexlify(blockHashOrBlockTag);
|
||||
let blockHash = hexlify(blockHashOrBlockTag);
|
||||
if (hexDataLength(blockHash) === 32) {
|
||||
return poll(() => {
|
||||
return this.perform('getBlock', { blockHash: blockHash, includeTransactions: !!includeTransactions }).then((block) => {
|
||||
@@ -917,7 +969,7 @@ export class BaseProvider extends Provider {
|
||||
return poll(() => {
|
||||
return this.perform('getBlock', { blockTag: blockTag, includeTransactions: !!includeTransactions }).then((block) => {
|
||||
if (block == null) {
|
||||
if (blockNumber > this._emitted.block) {
|
||||
if (blockNumber <= this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
@@ -935,7 +987,7 @@ export class BaseProvider extends Provider {
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
|
||||
let params = { transactionHash: checkHash(transactionHash) };
|
||||
let params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return poll(() => {
|
||||
return this.perform('getTransaction', params).then((result) => {
|
||||
if (result == null) {
|
||||
@@ -972,7 +1024,7 @@ export class BaseProvider extends Provider {
|
||||
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
|
||||
let params = { transactionHash: checkHash(transactionHash) };
|
||||
let params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return poll(() => {
|
||||
return this.perform('getTransactionReceipt', params).then((result) => {
|
||||
if (result == null) {
|
||||
@@ -1013,7 +1065,7 @@ export class BaseProvider extends Provider {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties(filter).then((filter) => {
|
||||
return this._resolveNames(filter, ['address']).then((filter) => {
|
||||
var params = { filter: checkFilter(filter) };
|
||||
let params = { filter: checkFilter(filter) };
|
||||
return this.perform('getLogs', params).then((result) => {
|
||||
return arrayOf(checkLog)(result);
|
||||
});
|
||||
@@ -1033,9 +1085,9 @@ export class BaseProvider extends Provider {
|
||||
|
||||
// @TODO: Could probably use resolveProperties instead?
|
||||
private _resolveNames(object: any, keys: Array<string>): Promise<{ [key: string]: string }> {
|
||||
var promises: Array<Promise<void>> = [];
|
||||
let promises: Array<Promise<void>> = [];
|
||||
|
||||
var result: { [key: string ]: string } = shallowCopy(object);
|
||||
let result: { [key: string ]: string } = shallowCopy(object);
|
||||
|
||||
keys.forEach(function(key) {
|
||||
if (result[key] == null) { return; }
|
||||
@@ -1062,8 +1114,8 @@ export class BaseProvider extends Provider {
|
||||
}
|
||||
|
||||
// keccak256('resolver(bytes32)')
|
||||
var data = '0x0178b8bf' + namehash(name).substring(2);
|
||||
var transaction = { to: network.ensAddress, data: data };
|
||||
let data = '0x0178b8bf' + namehash(name).substring(2);
|
||||
let transaction = { to: network.ensAddress, data: data };
|
||||
|
||||
return this.call(transaction).then((data) => {
|
||||
|
||||
@@ -1088,22 +1140,22 @@ export class BaseProvider extends Provider {
|
||||
return Promise.resolve(getAddress(name));
|
||||
} catch (error) { }
|
||||
|
||||
var self = this;
|
||||
let self = this;
|
||||
|
||||
var nodeHash = namehash(name);
|
||||
let nodeHash = namehash(name);
|
||||
|
||||
// Get the addr from the resovler
|
||||
return this._getResolver(name).then(function(resolverAddress) {
|
||||
|
||||
// keccak256('addr(bytes32)')
|
||||
var data = '0x3b3b57de' + nodeHash.substring(2);
|
||||
var transaction = { to: resolverAddress, data: data };
|
||||
let data = '0x3b3b57de' + nodeHash.substring(2);
|
||||
let transaction = { to: resolverAddress, data: data };
|
||||
return self.call(transaction);
|
||||
|
||||
// extract the address from the data
|
||||
}).then(function(data) {
|
||||
if (hexDataLength(data) !== 32) { return null; }
|
||||
var address = getAddress(hexDataSlice(data, 12));
|
||||
let address = getAddress(hexDataSlice(data, 12));
|
||||
if (address === '0x0000000000000000000000000000000000000000') { return null; }
|
||||
return address;
|
||||
});
|
||||
@@ -1118,17 +1170,17 @@ export class BaseProvider extends Provider {
|
||||
|
||||
address = getAddress(address);
|
||||
|
||||
var name = address.substring(2) + '.addr.reverse'
|
||||
var nodehash = namehash(name);
|
||||
let name = address.substring(2) + '.addr.reverse'
|
||||
let nodehash = namehash(name);
|
||||
|
||||
var self = this;
|
||||
let self = this;
|
||||
|
||||
return this._getResolver(name).then(function(resolverAddress) {
|
||||
if (!resolverAddress) { return null; }
|
||||
|
||||
// keccak('name(bytes32)')
|
||||
var data = '0x691f3431' + nodehash.substring(2);
|
||||
var transaction = { to: resolverAddress, data: data };
|
||||
let data = '0x691f3431' + nodehash.substring(2);
|
||||
let transaction = { to: resolverAddress, data: data };
|
||||
return self.call(transaction);
|
||||
|
||||
}).then(function(data) {
|
||||
@@ -1140,12 +1192,12 @@ export class BaseProvider extends Provider {
|
||||
data = data.substring(64);
|
||||
|
||||
if (data.length < 64) { return null; }
|
||||
var length = bigNumberify('0x' + data.substring(0, 64)).toNumber();
|
||||
let length = bigNumberify('0x' + data.substring(0, 64)).toNumber();
|
||||
data = data.substring(64);
|
||||
|
||||
if (2 * length > data.length) { return null; }
|
||||
|
||||
var name = toUtf8String('0x' + data.substring(0, 2 * length));
|
||||
let name = toUtf8String('0x' + data.substring(0, 2 * length));
|
||||
|
||||
// Make sure the reverse record matches the foward record
|
||||
return self.resolveName(name).then(function(addr) {
|
||||
@@ -1212,6 +1264,8 @@ export class BaseProvider extends Provider {
|
||||
return !(event.once);
|
||||
});
|
||||
|
||||
if (this.listenerCount() === 0) { this.polling = false; }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1261,6 +1315,7 @@ export class BaseProvider extends Provider {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
defineReadOnly(Provider, 'inherits', inheritable(Provider));
|
||||
|
||||
@@ -108,50 +108,60 @@ export class EtherscanProvider extends BaseProvider{
|
||||
|
||||
|
||||
perform(method: string, params: any) {
|
||||
//if (!params) { params = {}; }
|
||||
|
||||
var url = this.baseUrl;
|
||||
let url = this.baseUrl;
|
||||
|
||||
let apiKey = '';
|
||||
if (this.apiKey) { apiKey += '&apikey=' + this.apiKey; }
|
||||
|
||||
let get = (url: string, procFunc?: (value: any) => any) => {
|
||||
return fetchJson(url, null, procFunc || getJsonResult).then((result) => {
|
||||
this.emit('debug', {
|
||||
action: 'perform',
|
||||
request: url,
|
||||
response: result,
|
||||
provider: this
|
||||
});
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
switch (method) {
|
||||
case 'getBlockNumber':
|
||||
url += '/api?module=proxy&action=eth_blockNumber' + apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
|
||||
case 'getGasPrice':
|
||||
url += '/api?module=proxy&action=eth_gasPrice' + apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
|
||||
case 'getBalance':
|
||||
// Returns base-10 result
|
||||
url += '/api?module=account&action=balance&address=' + params.address;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return fetchJson(url, null, getResult);
|
||||
return get(url, getResult);
|
||||
|
||||
case 'getTransactionCount':
|
||||
url += '/api?module=proxy&action=eth_getTransactionCount&address=' + params.address;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
|
||||
|
||||
case 'getCode':
|
||||
url += '/api?module=proxy&action=eth_getCode&address=' + params.address;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url, getJsonResult);
|
||||
|
||||
case 'getStorageAt':
|
||||
url += '/api?module=proxy&action=eth_getStorageAt&address=' + params.address;
|
||||
url += '&position=' + params.position;
|
||||
url += '&tag=' + params.blockTag + apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url, getJsonResult);
|
||||
|
||||
|
||||
case 'sendTransaction':
|
||||
url += '/api?module=proxy&action=eth_sendRawTransaction&hex=' + params.signedTransaction;
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult).catch((error) => {
|
||||
return get(url).catch((error) => {
|
||||
if (error.responseText) {
|
||||
// "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 21464000000000 and got: 0"
|
||||
if (error.responseText.toLowerCase().indexOf('insufficient funds') >= 0) {
|
||||
@@ -178,34 +188,40 @@ export class EtherscanProvider extends BaseProvider{
|
||||
url += '&boolean=false';
|
||||
}
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
}
|
||||
throw new Error('getBlock by blockHash not implmeneted');
|
||||
|
||||
case 'getTransaction':
|
||||
url += '/api?module=proxy&action=eth_getTransactionByHash&txhash=' + params.transactionHash;
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
|
||||
case 'getTransactionReceipt':
|
||||
url += '/api?module=proxy&action=eth_getTransactionReceipt&txhash=' + params.transactionHash;
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
|
||||
|
||||
case 'call':
|
||||
var transaction = getTransactionString(params.transaction);
|
||||
case 'call': {
|
||||
let transaction = getTransactionString(params.transaction);
|
||||
if (transaction) { transaction = '&' + transaction; }
|
||||
url += '/api?module=proxy&action=eth_call' + transaction;
|
||||
//url += '&tag=' + params.blockTag + apiKey;
|
||||
if (params.blockTag !== 'latest') {
|
||||
throw new Error('EtherscanProvider does not support blockTag for call');
|
||||
}
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
}
|
||||
|
||||
case 'estimateGas':
|
||||
var transaction = getTransactionString(params.transaction);
|
||||
case 'estimateGas': {
|
||||
let transaction = getTransactionString(params.transaction);
|
||||
if (transaction) { transaction = '&' + transaction; }
|
||||
url += '/api?module=proxy&action=eth_estimateGas&' + transaction;
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getJsonResult);
|
||||
return get(url);
|
||||
}
|
||||
|
||||
case 'getLogs':
|
||||
url += '/api?module=logs&action=getLogs';
|
||||
@@ -227,7 +243,7 @@ export class EtherscanProvider extends BaseProvider{
|
||||
if (params.filter.topics.length > 1) {
|
||||
throw new Error('unsupported topic format');
|
||||
}
|
||||
var topic0 = params.filter.topics[0];
|
||||
let topic0 = params.filter.topics[0];
|
||||
if (typeof(topic0) !== 'string' || topic0.length !== 66) {
|
||||
throw new Error('unsupported topic0 format');
|
||||
}
|
||||
@@ -240,7 +256,7 @@ export class EtherscanProvider extends BaseProvider{
|
||||
url += apiKey;
|
||||
|
||||
var self = this;
|
||||
return fetchJson(url, null, getResult).then(function(logs: Array<any>) {
|
||||
return get(url, getResult).then(function(logs: Array<any>) {
|
||||
var txs: { [hash: string]: string } = {};
|
||||
|
||||
var seq = Promise.resolve();
|
||||
@@ -268,7 +284,7 @@ export class EtherscanProvider extends BaseProvider{
|
||||
if (this.network.name !== 'homestead') { return Promise.resolve(0.0); }
|
||||
url += '/api?module=stats&action=ethprice';
|
||||
url += apiKey;
|
||||
return fetchJson(url, null, getResult).then(function(result) {
|
||||
return get(url, getResult).then(function(result) {
|
||||
return parseFloat(result.ethusd);
|
||||
});
|
||||
|
||||
@@ -297,6 +313,12 @@ export class EtherscanProvider extends BaseProvider{
|
||||
url += '&sort=asc' + apiKey;
|
||||
|
||||
return fetchJson(url, null, getResult).then((result: Array<any>) => {
|
||||
this.emit('debug', {
|
||||
action: 'getHistory',
|
||||
request: url,
|
||||
response: result,
|
||||
provider: this
|
||||
});
|
||||
var output: Array<TransactionResponse> = [];
|
||||
result.forEach((tx) => {
|
||||
['contractAddress', 'to'].forEach(function(key) {
|
||||
|
||||
@@ -32,7 +32,8 @@ function checkNetworks(networks: Array<Network>): boolean {
|
||||
// Matches!
|
||||
if (check.name === network.name &&
|
||||
check.chainId === network.chainId &&
|
||||
check.ensAddress === network.ensAddress) { return; }
|
||||
((check.ensAddress === network.ensAddress) ||
|
||||
(check.ensAddress == null && network.ensAddress == null))) { return; }
|
||||
|
||||
errors.throwError(
|
||||
'provider mismatch',
|
||||
|
||||
@@ -6,11 +6,14 @@ import { BaseProvider } from './base-provider';
|
||||
|
||||
import { Signer } from '../abstract-signer';
|
||||
|
||||
import * as errors from '../errors';
|
||||
|
||||
import { getAddress } from '../utils/address';
|
||||
import { BigNumber } from '../utils/bignumber';
|
||||
import { hexlify, hexStripZeros } from '../utils/bytes';
|
||||
import { getNetwork } from '../utils/networks';
|
||||
import { defineReadOnly, resolveProperties, shallowCopy } from '../utils/properties';
|
||||
import { checkProperties, defineReadOnly, shallowCopy } from '../utils/properties';
|
||||
import { populateTransaction } from '../utils/transaction';
|
||||
import { toUtf8Bytes } from '../utils/utf8';
|
||||
import { fetchJson, poll } from '../utils/web';
|
||||
|
||||
@@ -18,9 +21,8 @@ import { fetchJson, poll } from '../utils/web';
|
||||
import { Arrayish } from '../utils/bytes';
|
||||
import { Network, Networkish } from '../utils/networks';
|
||||
import { ConnectionInfo } from '../utils/web';
|
||||
import { BlockTag, TransactionRequest, TransactionResponse } from '../providers/abstract-provider';
|
||||
|
||||
import * as errors from '../errors';
|
||||
import { BlockTag, TransactionRequest, TransactionResponse } from '../providers/abstract-provider';
|
||||
|
||||
function timer(timeout: number): Promise<any> {
|
||||
return new Promise(function(resolve) {
|
||||
@@ -78,15 +80,6 @@ export class JsonRpcSigner extends Signer {
|
||||
}
|
||||
}
|
||||
|
||||
/* May add back in the future; for now it is considered confusing. :)
|
||||
get address(): string {
|
||||
if (!this._address) {
|
||||
errors.throwError('no sync sync address available; use getAddress', errors.UNSUPPORTED_OPERATION, { operation: 'address' });
|
||||
}
|
||||
return this._address
|
||||
}
|
||||
*/
|
||||
|
||||
getAddress(): Promise<string> {
|
||||
if (this._address) {
|
||||
return Promise.resolve(this._address);
|
||||
@@ -110,21 +103,18 @@ export class JsonRpcSigner extends Signer {
|
||||
}
|
||||
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
|
||||
let tx: TransactionRequest = shallowCopy(transaction);
|
||||
|
||||
if (tx.from == null) {
|
||||
tx.from = this.getAddress().then((address) => {
|
||||
if (!address) { return null; }
|
||||
return address.toLowerCase();
|
||||
});
|
||||
}
|
||||
// Once populateTransaction resolves, the from address will be populated from getAddress
|
||||
let from: string = null;
|
||||
let getAddress = this.getAddress().then((address) => {
|
||||
if (address) { from = address.toLowerCase(); }
|
||||
return from;
|
||||
});
|
||||
|
||||
if (transaction.gasLimit == null) {
|
||||
tx.gasLimit = this.provider.estimateGas(tx);
|
||||
}
|
||||
|
||||
return resolveProperties(tx).then((tx) => {
|
||||
return this.provider.send('eth_sendTransaction', [ JsonRpcProvider.hexlifyTransaction(tx) ]).then((hash) => {
|
||||
return populateTransaction(transaction, this.provider, getAddress).then((tx) => {
|
||||
let hexTx = JsonRpcProvider.hexlifyTransaction(tx);
|
||||
hexTx.from = from;
|
||||
return this.provider.send('eth_sendTransaction', [ hexTx ]).then((hash) => {
|
||||
return poll(() => {
|
||||
return this.provider.getTransaction(hash).then((tx: TransactionResponse) => {
|
||||
if (tx === null) { return undefined; }
|
||||
@@ -176,6 +166,10 @@ export class JsonRpcSigner extends Signer {
|
||||
}
|
||||
}
|
||||
|
||||
const allowedTransactionKeys: { [ key: string ]: boolean } = {
|
||||
chainId: true, data: true, gasLimit: true, gasPrice:true, nonce: true, to: true, value: true
|
||||
}
|
||||
|
||||
export class JsonRpcProvider extends BaseProvider {
|
||||
readonly connection: ConnectionInfo;
|
||||
|
||||
@@ -236,14 +230,22 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
}
|
||||
|
||||
send(method: string, params: any): Promise<any> {
|
||||
var request = {
|
||||
let request = {
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
jsonrpc: "2.0"
|
||||
};
|
||||
|
||||
return fetchJson(this.connection, JSON.stringify(request), getResult);
|
||||
return fetchJson(this.connection, JSON.stringify(request), getResult).then((result) => {
|
||||
this.emit('debug', {
|
||||
action: 'send',
|
||||
request: request,
|
||||
response: result,
|
||||
provider: this
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
perform(method: string, params: any): Promise<any> {
|
||||
@@ -300,10 +302,10 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
return this.send('eth_getTransactionReceipt', [ params.transactionHash ]);
|
||||
|
||||
case 'call':
|
||||
return this.send('eth_call', [ JsonRpcProvider.hexlifyTransaction(params.transaction), 'latest' ]);
|
||||
return this.send('eth_call', [ JsonRpcProvider.hexlifyTransaction(params.transaction, { from: true }), params.blockTag ]);
|
||||
|
||||
case 'estimateGas':
|
||||
return this.send('eth_estimateGas', [ JsonRpcProvider.hexlifyTransaction(params.transaction) ]);
|
||||
return this.send('eth_estimateGas', [ JsonRpcProvider.hexlifyTransaction(params.transaction, { from: true }) ]);
|
||||
|
||||
case 'getLogs':
|
||||
if (params.filter && params.filter.address != null) {
|
||||
@@ -333,6 +335,7 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
|
||||
var seq = Promise.resolve();
|
||||
hashes.forEach(function(hash) {
|
||||
// @TODO: This should be garbage collected at some point... How? When?
|
||||
self._emitted['t:' + hash.toLowerCase()] = 'pending';
|
||||
seq = seq.then(function() {
|
||||
return self.getTransaction(hash).then(function(tx) {
|
||||
@@ -369,11 +372,22 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
// - gasLimit => gas
|
||||
// - All values hexlified
|
||||
// - All numeric values zero-striped
|
||||
// @TODO: Not any, a dictionary of string to strings
|
||||
static hexlifyTransaction(transaction: TransactionRequest): any {
|
||||
var result: any = {};
|
||||
// NOTE: This allows a TransactionRequest, but all values should be resolved
|
||||
// before this is called
|
||||
static hexlifyTransaction(transaction: TransactionRequest, allowExtra?: { [key: string]: boolean }): { [key: string]: string } {
|
||||
|
||||
// Some nodes (INFURA ropsten; INFURA mainnet is fine) don't like extra zeros.
|
||||
// Check only allowed properties are given
|
||||
let allowed = shallowCopy(allowedTransactionKeys);
|
||||
if (allowExtra) {
|
||||
for (let key in allowExtra) {
|
||||
if (allowExtra[key]) { allowed[key] = true; }
|
||||
}
|
||||
}
|
||||
checkProperties(transaction, allowed);
|
||||
|
||||
let result: { [key: string]: string } = {};
|
||||
|
||||
// Some nodes (INFURA ropsten; INFURA mainnet is fine) don't like leading zeros.
|
||||
['gasLimit', 'gasPrice', 'nonce', 'value'].forEach(function(key) {
|
||||
if ((<any>transaction)[key] == null) { return; }
|
||||
let value = hexStripZeros(hexlify((<any>transaction)[key]));
|
||||
@@ -384,7 +398,7 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
['from', 'to', 'data'].forEach(function(key) {
|
||||
if ((<any>transaction)[key] == null) { return; }
|
||||
result[key] = hexlify((<any>transaction)[key]);
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -844,7 +844,7 @@ class CoderArray extends Coder {
|
||||
result = uint256Coder.encode(count);
|
||||
}
|
||||
|
||||
errors.checkArgumentCount(count, value.length, 'in coder array' + (this.localName? (" "+ this.localName): ""));
|
||||
errors.checkArgumentCount(count, value.length, ' in coder array' + (this.localName? (" "+ this.localName): ""));
|
||||
|
||||
var coders = [];
|
||||
for (var i = 0; i < value.length; i++) { coders.push(this.coder); }
|
||||
|
||||
@@ -19,7 +19,7 @@ import { toUtf8Bytes, UnicodeNormalizationForm } from './utf8';
|
||||
import { pbkdf2 } from './pbkdf2';
|
||||
import { computeHmac, SupportedAlgorithms } from './hmac';
|
||||
import { defineReadOnly, isType, setType } from './properties';
|
||||
import { KeyPair } from './secp256k1';
|
||||
import { computeAddress, KeyPair } from './secp256k1';
|
||||
import { sha256 } from './sha2';
|
||||
|
||||
const N = bigNumberify("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
||||
@@ -54,6 +54,8 @@ export class HDNode {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
|
||||
readonly address: string;
|
||||
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
|
||||
@@ -81,6 +83,8 @@ export class HDNode {
|
||||
defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
|
||||
defineReadOnly(this, 'address', computeAddress(this.publicKey));
|
||||
|
||||
defineReadOnly(this, 'chainCode', hexlify(chainCode));
|
||||
|
||||
defineReadOnly(this, 'index', index);
|
||||
@@ -197,6 +201,8 @@ export function mnemonicToSeed(mnemonic: string, password?: string): string {
|
||||
export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string {
|
||||
if (!wordlist) { wordlist = langEn; }
|
||||
|
||||
errors.checkNormalize();
|
||||
|
||||
var words = wordlist.split(mnemonic);
|
||||
if ((words.length % 3) !== 0) { throw new Error('invalid mnemonic'); }
|
||||
|
||||
|
||||
@@ -14,10 +14,11 @@ import { sha256 } from './sha2';
|
||||
import { keccak256 as solidityKeccak256, pack as solidityPack, sha256 as soliditySha256 } from './solidity';
|
||||
import { randomBytes } from './random-bytes';
|
||||
import { getNetwork } from './networks';
|
||||
import { deepCopy, defineReadOnly, resolveProperties, shallowCopy } from './properties';
|
||||
import { checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy } from './properties';
|
||||
import * as RLP from './rlp';
|
||||
import { computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage } from './secp256k1';
|
||||
import { SigningKey } from './signing-key';
|
||||
import { populateTransaction } from './transaction';
|
||||
import { parse as parseTransaction, serialize as serializeTransaction } from './transaction';
|
||||
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from './utf8';
|
||||
import { commify, formatEther, parseEther, formatUnits, parseUnits } from './units';
|
||||
@@ -60,6 +61,7 @@ export {
|
||||
fetchJson,
|
||||
getNetwork,
|
||||
|
||||
checkProperties,
|
||||
deepCopy,
|
||||
defineReadOnly,
|
||||
resolveProperties,
|
||||
@@ -122,6 +124,7 @@ export {
|
||||
joinSignature,
|
||||
|
||||
parseTransaction,
|
||||
populateTransaction,
|
||||
serializeTransaction,
|
||||
|
||||
getJsonWalletAddress,
|
||||
|
||||
@@ -103,7 +103,7 @@ class _DeployDescription extends Description implements DeployDescription {
|
||||
});
|
||||
}
|
||||
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in Interface constructor');
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in Interface constructor');
|
||||
|
||||
try {
|
||||
return (bytecode + defaultAbiCoder.encode(this.inputs, params).substring(2));
|
||||
@@ -132,7 +132,7 @@ class _FunctionDescription extends Description implements FunctionDescription {
|
||||
readonly gas: BigNumber;
|
||||
|
||||
encode(params: Array<any>): string {
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in interface function ' + this.name);
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in interface function ' + this.name);
|
||||
|
||||
try {
|
||||
return this.sighash + defaultAbiCoder.encode(this.inputs, params).substring(2);
|
||||
@@ -182,19 +182,21 @@ class _EventDescription extends Description implements EventDescription {
|
||||
|
||||
let topics: Array<string> = [];
|
||||
if (!this.anonymous) { topics.push(this.topic); }
|
||||
|
||||
params.forEach((arg, index) => {
|
||||
if (arg === null) {
|
||||
topics.push(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let param = this.inputs[index];
|
||||
|
||||
if (!param.indexed) {
|
||||
errors.throwError('cannot filter non-indexed parameters; must be null', errors.INVALID_ARGUMENT, { argument: (param.name || index), value: arg });
|
||||
if (arg != null) {
|
||||
errors.throwError('cannot filter non-indexed parameters; must be null', errors.INVALID_ARGUMENT, { argument: (param.name || index), value: arg });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (param.type === 'string') {
|
||||
if (arg == null) {
|
||||
topics.push(null);
|
||||
} else if (param.type === 'string') {
|
||||
topics.push(id(arg));
|
||||
} else if (param.type === 'bytes') {
|
||||
topics.push(keccak256(arg));
|
||||
|
||||
@@ -7,33 +7,69 @@ export type Network = {
|
||||
name: string,
|
||||
chainId: number,
|
||||
ensAddress?: string,
|
||||
_defaultProvider?: (providers: any) => any
|
||||
}
|
||||
|
||||
export type Networkish = Network | string | number;
|
||||
|
||||
function ethDefaultProvider(network: string): (providers: any) => any {
|
||||
return function(providers: any): any {
|
||||
let providerList: Array<any> = [];
|
||||
|
||||
if (providers.InfuraProvider) {
|
||||
providerList.push(new providers.InfuraProvider(network));
|
||||
}
|
||||
|
||||
if (providers.EtherscanProvider) {
|
||||
providerList.push(new providers.EtherscanProvider(network));
|
||||
}
|
||||
|
||||
if (providerList.length === 0) { return null; }
|
||||
|
||||
if (providers.FallbackProvider) {
|
||||
return new providers.FallbackProvider(providerList);;
|
||||
}
|
||||
|
||||
return providerList[0];
|
||||
}
|
||||
}
|
||||
|
||||
function etcDefaultProvider(url: string, network: string): (providers: any) => any {
|
||||
return function(providers: any): any {
|
||||
if (providers.JsonRpcProvider) {
|
||||
return new providers.JsonRpcProvider(url, network);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const homestead: Network = {
|
||||
chainId: 1,
|
||||
ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
name: "homestead"
|
||||
name: "homestead",
|
||||
_defaultProvider: ethDefaultProvider('homestead')
|
||||
};
|
||||
|
||||
const ropsten: Network = {
|
||||
chainId: 3,
|
||||
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
|
||||
name: "ropsten"
|
||||
name: "ropsten",
|
||||
_defaultProvider: ethDefaultProvider('ropsten')
|
||||
};
|
||||
|
||||
const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
|
||||
const networks: { [name: string]: Network } = {
|
||||
unspecified: {
|
||||
chainId: 0
|
||||
chainId: 0,
|
||||
name: 'unspecified'
|
||||
},
|
||||
|
||||
homestead: homestead,
|
||||
mainnet: homestead,
|
||||
|
||||
morden: {
|
||||
chainId: 2
|
||||
chainId: 2,
|
||||
name: 'morden'
|
||||
},
|
||||
|
||||
ropsten: ropsten,
|
||||
@@ -41,19 +77,27 @@ const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
|
||||
|
||||
rinkeby: {
|
||||
chainId: 4,
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A"
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A",
|
||||
name: 'rinkeby',
|
||||
_defaultProvider: ethDefaultProvider('rinkeby')
|
||||
},
|
||||
|
||||
kovan: {
|
||||
chainId: 42
|
||||
chainId: 42,
|
||||
name: 'kovan',
|
||||
_defaultProvider: ethDefaultProvider('kovan')
|
||||
},
|
||||
|
||||
classic: {
|
||||
chainId: 61
|
||||
chainId: 61,
|
||||
name: 'classic',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io', 'classic')
|
||||
},
|
||||
|
||||
classicTestnet: {
|
||||
chainId: 62
|
||||
chainId: 62,
|
||||
name: 'classicTestnet',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io/morden', 'classicTestnet')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,17 +108,18 @@ const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
|
||||
* and verifies a network is a valid Network..
|
||||
*/
|
||||
export function getNetwork(network: Networkish): Network {
|
||||
// No network (null) or unspecified (chainId = 0)
|
||||
if (!network) { return null; }
|
||||
// No network (null)
|
||||
if (network == null) { return null; }
|
||||
|
||||
if (typeof(network) === 'number') {
|
||||
for (var name in networks) {
|
||||
for (let name in networks) {
|
||||
let n = networks[name];
|
||||
if (n.chainId === network) {
|
||||
return {
|
||||
name: name,
|
||||
name: n.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: (n.ensAddress || null),
|
||||
_defaultProvider: (n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -89,9 +134,10 @@ export function getNetwork(network: Networkish): Network {
|
||||
let n = networks[network];
|
||||
if (n == null) { return null; }
|
||||
return {
|
||||
name: network,
|
||||
name: n.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: n.ensAddress,
|
||||
_defaultProvider: (n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -110,10 +156,11 @@ export function getNetwork(network: Networkish): Network {
|
||||
errors.throwError('network chainId mismatch', errors.INVALID_ARGUMENT, { arg: 'network', value: network });
|
||||
}
|
||||
|
||||
// Standard Network
|
||||
// Standard Network (allow overriding the ENS address)
|
||||
return {
|
||||
name: network.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: (network.ensAddress || n.ensAddress || null),
|
||||
_defaultProvider: (network._defaultProvider || n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import * as errors from '../errors';
|
||||
|
||||
export function defineReadOnly(object: any, name: string, value: any): void {
|
||||
Object.defineProperty(object, name, {
|
||||
enumerable: true,
|
||||
@@ -42,6 +44,25 @@ export function resolveProperties(object: any): Promise<any> {
|
||||
});
|
||||
}
|
||||
|
||||
export function checkProperties(object: any, properties: { [ name: string ]: boolean }): void {
|
||||
if (!object || typeof(object) !== 'object') {
|
||||
errors.throwError('invalid object', errors.INVALID_ARGUMENT, {
|
||||
argument: 'object',
|
||||
value: object
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(object).forEach((key) => {
|
||||
if (!properties[key]) {
|
||||
errors.throwError('invalid object key - ' + key, errors.INVALID_ARGUMENT, {
|
||||
argument: 'transaction',
|
||||
value: object,
|
||||
key: key
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function shallowCopy(object: any): any {
|
||||
let result: any = {};
|
||||
for (var key in object) { result[key] = object[key]; }
|
||||
|
||||
@@ -9,6 +9,7 @@ import { getAddress } from './address';
|
||||
import { BigNumber, bigNumberify } from './bignumber';
|
||||
import { arrayify, hexlify, hexZeroPad, splitSignature, stripZeros, } from './bytes';
|
||||
import { keccak256 } from './keccak256';
|
||||
import { checkProperties, resolveProperties, shallowCopy } from './properties';
|
||||
|
||||
import * as RLP from './rlp';
|
||||
|
||||
@@ -19,6 +20,8 @@ import * as RLP from './rlp';
|
||||
import { Arrayish, Signature } from './bytes';
|
||||
import { BigNumberish } from './bignumber';
|
||||
|
||||
import { Provider } from '../providers/abstract-provider';
|
||||
|
||||
///////////////////////////////
|
||||
// Exported Types
|
||||
|
||||
@@ -65,7 +68,7 @@ function handleNumber(value: string): BigNumber {
|
||||
return bigNumberify(value);
|
||||
}
|
||||
|
||||
var transactionFields = [
|
||||
const transactionFields = [
|
||||
{ name: 'nonce', maxLength: 32 },
|
||||
{ name: 'gasPrice', maxLength: 32 },
|
||||
{ name: 'gasLimit', maxLength: 32 },
|
||||
@@ -74,8 +77,14 @@ var transactionFields = [
|
||||
{ name: 'data' },
|
||||
];
|
||||
|
||||
const allowedTransactionKeys: { [ key: string ]: boolean } = {
|
||||
chainId: true, data: true, gasLimit: true, gasPrice:true, nonce: true, to: true, value: true
|
||||
}
|
||||
|
||||
export function serialize(transaction: UnsignedTransaction, signature?: Arrayish | Signature): string {
|
||||
var raw: Array<string | Uint8Array> = [];
|
||||
checkProperties(transaction, allowedTransactionKeys);
|
||||
|
||||
let raw: Array<string | Uint8Array> = [];
|
||||
|
||||
transactionFields.forEach(function(fieldInfo) {
|
||||
let value = (<any>transaction)[fieldInfo.name] || ([]);
|
||||
@@ -115,7 +124,7 @@ export function serialize(transaction: UnsignedTransaction, signature?: Arrayish
|
||||
let sig = splitSignature(signature);
|
||||
|
||||
// We pushed a chainId and null r, s on for hashing only; remove those
|
||||
var v = 27 + sig.recoveryParam
|
||||
let v = 27 + sig.recoveryParam
|
||||
if (raw.length === 9) {
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
@@ -171,7 +180,7 @@ export function parse(rawTransaction: Arrayish): Transaction {
|
||||
tx.chainId = Math.floor((tx.v - 35) / 2);
|
||||
if (tx.chainId < 0) { tx.chainId = 0; }
|
||||
|
||||
var recoveryParam = tx.v - 27;
|
||||
let recoveryParam = tx.v - 27;
|
||||
|
||||
let raw = transaction.slice(0, 6);
|
||||
|
||||
@@ -182,7 +191,7 @@ export function parse(rawTransaction: Arrayish): Transaction {
|
||||
recoveryParam -= tx.chainId * 2 + 8;
|
||||
}
|
||||
|
||||
var digest = keccak256(RLP.encode(raw));
|
||||
let digest = keccak256(RLP.encode(raw));
|
||||
try {
|
||||
tx.from = recoverAddress(digest, { r: hexlify(tx.r), s: hexlify(tx.s), recoveryParam: recoveryParam });
|
||||
} catch (error) {
|
||||
@@ -194,3 +203,41 @@ export function parse(rawTransaction: Arrayish): Transaction {
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
export function populateTransaction(transaction: any, provider: Provider, from: string | Promise<string>): Promise<Transaction> {
|
||||
|
||||
if (!Provider.isProvider(provider)) {
|
||||
errors.throwError('missing provider', errors.INVALID_ARGUMENT, {
|
||||
argument: 'provider',
|
||||
value: provider
|
||||
});
|
||||
}
|
||||
|
||||
checkProperties(transaction, allowedTransactionKeys);
|
||||
|
||||
let tx = shallowCopy(transaction);
|
||||
|
||||
if (tx.to != null) {
|
||||
tx.to = provider.resolveName(tx.to);
|
||||
}
|
||||
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = provider.getGasPrice();
|
||||
}
|
||||
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = provider.getTransactionCount(from);
|
||||
}
|
||||
|
||||
if (tx.gasLimit == null) {
|
||||
let estimate = shallowCopy(tx);
|
||||
estimate.from = from;
|
||||
tx.gasLimit = provider.estimateGas(estimate);
|
||||
}
|
||||
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = provider.getNetwork().then((network) => network.chainId);
|
||||
}
|
||||
|
||||
return resolveProperties(tx);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import { HashZero } from '../constants';
|
||||
|
||||
import { checkNormalize } from '../errors';
|
||||
import { arrayify, concat, hexlify } from './bytes';
|
||||
|
||||
///////////////////////////////
|
||||
@@ -23,6 +23,7 @@ export enum UnicodeNormalizationForm {
|
||||
export function toUtf8Bytes(str: string, form: UnicodeNormalizationForm = UnicodeNormalizationForm.current): Uint8Array {
|
||||
|
||||
if (form != UnicodeNormalizationForm.current) {
|
||||
checkNormalize();
|
||||
str = str.normalize(form);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { XMLHttpRequest } from 'xmlhttprequest';
|
||||
|
||||
import { encode as base64Encode } from './base64';
|
||||
import { shallowCopy } from './properties';
|
||||
import { toUtf8Bytes } from './utf8';
|
||||
|
||||
import * as errors from '../errors';
|
||||
@@ -180,6 +181,7 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
|
||||
|
||||
export function poll(func: () => Promise<any>, options?: PollOptions): Promise<any> {
|
||||
if (!options) { options = {}; }
|
||||
options = shallowCopy(options);
|
||||
if (options.floor == null) { options.floor = 0; }
|
||||
if (options.ceiling == null) { options.ceiling = 10000; }
|
||||
if (options.interval == null) { options.interval = 250; }
|
||||
|
||||
@@ -10,7 +10,7 @@ import { defineReadOnly, resolveProperties, shallowCopy } from './utils/properti
|
||||
import { randomBytes } from './utils/random-bytes';
|
||||
import * as secretStorage from './utils/secret-storage';
|
||||
import { SigningKey } from './utils/signing-key';
|
||||
import { serialize as serializeTransaction } from './utils/transaction';
|
||||
import { populateTransaction, serialize as serializeTransaction } from './utils/transaction';
|
||||
import { Wordlist } from './utils/wordlist';
|
||||
|
||||
// Imported Abstracts
|
||||
@@ -24,7 +24,6 @@ import { BlockTag, TransactionRequest, TransactionResponse } from './providers/a
|
||||
|
||||
import * as errors from './errors';
|
||||
|
||||
|
||||
export class Wallet extends AbstractSigner {
|
||||
|
||||
readonly provider: Provider;
|
||||
@@ -72,7 +71,7 @@ export class Wallet extends AbstractSigner {
|
||||
return resolveProperties(transaction).then((tx) => {
|
||||
let rawTx = serializeTransaction(tx);
|
||||
let signature = this.signingKey.signDigest(keccak256(rawTx));
|
||||
return Promise.resolve(serializeTransaction(tx, signature));
|
||||
return serializeTransaction(tx, signature);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,36 +91,11 @@ export class Wallet extends AbstractSigner {
|
||||
}
|
||||
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
|
||||
if (!this.provider) { throw new Error('missing provider'); }
|
||||
|
||||
if (!transaction || typeof(transaction) !== 'object') {
|
||||
throw new Error('invalid transaction object');
|
||||
}
|
||||
|
||||
var tx = shallowCopy(transaction);
|
||||
|
||||
if (tx.to != null) {
|
||||
tx.to = this.provider.resolveName(tx.to);
|
||||
}
|
||||
|
||||
if (tx.gasLimit == null) {
|
||||
tx.from = this.getAddress();
|
||||
tx.gasLimit = this.provider.estimateGas(tx);
|
||||
}
|
||||
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = this.provider.getGasPrice();
|
||||
}
|
||||
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = this.getTransactionCount();
|
||||
}
|
||||
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = this.provider.getNetwork().then((network) => network.chainId);
|
||||
}
|
||||
|
||||
return this.provider.sendTransaction(this.sign(tx));
|
||||
return populateTransaction(transaction, this.provider, this.address).then((tx) => {
|
||||
return this.sign(tx).then((signedTransaction) => {
|
||||
return this.provider.sendTransaction(signedTransaction);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
encrypt(password: Arrayish | string, options?: any, progressCallback?: ProgressCallback): Promise<string> {
|
||||
@@ -165,7 +139,7 @@ export class Wallet extends AbstractSigner {
|
||||
return Wallet.fromMnemonic(mnemonic, options.path, options.locale);
|
||||
}
|
||||
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet> {
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback?: ProgressCallback): Promise<Wallet> {
|
||||
if (isCrowdsaleWallet(json)) {
|
||||
try {
|
||||
if (progressCallback) { progressCallback(0); }
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -132,9 +132,7 @@ class LangJa extends Wordlist {
|
||||
}
|
||||
|
||||
split(mnemonic: string): Array<string> {
|
||||
if (!mnemonic.normalize) {
|
||||
errors.throwError('Japanese is unsupported on this platform; missing String.prototype.normalize', errors.UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize' });
|
||||
}
|
||||
errors.checkNormalize();
|
||||
return mnemonic.split(/(?:\u3000| )+/g);
|
||||
}
|
||||
|
||||
|
||||
55
tests/local-tests.js
Normal file
55
tests/local-tests.js
Normal file
@@ -0,0 +1,55 @@
|
||||
// These are test cases that cannot be run on Travis CI, but running them locally can
|
||||
// help prevent certain bugs from getting committed.
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var ethers = require('..');
|
||||
|
||||
var wallet = new ethers.Wallet("0x0123456789012345678901234567890123456789012345678901234567890123");
|
||||
|
||||
describe("Local JSON-RPC", function() {
|
||||
|
||||
// https://github.com/ethers-io/ethers.js/issues/306
|
||||
it ("sends a transaction", function() {
|
||||
this.timeout(10000);
|
||||
|
||||
var provider = new ethers.providers.JsonRpcProvider();
|
||||
var signer = provider.getSigner(1);
|
||||
|
||||
return signer.sendTransaction({
|
||||
to: wallet.address,
|
||||
value: 1
|
||||
}).then(function(tx) {
|
||||
console.log(tx);
|
||||
return tx.wait().then(() => {
|
||||
console.log("Mined", provider);
|
||||
});
|
||||
}, function(error) {
|
||||
console.log(error);
|
||||
assert.ok(false, "throws an error");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("sends a wallet transactin", function() {
|
||||
this.timeout(10000);
|
||||
|
||||
var provider = new ethers.providers.JsonRpcProvider();
|
||||
var signer = wallet.connect(provider);
|
||||
|
||||
return signer.sendTransaction({
|
||||
to: provider.getSigner(1).getAddress(),
|
||||
value: 2
|
||||
}).then(function(tx) {
|
||||
console.log(tx);
|
||||
return tx.wait().then(() => {
|
||||
console.log("Mined");
|
||||
});
|
||||
}, function(error) {
|
||||
console.log(error);
|
||||
assert.ok(false, "throws an error");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
99
tests/shims/base64.js
Normal file
99
tests/shims/base64.js
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* See: https://github.com/MaxArt2501/base64-js
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 MaxArt2501
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], function() {factory(root);});
|
||||
} else factory(root);
|
||||
// node.js has always supported base64 conversions, while browsers that support
|
||||
// web workers support base64 too, but you may never know.
|
||||
})(typeof exports !== "undefined" ? exports : this, function(root) {
|
||||
if (root.atob) {
|
||||
// Some browsers' implementation of atob doesn't support whitespaces
|
||||
// in the encoded string (notably, IE). This wraps the native atob
|
||||
// in a function that strips the whitespaces.
|
||||
// The original function can be retrieved in atob.original
|
||||
try {
|
||||
root.atob(" ");
|
||||
} catch(e) {
|
||||
root.atob = (function(atob) {
|
||||
var func = function(string) {
|
||||
return atob(String(string).replace(/[\t\n\f\r ]+/g, ""));
|
||||
};
|
||||
func.original = atob;
|
||||
return func;
|
||||
})(root.atob);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// base64 character set, plus padding character (=)
|
||||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||
// Regular expression to check formal correctness of base64 encoded strings
|
||||
b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
||||
|
||||
root.btoa = function(string) {
|
||||
string = String(string);
|
||||
var bitmap, a, b, c,
|
||||
result = "", i = 0,
|
||||
rest = string.length % 3; // To determine the final padding
|
||||
|
||||
for (; i < string.length;) {
|
||||
if ((a = string.charCodeAt(i++)) > 255
|
||||
|| (b = string.charCodeAt(i++)) > 255
|
||||
|| (c = string.charCodeAt(i++)) > 255)
|
||||
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
||||
|
||||
bitmap = (a << 16) | (b << 8) | c;
|
||||
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63)
|
||||
+ b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
|
||||
}
|
||||
|
||||
// If there's need of padding, replace the last 'A's with equal signs
|
||||
return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
|
||||
};
|
||||
|
||||
root.atob = function(string) {
|
||||
// atob can work with strings with whitespaces, even inside the encoded part,
|
||||
// but only \t, \n, \f, \r and ' ', which can be stripped.
|
||||
string = String(string).replace(/[\t\n\f\r ]+/g, "");
|
||||
if (!b64re.test(string))
|
||||
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
||||
|
||||
// Adding the padding if missing, for semplicity
|
||||
string += "==".slice(2 - (string.length & 3));
|
||||
var bitmap, result = "", r1, r2, i = 0;
|
||||
for (; i < string.length;) {
|
||||
bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12
|
||||
| (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
|
||||
|
||||
result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255)
|
||||
: r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255)
|
||||
: String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
});
|
||||
73
tests/shims/index.js
Normal file
73
tests/shims/index.js
Normal file
@@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
var shims = [];
|
||||
|
||||
// Shim String.prototype.normalize
|
||||
try {
|
||||
var missing = [];
|
||||
|
||||
// Some platforms are missing certain normalization forms
|
||||
var forms = ["NFD", "NFC", "NFKD", "NFKC"];
|
||||
for (var i = 0; i < forms.length; i++) {
|
||||
try {
|
||||
"test".normalize(forms[i]);
|
||||
} catch(error) {
|
||||
missing.push(forms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.length) {
|
||||
shims.push("String.prototype.normalize (missing: " + missing.join(", ") + ")");
|
||||
throw new Error('bad normalize');
|
||||
}
|
||||
|
||||
// Some platforms have a native normalize, but it is broken; so we force our shim
|
||||
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
||||
shims.push("String.prototype.normalize (broken)");
|
||||
throw new Error('bad normalize');
|
||||
}
|
||||
} catch (error) {
|
||||
var unorm = require('./unorm.js');
|
||||
String.prototype.normalize = function(form) {
|
||||
var func = unorm[(form || 'NFC').toLowerCase()];
|
||||
if (!func) { throw new RangeError('invalid form - ' + form); }
|
||||
return func(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Shim atob and btoa
|
||||
var base64 = require('./base64.js');
|
||||
if (!global.atob) {
|
||||
shims.push("atob");
|
||||
global.atob = base64.atob;
|
||||
}
|
||||
if (!global.btoa) {
|
||||
shims.push("btoa");
|
||||
global.btoa = base64.btoa;
|
||||
}
|
||||
|
||||
// Shim Promise
|
||||
// @TODO: Check first?
|
||||
var promise = require('./es6-promise.auto.js');
|
||||
|
||||
// Shim ArrayBuffer.isView
|
||||
if (!ArrayBuffer.isView) {
|
||||
shims.push("ArrayBuffer.isView");
|
||||
ArrayBuffer.isView = function(obj) {
|
||||
// @TODO: This should probably check various instanceof aswell
|
||||
return !!(obj.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Shim nextTick
|
||||
if (!global.nextTick) {
|
||||
shims.push("nextTick");
|
||||
global.nextTick = function (callback) { setTimeout(callback, 0); }
|
||||
}
|
||||
|
||||
if (shims.length) {
|
||||
console.log("Shims Injected:");
|
||||
for (var i = 0; i < shims.length; i++) {
|
||||
console.log(' - ' + shims[i]);
|
||||
}
|
||||
}
|
||||
@@ -441,3 +441,72 @@ describe('Test Fixed Bytes Coder', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Filters', function() {
|
||||
// @TODO: Add a LOT more tests here
|
||||
function doTest(test) {
|
||||
it(test.name, function() {
|
||||
var iface = new ethers.utils.Interface([ test.signature ]);
|
||||
var eventDescription = iface.events[test.event];
|
||||
var filter = eventDescription.encodeTopics(test.args);
|
||||
assert.equal(filter.length, test.expected.length, 'filter length matches - ' + test.name);
|
||||
filter.forEach(function(expected, index) {
|
||||
assert.equal(expected, test.expected[index], 'signature topic matches - ' + index + ' - ' + test.name);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var Tests = [
|
||||
|
||||
// Skips null in non-indexed fields
|
||||
// See: https://github.com/ethers-io/ethers.js/issues/305
|
||||
{
|
||||
name: "creates correct filters for null non-indexed fields",
|
||||
|
||||
args: [ null, 2, null, null ],
|
||||
event: "LogSomething",
|
||||
signature: "event LogSomething(int hup, int indexed two, bool three, address indexed four)",
|
||||
|
||||
expected: [
|
||||
"0xf6b983969813047dce97b9ff8a48cfb0a13306eb2caae2ef186b280bc27491c8",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000002"
|
||||
]
|
||||
},
|
||||
|
||||
// https://etherscan.io/tx/0x820cc57bc77be44d8f4f024a18e18f64a8b6e62a82a3d7897db5970dbe181ba1
|
||||
{
|
||||
name: "transfer filtering from",
|
||||
|
||||
args: [
|
||||
"0x59DEa134510ebce4a0c7146595dc8A61Eb9D0D79"
|
||||
],
|
||||
event: "Transfer",
|
||||
signature: "event Transfer(address indexed from, address indexed to, uint value)",
|
||||
|
||||
expected: [
|
||||
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
||||
"0x00000000000000000000000059dea134510ebce4a0c7146595dc8a61eb9d0d79"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "transfer filtering to",
|
||||
|
||||
args: [
|
||||
null,
|
||||
"0x851b9167B7cbf772D38eFaf89705b35022880A07"
|
||||
],
|
||||
event: "Transfer",
|
||||
signature: "event Transfer(address indexed from, address indexed to, uint value)",
|
||||
|
||||
expected: [
|
||||
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
||||
null,
|
||||
"0x000000000000000000000000851b9167b7cbf772d38efaf89705b35022880a07"
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
Tests.forEach(function(test) {
|
||||
doTest(test);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,6 +22,8 @@ describe('Test HD Node Derivation', function(test) {
|
||||
var wallet = new ethers.Wallet(node.privateKey);
|
||||
assert.equal(wallet.address.toLowerCase(), nodeTest.address,
|
||||
'Generates address - ' + nodeTest.privateKey);
|
||||
|
||||
assert.equal(node.address, (new ethers.Wallet(node)).address, 'HDNode address matches - ' + nodeTest.privateKey);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -64,6 +66,8 @@ function testEasySeed(lang, locale) {
|
||||
}
|
||||
|
||||
testEasySeed(ethers.wordlists.en, 'en');
|
||||
testEasySeed(ethers.wordlists.es, 'es');
|
||||
testEasySeed(ethers.wordlists.fr, 'fr');
|
||||
testEasySeed(ethers.wordlists.ja, 'ja');
|
||||
testEasySeed(ethers.wordlists.zh_cn, 'zh_cn');
|
||||
testEasySeed(ethers.wordlists.zh_tw, 'zh_tw');
|
||||
|
||||
@@ -11,37 +11,7 @@
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
|
||||
<!--
|
||||
Shim for PhantomJS: Promise
|
||||
See: https://github.com/stefanpenner/es6-promise
|
||||
-->
|
||||
<script src="./dist/es6-promise.auto.js"></script>
|
||||
|
||||
<!--
|
||||
Shim for String.prototype.normalize
|
||||
See: https://github.com/walling/unorm
|
||||
-->
|
||||
<script src="./dist/unorm.js"></script>
|
||||
|
||||
<!--
|
||||
Shims for PhantomJS
|
||||
-->
|
||||
<script type="text/javascript">
|
||||
|
||||
// ArrayBuffer.isView
|
||||
if (!ArrayBuffer.isView) {
|
||||
ArrayBuffer.isView = function(obj) {
|
||||
// @TODO: This should probably check various instanceof aswell
|
||||
return !!(obj.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// nextTick
|
||||
if (!window.nextTick) {
|
||||
window.nextTick = function (callback) { setTimeout(callback, 0); }
|
||||
}
|
||||
</script>
|
||||
<script src="../dist/shims.js"></script>
|
||||
|
||||
<!-- Inject the mocha describe and it functions -->
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -733,7 +733,7 @@ var CoderArray = /** @class */ (function (_super) {
|
||||
count = value.length;
|
||||
result = uint256Coder.encode(count);
|
||||
}
|
||||
errors.checkArgumentCount(count, value.length, 'in coder array' + (this.localName ? (" " + this.localName) : ""));
|
||||
errors.checkArgumentCount(count, value.length, ' in coder array' + (this.localName ? (" " + this.localName) : ""));
|
||||
var coders = [];
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
coders.push(this.coder);
|
||||
|
||||
1
utils/hdnode.d.ts
vendored
1
utils/hdnode.d.ts
vendored
@@ -5,6 +5,7 @@ export declare class HDNode {
|
||||
private readonly keyPair;
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
readonly chainCode: string;
|
||||
|
||||
@@ -54,6 +54,7 @@ var HDNode = /** @class */ (function () {
|
||||
properties_1.defineReadOnly(this, 'keyPair', new secp256k1_1.KeyPair(privateKey));
|
||||
properties_1.defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
properties_1.defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
properties_1.defineReadOnly(this, 'address', secp256k1_1.computeAddress(this.publicKey));
|
||||
properties_1.defineReadOnly(this, 'chainCode', bytes_1.hexlify(chainCode));
|
||||
properties_1.defineReadOnly(this, 'index', index);
|
||||
properties_1.defineReadOnly(this, 'depth', depth);
|
||||
@@ -165,6 +166,7 @@ function mnemonicToEntropy(mnemonic, wordlist) {
|
||||
if (!wordlist) {
|
||||
wordlist = lang_en_1.langEn;
|
||||
}
|
||||
errors.checkNormalize();
|
||||
var words = wordlist.split(mnemonic);
|
||||
if ((words.length % 3) !== 0) {
|
||||
throw new Error('invalid mnemonic');
|
||||
|
||||
5
utils/index.d.ts
vendored
5
utils/index.d.ts
vendored
@@ -12,10 +12,11 @@ import { sha256 } from './sha2';
|
||||
import { keccak256 as solidityKeccak256, pack as solidityPack, sha256 as soliditySha256 } from './solidity';
|
||||
import { randomBytes } from './random-bytes';
|
||||
import { getNetwork } from './networks';
|
||||
import { deepCopy, defineReadOnly, resolveProperties, shallowCopy } from './properties';
|
||||
import { checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy } from './properties';
|
||||
import * as RLP from './rlp';
|
||||
import { computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage } from './secp256k1';
|
||||
import { SigningKey } from './signing-key';
|
||||
import { populateTransaction } from './transaction';
|
||||
import { parse as parseTransaction, serialize as serializeTransaction } from './transaction';
|
||||
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from './utf8';
|
||||
import { commify, formatEther, parseEther, formatUnits, parseUnits } from './units';
|
||||
@@ -31,4 +32,4 @@ import { Transaction, UnsignedTransaction } from './transaction';
|
||||
import { ConnectionInfo, OnceBlockable, PollOptions } from './web';
|
||||
import { EncryptOptions, ProgressCallback } from './secret-storage';
|
||||
import { Wordlist } from './wordlist';
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
|
||||
@@ -58,6 +58,7 @@ exports.randomBytes = random_bytes_1.randomBytes;
|
||||
var networks_1 = require("./networks");
|
||||
exports.getNetwork = networks_1.getNetwork;
|
||||
var properties_1 = require("./properties");
|
||||
exports.checkProperties = properties_1.checkProperties;
|
||||
exports.deepCopy = properties_1.deepCopy;
|
||||
exports.defineReadOnly = properties_1.defineReadOnly;
|
||||
exports.resolveProperties = properties_1.resolveProperties;
|
||||
@@ -73,8 +74,10 @@ exports.verifyMessage = secp256k1_1.verifyMessage;
|
||||
var signing_key_1 = require("./signing-key");
|
||||
exports.SigningKey = signing_key_1.SigningKey;
|
||||
var transaction_1 = require("./transaction");
|
||||
exports.parseTransaction = transaction_1.parse;
|
||||
exports.serializeTransaction = transaction_1.serialize;
|
||||
exports.populateTransaction = transaction_1.populateTransaction;
|
||||
var transaction_2 = require("./transaction");
|
||||
exports.parseTransaction = transaction_2.parse;
|
||||
exports.serializeTransaction = transaction_2.serialize;
|
||||
var utf8_1 = require("./utf8");
|
||||
exports.formatBytes32String = utf8_1.formatBytes32String;
|
||||
exports.parseBytes32String = utf8_1.parseBytes32String;
|
||||
|
||||
@@ -56,7 +56,7 @@ var _DeployDescription = /** @class */ (function (_super) {
|
||||
value: bytecode
|
||||
});
|
||||
}
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in Interface constructor');
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in Interface constructor');
|
||||
try {
|
||||
return (bytecode + abi_coder_1.defaultAbiCoder.encode(this.inputs, params).substring(2));
|
||||
}
|
||||
@@ -77,7 +77,7 @@ var _FunctionDescription = /** @class */ (function (_super) {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
_FunctionDescription.prototype.encode = function (params) {
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in interface function ' + this.name);
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in interface function ' + this.name);
|
||||
try {
|
||||
return this.sighash + abi_coder_1.defaultAbiCoder.encode(this.inputs, params).substring(2);
|
||||
}
|
||||
@@ -128,15 +128,17 @@ var _EventDescription = /** @class */ (function (_super) {
|
||||
topics.push(this.topic);
|
||||
}
|
||||
params.forEach(function (arg, index) {
|
||||
if (arg === null) {
|
||||
topics.push(null);
|
||||
return;
|
||||
}
|
||||
var param = _this.inputs[index];
|
||||
if (!param.indexed) {
|
||||
errors.throwError('cannot filter non-indexed parameters; must be null', errors.INVALID_ARGUMENT, { argument: (param.name || index), value: arg });
|
||||
if (arg != null) {
|
||||
errors.throwError('cannot filter non-indexed parameters; must be null', errors.INVALID_ARGUMENT, { argument: (param.name || index), value: arg });
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (param.type === 'string') {
|
||||
if (arg == null) {
|
||||
topics.push(null);
|
||||
}
|
||||
else if (param.type === 'string') {
|
||||
topics.push(hash_1.id(arg));
|
||||
}
|
||||
else if (param.type === 'bytes') {
|
||||
|
||||
1
utils/networks.d.ts
vendored
1
utils/networks.d.ts
vendored
@@ -2,6 +2,7 @@ export declare type Network = {
|
||||
name: string;
|
||||
chainId: number;
|
||||
ensAddress?: string;
|
||||
_defaultProvider?: (providers: any) => any;
|
||||
};
|
||||
export declare type Networkish = Network | string | number;
|
||||
/**
|
||||
|
||||
@@ -8,39 +8,78 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var errors = __importStar(require("../errors"));
|
||||
function ethDefaultProvider(network) {
|
||||
return function (providers) {
|
||||
var providerList = [];
|
||||
if (providers.InfuraProvider) {
|
||||
providerList.push(new providers.InfuraProvider(network));
|
||||
}
|
||||
if (providers.EtherscanProvider) {
|
||||
providerList.push(new providers.EtherscanProvider(network));
|
||||
}
|
||||
if (providerList.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (providers.FallbackProvider) {
|
||||
return new providers.FallbackProvider(providerList);
|
||||
;
|
||||
}
|
||||
return providerList[0];
|
||||
};
|
||||
}
|
||||
function etcDefaultProvider(url, network) {
|
||||
return function (providers) {
|
||||
if (providers.JsonRpcProvider) {
|
||||
return new providers.JsonRpcProvider(url, network);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
var homestead = {
|
||||
chainId: 1,
|
||||
ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
name: "homestead"
|
||||
name: "homestead",
|
||||
_defaultProvider: ethDefaultProvider('homestead')
|
||||
};
|
||||
var ropsten = {
|
||||
chainId: 3,
|
||||
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
|
||||
name: "ropsten"
|
||||
name: "ropsten",
|
||||
_defaultProvider: ethDefaultProvider('ropsten')
|
||||
};
|
||||
var networks = {
|
||||
unspecified: {
|
||||
chainId: 0
|
||||
chainId: 0,
|
||||
name: 'unspecified'
|
||||
},
|
||||
homestead: homestead,
|
||||
mainnet: homestead,
|
||||
morden: {
|
||||
chainId: 2
|
||||
chainId: 2,
|
||||
name: 'morden'
|
||||
},
|
||||
ropsten: ropsten,
|
||||
testnet: ropsten,
|
||||
rinkeby: {
|
||||
chainId: 4,
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A"
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A",
|
||||
name: 'rinkeby',
|
||||
_defaultProvider: ethDefaultProvider('rinkeby')
|
||||
},
|
||||
kovan: {
|
||||
chainId: 42
|
||||
chainId: 42,
|
||||
name: 'kovan',
|
||||
_defaultProvider: ethDefaultProvider('kovan')
|
||||
},
|
||||
classic: {
|
||||
chainId: 61
|
||||
chainId: 61,
|
||||
name: 'classic',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io', 'classic')
|
||||
},
|
||||
classicTestnet: {
|
||||
chainId: 62
|
||||
chainId: 62,
|
||||
name: 'classicTestnet',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io/morden', 'classicTestnet')
|
||||
}
|
||||
};
|
||||
/**
|
||||
@@ -50,18 +89,19 @@ var networks = {
|
||||
* and verifies a network is a valid Network..
|
||||
*/
|
||||
function getNetwork(network) {
|
||||
// No network (null) or unspecified (chainId = 0)
|
||||
if (!network) {
|
||||
// No network (null)
|
||||
if (network == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeof (network) === 'number') {
|
||||
for (var name in networks) {
|
||||
var n_1 = networks[name];
|
||||
for (var name_1 in networks) {
|
||||
var n_1 = networks[name_1];
|
||||
if (n_1.chainId === network) {
|
||||
return {
|
||||
name: name,
|
||||
name: n_1.name,
|
||||
chainId: n_1.chainId,
|
||||
ensAddress: n_1.ensAddress
|
||||
ensAddress: (n_1.ensAddress || null),
|
||||
_defaultProvider: (n_1._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -76,9 +116,10 @@ function getNetwork(network) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
name: network,
|
||||
name: n_2.name,
|
||||
chainId: n_2.chainId,
|
||||
ensAddress: n_2.ensAddress
|
||||
ensAddress: n_2.ensAddress,
|
||||
_defaultProvider: (n_2._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
var n = networks[network.name];
|
||||
@@ -93,11 +134,12 @@ function getNetwork(network) {
|
||||
if (network.chainId !== 0 && network.chainId !== n.chainId) {
|
||||
errors.throwError('network chainId mismatch', errors.INVALID_ARGUMENT, { arg: 'network', value: network });
|
||||
}
|
||||
// Standard Network
|
||||
// Standard Network (allow overriding the ENS address)
|
||||
return {
|
||||
name: network.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: (network.ensAddress || n.ensAddress || null),
|
||||
_defaultProvider: (network._defaultProvider || n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
exports.getNetwork = getNetwork;
|
||||
|
||||
3
utils/properties.d.ts
vendored
3
utils/properties.d.ts
vendored
@@ -2,6 +2,9 @@ export declare function defineReadOnly(object: any, name: string, value: any): v
|
||||
export declare function setType(object: any, type: string): void;
|
||||
export declare function isType(object: any, type: string): boolean;
|
||||
export declare function resolveProperties(object: any): Promise<any>;
|
||||
export declare function checkProperties(object: any, properties: {
|
||||
[name: string]: boolean;
|
||||
}): void;
|
||||
export declare function shallowCopy(object: any): any;
|
||||
export declare function deepCopy(object: any, frozen?: boolean): any;
|
||||
export declare function inheritable(parent: any): (child: any) => void;
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
'use strict';
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var errors = __importStar(require("../errors"));
|
||||
function defineReadOnly(object, name, value) {
|
||||
Object.defineProperty(object, name, {
|
||||
enumerable: true,
|
||||
@@ -38,6 +46,24 @@ function resolveProperties(object) {
|
||||
});
|
||||
}
|
||||
exports.resolveProperties = resolveProperties;
|
||||
function checkProperties(object, properties) {
|
||||
if (!object || typeof (object) !== 'object') {
|
||||
errors.throwError('invalid object', errors.INVALID_ARGUMENT, {
|
||||
argument: 'object',
|
||||
value: object
|
||||
});
|
||||
}
|
||||
Object.keys(object).forEach(function (key) {
|
||||
if (!properties[key]) {
|
||||
errors.throwError('invalid object key - ' + key, errors.INVALID_ARGUMENT, {
|
||||
argument: 'transaction',
|
||||
value: object,
|
||||
key: key
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.checkProperties = checkProperties;
|
||||
function shallowCopy(object) {
|
||||
var result = {};
|
||||
for (var key in object) {
|
||||
|
||||
2
utils/transaction.d.ts
vendored
2
utils/transaction.d.ts
vendored
@@ -1,6 +1,7 @@
|
||||
import { BigNumber } from './bignumber';
|
||||
import { Arrayish, Signature } from './bytes';
|
||||
import { BigNumberish } from './bignumber';
|
||||
import { Provider } from '../providers/abstract-provider';
|
||||
export declare type UnsignedTransaction = {
|
||||
to?: string;
|
||||
nonce?: number;
|
||||
@@ -26,3 +27,4 @@ export interface Transaction {
|
||||
}
|
||||
export declare function serialize(transaction: UnsignedTransaction, signature?: Arrayish | Signature): string;
|
||||
export declare function parse(rawTransaction: Arrayish): Transaction;
|
||||
export declare function populateTransaction(transaction: any, provider: Provider, from: string | Promise<string>): Promise<Transaction>;
|
||||
|
||||
@@ -14,7 +14,9 @@ var address_1 = require("./address");
|
||||
var bignumber_1 = require("./bignumber");
|
||||
var bytes_1 = require("./bytes");
|
||||
var keccak256_1 = require("./keccak256");
|
||||
var properties_1 = require("./properties");
|
||||
var RLP = __importStar(require("./rlp"));
|
||||
var abstract_provider_1 = require("../providers/abstract-provider");
|
||||
///////////////////////////////
|
||||
function handleAddress(value) {
|
||||
if (value === '0x') {
|
||||
@@ -36,7 +38,11 @@ var transactionFields = [
|
||||
{ name: 'value', maxLength: 32 },
|
||||
{ name: 'data' },
|
||||
];
|
||||
var allowedTransactionKeys = {
|
||||
chainId: true, data: true, gasLimit: true, gasPrice: true, nonce: true, to: true, value: true
|
||||
};
|
||||
function serialize(transaction, signature) {
|
||||
properties_1.checkProperties(transaction, allowedTransactionKeys);
|
||||
var raw = [];
|
||||
transactionFields.forEach(function (fieldInfo) {
|
||||
var value = transaction[fieldInfo.name] || ([]);
|
||||
@@ -139,3 +145,32 @@ function parse(rawTransaction) {
|
||||
return tx;
|
||||
}
|
||||
exports.parse = parse;
|
||||
function populateTransaction(transaction, provider, from) {
|
||||
if (!abstract_provider_1.Provider.isProvider(provider)) {
|
||||
errors.throwError('missing provider', errors.INVALID_ARGUMENT, {
|
||||
argument: 'provider',
|
||||
value: provider
|
||||
});
|
||||
}
|
||||
properties_1.checkProperties(transaction, allowedTransactionKeys);
|
||||
var tx = properties_1.shallowCopy(transaction);
|
||||
if (tx.to != null) {
|
||||
tx.to = provider.resolveName(tx.to);
|
||||
}
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = provider.getGasPrice();
|
||||
}
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = provider.getTransactionCount(from);
|
||||
}
|
||||
if (tx.gasLimit == null) {
|
||||
var estimate = properties_1.shallowCopy(tx);
|
||||
estimate.from = from;
|
||||
tx.gasLimit = provider.estimateGas(estimate);
|
||||
}
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = provider.getNetwork().then(function (network) { return network.chainId; });
|
||||
}
|
||||
return properties_1.resolveProperties(tx);
|
||||
}
|
||||
exports.populateTransaction = populateTransaction;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var constants_1 = require("../constants");
|
||||
var errors_1 = require("../errors");
|
||||
var bytes_1 = require("./bytes");
|
||||
///////////////////////////////
|
||||
var UnicodeNormalizationForm;
|
||||
@@ -16,6 +17,7 @@ var UnicodeNormalizationForm;
|
||||
function toUtf8Bytes(str, form) {
|
||||
if (form === void 0) { form = UnicodeNormalizationForm.current; }
|
||||
if (form != UnicodeNormalizationForm.current) {
|
||||
errors_1.checkNormalize();
|
||||
str = str.normalize(form);
|
||||
}
|
||||
var result = [];
|
||||
|
||||
@@ -9,6 +9,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var xmlhttprequest_1 = require("xmlhttprequest");
|
||||
var base64_1 = require("./base64");
|
||||
var properties_1 = require("./properties");
|
||||
var utf8_1 = require("./utf8");
|
||||
var errors = __importStar(require("../errors"));
|
||||
function fetchJson(connection, json, processFunc) {
|
||||
@@ -82,6 +83,9 @@ function fetchJson(connection, json, processFunc) {
|
||||
// @TODO: not any!
|
||||
var error = new Error('invalid response - ' + request.status);
|
||||
error.statusCode = request.status;
|
||||
if (request.responseText) {
|
||||
error.responseText = request.responseText;
|
||||
}
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
@@ -141,6 +145,7 @@ function poll(func, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options = properties_1.shallowCopy(options);
|
||||
if (options.floor == null) {
|
||||
options.floor = 0;
|
||||
}
|
||||
|
||||
2
wallet.d.ts
vendored
2
wallet.d.ts
vendored
@@ -30,6 +30,6 @@ export declare class Wallet extends AbstractSigner {
|
||||
* Static methods to create Wallet instances.
|
||||
*/
|
||||
static createRandom(options?: any): Wallet;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
static fromEncryptedJson(json: string, password: Arrayish, progressCallback?: ProgressCallback): Promise<Wallet>;
|
||||
static fromMnemonic(mnemonic: string, path?: string, wordlist?: Wordlist): Wallet;
|
||||
}
|
||||
|
||||
32
wallet.js
32
wallet.js
@@ -83,7 +83,7 @@ var Wallet = /** @class */ (function (_super) {
|
||||
return properties_1.resolveProperties(transaction).then(function (tx) {
|
||||
var rawTx = transaction_1.serialize(tx);
|
||||
var signature = _this.signingKey.signDigest(keccak256_1.keccak256(rawTx));
|
||||
return Promise.resolve(transaction_1.serialize(tx, signature));
|
||||
return transaction_1.serialize(tx, signature);
|
||||
});
|
||||
};
|
||||
Wallet.prototype.signMessage = function (message) {
|
||||
@@ -102,30 +102,12 @@ var Wallet = /** @class */ (function (_super) {
|
||||
return this.provider.getTransactionCount(this.address, blockTag);
|
||||
};
|
||||
Wallet.prototype.sendTransaction = function (transaction) {
|
||||
if (!this.provider) {
|
||||
throw new Error('missing provider');
|
||||
}
|
||||
if (!transaction || typeof (transaction) !== 'object') {
|
||||
throw new Error('invalid transaction object');
|
||||
}
|
||||
var tx = properties_1.shallowCopy(transaction);
|
||||
if (tx.to != null) {
|
||||
tx.to = this.provider.resolveName(tx.to);
|
||||
}
|
||||
if (tx.gasLimit == null) {
|
||||
tx.from = this.getAddress();
|
||||
tx.gasLimit = this.provider.estimateGas(tx);
|
||||
}
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = this.provider.getGasPrice();
|
||||
}
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = this.getTransactionCount();
|
||||
}
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = this.provider.getNetwork().then(function (network) { return network.chainId; });
|
||||
}
|
||||
return this.provider.sendTransaction(this.sign(tx));
|
||||
var _this = this;
|
||||
return transaction_1.populateTransaction(transaction, this.provider, this.address).then(function (tx) {
|
||||
return _this.sign(tx).then(function (signedTransaction) {
|
||||
return _this.provider.sendTransaction(signedTransaction);
|
||||
});
|
||||
});
|
||||
};
|
||||
Wallet.prototype.encrypt = function (password, options, progressCallback) {
|
||||
if (typeof (options) === 'function' && !progressCallback) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -131,9 +131,7 @@ var LangJa = /** @class */ (function (_super) {
|
||||
return wordlist.indexOf(word);
|
||||
};
|
||||
LangJa.prototype.split = function (mnemonic) {
|
||||
if (!mnemonic.normalize) {
|
||||
errors.throwError('Japanese is unsupported on this platform; missing String.prototype.normalize', errors.UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize' });
|
||||
}
|
||||
errors.checkNormalize();
|
||||
return mnemonic.split(/(?:\u3000| )+/g);
|
||||
};
|
||||
LangJa.prototype.join = function (words) {
|
||||
|
||||
Reference in New Issue
Block a user