Pārlūkot izejas kodu

Add initializeMint test for JS client

Loris Leiva 1 gadu atpakaļ
vecāks
revīzija
60482a813e

+ 5 - 3
clients/js/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@solana-program/token",
-  "version": "0.0.0",
+  "version": "0.1.0",
   "description": "JavaScript client for the Token program",
   "sideEffects": false,
   "module": "./dist/src/index.js",
@@ -25,7 +25,8 @@
     "lint": "eslint --ext js,ts,tsx src",
     "lint:fix": "eslint --fix --ext js,ts,tsx src",
     "format": "prettier --check src test",
-    "format:fix": "prettier --write src test"
+    "format:fix": "prettier --write src test",
+    "prepublishOnly": "pnpm build"
   },
   "publishConfig": {
     "access": "public",
@@ -33,13 +34,14 @@
   },
   "license": "MIT",
   "peerDependencies": {
-    "@solana/web3.js": "tp3"
+    "@solana/web3.js": "2.0.0-preview.3"
   },
   "devDependencies": {
     "@ava/typescript": "^4.1.0",
     "@solana/eslint-config-solana": "^3.0.0",
     "@solana/web3.js": "tp3",
     "@solana/webcrypto-ed25519-polyfill": "tp3",
+    "@solana-program/system": "^0.3.1",
     "@typescript-eslint/eslint-plugin": "^7.3.1",
     "@typescript-eslint/parser": "^7.3.1",
     "ava": "^6.1.2",

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 134 - 368
clients/js/pnpm-lock.yaml


+ 8 - 3
clients/js/src/generated/instructions/initializeMint.ts

@@ -30,6 +30,7 @@ import {
   getU32Encoder,
   getU8Decoder,
   getU8Encoder,
+  none,
   transformEncoder,
 } from '@solana/web3.js';
 import { TOKEN_PROGRAM_ADDRESS } from '../programs';
@@ -72,7 +73,7 @@ export type InitializeMintInstructionDataArgs = {
   /** Minting authority. */
   mintAuthority: Address;
   /** Optional authority that can freeze token accounts. */
-  freezeAuthority: OptionOrNullable<Address>;
+  freezeAuthority?: OptionOrNullable<Address>;
 };
 
 export function getInitializeMintInstructionDataEncoder(): Encoder<InitializeMintInstructionDataArgs> {
@@ -89,7 +90,11 @@ export function getInitializeMintInstructionDataEncoder(): Encoder<InitializeMin
         }),
       ],
     ]),
-    (value) => ({ ...value, discriminator: 0 })
+    (value) => ({
+      ...value,
+      discriminator: 0,
+      freezeAuthority: value.freezeAuthority ?? none(),
+    })
   );
 }
 
@@ -128,7 +133,7 @@ export type InitializeMintInput<
   rent?: Address<TAccountRent>;
   decimals: InitializeMintInstructionDataArgs['decimals'];
   mintAuthority: InitializeMintInstructionDataArgs['mintAuthority'];
-  freezeAuthority: InitializeMintInstructionDataArgs['freezeAuthority'];
+  freezeAuthority?: InitializeMintInstructionDataArgs['freezeAuthority'];
 };
 
 export function getInitializeMintInstruction<

+ 8 - 3
clients/js/src/generated/instructions/initializeMint2.ts

@@ -27,6 +27,7 @@ import {
   getStructEncoder,
   getU8Decoder,
   getU8Encoder,
+  none,
   transformEncoder,
 } from '@solana/web3.js';
 import { TOKEN_PROGRAM_ADDRESS } from '../programs';
@@ -63,7 +64,7 @@ export type InitializeMint2InstructionDataArgs = {
   /** The authority/multisignature to mint tokens. */
   mintAuthority: Address;
   /** The optional freeze authority/multisignature of the mint. */
-  freezeAuthority: OptionOrNullable<Address>;
+  freezeAuthority?: OptionOrNullable<Address>;
 };
 
 export function getInitializeMint2InstructionDataEncoder(): Encoder<InitializeMint2InstructionDataArgs> {
@@ -74,7 +75,11 @@ export function getInitializeMint2InstructionDataEncoder(): Encoder<InitializeMi
       ['mintAuthority', getAddressEncoder()],
       ['freezeAuthority', getOptionEncoder(getAddressEncoder())],
     ]),
-    (value) => ({ ...value, discriminator: 20 })
+    (value) => ({
+      ...value,
+      discriminator: 20,
+      freezeAuthority: value.freezeAuthority ?? none(),
+    })
   );
 }
 
@@ -102,7 +107,7 @@ export type InitializeMint2Input<TAccountMint extends string = string> = {
   mint: Address<TAccountMint>;
   decimals: InitializeMint2InstructionDataArgs['decimals'];
   mintAuthority: InitializeMint2InstructionDataArgs['mintAuthority'];
-  freezeAuthority: InitializeMint2InstructionDataArgs['freezeAuthority'];
+  freezeAuthority?: InitializeMint2InstructionDataArgs['freezeAuthority'];
 };
 
 export function getInitializeMint2Instruction<TAccountMint extends string>(

+ 0 - 42
clients/js/test/create.test.ts

@@ -1,42 +0,0 @@
-import {
-  Account,
-  appendTransactionMessageInstruction,
-  pipe,
-} from '@solana/web3.js';
-import test from 'ava';
-import {
-  Counter,
-  fetchCounterFromSeeds,
-  getCreateInstructionAsync,
-} from '../src/index.js';
-import {
-  createDefaultSolanaClient,
-  createDefaultTransaction,
-  generateKeyPairSignerWithSol,
-  signAndSendTransaction,
-} from './_setup.js';
-
-test('it creates a new counter account', async (t) => {
-  // Given an authority key pair with some SOL.
-  const client = createDefaultSolanaClient();
-  const authority = await generateKeyPairSignerWithSol(client);
-
-  // When we create a new counter account.
-  const createIx = await getCreateInstructionAsync({ authority });
-  await pipe(
-    await createDefaultTransaction(client, authority),
-    (tx) => appendTransactionMessageInstruction(createIx, tx),
-    (tx) => signAndSendTransaction(client, tx)
-  );
-
-  // Then we expect the counter account to exist and have a value of 0.
-  const counter = await fetchCounterFromSeeds(client.rpc, {
-    authority: authority.address,
-  });
-  t.like(counter, <Account<Counter>>{
-    data: {
-      authority: authority.address,
-      value: 0,
-    },
-  });
-});

+ 0 - 141
clients/js/test/increment.test.ts

@@ -1,141 +0,0 @@
-import {
-  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
-  appendTransactionMessageInstruction,
-  isProgramError,
-  isSolanaError,
-  lamports,
-  pipe,
-} from '@solana/web3.js';
-import test from 'ava';
-import {
-  TOKEN_ERROR__INVALID_PDA,
-  TOKEN_ERROR__INVALID_PROGRAM_OWNER,
-  TOKEN_PROGRAM_ADDRESS,
-  fetchCounter,
-  findCounterPda,
-  getIncrementInstruction,
-  getIncrementInstructionAsync,
-} from '../src/index.js';
-import {
-  createCounterForAuthority,
-  createDefaultSolanaClient,
-  createDefaultTransaction,
-  generateKeyPairSignerWithSol,
-  getBalance,
-  signAndSendTransaction,
-} from './_setup.js';
-
-test('it increments an existing counter by 1 by default', async (t) => {
-  // Given an authority key pair with an associated counter account of value 0.
-  const client = createDefaultSolanaClient();
-  const authority = await generateKeyPairSignerWithSol(client);
-  const [counterPda] = await createCounterForAuthority(client, authority);
-  t.is((await fetchCounter(client.rpc, counterPda)).data.value, 0);
-
-  // When we increment the counter account.
-  const incrementIx = await getIncrementInstructionAsync({ authority });
-  await pipe(
-    await createDefaultTransaction(client, authority),
-    (tx) => appendTransactionMessageInstruction(incrementIx, tx),
-    (tx) => signAndSendTransaction(client, tx)
-  );
-
-  // Then we expect the counter account to have a value of 1.
-  const counter = await fetchCounter(client.rpc, counterPda);
-  t.is(counter.data.value, 1);
-});
-
-test('it can increment an existing counter by a specified amount', async (t) => {
-  // Given an authority key pair with an associated counter account of value 0.
-  const client = createDefaultSolanaClient();
-  const authority = await generateKeyPairSignerWithSol(client);
-  const [counterPda] = await createCounterForAuthority(client, authority);
-  t.is((await fetchCounter(client.rpc, counterPda)).data.value, 0);
-
-  // When we increment the counter account by 5.
-  const incrementIx = await getIncrementInstructionAsync({
-    authority,
-    amount: 5,
-  });
-  await pipe(
-    await createDefaultTransaction(client, authority),
-    (tx) => appendTransactionMessageInstruction(incrementIx, tx),
-    (tx) => signAndSendTransaction(client, tx)
-  );
-
-  // Then we expect the counter account to have a value of 5.
-  const counter = await fetchCounter(client.rpc, counterPda);
-  t.is(counter.data.value, 5);
-});
-
-test('it cannot increment a counter that does not exist', async (t) => {
-  // Given an authority key pair with no associated counter account.
-  const client = createDefaultSolanaClient();
-  const authority = await generateKeyPairSignerWithSol(client);
-  const [counterPda] = await findCounterPda({ authority: authority.address });
-  t.is(await getBalance(client, counterPda), lamports(0n));
-
-  // When we try to increment the inexistent counter account.
-  const incrementIx = await getIncrementInstructionAsync({ authority });
-  const transactionMessage = pipe(
-    await createDefaultTransaction(client, authority),
-    (tx) => appendTransactionMessageInstruction(incrementIx, tx)
-  );
-  const promise = signAndSendTransaction(client, transactionMessage);
-
-  // Then we expect the program to throw an error.
-  const error = await t.throwsAsync(promise);
-  t.true(
-    isSolanaError(
-      error,
-      SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE
-    )
-  );
-  t.true(
-    isProgramError(
-      error.cause,
-      transactionMessage,
-      TOKEN_PROGRAM_ADDRESS,
-      TOKEN_ERROR__INVALID_PROGRAM_OWNER
-    )
-  );
-});
-
-test('it cannot increment a counter that belongs to another authority', async (t) => {
-  // Given two authority key pairs such that
-  // only one of them (authority A) is associated with a counter account.
-  const client = createDefaultSolanaClient();
-  const [authorityA, authorityB] = await Promise.all([
-    generateKeyPairSignerWithSol(client),
-    generateKeyPairSignerWithSol(client),
-  ]);
-  const [counterPda] = await createCounterForAuthority(client, authorityA);
-
-  // When authority B tries to increment the counter account of authority A.
-  const incrementIx = getIncrementInstruction({
-    authority: authorityB,
-    counter: counterPda,
-  });
-  const transactionMessage = pipe(
-    await createDefaultTransaction(client, authorityB),
-    (tx) => appendTransactionMessageInstruction(incrementIx, tx)
-  );
-  const promise = signAndSendTransaction(client, transactionMessage);
-
-  // Then we expect the program to throw an error.
-  const error = await t.throwsAsync(promise);
-  t.true(
-    isSolanaError(
-      error,
-      SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE
-    )
-  );
-  t.true(
-    isProgramError(
-      error.cause,
-      transactionMessage,
-      TOKEN_PROGRAM_ADDRESS,
-      TOKEN_ERROR__INVALID_PDA
-    )
-  );
-});

+ 66 - 0
clients/js/test/initializeMint.test.ts

@@ -0,0 +1,66 @@
+import { getCreateAccountInstruction } from '@solana-program/system';
+import {
+  Account,
+  appendTransactionMessageInstructions,
+  generateKeyPairSigner,
+  none,
+  pipe,
+  some,
+} from '@solana/web3.js';
+import test from 'ava';
+import {
+  Mint,
+  TOKEN_PROGRAM_ADDRESS,
+  fetchMint,
+  getInitializeMintInstruction,
+  getMintSize,
+} from '../src/index.js';
+import {
+  createDefaultSolanaClient,
+  createDefaultTransaction,
+  generateKeyPairSignerWithSol,
+  signAndSendTransaction,
+} from './_setup.js';
+
+test('it creates and initializes a new mint account', async (t) => {
+  // Given an authority and a mint account.
+  const client = createDefaultSolanaClient();
+  const authority = await generateKeyPairSignerWithSol(client);
+  const mint = await generateKeyPairSigner();
+
+  // When we create and initialize a mint account at this address.
+  const space = BigInt(getMintSize());
+  const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();
+  const instructions = [
+    getCreateAccountInstruction({
+      payer: authority,
+      newAccount: mint,
+      lamports: rent,
+      space,
+      programAddress: TOKEN_PROGRAM_ADDRESS,
+    }),
+    getInitializeMintInstruction({
+      mint: mint.address,
+      decimals: 2,
+      mintAuthority: authority.address,
+    }),
+  ];
+  await pipe(
+    await createDefaultTransaction(client, authority),
+    (tx) => appendTransactionMessageInstructions(instructions, tx),
+    (tx) => signAndSendTransaction(client, tx)
+  );
+
+  // Then we expect the mint account to exist and have the following data.
+  const mintAccount = await fetchMint(client.rpc, mint.address);
+  t.like(mintAccount, <Account<Mint>>{
+    address: mint.address,
+    data: {
+      mintAuthority: some(authority.address),
+      supply: 0n,
+      decimals: 2,
+      isInitialized: true,
+      freezeAuthority: none(),
+    },
+  });
+});

+ 6 - 0
program/idl.json

@@ -330,6 +330,9 @@
               },
               "fixed": true
             },
+            "defaultValue": {
+              "kind": "noneValueNode"
+            },
             "docs": ["Optional authority that can freeze token accounts."]
           }
         ],
@@ -1838,6 +1841,9 @@
               },
               "fixed": false
             },
+            "defaultValue": {
+              "kind": "noneValueNode"
+            },
             "docs": [
               "The optional freeze authority/multisignature of the mint."
             ]

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels