Refectoring; split getAddress, expose transactions, hex operations.
This commit is contained in:
parent
efbfed0d40
commit
af893e79a4
479
dist/ethers.d.ts
vendored
479
dist/ethers.d.ts
vendored
@ -1,3 +1,16 @@
|
||||
declare module "utils/keccak256" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export function keccak256(data: Arrayish): string;
|
||||
}
|
||||
declare module "utils/properties" {
|
||||
export function defineReadOnly(object: any, name: any, value: any): void;
|
||||
export function defineFrozen(object: any, name: any, value: any): void;
|
||||
export type DeferredSetter = (value: any) => void;
|
||||
export function defineDeferredReadOnly(object: any, name: any, value: any): DeferredSetter;
|
||||
export function resolveProperties(object: any): Promise<any>;
|
||||
export function shallowCopy(object: any): any;
|
||||
export function jsonCopy(object: any): any;
|
||||
}
|
||||
declare module "utils/errors" {
|
||||
export const UNKNOWN_ERROR = "UNKNOWN_ERROR";
|
||||
export const NOT_IMPLEMENTED = "NOT_IMPLEMENTED";
|
||||
@ -11,18 +24,36 @@ declare module "utils/errors" {
|
||||
export function throwError(message: string, code: string, params: any): never;
|
||||
export function checkNew(self: any, kind: any): void;
|
||||
}
|
||||
declare module "utils/secp256k1" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export const N: string;
|
||||
export interface Signature {
|
||||
r: string;
|
||||
s: string;
|
||||
recoveryParam: number;
|
||||
v?: number;
|
||||
}
|
||||
export class KeyPair {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly compressedPublicKey: string;
|
||||
readonly publicKeyBytes: Uint8Array;
|
||||
constructor(privateKey: Arrayish);
|
||||
sign(digest: Arrayish): Signature;
|
||||
}
|
||||
export function recoverPublicKey(digest: Arrayish, signature: Signature): string;
|
||||
export function computePublicKey(key: Arrayish, compressed?: boolean): string;
|
||||
export function recoverAddress(digest: Arrayish, signature: Signature): string;
|
||||
export function computeAddress(key: string): string;
|
||||
}
|
||||
declare module "utils/convert" {
|
||||
/**
|
||||
* Conversion Utilities
|
||||
*
|
||||
*/
|
||||
import { BigNumber } from "utils/bignumber";
|
||||
import { Signature } from "utils/secp256k1";
|
||||
export type Arrayish = string | ArrayLike<number>;
|
||||
export type Signature = {
|
||||
r: string;
|
||||
s: string;
|
||||
v: number;
|
||||
};
|
||||
export function isArrayish(value: any): boolean;
|
||||
export function arrayify(value: Arrayish | BigNumber): Uint8Array;
|
||||
export function concat(objects: Array<Arrayish>): Uint8Array;
|
||||
@ -30,23 +61,17 @@ declare module "utils/convert" {
|
||||
export function padZeros(value: Arrayish, length: number): Uint8Array;
|
||||
export function isHexString(value: any, length?: number): boolean;
|
||||
export function hexlify(value: Arrayish | BigNumber | number): string;
|
||||
export function hexDataLength(data: string): number;
|
||||
export function hexDataSlice(data: string, offset: number, length?: number): string;
|
||||
export function hexStripZeros(value: string): string;
|
||||
export function hexZeroPad(value: string, length: number): string;
|
||||
export function splitSignature(signature: Arrayish): Signature;
|
||||
}
|
||||
declare module "utils/bignumber" {
|
||||
/**
|
||||
* BigNumber
|
||||
*
|
||||
* A wrapper around the BN.js object. We use the BN.js library
|
||||
* because it is used by elliptic, so it is required regardles.
|
||||
*
|
||||
*/
|
||||
import _BN from 'bn.js';
|
||||
import { Arrayish } from "utils/convert";
|
||||
export type BigNumberish = BigNumber | string | number | Arrayish;
|
||||
export class BigNumber {
|
||||
readonly _bn: _BN.BN;
|
||||
private readonly _bn;
|
||||
constructor(value: BigNumberish);
|
||||
fromTwos(value: BigNumberish): BigNumber;
|
||||
toTwos(value: BigNumberish): BigNumber;
|
||||
@ -75,10 +100,6 @@ declare module "utils/bignumber" {
|
||||
export const ConstantTwo: BigNumber;
|
||||
export const ConstantWeiPerEther: BigNumber;
|
||||
}
|
||||
declare module "utils/keccak256" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export function keccak256(data: Arrayish): string;
|
||||
}
|
||||
declare module "utils/rlp" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export function encode(object: any): string;
|
||||
@ -87,7 +108,8 @@ declare module "utils/rlp" {
|
||||
declare module "utils/address" {
|
||||
import { BigNumber } from "utils/bignumber";
|
||||
import { Arrayish } from "utils/convert";
|
||||
export function getAddress(address: string, icapFormat?: boolean): string;
|
||||
export function getAddress(address: string): string;
|
||||
export function getIcapAddress(address: string): string;
|
||||
export function getContractAddress(transaction: {
|
||||
from: string;
|
||||
nonce: Arrayish | BigNumber | number;
|
||||
@ -105,15 +127,6 @@ declare module "utils/utf8" {
|
||||
export function toUtf8Bytes(str: string, form?: UnicodeNormalizationForm): Uint8Array;
|
||||
export function toUtf8String(bytes: Arrayish): string;
|
||||
}
|
||||
declare module "utils/properties" {
|
||||
export function defineReadOnly(object: any, name: any, value: any): void;
|
||||
export function defineFrozen(object: any, name: any, value: any): void;
|
||||
export type DeferredSetter = (value: any) => void;
|
||||
export function defineDeferredReadOnly(object: any, name: any, value: any): DeferredSetter;
|
||||
export function resolveProperties(object: any): Promise<any>;
|
||||
export function shallowCopy(object: any): any;
|
||||
export function jsonCopy(object: any): any;
|
||||
}
|
||||
declare module "utils/abi-coder" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export type CoerceFunc = (type: string, value: any) => any;
|
||||
@ -139,6 +152,7 @@ declare module "utils/abi-coder" {
|
||||
payable: boolean;
|
||||
stateMutability: string;
|
||||
};
|
||||
export function parseParamType(type: string): ParamType;
|
||||
export function parseSignature(fragment: string): EventFragment | FunctionFragment;
|
||||
export class AbiCoder {
|
||||
readonly coerceFunc: CoerceFunc;
|
||||
@ -151,15 +165,16 @@ declare module "utils/abi-coder" {
|
||||
declare module "contracts/interface" {
|
||||
import { ParamType } from "utils/abi-coder";
|
||||
import { BigNumber, BigNumberish } from "utils/bignumber";
|
||||
export class Indexed {
|
||||
readonly hash: string;
|
||||
constructor(value: string);
|
||||
}
|
||||
export class Description {
|
||||
readonly type: string;
|
||||
readonly inputs: Array<ParamType>;
|
||||
constructor(info: any);
|
||||
}
|
||||
export class Indexed {
|
||||
readonly type: string;
|
||||
readonly hash: string;
|
||||
constructor(value: string);
|
||||
}
|
||||
export class DeployDescription extends Description {
|
||||
readonly payable: boolean;
|
||||
encode(bytecode: string, params: Array<any>): string;
|
||||
@ -260,12 +275,44 @@ declare module "providers/networks" {
|
||||
*/
|
||||
export function getNetwork(network: Network | string | number): Network;
|
||||
}
|
||||
declare module "utils/transaction" {
|
||||
import { BigNumber, BigNumberish } from "utils/bignumber";
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { Signature } from "utils/secp256k1";
|
||||
export interface UnsignedTransaction {
|
||||
to?: string;
|
||||
nonce?: number;
|
||||
gasLimit?: BigNumberish;
|
||||
gasPrice?: BigNumberish;
|
||||
data?: Arrayish;
|
||||
value?: BigNumberish;
|
||||
chainId?: number;
|
||||
}
|
||||
export interface Transaction {
|
||||
hash?: string;
|
||||
to?: string;
|
||||
from?: string;
|
||||
nonce: number;
|
||||
gasLimit: BigNumber;
|
||||
gasPrice: BigNumber;
|
||||
data: string;
|
||||
value: BigNumber;
|
||||
chainId: number;
|
||||
r?: string;
|
||||
s?: string;
|
||||
v?: number;
|
||||
}
|
||||
export type SignDigestFunc = (digest: Arrayish) => Signature;
|
||||
export function sign(transaction: UnsignedTransaction, signDigest: SignDigestFunc): string;
|
||||
export function parse(rawTransaction: Arrayish): Transaction;
|
||||
}
|
||||
declare module "providers/provider" {
|
||||
import { BigNumber, BigNumberish } from "utils/bignumber";
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { Network } from "providers/networks";
|
||||
import { Transaction } from "utils/transaction";
|
||||
export type BlockTag = string | number;
|
||||
export type Block = {
|
||||
export interface Block {
|
||||
hash: string;
|
||||
parentHash: string;
|
||||
number: number;
|
||||
@ -277,7 +324,7 @@ declare module "providers/provider" {
|
||||
miner: string;
|
||||
extraData: string;
|
||||
transactions: Array<string>;
|
||||
};
|
||||
}
|
||||
export type TransactionRequest = {
|
||||
to?: string | Promise<string>;
|
||||
from?: string | Promise<string>;
|
||||
@ -288,25 +335,14 @@ declare module "providers/provider" {
|
||||
value?: BigNumberish | Promise<BigNumberish>;
|
||||
chainId?: number | Promise<number>;
|
||||
};
|
||||
export type TransactionResponse = {
|
||||
export interface TransactionResponse extends Transaction {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
hash: string;
|
||||
to?: string;
|
||||
from?: string;
|
||||
nonce?: number;
|
||||
gasLimit?: BigNumber;
|
||||
gasPrice?: BigNumber;
|
||||
data?: string;
|
||||
value: BigNumber;
|
||||
chainId?: number;
|
||||
r?: string;
|
||||
s?: string;
|
||||
v?: number;
|
||||
wait?: (timeout?: number) => Promise<TransactionResponse>;
|
||||
};
|
||||
export type TransactionReceipt = {
|
||||
from: string;
|
||||
wait: (timeout?: number) => Promise<TransactionResponse>;
|
||||
}
|
||||
export interface TransactionReceipt {
|
||||
contractAddress?: string;
|
||||
transactionIndex?: number;
|
||||
root?: string;
|
||||
@ -318,14 +354,14 @@ declare module "providers/provider" {
|
||||
blockNumber?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
status?: number;
|
||||
};
|
||||
}
|
||||
export type Filter = {
|
||||
fromBlock?: BlockTag;
|
||||
toBlock?: BlockTag;
|
||||
address?: string;
|
||||
topics?: Array<any>;
|
||||
};
|
||||
export type Log = {
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
transactionIndex?: number;
|
||||
@ -335,11 +371,10 @@ declare module "providers/provider" {
|
||||
topics?: Array<string>;
|
||||
transactionHash?: string;
|
||||
logIndex?: number;
|
||||
};
|
||||
}
|
||||
export function checkTransactionResponse(transaction: any): TransactionResponse;
|
||||
export class Provider {
|
||||
private _network;
|
||||
protected ready: Promise<Network>;
|
||||
private _events;
|
||||
protected _emitted: any;
|
||||
private _pollingInterval;
|
||||
@ -347,10 +382,15 @@ declare module "providers/provider" {
|
||||
private _lastBlockNumber;
|
||||
private _balances;
|
||||
/**
|
||||
* Sub-classing notes
|
||||
* - If the network is standard or fully specified, ready will resolve
|
||||
* - Otherwise, the sub-class must assign a Promise to ready
|
||||
* ready
|
||||
*
|
||||
* A Promise<Network> that resolves only once the provider is ready.
|
||||
*
|
||||
* Sub-classes that call the super with a network without a chainId
|
||||
* MUST set this. Standard named networks have a known chainId.
|
||||
*
|
||||
*/
|
||||
protected ready: Promise<Network>;
|
||||
constructor(network: string | Network);
|
||||
private _doPoll;
|
||||
resetEventsBlock(blockNumber: number): void;
|
||||
@ -366,7 +406,7 @@ declare module "providers/provider" {
|
||||
getTransactionCount(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<number>;
|
||||
getCode(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<string>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
call(transaction: TransactionRequest): Promise<string>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>): Promise<Block>;
|
||||
@ -391,22 +431,144 @@ declare module "providers/provider" {
|
||||
removeListener(eventName: any, listener: any): Provider;
|
||||
}
|
||||
}
|
||||
declare module "wallet/words" {
|
||||
export function getWord(index: number): string;
|
||||
export function getWordIndex(word: string): number;
|
||||
}
|
||||
declare module "utils/hmac" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
interface HashFunc {
|
||||
(): HashFunc;
|
||||
update(chunk: Uint8Array): HashFunc;
|
||||
digest(encoding: string): string;
|
||||
digest(): Uint8Array;
|
||||
}
|
||||
export interface HmacFunc extends HashFunc {
|
||||
(hashFunc: HashFunc, key: Arrayish): HmacFunc;
|
||||
}
|
||||
export function createSha256Hmac(key: Arrayish): HmacFunc;
|
||||
export function createSha512Hmac(key: Arrayish): HmacFunc;
|
||||
}
|
||||
declare module "utils/pbkdf2" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { HmacFunc } from "utils/hmac";
|
||||
export interface CreateHmacFunc {
|
||||
(key: Arrayish): HmacFunc;
|
||||
}
|
||||
export function pbkdf2(password: Arrayish, salt: Arrayish, iterations: number, keylen: number, createHmac: CreateHmacFunc): Uint8Array;
|
||||
}
|
||||
declare module "utils/sha2" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export function sha256(data: Arrayish): string;
|
||||
export function sha512(data: Arrayish): string;
|
||||
}
|
||||
declare module "wallet/hdnode" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { KeyPair } from "utils/secp256k1";
|
||||
export class HDNode {
|
||||
private readonly keyPair;
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
readonly chainCode: string;
|
||||
readonly index: number;
|
||||
readonly depth: number;
|
||||
constructor(keyPair: KeyPair, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string);
|
||||
private _derive;
|
||||
derivePath(path: string): HDNode;
|
||||
}
|
||||
export function fromMnemonic(mnemonic: string): HDNode;
|
||||
export function fromSeed(seed: Arrayish): HDNode;
|
||||
export function mnemonicToSeed(mnemonic: string, password?: string): string;
|
||||
export function mnemonicToEntropy(mnemonic: string): string;
|
||||
export function entropyToMnemonic(entropy: Arrayish): string;
|
||||
export function isValidMnemonic(mnemonic: string): boolean;
|
||||
}
|
||||
declare module "utils/random-bytes" {
|
||||
export function randomBytes(length: number): Uint8Array;
|
||||
}
|
||||
declare module "wallet/signing-key" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { HDNode } from "wallet/hdnode";
|
||||
import { Signature } from "utils/secp256k1";
|
||||
export class SigningKey {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
private readonly keyPair;
|
||||
constructor(privateKey: Arrayish | HDNode);
|
||||
signDigest(digest: Arrayish): Signature;
|
||||
}
|
||||
export function recoverAddress(digest: Arrayish, signature: Signature): string;
|
||||
export function computeAddress(key: string): string;
|
||||
}
|
||||
declare module "wallet/secret-storage" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { SigningKey } from "wallet/signing-key";
|
||||
export interface ProgressCallback {
|
||||
(percent: number): void;
|
||||
}
|
||||
export function isCrowdsaleWallet(json: string): boolean;
|
||||
export function isValidWallet(json: string): boolean;
|
||||
export function decryptCrowdsale(json: string, password: Arrayish | string): SigningKey;
|
||||
export function decrypt(json: string, password: any, progressCallback?: ProgressCallback): Promise<SigningKey>;
|
||||
export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish | string, options?: any, progressCallback?: ProgressCallback): Promise<string>;
|
||||
}
|
||||
declare module "wallet/wallet" {
|
||||
import { HDNode } from "wallet/hdnode";
|
||||
import { ProgressCallback } from "wallet/secret-storage";
|
||||
import { SigningKey } from "wallet/signing-key";
|
||||
import { BlockTag, Provider, TransactionRequest, TransactionResponse } from "providers/provider";
|
||||
import { BigNumber, BigNumberish } from "utils/bignumber";
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { UnsignedTransaction } from "utils/transaction";
|
||||
export interface Signer {
|
||||
address?: string;
|
||||
getAddress(): Promise<string>;
|
||||
sendTransaction(transaction: UnsignedTransaction): Promise<TransactionResponse>;
|
||||
provider: Provider;
|
||||
sign(transaction: UnsignedTransaction): string;
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getGasPrice(transaction?: TransactionRequest): Promise<BigNumber>;
|
||||
}
|
||||
export class Wallet implements Signer {
|
||||
readonly address: string;
|
||||
readonly privateKey: string;
|
||||
private mnemonic;
|
||||
private path;
|
||||
private readonly signingKey;
|
||||
provider: Provider;
|
||||
defaultGasLimit: number;
|
||||
constructor(privateKey: SigningKey | HDNode | Arrayish, provider?: Provider);
|
||||
sign(transaction: UnsignedTransaction): string;
|
||||
getAddress(): Promise<string>;
|
||||
getBalance(blockTag?: BlockTag): Promise<BigNumber>;
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse>;
|
||||
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse>;
|
||||
static hashMessage(message: Arrayish | string): string;
|
||||
signMessage(message: Arrayish | string): string;
|
||||
static verifyMessage(message: Arrayish | string, signature: string): string;
|
||||
encrypt(password: Arrayish | string, options: any, progressCallback: ProgressCallback): Promise<string>;
|
||||
static createRandom(options: any): Wallet;
|
||||
static isEncryptedWallet(json: string): boolean;
|
||||
static fromEncryptedWallet(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
static fromMnemonic(mnemonic: string, path?: string): Wallet;
|
||||
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
}
|
||||
}
|
||||
declare module "contracts/contract" {
|
||||
import { Interface } from "contracts/interface";
|
||||
import { Provider, TransactionResponse } from "providers/provider";
|
||||
import { Signer } from "wallet/wallet";
|
||||
import { ParamType } from "utils/abi-coder";
|
||||
import { BigNumber } from "utils/bignumber";
|
||||
interface Signer {
|
||||
defaultGasLimit?: BigNumber;
|
||||
defaultGasPrice?: BigNumber;
|
||||
address?: string;
|
||||
provider?: Provider;
|
||||
getAddress(): Promise<string>;
|
||||
getTransactionCount(): Promise<number>;
|
||||
estimateGas(tx: any): Promise<BigNumber>;
|
||||
sendTransaction(tx: any): Promise<any>;
|
||||
sign(tx: any): string | Promise<string>;
|
||||
}
|
||||
export type ContractEstimate = (...params: Array<any>) => Promise<BigNumber>;
|
||||
export type ContractFunction = (...params: Array<any>) => Promise<any>;
|
||||
export type ContractEvent = (...params: Array<any>) => void;
|
||||
@ -541,19 +703,11 @@ declare module "providers/index" {
|
||||
declare module "utils/id" {
|
||||
export function id(text: string): string;
|
||||
}
|
||||
declare module "utils/sha2" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export function sha256(data: Arrayish): string;
|
||||
export function sha512(data: Arrayish): string;
|
||||
}
|
||||
declare module "utils/solidity" {
|
||||
export function pack(types: Array<string>, values: Array<any>): string;
|
||||
export function keccak256(types: Array<string>, values: Array<any>): string;
|
||||
export function sha256(types: Array<string>, values: Array<any>): string;
|
||||
}
|
||||
declare module "utils/random-bytes" {
|
||||
export function randomBytes(length: number): Uint8Array;
|
||||
}
|
||||
declare module "utils/units" {
|
||||
import { BigNumber, BigNumberish } from "utils/bignumber";
|
||||
export function formatUnits(value: BigNumberish, unitType?: string | number, options?: any): string;
|
||||
@ -562,7 +716,7 @@ declare module "utils/units" {
|
||||
export function parseEther(ether: string): BigNumber;
|
||||
}
|
||||
declare module "utils/index" {
|
||||
import { getAddress, getContractAddress } from "utils/address";
|
||||
import { getAddress, getContractAddress, getIcapAddress } from "utils/address";
|
||||
import { AbiCoder, parseSignature } from "utils/abi-coder";
|
||||
import * as base64 from "utils/base64";
|
||||
import * as bigNumber from "utils/bignumber";
|
||||
@ -577,6 +731,7 @@ declare module "utils/index" {
|
||||
import * as utf8 from "utils/utf8";
|
||||
import * as units from "utils/units";
|
||||
import { fetchJson } from "utils/web";
|
||||
import { parse as parseTransaction } from "utils/transaction";
|
||||
const _default: {
|
||||
AbiCoder: typeof AbiCoder;
|
||||
defaultAbiCoder: AbiCoder;
|
||||
@ -597,6 +752,7 @@ declare module "utils/index" {
|
||||
namehash: typeof namehash;
|
||||
id: typeof id;
|
||||
getAddress: typeof getAddress;
|
||||
getIcapAddress: typeof getIcapAddress;
|
||||
getContractAddress: typeof getContractAddress;
|
||||
formatEther: typeof units.formatEther;
|
||||
parseEther: typeof units.parseEther;
|
||||
@ -609,175 +765,10 @@ declare module "utils/index" {
|
||||
solidityKeccak256: typeof solidity.keccak256;
|
||||
soliditySha256: typeof solidity.sha256;
|
||||
splitSignature: typeof convert.splitSignature;
|
||||
parseTransaction: typeof parseTransaction;
|
||||
};
|
||||
export default _default;
|
||||
}
|
||||
declare module "wallet/secp256k1" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
export type Signature = {
|
||||
r: string;
|
||||
s: string;
|
||||
recoveryParam: number;
|
||||
};
|
||||
export class KeyPair {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly compressedPublicKey: string;
|
||||
readonly publicKeyBytes: Uint8Array;
|
||||
constructor(privateKey: Arrayish);
|
||||
sign(digest: Arrayish): Signature;
|
||||
}
|
||||
export function recoverPublicKey(digest: Arrayish, signature: Signature): string;
|
||||
export function computePublicKey(key: Arrayish, compressed?: boolean): string;
|
||||
export const N: string;
|
||||
}
|
||||
declare module "wallet/words" {
|
||||
export function getWord(index: number): string;
|
||||
export function getWordIndex(word: string): number;
|
||||
}
|
||||
declare module "utils/hmac" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
interface HashFunc {
|
||||
(): HashFunc;
|
||||
update(chunk: Uint8Array): HashFunc;
|
||||
digest(encoding: string): string;
|
||||
digest(): Uint8Array;
|
||||
}
|
||||
export interface HmacFunc extends HashFunc {
|
||||
(hashFunc: HashFunc, key: Arrayish): HmacFunc;
|
||||
}
|
||||
export function createSha256Hmac(key: Arrayish): HmacFunc;
|
||||
export function createSha512Hmac(key: Arrayish): HmacFunc;
|
||||
}
|
||||
declare module "utils/pbkdf2" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { HmacFunc } from "utils/hmac";
|
||||
export interface CreateHmacFunc {
|
||||
(key: Arrayish): HmacFunc;
|
||||
}
|
||||
export function pbkdf2(password: Arrayish, salt: Arrayish, iterations: number, keylen: number, createHmac: CreateHmacFunc): Uint8Array;
|
||||
}
|
||||
declare module "wallet/hdnode" {
|
||||
import { KeyPair } from "wallet/secp256k1";
|
||||
import { Arrayish } from "utils/convert";
|
||||
export class HDNode {
|
||||
private readonly keyPair;
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
readonly chainCode: string;
|
||||
readonly index: number;
|
||||
readonly depth: number;
|
||||
constructor(keyPair: KeyPair, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string);
|
||||
private _derive;
|
||||
derivePath(path: string): HDNode;
|
||||
}
|
||||
export function fromMnemonic(mnemonic: string): HDNode;
|
||||
export function fromSeed(seed: Arrayish): HDNode;
|
||||
export function mnemonicToSeed(mnemonic: string, password?: string): string;
|
||||
export function mnemonicToEntropy(mnemonic: string): string;
|
||||
export function entropyToMnemonic(entropy: Arrayish): string;
|
||||
export function isValidMnemonic(mnemonic: string): boolean;
|
||||
}
|
||||
declare module "wallet/signing-key" {
|
||||
/**
|
||||
* SigningKey
|
||||
*
|
||||
*
|
||||
*/
|
||||
import { Signature } from "wallet/secp256k1";
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { HDNode } from "wallet/hdnode";
|
||||
export class SigningKey {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
private readonly keyPair;
|
||||
constructor(privateKey: Arrayish | HDNode);
|
||||
signDigest(digest: Arrayish): Signature;
|
||||
}
|
||||
export function recoverAddress(digest: Arrayish, signature: Signature): string;
|
||||
export function computeAddress(key: string): string;
|
||||
}
|
||||
declare module "wallet/secret-storage" {
|
||||
import { Arrayish } from "utils/convert";
|
||||
import { SigningKey } from "wallet/signing-key";
|
||||
export interface ProgressCallback {
|
||||
(percent: number): void;
|
||||
}
|
||||
export function isCrowdsaleWallet(json: string): boolean;
|
||||
export function isValidWallet(json: string): boolean;
|
||||
export function decryptCrowdsale(json: string, password: Arrayish | string): SigningKey;
|
||||
export function decrypt(json: string, password: any, progressCallback?: ProgressCallback): Promise<SigningKey>;
|
||||
export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish | string, options?: any, progressCallback?: ProgressCallback): Promise<string>;
|
||||
}
|
||||
declare module "wallet/wallet" {
|
||||
import { HDNode } from "wallet/hdnode";
|
||||
import { ProgressCallback } from "wallet/secret-storage";
|
||||
import { SigningKey } from "wallet/signing-key";
|
||||
import { BlockTag } from "providers/provider";
|
||||
import { BigNumber, BigNumberish } from "utils/bignumber";
|
||||
import { Arrayish } from "utils/convert";
|
||||
interface Provider {
|
||||
chainId: number;
|
||||
getBalance(address: string, blockTag: number | string): Promise<BigNumber>;
|
||||
getTransactionCount(address: string, blockTag: number | string): Promise<number>;
|
||||
estimateGas(transaction: any): Promise<BigNumber>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
sendTransaction(Bytes: any): Promise<string>;
|
||||
resolveName(address: string): Promise<string>;
|
||||
waitForTransaction(Bytes32: any): Promise<TransactionResponse>;
|
||||
}
|
||||
interface TransactionRequest {
|
||||
nonce?: number;
|
||||
to?: string;
|
||||
from?: string;
|
||||
data?: string;
|
||||
gasLimit?: BigNumber;
|
||||
gasPrice?: BigNumber;
|
||||
r?: string;
|
||||
s?: string;
|
||||
chainId?: number;
|
||||
v?: number;
|
||||
value?: BigNumber;
|
||||
}
|
||||
interface TransactionResponse extends TransactionRequest {
|
||||
hash?: string;
|
||||
blockHash?: string;
|
||||
block?: number;
|
||||
wait?: (timeout?: number) => Promise<TransactionResponse>;
|
||||
}
|
||||
export class Wallet {
|
||||
readonly address: string;
|
||||
readonly privateKey: string;
|
||||
private mnemonic;
|
||||
private path;
|
||||
private readonly signingKey;
|
||||
provider: any;
|
||||
defaultGasLimit: number;
|
||||
constructor(privateKey: SigningKey | HDNode | Arrayish, provider?: Provider);
|
||||
sign(transaction: TransactionRequest): string;
|
||||
static parseTransaction(rawTransaction: Arrayish): TransactionRequest;
|
||||
getAddress(): Promise<string>;
|
||||
getBalance(blockTag: BlockTag): Promise<BigNumber>;
|
||||
getTransactionCount(blockTag: BlockTag): Promise<number>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
sendTransaction(transaction: any): Promise<TransactionResponse>;
|
||||
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse>;
|
||||
static hashMessage(message: Arrayish | string): string;
|
||||
signMessage(message: Arrayish | string): string;
|
||||
static verifyMessage(message: Arrayish | string, signature: string): string;
|
||||
encrypt(password: Arrayish | string, options: any, progressCallback: ProgressCallback): Promise<string>;
|
||||
static createRandom(options: any): Wallet;
|
||||
static isEncryptedWallet(json: string): boolean;
|
||||
static fromEncryptedWallet(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
static fromMnemonic(mnemonic: string, path?: string): Wallet;
|
||||
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
}
|
||||
}
|
||||
declare module "wallet/index" {
|
||||
import { Wallet } from "wallet/wallet";
|
||||
import * as HDNode from "wallet/hdnode";
|
||||
|
723
dist/ethers.js
vendored
723
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
@ -3,8 +3,10 @@
|
||||
import { Interface } from './interface';
|
||||
|
||||
import { Provider, TransactionResponse } from '../providers/provider';
|
||||
import { Signer } from '../wallet/wallet';
|
||||
|
||||
import { getContractAddress } from '../utils/address';
|
||||
import { isHexString } from '../utils/convert';
|
||||
import { ParamType } from '../utils/abi-coder';
|
||||
import { BigNumber, ConstantZero } from '../utils/bignumber';
|
||||
import { defineReadOnly, resolveProperties } from '../utils/properties';
|
||||
@ -170,10 +172,10 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
}
|
||||
|
||||
if (transaction.gasLimit == null) {
|
||||
if (contract.signer.defaultGasLimit) {
|
||||
transaction.gasLimit = contract.signer.defaultGasLimit;
|
||||
if (contract.signer.estimateGas) {
|
||||
transaction.gasLimit = contract.signer.estimateGas(transaction);
|
||||
} else {
|
||||
transaction.gasLimit = 200000;
|
||||
transaction.gasLimit = contract.provider.estimateGas(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,8 +192,8 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
}
|
||||
|
||||
if (!transaction.gasPrice) {
|
||||
if (contract.signer.defaultGasPrice) {
|
||||
transaction.gasPrice = contract.signer.defaultGasPrice;
|
||||
if (contract.signer.getGasPrice) {
|
||||
transaction.gasPrice = contract.signer.getGasPrice(transaction);
|
||||
} else {
|
||||
transaction.gasPrice = contract.provider.getGasPrice();
|
||||
}
|
||||
@ -210,28 +212,6 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
throw new Error('unsupport type - ' + method.type);
|
||||
}
|
||||
}
|
||||
/*
|
||||
interface Provider {
|
||||
getNetwork(): Promise<Network>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
getTransactionCount(address: string | Promise<string>): Promise<number>;
|
||||
call(data: string): Promise<string>;
|
||||
estimateGas(tx: any): Promise<BigNumber>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
}
|
||||
*/
|
||||
interface Signer {
|
||||
defaultGasLimit?: BigNumber;
|
||||
defaultGasPrice?: BigNumber;
|
||||
address?: string;
|
||||
provider?: Provider;
|
||||
|
||||
getAddress(): Promise<string>;
|
||||
getTransactionCount(): Promise<number>;
|
||||
estimateGas(tx: any): Promise<BigNumber>;
|
||||
sendTransaction(tx: any): Promise<any>; // @TODO:
|
||||
sign(tx: any): string | Promise<string>;
|
||||
}
|
||||
|
||||
function isSigner(value: any): value is Signer {
|
||||
return (value && value.provider != null);
|
||||
@ -391,6 +371,14 @@ export class Contract {
|
||||
throw new Error('missing signer'); // @TODO: errors.throwError
|
||||
}
|
||||
|
||||
if (!isHexString(bytecode)) {
|
||||
errors.throwError('bytecode must be a valid hex string', errors.INVALID_ARGUMENT, { arg: 'bytecode', value: bytecode });
|
||||
}
|
||||
|
||||
if ((bytecode.length % 2) !== 0) {
|
||||
errors.throwError('bytecode must be valid data (even length)', errors.INVALID_ARGUMENT, { arg: 'bytecode', value: bytecode });
|
||||
}
|
||||
|
||||
// @TODO: overrides of args.length = this.interface.deployFunction.inputs.length + 1
|
||||
return this.signer.sendTransaction({
|
||||
data: this.interface.deployFunction.encode(bytecode, args)
|
||||
|
@ -39,13 +39,6 @@ function parseParams(params: Array<ParamType>): { names: Array<any>, types: Arra
|
||||
}
|
||||
}
|
||||
|
||||
export class Indexed {
|
||||
readonly hash: string;
|
||||
constructor(value: string) {
|
||||
defineReadOnly(this, 'hash', value);
|
||||
}
|
||||
}
|
||||
|
||||
export class Description {
|
||||
readonly type: string;
|
||||
readonly inputs: Array<ParamType>;
|
||||
@ -61,6 +54,16 @@ export class Description {
|
||||
}
|
||||
}
|
||||
|
||||
// @TOOD: Make this a description
|
||||
export class Indexed {
|
||||
readonly type: string;
|
||||
readonly hash: string;
|
||||
constructor(value: string) {
|
||||
defineReadOnly(this, 'type', 'indexed');
|
||||
defineReadOnly(this, 'hash', value);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeployDescription extends Description {
|
||||
readonly payable: boolean;
|
||||
|
||||
@ -160,7 +163,7 @@ export type CallTransaction = {
|
||||
value: BigNumber
|
||||
}
|
||||
|
||||
// @TODO: Make this a class
|
||||
// @TODO: Make this a description
|
||||
function Result() {}
|
||||
|
||||
export class EventDescription extends Description {
|
||||
|
@ -4,12 +4,13 @@
|
||||
|
||||
import { getAddress, getContractAddress } from '../utils/address';
|
||||
import { BigNumber, bigNumberify, BigNumberish } from '../utils/bignumber';
|
||||
import { Arrayish, hexlify, hexStripZeros, isHexString, stripZeros } from '../utils/convert';
|
||||
import { Arrayish, hexDataLength, hexDataSlice, hexlify, hexStripZeros, isHexString, stripZeros } from '../utils/convert';
|
||||
import { toUtf8String } from '../utils/utf8';
|
||||
import { decode as rlpDecode, encode as rlpEncode } from '../utils/rlp';
|
||||
import { namehash } from '../utils/namehash';
|
||||
import { getNetwork, Network } from './networks';
|
||||
import { resolveProperties } from '../utils/properties';
|
||||
import { parse as parseTransaction, Transaction } from '../utils/transaction';
|
||||
|
||||
import * as errors from '../utils/errors';
|
||||
|
||||
@ -24,22 +25,22 @@ function copyObject(obj) {
|
||||
|
||||
export type BlockTag = string | number;
|
||||
|
||||
export type Block = {
|
||||
hash: string,
|
||||
parentHash: string,
|
||||
number: number,
|
||||
export interface Block {
|
||||
hash: string;
|
||||
parentHash: string;
|
||||
number: number;
|
||||
|
||||
timestamp: number,
|
||||
nonce: string,
|
||||
difficulty: string,
|
||||
timestamp: number;
|
||||
nonce: string;
|
||||
difficulty: string;
|
||||
|
||||
gasLimit: BigNumber,
|
||||
gasUsed: BigNumber,
|
||||
gasLimit: BigNumber;
|
||||
gasUsed: BigNumber;
|
||||
|
||||
miner: string,
|
||||
extraData: string,
|
||||
miner: string;
|
||||
extraData: string;
|
||||
|
||||
transactions: Array<string>
|
||||
transactions: Array<string>;
|
||||
}
|
||||
|
||||
export type TransactionRequest = {
|
||||
@ -55,32 +56,20 @@ export type TransactionRequest = {
|
||||
chainId?: number | Promise<number>,
|
||||
}
|
||||
|
||||
export type TransactionResponse = {
|
||||
export interface TransactionResponse extends Transaction {
|
||||
// Only if a transaction has been mined
|
||||
blockNumber?: number,
|
||||
blockHash?: string,
|
||||
timestamp?: number,
|
||||
|
||||
hash: string,
|
||||
// Not optional (as it is in Transaction)
|
||||
from: string;
|
||||
|
||||
to?: string,
|
||||
from?: string,
|
||||
nonce?: number,
|
||||
// This function waits until the transaction has been mined
|
||||
wait: (timeout?: number) => Promise<TransactionResponse>
|
||||
};
|
||||
|
||||
gasLimit?: BigNumber,
|
||||
gasPrice?: BigNumber,
|
||||
|
||||
data?: string,
|
||||
value: BigNumber,
|
||||
chainId?: number,
|
||||
|
||||
r?: string,
|
||||
s?: string,
|
||||
v?: number,
|
||||
|
||||
wait?: (timeout?: number) => Promise<TransactionResponse>;
|
||||
}
|
||||
|
||||
export type TransactionReceipt = {
|
||||
export interface TransactionReceipt {
|
||||
contractAddress?: string,
|
||||
transactionIndex?: number,
|
||||
root?: string,
|
||||
@ -102,20 +91,20 @@ export type Filter = {
|
||||
}
|
||||
|
||||
// @TODO: Some of these are not options; force them?
|
||||
export type Log = {
|
||||
blockNumber?: number,
|
||||
blockHash?: string,
|
||||
transactionIndex?: number,
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
transactionIndex?: number;
|
||||
|
||||
removed?: boolean,
|
||||
removed?: boolean;
|
||||
|
||||
address: string,
|
||||
data?: string,
|
||||
address: string;
|
||||
data?: string;
|
||||
|
||||
topics?: Array<string>,
|
||||
topics?: Array<string>;
|
||||
|
||||
transactionHash?: string,
|
||||
logIndex?: number,
|
||||
transactionHash?: string;
|
||||
logIndex?: number;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -168,7 +157,7 @@ function arrayOf(check: CheckFunc): CheckFunc {
|
||||
}
|
||||
|
||||
function checkHash(hash: any): string {
|
||||
if (typeof(hash) === 'string' && isHexString(hash, 32)) {
|
||||
if (typeof(hash) === 'string' && hexDataLength(hash) === 32) {
|
||||
return hash;
|
||||
}
|
||||
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
|
||||
@ -199,7 +188,7 @@ function checkBoolean(value): boolean {
|
||||
throw new Error('invaid boolean - ' + value);
|
||||
}
|
||||
|
||||
function checkUint256(uint256): string {
|
||||
function checkUint256(uint256: string): string {
|
||||
if (!isHexString(uint256)) {
|
||||
throw new Error('invalid uint256');
|
||||
}
|
||||
@ -519,10 +508,9 @@ function getEventString(object) {
|
||||
} else if (object === 'pending') {
|
||||
return 'pending';
|
||||
|
||||
} else if (isHexString(object)) {
|
||||
if (object.length === 66) {
|
||||
return 'tx:' + object;
|
||||
}
|
||||
} else if (hexDataLength(object) === 32) {
|
||||
return 'tx:' + object;
|
||||
|
||||
} else if (Array.isArray(object)) {
|
||||
object = recurse(object, function(object) {
|
||||
if (object == null) { object = '0x'; }
|
||||
@ -581,7 +569,6 @@ type Event = {
|
||||
|
||||
export class Provider {
|
||||
private _network: Network;
|
||||
protected ready: Promise<Network>;
|
||||
|
||||
// string => Event
|
||||
private _events: any;
|
||||
@ -595,11 +582,17 @@ export class Provider {
|
||||
// string => BigNumber
|
||||
private _balances: any;
|
||||
|
||||
|
||||
/**
|
||||
* Sub-classing notes
|
||||
* - If the network is standard or fully specified, ready will resolve
|
||||
* - Otherwise, the sub-class must assign a Promise to ready
|
||||
* ready
|
||||
*
|
||||
* A Promise<Network> that resolves only once the provider is ready.
|
||||
*
|
||||
* Sub-classes that call the super with a network without a chainId
|
||||
* MUST set this. Standard named networks have a known chainId.
|
||||
*
|
||||
*/
|
||||
protected ready: Promise<Network>;
|
||||
|
||||
constructor(network: string | Network) {
|
||||
errors.checkNew(this, Provider);
|
||||
@ -859,16 +852,26 @@ export class Provider {
|
||||
});
|
||||
}
|
||||
|
||||
// @TODO: Shold this return the full tx instead of the hash? If so, that requires
|
||||
// the inclusion of secp256k1, which might be overkill for many applications...
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<string> {
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ signedTransaction: signedTransaction }).then(({ signedTransaction }) => {
|
||||
var params = { signedTransaction: hexlify(signedTransaction) };
|
||||
return this.perform('sendTransaction', params).then((result) => {
|
||||
result = hexlify(result);
|
||||
if (result.length !== 66) { throw new Error('invalid response - sendTransaction'); }
|
||||
return result;
|
||||
return this.perform('sendTransaction', params).then((hash) => {
|
||||
if (hexDataLength(hash) !== 32) { throw new Error('invalid response - sendTransaction'); }
|
||||
|
||||
// A signed transaction always has a from (and we add wait below)
|
||||
var tx = <TransactionResponse>parseTransaction(signedTransaction);
|
||||
|
||||
// Check the hash we expect is the same as the hash the server reported
|
||||
if (tx.hash !== hash) {
|
||||
errors.throwError('Transaction hash mismatch from Proivder.sendTransaction.', errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash });
|
||||
}
|
||||
this._emitted['t:' + tx.hash.toLowerCase()] = 'pending';
|
||||
tx.wait = (timeout?: number) => {
|
||||
return this.waitForTransaction(hash, timeout);
|
||||
};
|
||||
|
||||
return tx;
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -906,7 +909,7 @@ export class Provider {
|
||||
return resolveProperties({ blockHashOrBlockTag: blockHashOrBlockTag }).then(({ blockHashOrBlockTag }) => {
|
||||
try {
|
||||
var blockHash = hexlify(blockHashOrBlockTag);
|
||||
if (blockHash.length === 66) {
|
||||
if (hexDataLength(blockHash) === 32) {
|
||||
return stallPromise(() => {
|
||||
return (this._emitted['b:' + blockHash.toLowerCase()] == null);
|
||||
}, () => {
|
||||
@ -1028,8 +1031,8 @@ export class Provider {
|
||||
return this.call(transaction).then((data) => {
|
||||
|
||||
// extract the address from the data
|
||||
if (data.length != 66) { return null; }
|
||||
return getAddress('0x' + data.substring(26));
|
||||
if (hexDataLength(data) !== 32) { return null; }
|
||||
return getAddress(hexDataSlice(data, 12));
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1062,8 +1065,8 @@ export class Provider {
|
||||
|
||||
// extract the address from the data
|
||||
}).then(function(data) {
|
||||
if (data.length != 66) { return null; }
|
||||
var address = getAddress('0x' + data.substring(26));
|
||||
if (hexDataLength(data) !== 32) { return null; }
|
||||
var address = getAddress(hexDataSlice(data, 12));
|
||||
if (address === '0x0000000000000000000000000000000000000000') { return null; }
|
||||
return address;
|
||||
});
|
||||
|
@ -300,6 +300,9 @@ function parseSignatureFunction(fragment: string): FunctionFragment {
|
||||
return abi;
|
||||
}
|
||||
|
||||
export function parseParamType(type: string): ParamType {
|
||||
return parseParam(type, true);
|
||||
}
|
||||
|
||||
export function parseSignature(fragment: string): EventFragment | FunctionFragment {
|
||||
if(typeof(fragment) === 'string') {
|
||||
|
@ -78,7 +78,7 @@ function ibanChecksum(address: string): string {
|
||||
return checksum;
|
||||
};
|
||||
|
||||
export function getAddress(address: string, icapFormat?: boolean): string {
|
||||
export function getAddress(address: string): string {
|
||||
var result = null;
|
||||
|
||||
if (typeof(address) !== 'string') {
|
||||
@ -113,15 +113,15 @@ export function getAddress(address: string, icapFormat?: boolean): string {
|
||||
errors.throwError('invalid address', errors.INVALID_ARGUMENT, { arg: 'address', value: address });
|
||||
}
|
||||
|
||||
if (icapFormat) {
|
||||
var base36 = (new BN(result.substring(2), 16)).toString(36).toUpperCase();
|
||||
while (base36.length < 30) { base36 = '0' + base36; }
|
||||
return 'XE' + ibanChecksum('XE00' + base36) + base36;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getIcapAddress(address: string): string {
|
||||
var base36 = (new BN(getAddress(address).substring(2), 16)).toString(36).toUpperCase();
|
||||
while (base36.length < 30) { base36 = '0' + base36; }
|
||||
return 'XE' + ibanChecksum('XE00' + base36) + base36;
|
||||
}
|
||||
|
||||
// http://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed
|
||||
export function getContractAddress(transaction: { from: string, nonce: Arrayish | BigNumber | number }) {
|
||||
if (!transaction.from) { throw new Error('missing from address'); }
|
||||
|
@ -9,92 +9,33 @@
|
||||
*/
|
||||
|
||||
import _BN from 'bn.js';
|
||||
/*
|
||||
declare module _BN {
|
||||
|
||||
class BN {
|
||||
constructor(number: string | number, base?: number);
|
||||
|
||||
|
||||
toString(radix?: number): string;
|
||||
toNumber(): number;
|
||||
|
||||
fromTwos(value: any): BN;
|
||||
toTwos(value: any): BN;
|
||||
add(other: any): BN;
|
||||
sub(other: any): BN;
|
||||
div(other: any): BN;
|
||||
mul(other: any): BN;
|
||||
mod(modulo: any): BN;
|
||||
pow(exponent: any): BN;
|
||||
maskn(bits: number): BN;
|
||||
|
||||
eq(other: BN): boolean;
|
||||
gte(other: BN): boolean;
|
||||
gt(other: BN): boolean;
|
||||
lte(other: BN): boolean;
|
||||
lt(other: BN): boolean;
|
||||
isZero(): boolean;
|
||||
|
||||
static isBN(value: any): boolean;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import { Arrayish, hexlify, isArrayish, isHexString } from './convert';
|
||||
import { defineReadOnly } from './properties';
|
||||
import * as errors from '../utils/errors';
|
||||
|
||||
function _isBigNumber(value: any): value is BigNumber {
|
||||
return isBigNumber(value);
|
||||
}
|
||||
|
||||
// @TODO: is there a better way?
|
||||
/*
|
||||
export interface BigNumber {
|
||||
readonly _bn: BN;
|
||||
|
||||
fromTwos(value: any): BigNumber;
|
||||
toTwos(value: any): BigNumber;
|
||||
|
||||
add(other: any): BigNumber;
|
||||
sub(other: any): BigNumber;
|
||||
div(other: any): BigNumber;
|
||||
mul(other: any): BigNumber;
|
||||
mod(other: any): BigNumber;
|
||||
pow(other: any): BigNumber;
|
||||
maskn(value: any): BigNumber;
|
||||
eq(other: any): boolean;
|
||||
lt(other: any): boolean;
|
||||
lte(other: any): boolean;
|
||||
gt(other: any): boolean;
|
||||
gte(other: any): boolean;
|
||||
isZero(): boolean;
|
||||
toNumber(): number;
|
||||
toString(): string;
|
||||
toHexString(): string;
|
||||
}
|
||||
*/
|
||||
|
||||
export type BigNumberish = BigNumber | string | number | Arrayish;
|
||||
|
||||
export class BigNumber {
|
||||
readonly _bn: _BN.BN;
|
||||
private readonly _bn: _BN.BN;
|
||||
constructor(value: BigNumberish) {
|
||||
errors.checkNew(this, BigNumber);
|
||||
|
||||
if (typeof(value) === 'string') {
|
||||
if (isHexString(value)) {
|
||||
if (value == '0x') { value = '0x0'; }
|
||||
this._bn = new _BN.BN(value.substring(2), 16);
|
||||
defineReadOnly(this, '_bn', new _BN.BN(value.substring(2), 16));
|
||||
|
||||
} else if (value[0] === '-' && isHexString(value.substring(1))) {
|
||||
this._bn = (new _BN.BN(value.substring(3), 16)).mul(ConstantNegativeOne._bn);
|
||||
defineReadOnly(this, '_bn', (new _BN.BN(value.substring(3), 16)).mul(ConstantNegativeOne._bn));
|
||||
|
||||
} else if (value.match(/^-?[0-9]*$/)) {
|
||||
if (value == '') { value = '0'; }
|
||||
this._bn = new _BN.BN(value);
|
||||
defineReadOnly(this, '_bn', new _BN.BN(value));
|
||||
}
|
||||
|
||||
} else if (typeof(value) === 'number') {
|
||||
@ -102,19 +43,19 @@ export class BigNumber {
|
||||
errors.throwError('underflow', errors.NUMERIC_FAULT, { operation: 'setValue', fault: 'underflow', value: value, outputValue: Math.trunc(value) });
|
||||
}
|
||||
try {
|
||||
this._bn = new _BN.BN(value);
|
||||
defineReadOnly(this, '_bn', new _BN.BN(value));
|
||||
} catch (error) {
|
||||
errors.throwError('overflow', errors.NUMERIC_FAULT, { operation: 'setValue', fault: 'overflow', details: error.message });
|
||||
}
|
||||
|
||||
} else if (_BN.BN.isBN(value)) {
|
||||
this._bn = value;
|
||||
defineReadOnly(this, '_bn', value);
|
||||
|
||||
} else if (_isBigNumber(value)) {
|
||||
this._bn = value._bn;
|
||||
defineReadOnly(this, '_bn', value._bn);
|
||||
|
||||
} else if (isArrayish(value)) {
|
||||
this._bn = new _BN.BN(hexlify(value).substring(2), 16);
|
||||
defineReadOnly(this, '_bn', new _BN.BN(hexlify(value).substring(2), 16));
|
||||
|
||||
} else {
|
||||
errors.throwError('invalid BigNumber value', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||
|
@ -4,12 +4,13 @@
|
||||
*/
|
||||
|
||||
import { BigNumber } from './bignumber';
|
||||
import { Signature } from './secp256k1';
|
||||
|
||||
import errors = require('./errors');
|
||||
|
||||
export type Arrayish = string | ArrayLike<number>;
|
||||
|
||||
export type Signature = { r: string, s: string, v: number };
|
||||
|
||||
export type Arrayish = string | ArrayLike<number>;
|
||||
|
||||
|
||||
function isBigNumber(value: any): value is BigNumber {
|
||||
@ -140,7 +141,6 @@ export function isHexString(value: any, length?: number): boolean {
|
||||
|
||||
const HexCharacters: string = '0123456789abcdef';
|
||||
|
||||
// @TODO: Do not use any here
|
||||
export function hexlify(value: Arrayish | BigNumber | number): string {
|
||||
|
||||
if (isBigNumber(value)) {
|
||||
@ -196,6 +196,29 @@ export function hexlify(value: Arrayish | BigNumber | number): string {
|
||||
return 'never';
|
||||
}
|
||||
|
||||
export function hexDataLength(data: string) {
|
||||
if (!isHexString(data) || (data.length % 2) !== 0) {
|
||||
return null;
|
||||
}
|
||||
return (data.length - 2) / 2;
|
||||
}
|
||||
|
||||
export function hexDataSlice(data: string, offset: number, length?: number): string {
|
||||
if (!isHexString(data)) {
|
||||
errors.throwError('invalid hex data', errors.INVALID_ARGUMENT, { arg: 'value', value: data });
|
||||
}
|
||||
if ((data.length % 2) !== 0) {
|
||||
errors.throwError('hex data length must be even', errors.INVALID_ARGUMENT, { arg: 'value', value: data });
|
||||
}
|
||||
offset = 2 + 2 * offset;
|
||||
|
||||
if (length != null) {
|
||||
return '0x' + data.substring(offset, offset + 2 * length);
|
||||
}
|
||||
|
||||
return '0x' + data.substring(offset);
|
||||
}
|
||||
|
||||
export function hexStripZeros(value: string): string {
|
||||
if (!isHexString(value)) {
|
||||
errors.throwError('invalid hex string', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||
@ -217,13 +240,6 @@ export function hexZeroPad(value: string, length: number): string {
|
||||
return value;
|
||||
}
|
||||
|
||||
/* @TODO: Add something like this to make slicing code easier to understand
|
||||
function hexSlice(hex, start, end) {
|
||||
hex = hexlify(hex);
|
||||
return '0x' + hex.substring(2 + start * 2, 2 + end * 2);
|
||||
}
|
||||
*/
|
||||
|
||||
export function splitSignature(signature: Arrayish): Signature {
|
||||
let bytes: Uint8Array = arrayify(signature);
|
||||
if (bytes.length !== 65) {
|
||||
@ -238,6 +254,7 @@ export function splitSignature(signature: Arrayish): Signature {
|
||||
return {
|
||||
r: hexlify(bytes.slice(0, 32)),
|
||||
s: hexlify(bytes.slice(32, 64)),
|
||||
recoveryParam: (v - 27),
|
||||
v: v
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// This is SUPER useful, but adds 140kb (even zipped, adds 40kb)
|
||||
//var unorm = require('unorm');
|
||||
|
||||
import { getAddress, getContractAddress } from './address';
|
||||
import { getAddress, getContractAddress, getIcapAddress } from './address';
|
||||
import { AbiCoder, defaultAbiCoder, parseSignature } from './abi-coder';
|
||||
import * as base64 from './base64';
|
||||
import * as bigNumber from './bignumber';
|
||||
@ -19,7 +19,7 @@ import * as RLP from './rlp';
|
||||
import * as utf8 from './utf8';
|
||||
import * as units from './units';
|
||||
import { fetchJson } from './web';
|
||||
|
||||
import { parse as parseTransaction } from './transaction';
|
||||
|
||||
export default {
|
||||
AbiCoder: AbiCoder,
|
||||
@ -58,6 +58,7 @@ export default {
|
||||
id: id,
|
||||
|
||||
getAddress: getAddress,
|
||||
getIcapAddress: getIcapAddress,
|
||||
getContractAddress: getContractAddress,
|
||||
|
||||
formatEther: units.formatEther,
|
||||
@ -76,4 +77,6 @@ export default {
|
||||
soliditySha256: solidity.sha256,
|
||||
|
||||
splitSignature: convert.splitSignature,
|
||||
|
||||
parseTransaction: parseTransaction
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import { getAddress } from './address';
|
||||
import { arrayify, Arrayish, hexlify } from '../utils/convert';
|
||||
import { keccak256 } from './keccak256';
|
||||
import { defineReadOnly } from '../utils/properties';
|
||||
|
||||
import * as errors from '../utils/errors';
|
||||
@ -41,10 +43,13 @@ import * as elliptic from 'elliptic';
|
||||
const curve:_EC = new elliptic.ec('secp256k1');
|
||||
|
||||
|
||||
export type Signature = {
|
||||
export const N = '0x' + curve.n.toString(16);
|
||||
|
||||
export interface Signature {
|
||||
r: string;
|
||||
s: string;
|
||||
recoveryParam: number;
|
||||
v?: number;
|
||||
}
|
||||
|
||||
export class KeyPair {
|
||||
@ -71,7 +76,8 @@ export class KeyPair {
|
||||
return {
|
||||
recoveryParam: signature.recoveryParam,
|
||||
r: '0x' + signature.r.toString(16),
|
||||
s: '0x' + signature.s.toString(16)
|
||||
s: '0x' + signature.s.toString(16),
|
||||
v: 27 + signature.recoveryParam
|
||||
}
|
||||
|
||||
}
|
||||
@ -82,8 +88,7 @@ export function recoverPublicKey(digest: Arrayish, signature: Signature): string
|
||||
r: arrayify(signature.r),
|
||||
s: arrayify(signature.s)
|
||||
};
|
||||
|
||||
return '0x' + curve.recoverPubKey(arrayify(digest), sig, signature.recoveryParam).getPublic(false, 'hex');
|
||||
return '0x' + curve.recoverPubKey(arrayify(digest), sig, signature.recoveryParam).encode('hex', false);
|
||||
}
|
||||
|
||||
export function computePublicKey(key: Arrayish, compressed?: boolean): string {
|
||||
@ -110,4 +115,13 @@ export function computePublicKey(key: Arrayish, compressed?: boolean): string {
|
||||
return null;
|
||||
}
|
||||
|
||||
export const N = '0x' + curve.n.toString(16);
|
||||
export function recoverAddress(digest: Arrayish, signature: Signature): string {
|
||||
return computeAddress(recoverPublicKey(digest, signature));
|
||||
}
|
||||
|
||||
export function computeAddress(key: string): string {
|
||||
// Strip off the leading "0x04"
|
||||
let publicKey = '0x' + computePublicKey(key).slice(4);
|
||||
return getAddress('0x' + keccak256(publicKey).substring(26));
|
||||
}
|
||||
|
170
src.ts/utils/transaction.ts
Normal file
170
src.ts/utils/transaction.ts
Normal file
@ -0,0 +1,170 @@
|
||||
|
||||
import { getAddress } from './address';
|
||||
import { BigNumber, bigNumberify, BigNumberish,ConstantZero } from './bignumber';
|
||||
import { arrayify, Arrayish, hexlify, stripZeros, } from './convert';
|
||||
import { keccak256 } from './keccak256';
|
||||
import { recoverAddress, Signature } from './secp256k1';
|
||||
import * as RLP from './rlp';
|
||||
|
||||
export interface UnsignedTransaction {
|
||||
to?: string;
|
||||
nonce?: number;
|
||||
|
||||
gasLimit?: BigNumberish;
|
||||
gasPrice?: BigNumberish;
|
||||
|
||||
data?: Arrayish;
|
||||
value?: BigNumberish;
|
||||
chainId?: number;
|
||||
}
|
||||
|
||||
|
||||
export interface Transaction {
|
||||
hash?: string;
|
||||
|
||||
to?: string;
|
||||
from?: string;
|
||||
nonce: number;
|
||||
|
||||
gasLimit: BigNumber;
|
||||
gasPrice: BigNumber;
|
||||
|
||||
data: string;
|
||||
value: BigNumber;
|
||||
chainId: number;
|
||||
|
||||
r?: string;
|
||||
s?: string;
|
||||
v?: number;
|
||||
}
|
||||
|
||||
|
||||
function handleAddress(value: string): string {
|
||||
if (value === '0x') { return null; }
|
||||
return getAddress(value);
|
||||
}
|
||||
|
||||
function handleNumber(value: string): BigNumber {
|
||||
if (value === '0x') { return ConstantZero; }
|
||||
return bigNumberify(value);
|
||||
}
|
||||
|
||||
var transactionFields = [
|
||||
{name: 'nonce', maxLength: 32 },
|
||||
{name: 'gasPrice', maxLength: 32 },
|
||||
{name: 'gasLimit', maxLength: 32 },
|
||||
{name: 'to', length: 20 },
|
||||
{name: 'value', maxLength: 32 },
|
||||
{name: 'data' },
|
||||
];
|
||||
|
||||
|
||||
export type SignDigestFunc = (digest: Arrayish) => Signature;
|
||||
|
||||
export function sign(transaction: UnsignedTransaction, signDigest: SignDigestFunc): string {
|
||||
|
||||
var raw = [];
|
||||
|
||||
transactionFields.forEach(function(fieldInfo) {
|
||||
let value = transaction[fieldInfo.name] || ([]);
|
||||
value = arrayify(hexlify(value));
|
||||
|
||||
// Fixed-width field
|
||||
if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {
|
||||
let error: any = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'wrong length';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Variable-width (with a maximum)
|
||||
if (fieldInfo.maxLength) {
|
||||
value = stripZeros(value);
|
||||
if (value.length > fieldInfo.maxLength) {
|
||||
let error: any = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'too long';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
raw.push(hexlify(value));
|
||||
});
|
||||
|
||||
if (transaction.chainId) {
|
||||
raw.push(hexlify(transaction.chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
}
|
||||
|
||||
var digest = keccak256(RLP.encode(raw));
|
||||
|
||||
var signature = signDigest(digest);
|
||||
|
||||
var v = 27 + signature.recoveryParam
|
||||
if (transaction.chainId) {
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
v += transaction.chainId * 2 + 8;
|
||||
}
|
||||
|
||||
raw.push(hexlify(v));
|
||||
raw.push(signature.r);
|
||||
raw.push(signature.s);
|
||||
|
||||
return RLP.encode(raw);
|
||||
}
|
||||
|
||||
export function parse(rawTransaction: Arrayish): Transaction {
|
||||
var signedTransaction = RLP.decode(rawTransaction);
|
||||
if (signedTransaction.length !== 9) { throw new Error('invalid transaction'); }
|
||||
|
||||
let tx: Transaction = {
|
||||
nonce: handleNumber(signedTransaction[0]).toNumber(),
|
||||
gasPrice: handleNumber(signedTransaction[1]),
|
||||
gasLimit: handleNumber(signedTransaction[2]),
|
||||
to: handleAddress(signedTransaction[3]),
|
||||
value: handleNumber(signedTransaction[4]),
|
||||
data: signedTransaction[5],
|
||||
chainId: 0
|
||||
};
|
||||
|
||||
var v = arrayify(signedTransaction[6]);
|
||||
var r = arrayify(signedTransaction[7]);
|
||||
var s = arrayify(signedTransaction[8]);
|
||||
|
||||
if (v.length >= 1 && r.length >= 1 && r.length <= 32 && s.length >= 1 && s.length <= 32) {
|
||||
tx.v = bigNumberify(v).toNumber();
|
||||
tx.r = signedTransaction[7];
|
||||
tx.s = signedTransaction[8];
|
||||
|
||||
var chainId = (tx.v - 35) / 2;
|
||||
if (chainId < 0) { chainId = 0; }
|
||||
chainId = Math.trunc(chainId);
|
||||
|
||||
tx.chainId = chainId;
|
||||
|
||||
var recoveryParam = tx.v - 27;
|
||||
|
||||
let raw = signedTransaction.slice(0, 6);
|
||||
|
||||
if (chainId) {
|
||||
raw.push(hexlify(chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
recoveryParam -= chainId * 2 + 8;
|
||||
}
|
||||
|
||||
var digest = keccak256(RLP.encode(raw));
|
||||
try {
|
||||
tx.from = recoverAddress(digest, { r: hexlify(r), s: hexlify(s), recoveryParam: recoveryParam });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
tx.hash = keccak256(rawTransaction);
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
@ -3,8 +3,6 @@
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||
|
||||
import { KeyPair, N } from './secp256k1';
|
||||
|
||||
import { getWord, getWordIndex } from './words';
|
||||
|
||||
import { arrayify, Arrayish, hexlify } from '../utils/convert';
|
||||
@ -12,6 +10,7 @@ import { bigNumberify } from '../utils/bignumber';
|
||||
import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
|
||||
import { pbkdf2 } from '../utils/pbkdf2';
|
||||
import { createSha512Hmac } from '../utils/hmac';
|
||||
import { KeyPair, N } from '../utils/secp256k1';
|
||||
import { sha256 } from '../utils/sha2';
|
||||
|
||||
import * as errors from '../utils/errors';
|
||||
|
@ -6,13 +6,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import { computePublicKey, KeyPair, recoverPublicKey, Signature } from './secp256k1';
|
||||
|
||||
import { getAddress } from '../utils/address';
|
||||
import { arrayify, Arrayish, hexlify } from '../utils/convert';
|
||||
import { HDNode } from './hdnode';
|
||||
import { keccak256 } from '../utils/keccak256';
|
||||
import { defineReadOnly } from '../utils/properties';
|
||||
import { computePublicKey, KeyPair, recoverPublicKey, Signature } from '../utils/secp256k1';
|
||||
|
||||
import errors = require('../utils/errors');
|
||||
|
||||
|
@ -7,14 +7,14 @@ import * as secretStorage from './secret-storage';
|
||||
import { ProgressCallback } from './secret-storage';
|
||||
import { recoverAddress, SigningKey } from './signing-key';
|
||||
|
||||
import { BlockTag } from '../providers/provider';
|
||||
import { BlockTag, Provider, TransactionRequest, TransactionResponse } from '../providers/provider';
|
||||
|
||||
import { getAddress } from '../utils/address';
|
||||
import { BigNumber, bigNumberify, BigNumberish, ConstantZero } from '../utils/bignumber';
|
||||
import { arrayify, Arrayish, concat, hexlify, stripZeros, hexZeroPad } from '../utils/convert';
|
||||
import { BigNumber, BigNumberish } from '../utils/bignumber';
|
||||
import { arrayify, Arrayish, concat, hexlify, hexZeroPad } from '../utils/convert';
|
||||
import { keccak256 } from '../utils/keccak256';
|
||||
import { defineReadOnly, resolveProperties, shallowCopy } from '../utils/properties';
|
||||
import { randomBytes } from '../utils/random-bytes';
|
||||
import * as RLP from '../utils/rlp';
|
||||
import { sign as signTransaction, UnsignedTransaction } from '../utils/transaction';
|
||||
import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
|
||||
|
||||
import * as errors from '../utils/errors';
|
||||
@ -25,53 +25,28 @@ import * as errors from '../utils/errors';
|
||||
console.log("Fix this! Setimmediate");
|
||||
//import _setimmediate = require('setimmediate');
|
||||
|
||||
export interface Signer {
|
||||
// One of these MUST be specified
|
||||
address?: string;
|
||||
getAddress(): Promise<string>
|
||||
|
||||
interface Provider {
|
||||
chainId: number;
|
||||
getBalance(address: string, blockTag: number | string): Promise<BigNumber>;
|
||||
getTransactionCount(address: string, blockTag: number | string): Promise<number>;
|
||||
estimateGas(transaction: any): Promise<BigNumber>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
sendTransaction(Bytes): Promise<string>;
|
||||
resolveName(address: string): Promise<string>
|
||||
waitForTransaction(Bytes32): Promise<TransactionResponse>;
|
||||
sendTransaction(transaction: UnsignedTransaction): Promise<TransactionResponse>;
|
||||
|
||||
// If sendTransaction is not implemented, the following MUST be
|
||||
provider: Provider;
|
||||
sign(transaction: UnsignedTransaction): string;
|
||||
|
||||
// The following MAY be i,plemented
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getGasPrice(transaction?: TransactionRequest): Promise<BigNumber>
|
||||
}
|
||||
|
||||
interface TransactionRequest {
|
||||
nonce?: number;
|
||||
to?: string;
|
||||
from?: string;
|
||||
data?: string;
|
||||
gasLimit?: BigNumber;
|
||||
gasPrice?: BigNumber;
|
||||
r?: string;
|
||||
s?: string;
|
||||
chainId?: number;
|
||||
v?: number;
|
||||
value?: BigNumber;
|
||||
}
|
||||
|
||||
interface TransactionResponse extends TransactionRequest {
|
||||
hash?: string;
|
||||
blockHash?: string;
|
||||
block?: number;
|
||||
wait?: (timeout?: number) => Promise<TransactionResponse>;
|
||||
}
|
||||
|
||||
|
||||
// @TODO: Move to HDNode
|
||||
var defaultPath = "m/44'/60'/0'/0/0";
|
||||
|
||||
var transactionFields = [
|
||||
{name: 'nonce', maxLength: 32, },
|
||||
{name: 'gasPrice', maxLength: 32, },
|
||||
{name: 'gasLimit', maxLength: 32, },
|
||||
{name: 'to', length: 20, },
|
||||
{name: 'value', maxLength: 32, },
|
||||
{name: 'data'},
|
||||
];
|
||||
|
||||
// @TODO: Bytes32 or SigningKey
|
||||
export class Wallet {
|
||||
export class Wallet implements Signer {
|
||||
readonly address: string;
|
||||
readonly privateKey: string;
|
||||
|
||||
@ -80,7 +55,7 @@ export class Wallet {
|
||||
|
||||
private readonly signingKey: SigningKey;
|
||||
|
||||
provider: any;
|
||||
provider: Provider;
|
||||
|
||||
//private _provider;
|
||||
|
||||
@ -93,178 +68,44 @@ export class Wallet {
|
||||
if (privateKey instanceof SigningKey) {
|
||||
this.signingKey = privateKey;
|
||||
if (this.signingKey.mnemonic) {
|
||||
Object.defineProperty(this, 'mnemonic', {
|
||||
enumerable: true,
|
||||
value: this.signingKey.mnemonic,
|
||||
writable: false
|
||||
});
|
||||
//this.mnemonic = this.signingKey.mnemonic;
|
||||
this.path = this.signingKey.path;
|
||||
defineReadOnly(this, 'mnemonic', privateKey.mnemonic);
|
||||
defineReadOnly(this, 'path', privateKey.path);
|
||||
}
|
||||
} else {
|
||||
this.signingKey = new SigningKey(privateKey);
|
||||
}
|
||||
|
||||
this.privateKey = this.signingKey.privateKey
|
||||
defineReadOnly(this, 'privateKey', this.signingKey.privateKey);
|
||||
|
||||
this.provider = provider;
|
||||
|
||||
//this.address = this.signingKey.address;
|
||||
Object.defineProperty(this, 'address', {
|
||||
enumerable: true,
|
||||
value: this.signingKey.address,
|
||||
writable: false
|
||||
});
|
||||
defineReadOnly(this, 'address', this.signingKey.address);
|
||||
}
|
||||
|
||||
sign(transaction: TransactionRequest): string {
|
||||
var chainId = transaction.chainId;
|
||||
if (chainId == null && this.provider) { chainId = this.provider.chainId; }
|
||||
if (!chainId) { chainId = 0; }
|
||||
|
||||
var raw = [];
|
||||
transactionFields.forEach(function(fieldInfo) {
|
||||
let value = transaction[fieldInfo.name] || ([]);
|
||||
value = arrayify(hexlify(value));
|
||||
|
||||
// Fixed-width field
|
||||
if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {
|
||||
let error: any = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'wrong length';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Variable-width (with a maximum)
|
||||
if (fieldInfo.maxLength) {
|
||||
value = stripZeros(value);
|
||||
if (value.length > fieldInfo.maxLength) {
|
||||
let error: any = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'too long';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
raw.push(hexlify(value));
|
||||
});
|
||||
|
||||
if (chainId) {
|
||||
raw.push(hexlify(chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
}
|
||||
|
||||
var digest = keccak256(RLP.encode(raw));
|
||||
|
||||
var signature = this.signingKey.signDigest(digest);
|
||||
|
||||
var v = 27 + signature.recoveryParam
|
||||
if (chainId) {
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
v += chainId * 2 + 8;
|
||||
}
|
||||
|
||||
raw.push(hexlify(v));
|
||||
raw.push(signature.r);
|
||||
raw.push(signature.s);
|
||||
|
||||
return RLP.encode(raw);
|
||||
}
|
||||
/*
|
||||
set provider(provider: Provider) {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
get provider() {
|
||||
return this._provider;
|
||||
}
|
||||
*/
|
||||
static parseTransaction(rawTransaction: Arrayish): TransactionRequest {
|
||||
rawTransaction = hexlify(rawTransaction);
|
||||
var signedTransaction = RLP.decode(rawTransaction);
|
||||
if (signedTransaction.length !== 9) { throw new Error('invalid transaction'); }
|
||||
|
||||
var raw = [];
|
||||
|
||||
var transaction: any = { }
|
||||
|
||||
transactionFields.forEach(function(fieldInfo, index) {
|
||||
transaction[fieldInfo.name] = signedTransaction[index];
|
||||
raw.push(signedTransaction[index]);
|
||||
});
|
||||
|
||||
if (transaction.to) {
|
||||
if (transaction.to == '0x') {
|
||||
delete transaction.to;
|
||||
} else {
|
||||
transaction.to = getAddress(transaction.to);
|
||||
}
|
||||
}
|
||||
|
||||
['gasPrice', 'gasLimit', 'nonce', 'value'].forEach(function(name: string) {
|
||||
if (!transaction[name]) { return; }
|
||||
let value: BigNumber = ConstantZero;
|
||||
if (transaction[name].length > 0) {
|
||||
value = bigNumberify(transaction[name]);
|
||||
}
|
||||
transaction[name] = value;
|
||||
});
|
||||
|
||||
transaction.nonce = transaction.nonce.toNumber();
|
||||
|
||||
|
||||
var v = arrayify(signedTransaction[6]);
|
||||
var r = arrayify(signedTransaction[7]);
|
||||
var s = arrayify(signedTransaction[8]);
|
||||
|
||||
if (v.length >= 1 && r.length >= 1 && r.length <= 32 && s.length >= 1 && s.length <= 32) {
|
||||
transaction.v = bigNumberify(v).toNumber();
|
||||
transaction.r = signedTransaction[7];
|
||||
transaction.s = signedTransaction[8];
|
||||
|
||||
var chainId = (transaction.v - 35) / 2;
|
||||
if (chainId < 0) { chainId = 0; }
|
||||
chainId = Math.trunc(chainId);
|
||||
|
||||
transaction.chainId = chainId;
|
||||
|
||||
var recoveryParam = transaction.v - 27;
|
||||
|
||||
if (chainId) {
|
||||
raw.push(hexlify(chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
recoveryParam -= chainId * 2 + 8;
|
||||
}
|
||||
|
||||
var digest = keccak256(RLP.encode(raw));
|
||||
try {
|
||||
transaction.from = recoverAddress(digest, { r: hexlify(r), s: hexlify(s), recoveryParam });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
return transaction;
|
||||
sign(transaction: UnsignedTransaction): string {
|
||||
return signTransaction(transaction, this.signingKey.signDigest.bind(this.signingKey));
|
||||
}
|
||||
|
||||
getAddress(): Promise<string> {
|
||||
return Promise.resolve(this.address);
|
||||
}
|
||||
|
||||
getBalance(blockTag: BlockTag): Promise<BigNumber> {
|
||||
getBalance(blockTag?: BlockTag): Promise<BigNumber> {
|
||||
if (!this.provider) { throw new Error('missing provider'); }
|
||||
return this.provider.getBalance(this.address, blockTag);
|
||||
}
|
||||
|
||||
getTransactionCount(blockTag: BlockTag): Promise<number> {
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number> {
|
||||
if (!this.provider) { throw new Error('missing provider'); }
|
||||
return this.provider.getTransactionCount(this.address, blockTag);
|
||||
}
|
||||
|
||||
getGasPrice(): Promise<BigNumber> {
|
||||
if (!this.provider) { throw new Error('missing provider'); }
|
||||
|
||||
return this.provider.getGasPrice();
|
||||
}
|
||||
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber> {
|
||||
if (!this.provider) { throw new Error('missing provider'); }
|
||||
|
||||
@ -279,64 +120,40 @@ export class Wallet {
|
||||
return this.provider.estimateGas(calculate);
|
||||
}
|
||||
|
||||
sendTransaction(transaction: any): Promise<TransactionResponse> {
|
||||
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 gasLimit = transaction.gasLimit;
|
||||
if (gasLimit == null) { gasLimit = this.defaultGasLimit; }
|
||||
var tx = shallowCopy(transaction);
|
||||
|
||||
var self = this;
|
||||
|
||||
var gasPricePromise = null;
|
||||
if (transaction.gasPrice) {
|
||||
gasPricePromise = Promise.resolve(transaction.gasPrice);
|
||||
} else {
|
||||
gasPricePromise = this.provider.getGasPrice();
|
||||
if (tx.to != null) {
|
||||
tx.to = this.provider.resolveName(tx.to);
|
||||
}
|
||||
|
||||
var noncePromise = null;
|
||||
if (transaction.nonce) {
|
||||
noncePromise = Promise.resolve(transaction.nonce);
|
||||
} else {
|
||||
noncePromise = this.provider.getTransactionCount(self.address, 'pending');
|
||||
if (tx.gasLimit == null) {
|
||||
tx.gasLimit = this.estimateGas(tx);
|
||||
}
|
||||
|
||||
var chainId: number = this.provider.chainId;
|
||||
|
||||
var toPromise = null;
|
||||
if (transaction.to) {
|
||||
toPromise = this.provider.resolveName(transaction.to);
|
||||
} else {
|
||||
toPromise = Promise.resolve(undefined);
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = this.getGasPrice();
|
||||
}
|
||||
|
||||
var data = hexlify(transaction.data || '0x');
|
||||
var value = ConstantZero;
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = this.getTransactionCount();
|
||||
}
|
||||
|
||||
return Promise.all([gasPricePromise, noncePromise, toPromise]).then(function(results: [ BigNumber, number, string]) {
|
||||
var signedTransaction = self.sign({
|
||||
to: results[2],
|
||||
data: data,
|
||||
gasLimit: gasLimit,
|
||||
gasPrice: results[0],
|
||||
nonce: results[1],
|
||||
value: value,
|
||||
chainId: chainId
|
||||
});
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = this.provider.getNetwork().then((network) => network.chainId);
|
||||
}
|
||||
|
||||
return self.provider.sendTransaction(signedTransaction).then(function(hash) {
|
||||
var transaction: TransactionResponse = Wallet.parseTransaction(signedTransaction);
|
||||
transaction.hash = hash;
|
||||
transaction.wait = function() {
|
||||
return self.provider.waitForTransaction(hash);
|
||||
};
|
||||
return transaction;
|
||||
});
|
||||
return resolveProperties(tx).then((tx) => {
|
||||
console.log('To Sign', tx);
|
||||
return this.provider.sendTransaction(this.sign(tx));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse> {
|
||||
|
12
src/contracts/contract.d.ts
vendored
12
src/contracts/contract.d.ts
vendored
@ -1,18 +1,8 @@
|
||||
import { Interface } from './interface';
|
||||
import { Provider, TransactionResponse } from '../providers/provider';
|
||||
import { Signer } from '../wallet/wallet';
|
||||
import { ParamType } from '../utils/abi-coder';
|
||||
import { BigNumber } from '../utils/bignumber';
|
||||
interface Signer {
|
||||
defaultGasLimit?: BigNumber;
|
||||
defaultGasPrice?: BigNumber;
|
||||
address?: string;
|
||||
provider?: Provider;
|
||||
getAddress(): Promise<string>;
|
||||
getTransactionCount(): Promise<number>;
|
||||
estimateGas(tx: any): Promise<BigNumber>;
|
||||
sendTransaction(tx: any): Promise<any>;
|
||||
sign(tx: any): string | Promise<string>;
|
||||
}
|
||||
export declare type ContractEstimate = (...params: Array<any>) => Promise<BigNumber>;
|
||||
export declare type ContractFunction = (...params: Array<any>) => Promise<any>;
|
||||
export declare type ContractEvent = (...params: Array<any>) => void;
|
||||
|
@ -9,6 +9,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var interface_1 = require("./interface");
|
||||
var address_1 = require("../utils/address");
|
||||
var convert_1 = require("../utils/convert");
|
||||
var bignumber_1 = require("../utils/bignumber");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
@ -154,11 +155,11 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
});
|
||||
}
|
||||
if (transaction.gasLimit == null) {
|
||||
if (contract.signer.defaultGasLimit) {
|
||||
transaction.gasLimit = contract.signer.defaultGasLimit;
|
||||
if (contract.signer.estimateGas) {
|
||||
transaction.gasLimit = contract.signer.estimateGas(transaction);
|
||||
}
|
||||
else {
|
||||
transaction.gasLimit = 200000;
|
||||
transaction.gasLimit = contract.provider.estimateGas(transaction);
|
||||
}
|
||||
}
|
||||
if (!transaction.nonce) {
|
||||
@ -176,8 +177,8 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
}
|
||||
}
|
||||
if (!transaction.gasPrice) {
|
||||
if (contract.signer.defaultGasPrice) {
|
||||
transaction.gasPrice = contract.signer.defaultGasPrice;
|
||||
if (contract.signer.getGasPrice) {
|
||||
transaction.gasPrice = contract.signer.getGasPrice(transaction);
|
||||
}
|
||||
else {
|
||||
transaction.gasPrice = contract.provider.getGasPrice();
|
||||
@ -317,6 +318,12 @@ var Contract = /** @class */ (function () {
|
||||
if (this.signer == null) {
|
||||
throw new Error('missing signer'); // @TODO: errors.throwError
|
||||
}
|
||||
if (!convert_1.isHexString(bytecode)) {
|
||||
errors.throwError('bytecode must be a valid hex string', errors.INVALID_ARGUMENT, { arg: 'bytecode', value: bytecode });
|
||||
}
|
||||
if ((bytecode.length % 2) !== 0) {
|
||||
errors.throwError('bytecode must be valid data (even length)', errors.INVALID_ARGUMENT, { arg: 'bytecode', value: bytecode });
|
||||
}
|
||||
// @TODO: overrides of args.length = this.interface.deployFunction.inputs.length + 1
|
||||
return this.signer.sendTransaction({
|
||||
data: this.interface.deployFunction.encode(bytecode, args)
|
||||
|
9
src/contracts/interface.d.ts
vendored
9
src/contracts/interface.d.ts
vendored
@ -1,14 +1,15 @@
|
||||
import { ParamType } from '../utils/abi-coder';
|
||||
import { BigNumber, BigNumberish } from '../utils/bignumber';
|
||||
export declare class Indexed {
|
||||
readonly hash: string;
|
||||
constructor(value: string);
|
||||
}
|
||||
export declare class Description {
|
||||
readonly type: string;
|
||||
readonly inputs: Array<ParamType>;
|
||||
constructor(info: any);
|
||||
}
|
||||
export declare class Indexed {
|
||||
readonly type: string;
|
||||
readonly hash: string;
|
||||
constructor(value: string);
|
||||
}
|
||||
export declare class DeployDescription extends Description {
|
||||
readonly payable: boolean;
|
||||
encode(bytecode: string, params: Array<any>): string;
|
||||
|
@ -52,13 +52,6 @@ function parseParams(params) {
|
||||
types: types
|
||||
};
|
||||
}
|
||||
var Indexed = /** @class */ (function () {
|
||||
function Indexed(value) {
|
||||
properties_1.defineReadOnly(this, 'hash', value);
|
||||
}
|
||||
return Indexed;
|
||||
}());
|
||||
exports.Indexed = Indexed;
|
||||
var Description = /** @class */ (function () {
|
||||
function Description(info) {
|
||||
for (var key in info) {
|
||||
@ -74,6 +67,15 @@ var Description = /** @class */ (function () {
|
||||
return Description;
|
||||
}());
|
||||
exports.Description = Description;
|
||||
// @TOOD: Make this a description
|
||||
var Indexed = /** @class */ (function () {
|
||||
function Indexed(value) {
|
||||
properties_1.defineReadOnly(this, 'type', 'indexed');
|
||||
properties_1.defineReadOnly(this, 'hash', value);
|
||||
}
|
||||
return Indexed;
|
||||
}());
|
||||
exports.Indexed = Indexed;
|
||||
var DeployDescription = /** @class */ (function (_super) {
|
||||
__extends(DeployDescription, _super);
|
||||
function DeployDescription() {
|
||||
@ -164,7 +166,7 @@ var FunctionDescription = /** @class */ (function (_super) {
|
||||
return FunctionDescription;
|
||||
}(Description));
|
||||
exports.FunctionDescription = FunctionDescription;
|
||||
// @TODO: Make this a class
|
||||
// @TODO: Make this a description
|
||||
function Result() { }
|
||||
var EventDescription = /** @class */ (function (_super) {
|
||||
__extends(EventDescription, _super);
|
||||
|
46
src/providers/provider.d.ts
vendored
46
src/providers/provider.d.ts
vendored
@ -1,8 +1,9 @@
|
||||
import { BigNumber, BigNumberish } from '../utils/bignumber';
|
||||
import { Arrayish } from '../utils/convert';
|
||||
import { Network } from './networks';
|
||||
import { Transaction } from '../utils/transaction';
|
||||
export declare type BlockTag = string | number;
|
||||
export declare type Block = {
|
||||
export interface Block {
|
||||
hash: string;
|
||||
parentHash: string;
|
||||
number: number;
|
||||
@ -14,7 +15,7 @@ export declare type Block = {
|
||||
miner: string;
|
||||
extraData: string;
|
||||
transactions: Array<string>;
|
||||
};
|
||||
}
|
||||
export declare type TransactionRequest = {
|
||||
to?: string | Promise<string>;
|
||||
from?: string | Promise<string>;
|
||||
@ -25,25 +26,14 @@ export declare type TransactionRequest = {
|
||||
value?: BigNumberish | Promise<BigNumberish>;
|
||||
chainId?: number | Promise<number>;
|
||||
};
|
||||
export declare type TransactionResponse = {
|
||||
export interface TransactionResponse extends Transaction {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
hash: string;
|
||||
to?: string;
|
||||
from?: string;
|
||||
nonce?: number;
|
||||
gasLimit?: BigNumber;
|
||||
gasPrice?: BigNumber;
|
||||
data?: string;
|
||||
value: BigNumber;
|
||||
chainId?: number;
|
||||
r?: string;
|
||||
s?: string;
|
||||
v?: number;
|
||||
wait?: (timeout?: number) => Promise<TransactionResponse>;
|
||||
};
|
||||
export declare type TransactionReceipt = {
|
||||
from: string;
|
||||
wait: (timeout?: number) => Promise<TransactionResponse>;
|
||||
}
|
||||
export interface TransactionReceipt {
|
||||
contractAddress?: string;
|
||||
transactionIndex?: number;
|
||||
root?: string;
|
||||
@ -55,14 +45,14 @@ export declare type TransactionReceipt = {
|
||||
blockNumber?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
status?: number;
|
||||
};
|
||||
}
|
||||
export declare type Filter = {
|
||||
fromBlock?: BlockTag;
|
||||
toBlock?: BlockTag;
|
||||
address?: string;
|
||||
topics?: Array<any>;
|
||||
};
|
||||
export declare type Log = {
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
transactionIndex?: number;
|
||||
@ -72,11 +62,10 @@ export declare type Log = {
|
||||
topics?: Array<string>;
|
||||
transactionHash?: string;
|
||||
logIndex?: number;
|
||||
};
|
||||
}
|
||||
export declare function checkTransactionResponse(transaction: any): TransactionResponse;
|
||||
export declare class Provider {
|
||||
private _network;
|
||||
protected ready: Promise<Network>;
|
||||
private _events;
|
||||
protected _emitted: any;
|
||||
private _pollingInterval;
|
||||
@ -84,10 +73,15 @@ export declare class Provider {
|
||||
private _lastBlockNumber;
|
||||
private _balances;
|
||||
/**
|
||||
* Sub-classing notes
|
||||
* - If the network is standard or fully specified, ready will resolve
|
||||
* - Otherwise, the sub-class must assign a Promise to ready
|
||||
* ready
|
||||
*
|
||||
* A Promise<Network> that resolves only once the provider is ready.
|
||||
*
|
||||
* Sub-classes that call the super with a network without a chainId
|
||||
* MUST set this. Standard named networks have a known chainId.
|
||||
*
|
||||
*/
|
||||
protected ready: Promise<Network>;
|
||||
constructor(network: string | Network);
|
||||
private _doPoll;
|
||||
resetEventsBlock(blockNumber: number): void;
|
||||
@ -103,7 +97,7 @@ export declare class Provider {
|
||||
getTransactionCount(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<number>;
|
||||
getCode(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<string>;
|
||||
sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
call(transaction: TransactionRequest): Promise<string>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>): Promise<Block>;
|
||||
|
@ -16,6 +16,7 @@ var rlp_1 = require("../utils/rlp");
|
||||
var namehash_1 = require("../utils/namehash");
|
||||
var networks_1 = require("./networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var transaction_1 = require("../utils/transaction");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
function copyObject(obj) {
|
||||
var result = {};
|
||||
@ -24,6 +25,8 @@ function copyObject(obj) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
;
|
||||
;
|
||||
//////////////////////////////
|
||||
// Request and Response Checking
|
||||
// @TODO: not any?
|
||||
@ -73,7 +76,7 @@ function arrayOf(check) {
|
||||
});
|
||||
}
|
||||
function checkHash(hash) {
|
||||
if (typeof (hash) === 'string' && convert_1.isHexString(hash, 32)) {
|
||||
if (typeof (hash) === 'string' && convert_1.hexDataLength(hash) === 32) {
|
||||
return hash;
|
||||
}
|
||||
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
|
||||
@ -369,10 +372,8 @@ function getEventString(object) {
|
||||
else if (object === 'pending') {
|
||||
return 'pending';
|
||||
}
|
||||
else if (convert_1.isHexString(object)) {
|
||||
if (object.length === 66) {
|
||||
return 'tx:' + object;
|
||||
}
|
||||
else if (convert_1.hexDataLength(object) === 32) {
|
||||
return 'tx:' + object;
|
||||
}
|
||||
else if (Array.isArray(object)) {
|
||||
object = recurse(object, function (object) {
|
||||
@ -430,11 +431,6 @@ type Event = {
|
||||
}
|
||||
*/
|
||||
var Provider = /** @class */ (function () {
|
||||
/**
|
||||
* Sub-classing notes
|
||||
* - If the network is standard or fully specified, ready will resolve
|
||||
* - Otherwise, the sub-class must assign a Promise to ready
|
||||
*/
|
||||
function Provider(network) {
|
||||
errors.checkNew(this, Provider);
|
||||
network = networks_1.getNetwork(network);
|
||||
@ -701,20 +697,27 @@ var Provider = /** @class */ (function () {
|
||||
});
|
||||
});
|
||||
};
|
||||
// @TODO: Shold this return the full tx instead of the hash? If so, that requires
|
||||
// the inclusion of secp256k1, which might be overkill for many applications...
|
||||
Provider.prototype.sendTransaction = function (signedTransaction) {
|
||||
var _this = this;
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ signedTransaction: signedTransaction }).then(function (_a) {
|
||||
var signedTransaction = _a.signedTransaction;
|
||||
var params = { signedTransaction: convert_1.hexlify(signedTransaction) };
|
||||
return _this.perform('sendTransaction', params).then(function (result) {
|
||||
result = convert_1.hexlify(result);
|
||||
if (result.length !== 66) {
|
||||
return _this.perform('sendTransaction', params).then(function (hash) {
|
||||
if (convert_1.hexDataLength(hash) !== 32) {
|
||||
throw new Error('invalid response - sendTransaction');
|
||||
}
|
||||
return result;
|
||||
// A signed transaction always has a from (and we add wait below)
|
||||
var tx = transaction_1.parse(signedTransaction);
|
||||
// Check the hash we expect is the same as the hash the server reported
|
||||
if (tx.hash !== hash) {
|
||||
errors.throwError('Transaction hash mismatch from Proivder.sendTransaction.', errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash });
|
||||
}
|
||||
_this._emitted['t:' + tx.hash.toLowerCase()] = 'pending';
|
||||
tx.wait = function (timeout) {
|
||||
return _this.waitForTransaction(hash, timeout);
|
||||
};
|
||||
return tx;
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -752,7 +755,7 @@ var Provider = /** @class */ (function () {
|
||||
var blockHashOrBlockTag = _a.blockHashOrBlockTag;
|
||||
try {
|
||||
var blockHash = convert_1.hexlify(blockHashOrBlockTag);
|
||||
if (blockHash.length === 66) {
|
||||
if (convert_1.hexDataLength(blockHash) === 32) {
|
||||
return stallPromise(function () {
|
||||
return (_this._emitted['b:' + blockHash.toLowerCase()] == null);
|
||||
}, function () {
|
||||
@ -874,10 +877,10 @@ var Provider = /** @class */ (function () {
|
||||
var transaction = { to: network.ensAddress, data: data };
|
||||
return _this.call(transaction).then(function (data) {
|
||||
// extract the address from the data
|
||||
if (data.length != 66) {
|
||||
if (convert_1.hexDataLength(data) !== 32) {
|
||||
return null;
|
||||
}
|
||||
return address_1.getAddress('0x' + data.substring(26));
|
||||
return address_1.getAddress(convert_1.hexDataSlice(data, 12));
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -904,10 +907,10 @@ var Provider = /** @class */ (function () {
|
||||
return self.call(transaction);
|
||||
// extract the address from the data
|
||||
}).then(function (data) {
|
||||
if (data.length != 66) {
|
||||
if (convert_1.hexDataLength(data) !== 32) {
|
||||
return null;
|
||||
}
|
||||
var address = address_1.getAddress('0x' + data.substring(26));
|
||||
var address = address_1.getAddress(convert_1.hexDataSlice(data, 12));
|
||||
if (address === '0x0000000000000000000000000000000000000000') {
|
||||
return null;
|
||||
}
|
||||
|
1
src/utils/abi-coder.d.ts
vendored
1
src/utils/abi-coder.d.ts
vendored
@ -22,6 +22,7 @@ export declare type FunctionFragment = {
|
||||
payable: boolean;
|
||||
stateMutability: string;
|
||||
};
|
||||
export declare function parseParamType(type: string): ParamType;
|
||||
export declare function parseSignature(fragment: string): EventFragment | FunctionFragment;
|
||||
export declare class AbiCoder {
|
||||
readonly coerceFunc: CoerceFunc;
|
||||
|
@ -244,6 +244,10 @@ function parseSignatureFunction(fragment) {
|
||||
}
|
||||
return abi;
|
||||
}
|
||||
function parseParamType(type) {
|
||||
return parseParam(type, true);
|
||||
}
|
||||
exports.parseParamType = parseParamType;
|
||||
function parseSignature(fragment) {
|
||||
if (typeof (fragment) === 'string') {
|
||||
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
||||
|
3
src/utils/address.d.ts
vendored
3
src/utils/address.d.ts
vendored
@ -1,6 +1,7 @@
|
||||
import { BigNumber } from './bignumber';
|
||||
import { Arrayish } from './convert';
|
||||
export declare function getAddress(address: string, icapFormat?: boolean): string;
|
||||
export declare function getAddress(address: string): string;
|
||||
export declare function getIcapAddress(address: string): string;
|
||||
export declare function getContractAddress(transaction: {
|
||||
from: string;
|
||||
nonce: Arrayish | BigNumber | number;
|
||||
|
@ -65,7 +65,7 @@ function ibanChecksum(address) {
|
||||
return checksum;
|
||||
}
|
||||
;
|
||||
function getAddress(address, icapFormat) {
|
||||
function getAddress(address) {
|
||||
var result = null;
|
||||
if (typeof (address) !== 'string') {
|
||||
errors.throwError('invalid address', errors.INVALID_ARGUMENT, { arg: 'address', value: address });
|
||||
@ -96,16 +96,17 @@ function getAddress(address, icapFormat) {
|
||||
else {
|
||||
errors.throwError('invalid address', errors.INVALID_ARGUMENT, { arg: 'address', value: address });
|
||||
}
|
||||
if (icapFormat) {
|
||||
var base36 = (new BN(result.substring(2), 16)).toString(36).toUpperCase();
|
||||
while (base36.length < 30) {
|
||||
base36 = '0' + base36;
|
||||
}
|
||||
return 'XE' + ibanChecksum('XE00' + base36) + base36;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.getAddress = getAddress;
|
||||
function getIcapAddress(address) {
|
||||
var base36 = (new BN(getAddress(address).substring(2), 16)).toString(36).toUpperCase();
|
||||
while (base36.length < 30) {
|
||||
base36 = '0' + base36;
|
||||
}
|
||||
return 'XE' + ibanChecksum('XE00' + base36) + base36;
|
||||
}
|
||||
exports.getIcapAddress = getIcapAddress;
|
||||
// http://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed
|
||||
function getContractAddress(transaction) {
|
||||
if (!transaction.from) {
|
||||
|
10
src/utils/bignumber.d.ts
vendored
10
src/utils/bignumber.d.ts
vendored
@ -1,15 +1,7 @@
|
||||
/**
|
||||
* BigNumber
|
||||
*
|
||||
* A wrapper around the BN.js object. We use the BN.js library
|
||||
* because it is used by elliptic, so it is required regardles.
|
||||
*
|
||||
*/
|
||||
import _BN from 'bn.js';
|
||||
import { Arrayish } from './convert';
|
||||
export declare type BigNumberish = BigNumber | string | number | Arrayish;
|
||||
export declare class BigNumber {
|
||||
readonly _bn: _BN.BN;
|
||||
private readonly _bn;
|
||||
constructor(value: BigNumberish);
|
||||
fromTwos(value: BigNumberish): BigNumber;
|
||||
toTwos(value: BigNumberish): BigNumber;
|
||||
|
@ -18,38 +18,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
*
|
||||
*/
|
||||
var bn_js_1 = __importDefault(require("bn.js"));
|
||||
/*
|
||||
declare module _BN {
|
||||
|
||||
class BN {
|
||||
constructor(number: string | number, base?: number);
|
||||
|
||||
|
||||
toString(radix?: number): string;
|
||||
toNumber(): number;
|
||||
|
||||
fromTwos(value: any): BN;
|
||||
toTwos(value: any): BN;
|
||||
add(other: any): BN;
|
||||
sub(other: any): BN;
|
||||
div(other: any): BN;
|
||||
mul(other: any): BN;
|
||||
mod(modulo: any): BN;
|
||||
pow(exponent: any): BN;
|
||||
maskn(bits: number): BN;
|
||||
|
||||
eq(other: BN): boolean;
|
||||
gte(other: BN): boolean;
|
||||
gt(other: BN): boolean;
|
||||
lte(other: BN): boolean;
|
||||
lt(other: BN): boolean;
|
||||
isZero(): boolean;
|
||||
|
||||
static isBN(value: any): boolean;
|
||||
}
|
||||
}
|
||||
*/
|
||||
var convert_1 = require("./convert");
|
||||
var properties_1 = require("./properties");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
function _isBigNumber(value) {
|
||||
return isBigNumber(value);
|
||||
@ -62,16 +32,16 @@ var BigNumber = /** @class */ (function () {
|
||||
if (value == '0x') {
|
||||
value = '0x0';
|
||||
}
|
||||
this._bn = new bn_js_1.default.BN(value.substring(2), 16);
|
||||
properties_1.defineReadOnly(this, '_bn', new bn_js_1.default.BN(value.substring(2), 16));
|
||||
}
|
||||
else if (value[0] === '-' && convert_1.isHexString(value.substring(1))) {
|
||||
this._bn = (new bn_js_1.default.BN(value.substring(3), 16)).mul(exports.ConstantNegativeOne._bn);
|
||||
properties_1.defineReadOnly(this, '_bn', (new bn_js_1.default.BN(value.substring(3), 16)).mul(exports.ConstantNegativeOne._bn));
|
||||
}
|
||||
else if (value.match(/^-?[0-9]*$/)) {
|
||||
if (value == '') {
|
||||
value = '0';
|
||||
}
|
||||
this._bn = new bn_js_1.default.BN(value);
|
||||
properties_1.defineReadOnly(this, '_bn', new bn_js_1.default.BN(value));
|
||||
}
|
||||
}
|
||||
else if (typeof (value) === 'number') {
|
||||
@ -79,20 +49,20 @@ var BigNumber = /** @class */ (function () {
|
||||
errors.throwError('underflow', errors.NUMERIC_FAULT, { operation: 'setValue', fault: 'underflow', value: value, outputValue: Math.trunc(value) });
|
||||
}
|
||||
try {
|
||||
this._bn = new bn_js_1.default.BN(value);
|
||||
properties_1.defineReadOnly(this, '_bn', new bn_js_1.default.BN(value));
|
||||
}
|
||||
catch (error) {
|
||||
errors.throwError('overflow', errors.NUMERIC_FAULT, { operation: 'setValue', fault: 'overflow', details: error.message });
|
||||
}
|
||||
}
|
||||
else if (bn_js_1.default.BN.isBN(value)) {
|
||||
this._bn = value;
|
||||
properties_1.defineReadOnly(this, '_bn', value);
|
||||
}
|
||||
else if (_isBigNumber(value)) {
|
||||
this._bn = value._bn;
|
||||
properties_1.defineReadOnly(this, '_bn', value._bn);
|
||||
}
|
||||
else if (convert_1.isArrayish(value)) {
|
||||
this._bn = new bn_js_1.default.BN(convert_1.hexlify(value).substring(2), 16);
|
||||
properties_1.defineReadOnly(this, '_bn', new bn_js_1.default.BN(convert_1.hexlify(value).substring(2), 16));
|
||||
}
|
||||
else {
|
||||
errors.throwError('invalid BigNumber value', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||
|
8
src/utils/convert.d.ts
vendored
8
src/utils/convert.d.ts
vendored
@ -3,12 +3,8 @@
|
||||
*
|
||||
*/
|
||||
import { BigNumber } from './bignumber';
|
||||
import { Signature } from './secp256k1';
|
||||
export declare type Arrayish = string | ArrayLike<number>;
|
||||
export declare type Signature = {
|
||||
r: string;
|
||||
s: string;
|
||||
v: number;
|
||||
};
|
||||
export declare function isArrayish(value: any): boolean;
|
||||
export declare function arrayify(value: Arrayish | BigNumber): Uint8Array;
|
||||
export declare function concat(objects: Array<Arrayish>): Uint8Array;
|
||||
@ -16,6 +12,8 @@ export declare function stripZeros(value: Arrayish): Uint8Array;
|
||||
export declare function padZeros(value: Arrayish, length: number): Uint8Array;
|
||||
export declare function isHexString(value: any, length?: number): boolean;
|
||||
export declare function hexlify(value: Arrayish | BigNumber | number): string;
|
||||
export declare function hexDataLength(data: string): number;
|
||||
export declare function hexDataSlice(data: string, offset: number, length?: number): string;
|
||||
export declare function hexStripZeros(value: string): string;
|
||||
export declare function hexZeroPad(value: string, length: number): string;
|
||||
export declare function splitSignature(signature: Arrayish): Signature;
|
||||
|
@ -120,7 +120,6 @@ function isHexString(value, length) {
|
||||
}
|
||||
exports.isHexString = isHexString;
|
||||
var HexCharacters = '0123456789abcdef';
|
||||
// @TODO: Do not use any here
|
||||
function hexlify(value) {
|
||||
if (isBigNumber(value)) {
|
||||
return value.toHexString();
|
||||
@ -167,6 +166,27 @@ function hexlify(value) {
|
||||
return 'never';
|
||||
}
|
||||
exports.hexlify = hexlify;
|
||||
function hexDataLength(data) {
|
||||
if (!isHexString(data) || (data.length % 2) !== 0) {
|
||||
return null;
|
||||
}
|
||||
return (data.length - 2) / 2;
|
||||
}
|
||||
exports.hexDataLength = hexDataLength;
|
||||
function hexDataSlice(data, offset, length) {
|
||||
if (!isHexString(data)) {
|
||||
errors.throwError('invalid hex data', errors.INVALID_ARGUMENT, { arg: 'value', value: data });
|
||||
}
|
||||
if ((data.length % 2) !== 0) {
|
||||
errors.throwError('hex data length must be even', errors.INVALID_ARGUMENT, { arg: 'value', value: data });
|
||||
}
|
||||
offset = 2 + 2 * offset;
|
||||
if (length != null) {
|
||||
return '0x' + data.substring(offset, offset + 2 * length);
|
||||
}
|
||||
return '0x' + data.substring(offset);
|
||||
}
|
||||
exports.hexDataSlice = hexDataSlice;
|
||||
function hexStripZeros(value) {
|
||||
if (!isHexString(value)) {
|
||||
errors.throwError('invalid hex string', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||
@ -187,12 +207,6 @@ function hexZeroPad(value, length) {
|
||||
return value;
|
||||
}
|
||||
exports.hexZeroPad = hexZeroPad;
|
||||
/* @TODO: Add something like this to make slicing code easier to understand
|
||||
function hexSlice(hex, start, end) {
|
||||
hex = hexlify(hex);
|
||||
return '0x' + hex.substring(2 + start * 2, 2 + end * 2);
|
||||
}
|
||||
*/
|
||||
function splitSignature(signature) {
|
||||
var bytes = arrayify(signature);
|
||||
if (bytes.length !== 65) {
|
||||
@ -205,6 +219,7 @@ function splitSignature(signature) {
|
||||
return {
|
||||
r: hexlify(bytes.slice(0, 32)),
|
||||
s: hexlify(bytes.slice(32, 64)),
|
||||
recoveryParam: (v - 27),
|
||||
v: v
|
||||
};
|
||||
}
|
||||
|
5
src/utils/index.d.ts
vendored
5
src/utils/index.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
import { getAddress, getContractAddress } from './address';
|
||||
import { getAddress, getContractAddress, getIcapAddress } from './address';
|
||||
import { AbiCoder, parseSignature } from './abi-coder';
|
||||
import * as base64 from './base64';
|
||||
import * as bigNumber from './bignumber';
|
||||
@ -13,6 +13,7 @@ import * as RLP from './rlp';
|
||||
import * as utf8 from './utf8';
|
||||
import * as units from './units';
|
||||
import { fetchJson } from './web';
|
||||
import { parse as parseTransaction } from './transaction';
|
||||
declare const _default: {
|
||||
AbiCoder: typeof AbiCoder;
|
||||
defaultAbiCoder: AbiCoder;
|
||||
@ -33,6 +34,7 @@ declare const _default: {
|
||||
namehash: typeof namehash;
|
||||
id: typeof id;
|
||||
getAddress: typeof getAddress;
|
||||
getIcapAddress: typeof getIcapAddress;
|
||||
getContractAddress: typeof getContractAddress;
|
||||
formatEther: typeof units.formatEther;
|
||||
parseEther: typeof units.parseEther;
|
||||
@ -45,5 +47,6 @@ declare const _default: {
|
||||
solidityKeccak256: typeof solidity.keccak256;
|
||||
soliditySha256: typeof solidity.sha256;
|
||||
splitSignature: typeof convert.splitSignature;
|
||||
parseTransaction: typeof parseTransaction;
|
||||
};
|
||||
export default _default;
|
||||
|
@ -25,6 +25,7 @@ var RLP = __importStar(require("./rlp"));
|
||||
var utf8 = __importStar(require("./utf8"));
|
||||
var units = __importStar(require("./units"));
|
||||
var web_1 = require("./web");
|
||||
var transaction_1 = require("./transaction");
|
||||
exports.default = {
|
||||
AbiCoder: abi_coder_1.AbiCoder,
|
||||
defaultAbiCoder: abi_coder_1.defaultAbiCoder,
|
||||
@ -49,6 +50,7 @@ exports.default = {
|
||||
namehash: namehash_1.namehash,
|
||||
id: id_1.id,
|
||||
getAddress: address_1.getAddress,
|
||||
getIcapAddress: address_1.getIcapAddress,
|
||||
getContractAddress: address_1.getContractAddress,
|
||||
formatEther: units.formatEther,
|
||||
parseEther: units.parseEther,
|
||||
@ -61,4 +63,5 @@ exports.default = {
|
||||
solidityKeccak256: solidity.keccak256,
|
||||
soliditySha256: solidity.sha256,
|
||||
splitSignature: convert.splitSignature,
|
||||
parseTransaction: transaction_1.parse
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var convert_1 = require("./convert");
|
||||
var crypto_1 = require("crypto");
|
||||
//function _randomBytes(length) { return "0x00"; }
|
||||
function randomBytes(length) {
|
||||
return convert_1.arrayify(crypto_1.randomBytes(length));
|
||||
}
|
||||
|
20
src/utils/secp256k1.d.ts
vendored
Normal file
20
src/utils/secp256k1.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import { Arrayish } from '../utils/convert';
|
||||
export declare const N: string;
|
||||
export interface Signature {
|
||||
r: string;
|
||||
s: string;
|
||||
recoveryParam: number;
|
||||
v?: number;
|
||||
}
|
||||
export declare class KeyPair {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly compressedPublicKey: string;
|
||||
readonly publicKeyBytes: Uint8Array;
|
||||
constructor(privateKey: Arrayish);
|
||||
sign(digest: Arrayish): Signature;
|
||||
}
|
||||
export declare function recoverPublicKey(digest: Arrayish, signature: Signature): string;
|
||||
export declare function computePublicKey(key: Arrayish, compressed?: boolean): string;
|
||||
export declare function recoverAddress(digest: Arrayish, signature: Signature): string;
|
||||
export declare function computeAddress(key: string): string;
|
81
src/utils/secp256k1.js
Normal file
81
src/utils/secp256k1.js
Normal file
@ -0,0 +1,81 @@
|
||||
'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 address_1 = require("./address");
|
||||
var convert_1 = require("../utils/convert");
|
||||
var keccak256_1 = require("./keccak256");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
var elliptic = __importStar(require("elliptic"));
|
||||
var curve = new elliptic.ec('secp256k1');
|
||||
exports.N = '0x' + curve.n.toString(16);
|
||||
var KeyPair = /** @class */ (function () {
|
||||
function KeyPair(privateKey) {
|
||||
var keyPair = curve.keyFromPrivate(convert_1.arrayify(privateKey));
|
||||
properties_1.defineReadOnly(this, 'privateKey', convert_1.hexlify(keyPair.priv.toArray('be', 32)));
|
||||
properties_1.defineReadOnly(this, 'publicKey', '0x' + keyPair.getPublic(false, 'hex'));
|
||||
properties_1.defineReadOnly(this, 'compressedPublicKey', '0x' + keyPair.getPublic(true, 'hex'));
|
||||
properties_1.defineReadOnly(this, 'publicKeyBytes', keyPair.getPublic().encode(null, true));
|
||||
}
|
||||
KeyPair.prototype.sign = function (digest) {
|
||||
var keyPair = curve.keyFromPrivate(convert_1.arrayify(this.privateKey));
|
||||
var signature = keyPair.sign(convert_1.arrayify(digest), { canonical: true });
|
||||
return {
|
||||
recoveryParam: signature.recoveryParam,
|
||||
r: '0x' + signature.r.toString(16),
|
||||
s: '0x' + signature.s.toString(16),
|
||||
v: 27 + signature.recoveryParam
|
||||
};
|
||||
};
|
||||
return KeyPair;
|
||||
}());
|
||||
exports.KeyPair = KeyPair;
|
||||
function recoverPublicKey(digest, signature) {
|
||||
var sig = {
|
||||
r: convert_1.arrayify(signature.r),
|
||||
s: convert_1.arrayify(signature.s)
|
||||
};
|
||||
return '0x' + curve.recoverPubKey(convert_1.arrayify(digest), sig, signature.recoveryParam).encode('hex', false);
|
||||
}
|
||||
exports.recoverPublicKey = recoverPublicKey;
|
||||
function computePublicKey(key, compressed) {
|
||||
var bytes = convert_1.arrayify(key);
|
||||
if (bytes.length === 32) {
|
||||
var keyPair = new KeyPair(bytes);
|
||||
if (compressed) {
|
||||
return keyPair.compressedPublicKey;
|
||||
}
|
||||
return keyPair.publicKey;
|
||||
}
|
||||
else if (bytes.length === 33) {
|
||||
if (compressed) {
|
||||
return convert_1.hexlify(bytes);
|
||||
}
|
||||
return '0x' + curve.keyFromPublic(bytes).getPublic(false, 'hex');
|
||||
}
|
||||
else if (bytes.length === 65) {
|
||||
if (!compressed) {
|
||||
return convert_1.hexlify(bytes);
|
||||
}
|
||||
return '0x' + curve.keyFromPublic(bytes).getPublic(true, 'hex');
|
||||
}
|
||||
errors.throwError('invalid public or private key', errors.INVALID_ARGUMENT, { arg: 'key', value: '[REDACTED]' });
|
||||
return null;
|
||||
}
|
||||
exports.computePublicKey = computePublicKey;
|
||||
function recoverAddress(digest, signature) {
|
||||
return computeAddress(recoverPublicKey(digest, signature));
|
||||
}
|
||||
exports.recoverAddress = recoverAddress;
|
||||
function computeAddress(key) {
|
||||
// Strip off the leading "0x04"
|
||||
var publicKey = '0x' + computePublicKey(key).slice(4);
|
||||
return address_1.getAddress('0x' + keccak256_1.keccak256(publicKey).substring(26));
|
||||
}
|
||||
exports.computeAddress = computeAddress;
|
29
src/utils/transaction.d.ts
vendored
Normal file
29
src/utils/transaction.d.ts
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
import { BigNumber, BigNumberish } from './bignumber';
|
||||
import { Arrayish } from './convert';
|
||||
import { Signature } from './secp256k1';
|
||||
export interface UnsignedTransaction {
|
||||
to?: string;
|
||||
nonce?: number;
|
||||
gasLimit?: BigNumberish;
|
||||
gasPrice?: BigNumberish;
|
||||
data?: Arrayish;
|
||||
value?: BigNumberish;
|
||||
chainId?: number;
|
||||
}
|
||||
export interface Transaction {
|
||||
hash?: string;
|
||||
to?: string;
|
||||
from?: string;
|
||||
nonce: number;
|
||||
gasLimit: BigNumber;
|
||||
gasPrice: BigNumber;
|
||||
data: string;
|
||||
value: BigNumber;
|
||||
chainId: number;
|
||||
r?: string;
|
||||
s?: string;
|
||||
v?: number;
|
||||
}
|
||||
export declare type SignDigestFunc = (digest: Arrayish) => Signature;
|
||||
export declare function sign(transaction: UnsignedTransaction, signDigest: SignDigestFunc): string;
|
||||
export declare function parse(rawTransaction: Arrayish): Transaction;
|
126
src/utils/transaction.js
Normal file
126
src/utils/transaction.js
Normal file
@ -0,0 +1,126 @@
|
||||
"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 address_1 = require("./address");
|
||||
var bignumber_1 = require("./bignumber");
|
||||
var convert_1 = require("./convert");
|
||||
var keccak256_1 = require("./keccak256");
|
||||
var secp256k1_1 = require("./secp256k1");
|
||||
var RLP = __importStar(require("./rlp"));
|
||||
function handleAddress(value) {
|
||||
if (value === '0x') {
|
||||
return null;
|
||||
}
|
||||
return address_1.getAddress(value);
|
||||
}
|
||||
function handleNumber(value) {
|
||||
if (value === '0x') {
|
||||
return bignumber_1.ConstantZero;
|
||||
}
|
||||
return bignumber_1.bigNumberify(value);
|
||||
}
|
||||
var transactionFields = [
|
||||
{ name: 'nonce', maxLength: 32 },
|
||||
{ name: 'gasPrice', maxLength: 32 },
|
||||
{ name: 'gasLimit', maxLength: 32 },
|
||||
{ name: 'to', length: 20 },
|
||||
{ name: 'value', maxLength: 32 },
|
||||
{ name: 'data' },
|
||||
];
|
||||
function sign(transaction, signDigest) {
|
||||
var raw = [];
|
||||
transactionFields.forEach(function (fieldInfo) {
|
||||
var value = transaction[fieldInfo.name] || ([]);
|
||||
value = convert_1.arrayify(convert_1.hexlify(value));
|
||||
// Fixed-width field
|
||||
if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {
|
||||
var error = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'wrong length';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
// Variable-width (with a maximum)
|
||||
if (fieldInfo.maxLength) {
|
||||
value = convert_1.stripZeros(value);
|
||||
if (value.length > fieldInfo.maxLength) {
|
||||
var error = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'too long';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
raw.push(convert_1.hexlify(value));
|
||||
});
|
||||
if (transaction.chainId) {
|
||||
raw.push(convert_1.hexlify(transaction.chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
}
|
||||
var digest = keccak256_1.keccak256(RLP.encode(raw));
|
||||
var signature = signDigest(digest);
|
||||
var v = 27 + signature.recoveryParam;
|
||||
if (transaction.chainId) {
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
v += transaction.chainId * 2 + 8;
|
||||
}
|
||||
raw.push(convert_1.hexlify(v));
|
||||
raw.push(signature.r);
|
||||
raw.push(signature.s);
|
||||
return RLP.encode(raw);
|
||||
}
|
||||
exports.sign = sign;
|
||||
function parse(rawTransaction) {
|
||||
var signedTransaction = RLP.decode(rawTransaction);
|
||||
if (signedTransaction.length !== 9) {
|
||||
throw new Error('invalid transaction');
|
||||
}
|
||||
var tx = {
|
||||
nonce: handleNumber(signedTransaction[0]).toNumber(),
|
||||
gasPrice: handleNumber(signedTransaction[1]),
|
||||
gasLimit: handleNumber(signedTransaction[2]),
|
||||
to: handleAddress(signedTransaction[3]),
|
||||
value: handleNumber(signedTransaction[4]),
|
||||
data: signedTransaction[5],
|
||||
chainId: 0
|
||||
};
|
||||
var v = convert_1.arrayify(signedTransaction[6]);
|
||||
var r = convert_1.arrayify(signedTransaction[7]);
|
||||
var s = convert_1.arrayify(signedTransaction[8]);
|
||||
if (v.length >= 1 && r.length >= 1 && r.length <= 32 && s.length >= 1 && s.length <= 32) {
|
||||
tx.v = bignumber_1.bigNumberify(v).toNumber();
|
||||
tx.r = signedTransaction[7];
|
||||
tx.s = signedTransaction[8];
|
||||
var chainId = (tx.v - 35) / 2;
|
||||
if (chainId < 0) {
|
||||
chainId = 0;
|
||||
}
|
||||
chainId = Math.trunc(chainId);
|
||||
tx.chainId = chainId;
|
||||
var recoveryParam = tx.v - 27;
|
||||
var raw = signedTransaction.slice(0, 6);
|
||||
if (chainId) {
|
||||
raw.push(convert_1.hexlify(chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
recoveryParam -= chainId * 2 + 8;
|
||||
}
|
||||
var digest = keccak256_1.keccak256(RLP.encode(raw));
|
||||
try {
|
||||
tx.from = secp256k1_1.recoverAddress(digest, { r: convert_1.hexlify(r), s: convert_1.hexlify(s), recoveryParam: recoveryParam });
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
tx.hash = keccak256_1.keccak256(rawTransaction);
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
exports.parse = parse;
|
2
src/wallet/hdnode.d.ts
vendored
2
src/wallet/hdnode.d.ts
vendored
@ -1,5 +1,5 @@
|
||||
import { KeyPair } from './secp256k1';
|
||||
import { Arrayish } from '../utils/convert';
|
||||
import { KeyPair } from '../utils/secp256k1';
|
||||
export declare class HDNode {
|
||||
private readonly keyPair;
|
||||
readonly privateKey: string;
|
||||
|
@ -9,13 +9,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||
var secp256k1_1 = require("./secp256k1");
|
||||
var words_1 = require("./words");
|
||||
var convert_1 = require("../utils/convert");
|
||||
var bignumber_1 = require("../utils/bignumber");
|
||||
var utf8_1 = require("../utils/utf8");
|
||||
var pbkdf2_1 = require("../utils/pbkdf2");
|
||||
var hmac_1 = require("../utils/hmac");
|
||||
var secp256k1_1 = require("../utils/secp256k1");
|
||||
var sha2_1 = require("../utils/sha2");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
// "Bitcoin seed"
|
||||
|
@ -37,7 +37,7 @@ function recoverPublicKey(digest, signature) {
|
||||
r: convert_1.arrayify(signature.r),
|
||||
s: convert_1.arrayify(signature.s)
|
||||
};
|
||||
return '0x' + curve.recoverPubKey(convert_1.arrayify(digest), sig, signature.recoveryParam).getPublic(false, 'hex');
|
||||
return '0x' + curve.recoverPubKey(convert_1.arrayify(digest), sig, signature.recoveryParam).encode('hex', false);
|
||||
}
|
||||
exports.recoverPublicKey = recoverPublicKey;
|
||||
function computePublicKey(key, compressed) {
|
||||
|
7
src/wallet/signing-key.d.ts
vendored
7
src/wallet/signing-key.d.ts
vendored
@ -1,11 +1,6 @@
|
||||
/**
|
||||
* SigningKey
|
||||
*
|
||||
*
|
||||
*/
|
||||
import { Signature } from './secp256k1';
|
||||
import { Arrayish } from '../utils/convert';
|
||||
import { HDNode } from './hdnode';
|
||||
import { Signature } from '../utils/secp256k1';
|
||||
export declare class SigningKey {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
|
@ -5,12 +5,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
*
|
||||
*
|
||||
*/
|
||||
var secp256k1_1 = require("./secp256k1");
|
||||
var address_1 = require("../utils/address");
|
||||
var convert_1 = require("../utils/convert");
|
||||
var hdnode_1 = require("./hdnode");
|
||||
var keccak256_1 = require("../utils/keccak256");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var secp256k1_1 = require("../utils/secp256k1");
|
||||
var errors = require("../utils/errors");
|
||||
var SigningKey = /** @class */ (function () {
|
||||
function SigningKey(privateKey) {
|
||||
|
55
src/wallet/wallet.d.ts
vendored
55
src/wallet/wallet.d.ts
vendored
@ -1,54 +1,36 @@
|
||||
import { HDNode } from './hdnode';
|
||||
import { ProgressCallback } from './secret-storage';
|
||||
import { SigningKey } from './signing-key';
|
||||
import { BlockTag } from '../providers/provider';
|
||||
import { BlockTag, Provider, TransactionRequest, TransactionResponse } from '../providers/provider';
|
||||
import { BigNumber, BigNumberish } from '../utils/bignumber';
|
||||
import { Arrayish } from '../utils/convert';
|
||||
interface Provider {
|
||||
chainId: number;
|
||||
getBalance(address: string, blockTag: number | string): Promise<BigNumber>;
|
||||
getTransactionCount(address: string, blockTag: number | string): Promise<number>;
|
||||
estimateGas(transaction: any): Promise<BigNumber>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
sendTransaction(Bytes: any): Promise<string>;
|
||||
resolveName(address: string): Promise<string>;
|
||||
waitForTransaction(Bytes32: any): Promise<TransactionResponse>;
|
||||
import { UnsignedTransaction } from '../utils/transaction';
|
||||
export interface Signer {
|
||||
address?: string;
|
||||
getAddress(): Promise<string>;
|
||||
sendTransaction(transaction: UnsignedTransaction): Promise<TransactionResponse>;
|
||||
provider: Provider;
|
||||
sign(transaction: UnsignedTransaction): string;
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
getGasPrice(transaction?: TransactionRequest): Promise<BigNumber>;
|
||||
}
|
||||
interface TransactionRequest {
|
||||
nonce?: number;
|
||||
to?: string;
|
||||
from?: string;
|
||||
data?: string;
|
||||
gasLimit?: BigNumber;
|
||||
gasPrice?: BigNumber;
|
||||
r?: string;
|
||||
s?: string;
|
||||
chainId?: number;
|
||||
v?: number;
|
||||
value?: BigNumber;
|
||||
}
|
||||
interface TransactionResponse extends TransactionRequest {
|
||||
hash?: string;
|
||||
blockHash?: string;
|
||||
block?: number;
|
||||
wait?: (timeout?: number) => Promise<TransactionResponse>;
|
||||
}
|
||||
export declare class Wallet {
|
||||
export declare class Wallet implements Signer {
|
||||
readonly address: string;
|
||||
readonly privateKey: string;
|
||||
private mnemonic;
|
||||
private path;
|
||||
private readonly signingKey;
|
||||
provider: any;
|
||||
provider: Provider;
|
||||
defaultGasLimit: number;
|
||||
constructor(privateKey: SigningKey | HDNode | Arrayish, provider?: Provider);
|
||||
sign(transaction: TransactionRequest): string;
|
||||
static parseTransaction(rawTransaction: Arrayish): TransactionRequest;
|
||||
sign(transaction: UnsignedTransaction): string;
|
||||
getAddress(): Promise<string>;
|
||||
getBalance(blockTag: BlockTag): Promise<BigNumber>;
|
||||
getTransactionCount(blockTag: BlockTag): Promise<number>;
|
||||
getBalance(blockTag?: BlockTag): Promise<BigNumber>;
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
getGasPrice(): Promise<BigNumber>;
|
||||
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
sendTransaction(transaction: any): Promise<TransactionResponse>;
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse>;
|
||||
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse>;
|
||||
static hashMessage(message: Arrayish | string): string;
|
||||
signMessage(message: Arrayish | string): string;
|
||||
@ -60,4 +42,3 @@ export declare class Wallet {
|
||||
static fromMnemonic(mnemonic: string, path?: string): Wallet;
|
||||
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback: ProgressCallback): Promise<Wallet>;
|
||||
}
|
||||
export {};
|
||||
|
@ -14,27 +14,18 @@ var scrypt_js_1 = __importDefault(require("scrypt-js"));
|
||||
var hdnode_1 = require("./hdnode");
|
||||
var secretStorage = __importStar(require("./secret-storage"));
|
||||
var signing_key_1 = require("./signing-key");
|
||||
var address_1 = require("../utils/address");
|
||||
var bignumber_1 = require("../utils/bignumber");
|
||||
var convert_1 = require("../utils/convert");
|
||||
var keccak256_1 = require("../utils/keccak256");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var random_bytes_1 = require("../utils/random-bytes");
|
||||
var RLP = __importStar(require("../utils/rlp"));
|
||||
var transaction_1 = require("../utils/transaction");
|
||||
var utf8_1 = require("../utils/utf8");
|
||||
var errors = __importStar(require("../utils/errors"));
|
||||
// This ensures we inject a setImmediate into the global space, which
|
||||
// dramatically improves the performance of the scrypt PBKDF.
|
||||
console.log("Fix this! Setimmediate");
|
||||
// @TODO: Move to HDNode
|
||||
var defaultPath = "m/44'/60'/0'/0/0";
|
||||
var transactionFields = [
|
||||
{ name: 'nonce', maxLength: 32, },
|
||||
{ name: 'gasPrice', maxLength: 32, },
|
||||
{ name: 'gasLimit', maxLength: 32, },
|
||||
{ name: 'to', length: 20, },
|
||||
{ name: 'value', maxLength: 32, },
|
||||
{ name: 'data' },
|
||||
];
|
||||
// @TODO: Bytes32 or SigningKey
|
||||
var Wallet = /** @class */ (function () {
|
||||
function Wallet(privateKey, provider) {
|
||||
//private _provider;
|
||||
@ -44,146 +35,19 @@ var Wallet = /** @class */ (function () {
|
||||
if (privateKey instanceof signing_key_1.SigningKey) {
|
||||
this.signingKey = privateKey;
|
||||
if (this.signingKey.mnemonic) {
|
||||
Object.defineProperty(this, 'mnemonic', {
|
||||
enumerable: true,
|
||||
value: this.signingKey.mnemonic,
|
||||
writable: false
|
||||
});
|
||||
//this.mnemonic = this.signingKey.mnemonic;
|
||||
this.path = this.signingKey.path;
|
||||
properties_1.defineReadOnly(this, 'mnemonic', privateKey.mnemonic);
|
||||
properties_1.defineReadOnly(this, 'path', privateKey.path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.signingKey = new signing_key_1.SigningKey(privateKey);
|
||||
}
|
||||
this.privateKey = this.signingKey.privateKey;
|
||||
properties_1.defineReadOnly(this, 'privateKey', this.signingKey.privateKey);
|
||||
this.provider = provider;
|
||||
//this.address = this.signingKey.address;
|
||||
Object.defineProperty(this, 'address', {
|
||||
enumerable: true,
|
||||
value: this.signingKey.address,
|
||||
writable: false
|
||||
});
|
||||
properties_1.defineReadOnly(this, 'address', this.signingKey.address);
|
||||
}
|
||||
Wallet.prototype.sign = function (transaction) {
|
||||
var chainId = transaction.chainId;
|
||||
if (chainId == null && this.provider) {
|
||||
chainId = this.provider.chainId;
|
||||
}
|
||||
if (!chainId) {
|
||||
chainId = 0;
|
||||
}
|
||||
var raw = [];
|
||||
transactionFields.forEach(function (fieldInfo) {
|
||||
var value = transaction[fieldInfo.name] || ([]);
|
||||
value = convert_1.arrayify(convert_1.hexlify(value));
|
||||
// Fixed-width field
|
||||
if (fieldInfo.length && value.length !== fieldInfo.length && value.length > 0) {
|
||||
var error = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'wrong length';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
// Variable-width (with a maximum)
|
||||
if (fieldInfo.maxLength) {
|
||||
value = convert_1.stripZeros(value);
|
||||
if (value.length > fieldInfo.maxLength) {
|
||||
var error = new Error('invalid ' + fieldInfo.name);
|
||||
error.reason = 'too long';
|
||||
error.value = value;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
raw.push(convert_1.hexlify(value));
|
||||
});
|
||||
if (chainId) {
|
||||
raw.push(convert_1.hexlify(chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
}
|
||||
var digest = keccak256_1.keccak256(RLP.encode(raw));
|
||||
var signature = this.signingKey.signDigest(digest);
|
||||
var v = 27 + signature.recoveryParam;
|
||||
if (chainId) {
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
raw.pop();
|
||||
v += chainId * 2 + 8;
|
||||
}
|
||||
raw.push(convert_1.hexlify(v));
|
||||
raw.push(signature.r);
|
||||
raw.push(signature.s);
|
||||
return RLP.encode(raw);
|
||||
};
|
||||
/*
|
||||
set provider(provider: Provider) {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
get provider() {
|
||||
return this._provider;
|
||||
}
|
||||
*/
|
||||
Wallet.parseTransaction = function (rawTransaction) {
|
||||
rawTransaction = convert_1.hexlify(rawTransaction);
|
||||
var signedTransaction = RLP.decode(rawTransaction);
|
||||
if (signedTransaction.length !== 9) {
|
||||
throw new Error('invalid transaction');
|
||||
}
|
||||
var raw = [];
|
||||
var transaction = {};
|
||||
transactionFields.forEach(function (fieldInfo, index) {
|
||||
transaction[fieldInfo.name] = signedTransaction[index];
|
||||
raw.push(signedTransaction[index]);
|
||||
});
|
||||
if (transaction.to) {
|
||||
if (transaction.to == '0x') {
|
||||
delete transaction.to;
|
||||
}
|
||||
else {
|
||||
transaction.to = address_1.getAddress(transaction.to);
|
||||
}
|
||||
}
|
||||
['gasPrice', 'gasLimit', 'nonce', 'value'].forEach(function (name) {
|
||||
if (!transaction[name]) {
|
||||
return;
|
||||
}
|
||||
var value = bignumber_1.ConstantZero;
|
||||
if (transaction[name].length > 0) {
|
||||
value = bignumber_1.bigNumberify(transaction[name]);
|
||||
}
|
||||
transaction[name] = value;
|
||||
});
|
||||
transaction.nonce = transaction.nonce.toNumber();
|
||||
var v = convert_1.arrayify(signedTransaction[6]);
|
||||
var r = convert_1.arrayify(signedTransaction[7]);
|
||||
var s = convert_1.arrayify(signedTransaction[8]);
|
||||
if (v.length >= 1 && r.length >= 1 && r.length <= 32 && s.length >= 1 && s.length <= 32) {
|
||||
transaction.v = bignumber_1.bigNumberify(v).toNumber();
|
||||
transaction.r = signedTransaction[7];
|
||||
transaction.s = signedTransaction[8];
|
||||
var chainId = (transaction.v - 35) / 2;
|
||||
if (chainId < 0) {
|
||||
chainId = 0;
|
||||
}
|
||||
chainId = Math.trunc(chainId);
|
||||
transaction.chainId = chainId;
|
||||
var recoveryParam = transaction.v - 27;
|
||||
if (chainId) {
|
||||
raw.push(convert_1.hexlify(chainId));
|
||||
raw.push('0x');
|
||||
raw.push('0x');
|
||||
recoveryParam -= chainId * 2 + 8;
|
||||
}
|
||||
var digest = keccak256_1.keccak256(RLP.encode(raw));
|
||||
try {
|
||||
transaction.from = signing_key_1.recoverAddress(digest, { r: convert_1.hexlify(r), s: convert_1.hexlify(s), recoveryParam: recoveryParam });
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
return transaction;
|
||||
return transaction_1.sign(transaction, this.signingKey.signDigest.bind(this.signingKey));
|
||||
};
|
||||
Wallet.prototype.getAddress = function () {
|
||||
return Promise.resolve(this.address);
|
||||
@ -200,6 +64,12 @@ var Wallet = /** @class */ (function () {
|
||||
}
|
||||
return this.provider.getTransactionCount(this.address, blockTag);
|
||||
};
|
||||
Wallet.prototype.getGasPrice = function () {
|
||||
if (!this.provider) {
|
||||
throw new Error('missing provider');
|
||||
}
|
||||
return this.provider.getGasPrice();
|
||||
};
|
||||
Wallet.prototype.estimateGas = function (transaction) {
|
||||
if (!this.provider) {
|
||||
throw new Error('missing provider');
|
||||
@ -217,59 +87,32 @@ var Wallet = /** @class */ (function () {
|
||||
return this.provider.estimateGas(calculate);
|
||||
};
|
||||
Wallet.prototype.sendTransaction = function (transaction) {
|
||||
var _this = this;
|
||||
if (!this.provider) {
|
||||
throw new Error('missing provider');
|
||||
}
|
||||
if (!transaction || typeof (transaction) !== 'object') {
|
||||
throw new Error('invalid transaction object');
|
||||
}
|
||||
var gasLimit = transaction.gasLimit;
|
||||
if (gasLimit == null) {
|
||||
gasLimit = this.defaultGasLimit;
|
||||
var tx = properties_1.shallowCopy(transaction);
|
||||
if (tx.to != null) {
|
||||
tx.to = this.provider.resolveName(tx.to);
|
||||
}
|
||||
var self = this;
|
||||
var gasPricePromise = null;
|
||||
if (transaction.gasPrice) {
|
||||
gasPricePromise = Promise.resolve(transaction.gasPrice);
|
||||
if (tx.gasLimit == null) {
|
||||
tx.gasLimit = this.estimateGas(tx);
|
||||
}
|
||||
else {
|
||||
gasPricePromise = this.provider.getGasPrice();
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = this.getGasPrice();
|
||||
}
|
||||
var noncePromise = null;
|
||||
if (transaction.nonce) {
|
||||
noncePromise = Promise.resolve(transaction.nonce);
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = this.getTransactionCount();
|
||||
}
|
||||
else {
|
||||
noncePromise = this.provider.getTransactionCount(self.address, 'pending');
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = this.provider.getNetwork().then(function (network) { return network.chainId; });
|
||||
}
|
||||
var chainId = this.provider.chainId;
|
||||
var toPromise = null;
|
||||
if (transaction.to) {
|
||||
toPromise = this.provider.resolveName(transaction.to);
|
||||
}
|
||||
else {
|
||||
toPromise = Promise.resolve(undefined);
|
||||
}
|
||||
var data = convert_1.hexlify(transaction.data || '0x');
|
||||
var value = bignumber_1.ConstantZero;
|
||||
return Promise.all([gasPricePromise, noncePromise, toPromise]).then(function (results) {
|
||||
var signedTransaction = self.sign({
|
||||
to: results[2],
|
||||
data: data,
|
||||
gasLimit: gasLimit,
|
||||
gasPrice: results[0],
|
||||
nonce: results[1],
|
||||
value: value,
|
||||
chainId: chainId
|
||||
});
|
||||
return self.provider.sendTransaction(signedTransaction).then(function (hash) {
|
||||
var transaction = Wallet.parseTransaction(signedTransaction);
|
||||
transaction.hash = hash;
|
||||
transaction.wait = function () {
|
||||
return self.provider.waitForTransaction(hash);
|
||||
};
|
||||
return transaction;
|
||||
});
|
||||
return properties_1.resolveProperties(tx).then(function (tx) {
|
||||
console.log('To Sign', tx);
|
||||
return _this.provider.sendTransaction(_this.sign(tx));
|
||||
});
|
||||
};
|
||||
Wallet.prototype.send = function (addressOrName, amountWei, options) {
|
||||
|
@ -29,15 +29,15 @@ describe('Checksum and ICAP address generation', function() {
|
||||
it(('correctly transforms address - ' + test.name), function() {
|
||||
assert.equal(ethers.utils.getAddress(test.address), test.checksumAddress,
|
||||
'correctly computes checksum address from address');
|
||||
assert.equal(ethers.utils.getAddress(test.address, true), test.icapAddress,
|
||||
assert.equal(ethers.utils.getIcapAddress(test.address), test.icapAddress,
|
||||
'correctly computes ICAP address from address');
|
||||
assert.equal(ethers.utils.getAddress(test.checksumAddress), test.checksumAddress,
|
||||
'correctly computes checksum address from checksum address');
|
||||
assert.equal(ethers.utils.getAddress(test.checksumAddress, true), test.icapAddress,
|
||||
assert.equal(ethers.utils.getIcapAddress(test.checksumAddress), test.icapAddress,
|
||||
'correctly computes ICAP address from checksum address');
|
||||
assert.equal(ethers.utils.getAddress(test.icapAddress), test.checksumAddress,
|
||||
'correctly computes checksum address from icap address');
|
||||
assert.equal(ethers.utils.getAddress(test.icapAddress, true), test.icapAddress,
|
||||
assert.equal(ethers.utils.getIcapAddress(test.icapAddress), test.icapAddress,
|
||||
'correctly computes ICAP address from icap address');
|
||||
});
|
||||
});
|
||||
|
@ -200,7 +200,7 @@ describe('Test Contract Events', function() {
|
||||
|
||||
test.normalizedValues.forEach(function(expected, index) {
|
||||
if (test.indexed[index]) {
|
||||
assert.ok((parsed[index].indexed && parsed[index].hash == null), 'parsed event data has empty Indexed - ' + index);
|
||||
assert.ok((parsed[index].type === 'indexed' && parsed[index].hash == null), 'parsed event data has empty Indexed - ' + index);
|
||||
} else {
|
||||
assert.ok(equals(parsed[index], expected), 'parsed event data matches - ' + index);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ function equals(name, actual, expected) {
|
||||
|
||||
if (typeof(actual) === 'object') {
|
||||
if (expected.indexed) {
|
||||
assert.ok(!!actual.indexed, 'index property has index - ' + name);
|
||||
assert.ok(actual.type === 'indexed', 'index property has index - ' + name);
|
||||
if (expected.hash) {
|
||||
assert.equal(actual.hash, expected.hash, 'index property with known hash matches - ' + name);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ describe('Test Transaction Signing and Parsing', function() {
|
||||
|
||||
var transaction = {};
|
||||
|
||||
var parsedTransaction = Wallet.parseTransaction(test.signedTransaction);
|
||||
var parsedTransaction = ethers.utils.parseTransaction(test.signedTransaction);
|
||||
|
||||
['nonce', 'gasLimit', 'gasPrice', 'to', 'value', 'data'].forEach(function(key) {
|
||||
var expected = test[key];
|
||||
@ -139,7 +139,7 @@ describe('Test Transaction Signing and Parsing', function() {
|
||||
|
||||
// EIP155
|
||||
|
||||
var parsedTransactionChainId5 = Wallet.parseTransaction(test.signedTransactionChainId5);
|
||||
var parsedTransactionChainId5 = ethers.utils.parseTransaction(test.signedTransactionChainId5);
|
||||
['data', 'from', 'nonce', 'to'].forEach(function (key) {
|
||||
assert.equal(parsedTransaction[key], parsedTransactionChainId5[key],
|
||||
'eip155 parsed ' + key);
|
||||
|
Loading…
Reference in New Issue
Block a user