UNPKG

@pokt-network/web3-provider

Version:
192 lines (191 loc) 5.57 kB
/** * @author Pabel Nunez Landestoy <pabel@pokt.network> */ const pocket_core = require('@pokt-network/pocket-js') const Pocket = pocket_core.Pocket const typeGuard = pocket_core.typeGuard const Hex = pocket_core.Hex const RpcError = pocket_core.RpcError /** * Pocket Web3 Provider * Sends Relays to the Pocket Network * @constructor * @param {string} activeBlockchain - Target blockchain hash. * @param {PocketAAT} pocketAAT - Pocket Authentication Token object. * @param {Pocket} pocket - Pocket instance. * @param {Object} transactionSigner - Object containing the TransactionSigner interface methods. */ class PocketProvider { constructor(activeBlockchain, pocketAAT, pocket, transactionSigner) { this.pocket = pocket this.activeBlockchain = activeBlockchain this.pocketAAT = pocketAAT this.transactionSigner = transactionSigner this.isConnected = true if (!this.isValid()) { throw new Error("Invalid PocketProvider properties."); } } /** * activeBlockchain property setter * @method setActiveBlockchain * @param {string} - Blockchain hex representation. * @memberof PocketProvider */ set setActiveBlockchain(blockchain) { if (blockchain.length !== 0 && Hex.isHex(blockchain)) { this.activeBlockchain = blockchain } } /** * * @method send * @param {{}} payload - Object containing the payload. * @returns {RelayResponse} - Relay response object. * @memberof PocketProvider */ async send(payload, callback) { // Check the relay request const relayData = await this._generateRelayData(payload) if (typeGuard(relayData, Error)) { throw relayData } try { // Send relay to the network const result = await this.pocket.sendRelay( JSON.stringify(relayData), this.activeBlockchain, this.pocketAAT, ) // Handle the result if is an Error if (typeGuard(result, RpcError)) { this.isConnected = false // Return error result if (callback) { callback(result) return } return result } // Result is SendResponse if (callback) { callback(null, JSON.parse(result.payload)) return } // return if async return JSON.parse(result.payload) } catch (error) { this.isConnected = false if (callback) { callback(new RpcError.fromError(error)) return } // return if async return new RpcError.fromError(error) } } /** * Verifies the Pocket Provider minimum requirements * @method isValid * @memberof PocketProvider */ isValid() { return this.activeBlockchain.length !== 0 && this.pocketAAT.isValid() } /** * Method to get the nonce for a given address * @method _getNonce * @param {string} sender - Sender's address. * @returns {RelayResponse} - A relay response object. * @memberof PocketProvider */ async _getNonce(sender) { const data = { "id": new Date().getTime(), "jsonrpc": "2.0", "method": "eth_getTransactionCount", "params": [sender, "latest"] } try { const response = await this.send(data) if (typeGuard(response, RpcError)) { return response } return response.result } catch (error) { return error } } /** * Method to generate the relay data according to the given JSON-RPC payload * @method _generateRelayData * @param {any} relay - Provided relay payload object. * @returns {any} - Relay request data object. * @memberof PocketProvider */ async _generateRelayData(payload) { try { // Retrieve method from payload const method = payload.method // Check rpc method if (method !== undefined && method === "eth_sendTransaction") { const relayData = await this._parseRelayParams(payload) return relayData } else { return payload } } catch { return payload } } /** * Method to parse the relay payload * @method _parseRelayParams * @param {RelayPayload} payload - Relay payload object. * @returns {RelayRequest} - Relay request. * @memberof PocketProvider */ async _parseRelayParams(payload) { const txParams = payload.params[0] const sender = txParams.from // Verify address exists in the TransactionSigner if (this.transactionSigner === undefined) { return new Error( "Error: TransactionSigner is undefined" ) } const hasAddress = await this.transactionSigner.hasAddress(sender) // Handle errors if (hasAddress === false || hasAddress === undefined) { return new Error("Address doesn't exist in the provided transactionSigner") } let nonce // Get the nonce for the sender if (txParams.nonce) { nonce = txParams.nonce }else { nonce = await this._getNonce(sender) } // Handle errors if (typeGuard(nonce, RpcError)) { return nonce } // Assign the nonce value to the tx params txParams.nonce = nonce // Signs the transaction with the updated nonce const signedTx = await this.transactionSigner.signTransaction(txParams) if (typeGuard(signedTx, Error)) { return signedTx } // Create relay data object const relayData = { "id": payload.id, "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [signedTx] } return relayData } } module.exports.PocketProvider = PocketProvider