Skip to content

Commit bd883bd

Browse files
authored
Add encodeMPTokenMetadata and decodeMPTokenMetadata utility functions (#3117)
* WIP commit * WIP commit * WIP commit * WIP commit * fix tests * update history * add more tests * add JSDOC tag * add stable stringify * fix JSDoc comments * refactor utility functions * fix test name * add encode deocde in integration test
1 parent 3fb9c94 commit bd883bd

File tree

16 files changed

+1254
-341
lines changed

16 files changed

+1254
-341
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/xrpl/HISTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
66

77
### Added
88
* Export `Batch` (XLS-56) transaction types and utilities
9+
* Add `encodeMPTokenMetadata` and `decodeMPTokenMetadata` helper functions to encode and decode MPTokenMetadata as per XLS-89 standard.
910

1011
### Fixed
1112
* Fix incorrect type checking in `validateVaultCreate` that prevented vault creation with MPT as an asset.
13+
* [Breaking change] Fix `MPTokenMetadata` type to adhere to the XLS-89 standard. Since XLS-89 is still in a forming state and undergoing changes, this breaking change is being released as a bug fix via patch version bump. If you are using `MPTokenMetadata` in your code, please verify that it adheres to the updated type definition.
14+
* [Breaking change] Fix `validateMPTokenMetadata` to correctly validate MPTokenMetadata as per XLS-89 standard. Since XLS-89 is still in a forming state and undergoing changes, this breaking change is being released as a bug fix via patch version bump. If you are using `validateMPTokenMetadata` in your code, expect it to change as per the XLS-89 standard.
1215

1316
## 4.4.2 (2025-09-25)
1417

packages/xrpl/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
"eventemitter3": "^5.0.1",
3131
"ripple-address-codec": "^5.0.0",
3232
"ripple-binary-codec": "^2.5.0",
33-
"ripple-keypairs": "^2.0.0"
33+
"ripple-keypairs": "^2.0.0",
34+
"fast-json-stable-stringify": "^2.1.0"
3435
},
3536
"devDependencies": {
3637
"@types/node": "^18.18.38",

packages/xrpl/src/models/common/index.ts

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -220,25 +220,109 @@ export interface PriceData {
220220
}
221221

222222
/**
223-
* MPTokenMetadata object as per the XLS-89d standard.
223+
* {@link MPTokenMetadata} object as per the XLS-89 standard.
224+
* Use {@link encodeMPTokenMetadata} utility function to convert to a compact hex string for on-ledger storage.
225+
* Use {@link decodeMPTokenMetadata} utility function to convert from a hex string to this format.
224226
*/
225227
export interface MPTokenMetadata {
228+
/**
229+
* Ticker symbol used to represent the token.
230+
* Uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.
231+
*
232+
* @example "TBILL"
233+
*/
226234
ticker: string
235+
236+
/**
237+
* Display name of the token.
238+
* Any UTF-8 string.
239+
*
240+
* @example "T-Bill Yield Token"
241+
*/
227242
name: string
243+
244+
/**
245+
* Short description of the token.
246+
* Any UTF-8 string.
247+
*
248+
* @example "A yield-bearing stablecoin backed by short-term U.S. Treasuries"
249+
*/
250+
desc?: string
251+
252+
/**
253+
* URI to the token icon.
254+
* Can be a `hostname/path` (HTTPS assumed) or full URI for other protocols (e.g., ipfs://).
255+
*
256+
* @example "example.org/token-icon.png" or "ipfs://QmXxxx"
257+
*/
228258
icon: string
259+
260+
/**
261+
* Top-level classification of token purpose.
262+
* Allowed values: "rwa", "memes", "wrapped", "gaming", "defi", "other"
263+
*
264+
* @example "rwa"
265+
*/
229266
asset_class: string
230-
issuer_name: string
231-
desc?: string
267+
268+
/**
269+
* Optional subcategory of the asset class.
270+
* Required if `asset_class` is "rwa".
271+
* Allowed values: "stablecoin", "commodity", "real_estate", "private_credit", "equity", "treasury", "other"
272+
*
273+
* @example "treasury"
274+
*/
232275
asset_subclass?: string
233-
urls?: MPTokenMetadataUrl[]
234-
additional_info?: string
276+
277+
/**
278+
* The name of the issuer account.
279+
* Any UTF-8 string.
280+
*
281+
* @example "Example Yield Co."
282+
*/
283+
issuer_name: string
284+
285+
/**
286+
* List of related URIs (site, dashboard, social media, documentation, etc.).
287+
* Each URI object contains the link, its category, and a human-readable title.
288+
*/
289+
uris?: MPTokenMetadataUri[]
290+
291+
/**
292+
* Freeform field for key token details like interest rate, maturity date, term, or other relevant info.
293+
* Can be any valid JSON object or UTF-8 string.
294+
*
295+
* @example { "interest_rate": "5.00%", "maturity_date": "2045-06-30" }
296+
*/
297+
additional_info?: string | Record<string, unknown>
235298
}
236299

237300
/**
238-
* MPTokenMetadataUrl object as per the XLS-89d standard.
301+
* {@link MPTokenMetadataUri} object as per the XLS-89 standard.
302+
* Used within the `uris` array of {@link MPTokenMetadata}.
239303
*/
240-
export interface MPTokenMetadataUrl {
241-
url: string
242-
type: string
304+
export interface MPTokenMetadataUri {
305+
/**
306+
* URI to the related resource.
307+
* Can be a `hostname/path` (HTTPS assumed) or full URI for other protocols (e.g., ipfs://).
308+
*
309+
* @example "exampleyield.com/tbill" or "ipfs://QmXxxx"
310+
*/
311+
uri: string
312+
313+
/**
314+
* The category of the link.
315+
* Allowed values: "website", "social", "docs", "other"
316+
*
317+
* @example "website"
318+
*/
319+
category: string
320+
321+
/**
322+
* A human-readable label for the link.
323+
* Any UTF-8 string.
324+
*
325+
* @example "Product Page"
326+
*/
243327
title: string
244328
}

packages/xrpl/src/models/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export {
1313
convertTxFlagsToNumber,
1414
parseTransactionFlags,
1515
} from './utils/flags'
16+
export {
17+
validateMPTokenMetadata,
18+
decodeMPTokenMetadata,
19+
encodeMPTokenMetadata,
20+
} from './utils/mptokenMetadata'
1621
export * from './methods'
1722
export * from './transactions'
1823
export * from './common'

packages/xrpl/src/models/transactions/MPTokenIssuanceCreate.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { ValidationError } from '../../errors'
22
import { isHex, INTEGER_SANITY_CHECK, isFlagEnabled } from '../utils'
3+
import {
4+
MAX_MPT_META_BYTE_LENGTH,
5+
MPT_META_WARNING_HEADER,
6+
validateMPTokenMetadata,
7+
} from '../utils/mptokenMetadata'
38

49
import {
510
BaseTransaction,
@@ -8,9 +13,6 @@ import {
813
validateOptionalField,
914
isString,
1015
isNumber,
11-
MAX_MPT_META_BYTE_LENGTH,
12-
MPT_META_WARNING_HEADER,
13-
validateMPTokenMetadata,
1416
} from './common'
1517
import type { TransactionMetadataBase } from './metadata'
1618

@@ -109,10 +111,9 @@ export interface MPTokenIssuanceCreate extends BaseTransaction {
109111
TransferFee?: number
110112

111113
/**
112-
* Optional arbitrary metadata about this issuance, encoded as a hex string and limited to 1024 bytes.
113-
*
114-
* The decoded value must be a UTF-8 encoded JSON object that adheres to the
115-
* XLS-89d MPTokenMetadata standard.
114+
* Should follow {@link https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema | XLS-89} standard.
115+
* Use {@link encodeMPTokenMetadata} utility function to convert to convert {@link MPTokenMetadata} to a blob.
116+
* Use {@link decodeMPTokenMetadata} utility function to convert from a blob to {@link MPTokenMetadata}.
116117
*
117118
* While adherence to the XLS-89d format is not mandatory, non-compliant metadata
118119
* may not be discoverable by ecosystem tools such as explorers and indexers.

0 commit comments

Comments
 (0)