@nextrope/xrpl
Version:
A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser
162 lines (145 loc) • 4.66 kB
text/typescript
import { ValidationError } from '../../errors'
import { Amount } from '../common'
import { isFlagEnabled } from '../utils'
import {
BaseTransaction,
GlobalFlagsInterface,
validateBaseTransaction,
isAmount,
parseAmountValue,
isAccount,
validateOptionalField,
Account,
} from './common'
import type { TransactionMetadataBase } from './metadata'
/**
* Transaction Flags for an NFTokenCreateOffer Transaction.
*
* @category Transaction Flags
*/
export enum NFTokenCreateOfferFlags {
/**
* If set, indicates that the offer is a sell offer.
* Otherwise, it is a buy offer.
*/
tfSellNFToken = 0x00000001,
}
/**
* Map of flags to boolean values representing {@link NFTokenCreateOffer} transaction
* flags.
*
* @category Transaction Flags
*/
export interface NFTokenCreateOfferFlagsInterface extends GlobalFlagsInterface {
tfSellNFToken?: boolean
}
/**
* The NFTokenCreateOffer transaction creates either an offer to buy an
* NFT the submitting account does not own, or an offer to sell an NFT
* the submitting account does own.
*/
export interface NFTokenCreateOffer extends BaseTransaction {
TransactionType: 'NFTokenCreateOffer'
/**
* Identifies the NFTokenID of the NFToken object that the
* offer references.
*/
NFTokenID: string
/**
* Indicates the amount expected or offered for the Token.
*
* The amount must be non-zero, except when this is a sell
* offer and the asset is XRP. This would indicate that the current
* owner of the token is giving it away free, either to anyone at all,
* or to the account identified by the Destination field.
*/
Amount: Amount
/**
* Indicates the AccountID of the account that owns the
* corresponding NFToken.
*
* If the offer is to buy a token, this field must be present
* and it must be different than Account (since an offer to
* buy a token one already holds is meaningless).
*
* If the offer is to sell a token, this field must not be
* present, as the owner is, implicitly, the same as Account
* (since an offer to sell a token one doesn't already hold
* is meaningless).
*/
Owner?: Account
/**
* Indicates the time after which the offer will no longer
* be valid. The value is the number of seconds since the
* Ripple Epoch.
*/
Expiration?: number
/**
* If present, indicates that this offer may only be
* accepted by the specified account. Attempts by other
* accounts to accept this offer MUST fail.
*/
Destination?: Account
Flags?: number | NFTokenCreateOfferFlagsInterface
}
export interface NFTokenCreateOfferMetadata extends TransactionMetadataBase {
// rippled 1.11.0 or later
offer_id?: string
}
function validateNFTokenSellOfferCases(tx: Record<string, unknown>): void {
if (tx.Owner != null) {
throw new ValidationError(
'NFTokenCreateOffer: Owner must not be present for sell offers',
)
}
}
function validateNFTokenBuyOfferCases(tx: Record<string, unknown>): void {
if (tx.Owner == null) {
throw new ValidationError(
'NFTokenCreateOffer: Owner must be present for buy offers',
)
}
if (parseAmountValue(tx.Amount) <= 0) {
throw new ValidationError(
'NFTokenCreateOffer: Amount must be greater than 0 for buy offers',
)
}
}
/**
* Verify the form and type of an NFTokenCreateOffer at runtime.
*
* @param tx - An NFTokenCreateOffer Transaction.
* @throws When the NFTokenCreateOffer is Malformed.
*/
export function validateNFTokenCreateOffer(tx: Record<string, unknown>): void {
validateBaseTransaction(tx)
if (tx.Account === tx.Owner) {
throw new ValidationError(
'NFTokenCreateOffer: Owner and Account must not be equal',
)
}
if (tx.Account === tx.Destination) {
throw new ValidationError(
'NFTokenCreateOffer: Destination and Account must not be equal',
)
}
validateOptionalField(tx, 'Destination', isAccount)
validateOptionalField(tx, 'Owner', isAccount)
if (tx.NFTokenID == null) {
throw new ValidationError('NFTokenCreateOffer: missing field NFTokenID')
}
if (!isAmount(tx.Amount)) {
throw new ValidationError('NFTokenCreateOffer: invalid Amount')
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- checked in BaseTransaction
const flags = (tx.Flags ?? 0) as number | NFTokenCreateOfferFlagsInterface
const isTfSellNFToken =
typeof flags === 'number'
? isFlagEnabled(flags, NFTokenCreateOfferFlags.tfSellNFToken)
: flags.tfSellNFToken ?? false
if (isTfSellNFToken) {
validateNFTokenSellOfferCases(tx)
} else {
validateNFTokenBuyOfferCases(tx)
}
}