caver-js
Version:
caver-js is a JavaScript API library that allows developers to interact with a Klaytn node
336 lines (310 loc) • 14.4 kB
JavaScript
/*
Copyright 2020 The caver-js Authors
This file is part of the caver-js library.
The caver-js library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The caver-js library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the caver-js. If not, see <http://www.gnu.org/licenses/>.
*/
const _ = require('lodash')
const utils = require('../../caver-utils')
const AccountKeyDecoder = require('./accountKey/accountKeyDecoder')
const AccountKeyLegacy = require('./accountKey/accountKeyLegacy')
const AccountKeyPublic = require('./accountKey/accountKeyPublic')
const AccountKeyFail = require('./accountKey/accountKeyFail')
const AccountKeyWeightedMultiSig = require('./accountKey/accountKeyWeightedMultiSig')
const AccountKeyRoleBased = require('./accountKey/accountKeyRoleBased')
const WeightedMultiSigOptions = require('./accountKey/weightedMultiSigOptions')
const WeightedPublicKey = require('./accountKey/weightedPublicKey')
const { isMultipleKeysFormat, isRoleBasedKeysFormat } = require('../../caver-wallet/src/keyring/keyringHelper')
function isAccountKeyInstance(accountKey) {
if (
!(accountKey instanceof AccountKeyLegacy) &&
!(accountKey instanceof AccountKeyPublic) &&
!(accountKey instanceof AccountKeyFail) &&
!(accountKey instanceof AccountKeyWeightedMultiSig) &&
!(accountKey instanceof AccountKeyRoleBased)
)
return false
return true
}
/**
* Representing an Account which includes information for account update.
*
* @class
* @hideconstructor
*/
class Account {
/**
* Creates an Account instance with an address and an accountKey.
*
* If `accountKey` is a public key string, an `Account` instance with `AccountKeyPublic` as accountKey is created.
*
* If `accountKey` is an array containing public key strings, an `Account` instance with `AccountKeyWeightedMultiSig` as accountKey is created.
* If options are not defined as the last parameter, it is created using a default option with a threshold of 1 and a weight of 1 for each key.
*
* If `accountKey` is an array containing accountKeys that are used for each role, an `Account` instance with `AccountKeyRoleBased` is created.
* Options must be defined for each role with WeightedMultiSigOptions (or object).
* If options are not defined, the default option is used for roles that use multiple public keys.
*
* @example
* // Create an account instance with AccountKeyPublic
* caver.account.create('0x{address in hex}', '0x{public key}')
*
* // Create an account instance with AccountKeyWeightedMultiSig
* caver.account.create('0x{address in hex}', ['0x{public key}', '0x{public key}'], { threshold: 1, weight: [1, 1] })
*
* // Create an account instance with AccountKeyWeightedMultiSig (use the WeightedMultiSigOptions)
* const options = new caver.account.weightedMultiSigOptions(1, [1, 1])
* caver.account.create('0x{address in hex}', ['0x{public key}', '0x{public key}'], options)
*
* // Create an account instance with AccountKeyRoleBased
* caver.account.create('0x{address in hex}', [['0x{public key}'], ['0x{public key}', '0x{public key}'], ['0x{public key}']], [{}, { threshold: 1, weight: [1, 1] }, {}])
*
* // Create an account instance with AccountKeyRoleBased (use the WeightedMultiSigOptions)
* const options = [
* {},
* new caver.account.weightedMultiSigOptions(1, [1, 1]),
* {}
* ]
* caver.account.create('0x{address in hex}', [['0x{public key}'], ['0x{public key}', '0x{public key}'], ['0x{public key}']], options)
*
* @param {string} address The address of Account.
* @param {string|Array.<string>|Array.<Array.<string>>} accountKey The accountKey value of Account. Depending on this, Account's accountKey will be AccountKeyLegacy / AccountKeyPublic / AccountKeyFail / AccountKeyWeightedMultiSig / AccountKeyRoleBased.
* @param {object|Array.<object>|WeightedMultiSigOptions|Array.<WeightedMultiSigOptions>} [options] The options that includes 'threshold' and 'weight'. This is only necessary if AccountKeyWeightedMultiSig or AccountKeyRoleBased.
* @return {Account}
*/
static create(address, accountKey, options) {
if (_.isString(accountKey)) {
if (utils.isValidPublicKey(accountKey)) {
return Account.createWithAccountKeyPublic(address, accountKey)
}
return Account.createFromRLPEncoding(address, accountKey)
}
if (isMultipleKeysFormat(accountKey)) {
if (accountKey.length === 0) throw new Error(`Empty accountKey array.`)
return Account.createWithAccountKeyWeightedMultiSig(address, accountKey, options)
}
if (isRoleBasedKeysFormat(accountKey)) {
return Account.createWithAccountKeyRoleBased(address, accountKey, options)
}
throw new Error(`Unsupported accountKey type: ${typeof accountKey}`)
}
/**
* Creates an Account instance from RLP-encoded account key.
*
* @example
* caver.account.createFromRLPEncoding('0x{address in hex}', '0x04f84...')
*
* @param {string} address The address of Account.
* @param {string} rlpEncodedKey The RLP-encoded accountKey string.
* @return {Account}
*/
static createFromRLPEncoding(address, rlpEncodedKey) {
const accountKey = AccountKeyDecoder.decode(rlpEncodedKey)
return new Account(address, accountKey)
}
/**
* Creates an Account instance which has AccountKeyLegacy as an accountKey.
*
* @example
* caver.account.createWithAccountKeyLegacy('0x{address in hex}')
*
* @param {string} address The address of Account.
* @return {Account}
*/
static createWithAccountKeyLegacy(address) {
return new Account(address, new AccountKeyLegacy())
}
/**
* Creates an Account instance which has AccountKeyPublic as an accountKey.
*
* @example
* caver.account.createWithAccountKeyPublic('0x{address in hex}', '0xb5a9a...')
*
* @param {string} address The address of Account.
* @param {string} publicKey The public key string.
* @return {Account}
*/
static createWithAccountKeyPublic(address, publicKey) {
return new Account(address, new AccountKeyPublic(publicKey))
}
/**
* Creates an Account instance which has AccountKeyFail as an accountKey.
*
* @example
* caver.account.createWithAccountKeyFail('0x{address in hex}')
*
* @param {string} address The address of Account.
* @return {Account}
*/
static createWithAccountKeyFail(address) {
return new Account(address, new AccountKeyFail())
}
/**
* Creates an Account instance which has AccountKeyWeightedMultiSig as an accountKey.
* If options are not defined as the last parameter, it is created using a default option with a threshold of 1 and a weight of 1 for each key.
*
* @example
* // create an Account instance without options
* caver.account.createWithAccountKeyWeightedMultiSig('0x{address in hex}', ['0xb5a9a...', '0xfe4b8...'])
*
* // create an Account instance with options
* const options = { threshold: 2, weight: [1,1] }
* caver.account.createWithAccountKeyWeightedMultiSig('0x{address in hex}', ['0xb5a9a...', '0xfe4b8...'], options)
*
* // create an Account instance with options (use the WeightedMultiSigOptions)
* const options = new caver.account.weightedMultiSigOptions(2, [1, 1])
* caver.account.createWithAccountKeyWeightedMultiSig('0x{address in hex}', ['0xb5a9a...', '0xfe4b8...'], options)
*
* @param {string} address The address of Account.
* @param {Array.<string>} publicKeyArray The array that includes multiple public key strings.
* @param {object|WeightedMultiSigOptions} [options] The object that includes threshold and weight array.
* @return {Account}
*/
static createWithAccountKeyWeightedMultiSig(address, publicKeyArray, options) {
if (!utils.isAddress(address)) throw new Error(`Invalid address: ${address}`)
if (!_.isArray(publicKeyArray)) throw new Error(`Invalid public key array: ${publicKeyArray}`)
return new Account(address, AccountKeyWeightedMultiSig.fromPublicKeysAndOptions(publicKeyArray, options))
}
/**
* Creates an Account instance which has AccountKeyRoleBased as an accountKey.
* If options are not defined, the default option is used for roles that use multiple public keys.
*
* @example
* // create an Account instance without options
* const publicKeys = [
* ['0x034f1...', '0xfe4b8...'],
* ['0xb5a9a...'],
* ['0x034f1...', '0xb5a9a...']
* ]
* caver.account.createWithAccountKeyRoleBased('0x{address in hex}', publicKeys)
*
* // create an Account instance with options
* const options = [
* { threshold: 2, weight: [1, 1] },
* {},
* { threshold: 3, weight: [1, 2] }
* ]
* caver.account.createWithAccountKeyRoleBased('0x{address in hex}', publicKeys, options)
*
* // create an Account instance with options (use the WeightedMultiSigOptions)
* const options = [
* new caver.account.weightedMultiSigOptions(2, [1, 1]),
* new caver.account.weightedMultiSigOptions(),
* new caver.account.weightedMultiSigOptions(3, [1, 2])
* ]
* caver.account.createWithAccountKeyRoleBased('0x{address in hex}', publicKeys, options)
*
* @param {string} address The address of Account.
* @param {Array.<Array.<string>>} roledBasedPublicKeyArray A two-dimensional array containing arrays of public key strings for each role.
* @param {Array.<object|WeightedMultiSigOptions>} [options] An array that contains objects with threshold and weight array defined for each role.
* @return {Account}
*/
static createWithAccountKeyRoleBased(address, roledBasedPublicKeyArray, options) {
return new Account(address, AccountKeyRoleBased.fromRoleBasedPublicKeysAndOptions(roledBasedPublicKeyArray, options))
}
/**
* The account key types which are used in the `caver.account` package.
*
* @typedef {AccountKeyLegacy|AccountKeyPublic|AccountKeyFail|AccountKeyWeightedMultiSig|AccountKeyRoleBased} Account.AccountKey
*/
/**
* Creates an account. It is recommended to use [caver.account.create]{@link Account#create} rather than using the constructor directly.
*
* @example
* const accountKey = new caver.account.accountKey.accountKeyLegacy()
* const account = new caver.account('0x{address in hex}', accountKey)
*
* @constructor
* @hideconstructor
* @param {string} address - The address of account.
* @param {Account.AccountKey} accountKey - The accountKey of account.
*/
constructor(address, accountKey) {
this.address = address
this.accountKey = accountKey
}
/**
* @type {string}
*/
get address() {
return this._address
}
set address(addressInput) {
if (!utils.isAddress(addressInput)) throw new Error(`Invalid address : ${addressInput}`)
this._address = utils.addHexPrefix(addressInput)
}
/**
* @type {Account.AccountKey}
*/
get accountKey() {
return this._accountKey
}
set accountKey(accountKey) {
if (!isAccountKeyInstance(accountKey))
throw new Error(
`Invalid accountKey. accountKey should be an instance of AccountKeyLegacy, AccountKeyPublic, AccountKeyFail, AccountKeyWeightedMultiSig or AccountKeyRoleBased`
)
this._accountKey = accountKey
}
/**
* returns RLP-encoded account key string.
*
* @example
* const encodedAccountKey = account.getRLPEncodingAccountKey()
*
* @return {string}
*/
getRLPEncodingAccountKey() {
return this._accountKey.getRLPEncoding()
}
}
/**
* @example
* caver.account.weightedMultiSigOptions
*
* @type {typeof WeightedMultiSigOptions}
* */
Account.weightedMultiSigOptions = WeightedMultiSigOptions
/**
* A module that provides functions for accountKey.
*
* @typedef {object} AccountKeyModule
* @property {function} decode - A function to decode the accountKey. Please refer to {@link AccountKeyDecoder.decode|caver.account.accountKey.decode}.
* @property {typeof AccountKeyLegacy} accountKeyLegacy - Class representing accountKeyLegacy.
* @property {typeof AccountKeyPublic} accountKeyPublic - Class representing AccountKeyPublic.
* @property {typeof AccountKeyFail} accountKeyFail - Class representing AccountKeyFail.
* @property {typeof AccountKeyWeightedMultiSig} accountKeyWeightedMultiSig - Class representing AccountKeyWeightedMultiSig.
* @property {typeof AccountKeyRoleBased} accountKeyRoleBased - Class representing AccountKeyRoleBased.
* @property {typeof WeightedPublicKey} weightedPublicKey - Class representing WeightedPublicKey.
*/
/**
* @example
* caver.account.accountKey
* caver.account.accountKey.decode('0x{encoded account key}')
* caver.account.accountKey.accountKeyLegacy
* caver.account.accountKey.accountKeyPublic
* caver.account.accountKey.accountKeyFail
* caver.account.accountKey.accountKeyWeightedMultiSig
* caver.account.accountKey.accountKeyRoleBased
* caver.account.accountKey.weightedPublicKey
*
* @type {AccountKeyModule}
* */
Account.accountKey = {
decode: AccountKeyDecoder.decode,
accountKeyLegacy: AccountKeyLegacy,
accountKeyPublic: AccountKeyPublic,
accountKeyFail: AccountKeyFail,
accountKeyWeightedMultiSig: AccountKeyWeightedMultiSig,
accountKeyRoleBased: AccountKeyRoleBased,
weightedPublicKey: WeightedPublicKey,
}
module.exports = Account