Repository: solana-labs/solana-program-library
Pull request #6290 (2024-02-23 21:02:47)

token-js: refactor metadata pointer tests
The `MetadataPointer` tests are a little bit difficult to follow, so this change
refactors them to be a bit more legible, so onlookers can see what's going on
and learn how to use the `MetadataPointer` instructions & state from observing
the tests.



Patch:
diff --git a/libraries/type-length-value/js/.nojekyll b/libraries/type-length-value/js/.nojekyll
new file mode 100644
index 000000000..e69de29bb
diff --git a/libraries/type-length-value/js/package.json b/libraries/type-length-value/js/package.json
index 7bff273d1..348dc2484 100644
--- a/libraries/type-length-value/js/package.json
+++ b/libraries/type-length-value/js/package.json
@@ -28,17 +28,20 @@
         "import": "./lib/esm/index.js"
     },
     "scripts": {
-        "nuke": "shx rm -rf node_modules package-lock.json || true",
-        "reinstall": "npm run nuke && npm install",
-        "clean": "shx rm -rf lib **/*.tsbuildinfo || true",
         "build": "tsc --build --verbose tsconfig.all.json",
-        "postbuild": "shx echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json",
-        "watch": "tsc --build --verbose --watch tsconfig.all.json",
-        "release": "npm run clean && npm run build",
+        "clean": "shx rm -rf lib **/*.tsbuildinfo || true",
+        "deploy": "npm run deploy:docs",
+        "deploy:docs": "npm run docs && gh-pages --dest type-length-value/js --dist docs --dotfiles",
+        "docs": "shx rm -rf docs && typedoc && shx cp .nojekyll docs/",
         "fmt": "prettier --write '{*,**/*}.{ts,tsx,js,jsx,json}'",
         "lint": "prettier --check '{*,**/*}.{ts,tsx,js,jsx,json}' && eslint --max-warnings 0 .",
         "lint:fix": "npm run fmt && eslint --fix .",
-        "test": "mocha test"
+        "nuke": "shx rm -rf node_modules package-lock.json || true",
+        "postbuild": "shx echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json",
+        "reinstall": "npm run nuke && npm install",
+        "release": "npm run clean && npm run build",
+        "test": "mocha test",
+        "watch": "tsc --build --verbose --watch tsconfig.all.json"
     },
     "dependencies": {
         "buffer": "^6.0.3"
@@ -59,6 +62,7 @@
         "prettier": "^3.2.5",
         "shx": "^0.3.4",
         "ts-node": "^10.9.2",
+        "typedoc": "^0.25.8",
         "typescript": "^5.3.3"
     }
 }
diff --git a/libraries/type-length-value/js/typedoc.json b/libraries/type-length-value/js/typedoc.json
new file mode 100644
index 000000000..c39fc53ae
--- /dev/null
+++ b/libraries/type-length-value/js/typedoc.json
@@ -0,0 +1,5 @@
+{
+    "entryPoints": ["src/index.ts"],
+    "out": "docs",
+    "readme": "README.md"
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7edd9fd04..647b43797 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,5 +1,9 @@
 lockfileVersion: '6.0'
 
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
 importers:
 
   .:
@@ -177,6 +181,9 @@ importers:
       ts-node:
         specifier: ^10.9.2
         version: 10.9.2(@types/node@20.11.20)(typescript@5.3.3)
+      typedoc:
+        specifier: ^0.25.8
+        version: 0.25.8(typescript@5.3.3)
       typescript:
         specifier: ^5.3.3
         version: 5.3.3
@@ -2388,7 +2395,7 @@ packages:
       '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
       '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
       eslint: 8.56.0
-      eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.0.2)(eslint@8.56.0)(jest@29.7.0)(typescript@5.3.3)
+      eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
       eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0)
       eslint-plugin-simple-import-sort: 10.0.0(eslint@8.56.0)
       eslint-plugin-sort-keys-fix: 1.1.2
@@ -4500,6 +4507,27 @@ packages:
       - supports-color
     dev: true
 
+  /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.56.0)(typescript@5.3.3):
+    resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==}
+    engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+    peerDependencies:
+      '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0
+      eslint: ^7.0.0 || ^8.0.0
+      jest: '*'
+    peerDependenciesMeta:
+      '@typescript-eslint/eslint-plugin':
+        optional: true
+      jest:
+        optional: true
+    dependencies:
+      '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
+      '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+      eslint: 8.56.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
   /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.0.2)(eslint@8.56.0)(jest@29.7.0)(typescript@5.3.3):
     resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -8283,7 +8311,3 @@ packages:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
     dev: true
-
-settings:
-  autoInstallPeers: true
-  excludeLinksFromLockfile: false


Test patch:
diff --git a/token/js/test/unit/metadataPointer.test.ts b/token/js/test/unit/metadataPointer.test.ts
index d7469421a..5b7580767 100644
--- a/token/js/test/unit/metadataPointer.test.ts
+++ b/token/js/test/unit/metadataPointer.test.ts
@@ -8,39 +8,41 @@ import {
     getMetadataPointerState,
 } from '../../src';
 
-describe('SPL Token 2022 Metadata Extension', () => {
-    it('can create createInitializeMetadataPointerInstruction', () => {
-        const mint = PublicKey.unique();
-        const authority = new PublicKey('1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM');
-        const metadataAddress = new PublicKey('1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh');
+const AUTHORITY_ADDRESS_BYTES = Buffer.alloc(32).fill(8);
+const METADATA_ADDRESS_BYTES = Buffer.alloc(32).fill(5);
+const NULL_OPTIONAL_NONZERO_PUBKEY_BYTES = Buffer.alloc(32).fill(0);
 
+describe('SPL Token 2022 MetadataPointer Extension', () => {
+    it('can create InitializeMetadataPointerInstruction', () => {
+        const mint = PublicKey.unique();
+        const authority = new PublicKey(AUTHORITY_ADDRESS_BYTES);
+        const metadataAddress = new PublicKey(METADATA_ADDRESS_BYTES);
         const instruction = createInitializeMetadataPointerInstruction(
             mint,
             authority,
             metadataAddress,
             TOKEN_2022_PROGRAM_ID
         );
-
         expect(instruction).to.deep.equal(
             new TransactionInstruction({
                 programId: TOKEN_2022_PROGRAM_ID,
                 keys: [{ isSigner: false, isWritable: true, pubkey: mint }],
-                data: Buffer.from([
-                    // Output of rust implementation
-                    39, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                data: Buffer.concat([
+                    Buffer.from([
+                        39, // Token instruction discriminator
+                        0, // MetadataPointer instruction discriminator
+                    ]),
+                    AUTHORITY_ADDRESS_BYTES,
+                    METADATA_ADDRESS_BYTES,
                 ]),
             })
         );
     });
-
-    it('can create createUpdateMetadataPointerInstruction', () => {
+    it('can create UpdateMetadataPointerInstruction', () => {
         const mint = PublicKey.unique();
         const authority = PublicKey.unique();
-        const metadataAddress = new PublicKey('11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP');
-
+        const metadataAddress = new PublicKey(METADATA_ADDRESS_BYTES);
         const instruction = createUpdateMetadataPointerInstruction(mint, authority, metadataAddress);
-
         expect(instruction).to.deep.equal(
             new TransactionInstruction({
                 programId: TOKEN_2022_PROGRAM_ID,
@@ -48,22 +50,21 @@ describe('SPL Token 2022 Metadata Extension', () => {
                     { isSigner: false, isWritable: true, pubkey: mint },
                     { isSigner: true, isWritable: false, pubkey: authority },
                 ],
-                data: Buffer.from([
-                    // Output of rust implementation
-                    39, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    0,
+                data: Buffer.concat([
+                    Buffer.from([
+                        39, // Token instruction discriminator
+                        1, // MetadataPointer instruction discriminator
+                    ]),
+                    METADATA_ADDRESS_BYTES,
                 ]),
             })
         );
     });
-
-    it('can create createUpdateMetadataPointerInstruction to none', () => {
+    it('can create UpdateMetadataPointerInstruction to none', () => {
         const mint = PublicKey.unique();
         const authority = PublicKey.unique();
         const metadataAddress = null;
-
         const instruction = createUpdateMetadataPointerInstruction(mint, authority, metadataAddress);
-
         expect(instruction).to.deep.equal(
             new TransactionInstruction({
                 programId: TOKEN_2022_PROGRAM_ID,
@@ -71,70 +72,70 @@ describe('SPL Token 2022 Metadata Extension', () => {
                     { isSigner: false, isWritable: true, pubkey: mint },
                     { isSigner: true, isWritable: false, pubkey: authority },
                 ],
-                data: Buffer.from([
-                    // Output of rust implementation
-                    39, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    0,
+                data: Buffer.concat([
+                    Buffer.from([
+                        39, // Token instruction discriminator
+                        1, // MetadataPointer instruction discriminator
+                    ]),
+                    NULL_OPTIONAL_NONZERO_PUBKEY_BYTES,
                 ]),
             })
         );
     });
-
     it('can get state with authority and metadata address', async () => {
         const mintInfo = {
-            tlvData: Buffer.from([
-                18, 0, 64, 0, 134, 125, 9, 16, 205, 223, 26, 224, 220, 174, 52, 213, 193, 216, 9, 80, 82, 181, 8, 228,
-                75, 112, 233, 116, 2, 183, 51, 228, 88, 64, 179, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+            tlvData: Buffer.concat([
+                Buffer.from([
+                    // Extension discriminator
+                    18, 0,
+                    // Extension length
+                    64, 0,
+                ]),
+                AUTHORITY_ADDRESS_BYTES,
+                METADATA_ADDRESS_BYTES,
             ]),
         } as Mint;
-
         const metadataPointer = getMetadataPointerState(mintInfo);
-
         expect(metadataPointer).to.deep.equal({
-            authority: new PublicKey([
-                134, 125, 9, 16, 205, 223, 26, 224, 220, 174, 52, 213, 193, 216, 9, 80, 82, 181, 8, 228, 75, 112, 233,
-                116, 2, 183, 51, 228, 88, 64, 179, 158,
-            ]),
-            metadataAddress: new PublicKey([
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-            ]),
+            authority: new PublicKey(AUTHORITY_ADDRESS_BYTES),
+            metadataAddress: new PublicKey(METADATA_ADDRESS_BYTES),
         });
     });
     it('can get state with only metadata address', async () => {
         const mintInfo = {
-            tlvData: Buffer.from([
-                18, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+            tlvData: Buffer.concat([
+                Buffer.from([
+                    // Extension discriminator
+                    18, 0,
+                    // Extension length
+                    64, 0,
+                ]),
+                NULL_OPTIONAL_NONZERO_PUBKEY_BYTES,
+                METADATA_ADDRESS_BYTES,
             ]),
         } as Mint;
-
         const metadataPointer = getMetadataPointerState(mintInfo);
-
         expect(metadataPointer).to.deep.equal({
             authority: null,
-            metadataAddress: new PublicKey([
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-            ]),
+            metadataAddress: new PublicKey(METADATA_ADDRESS_BYTES),
         });
     });
-
     it('can get state with only authority address', async () => {
         const mintInfo = {
-            tlvData: Buffer.from([
-                18, 0, 64, 0, 16, 218, 238, 42, 17, 19, 152, 173, 216, 24, 229, 204, 215, 108, 49, 98, 233, 115, 53,
-                252, 9, 156, 216, 23, 14, 157, 139, 132, 28, 182, 4, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            tlvData: Buffer.concat([
+                Buffer.from([
+                    // Extension discriminator
+                    18, 0,
+                    // Extension length
+                    64, 0,
+                ]),
+                AUTHORITY_ADDRESS_BYTES,
+                NULL_OPTIONAL_NONZERO_PUBKEY_BYTES,
             ]),
         } as Mint;
-
         const metadataPointer = getMetadataPointerState(mintInfo);
-
         expect(metadataPointer).to.deep.equal({
-            authority: new PublicKey([
-                16, 218, 238, 42, 17, 19, 152, 173, 216, 24, 229, 204, 215, 108, 49, 98, 233, 115, 53, 252, 9, 156, 216,
-                23, 14, 157, 139, 132, 28, 182, 4, 191,
-            ]),
+            authority: new PublicKey(AUTHORITY_ADDRESS_BYTES),
             metadataAddress: null,
         });
     });