From 7c9a91e589048d5be210293ca3344857022728d4 Mon Sep 17 00:00:00 2001 From: Joe C Date: Thu, 2 May 2024 15:27:30 -0500 Subject: [PATCH] refactor(experimental): graphql: token-2022 extensions: default account state This PR adds support for Token-2022's `DefaultAccountState` extension in the GraphQL schema. cc @Hrushi20. Continuing work on #2406. --- .../rpc-graphql/src/__tests__/__setup__.ts | 30 ++++++ .../src/__tests__/transaction-tests.ts | 100 ++++++++++++++++++ .../rpc-graphql/src/resolvers/instruction.ts | 19 ++++ .../rpc-graphql/src/schema/instruction.ts | 27 +++++ 4 files changed, 176 insertions(+) diff --git a/packages/rpc-graphql/src/__tests__/__setup__.ts b/packages/rpc-graphql/src/__tests__/__setup__.ts index 4b70454f4602..812b0e03c022 100644 --- a/packages/rpc-graphql/src/__tests__/__setup__.ts +++ b/packages/rpc-graphql/src/__tests__/__setup__.ts @@ -1715,6 +1715,36 @@ export const mockTransactionToken2022AllExtensions = { programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', stackHeight: null, }, + { + parsed: { + info: { + accountState: 'frozen', + freezeAuthority: '2Pwe6Yahh5cbzvCwRMtTYFeboSwYiWeHhYJzZZBsU6eB', + mint: 'FsHcsGiY43QmZc6yTgwYC1DA5U3ZgycXxn3bd2oBjrEZ', + }, + type: 'updateDefaultAccountState', + }, + program: 'spl-token', + programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + stackHeight: null, + }, + { + parsed: { + info: { + accountState: 'frozen', + mint: 'FsHcsGiY43QmZc6yTgwYC1DA5U3ZgycXxn3bd2oBjrEZ', + multisigFreezeAuthority: '2Pwe6Yahh5cbzvCwRMtTYFeboSwYiWeHhYJzZZBsU6eB', + signers: [ + '2Pwe6Yahh5cbzvCwRMtTYFeboSwYiWeHhYJzZZBsU6eB', + '2Pwe6Yahh5cbzvCwRMtTYFeboSwYiWeHhYJzZZBsU6eB', + ], + }, + type: 'updateDefaultAccountState', + }, + program: 'spl-token', + programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + stackHeight: null, + }, // Initializing Account Extensions. { parsed: { diff --git a/packages/rpc-graphql/src/__tests__/transaction-tests.ts b/packages/rpc-graphql/src/__tests__/transaction-tests.ts index 4f9992232eae..758651bae43b 100644 --- a/packages/rpc-graphql/src/__tests__/transaction-tests.ts +++ b/packages/rpc-graphql/src/__tests__/transaction-tests.ts @@ -1262,6 +1262,106 @@ describe('transaction', () => { }, }); }); + it('initialize-default-account-state', async () => { + expect.assertions(1); + const source = /* GraphQL */ ` + query testQuery($signature: Signature!) { + transaction(signature: $signature) { + message { + instructions { + programId + ... on SplTokenInitializeDefaultAccountStateInstruction { + accountState + mint { + address + } + } + } + } + } + } + `; + const result = await rpcGraphQL.query(source, { signature }); + expect(result).toMatchObject({ + data: { + transaction: { + message: { + instructions: expect.arrayContaining([ + { + accountState: expect.any(String), + mint: { + address: expect.any(String), + }, + programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + }, + ]), + }, + }, + }, + }); + }); + it('update-default-account-state', async () => { + expect.assertions(1); + const source = /* GraphQL */ ` + query testQuery($signature: Signature!) { + transaction(signature: $signature) { + message { + instructions { + programId + ... on SplTokenUpdateDefaultAccountStateInstruction { + accountState + freezeAuthority { + address + } + mint { + address + } + multisigFreezeAuthority { + address + } + signers + } + } + } + } + } + `; + const result = await rpcGraphQL.query(source, { signature }); + expect(result).toMatchObject({ + data: { + transaction: { + message: { + instructions: expect.arrayContaining([ + { + accountState: expect.any(String), + freezeAuthority: { + address: expect.any(String), + }, + mint: { + address: expect.any(String), + }, + multisigFreezeAuthority: null, + programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + signers: null, + }, + { + accountState: expect.any(String), + freezeAuthority: null, + mint: { + address: expect.any(String), + }, + multisigFreezeAuthority: { + address: expect.any(String), + }, + programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + signers: expect.arrayContaining([expect.any(String)]), + }, + ]), + }, + }, + }, + }); + }); }); }); }); diff --git a/packages/rpc-graphql/src/resolvers/instruction.ts b/packages/rpc-graphql/src/resolvers/instruction.ts index 31074364fee5..b459ab05e768 100644 --- a/packages/rpc-graphql/src/resolvers/instruction.ts +++ b/packages/rpc-graphql/src/resolvers/instruction.ts @@ -182,6 +182,11 @@ export const instructionResolvers = { multisigOwner: resolveAccount('multisigOwner'), owner: resolveAccount('owner'), }, + SplTokenDefaultAccountState: { + FROZEN: 'frozen', + INITIALIZED: 'initialized', + UNINITIALIZED: 'uninitialized', + }, SplTokenFreezeAccountInstruction: { account: resolveAccount('account'), freezeAuthority: resolveAccount('freezeAuthority'), @@ -208,6 +213,9 @@ export const instructionResolvers = { owner: resolveAccount('owner'), rentSysvar: resolveAccount('rentSysvar'), }, + SplTokenInitializeDefaultAccountStateInstruction: { + mint: resolveAccount('mint'), + }, SplTokenInitializeGroupMemberPointerInstruction: { authority: resolveAccount('authority'), memberAddress: resolveAccount('memberAddress'), @@ -308,6 +316,11 @@ export const instructionResolvers = { SplTokenUiAmountToAmountInstruction: { mint: resolveAccount('mint'), }, + SplTokenUpdateDefaultAccountStateInstruction: { + freezeAuthority: resolveAccount('freezeAuthority'), + mint: resolveAccount('mint'), + multisigFreezeAuthority: resolveAccount('multisigFreezeAuthority'), + }, SplTokenUpdateGroupMemberPointerInstruction: { authority: resolveAccount('authority'), memberAddress: resolveAccount('memberAddress'), @@ -607,6 +620,12 @@ export const instructionResolvers = { if (jsonParsedConfigs.instructionType === 'updateTransferHook') { return 'SplTokenUpdateTransferHookInstruction'; } + if (jsonParsedConfigs.instructionType === 'initializeDefaultAccountState') { + return 'SplTokenInitializeDefaultAccountStateInstruction'; + } + if (jsonParsedConfigs.instructionType === 'updateDefaultAccountState') { + return 'SplTokenUpdateDefaultAccountStateInstruction'; + } } if (jsonParsedConfigs.programName === 'stake') { if (jsonParsedConfigs.instructionType === 'initialize') { diff --git a/packages/rpc-graphql/src/schema/instruction.ts b/packages/rpc-graphql/src/schema/instruction.ts index 39379f15a10a..2df0aa93f9d9 100644 --- a/packages/rpc-graphql/src/schema/instruction.ts +++ b/packages/rpc-graphql/src/schema/instruction.ts @@ -503,6 +503,33 @@ export const instructionTypeDefs = /* GraphQL */ ` uiAmount: String } + enum SplTokenDefaultAccountState { + FROZEN + INITIALIZED + UNINITIALIZED + } + + """ + SplToken-2022: InitializeDefaultAccountState instruction + """ + type SplTokenInitializeDefaultAccountStateInstruction implements TransactionInstruction { + programId: Address + accountState: SplTokenDefaultAccountState + mint: Account + } + + """ + SplToken-2022: UpdateDefaultAccountState instruction + """ + type SplTokenUpdateDefaultAccountStateInstruction implements TransactionInstruction { + programId: Address + accountState: SplTokenDefaultAccountState + freezeAuthority: Account + mint: Account + multisigFreezeAuthority: Account + signers: [Address] + } + """ SplToken-2022: InitializeMintCloseAuthority instruction """