Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #430 from klaytn/release/v1.6.0
Browse files Browse the repository at this point in the history
[Master] release/v1.6.0 QA Sign-off
  • Loading branch information
jimni1222 authored Mar 15, 2021
2 parents 3068324 + f835936 commit f9d5d42
Show file tree
Hide file tree
Showing 23 changed files with 3,098 additions and 17 deletions.
22 changes: 22 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ defaults: &defaults
docker:
- image: kjhman21/node:10.15.3-mocha

orbs:
cypress: cypress-io/[email protected]

jobs:
test:
<<: *defaults
Expand All @@ -19,6 +22,25 @@ jobs:
- run:
name: "Run test code"
command: npm test
- run:
name: "Run test on Web env"
command: |
sudo apt update
sudo apt-get install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
cd ./test/test-web
./prepareWebTest.sh
npm run cypress:run
./terminateTest.sh
cypress/run:
<<: *defaults
steps:
- checkout
- run:
name: "Run test on Web env"
command: |
cd ./test/test-web
./prepareWebTest.sh
./runWebEnvTest.sh
tag_verify:
<<: *defaults
Expand Down
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ node_modules/
package-lock.json
.git
dist/*
caver-cli
caver-cli
test/test-web/*
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ module.exports = {
'guard-for-in': 0,
'prefer-spread': 0,
'global-require': 0,
'no-multi-assign': 0,
'no-await-in-loop': 0,
'no-control-regex': 0,
'object-shorthand': 0,
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "caver-js",
"version": "1.5.7",
"version": "1.6.0",
"description": "caver-js is a JavaScript API library that allows developers to interact with a Klaytn node",
"main": "index.js",
"scripts": {
Expand All @@ -9,13 +9,13 @@
"build": "./node_modules/.bin/webpack --mode production",
"lint": "./node_modules/.bin/eslint './**/*.js'",
"lintFix": "./node_modules/.bin/eslint './**/*.js' --fix",
"serTest": "mocha test/transactionType/serializationTest.js && mocha test/compressionPublicKey.js && mocha test/encodeContractDeploy.js && mocha test/parseAccountKey.js && mocha test/decodeTransaction.js",
"serTest": "mocha test/transactionType/serializationTest.js && mocha test/compressionPublicKey.js && mocha test/encodeContractDeploy.js && mocha test/parseAccountKey.js && mocha test/decodeTransaction.js && mocha ./test/abi.encodeParameter.js && mocha ./test/abi.decodeParameter.js && mocha ./test/abi.decodeLog.js",
"accountTest": "mocha test/packages/caver.account.js && mocha test/packages/caver.account.accountKey.js",
"walletTest": "mocha test/packages/caver.wallet.js && mocha test/packages/caver.wallet.keyring.js && mocha test/accountLib.js && mocha test/accounts.privateKeyToPublicKey.js && mocha test/accounts.recover.js && mocha test/packages/caver.klay.accounts.js && mocha test/isValidPrivateKey.js && mocha test/privateKeyToAccount.js",
"rpcTest": "mocha test/packages/caver.rpc.js",
"transactionTest": "mocha test/packages/caver.transaction/*.js",
"txTest": "mocha test/methodErrorHandling.js && mocha test/sendSignedTransaction.js && mocha test/estimateComputationCost.js && mocha test/getTransactionReceipt.js && mocha test/setNonceWithPendingTag.js && mocha test/getTransaction.js && mocha test/setContractOptions.js && mocha test/encodeContractDeploy.js && mocha test/accounts.signTransaction.js && mocha test/sendTransactionCallback.js && mocha test/signWithMultiSig.js && mocha test/transactionType/legacyTransaction.js && mocha test/transactionType/valueTransfer* && mocha test/transactionType/accountUpdate.js && mocha test/transactionType/contract* && mocha test/transactionType/cancelTransaction.js && mocha test/transactionType/feeDelegated*",
"etcTest": "mocha ./test/contract.setWallet.js && mocha ./test/setRequestManager.js && mocha test/contractError.js && mocha test/reconnectTest.js && mocha test/packages/caver.utils.js && mocha test/confirmationListener.js && mocha test/hashMessage.js && mocha test/iban.* && mocha test/randomHex.js && mocha test/sha3.js && mocha test/toChecksumAddress.js && mocha test/unitMap.js && mocha test/default* && mocha test/getNodeInfo.js && mocha test/eventEmitter.js && mocha test/packages/caver.klay.net.js && mocha test/getNetworkType.js && mocha test/invalidResponse.js && mocha test/isContractDeployment.js && mocha test/personal.js && mocha test/multiProviderTest.js && mocha test/subscription.js && mocha test/supportsSubscriptions.js && mocha test/contract.once.js && mocha test/setProvider.js && mocha test/contractOverloading.js",
"etcTest": "mocha ./test/tupleTest.js && mocha ./test/contract.setWallet.js && mocha ./test/setRequestManager.js && mocha test/contractError.js && mocha test/reconnectTest.js && mocha test/packages/caver.utils.js && mocha test/confirmationListener.js && mocha test/hashMessage.js && mocha test/iban.* && mocha test/randomHex.js && mocha test/sha3.js && mocha test/toChecksumAddress.js && mocha test/unitMap.js && mocha test/default* && mocha test/getNodeInfo.js && mocha test/eventEmitter.js && mocha test/packages/caver.klay.net.js && mocha test/getNetworkType.js && mocha test/invalidResponse.js && mocha test/isContractDeployment.js && mocha test/personal.js && mocha test/multiProviderTest.js && mocha test/subscription.js && mocha test/supportsSubscriptions.js && mocha test/contract.once.js && mocha test/setProvider.js && mocha test/contractOverloading.js",
"accountKeyTest": "mocha test/scenarioTest/accountKeyPublic.js && mocha test/scenarioTest/accountKeyMultiSig.js && mocha test/scenarioTest/accountKeyRoleBased.js",
"kctTest": "mocha test/packages/caver.klay.KIP7.js && mocha test/packages/caver.klay.KIP17.js && mocha test/packages/caver.kct.kip37.js",
"intTxTest": "npm run intLEGACYTest && npm run intVTTest && npm run intVTMTest && npm run intACCUPTest && npm run intDEPLTest && npm run intEXETest && npm run intCANCELTest && npm run intFDTest && npm run intFDRTest",
Expand Down Expand Up @@ -57,6 +57,7 @@
"license": "LGPL",
"dependencies": {
"@babel/runtime": "^7.3.1",
"@ethersproject/abi": "5.0.7",
"@web3-js/scrypt-shim": "^0.1.0",
"any-promise": "1.3.0",
"bignumber.js": "^8.0.2",
Expand All @@ -82,7 +83,7 @@
"semver": "6.2.0",
"utf8": "2.1.1",
"uuid": "^3.0.0",
"webpack": "^4.43.0",
"webpack": "4.44.2",
"webpack-cli": "^3.3.12",
"websocket": "^1.0.31",
"xhr2-cookies": "^1.1.0"
Expand All @@ -92,13 +93,13 @@
"@babel/plugin-external-helpers": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.3.1",
"babel-eslint": "^8.2.6",
"babel-eslint": "^10.1.0",
"babel-plugin-external-helpers": "^6.22.0",
"babelrc-rollup": "^3.0.0",
"browserify": "^16.2.2",
"chai-as-promised": "^7.1.1",
"del": "^3.0.0",
"eslint": "^6.5.1",
"eslint": "^7.11.0",
"eslint-config-airbnb": "^17.0.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^6.4.0",
Expand Down
147 changes: 139 additions & 8 deletions packages/caver-abi/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
*/

const _ = require('lodash')
const EthersAbi = require('ethers/utils/abi-coder').AbiCoder

const EthersAbiCoder = require('@ethersproject/abi').AbiCoder
const ParamType = require('@ethersproject/abi').ParamType
const utils = require('../../caver-utils')

const ethersAbiCoder = new EthersAbi(function(type, value) {
const ethersAbiCoder = new EthersAbiCoder(function(type, value) {
if (type.match(/^u?int/) && !_.isArray(value) && (!_.isObject(value) || value.constructor.name !== 'BN')) {
return value.toString()
}
Expand Down Expand Up @@ -88,14 +90,56 @@ ABICoder.prototype.encodeParameter = function(type, param) {

/**
* Should be used to encode list of params
* Tuple type can be used like below
* `caver.abi.encodeParameters(['tuple(bytes32,bool)', 'tuple(bool,address)'], [['0xabd...', true], [true, '0x776...']])`
*
* @method encodeParameters
* @param {Array} types
* @param {Array} params
* @return {String} encoded list of params
*/
ABICoder.prototype.encodeParameters = function(types, params) {
return ethersAbiCoder.encode(this.mapTypes(types), params)
const self = this
types = self.mapTypes(types)

params = params.map(function(param, index) {
let type = types[index]

// { components: [[Object], [Object]], name: 'b', type: 'tuple' }
if (typeof type === 'object' && type.type) {
// We may get a named type of shape {name, type}
type = type.type
}

param = self.formatParam(type, param)

// If the type is string but number comes in, ethersAbiCoder ignores the type and encodes successfully.
// To avoid invalid encoding value, adding error handling.
if (type === 'string' && typeof param !== 'string') throw new Error(`Invalid parameter: Parameter value and type do not match.`)

// Format params for tuples
if (typeof type === 'string' && type.includes('tuple')) {
const coder = ethersAbiCoder._getCoder(ParamType.from(type))
// eslint-disable-next-line no-shadow
const modifyParams = (coder, param) => {
if (coder.name === 'array') {
return param.map(p => modifyParams(ethersAbiCoder._getCoder(ParamType.from(coder.type.replace('[]', ''))), p))
}
coder.coders.forEach((c, i) => {
if (c.name === 'tuple') {
modifyParams(c, param[i])
} else {
param[i] = self.formatParam(c.name, param[i])
}
})
}
modifyParams(coder, param)
}

return param
})

return ethersAbiCoder.encode(types, params)
}

/**
Expand Down Expand Up @@ -143,6 +187,12 @@ ABICoder.prototype.mapTypes = function(types) {
const self = this
const mappedTypes = []
types.forEach(function(type) {
// Remap `function` type params to bytes24 since Ethers does not
// recognize former type. Solidity docs say `Function` is a bytes24
// encoding the contract address followed by the function selector hash.
if (typeof type === 'object' && type.type === 'function') {
type = Object.assign({}, type, { type: 'bytes24' })
}
if (self.isSimplifiedStructFormat(type)) {
const structName = Object.keys(type)[0]
mappedTypes.push(
Expand All @@ -156,7 +206,6 @@ ABICoder.prototype.mapTypes = function(types) {

mappedTypes.push(type)
})

return mappedTypes
}

Expand Down Expand Up @@ -219,6 +268,68 @@ ABICoder.prototype.mapStructToCoderFormat = function(struct) {
return components
}

/**
* Handle some formatting of params for backwards compatability with Ethers V4
*
* @method formatParam
* @param {String} - type
* @param {any} - param
* @return {any} - The formatted param
*/
ABICoder.prototype.formatParam = function(type, param) {
const paramTypeBytes = new RegExp(/^bytes([0-9]*)$/)
const paramTypeBytesArray = new RegExp(/^bytes([0-9]*)\[\]$/)
const paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/)
const paramTypeNumberArray = new RegExp(/^(u?int)([0-9]*)\[\]$/)

// Format BN to string
if (utils.isBN(param) || utils.isBigNumber(param)) {
return param.toString(10)
}

if (type.match(paramTypeBytesArray) || type.match(paramTypeNumberArray)) {
return param.map(p => this.formatParam(type.replace('[]', ''), p))
}

// Format correct width for u?int[0-9]*
let match = type.match(paramTypeNumber)
if (match) {
const size = parseInt(match[2] || '256')
if (size / 8 < param.length) {
// pad to correct bit width
param = utils.leftPad(param, size)
}
}

// Format correct length for bytes[0-9]+
match = type.match(paramTypeBytes)
if (match) {
if (Buffer.isBuffer(param)) {
param = utils.toHex(param)
}

// format to correct length
const size = parseInt(match[1])
if (size) {
let maxSize = size * 2
if (param.substring(0, 2) === '0x') {
maxSize += 2
}
if (param.length < maxSize) {
// pad to correct length
param = utils.rightPad(param, size * 2)
}
}

// format odd-length bytes to even-length
if (param.length % 2 === 1) {
param = `0x0${param.substring(2)}`
}
}

return param
}

/**
* Encodes a function call from its json interface and parameters.
*
Expand Down Expand Up @@ -246,17 +357,37 @@ ABICoder.prototype.decodeParameter = function(type, bytes) {
/**
* Should be used to decode list of params
*
* @method decodeParameter
* @method decodeParameters
* @param {Array} outputs
* @param {String} bytes
* @return {Array} array of plain params
*/
ABICoder.prototype.decodeParameters = function(outputs, bytes) {
return this.decodeParametersWith(outputs, bytes, false)
}

/**
* Should be used to decode list of params
*
* @method decodeParametersWith
* @param {Array} outputs
* @param {String} bytes
* @param {Boolean} loose must be passed for decoding bytes and string parameters for logs emitted with solc 0.4.x
* Please refer to https://github.com/ChainSafe/web3.js/commit/e80337e16e5c04683fc40148378775234c28e0fb.
* @return {Array} array of plain params
*/
ABICoder.prototype.decodeParametersWith = function(outputs, bytes, loose) {
if (outputs.length > 0 && (!bytes || bytes === '0x' || bytes === '0X')) {
throw new Error("Returned values aren't valid, did it run Out of Gas?")
throw new Error(
"Returned values aren't valid, did it run Out of Gas? " +
'You might also see this error if you are not using the ' +
'correct ABI for the contract you are retrieving data from, ' +
'requesting data from a block number that does not exist, ' +
'or querying a node which is not fully synced.'
)
}

const res = ethersAbiCoder.decode(this.mapTypes(outputs), `0x${bytes.replace(/0x/i, '')}`)
const res = ethersAbiCoder.decode(this.mapTypes(outputs), `0x${bytes.replace(/0x/i, '')}`, loose)
const returnValue = new Result()
returnValue.__length__ = 0

Expand Down Expand Up @@ -311,7 +442,7 @@ ABICoder.prototype.decodeLog = function(inputs, data, topics) {
})

const nonIndexedData = data
const notIndexedParams = nonIndexedData ? this.decodeParameters(notIndexedInputs, nonIndexedData) : []
const notIndexedParams = nonIndexedData ? this.decodeParametersWith(notIndexedInputs, nonIndexedData, true) : []

const returnValue = new Result()
returnValue.__length__ = 0
Expand Down
Loading

0 comments on commit f9d5d42

Please sign in to comment.