diff --git a/public/locales/en-US/translations.json b/public/locales/en-US/translations.json
index bf49cd4b1..08cae7d73 100644
--- a/public/locales/en-US/translations.json
+++ b/public/locales/en-US/translations.json
@@ -461,6 +461,7 @@
"burnable": "Burnable",
"only_xrp": "Only XRP",
"transferable": "Transferable",
+ "mutable": "Mutable",
"buy_offers": "Buy Offers",
"sell_offers": "Sell Offers",
"offer_index": "Offer ID",
diff --git a/src/containers/NFT/NFTHeader/Settings.tsx b/src/containers/NFT/NFTHeader/Settings.tsx
index 185143dce..0e0195eb3 100644
--- a/src/containers/NFT/NFTHeader/Settings.tsx
+++ b/src/containers/NFT/NFTHeader/Settings.tsx
@@ -14,6 +14,7 @@ export const Settings = ({ flags }: Props) => {
const transferable = flags.includes('lsfTransferable')
? 'enabled'
: 'disabled'
+ const mutable = flags.includes('lsfMutable') ? 'enabled' : 'disabled'
return (
@@ -21,6 +22,7 @@ export const Settings = ({ flags }: Props) => {
+
)
diff --git a/src/containers/NFT/NFTHeader/test/Settings.test.js b/src/containers/NFT/NFTHeader/test/Settings.test.js
index 40a92b5ed..bc3d12ada 100644
--- a/src/containers/NFT/NFTHeader/test/Settings.test.js
+++ b/src/containers/NFT/NFTHeader/test/Settings.test.js
@@ -19,8 +19,8 @@ describe('NFT Setttings container', () => {
it('renders defined fields', () => {
const { container } = renderSettings()
- expect(container.querySelectorAll('.row').length).toEqual(3)
+ expect(container.querySelectorAll('.row').length).toEqual(4)
expect((container.textContent.match(/enabled/g) || []).length).toEqual(2)
- expect((container.textContent.match(/disabled/g) || []).length).toEqual(1)
+ expect((container.textContent.match(/disabled/g) || []).length).toEqual(2)
})
})
diff --git a/src/containers/shared/test/transactionUtils.test.ts b/src/containers/shared/test/transactionUtils.test.ts
new file mode 100644
index 000000000..f4502c0cc
--- /dev/null
+++ b/src/containers/shared/test/transactionUtils.test.ts
@@ -0,0 +1,27 @@
+import { Transaction } from '../components/Transaction/types'
+import { buildFlags } from '../transactionUtils'
+
+const buildNFTokenMint = (flags: number): Transaction =>
+ ({
+ tx: {
+ TransactionType: 'NFTokenMint',
+ Flags: flags,
+ },
+ }) as unknown as Transaction
+
+describe('transactionUtils buildFlags', () => {
+ it('decodes NFTokenMint type-specific flags', () => {
+ expect(buildFlags(buildNFTokenMint(0x00000001))).toEqual(['tfBurnable'])
+ expect(buildFlags(buildNFTokenMint(0x00000008))).toEqual(['tfTransferable'])
+ })
+
+ it('decodes the tfMutable flag (XLS-46 dynamic NFTs)', () => {
+ expect(buildFlags(buildNFTokenMint(0x00000010))).toEqual(['tfMutable'])
+ })
+
+ it('decodes multiple NFTokenMint flags including tfMutable', () => {
+ expect(
+ buildFlags(buildNFTokenMint(0x00000001 | 0x00000008 | 0x00000010)),
+ ).toEqual(['tfMutable', 'tfTransferable', 'tfBurnable'])
+ })
+})
diff --git a/src/containers/shared/transactionUtils.ts b/src/containers/shared/transactionUtils.ts
index 6b3c4900c..69e43d836 100644
--- a/src/containers/shared/transactionUtils.ts
+++ b/src/containers/shared/transactionUtils.ts
@@ -82,6 +82,7 @@ export const TX_FLAGS: Record> = {
0x00000002: 'tfOnlyXRP',
0x00000004: 'tfTrustLine',
0x00000008: 'tfTransferable',
+ 0x00000010: 'tfMutable',
},
NFTokenOfferCreate: {
0x00000001: 'tfSellNFToken',
diff --git a/src/rippled/lib/utils.ts b/src/rippled/lib/utils.ts
index 823870688..0e3e5b941 100644
--- a/src/rippled/lib/utils.ts
+++ b/src/rippled/lib/utils.ts
@@ -36,6 +36,7 @@ const NFT_FLAGS: FlagMap = {
0x00000001: 'lsfBurnable',
0x00000002: 'lsfOnlyXRP',
0x00000008: 'lsfTransferable',
+ 0x00000010: 'lsfMutable',
}
const MPT_ISSUANCE_FLAGS: FlagMap = {
0x00000001: 'lsfMPTLocked',