Repository: solana-labs/solana-program-library (rust)

Issue:
@solana/spl-token library doesn't work in Vite project
When I install `"@solana/spl-token": "^0.4.8"` in vite project and run `vite build`, I see this error.

../../node_modules/@solana/spl-type-length-value/lib/esm/splDiscriminate.js (1:9): "createHash" is not exported by "__vite-browser-external", imported by "../../node_modules/@solana/spl-type-length-value/lib/esm/splDiscriminate.js".

1: import { createHash } from 'crypto';
            ^
2: export const splDiscriminate = (discriminator, length = 8) => {
3:     const digest = createHash('sha256').update(discriminator).digest();

It's because Vite doesn't support built-in node.js module like `crypto`.
https://www.npmjs.com/package/crypto

Can you update your package to include the polyfills as default?

Thanks

Pull request:
Hardcode the discriminators so that you don't have to compute them at runtime
1. There is no need to compute these well-known values at runtime
2. Adding insult to injury, computing them requires a SHA-256 _polyfill_ for browsers

Resolves #7351.

Patch:
diff --git a/.github/workflows/pull-request-js.yml b/.github/workflows/pull-request-js.yml
index e2f372963..87ce3723e 100644
--- a/.github/workflows/pull-request-js.yml
+++ b/.github/workflows/pull-request-js.yml
@@ -48,8 +48,6 @@ jobs:
             name-service,
             stake-pool,
             token,
-            token-group,
-            token-metadata,
             token-swap,
           ]
         include:
@@ -58,8 +56,12 @@ jobs:
             node-version: 20.x
           - package: single-pool
             node-version: 20.5
+          - package: token-group
+            node-version: 20.x
           - package: token-lending
             node-version: 18.5
+          - package: token-metadata
+            node-version: 20.x
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7c9b07358..51354150a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -375,8 +375,8 @@ importers:
         specifier: ^4.0.1
         version: 4.0.1
       '@solana/spl-token':
-        specifier: 0.4.6
-        version: 0.4.6(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+        specifier: 0.4.9
+        version: link:../../token/js
       '@solana/web3.js':
         specifier: ^1.95.3
         version: 1.95.3
@@ -462,10 +462,10 @@ importers:
       '@solana/codecs':
         specifier: 2.0.0-rc.1
         version: 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/spl-type-length-value':
-        specifier: 0.1.0
-        version: 0.1.0
     devDependencies:
+      '@solana/spl-type-length-value':
+        specifier: 0.2.0
+        version: link:../../libraries/type-length-value/js
       '@solana/web3.js':
         specifier: ^1.95.3
         version: 1.95.3
@@ -540,8 +540,8 @@ importers:
         specifier: ^12.1.1
         version: 12.1.1(rollup@4.24.0)(tslib@2.8.0)(typescript@5.6.3)
       '@solana/spl-token':
-        specifier: 0.4.6
-        version: 0.4.6(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+        specifier: 0.4.9
+        version: link:../../token/js
       '@solana/web3.js':
         specifier: ^1.95.3
         version: 1.95.3
@@ -584,10 +584,10 @@ importers:
       '@solana/codecs':
         specifier: 2.0.0-rc.1
         version: 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/spl-type-length-value':
-        specifier: 0.1.0
-        version: 0.1.0
     devDependencies:
+      '@solana/spl-type-length-value':
+        specifier: 0.2.0
+        version: link:../../libraries/type-length-value/js
       '@solana/web3.js':
         specifier: ^1.95.3
         version: 1.95.3
@@ -647,8 +647,8 @@ importers:
         version: 0.2.0
     devDependencies:
       '@solana/spl-token':
-        specifier: 0.4.6
-        version: 0.4.6(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+        specifier: 0.4.9
+        version: link:../../token/js
       '@solana/web3.js':
         specifier: ^1.95.3
         version: 1.95.3
@@ -701,10 +701,10 @@ importers:
         specifier: ^0.2.0
         version: 0.2.0
       '@solana/spl-token-group':
-        specifier: ^0.0.6
+        specifier: ^0.0.7
         version: link:../../token-group/js
       '@solana/spl-token-metadata':
-        specifier: ^0.1.5
+        specifier: ^0.1.6
         version: link:../../token-metadata/js
       buffer:
         specifier: ^6.0.3
@@ -2242,6 +2242,7 @@ packages:
       - bufferutil
       - encoding
       - utf-8-validate
+    dev: false
 
   /@solana/buffer-layout@4.0.1:
     resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==}
@@ -2249,11 +2250,6 @@ packages:
     dependencies:
       buffer: 6.0.3
 
-  /@solana/codecs-core@2.0.0-preview.2:
-    resolution: {integrity: sha512-gLhCJXieSCrAU7acUJjbXl+IbGnqovvxQLlimztPoGgfLQ1wFYu+XJswrEVQqknZYK1pgxpxH3rZ+OKFs0ndQg==}
-    dependencies:
-      '@solana/errors': 2.0.0-preview.2
-
   /@solana/codecs-core@2.0.0-rc.1(typescript@5.6.3):
     resolution: {integrity: sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==}
     peerDependencies:
@@ -2262,13 +2258,6 @@ packages:
       '@solana/errors': 2.0.0-rc.1(typescript@5.6.3)
       typescript: 5.6.3
 
-  /@solana/codecs-data-structures@2.0.0-preview.2:
-    resolution: {integrity: sha512-Xf5vIfromOZo94Q8HbR04TbgTwzigqrKII0GjYr21K7rb3nba4hUW2ir8kguY7HWFBcjHGlU5x3MevKBOLp3Zg==}
-    dependencies:
-      '@solana/codecs-core': 2.0.0-preview.2
-      '@solana/codecs-numbers': 2.0.0-preview.2
-      '@solana/errors': 2.0.0-preview.2
-
   /@solana/codecs-data-structures@2.0.0-rc.1(typescript@5.6.3):
     resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==}
     peerDependencies:
@@ -2278,12 +2267,7 @@ packages:
       '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.6.3)
       '@solana/errors': 2.0.0-rc.1(typescript@5.6.3)
       typescript: 5.6.3
-
-  /@solana/codecs-numbers@2.0.0-preview.2:
-    resolution: {integrity: sha512-aLZnDTf43z4qOnpTcDsUVy1Ci9im1Md8thWipSWbE+WM9ojZAx528oAql+Cv8M8N+6ALKwgVRhPZkto6E59ARw==}
-    dependencies:
-      '@solana/codecs-core': 2.0.0-preview.2
-      '@solana/errors': 2.0.0-preview.2
+    dev: false
 
   /@solana/codecs-numbers@2.0.0-rc.1(typescript@5.6.3):
     resolution: {integrity: sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==}
@@ -2294,16 +2278,6 @@ packages:
       '@solana/errors': 2.0.0-rc.1(typescript@5.6.3)
       typescript: 5.6.3
 
-  /@solana/codecs-strings@2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22):
-    resolution: {integrity: sha512-EgBwY+lIaHHgMJIqVOGHfIfpdmmUDNoNO/GAUGeFPf+q0dF+DtwhJPEMShhzh64X2MeCZcmSO6Kinx0Bvmmz2g==}
-    peerDependencies:
-      fastestsmallesttextencoderdecoder: ^1.0.22
-    dependencies:
-      '@solana/codecs-core': 2.0.0-preview.2
-      '@solana/codecs-numbers': 2.0.0-preview.2
-      '@solana/errors': 2.0.0-preview.2
-      fastestsmallesttextencoderdecoder: 1.0.22
-
   /@solana/codecs-strings@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3):
     resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==}
     peerDependencies:
@@ -2316,17 +2290,6 @@ packages:
       fastestsmallesttextencoderdecoder: 1.0.22
       typescript: 5.6.3
 
-  /@solana/codecs@2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22):
-    resolution: {integrity: sha512-4HHzCD5+pOSmSB71X6w9ptweV48Zj1Vqhe732+pcAQ2cMNnN0gMPMdDq7j3YwaZDZ7yrILVV/3+HTnfT77t2yA==}
-    dependencies:
-      '@solana/codecs-core': 2.0.0-preview.2
-      '@solana/codecs-data-structures': 2.0.0-preview.2
-      '@solana/codecs-numbers': 2.0.0-preview.2
-      '@solana/codecs-strings': 2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22)
-      '@solana/options': 2.0.0-preview.2
-    transitivePeerDependencies:
-      - fastestsmallesttextencoderdecoder
-
   /@solana/codecs@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3):
     resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==}
     peerDependencies:
@@ -2340,13 +2303,7 @@ packages:
       typescript: 5.6.3
     transitivePeerDependencies:
       - fastestsmallesttextencoderdecoder
-
-  /@solana/errors@2.0.0-preview.2:
-    resolution: {integrity: sha512-H2DZ1l3iYF5Rp5pPbJpmmtCauWeQXRJapkDg8epQ8BJ7cA2Ut/QEtC3CMmw/iMTcuS6uemFNLcWvlOfoQhvQuA==}
-    hasBin: true
-    dependencies:
-      chalk: 5.3.0
-      commander: 12.1.0
+    dev: false
 
   /@solana/errors@2.0.0-rc.1(typescript@5.6.3):
     resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==}
@@ -2423,12 +2380,6 @@ packages:
       typescript: 5.6.3
     dev: false
 
-  /@solana/options@2.0.0-preview.2:
-    resolution: {integrity: sha512-FAHqEeH0cVsUOTzjl5OfUBw2cyT8d5Oekx4xcn5hn+NyPAfQJgM3CEThzgRD6Q/4mM5pVUnND3oK/Mt1RzSE/w==}
-    dependencies:
-      '@solana/codecs-core': 2.0.0-preview.2
-      '@solana/codecs-numbers': 2.0.0-preview.2
-
   /@solana/options@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3):
     resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==}
     peerDependencies:
@@ -2442,6 +2393,7 @@ packages:
       typescript: 5.6.3
     transitivePeerDependencies:
       - fastestsmallesttextencoderdecoder
+    dev: false
 
   /@solana/prettier-config-solana@0.0.5(prettier@3.3.3):
     resolution: {integrity: sha512-igtLH1QaX5xzSLlqteexRIg9X1QKA03xKYQc2qY1TrMDDhxKXoRZOStQPWdita2FVJzxTGz/tdMGC1vS0biRcg==}
@@ -2466,56 +2418,6 @@ packages:
       - fastestsmallesttextencoderdecoder
     dev: false
 
-  /@solana/spl-token-group@0.0.4(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22):
-    resolution: {integrity: sha512-7+80nrEMdUKlK37V6kOe024+T7J4nNss0F8LQ9OOPYdWCCfJmsGUzVx2W3oeizZR4IHM6N4yC9v1Xqwc3BTPWw==}
-    engines: {node: '>=16'}
-    peerDependencies:
-      '@solana/web3.js': ^1.91.6
-    dependencies:
-      '@solana/codecs': 2.0.0-preview.2(fastestsmallesttextencoderdecoder@1.0.22)
-      '@solana/spl-type-length-value': 0.1.0
-      '@solana/web3.js': 1.95.3
-    transitivePeerDependencies:
-      - fastestsmallesttextencoderdecoder
-
-  /@solana/spl-token-metadata@0.1.5(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3):
-    resolution: {integrity: sha512-DSBlo7vjuLe/xvNn75OKKndDBkFxlqjLdWlq6rf40StnrhRn7TDntHGLZpry1cf3uzQFShqeLROGNPAJwvkPnA==}
-    engines: {node: '>=16'}
-    peerDependencies:
-      '@solana/web3.js': ^1.95.3
-    dependencies:
-      '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/spl-type-length-value': 0.1.0
-      '@solana/web3.js': 1.95.3
-    transitivePeerDependencies:
-      - fastestsmallesttextencoderdecoder
-      - typescript
-
-  /@solana/spl-token@0.4.6(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3):
-    resolution: {integrity: sha512-1nCnUqfHVtdguFciVWaY/RKcQz1IF4b31jnKgAmjU9QVN1q7dRUkTEWJZgTYIEtsULjVnC9jRqlhgGN39WbKKA==}
-    engines: {node: '>=16'}
-    peerDependencies:
-      '@solana/web3.js': ^1.91.6
-    dependencies:
-      '@solana/buffer-layout': 4.0.1
-      '@solana/buffer-layout-utils': 0.2.0
-      '@solana/spl-token-group': 0.0.4(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)
-      '@solana/spl-token-metadata': 0.1.5(@solana/web3.js@1.95.3)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/web3.js': 1.95.3
-      buffer: 6.0.3
-    transitivePeerDependencies:
-      - bufferutil
-      - encoding
-      - fastestsmallesttextencoderdecoder
-      - typescript
-      - utf-8-validate
-
-  /@solana/spl-type-length-value@0.1.0:
-    resolution: {integrity: sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA==}
-    engines: {node: '>=16'}
-    dependencies:
-      buffer: 6.0.3
-
   /@solana/transaction-messages@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3):
     resolution: {integrity: sha512-pZTetOtRDwfuK/fyE8FKbtRsLQOTgEIQld3tskB85npUHaEgrnCYzp3nJtMhKOLel3w3f/27VtWLNSrRyyAiew==}
     peerDependencies:
@@ -3639,6 +3541,7 @@ packages:
 
   /bignumber.js@9.1.2:
     resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==}
+    dev: false
 
   /binary-extensions@2.2.0:
     resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
diff --git a/stake-pool/js/package.json b/stake-pool/js/package.json
index ad0fb2f4c..25592950e 100644
--- a/stake-pool/js/package.json
+++ b/stake-pool/js/package.json
@@ -44,7 +44,7 @@
   "license": "ISC",
   "dependencies": {
     "@solana/buffer-layout": "^4.0.1",
-    "@solana/spl-token": "0.4.6",
+    "@solana/spl-token": "0.4.9",
     "@solana/web3.js": "^1.95.3",
     "bn.js": "^5.2.0",
     "buffer": "^6.0.3",
diff --git a/token-group/js/package.json b/token-group/js/package.json
index a150662cc..431214f97 100644
--- a/token-group/js/package.json
+++ b/token-group/js/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@solana/spl-token-group",
     "description": "SPL Token Group Interface JS API",
-    "version": "0.0.6",
+    "version": "0.0.7",
     "author": "Solana Labs Maintainers <maintainers@solanalabs.com>",
     "repository": "https://github.com/solana-labs/solana-program-library",
     "license": "Apache-2.0",
@@ -46,10 +46,10 @@
         "@solana/web3.js": "^1.95.3"
     },
     "dependencies": {
-        "@solana/codecs": "2.0.0-rc.1",
-        "@solana/spl-type-length-value": "0.1.0"
+        "@solana/codecs": "2.0.0-rc.1"
     },
     "devDependencies": {
+        "@solana/spl-type-length-value": "0.2.0",
         "@solana/web3.js": "^1.95.3",
         "@types/chai": "^5.0.0",
         "@types/mocha": "^10.0.9",
diff --git a/token-group/js/src/instruction.ts b/token-group/js/src/instruction.ts
index 6d14cbb4b..b51dd03cd 100644
--- a/token-group/js/src/instruction.ts
+++ b/token-group/js/src/instruction.ts
@@ -8,7 +8,6 @@ import {
     getU64Encoder,
     transformEncoder,
 } from '@solana/codecs';
-import { splDiscriminate } from '@solana/spl-type-length-value';
 import { SystemProgram, TransactionInstruction } from '@solana/web3.js';
 
 function getInstructionEncoder<T extends object>(discriminator: Uint8Array, dataEncoder: Encoder<T>): Encoder<T> {
@@ -43,7 +42,10 @@ export function createInitializeGroupInstruction(args: InitializeGroupInstructio
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_group_interface:initialize_token_group'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_group_interface:initialize_token_group') */
+                    121, 113, 108, 39, 54, 51, 0, 4,
+                ]),
                 getStructEncoder([
                     ['updateAuthority', getPublicKeyEncoder()],
                     ['maxSize', getU64Encoder()],
@@ -70,7 +72,10 @@ export function createUpdateGroupMaxSizeInstruction(args: UpdateGroupMaxSize): T
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_group_interface:update_group_max_size'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_group_interface:update_group_max_size') */
+                    108, 37, 171, 143, 248, 30, 18, 110,
+                ]),
                 getStructEncoder([['maxSize', getU64Encoder()]]),
             ).encode({ maxSize }),
         ),
@@ -95,7 +100,10 @@ export function createUpdateGroupAuthorityInstruction(args: UpdateGroupAuthority
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_group_interface:update_authority'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_group_interface:update_authority') */
+                    161, 105, 88, 1, 237, 221, 216, 203,
+                ]),
                 getStructEncoder([['newAuthority', getPublicKeyEncoder()]]),
             ).encode({ newAuthority: newAuthority ?? SystemProgram.programId }),
         ),
@@ -125,7 +133,10 @@ export function createInitializeMemberInstruction(args: InitializeMember): Trans
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_group_interface:initialize_member'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_group_interface:initialize_member') */
+                    152, 32, 222, 176, 223, 237, 116, 134,
+                ]),
                 getStructEncoder([]),
             ).encode({}),
         ),
diff --git a/token-lending/js/package.json b/token-lending/js/package.json
index 98985b235..ffb426a95 100644
--- a/token-lending/js/package.json
+++ b/token-lending/js/package.json
@@ -37,14 +37,14 @@
         "bignumber.js": "^9.0.1"
     },
     "peerDependencies": {
-        "@solana/spl-token": "0.4.6",
+        "@solana/spl-token": "0.4.9",
         "@solana/web3.js": "^1.20.3"
     },
     "devDependencies": {
         "@rollup/plugin-commonjs": "^28.0.1",
         "@rollup/plugin-node-resolve": "^15.3.0",
         "@rollup/plugin-typescript": "^12.1.1",
-        "@solana/spl-token": "0.4.6",
+        "@solana/spl-token": "0.4.9",
         "@solana/web3.js": "^1.95.3",
         "@types/eslint": "^8.56.7",
         "@types/node": "^22.7.6",
diff --git a/token-metadata/js/package.json b/token-metadata/js/package.json
index 82cad172a..809e0c29a 100644
--- a/token-metadata/js/package.json
+++ b/token-metadata/js/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@solana/spl-token-metadata",
     "description": "SPL Token Metadata Interface JS API",
-    "version": "0.1.5",
+    "version": "0.1.6",
     "author": "Solana Labs Maintainers <maintainers@solanalabs.com>",
     "repository": "https://github.com/solana-labs/solana-program-library",
     "license": "Apache-2.0",
@@ -46,10 +46,10 @@
         "@solana/web3.js": "^1.95.3"
     },
     "dependencies": {
-        "@solana/codecs": "2.0.0-rc.1",
-        "@solana/spl-type-length-value": "0.1.0"
+        "@solana/codecs": "2.0.0-rc.1"
     },
     "devDependencies": {
+        "@solana/spl-type-length-value": "0.2.0",
         "@solana/web3.js": "^1.95.3",
         "@types/chai": "^5.0.0",
         "@types/mocha": "^10.0.9",
diff --git a/token-metadata/js/src/instruction.ts b/token-metadata/js/src/instruction.ts
index 2afdb1121..44fc4a3d8 100644
--- a/token-metadata/js/src/instruction.ts
+++ b/token-metadata/js/src/instruction.ts
@@ -14,7 +14,6 @@ import {
     transformEncoder,
 } from '@solana/codecs';
 import type { VariableSizeEncoder } from '@solana/codecs';
-import { splDiscriminate } from '@solana/spl-type-length-value';
 import type { PublicKey } from '@solana/web3.js';
 import { SystemProgram, TransactionInstruction } from '@solana/web3.js';
 
@@ -66,7 +65,10 @@ export function createInitializeInstruction(args: InitializeInstructionArgs): Tr
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_metadata_interface:initialize_account'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_metadata_interface:initialize_account') */
+                    210, 225, 30, 162, 88, 184, 77, 141,
+                ]),
                 getStructEncoder([
                     ['name', getStringEncoder()],
                     ['symbol', getStringEncoder()],
@@ -99,7 +101,10 @@ export function createUpdateFieldInstruction(args: UpdateFieldInstruction): Tran
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_metadata_interface:updating_field'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_metadata_interface:updating_field') */
+                    221, 233, 49, 45, 181, 202, 220, 200,
+                ]),
                 getStructEncoder([
                     ['field', getDataEnumCodec(getFieldCodec())],
                     ['value', getStringEncoder()],
@@ -127,7 +132,10 @@ export function createRemoveKeyInstruction(args: RemoveKeyInstructionArgs) {
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_metadata_interface:remove_key_ix'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_metadata_interface:remove_key_ix') */
+                    234, 18, 32, 56, 89, 141, 37, 181,
+                ]),
                 getStructEncoder([
                     ['idempotent', getBooleanEncoder()],
                     ['key', getStringEncoder()],
@@ -155,7 +163,10 @@ export function createUpdateAuthorityInstruction(args: UpdateAuthorityInstructio
         ],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_metadata_interface:update_the_authority'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_metadata_interface:update_the_authority') */
+                    215, 228, 166, 228, 84, 100, 86, 123,
+                ]),
                 getStructEncoder([['newAuthority', getPublicKeyEncoder()]]),
             ).encode({ newAuthority: newAuthority ?? SystemProgram.programId }),
         ),
@@ -176,7 +187,10 @@ export function createEmitInstruction(args: EmitInstructionArgs): TransactionIns
         keys: [{ isSigner: false, isWritable: false, pubkey: metadata }],
         data: Buffer.from(
             getInstructionEncoder(
-                splDiscriminate('spl_token_metadata_interface:emitter'),
+                new Uint8Array([
+                    /* await splDiscriminate('spl_token_metadata_interface:emitter') */
+                    250, 166, 180, 250, 13, 12, 184, 70,
+                ]),
                 getStructEncoder([
                     ['start', getOptionEncoder(getU64Encoder())],
                     ['end', getOptionEncoder(getU64Encoder())],
diff --git a/token-swap/js/package.json b/token-swap/js/package.json
index a18e921bb..3b7477aad 100644
--- a/token-swap/js/package.json
+++ b/token-swap/js/package.json
@@ -49,7 +49,7 @@
     "@solana/web3.js": "^1.95.3"
   },
   "devDependencies": {
-    "@solana/spl-token": "0.4.6",
+    "@solana/spl-token": "0.4.9",
     "@solana/web3.js": "^1.95.3",
     "@types/bn.js": "^5.1.6",
     "@types/chai-as-promised": "^8.0.1",
diff --git a/token/js/package.json b/token/js/package.json
index 5661b7c43..2ef975820 100644
--- a/token/js/package.json
+++ b/token/js/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@solana/spl-token",
     "description": "SPL Token Program JS API",
-    "version": "0.4.8",
+    "version": "0.4.9",
     "author": "Solana Labs Maintainers <maintainers@solanalabs.com>",
     "repository": "https://github.com/solana-labs/solana-program-library",
     "license": "Apache-2.0",
@@ -55,8 +55,8 @@
     "dependencies": {
         "@solana/buffer-layout": "^4.0.0",
         "@solana/buffer-layout-utils": "^0.2.0",
-        "@solana/spl-token-group": "^0.0.6",
-        "@solana/spl-token-metadata": "^0.1.5",
+        "@solana/spl-token-group": "^0.0.7",
+        "@solana/spl-token-metadata": "^0.1.6",
         "buffer": "^6.0.3"
     },
     "devDependencies": {


Test patch:
diff --git a/token-group/js/test/instruction.test.ts b/token-group/js/test/instruction.test.ts
index ad8f405d4..8f4dcac0a 100644
--- a/token-group/js/test/instruction.test.ts
+++ b/token-group/js/test/instruction.test.ts
@@ -30,7 +30,7 @@ describe('Token Group Instructions', () => {
     const mintAuthority = new PublicKey('66666666666666666666666666666666666666666666');
     const maxSize = BigInt(100);
 
-    it('Can create InitializeGroup Instruction', () => {
+    it('Can create InitializeGroup Instruction', async () => {
         checkPackUnpack(
             createInitializeGroupInstruction({
                 programId,
@@ -40,7 +40,7 @@ describe('Token Group Instructions', () => {
                 updateAuthority,
                 maxSize,
             }),
-            splDiscriminate('spl_token_group_interface:initialize_token_group'),
+            await splDiscriminate('spl_token_group_interface:initialize_token_group'),
             getStructDecoder([
                 ['updateAuthority', fixDecoderSize(getBytesDecoder(), 32)],
                 ['maxSize', getU64Decoder()],
@@ -49,7 +49,7 @@ describe('Token Group Instructions', () => {
         );
     });
 
-    it('Can create UpdateGroupMaxSize Instruction', () => {
+    it('Can create UpdateGroupMaxSize Instruction', async () => {
         checkPackUnpack(
             createUpdateGroupMaxSizeInstruction({
                 programId,
@@ -57,13 +57,13 @@ describe('Token Group Instructions', () => {
                 updateAuthority,
                 maxSize,
             }),
-            splDiscriminate('spl_token_group_interface:update_group_max_size'),
+            await splDiscriminate('spl_token_group_interface:update_group_max_size'),
             getStructDecoder([['maxSize', getU64Decoder()]]),
             { maxSize },
         );
     });
 
-    it('Can create UpdateGroupAuthority Instruction', () => {
+    it('Can create UpdateGroupAuthority Instruction', async () => {
         checkPackUnpack(
             createUpdateGroupAuthorityInstruction({
                 programId,
@@ -71,13 +71,13 @@ describe('Token Group Instructions', () => {
                 currentAuthority: updateAuthority,
                 newAuthority: PublicKey.default,
             }),
-            splDiscriminate('spl_token_group_interface:update_authority'),
+            await splDiscriminate('spl_token_group_interface:update_authority'),
             getStructDecoder([['newAuthority', fixDecoderSize(getBytesDecoder(), 32)]]),
             { newAuthority: Uint8Array.from(PublicKey.default.toBuffer()) },
         );
     });
 
-    it('Can create InitializeMember Instruction', () => {
+    it('Can create InitializeMember Instruction', async () => {
         const member = new PublicKey('22222222222222222222222222222222222222222222');
         const memberMint = new PublicKey('33333333333333333333333333333333333333333333');
         const memberMintAuthority = new PublicKey('44444444444444444444444444444444444444444444');
@@ -93,7 +93,7 @@ describe('Token Group Instructions', () => {
                 group,
                 groupUpdateAuthority,
             }),
-            splDiscriminate('spl_token_group_interface:initialize_member'),
+            await splDiscriminate('spl_token_group_interface:initialize_member'),
             getStructDecoder([]),
             {},
         );
diff --git a/token-metadata/js/test/instruction.test.ts b/token-metadata/js/test/instruction.test.ts
index a9dded10b..2641238cc 100644
--- a/token-metadata/js/test/instruction.test.ts
+++ b/token-metadata/js/test/instruction.test.ts
@@ -48,7 +48,7 @@ describe('Token Metadata Instructions', () => {
     const mint = new PublicKey('55555555555555555555555555555555555555555555');
     const mintAuthority = new PublicKey('66666666666666666666666666666666666666666666');
 
-    it('Can create Initialize Instruction', () => {
+    it('Can create Initialize Instruction', async () => {
         const name = 'My test token';
         const symbol = 'TEST';
         const uri = 'http://test.test';
@@ -63,7 +63,7 @@ describe('Token Metadata Instructions', () => {
                 symbol,
                 uri,
             }),
-            splDiscriminate('spl_token_metadata_interface:initialize_account'),
+            await splDiscriminate('spl_token_metadata_interface:initialize_account'),
             getStructDecoder([
                 ['name', getStringDecoder()],
                 ['symbol', getStringDecoder()],
@@ -73,7 +73,7 @@ describe('Token Metadata Instructions', () => {
         );
     });
 
-    it('Can create Update Field Instruction', () => {
+    it('Can create Update Field Instruction', async () => {
         const field = 'MyTestField';
         const value = 'http://test.uri';
         checkPackUnpack(
@@ -84,7 +84,7 @@ describe('Token Metadata Instructions', () => {
                 field,
                 value,
             }),
-            splDiscriminate('spl_token_metadata_interface:updating_field'),
+            await splDiscriminate('spl_token_metadata_interface:updating_field'),
             getStructDecoder([
                 ['key', getDataEnumCodec(getFieldCodec())],
                 ['value', getStringDecoder()],
@@ -93,7 +93,7 @@ describe('Token Metadata Instructions', () => {
         );
     });
 
-    it('Can create Update Field Instruction with Field Enum', () => {
+    it('Can create Update Field Instruction with Field Enum', async () => {
         const field = 'Name';
         const value = 'http://test.uri';
         checkPackUnpack(
@@ -104,7 +104,7 @@ describe('Token Metadata Instructions', () => {
                 field,
                 value,
             }),
-            splDiscriminate('spl_token_metadata_interface:updating_field'),
+            await splDiscriminate('spl_token_metadata_interface:updating_field'),
             getStructDecoder([
                 ['key', getDataEnumCodec(getFieldCodec())],
                 ['value', getStringDecoder()],
@@ -113,7 +113,7 @@ describe('Token Metadata Instructions', () => {
         );
     });
 
-    it('Can create Remove Key Instruction', () => {
+    it('Can create Remove Key Instruction', async () => {
         checkPackUnpack(
             createRemoveKeyInstruction({
                 programId,
@@ -122,7 +122,7 @@ describe('Token Metadata Instructions', () => {
                 key: 'MyTestField',
                 idempotent: true,
             }),
-            splDiscriminate('spl_token_metadata_interface:remove_key_ix'),
+            await splDiscriminate('spl_token_metadata_interface:remove_key_ix'),
             getStructDecoder([
                 ['idempotent', getBooleanDecoder()],
                 ['key', getStringDecoder()],
@@ -131,7 +131,7 @@ describe('Token Metadata Instructions', () => {
         );
     });
 
-    it('Can create Update Authority Instruction', () => {
+    it('Can create Update Authority Instruction', async () => {
         const newAuthority = PublicKey.default;
         checkPackUnpack(
             createUpdateAuthorityInstruction({
@@ -140,13 +140,13 @@ describe('Token Metadata Instructions', () => {
                 oldAuthority: updateAuthority,
                 newAuthority,
             }),
-            splDiscriminate('spl_token_metadata_interface:update_the_authority'),
+            await splDiscriminate('spl_token_metadata_interface:update_the_authority'),
             getStructDecoder([['newAuthority', fixDecoderSize(getBytesDecoder(), 32)]]),
             { newAuthority: Uint8Array.from(newAuthority.toBuffer()) },
         );
     });
 
-    it('Can create Emit Instruction', () => {
+    it('Can create Emit Instruction', async () => {
         const start: Option<bigint> = some(0n);
         const end: Option<bigint> = some(10n);
         checkPackUnpack(
@@ -156,7 +156,7 @@ describe('Token Metadata Instructions', () => {
                 start: 0n,
                 end: 10n,
             }),
-            splDiscriminate('spl_token_metadata_interface:emitter'),
+            await splDiscriminate('spl_token_metadata_interface:emitter'),
             getStructDecoder([
                 ['start', getOptionDecoder(getU64Decoder())],
                 ['end', getOptionDecoder(getU64Decoder())],