Skip to content
3 changes: 3 additions & 0 deletions packages/ripple-binary-codec/HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

### Fixed
- add `MPTAmount` support in `Issue` (rippled internal type)

## 2.3.0 (2025-2-13)

### Added
Expand Down
57 changes: 45 additions & 12 deletions packages/ripple-binary-codec/src/types/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,35 @@ import { BinaryParser } from '../serdes/binary-parser'
import { AccountID } from './account-id'
import { Currency } from './currency'
import { JsonObject, SerializedType } from './serialized-type'
import { Hash192 } from './hash-192'

interface XRPIssue extends JsonObject {
currency: string
}

interface IOUIssue extends JsonObject {
currency: string
issuer: string
}
interface MPTIssue extends JsonObject {
mpt_issuance_id: string
}
/**
* Interface for JSON objects that represent amounts
*/
interface IssueObject extends JsonObject {
currency: string
issuer?: string
}
type IssueObject = XRPIssue | IOUIssue | MPTIssue

/**
* Type guard for AmountObject
*/
function isIssueObject(arg): arg is IssueObject {
const keys = Object.keys(arg).sort()
if (keys.length === 1) {
return keys[0] === 'currency'
}
return keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer'
const isXRP = keys.length === 1 && keys[0] === 'currency'
const isIOU =
keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer'
const isMPT = keys.length === 1 && keys[0] === 'mpt_issuance_id'

return isXRP || isIOU || isMPT
}

/**
Expand All @@ -47,12 +58,26 @@ class Issue extends SerializedType {
}

if (isIssueObject(value)) {
const currency = Currency.from(value.currency).toBytes()
if (value.issuer == null) {
if (value.currency) {
const currency = Currency.from(value.currency.toString()).toBytes()

//IOU case
if (value.issuer) {
const issuer = AccountID.from(value.issuer.toString()).toBytes()
return new Issue(concat([currency, issuer]))
}

//XRP case
return new Issue(currency)
}
const issuer = AccountID.from(value.issuer).toBytes()
return new Issue(concat([currency, issuer]))

// MPT case
if (value.mpt_issuance_id) {
const mptIssuanceIdBytes = Hash192.from(
value.mpt_issuance_id.toString(),
).toBytes()
return new Issue(mptIssuanceIdBytes)
}
}

throw new Error('Invalid type to construct an Amount')
Expand All @@ -79,7 +104,15 @@ class Issue extends SerializedType {
* @returns the JSON interpretation of this.bytes
*/
toJSON(): IssueObject {
// If the buffer is exactly 24 bytes, treat it as an MPT amount.
if (this.toBytes.length === Hash192.width) {
return {
mpt_issuance_id: this.toHex().toUpperCase(),
}
}

const parser = new BinaryParser(this.toString())

const currency = Currency.fromParser(parser) as Currency
if (currency.toJSON() === 'XRP') {
return { currency: currency.toJSON() }
Expand Down
Loading