Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit a61306d

Browse files
author
Joe C
authored
token js: add variable length extension support to getMintLen (#6085)
* token js: add variable length extension support to `getMintLen` * add jon suggestions
1 parent a6b6623 commit a61306d

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

token/js/src/extensions/extensionType.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ function addTypeAndLengthToLen(len: number): number {
4949
return len + TYPE_SIZE + LENGTH_SIZE;
5050
}
5151

52+
function isVariableLengthExtension(e: ExtensionType): boolean {
53+
switch (e) {
54+
case ExtensionType.TokenMetadata:
55+
return true;
56+
default:
57+
return false;
58+
}
59+
}
60+
5261
// NOTE: All of these should eventually use their type's Span instead of these
5362
// constants. This is provided for at least creation to work.
5463
export function getTypeLen(e: ExtensionType): number {
@@ -176,8 +185,12 @@ export function getAccountTypeOfMintType(e: ExtensionType): ExtensionType {
176185
}
177186
}
178187

179-
function getLen(extensionTypes: ExtensionType[], baseSize: number): number {
180-
if (extensionTypes.length === 0) {
188+
function getLen(
189+
extensionTypes: ExtensionType[],
190+
baseSize: number,
191+
variableLengthExtensions: { [E in ExtensionType]?: number } = {}
192+
): number {
193+
if (extensionTypes.length === 0 && Object.keys(variableLengthExtensions).length === 0) {
181194
return baseSize;
182195
} else {
183196
const accountLength =
@@ -186,7 +199,15 @@ function getLen(extensionTypes: ExtensionType[], baseSize: number): number {
186199
extensionTypes
187200
.filter((element, i) => i === extensionTypes.indexOf(element))
188201
.map((element) => addTypeAndLengthToLen(getTypeLen(element)))
189-
.reduce((a, b) => a + b);
202+
.reduce((a, b) => a + b, 0) +
203+
Object.entries(variableLengthExtensions)
204+
.map(([extension, len]) => {
205+
if (!isVariableLengthExtension(Number(extension))) {
206+
throw Error(`Extension ${extension} is not variable length`);
207+
}
208+
return addTypeAndLengthToLen(len);
209+
})
210+
.reduce((a, b) => a + b, 0);
190211
if (accountLength === MULTISIG_SIZE) {
191212
return accountLength + TYPE_SIZE;
192213
} else {
@@ -195,11 +216,15 @@ function getLen(extensionTypes: ExtensionType[], baseSize: number): number {
195216
}
196217
}
197218

198-
export function getMintLen(extensionTypes: ExtensionType[]): number {
199-
return getLen(extensionTypes, MINT_SIZE);
219+
export function getMintLen(
220+
extensionTypes: ExtensionType[],
221+
variableLengthExtensions: { [E in ExtensionType]?: number } = {}
222+
): number {
223+
return getLen(extensionTypes, MINT_SIZE, variableLengthExtensions);
200224
}
201225

202226
export function getAccountLen(extensionTypes: ExtensionType[]): number {
227+
// There are currently no variable length extensions for accounts
203228
return getLen(extensionTypes, ACCOUNT_SIZE);
204229
}
205230

token/js/test/unit/index.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
createInitializeAccount3Instruction,
2424
createAmountToUiAmountInstruction,
2525
createUiAmountToAmountInstruction,
26+
getMintLen,
2627
} from '../../src';
2728

2829
chai.use(chaiAsPromised);
@@ -234,13 +235,36 @@ describe('state', () => {
234235
});
235236

236237
describe('extensionType', () => {
237-
it('calculates size', () => {
238+
it('calculates size for accounts', () => {
238239
expect(getAccountLen([ExtensionType.MintCloseAuthority, ExtensionType.TransferFeeConfig])).to.eql(314);
239240
expect(getAccountLen([])).to.eql(165);
240241
expect(getAccountLen([ExtensionType.ImmutableOwner])).to.eql(170);
241242
expect(getAccountLen([ExtensionType.PermanentDelegate])).to.eql(202);
242243
});
243244

245+
it('calculates size for mints', () => {
246+
expect(getMintLen([ExtensionType.TransferFeeConfig, ExtensionType.NonTransferable])).to.eql(282);
247+
expect(getMintLen([])).to.eql(82);
248+
expect(getMintLen([ExtensionType.TransferHook])).to.eql(234);
249+
expect(getMintLen([ExtensionType.MetadataPointer])).to.eql(234);
250+
expect(
251+
getMintLen([ExtensionType.TransferFeeConfig, ExtensionType.NonTransferable], {
252+
[ExtensionType.TokenMetadata]: 200,
253+
})
254+
).to.eql(486);
255+
expect(
256+
getMintLen([], {
257+
[ExtensionType.TokenMetadata]: 200,
258+
})
259+
).to.eql(370);
260+
// Should error on an extension that isn't variable-length
261+
expect(() =>
262+
getMintLen([ExtensionType.TransferFeeConfig, ExtensionType.NonTransferable], {
263+
[ExtensionType.TransferHook]: 200,
264+
})
265+
).to.throw('Extension 14 is not variable length');
266+
});
267+
244268
it('exclusive and exhaustive predicates', () => {
245269
const exts = Object.values(ExtensionType).filter(Number.isInteger);
246270
const mintExts = exts.filter((e: any): e is ExtensionType => isMintExtension(e));

0 commit comments

Comments
 (0)