@omisego/omg-js-childchain
Advanced tools
Comparing version 3.0.0-alpha.10 to 3.0.0-alpha.12
{ | ||
"name": "@omisego/omg-js-childchain", | ||
"version": "3.0.0-alpha.10", | ||
"version": "3.0.0-alpha.12", | ||
"description": "Module to interact with OMG ChildChain", | ||
@@ -27,5 +27,7 @@ "keywords": [ | ||
"dependencies": { | ||
"@omisego/omg-js-util": "^3.0.0-alpha.10", | ||
"@hapi/joi": "^16.1.8", | ||
"@omisego/omg-js-util": "^3.0.0-alpha.12", | ||
"bn.js": "^5.0.0", | ||
"debug": "^4.0.1", | ||
"json-bigint": "^0.3.0", | ||
"json-bigint": "git+https://git@github.com/omisego/json-bigint.git", | ||
"request": "^2.88.0", | ||
@@ -38,3 +40,3 @@ "request-promise-native": "^1.0.7", | ||
}, | ||
"gitHead": "7de6ec5c4fcc2492cbc16b1b008ff7798c1f37d1" | ||
"gitHead": "9e38443a3e8d9b8aedf56155acf4bb0eb3c71e4b" | ||
} |
@@ -16,5 +16,21 @@ /* | ||
const { | ||
childchainConstructorSchema, | ||
getUtxosSchema, | ||
getBalanceSchema, | ||
getTransactionsSchema, | ||
getExitDataSchema, | ||
createTransactionSchema, | ||
signTypedDataSchema, | ||
submitTypedSchema, | ||
signTransactionSchema, | ||
buildSignedTransactionSchema, | ||
sendTransactionSchema, | ||
inFlightExitGetOutputChallengeDataSchema, | ||
inFlightExitGetInputChallengeDataSchema | ||
} = require('./validators') | ||
const Joi = require('@hapi/joi') | ||
const rpcApi = require('./rpc/rpcApi') | ||
const rlp = require('rlp') | ||
const { InvalidArgumentError, transaction, sign, hexPrefix } = require('@omisego/omg-js-util') | ||
const { transaction, sign, hexPrefix } = require('@omisego/omg-js-util') | ||
global.Buffer = global.Buffer || require('buffer').Buffer | ||
@@ -26,8 +42,10 @@ | ||
* | ||
*@param {string} watcherUrl the url of the watcher server | ||
*@param {string} [watcherProxyUrl] *optional* the proxy url for requests made to the watcher server | ||
*@return {Object} ChildChain Object | ||
* @param {Object} config the rootchain configuration object | ||
* @param {string} config.watcherUrl the url of the watcher server (running in security-critical and informational mode) | ||
* @param {string} [config.watcherProxyUrl] *optional* the proxy url for requests made to the watcher server | ||
* @return {ChildChain} a ChildChain Object | ||
* | ||
*/ | ||
constructor ({ watcherUrl, watcherProxyUrl }) { | ||
Joi.assert({ watcherUrl, watcherProxyUrl }, childchainConstructorSchema) | ||
this.watcherUrl = watcherUrl | ||
@@ -41,7 +59,7 @@ this.watcherProxyUrl = watcherProxyUrl | ||
* @method getUtxos | ||
* @param {string} address | ||
* @return {Array} array of UTXOs | ||
* @param {string} address address to check | ||
* @return {Promise<UTXO[]>} promise that resolves with an array of UTXOs | ||
*/ | ||
async getUtxos (address) { | ||
validateAddress(address) | ||
Joi.assert(address, getUtxosSchema) | ||
return rpcApi.post({ | ||
@@ -58,7 +76,7 @@ url: `${this.watcherUrl}/account.get_utxos`, | ||
* @method getBalance | ||
* @param {string} address | ||
* @return {Array} array of balances (one per currency) | ||
* @param {string} address address to check | ||
* @return {Promise<Balance[]>} promise that resolves with an array of balances (one per currency) | ||
*/ | ||
async getBalance (address) { | ||
validateAddress(address) | ||
Joi.assert(address, getBalanceSchema) | ||
return rpcApi.post({ | ||
@@ -75,6 +93,7 @@ url: `${this.watcherUrl}/account.get_balance`, | ||
* @method getTransaction | ||
* @param {object} id The hash of the transaction to get | ||
* @return {Array} array of transactions | ||
* @param {string} id the hash of the transaction to get | ||
* @return {Promise<TransactionData>} promise that resolves with a transaction | ||
*/ | ||
async getTransaction (id) { | ||
Joi.assert(id, Joi.string().required()) | ||
return rpcApi.post({ | ||
@@ -91,6 +110,12 @@ url: `${this.watcherUrl}/transaction.get`, | ||
* @method getTransactions | ||
* @param {object} filters Filter the results by `address`, `blknum` and `limit` | ||
* @return {Array} array of transactions | ||
* @param {Object} filters filter object | ||
* @param {string} [filters.address] address to filter by | ||
* @param {string} [filters.metadata] metadata to filter by | ||
* @param {number} [filters.blknum] blknum to filter by | ||
* @param {number} [filters.limit] max number of transactions to return | ||
* @param {number} [filters.page] page of paginated request | ||
* @return {Promise<TransactionData[]>} promise that resolves with an array of transactions | ||
*/ | ||
async getTransactions (filters) { | ||
Joi.assert(filters, getTransactionsSchema) | ||
return rpcApi.post({ | ||
@@ -107,11 +132,11 @@ url: `${this.watcherUrl}/transaction.all`, | ||
* @method getExitData | ||
* @param {Object} utxo | ||
* @return {string} exit data for the UTXO | ||
* @param {UTXO} utxo utxo object | ||
* @return {Promise<ExitData>} promise that resolves with the exit data for the UTXO | ||
*/ | ||
async getExitData (utxo) { | ||
// Calculate the utxoPos | ||
Joi.assert(utxo, getExitDataSchema) | ||
const utxoPos = transaction.encodeUtxoPos(utxo) | ||
return rpcApi.post({ | ||
url: `${this.watcherUrl}/utxo.get_exit_data`, | ||
body: { utxo_pos: Number(utxoPos.toString()) }, | ||
body: { utxo_pos: utxoPos }, | ||
proxyUrl: this.watcherProxyUrl | ||
@@ -125,9 +150,10 @@ }) | ||
* @method getChallengeData | ||
* @param {Object} utxo | ||
* @return {string} challenge data for the UTXO | ||
* @param {number} utxoPos utxo position | ||
* @return {Promise<Object>} promise that resolves with the challenge data | ||
*/ | ||
async getChallengeData (utxoPos) { | ||
Joi.assert(utxoPos, Joi.number().required()) | ||
return rpcApi.post({ | ||
url: `${this.watcherUrl}/utxo.get_challenge_data`, | ||
body: { utxo_pos: Number(utxoPos.toString()) }, | ||
body: { utxo_pos: utxoPos }, | ||
proxyUrl: this.watcherProxyUrl | ||
@@ -141,9 +167,11 @@ }) | ||
* @method createTransaction | ||
* @param {string} owner | ||
* @param {Array} payments | ||
* @param {Object} fee | ||
* @param {string} metadata | ||
* @return {Object} a object containing the list of transactions that will fullfil the required spend. | ||
* @param {Object} args an arguments object | ||
* @param {string} args.owner owner of the input utxos | ||
* @param {Object[]} args.payments payments made as outputs | ||
* @param {Object} [args.fee] fee paid | ||
* @param {string} [args.metadata] metadata to include in the transaction | ||
* @return {Promise<Object>} promise that resolves with an object containing the list of transactions that will fullfil the required spend | ||
*/ | ||
createTransaction ({ owner, payments, fee, metadata }) { | ||
Joi.assert({ owner, payments, fee, metadata }, createTransactionSchema) | ||
return rpcApi.post({ | ||
@@ -161,10 +189,9 @@ url: `${this.watcherUrl}/transaction.create`, | ||
* @param {Object} txData the transaction data that is returned from `createTransaction` | ||
* @param {Array} privateKeys An array of private keys to sign the inputs of the transaction | ||
* @param {string[]} privateKeys an array of private keys to sign the inputs of the transaction | ||
* @return {Object} a transaction typed data, including the signatures. This can be passed in to `submitTyped` | ||
*/ | ||
signTypedData (txData, privateKeys) { | ||
// Sign the transaction | ||
Joi.assert({ txData, privateKeys }, signTypedDataSchema) | ||
const toSign = Buffer.from(txData.sign_hash.replace('0x', ''), 'hex') | ||
txData.typed_data.signatures = sign(toSign, privateKeys) | ||
return txData.typed_data | ||
@@ -178,5 +205,6 @@ } | ||
* @param {Object} data can be obtained by calling `signTypedData` | ||
* @return {Object} a transaction | ||
* @return {Promise<Object>} promise that resolves with a transaction | ||
*/ | ||
submitTyped (data) { | ||
Joi.assert(data, submitTypedSchema) | ||
return rpcApi.post({ | ||
@@ -193,7 +221,8 @@ url: `${this.watcherUrl}/transaction.submit_typed`, | ||
* @method signTransaction | ||
* @param {string} typedData The typedData of the transaction, as returned by transaction.getTypedData() | ||
* @param {Array} privateKeys An array of private keys to sign the inputs of the transaction | ||
* @return {Array} array of signatures | ||
* @param {Object} typedData the typedData of the transaction, as returned by transaction.getTypedData() | ||
* @param {string[]} privateKeys an array of private keys to sign the inputs of the transaction | ||
* @return {string[]} array of signatures | ||
*/ | ||
signTransaction (typedData, privateKeys) { | ||
Joi.assert({ typedData, privateKeys }, signTransactionSchema) | ||
const toSign = transaction.getToSignHash(typedData) | ||
@@ -207,12 +236,10 @@ return sign(toSign, privateKeys) | ||
* @method buildSignedTransaction | ||
* @param {string} txData The typedData of the transaction, as returned by transaction.getTypedData | ||
* @param {Array} signatures An array of signatures, one for each input spent by the transaction | ||
* @return {string} signed transaction | ||
* @param {Object} typedData the typedData of the transaction, as returned by transaction.getTypedData | ||
* @param {string[]} signatures an array of signatures, one for each input spent by the transaction | ||
* @return {string} a signed transaction | ||
*/ | ||
buildSignedTransaction (txData, signatures) { | ||
// Convert the data to an array | ||
const txArray = transaction.toArray(txData.message) | ||
// Prepend the signatures | ||
const signedTx = [signatures, txData.message.txType, ...txArray] | ||
// rlp-encode the transaction + signatures | ||
buildSignedTransaction (typedData, signatures) { | ||
Joi.assert({ typedData, signatures }, buildSignedTransactionSchema) | ||
const txArray = transaction.toArray(typedData.message) | ||
const signedTx = [signatures, typedData.message.txType, ...txArray] | ||
return hexPrefix(rlp.encode(signedTx).toString('hex')) | ||
@@ -226,6 +253,6 @@ } | ||
* @param {string} transaction the encoded signed transaction, as returned by buildSignedTransaction | ||
* @return {Object} the submitted transaction | ||
* @return {Promise<Object>} promise that resolves with the submitted transaction | ||
*/ | ||
async submitTransaction (transaction) { | ||
// validateTxBody(transactionBody) | ||
Joi.assert(transaction, Joi.string().required()) | ||
return rpcApi.post({ | ||
@@ -239,14 +266,17 @@ url: `${this.watcherUrl}/transaction.submit`, | ||
/** | ||
* create, sign, build and submit a transaction to the childchain using raw privatekey | ||
* Create, sign, build and submit a transaction to the childchain using raw privatekey | ||
* | ||
* @method sendTransaction | ||
* @param {Array} fromAddress - the address of the sender | ||
* @param {Array} fromUtxos - array of utxos to spend | ||
* @param {Array} fromPrivateKeys - private keys of the utxos to spend | ||
* @param {string} toAddress - the address of the recipient | ||
* @param {number} toAmount - amount to transact | ||
* @param {string} currency - address of the erc20 contract (or transaction.ETH_CURRENCY for ETH) | ||
* @param {string} metadata - the metadata to include in the transaction. Must be a 32-byte hex string | ||
* @param {string} verifyingContract - address of the RootChain contract | ||
* @return {Object} the submitted transaction | ||
* @param {Object} args an arguments object | ||
* @param {string} args.fromAddress the address of the sender | ||
* @param {Object[]} args.fromUtxos array of utxos to spend | ||
* @param {string[]} args.fromPrivateKeys private keys of the utxos to spend | ||
* @param {string} args.toAddress the address of the recipient | ||
* @param {number} args.toAmount amount to transact | ||
* @param {string} args.currency address of the erc20 contract (or transaction.ETH_CURRENCY for ETH) | ||
* @param {string} args.metadata the metadata to include in the transaction. Must be a 32-byte hex string | ||
* @param {string} args.verifyingContract address of the RootChain contract | ||
* @param {number} args.feeAmount amount of fee to pay | ||
* @param {string} args.feeCurrency currency of the fee | ||
* @return {Promise<Object>} promise that resolves with the submitted transaction | ||
*/ | ||
@@ -265,7 +295,14 @@ async sendTransaction ({ | ||
}) { | ||
validateAddress(fromAddress) | ||
validateAddress(toAddress) | ||
validatePrivateKey(fromPrivateKeys) | ||
// create the transaction body | ||
Joi.assert({ | ||
fromAddress, | ||
fromUtxos, | ||
fromPrivateKeys, | ||
toAddress, | ||
toAmount, | ||
currency, | ||
metadata, | ||
verifyingContract, | ||
feeAmount, | ||
feeCurrency | ||
}, sendTransactionSchema) | ||
const txBody = transaction.createTransactionBody( | ||
@@ -280,10 +317,6 @@ fromAddress, | ||
feeCurrency | ||
) | ||
const typedData = transaction.getTypedData(txBody, verifyingContract) | ||
// Sign it | ||
const signatures = this.signTransaction(typedData, fromPrivateKeys) | ||
// Build the signed transaction | ||
const signedTx = this.buildSignedTransaction(typedData, signatures) | ||
// submit transaction | ||
return this.submitTransaction(signedTx) | ||
@@ -293,7 +326,7 @@ } | ||
/** | ||
* Returns the current status of the Watcher. | ||
* Should be called periodically to see if there are any byzantine_events to be acted on. | ||
* Returns the current status of the Watcher | ||
* Should be called periodically to see if there are any byzantine_events to be acted on | ||
* | ||
* @method status | ||
* @return {Object} | ||
* @return {Promise<Object>} promise that resolves with the status | ||
*/ | ||
@@ -309,3 +342,3 @@ async status () { | ||
/** | ||
* Gets the data to challenge an invalid input piggybacked on an in-flight exit. | ||
* Gets the data to challenge an invalid input piggybacked on an in-flight exit | ||
* | ||
@@ -315,5 +348,6 @@ * @method inFlightExitGetInputChallengeData | ||
* @param {number} inputIndex invalid input index | ||
* @return {Object} input challenge data for the in-flight transaction | ||
* @return {Promise<Object>} promise that resolves with input challenge data for the in-flight transaction | ||
*/ | ||
async inFlightExitGetInputChallengeData (txbytes, inputIndex) { | ||
Joi.assert({ txbytes, inputIndex }, inFlightExitGetInputChallengeDataSchema) | ||
return rpcApi.post({ | ||
@@ -335,5 +369,6 @@ url: `${this.watcherUrl}/in_flight_exit.get_input_challenge_data`, | ||
* @param {number} outputIndex invalid output index | ||
* @return {Object} input challenge data for the in-flight transaction | ||
* @return {Promise<Object>} promise that resolves with the input challenge data for the in-flight transaction | ||
*/ | ||
async inFlightExitGetOutputChallengeData (txbytes, outputIndex) { | ||
Joi.assert({ txbytes, outputIndex }, inFlightExitGetOutputChallengeDataSchema) | ||
return rpcApi.post({ | ||
@@ -354,5 +389,6 @@ url: `${this.watcherUrl}/in_flight_exit.get_output_challenge_data`, | ||
* @param {string} txbytes the hex-encoded transaction | ||
* @return {Object} exit data for the in-flight transaction | ||
* @return {Promise<Object>} promise that resolves with exit data for the in-flight transaction | ||
*/ | ||
async inFlightExitGetData (txbytes) { | ||
Joi.assert(txbytes, Joi.string().required()) | ||
return rpcApi.post({ | ||
@@ -370,5 +406,6 @@ url: `${this.watcherUrl}/in_flight_exit.get_data`, | ||
* @param {string} txbytes the hex-encoded transaction | ||
* @return {Object} a competitor to the in-flight transaction | ||
*/ | ||
* @return {Promise<Object>} promise that resolves with a competitor to the in-flight transaction | ||
*/ | ||
async inFlightExitGetCompetitor (txbytes) { | ||
Joi.assert(txbytes, Joi.string().required()) | ||
return rpcApi.post({ | ||
@@ -382,9 +419,10 @@ url: `${this.watcherUrl}/in_flight_exit.get_competitor`, | ||
/** | ||
* Proves that a transaction has been put into a block (and therefore is canonical). | ||
* Proves that a transaction has been put into a block (and therefore is canonical) | ||
* | ||
* @method inFlightExitProveCanonical | ||
* @param {string} txbytes the hex-encoded transaction | ||
* @return {Object} the inclusion proof of the transaction | ||
* @return {Promise<Object>} promise that resolves with the inclusion proof of the transaction | ||
*/ | ||
async inFlightExitProveCanonical (txbytes) { | ||
Joi.assert(txbytes, Joi.string().required()) | ||
return rpcApi.post({ | ||
@@ -398,18 +436,2 @@ url: `${this.watcherUrl}/in_flight_exit.prove_canonical`, | ||
function validatePrivateKey (arg) { | ||
// TODO | ||
const valid = true | ||
if (!valid) { | ||
throw new InvalidArgumentError() | ||
} | ||
} | ||
function validateAddress (arg) { | ||
// TODO | ||
const valid = true | ||
if (!valid) { | ||
throw new InvalidArgumentError() | ||
} | ||
} | ||
module.exports = ChildChain |
@@ -67,4 +67,3 @@ /* | ||
} catch (err) { | ||
console.warn(err) | ||
throw new Error('Unknown server error') | ||
throw new Error(`Unable to parse response from server: ${err}`) | ||
} | ||
@@ -71,0 +70,0 @@ debug(`rpc response is ${JSON.stringify(json)}`) |
@@ -111,3 +111,3 @@ /* | ||
}) | ||
const res = await childchainWithProxy.getTransaction(3) | ||
const res = await childchainWithProxy.getTransaction('0x123') | ||
const expectedCall = { | ||
@@ -117,3 +117,3 @@ method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ id: 3, jsonrpc: '2.0' }), | ||
body: JSON.stringify({ id: '0x123', jsonrpc: '2.0' }), | ||
proxy: proxyUrl, | ||
@@ -128,3 +128,3 @@ rejectUnauthorized: false | ||
const childchainNoProxy = new ChildChain({ watcherUrl }) | ||
const res = await childchainNoProxy.getTransaction(4) | ||
const res = await childchainNoProxy.getTransaction('0xabc') | ||
const expectedCall = { | ||
@@ -134,3 +134,3 @@ method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ id: 4, jsonrpc: '2.0' }) | ||
body: JSON.stringify({ id: '0xabc', jsonrpc: '2.0' }) | ||
} | ||
@@ -137,0 +137,0 @@ assert.equal(res, 'foobar') |
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable and can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
39946
10
815
8
1
+ Added@hapi/joi@^16.1.8
+ Addedbn.js@^5.0.0
+ Added@hapi/address@2.1.4(transitive)
+ Added@hapi/formula@1.2.0(transitive)
+ Added@hapi/hoek@8.5.1(transitive)
+ Added@hapi/joi@16.1.8(transitive)
+ Added@hapi/pinpoint@1.0.2(transitive)
+ Added@hapi/topo@3.1.6(transitive)
- Removedbignumber.js@9.1.2(transitive)
- Removedjson-bigint@0.3.1(transitive)
Updatedjson-bigint@git+https://git@github.com/omisego/json-bigint.git