import { default as xdr } from './generated/xdr_generated'
import { Keypair } from './keypair'
import { UnsignedHyper, Hyper } from 'js-xdr'
import { encodeCheck } from './strkey'
import isUndefined from 'lodash/isUndefined'
import isString from 'lodash/isString'
import isBoolean from 'lodash/isBoolean'
import BigNumber from 'bignumber.js'
import { Hasher } from './util/hasher'
// TODO: split
const CURRENCY_PRECISION = 2
/**
* Lot types.
*/
export const lotTypes = Object.freeze({
noAuction: 'lotTypeNoAuction',
englishAuction: 'lotTypeEng'
})
/**
* Auction close actions.
*/
export const closeAuctionActions = Object.freeze({
markSold: 'closeAuctionActionMarkSold',
markFinished: 'closeAuctionActionMarkFinished'
})
/**
* Manage participant actions.
*/
export const manageParticipantActions = Object.freeze({
chooseWinner: 'manageParticipantActionChooseWinner',
reject: 'manageParticipantActionReject',
approveBuyNow: 'manageParticipantActionApproveBuyNow'
})
/**
* Review request actions.
*/
export const reviewRequestActions = Object.freeze({
approve: 'reviewRequestActionApprove',
reject: 'reviewRequestActionReject',
permanentReject: 'reviewRequestActionPermanentReject'
})
/**
* Reviewable request types.
*/
export const reviewableRequestTypes = Object.freeze({
lot: 'requestTypeCreateLot',
participation: 'requestTypeRequestParticipation',
bid: 'requestTypeCreateBid'
})
/**
* Account types.
*/
export const accountTypes = Object.freeze({
master: 'accountTypeMaster',
platform: 'accountTypePlatform',
dealer: 'accountTypeDealer',
user: 'accountTypeUser',
admin: 'accountTypeAdmin'
})
/**
* `Operation` class represents [operations](https://www.stellar.org/developers/learn/concepts/operations.html) in Stellar network.
* Use one of static methods to create operations:
* * `{@link Operation.createAccount}`
* * `{@link Operation.payment}`
* * `{@link Operation.pathPayment}`
* * `{@link Operation.manageOffer}`
* * `{@link Operation.createPassiveOffer}`
* * `{@link Operation.setOptions}`
* * `{@link Operation.changeTrust}`
* * `{@link Operation.allowTrust}`
* * `{@link Operation.accountMerge}`
* * `{@link Operation.inflation}`
*
* @class Operation
*/
export class Operation {
/**
* Create and fund a non existent account.
* @param {object} opts
* @param {string} opts.destination - Destination account ID to create an account for.
* @param {string} opts.platformId - id of platform account belongs to
* @param {xdr.AccountType} opts.accountType - account type
* @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
* @returns {xdr.CreateAccountOp}
*/
static createAccount (opts) {
if (!Keypair.isValidAccountId(opts.destination)) {
throw new Error('destination is invalid')
}
if (!Keypair.isValidAccountId(opts.destination)) {
throw new Error('platformId is invalid')
}
if (opts.accountType === undefined) {
opts.accountType = accountTypes.user
}
let attributes = {
destination: Keypair.fromAccountId(opts.destination).xdrAccountId(),
accountType: xdr.AccountType.fromName(opts.accountType),
platformId: Keypair.fromAccountId(opts.platformId).xdrAccountId(),
ext: new xdr.CreateAccountOpExt('emptyVersion')
}
let createAccountOp = new xdr.CreateAccountOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.createAccount(createAccountOp)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Creates a lot.
*
* @param {object} opts Operation options.
* @param {string} opts.requestId Lot creation request ID.
* @param {string} opts.type Lot type.
* @param {string} opts.startPrice Start price.
* @param {string} opts.minStep Minimum bid step.
* @param {string} opts.maxStep Maximum bid step.
* @param {string} opts.duration Auction duration in seconds.
* @param {string} opts.details Lot details.
* @param {boolean} [opts.buyNowSupport] Allow "buy now" feature for this lot.
* @param {string} [opts.buyNowPrice] "Buy now" price.
* @param {string} [opts.deposit] Required deposit amount.
* @param {string} opts.startTime Auction start time.
* @param {string} opts.currency Lot's currency.
*
* @return {Operation}
*/
static createLot (opts) {
if (!this.isValidBigNumeric(opts.startPrice, CURRENCY_PRECISION, true)) {
throw new TypeError('startPrice argument must be of type String and represent a positive number with valid precision or zero')
}
if (
!(
isUndefined(opts.deposit) ||
this.isValidBigNumeric(opts.deposit, CURRENCY_PRECISION)
)
) {
throw new TypeError('deposit argument must be of type String and represent a positive number with valid precision')
}
if (!this.isValidBigNumeric(opts.minStep, CURRENCY_PRECISION, true)) {
throw new TypeError('minStep argument must be of type String and represent a positive number with valid precision or zero')
}
if (!this.isValidBigNumeric(opts.maxStep, CURRENCY_PRECISION, true)) {
throw new TypeError('maxStep argument must be of type String and represent a positive number with valid precision or zero')
}
if (!this.isValidBigNumeric(opts.duration, 0, true)) {
throw new TypeError('duration argument must be of type String and represent a positive number or zero')
}
if (!this.isValidBigNumeric(opts.startTime, 0, true)) {
throw new TypeError('startTime argument must be of type String and represent a positive number or zero')
}
if (!this.isValidBigNumeric(opts.buyNowPrice, CURRENCY_PRECISION, true)) {
throw new Error('buyNowPrice argument must be of type String and represent a positive number or zero')
}
if (!this.isValidBigNumeric(opts.requestId, 0, true)) {
throw new TypeError('requestId argument must be of type String and represent positivie number or zero')
}
if (!(isUndefined(opts.buyNowSupport) || isBoolean(opts.buyNowSupport))) {
throw new TypeError('buyNowSupport argument must be of type Boolean')
}
if (!this.isValidString(opts.currency, 3, 3)) {
throw new TypeError('currency argument must be of type String with length 3')
}
let attributes = {}
attributes.requestId = UnsignedHyper.fromString(opts.requestId)
attributes.lotType = xdr.LotType.fromName(opts.type)
attributes.buyNowSupport = opts.buyNowSupport || false
attributes.startPrice = this._toXDRPrice(opts.startPrice)
attributes.minStep = this._toXDRPrice(opts.minStep)
attributes.maxStep = this._toXDRPrice(opts.maxStep)
attributes.buyNowPrice = this._toXDRPrice(opts.buyNowPrice || '0')
attributes.deposit = this._toXDRPrice(opts.deposit || '0')
attributes.details = opts.details
attributes.duration = UnsignedHyper.fromString(opts.duration || '0')
attributes.startTime = Hyper.fromString(opts.startTime)
attributes.currency = opts.currency
attributes.ext = new xdr.CreateLotOpExt(xdr.LedgerVersion.emptyVersion())
let createLotOp = new xdr.CreateLotOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.createLot(createLotOp)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Approve or reject reviewable request
*
* @param {object} opts
* @param {string} opts.requestId - id of reviewable request
* @param {string} opts.hash - hash of the body a request (need this to ensure that we review what we expect)
* @param {string} opts.requestType - type of the request to review
* @param {string} opts.action - on of the {approve, reject, permanentReject}
* @param {string} opts.rejectReason - reason of reject or permanent reject (for approve pass empty string)
*/
static reviewRequest (opts) {
let attrs = {}
if (isUndefined(opts.requestId) || opts.requestId === '0') {
throw new Error('opts.requestId is invalid')
}
attrs.requestId = UnsignedHyper.fromString(opts.requestId)
attrs.hash = Hasher.hash(opts.hash)
if (!this.isValidString(opts.rejectReason, 0, 256)) {
throw new Error('opts.rejectReason is invalid')
}
attrs.rejectReason = opts.rejectReason
if (!Object.values(reviewRequestActions).find(x => x === opts.action)) {
throw new Error(`action must be one of the following: ${Object.keys(reviewRequestActions)}`)
}
attrs.action = xdr.ReviewRequestAction.fromName(opts.action)
if (!Object
.values(reviewableRequestTypes)
.find(x => x === opts.requestType)) {
throw new Error(`requestType must be one of the following: ${Object.keys(reviewableRequestTypes)}`)
}
let requestType = xdr.ReviewableRequestType.fromName(opts.requestType)
attrs.requestDetails = new xdr.ReviewRequestOpRequestDetails(requestType)
attrs.ext = new xdr.ReviewRequestOpExt(xdr.LedgerVersion.emptyVersion())
let reviewRequestOp = new xdr.ReviewRequestOp(attrs)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.reviewRequest(reviewRequestOp)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* CancelRequestOp
* cancels request with a given id.
* Only creator of the request is allowed to perform this operation.
*
* @param {string} opts.requestId - id of the request to cancel
* @param {string} opts.source - source of the operation
* @return {xdr.Operation}
*/
static cancelRequest (opts) {
let attrs = {}
if (isUndefined(opts.requestId) || opts.requestId <= '0') {
throw new Error('opts.requestId must be a string and represent a positive number')
}
attrs.requestId = UnsignedHyper.fromString(opts.requestId)
attrs.ext = new xdr.CancelRequestOpExt(xdr.LedgerVersion.emptyVersion())
let cancelRequestOp = new xdr.CancelRequestOp(attrs)
let opAttrs = {}
opAttrs.body = new xdr.OperationBody.cancelRequest(cancelRequestOp)
this.setSourceAccount(opAttrs, opts)
return new xdr.Operation(opAttrs)
}
/**
* Request "buy now".
*
* @param {object} opts
* @param {string} opts.lotId ID of the lot to be bought.
*
* @return {xdr.RequestBuyNowOp}
*/
static requestBuyNow (opts) {
let attributes = {}
attributes.lotId = UnsignedHyper.fromString(opts.lotId)
attributes.ext = new xdr.RequestBuyNowOpExt(
xdr.LedgerVersion.emptyVersion()
)
let requestBuyNowOp = new xdr.RequestBuyNowOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.requestBuyNow(requestBuyNowOp)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Create a recovery op.
*
* @param {object} opts
* @param {string} opts.account - The target account to recover
* @param {string} opts.newSigner - Signer to recover to.
* @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
* @returns {xdr.RecoverOp}
*/
static recover (opts) {
if (!Keypair.isValidPublicKey(opts.account)) {
throw new TypeError('account is invalid')
}
if (!Keypair.isValidPublicKey(opts.newSigner)) {
throw new TypeError('newSigner is invalid')
}
let attributes = {
ext: new xdr.RecoverOpExt(xdr.LedgerVersion.emptyVersion())
}
attributes.account = Keypair.fromAccountId(opts.account).xdrAccountId()
attributes.newSigner = Keypair.fromAccountId(opts.newSigner).xdrAccountId()
let recover = new xdr.RecoverOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.recover(recover)
Operation.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Create a bid.
*
* @param {object} opts Operation options.
* @param {string} opts.lotId ID of the lot.
* @param {string} opts.amount Amount of the bid.
*
* @return {Operation}
*/
static createBid (opts) {
if (!this.isValidBigNumeric(opts.lotId, 0, true)) {
throw new TypeError('lotId argument must be of type String and represent positivie number or zero')
}
if (!this.isValidBigNumeric(opts.amount, CURRENCY_PRECISION)) {
throw new TypeError('amount argument must be of type String and represent a positive number with valid precision')
}
let attributes = {}
attributes.lotId = UnsignedHyper.fromString(opts.lotId)
attributes.amount = this._toXDRPrice(opts.amount)
attributes.ext = new xdr.CreateBidOpExt(xdr.LedgerVersion.emptyVersion())
let createBid1 = new xdr.CreateBidOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.createBid(createBid1)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Leave a message for the lot.
*
* @param {object} opts Operation options.
* @param {string} opts.lotId The lot to which this message is assigned to.
* @param {string} opts.receiverId accountId of the receiver.
* @param {string} opts.text Message content.
*
* @return {Operation}
*
*/
static sendMessage (opts) {
let attributes = {}
if (!this.isValidBigNumeric(opts.lotId, 0, true)) {
throw new TypeError('lotId argument must be of type String and represent positivie number or zero')
}
if (!Keypair.isValidPublicKey(opts.receiverId)) {
throw new TypeError('receiverId is invalid')
}
attributes.lotId = UnsignedHyper.fromString(opts.lotId)
attributes.receiverId = Keypair
.fromAccountId(opts.receiverId)
.xdrAccountId()
attributes.text = opts.text
attributes.ext = new xdr.SendMessageOpExt(xdr.LedgerVersion.emptyVersion())
let sendMessage = new xdr.SendMessageOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.sendMessage(sendMessage)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Returns an XDR SetOptionsOp. A "set options" operations set or clear account flags,
* set the account's inflation destination, and/or add new signers to the account.
* The account flags are the xdr.AccountFlags enum, which are:
* - AUTH_REQUIRED_FLAG = 0x1
* - AUTH_REVOCABLE_FLAG = 0x2
* @param {object} opts
* @param {string} [opts.inflationDest] - Set this account ID as the account's inflation destination.
* @param {number} [opts.clearFlags] - Bitmap integer for which flags to clear.
* @param {number} [opts.setFlags] - Bitmap integer for which flags to set.
* @param {number} [opts.masterWeight] - The master key weight.
* @param {number} [opts.lowThreshold] - The sum weight for the low threshold.
* @param {number} [opts.medThreshold] - The sum weight for the medium threshold.
* @param {number} [opts.highThreshold] - The sum weight for the high threshold.
* @param {object} [opts.signer] - Add or remove a signer from the account. The signer is
* deleted if the weight is 0.
* @param {string} [opts.signer.address] - The address of the new signer.
* @param {number} [opts.signer.weight] - The weight of the new signer (0 to delete or 1-255)
* @param {string} [opts.homeDomain] - sets the home domain used for reverse federation lookup.
* @param {string} [opts.source] - The source account (defaults to transaction source).
* @returns {xdr.SetOptionsOp}
*/
static setOptions (opts) {
let attributes = {}
attributes.clearFlags = opts.clearFlags
attributes.setFlags = opts.setFlags
let masterWeightInvalid = !isUndefined(opts.masterWeight) &&
(opts.masterWeight < 0 || opts.masterWeight > 255)
if (masterWeightInvalid) {
throw new Error('masterWeight value must be between 0 and 255')
}
let lowThresholdInvalid = !isUndefined(opts.lowThreshold) &&
(opts.lowThreshold < 0 || opts.lowThreshold > 255)
if (lowThresholdInvalid) {
throw new Error('lowThreshold value must be between 0 and 255')
}
let medThresholdInvalid = !isUndefined(opts.medThreshold) &&
(opts.medThreshold < 0 || opts.medThreshold > 255)
if (medThresholdInvalid) {
throw new Error('medThreshold value must be between 0 and 255')
}
let highThresholdInvalid = !isUndefined(opts.highThreshold) &&
(opts.highThreshold < 0 || opts.highThreshold > 255)
if (highThresholdInvalid) {
throw new Error('highThreshold value must be between 0 and 255')
}
attributes.masterWeight = opts.masterWeight
attributes.lowThreshold = opts.lowThreshold
attributes.medThreshold = opts.medThreshold
attributes.highThreshold = opts.highThreshold
if (!isUndefined(opts.homeDomain) && !isString(opts.homeDomain)) {
throw new TypeError('homeDomain argument must be of type String')
}
attributes.homeDomain = opts.homeDomain
if (opts.signer) {
if (!Keypair.isValidAccountId(opts.signer.address)) {
throw new Error('signer.address is invalid')
}
if (opts.signer.weight < 0 || opts.signer.weight > 255) {
throw new Error('signer.weight value must be between 0 and 255')
}
attributes.signer = new xdr.Signer({
pubKey: Keypair.fromAccountId(opts.signer.address).xdrAccountId(),
weight: opts.signer.weight,
ext: new xdr.SignerExt(xdr.LedgerVersion.emptyVersion())
})
}
attributes.ext = new xdr.SetOptionsOpExt(xdr.LedgerVersion.emptyVersion())
let setOptionsOp = new xdr.SetOptionsOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.setOption(setOptionsOp)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Make a request to participate in an auction.
*
* @param {object} opts Operation options.
* @param {string} opts.lotId ID of the lot.
* @param {boolean} opts.isBuyNow do buy now after registration
*
* @return {Operation}
*/
static requestParticipation (opts) {
let attributes = {}
if (!this.isValidBigNumeric(opts.lotId, 0, true)) {
throw new TypeError('lotId argument must be of type String and represent positivie number or zero')
}
if (isUndefined(opts.isBuyNow)) {
opts.isBuyNow = false
}
attributes.lotId = UnsignedHyper.fromString(opts.lotId)
attributes.isBuyNow = opts.isBuyNow
attributes.ext = new xdr.RequestParticipationOpExt(
xdr.LedgerVersion.emptyVersion()
)
let request = new xdr.RequestParticipationOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.requestParticipation(request)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Close the auction.
*
* @param {object} opts Operation options.
* @param {string} opts.lotId ID of the lot.
* @param {string} opts.action Auction resolution action.
*
* @return {xdr.CloseAuctionOp}
*/
static closeAuction (opts) {
let attributes = {}
if (!Object.values(closeAuctionActions).find(x => x === opts.action)) {
throw new Error(`actions must be on the following: ${Object.keys(closeAuctionActions)}`)
}
if (!this.isValidBigNumeric(opts.lotId, 0, true)) {
throw new TypeError('lotId argument must be of type String and represent positivie number or zero')
}
attributes.action = xdr.CloseAuctionAction.fromName(opts.action)
attributes.lotId = UnsignedHyper.fromString(opts.lotId)
attributes.ext = new xdr.CloseAuctionOpExt(
xdr.LedgerVersion.emptyVersion()
)
let closeAuction = new xdr.CloseAuctionOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.closeAuction(closeAuction)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
/**
* Manage participant.
*
* @param {object} opts Operation options.
* @param {string} opts.lotId ID of the lot.
* @param {string} opts.action Participant manage action.
* @param {string} opts.accountId Participant's account ID.
*
* @return {xdr.manageParticipantOp}
*/
static manageParticipant (opts) {
let attributes = {}
if (!Object.values(manageParticipantActions).find(x => x === opts.action)) {
throw new Error(`actions must be on the following: ${Object.keys(manageParticipantActions)}`)
}
if (!this.isValidBigNumeric(opts.lotId, 0, true)) {
throw new TypeError('lotId argument must be of type String and represent positivie number or zero')
}
if (!Keypair.isValidPublicKey(opts.accountId)) {
throw new TypeError('accountId is invalid')
}
attributes.action = xdr.ManageParticipantAction.fromName(opts.action)
attributes.lotId = UnsignedHyper.fromString(opts.lotId)
attributes.accountId = Keypair.fromAccountId(opts.accountId).xdrAccountId()
attributes.ext = new xdr.ManageParticipantOpExt(
xdr.LedgerVersion.emptyVersion()
)
let manageParticipant = new xdr.ManageParticipantOp(attributes)
let opAttributes = {}
opAttributes.body = xdr.OperationBody.manageParticipant(manageParticipant)
this.setSourceAccount(opAttributes, opts)
return new xdr.Operation(opAttributes)
}
static setSourceAccount (opAttributes, opts) {
if (opts.source) {
if (!Keypair.isValidAccountId(opts.source)) {
throw new Error('Source address is invalid')
}
opAttributes.sourceAccount = Keypair
.fromAccountId(opts.source)
.xdrAccountId()
}
opAttributes.ext = new xdr.OperationExt(xdr.LedgerVersion.emptyVersion())
}
/**
* Converts the XDR Operation object to the opts object used to create the XDR
* operation.
* @param {xdr.Operation} operation - An XDR Operation.
* @return {Operation}
*/
static operationToObject (operation) {
function accountIdtoAddress (accountId) {
return encodeCheck('accountId', accountId.ed25519())
}
let result = {}
if (operation.sourceAccount()) {
result.source = accountIdtoAddress(operation.sourceAccount())
}
let attrs = operation.body().value()
switch (operation.body().switch().name) {
case 'createLot':
result.type = 'createLot'
result.requestId = Operation._fromXDRBigNumeric(attrs.requestId())
result.lotType = attrs.lotType().name
result.buyNowSupport = attrs.buyNowSupport()
result.startPrice = Operation._fromXDRBigNumeric(attrs.startPrice())
result.buyNowPrice = Operation._fromXDRBigNumeric(attrs.buyNowPrice())
result.minStep = Operation._fromXDRBigNumeric(attrs.minStep())
result.maxStep = Operation._fromXDRBigNumeric(attrs.maxStep())
result.deposit = Operation._fromXDRBigNumeric(attrs.deposit())
result.startTime = Operation._fromXDRBigNumeric(attrs.startTime())
result.currency = attrs.currency().toString('utf8')
result.duration = Operation._fromXDRBigNumeric(attrs.duration())
result.details = attrs.details().toString('utf8')
break
case 'reviewRequest':
result.type = 'reviewRequest'
result.requestId = attrs.requestId().toString()
result.hash = attrs.hash().toString('hex')
result.requestType = attrs.requestDetails().switch().name
result.action = attrs.action().name
result.rejectReason = attrs.rejectReason().toString('utf8')
break
case 'cancelRequest':
result.type = 'cancelRequest'
result.requestId = attrs.requestId().toString()
break
case 'changeLot':
result.type = 'changeLot'
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
result.details = attrs.details().toString('utf8')
break
case 'requestBuyNow':
result.type = 'requestBuyNow'
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
break
case 'reviewBuyNow':
result.type = 'reviewBuyNow'
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
result.accountId = accountIdtoAddress(attrs.accountId())
result.paperHash = attrs.paperHash()
result.paperLink = attrs.paperLink()
result.isApproved = attrs.isApproved()
break
case 'recover':
result.type = 'recover'
result.account = accountIdtoAddress(attrs.account())
result.newSigner = accountIdtoAddress(attrs.newSigner())
break
case 'createBid':
result.type = 'createBid'
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
result.amount = Operation._fromXDRBigNumeric(attrs.amount())
break
case 'requestParticipation':
result.type = 'requestParticipation'
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
result.isBuyNow = attrs.isBuyNow()
break
case 'createAccount':
result.type = 'createAccount'
result.destination = accountIdtoAddress(attrs.destination())
result.platformId = accountIdtoAddress(attrs.platformId())
result.accountType = attrs.accountType()
break
case 'sendMessage':
result.type = 'sendMessage'
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
result.text = attrs.text().toString('utf8')
result.receiverId = accountIdtoAddress(attrs.receiverId())
break
case 'setOption':
result.type = 'setOptions'
if (attrs.inflationDest()) {
result.inflationDest = accountIdtoAddress(attrs.inflationDest())
}
result.clearFlags = attrs.clearFlags()
result.setFlags = attrs.setFlags()
result.masterWeight = attrs.masterWeight()
result.lowThreshold = attrs.lowThreshold()
result.medThreshold = attrs.medThreshold()
result.highThreshold = attrs.highThreshold()
result.homeDomain = attrs.homeDomain()
if (attrs.signer()) {
let signer = {}
signer.address = accountIdtoAddress(attrs.signer().pubKey())
signer.weight = attrs.signer().weight()
result.signer = signer
}
break
case 'closeAuction':
result.type = 'closeAuction'
result.action = attrs.action().name
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
break
case 'manageParticipant':
result.type = 'manageParticipant'
result.action = attrs.action().name
result.lotId = Operation._fromXDRBigNumeric(attrs.lotId())
result.accountId = accountIdtoAddress(attrs.accountId())
break
default:
throw new Error('Unknown operation')
}
return result
}
static isValidString (value, minSize, maxSize) {
if (!isString(value)) {
return false
}
if (!isUndefined(minSize) && value.length < minSize) {
return false
}
if (!isUndefined(maxSize) && value.length > maxSize) {
return false
}
return true
}
static isValidBigNumeric (value, decimalPlaces = 0, allowZero = false) {
if (!isString(value)) {
return false
}
let numeric
try {
numeric = new BigNumber(value)
} catch (e) {
return false
}
// == 0
if (!allowZero && numeric.isZero()) {
return false
}
// < 0
if (numeric.isNegative()) {
return false
}
if (numeric.decimalPlaces() > decimalPlaces) {
return false
}
// Infinity
if (!numeric.isFinite()) {
return false
}
// NaN
if (numeric.isNaN()) {
return false
}
return true
}
/**
* @private
*/
static _toXDRBigNumeric (value) {
let numeric = new BigNumber(value)
return Hyper.fromString(numeric.toString())
}
/**
* @private
*/
static _fromXDRBigNumeric (value) {
return new BigNumber(value).toString()
}
/**
* @private
*/
static _fromXDRPrice (price) {
let result = new BigNumber(price)
return (result / Math.pow(10, CURRENCY_PRECISION)).toString()
}
/**
* @private
*/
static _toXDRPrice (price) {
let numeric = new BigNumber(price) * Math.pow(10, CURRENCY_PRECISION)
return UnsignedHyper.fromString(numeric.toString())
}
}