Fixed sendTransaction for JsonRpcSigner.

This commit is contained in:
Richard Moore 2018-06-26 18:37:21 -04:00
parent 0b35f1959a
commit 8a340c8ff3
No known key found for this signature in database
GPG Key ID: 525F70A6FCABC295
4 changed files with 102 additions and 48 deletions

View File

@ -118,7 +118,7 @@ var JsonRpcSigner = /** @class */ (function (_super) {
};
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
var _this = this;
var tx = hexlifyTransaction(transaction);
var tx = properties_1.shallowCopy(transaction);
if (tx.from == null) {
tx.from = this.getAddress().then(function (address) {
if (!address) {
@ -128,7 +128,28 @@ var JsonRpcSigner = /** @class */ (function (_super) {
});
}
return properties_1.resolveProperties(tx).then(function (tx) {
return _this.provider.send('eth_sendTransaction', [tx]);
tx = hexlifyTransaction(tx);
return _this.provider.send('eth_sendTransaction', [tx]).then(function (hash) {
// @TODO: Make a pollProperty method in utils
return new Promise(function (resolve, reject) {
var count = 0;
var check = function () {
_this.provider.getTransaction(hash).then(function (tx) {
if (tx == null) {
if (count++ > 500) {
// @TODO: Better error
reject(new Error('could not find transaction'));
return;
}
setTimeout(check, 200);
return;
}
resolve(_this.provider._wrapTransaction(tx.raw, hash));
});
};
setTimeout(check, 50);
});
});
});
};
JsonRpcSigner.prototype.signMessage = function (message) {

View File

@ -244,6 +244,7 @@ function checkTransactionResponse(transaction) {
if (transaction.to == null && transaction.creates == null) {
transaction.creates = address_1.getContractAddress(transaction);
}
// @TODO: use transaction.serialize? Have to add support for including v, r, and s...
if (!transaction.raw) {
// Very loose providers (e.g. TestRPC) don't provide a signature or raw
if (transaction.v && transaction.r && transaction.s) {
@ -797,31 +798,35 @@ var Provider = /** @class */ (function () {
var signedTransaction = _a.signedTransaction;
var params = { signedTransaction: bytes_1.hexlify(signedTransaction) };
return _this.perform('sendTransaction', params).then(function (hash) {
if (bytes_1.hexDataLength(hash) !== 32) {
throw new Error('invalid response - sendTransaction');
}
// 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).then(function (receipt) {
if (receipt.status === 0) {
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
transaction: tx
});
}
return receipt;
});
};
return tx;
return _this._wrapTransaction(signedTransaction, hash);
});
});
});
};
Provider.prototype._wrapTransaction = function (signedTransaction, hash) {
var _this = this;
if (bytes_1.hexDataLength(hash) !== 32) {
throw new Error('invalid response - sendTransaction');
}
// 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).then(function (receipt) {
if (receipt.status === 0) {
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
transaction: tx
});
}
return receipt;
});
};
return tx;
};
Provider.prototype.call = function (transaction) {
var _this = this;
var tx = properties_1.shallowCopy(transaction);

View File

@ -9,7 +9,7 @@ import { Signer } from '../wallet/wallet';
import { getAddress } from '../utils/address';
import { BigNumber } from '../utils/bignumber';
import { Arrayish, hexlify, hexStripZeros } from '../utils/bytes';
import { defineReadOnly, resolveProperties } from '../utils/properties';
import { defineReadOnly, resolveProperties, shallowCopy } from '../utils/properties';
import { toUtf8Bytes } from '../utils/utf8';
import { ConnectionInfo, fetchJson } from '../utils/web';
@ -109,7 +109,7 @@ export class JsonRpcSigner extends Signer {
}
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
let tx = hexlifyTransaction(transaction);
let tx = shallowCopy(transaction);
if (tx.from == null) {
tx.from = this.getAddress().then((address) => {
@ -119,7 +119,28 @@ export class JsonRpcSigner extends Signer {
}
return resolveProperties(tx).then((tx) => {
return this.provider.send('eth_sendTransaction', [ tx ]);
tx = hexlifyTransaction(tx);
return this.provider.send('eth_sendTransaction', [ tx ]).then((hash) => {
// @TODO: Make a pollProperty method in utils
return new Promise((resolve: (result: TransactionResponse) => void, reject) => {
let count = 0;
let check = () => {
this.provider.getTransaction(hash).then((tx: TransactionResponse) => {
if (tx == null) {
if (count++ > 500) {
// @TODO: Better error
reject(new Error('could not find transaction'));
return;
}
setTimeout(check, 200);
return;
}
resolve(this.provider._wrapTransaction(tx.raw, hash));
});
}
setTimeout(check, 50);
});
});
});
}

View File

@ -62,6 +62,9 @@ export interface TransactionResponse extends Transaction {
// Not optional (as it is in Transaction)
from: string;
// The raw transaction
raw?: string,
// This function waits until the transaction has been mined
wait: (timeout?: number) => Promise<TransactionReceipt>
};
@ -350,6 +353,7 @@ export function checkTransactionResponse(transaction: any): TransactionResponse
transaction.creates = getContractAddress(transaction);
}
// @TODO: use transaction.serialize? Have to add support for including v, r, and s...
if (!transaction.raw) {
// Very loose providers (e.g. TestRPC) don't provide a signature or raw
if (transaction.v && transaction.r && transaction.s) {
@ -960,33 +964,36 @@ export class Provider {
return resolveProperties({ signedTransaction: signedTransaction }).then(({ signedTransaction }) => {
var params = { signedTransaction: hexlify(signedTransaction) };
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).then((receipt) => {
if (receipt.status === 0) {
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
transaction: tx
});
}
return receipt;
});
};
return tx;
return this._wrapTransaction(signedTransaction, hash);
});
});
});
}
_wrapTransaction(signedTransaction: string, hash?: string): TransactionResponse {
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).then((receipt) => {
if (receipt.status === 0) {
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
transaction: tx
});
}
return receipt;
});
};
return tx;
}
call(transaction: TransactionRequest): Promise<string> {
let tx: TransactionRequest = shallowCopy(transaction);