From 1b12bd391fd90938add3ba259fcdac75e0d53216 Mon Sep 17 00:00:00 2001 From: Joe C Date: Tue, 28 Nov 2023 08:18:50 -0500 Subject: [PATCH] refactor(experimental-graphql): revise accounts schema (again) This PR attempts to revise the accounts schema, as per #1831. --- .../rpc-graphql/src/__tests__/account-test.ts | 625 +++++++++--------- .../src/__tests__/program-accounts-test.ts | 437 ++++++------ packages/rpc-graphql/src/loaders/account.ts | 74 +-- .../src/loaders/program-accounts.ts | 66 +- .../src/loaders/transformers/account.ts | 56 ++ packages/rpc-graphql/src/schema/account.ts | 172 ++--- 6 files changed, 692 insertions(+), 738 deletions(-) create mode 100644 packages/rpc-graphql/src/loaders/transformers/account.ts diff --git a/packages/rpc-graphql/src/__tests__/account-test.ts b/packages/rpc-graphql/src/__tests__/account-test.ts index 682f21d64d25..005a36d5207e 100644 --- a/packages/rpc-graphql/src/__tests__/account-test.ts +++ b/packages/rpc-graphql/src/__tests__/account-test.ts @@ -84,6 +84,7 @@ describe('account', () => { executable lamports rentEpoch + space } } `; @@ -94,6 +95,7 @@ describe('account', () => { executable: false, lamports: 10290815n, rentEpoch: 0n, + space: 165n, }, }, }); @@ -105,16 +107,17 @@ describe('account', () => { address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', commitment: 'confirmed', }; - it("can perform a nested query for the account's owner", async () => { + it("can perform a nested query for the account's ownerProgram", async () => { expect.assertions(1); const source = /* GraphQL */ ` query testQuery($address: String!, $commitment: Commitment) { account(address: $address, commitment: $commitment) { - owner { + ownerProgram { address executable lamports rentEpoch + space } } } @@ -123,11 +126,12 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - owner: { + ownerProgram: { address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', executable: true, lamports: expect.any(BigInt), rentEpoch: expect.any(BigInt), + space: 133352n, }, }, }, @@ -140,18 +144,19 @@ describe('account', () => { address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', commitment: 'confirmed', }; - it("can perform a double nested query for each account's owner", async () => { + it("can perform a double nested query for each account's ownerProgram", async () => { expect.assertions(1); const source = /* GraphQL */ ` query testQuery($address: String!, $commitment: Commitment) { account(address: $address, commitment: $commitment) { - owner { + ownerProgram { address - owner { + ownerProgram { address executable lamports rentEpoch + space } } } @@ -161,13 +166,14 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - owner: { + ownerProgram: { address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', - owner: { + ownerProgram: { address: 'BPFLoader2111111111111111111111111111111111', executable: true, lamports: expect.any(BigInt), rentEpoch: expect.any(BigInt), + space: 25n, }, }, }, @@ -181,16 +187,16 @@ describe('account', () => { address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', commitment: 'confirmed', }; - it("can perform a triple nested query for each account's owner", async () => { + it("can perform a triple nested query for each account's ownerProgram", async () => { expect.assertions(1); const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - owner { + ownerProgram { address - owner { + ownerProgram { address - owner { + ownerProgram { address } } @@ -202,11 +208,11 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - owner: { + ownerProgram: { address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', - owner: { + ownerProgram: { address: 'BPFLoader2111111111111111111111111111111111', - owner: { + ownerProgram: { address: 'NativeLoader1111111111111111111111111111111', }, }, @@ -227,7 +233,7 @@ describe('account', () => { const source = /* GraphQL */ ` query testQuery($address: String!, $encoding: AccountEncoding) { account(address: $address, encoding: $encoding) { - encoding + address ... on AccountBase58 { data } @@ -238,8 +244,8 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { + address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk', data: '2Uw1bpnsXxu3e', - encoding: 'BASE_58', }, }, }); @@ -254,7 +260,7 @@ describe('account', () => { const source = /* GraphQL */ ` query testQuery($address: String!, $encoding: AccountEncoding) { account(address: $address, encoding: $encoding) { - encoding + address ... on AccountBase64 { data } @@ -265,8 +271,8 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { + address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk', data: 'dGVzdCBkYXRh', - encoding: 'BASE_64', }, }, }); @@ -281,7 +287,7 @@ describe('account', () => { const source = /* GraphQL */ ` query testQuery($address: String!, $encoding: AccountEncoding) { account(address: $address, encoding: $encoding) { - encoding + address ... on AccountBase64Zstd { data } @@ -292,8 +298,8 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { + address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk', data: 'KLUv/QBYSQAAdGVzdCBkYXRh', - encoding: 'BASE_64_ZSTD', }, }, }); @@ -303,14 +309,11 @@ describe('account', () => { const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address, encoding: PARSED) { - encoding ... on AccountBase64 { data } ... on MintAccount { - mintData: data { - supply - } + supply } } } @@ -322,10 +325,7 @@ describe('account', () => { expect(resultParsed).toMatchObject({ data: { account: { - encoding: 'PARSED', - mintData: { - supply: expect.any(String), - }, + supply: expect.any(String), }, }, }); @@ -338,7 +338,6 @@ describe('account', () => { data: { account: { data: 'dGVzdCBkYXRh', - encoding: 'BASE_64', }, }, }); @@ -352,11 +351,8 @@ describe('account', () => { const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - encoding ... on MintAccount { - mintData: data { - supply - } + supply } } } @@ -365,39 +361,36 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - encoding: 'PARSED', - mintData: { - supply: expect.any(String), - }, + supply: expect.any(String), }, }, }); }); }); describe('specific account type queries', () => { - it('can get a mint account', async () => { + it('can get a nonce account', async () => { expect.assertions(1); - // See scripts/fixtures/spl-token-mint-account.json + // See scripts/fixtures/nonce-account.json const variableValues = { - address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', + address: 'AiZExP8mK4RxDozh4r57knvqSZgkz86HrzPAMx61XMqU', }; const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - ... on MintAccount { - data { - decimals - isInitialized - mintAuthority { - address - lamports - } - supply + address + lamports + ownerProgram { + address + } + rentEpoch + space + ... on NonceAccount { + authority { + address } - meta { - program - space - type + blockhash + feeCalculator { + lamportsPerSignature } } } @@ -407,55 +400,48 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - data: { - decimals: 6, - isInitialized: true, - mintAuthority: { - address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', - lamports: expect.any(BigInt), - }, - supply: expect.any(String), + address: 'AiZExP8mK4RxDozh4r57knvqSZgkz86HrzPAMx61XMqU', + authority: { + address: '3xxDCjN8s6MgNHwdRExRLa6gHmmRTWPnUdzkbKfEgNAe', }, - meta: { - program: 'spl-token', - space: 82n, - type: 'mint', + blockhash: expect.any(String), + feeCalculator: { + lamportsPerSignature: expect.any(String), + }, + lamports: expect.any(BigInt), + ownerProgram: { + address: '11111111111111111111111111111111', }, + rentEpoch: expect.any(BigInt), + space: 80n, }, }, }); }); - it('can get a token account', async () => { + it('can get an address lookup table account', async () => { expect.assertions(1); - // See scripts/fixtures/spl-token-token-account.json + // See scripts/fixtures/address-lookup-table-account.json const variableValues = { - address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', + address: '2JPQuT3dHtPjrdcbUQyrrT4XYRYaWpWfmAJ54SUapg6n', }; const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - ... on TokenAccount { - data { - isNative - mint { - address - } - owner { - address - } - state - tokenAmount { - amount - decimals - uiAmount - uiAmountString - } - } - meta { - program - space - type + address + lamports + ownerProgram { + address + } + rentEpoch + space + ... on LookupTableAccount { + addresses + authority { + address } + deactivationSlot + lastExtendedSlot + lastExtendedSlotStartIndex } } } @@ -464,54 +450,48 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - data: { - isNative: expect.any(Boolean), - mint: { - address: expect.any(String), - }, - owner: { - address: '6UsGbaMgchgj4wiwKKuE1v5URHdcDfEiMSM25QpesKir', - }, - state: expect.any(String), - tokenAmount: { - amount: expect.any(String), - decimals: expect.any(Number), - uiAmountString: expect.any(String), - }, + address: '2JPQuT3dHtPjrdcbUQyrrT4XYRYaWpWfmAJ54SUapg6n', + addresses: expect.any(Array), + authority: { + address: '4msgK65vdz5ADUAB3eTQGpF388NuQUAoknLxutUQJd5B', }, - meta: { - program: 'spl-token', - space: 165n, - type: 'account', + deactivationSlot: expect.any(String), + lamports: expect.any(BigInt), + lastExtendedSlot: expect.any(String), + lastExtendedSlotStartIndex: expect.any(Number), + ownerProgram: { + address: 'AddressLookupTab1e1111111111111111111111111', }, + rentEpoch: expect.any(BigInt), + space: 1304n, }, }, }); }); - it('can get a nonce account', async () => { + it('can get a mint account', async () => { expect.assertions(1); - // See scripts/fixtures/nonce-account.json + // See scripts/fixtures/spl-token-mint-account.json const variableValues = { - address: 'AiZExP8mK4RxDozh4r57knvqSZgkz86HrzPAMx61XMqU', + address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', }; const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - ... on NonceAccount { - data { - authority { - address - } - blockhash - feeCalculator { - lamportsPerSignature - } - } - meta { - program - space - type + address + lamports + ownerProgram { + address + } + rentEpoch + space + ... on MintAccount { + decimals + isInitialized + mintAuthority { + address + lamports } + supply } } } @@ -520,69 +500,54 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - data: { - authority: { - address: '3xxDCjN8s6MgNHwdRExRLa6gHmmRTWPnUdzkbKfEgNAe', - }, - blockhash: expect.any(String), - feeCalculator: { - lamportsPerSignature: expect.any(String), - }, + address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', + decimals: 6, + isInitialized: true, + lamports: expect.any(BigInt), + mintAuthority: { + address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', + lamports: expect.any(BigInt), }, - meta: { - program: 'nonce', - space: 80n, - type: 'initialized', + ownerProgram: { + address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }, + rentEpoch: expect.any(BigInt), + space: 82n, + supply: expect.any(String), }, }, }); }); - it('can get a stake account', async () => { + it('can get a token account', async () => { expect.assertions(1); - // See scripts/fixtures/stake-account.json + // See scripts/fixtures/spl-token-token-account.json const variableValues = { - address: 'CSg2vQGbnwWdSyJpwK4i3qGfB6FebaV3xQTx4U1MbixN', + address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', }; const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - ... on StakeAccount { - data { - meta { - authorized { - staker { - address - } - withdrawer { - address - } - } - lockup { - custodian { - address - } - epoch - unixTimestamp - } - rentExemptReserve - } - stake { - creditsObserved - delegation { - activationEpoch - deactivationEpoch - stake - voter { - address - } - } - } + address + lamports + ownerProgram { + address + } + rentEpoch + space + ... on TokenAccount { + isNative + mint { + address } - meta { - program - space - type + owner { + address + } + state + tokenAmount { + amount + decimals + uiAmount + uiAmountString } } } @@ -592,90 +557,75 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - data: { - meta: { - authorized: { - staker: { - address: '3HRNKNXafhr3wE9NSXRpNVdFYt6EVygdqFwqf6WpG57V', - }, - withdrawer: { - address: '3HRNKNXafhr3wE9NSXRpNVdFYt6EVygdqFwqf6WpG57V', - }, - }, - lockup: { - custodian: { - address: '11111111111111111111111111111111', - }, - epoch: expect.any(BigInt), - unixTimestamp: expect.any(BigInt), - }, - rentExemptReserve: expect.any(String), - }, - stake: { - creditsObserved: expect.any(BigInt), - delegation: { - activationEpoch: expect.any(BigInt), - deactivationEpoch: expect.any(BigInt), - stake: expect.any(String), - voter: { - address: 'CertusDeBmqN8ZawdkxK5kFGMwBXdudvWHYwtNgNhvLu', - }, - }, - }, + address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', + isNative: expect.any(Boolean), + lamports: expect.any(BigInt), + mint: { + address: expect.any(String), }, - meta: { - program: 'stake', - space: 200n, - type: 'delegated', + owner: { + address: '6UsGbaMgchgj4wiwKKuE1v5URHdcDfEiMSM25QpesKir', + }, + ownerProgram: { + address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + }, + rentEpoch: expect.any(BigInt), + space: 165n, + state: expect.any(String), + tokenAmount: { + amount: expect.any(String), + decimals: expect.any(Number), + uiAmountString: expect.any(String), }, }, }, }); }); - it('can get a vote account', async () => { + it('can get a stake account', async () => { expect.assertions(1); - // See scripts/fixtures/vote-account.json + // See scripts/fixtures/stake-account.json const variableValues = { - address: '4QUZQ4c7bZuJ4o4L8tYAEGnePFV27SUFEVmC7BYfsXRp', + address: 'CSg2vQGbnwWdSyJpwK4i3qGfB6FebaV3xQTx4U1MbixN', }; const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - ... on VoteAccount { - data { - authorizedVoters { - authorizedVoter { + address + lamports + ownerProgram { + address + } + rentEpoch + space + ... on StakeAccount { + meta { + authorized { + staker { + address + } + withdrawer { address } - epoch - } - authorizedWithdrawer { - address } - commission - epochCredits { - credits + lockup { + custodian { + address + } epoch - previousCredits - } - lastTimestamp { - slot - timestamp - } - node { - address - } - priorVoters - rootSlot - votes { - confirmationCount - slot + unixTimestamp } + rentExemptReserve } - meta { - program - space - type + stake { + creditsObserved + delegation { + activationEpoch + deactivationEpoch + stake + voter { + address + } + } } } } @@ -685,74 +635,90 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - data: { - authorizedVoters: expect.arrayContaining([ - { - authorizedVoter: { - address: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr', - }, - epoch: expect.any(BigInt), + address: 'CSg2vQGbnwWdSyJpwK4i3qGfB6FebaV3xQTx4U1MbixN', + lamports: expect.any(BigInt), + meta: { + authorized: { + staker: { + address: '3HRNKNXafhr3wE9NSXRpNVdFYt6EVygdqFwqf6WpG57V', }, - ]), - authorizedWithdrawer: { - address: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr', - }, - commission: expect.any(Number), - epochCredits: expect.arrayContaining([ - { - credits: expect.any(String), - epoch: expect.any(BigInt), - previousCredits: expect.any(String), + withdrawer: { + address: '3HRNKNXafhr3wE9NSXRpNVdFYt6EVygdqFwqf6WpG57V', }, - ]), - lastTimestamp: { - slot: expect.any(BigInt), - timestamp: expect.any(BigInt), - }, - node: { - address: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr', }, - priorVoters: expect.any(Array), - rootSlot: expect.any(BigInt), - votes: expect.arrayContaining([ - { - confirmationCount: expect.any(Number), - slot: expect.any(BigInt), + lockup: { + custodian: { + address: '11111111111111111111111111111111', }, - ]), + epoch: expect.any(BigInt), + unixTimestamp: expect.any(BigInt), + }, + rentExemptReserve: expect.any(String), }, - meta: { - program: 'vote', - space: expect.any(BigInt), - type: 'vote', + ownerProgram: { + address: 'Stake11111111111111111111111111111111111111', + }, + rentEpoch: expect.any(BigInt), + space: 200n, + stake: { + creditsObserved: expect.any(BigInt), + delegation: { + activationEpoch: expect.any(BigInt), + deactivationEpoch: expect.any(BigInt), + stake: expect.any(String), + voter: { + address: 'CertusDeBmqN8ZawdkxK5kFGMwBXdudvWHYwtNgNhvLu', + }, + }, }, }, }, }); }); - it('can get an address lookup table account', async () => { + it('can get a vote account', async () => { expect.assertions(1); - // See scripts/fixtures/address-lookup-table-account.json + // See scripts/fixtures/vote-account.json const variableValues = { - address: '2JPQuT3dHtPjrdcbUQyrrT4XYRYaWpWfmAJ54SUapg6n', + address: '4QUZQ4c7bZuJ4o4L8tYAEGnePFV27SUFEVmC7BYfsXRp', }; const source = /* GraphQL */ ` query testQuery($address: String!) { account(address: $address) { - ... on LookupTableAccount { - data { - addresses - authority { + address + lamports + ownerProgram { + address + } + rentEpoch + space + ... on VoteAccount { + authorizedVoters { + authorizedVoter { address } - deactivationSlot - lastExtendedSlot - lastExtendedSlotStartIndex + epoch } - meta { - program - space - type + authorizedWithdrawer { + address + } + commission + epochCredits { + credits + epoch + previousCredits + } + lastTimestamp { + slot + timestamp + } + node { + address + } + priorVoters + rootSlot + votes { + confirmationCount + slot } } } @@ -762,20 +728,47 @@ describe('account', () => { expect(result).toMatchObject({ data: { account: { - data: { - addresses: expect.any(Array), - authority: { - address: '4msgK65vdz5ADUAB3eTQGpF388NuQUAoknLxutUQJd5B', + address: '4QUZQ4c7bZuJ4o4L8tYAEGnePFV27SUFEVmC7BYfsXRp', + authorizedVoters: expect.arrayContaining([ + { + authorizedVoter: { + address: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr', + }, + epoch: expect.any(BigInt), }, - deactivationSlot: expect.any(String), - lastExtendedSlot: expect.any(String), - lastExtendedSlotStartIndex: expect.any(Number), + ]), + authorizedWithdrawer: { + address: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr', }, - meta: { - program: 'address-lookup-table', - space: 1304n, - type: 'lookupTable', + commission: expect.any(Number), + epochCredits: expect.arrayContaining([ + { + credits: expect.any(String), + epoch: expect.any(BigInt), + previousCredits: expect.any(String), + }, + ]), + lamports: expect.any(BigInt), + lastTimestamp: { + slot: expect.any(BigInt), + timestamp: expect.any(BigInt), + }, + node: { + address: 'HMU77m6WSL9Xew9YvVCgz1hLuhzamz74eD9avi4XPdr', + }, + ownerProgram: { + address: 'Vote111111111111111111111111111111111111111', }, + priorVoters: expect.any(Array), + rentEpoch: expect.any(BigInt), + rootSlot: expect.any(BigInt), + space: 3731n, + votes: expect.arrayContaining([ + { + confirmationCount: expect.any(Number), + slot: expect.any(BigInt), + }, + ]), }, }, }); @@ -810,7 +803,7 @@ describe('account', () => { query testQuery { account(address: "CSg2vQGbnwWdSyJpwK4i3qGfB6FebaV3xQTx4U1MbixN") { address - owner { + ownerProgram { address } } @@ -821,7 +814,7 @@ describe('account', () => { data: { account: { address: 'CSg2vQGbnwWdSyJpwK4i3qGfB6FebaV3xQTx4U1MbixN', - owner: { + ownerProgram: { address: 'Stake11111111111111111111111111111111111111', }, }, @@ -837,9 +830,9 @@ describe('account', () => { query testQuery { account(address: "AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca") { address - owner { + ownerProgram { address - owner { + ownerProgram { address } } @@ -851,9 +844,9 @@ describe('account', () => { data: { account: { address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca', - owner: { + ownerProgram: { address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', - owner: { + ownerProgram: { address: 'BPFLoader2111111111111111111111111111111111', }, }, @@ -870,13 +863,11 @@ describe('account', () => { const source = ` query testQuery { account(address: "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr") { + address ... on MintAccount { - address - data { - mintAuthority { - address - lamports - } + mintAuthority { + address + lamports } } } @@ -887,11 +878,9 @@ describe('account', () => { data: { account: { address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', - data: { - mintAuthority: { - address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', - lamports: expect.any(BigInt), - }, + mintAuthority: { + address: 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr', + lamports: expect.any(BigInt), }, }, }, diff --git a/packages/rpc-graphql/src/__tests__/program-accounts-test.ts b/packages/rpc-graphql/src/__tests__/program-accounts-test.ts index f52f9800f556..a27d1609c0ae 100644 --- a/packages/rpc-graphql/src/__tests__/program-accounts-test.ts +++ b/packages/rpc-graphql/src/__tests__/program-accounts-test.ts @@ -1,4 +1,3 @@ -/* eslint-disable sort-keys-fix/sort-keys-fix */ import { createSolanaRpcApi, SolanaRpcMethods } from '@solana/rpc-core'; import { createHttpTransport, createJsonRpc, type Rpc } from '@solana/rpc-transport'; import fetchMock from 'jest-fetch-mock-fork'; @@ -21,8 +20,8 @@ describe('programAccounts', () => { describe('basic queries', () => { // See scripts/fixtures/gpa2-1.json, scripts/fixtures/gpa2-2.json, const variableValues = { - programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', commitment: 'confirmed', + programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', }; it("can query program accounts' lamports balances", async () => { expect.assertions(1); @@ -86,18 +85,17 @@ describe('programAccounts', () => { expect.assertions(1); // See scripts/fixtures/gpa2-1.json, scripts/fixtures/gpa2-2.json, const variableValues = { - programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', commitment: 'confirmed', encoding: 'BASE_58', + programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', }; const source = /* GraphQL */ ` query testQuery($programAddress: String!, $commitment: Commitment, $encoding: AccountEncoding) { programAccounts(programAddress: $programAddress, commitment: $commitment, encoding: $encoding) { - encoding + address + executable ... on AccountBase58 { - address data - executable } } } @@ -109,13 +107,11 @@ describe('programAccounts', () => { { address: 'C5q1p5UiCVrt6vcLJDGcS4AZ98fahKyb9XkDRdqATK17', data: '2Uw1bpnsXxu3e', - encoding: 'BASE_58', executable: false, }, { address: 'Hhsoev7Apk5dMbktzLUrsTHuMq9e9GSYBaLcnN2PfdKS', data: '2Uw1bpnsXxu3e', - encoding: 'BASE_58', executable: false, }, ]), @@ -126,18 +122,17 @@ describe('programAccounts', () => { expect.assertions(1); // See scripts/fixtures/gpa2-1.json, scripts/fixtures/gpa2-2.json, const variableValues = { - programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', commitment: 'confirmed', encoding: 'BASE_64', + programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', }; const source = /* GraphQL */ ` query testQuery($programAddress: String!, $commitment: Commitment, $encoding: AccountEncoding) { programAccounts(programAddress: $programAddress, commitment: $commitment, encoding: $encoding) { - encoding + address + executable ... on AccountBase64 { - address data - executable } } } @@ -149,13 +144,11 @@ describe('programAccounts', () => { { address: 'C5q1p5UiCVrt6vcLJDGcS4AZ98fahKyb9XkDRdqATK17', data: 'dGVzdCBkYXRh', - encoding: 'BASE_64', executable: false, }, { address: 'Hhsoev7Apk5dMbktzLUrsTHuMq9e9GSYBaLcnN2PfdKS', data: 'dGVzdCBkYXRh', - encoding: 'BASE_64', executable: false, }, ]), @@ -166,18 +159,17 @@ describe('programAccounts', () => { expect.assertions(1); // See scripts/fixtures/gpa2-1.json, scripts/fixtures/gpa2-2.json, const variableValues = { - programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', commitment: 'confirmed', encoding: 'BASE_64_ZSTD', + programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6', }; const source = /* GraphQL */ ` query testQuery($programAddress: String!, $commitment: Commitment, $encoding: AccountEncoding) { programAccounts(programAddress: $programAddress, commitment: $commitment, encoding: $encoding) { - encoding + address + executable ... on AccountBase64Zstd { - address data - executable } } } @@ -189,13 +181,11 @@ describe('programAccounts', () => { { address: 'C5q1p5UiCVrt6vcLJDGcS4AZ98fahKyb9XkDRdqATK17', data: 'KLUv/QBYSQAAdGVzdCBkYXRh', - encoding: 'BASE_64_ZSTD', executable: false, }, { address: 'Hhsoev7Apk5dMbktzLUrsTHuMq9e9GSYBaLcnN2PfdKS', data: 'KLUv/QBYSQAAdGVzdCBkYXRh', - encoding: 'BASE_64_ZSTD', executable: false, }, ]), @@ -212,16 +202,19 @@ describe('programAccounts', () => { const source = /* GraphQL */ ` query testQuery($programAddress: String!) { programAccounts(programAddress: $programAddress) { + address + lamports + ownerProgram { + address + } ... on LookupTableAccount { - data { - addresses - authority { - address - } - deactivationSlot - lastExtendedSlot - lastExtendedSlotStartIndex + addresses + authority { + address } + deactivationSlot + lastExtendedSlot + lastExtendedSlotStartIndex } } } @@ -231,14 +224,17 @@ describe('programAccounts', () => { data: { programAccounts: expect.arrayContaining([ { - data: { - addresses: expect.arrayContaining([expect.any(String)]), - authority: { - address: expect.any(String), - }, - deactivationSlot: expect.any(String), - lastExtendedSlot: expect.any(String), - lastExtendedSlotStartIndex: expect.any(Number), + address: expect.any(String), + addresses: expect.arrayContaining([expect.any(String)]), + authority: { + address: expect.any(String), + }, + deactivationSlot: expect.any(String), + lamports: expect.any(BigInt), + lastExtendedSlot: expect.any(String), + lastExtendedSlotStartIndex: expect.any(Number), + ownerProgram: { + address: 'AddressLookupTab1e1111111111111111111111111', }, }, ]), @@ -253,32 +249,33 @@ describe('programAccounts', () => { const source = /* GraphQL */ ` query testQuery($programAddress: String!) { programAccounts(programAddress: $programAddress) { + address + lamports + ownerProgram { + address + } ... on MintAccount { - data { - decimals - isInitialized - mintAuthority { - address - } - supply + decimals + isInitialized + mintAuthority { + address } + supply } ... on TokenAccount { - data { - isNative - mint { - address - } - owner { - address - } - state - tokenAmount { - amount - decimals - uiAmount - uiAmountString - } + isNative + mint { + address + } + owner { + address + } + state + tokenAmount { + amount + decimals + uiAmount + uiAmountString } } } @@ -290,32 +287,38 @@ describe('programAccounts', () => { programAccounts: expect.arrayContaining([ // Mint account { - data: { - decimals: expect.any(Number), - isInitialized: expect.any(Boolean), - mintAuthority: { - address: expect.any(String), - }, - supply: expect.any(String), + address: expect.any(String), + decimals: expect.any(Number), + isInitialized: expect.any(Boolean), + lamports: expect.any(BigInt), + mintAuthority: { + address: expect.any(String), + }, + ownerProgram: { + address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }, + supply: expect.any(String), }, // Token account { - data: { - isNative: expect.any(Boolean), - mint: { - address: expect.any(String), - }, - owner: { - address: expect.any(String), - }, - state: expect.any(String), - tokenAmount: expect.objectContaining({ - amount: expect.any(String), - decimals: expect.any(Number), - uiAmountString: expect.any(String), - }), + address: expect.any(String), + isNative: expect.any(Boolean), + lamports: expect.any(BigInt), + mint: { + address: expect.any(String), + }, + owner: { + address: expect.any(String), }, + ownerProgram: { + address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + }, + state: expect.any(String), + tokenAmount: expect.objectContaining({ + amount: expect.any(String), + decimals: expect.any(Number), + uiAmountString: expect.any(String), + }), }, ]), }, @@ -329,15 +332,18 @@ describe('programAccounts', () => { const source = /* GraphQL */ ` query testQuery($programAddress: String!) { programAccounts(programAddress: $programAddress) { + address + lamports + ownerProgram { + address + } ... on NonceAccount { - data { - authority { - address - } - blockhash - feeCalculator { - lamportsPerSignature - } + authority { + address + } + blockhash + feeCalculator { + lamportsPerSignature } } } @@ -348,14 +354,17 @@ describe('programAccounts', () => { data: { programAccounts: expect.arrayContaining([ { - data: { - authority: { - address: expect.any(String), - }, - blockhash: expect.any(String), - feeCalculator: { - lamportsPerSignature: expect.any(String), - }, + address: expect.any(String), + authority: { + address: expect.any(String), + }, + blockhash: expect.any(String), + feeCalculator: { + lamportsPerSignature: expect.any(String), + }, + lamports: expect.any(BigInt), + ownerProgram: { + address: '11111111111111111111111111111111', }, }, ]), @@ -370,35 +379,38 @@ describe('programAccounts', () => { const source = /* GraphQL */ ` query testQuery($programAddress: String!) { programAccounts(programAddress: $programAddress) { + address + lamports + ownerProgram { + address + } ... on StakeAccount { - data { - meta { - authorized { - staker { - address - } - withdrawer { - address - } + meta { + authorized { + staker { + address } - lockup { - custodian { - address - } - epoch - unixTimestamp + withdrawer { + address } - rentExemptReserve } - stake { - creditsObserved - delegation { - activationEpoch - deactivationEpoch - stake - voter { - address - } + lockup { + custodian { + address + } + epoch + unixTimestamp + } + rentExemptReserve + } + stake { + creditsObserved + delegation { + activationEpoch + deactivationEpoch + stake + voter { + address } } } @@ -411,34 +423,37 @@ describe('programAccounts', () => { data: { programAccounts: expect.arrayContaining([ { - data: { - meta: { - authorized: { - staker: { - address: expect.any(String), - }, - withdrawer: { - address: expect.any(String), - }, + address: expect.any(String), + lamports: expect.any(BigInt), + meta: { + authorized: { + staker: { + address: expect.any(String), }, - lockup: { - custodian: { - address: expect.any(String), - }, - epoch: expect.any(BigInt), - unixTimestamp: expect.any(BigInt), + withdrawer: { + address: expect.any(String), }, - rentExemptReserve: expect.any(String), }, - stake: { - creditsObserved: expect.any(BigInt), - delegation: { - activationEpoch: expect.any(BigInt), - deactivationEpoch: expect.any(BigInt), - stake: expect.any(String), - voter: { - address: expect.any(String), - }, + lockup: { + custodian: { + address: expect.any(String), + }, + epoch: expect.any(BigInt), + unixTimestamp: expect.any(BigInt), + }, + rentExemptReserve: expect.any(String), + }, + ownerProgram: { + address: 'Stake11111111111111111111111111111111111111', + }, + stake: { + creditsObserved: expect.any(BigInt), + delegation: { + activationEpoch: expect.any(BigInt), + deactivationEpoch: expect.any(BigInt), + stake: expect.any(String), + voter: { + address: expect.any(String), }, }, }, @@ -455,36 +470,39 @@ describe('programAccounts', () => { const source = /* GraphQL */ ` query testQuery($programAddress: String!) { programAccounts(programAddress: $programAddress) { + address + lamports + ownerProgram { + address + } ... on VoteAccount { - data { - authorizedVoters { - authorizedVoter { - address - } - epoch - } - authorizedWithdrawer { + authorizedVoters { + authorizedVoter { address } - commission - epochCredits { - credits - epoch - previousCredits - } - lastTimestamp { - slot - timestamp - } - node { - address - } - priorVoters - rootSlot - votes { - confirmationCount - slot - } + epoch + } + authorizedWithdrawer { + address + } + commission + epochCredits { + credits + epoch + previousCredits + } + lastTimestamp { + slot + timestamp + } + node { + address + } + priorVoters + rootSlot + votes { + confirmationCount + slot } } } @@ -495,42 +513,45 @@ describe('programAccounts', () => { data: { programAccounts: expect.arrayContaining([ { - data: { - authorizedVoters: expect.arrayContaining([ - { - authorizedVoter: { - address: expect.any(String), - }, - epoch: expect.any(BigInt), - }, - ]), - authorizedWithdrawer: { - address: expect.any(String), - }, - commission: expect.any(Number), - epochCredits: expect.arrayContaining([ - { - credits: expect.any(String), - epoch: expect.any(BigInt), - previousCredits: expect.any(String), + address: expect.any(String), + authorizedVoters: expect.arrayContaining([ + { + authorizedVoter: { + address: expect.any(String), }, - ]), - lastTimestamp: { - slot: expect.any(BigInt), - timestamp: expect.any(BigInt), + epoch: expect.any(BigInt), }, - node: { - address: expect.any(String), + ]), + authorizedWithdrawer: { + address: expect.any(String), + }, + commission: expect.any(Number), + epochCredits: expect.arrayContaining([ + { + credits: expect.any(String), + epoch: expect.any(BigInt), + previousCredits: expect.any(String), }, - priorVoters: expect.any(Array), - rootSlot: expect.any(BigInt), - votes: expect.arrayContaining([ - { - confirmationCount: expect.any(Number), - slot: expect.any(BigInt), - }, - ]), + ]), + lamports: expect.any(BigInt), + lastTimestamp: { + slot: expect.any(BigInt), + timestamp: expect.any(BigInt), + }, + node: { + address: expect.any(String), + }, + ownerProgram: { + address: 'Vote111111111111111111111111111111111111111', }, + priorVoters: expect.any(Array), + rootSlot: expect.any(BigInt), + votes: expect.arrayContaining([ + { + confirmationCount: expect.any(Number), + slot: expect.any(BigInt), + }, + ]), }, ]), }, @@ -543,13 +564,13 @@ describe('programAccounts', () => { expect.assertions(1); // See scripts/fixtures/gpa1.json const variableValues = { - programAddress: 'DXngmJfjurhnAwbMPgpUGPH6qNvetCKRJ6PiD4ag4PTj', commitment: 'confirmed', dataSlice: { length: 5, offset: 0, }, encoding: 'BASE_58', + programAddress: 'DXngmJfjurhnAwbMPgpUGPH6qNvetCKRJ6PiD4ag4PTj', }; const source = /* GraphQL */ ` query testQuery( @@ -564,7 +585,6 @@ describe('programAccounts', () => { dataSlice: $dataSlice encoding: $encoding ) { - encoding ... on AccountBase58 { data } @@ -577,7 +597,6 @@ describe('programAccounts', () => { programAccounts: expect.arrayContaining([ { data: 'E8f4pET', - encoding: 'BASE_58', }, ]), }, @@ -589,13 +608,13 @@ describe('programAccounts', () => { expect.assertions(1); // See scripts/fixtures/gpa1.json const variableValues = { - programAddress: 'DXngmJfjurhnAwbMPgpUGPH6qNvetCKRJ6PiD4ag4PTj', commitment: 'confirmed', dataSlice: { length: 5, offset: 0, }, encoding: 'BASE_64', + programAddress: 'DXngmJfjurhnAwbMPgpUGPH6qNvetCKRJ6PiD4ag4PTj', }; const source = /* GraphQL */ ` query testQuery( @@ -610,7 +629,6 @@ describe('programAccounts', () => { dataSlice: $dataSlice encoding: $encoding ) { - encoding ... on AccountBase64 { data } @@ -623,7 +641,6 @@ describe('programAccounts', () => { programAccounts: expect.arrayContaining([ { data: 'dGVzdCA=', - encoding: 'BASE_64', }, ]), }, diff --git a/packages/rpc-graphql/src/loaders/account.ts b/packages/rpc-graphql/src/loaders/account.ts index 1880e1679e3d..a2bf81d4db97 100644 --- a/packages/rpc-graphql/src/loaders/account.ts +++ b/packages/rpc-graphql/src/loaders/account.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Address } from '@solana/addresses'; import { SolanaRpcMethods } from '@solana/rpc-core'; import DataLoader from 'dataloader'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -10,56 +8,21 @@ import { GraphQLResolveInfo } from 'graphql'; import type { Rpc } from '../context'; import { AccountQueryArgs } from '../schema/account'; import { onlyPresentFieldRequested } from './common/resolve-info'; - -function normalizeArgs(args: AccountQueryArgs) { - const { address, commitment, dataSlice, encoding, minContextSlot } = args; - return { - address, - commitment: commitment ?? 'confirmed', - dataSlice, - encoding: encoding ?? 'jsonParsed', - minContextSlot, - }; +import { transformLoadedAccount } from './transformers/account'; + +/* Normalizes RPC optional configs to use GraphQL API defaults */ +function normalizeArgs({ + address, + commitment = 'confirmed', + dataSlice, + encoding = 'jsonParsed', + minContextSlot, +}: AccountQueryArgs) { + return { address, commitment, dataSlice, encoding, minContextSlot }; } -export function refineJsonParsedAccountData(jsonParsedAccountData: any) { - const meta = { - program: jsonParsedAccountData.program, - space: jsonParsedAccountData.space, - type: jsonParsedAccountData.parsed.type, - }; - const data = jsonParsedAccountData.parsed.info; - return { data, meta }; -} - -function processQueryResponse({ address, account, encoding }: { address: Address; account: any; encoding: string }) { - const [refinedData, responseEncoding] = Array.isArray(account.data) - ? encoding === 'jsonParsed' - ? [account.data[0], 'base64'] - : [account.data[0], encoding] - : [refineJsonParsedAccountData(account.data), 'jsonParsed']; - - const responseBase = { - ...account, - address, - encoding: responseEncoding, - }; - return typeof refinedData === 'object' && 'meta' in refinedData - ? { - ...responseBase, - data: refinedData.data, - meta: refinedData.meta, - } - : { - ...responseBase, - data: refinedData, - }; -} - -// Default to jsonParsed encoding if none is provided -export async function loadAccount(rpc: Rpc, { address, ...config }: ReturnType) { - const { encoding } = config; - +/* Load an account from the RPC, transform it, then return it */ +async function loadAccount(rpc: Rpc, { address, ...config }: ReturnType) { const account = await rpc .getAccountInfo(address, config as Parameters[1]) .send() @@ -67,13 +30,7 @@ export async function loadAccount(rpc: Rpc, { address, ...config }: ReturnType { throw e; }); - - // Account does not exist, return only the address - if (account === null) { - return { address }; - } - - return processQueryResponse({ account, address, encoding }); + return account === null ? { address } : transformLoadedAccount({ account, address, encoding: config.encoding }); } function createAccountBatchLoadFn(rpc: Rpc) { @@ -87,8 +44,9 @@ export function createAccountLoader(rpc: Rpc) { const loader = new DataLoader(createAccountBatchLoadFn(rpc), { cacheKeyFn: fastStableStringify }); return { load: async (args: AccountQueryArgs, info?: GraphQLResolveInfo) => { - // If a user only requests the account's address, don't call the RPC or the cache if (onlyPresentFieldRequested('address', info)) { + // If a user only requests the account's address, + // don't call the RPC or the cache return { address: args.address }; } return loader.load(normalizeArgs(args)); diff --git a/packages/rpc-graphql/src/loaders/program-accounts.ts b/packages/rpc-graphql/src/loaders/program-accounts.ts index 82e0dfdc86ca..3c0828f5a33c 100644 --- a/packages/rpc-graphql/src/loaders/program-accounts.ts +++ b/packages/rpc-graphql/src/loaders/program-accounts.ts @@ -8,50 +8,23 @@ import { GraphQLResolveInfo } from 'graphql'; import type { Rpc } from '../context'; import { ProgramAccountsQueryArgs } from '../schema/program-accounts'; -import { refineJsonParsedAccountData } from './account'; import { onlyPresentFieldRequested } from './common/resolve-info'; +import { transformLoadedAccount } from './transformers/account'; -function normalizeArgs(args: ProgramAccountsQueryArgs) { - const { commitment, dataSlice, encoding, filters, minContextSlot, programAddress } = args; - return { - commitment: commitment ?? 'confirmed', - dataSlice, - encoding: encoding ?? 'jsonParsed', - filters, - minContextSlot, - programAddress, - }; -} - -function processQueryResponse({ encoding, programAccounts }: { encoding: string; programAccounts: any[] }) { - return programAccounts.map(programAccount => { - const [refinedData, responseEncoding] = Array.isArray(programAccount.account.data) - ? encoding === 'jsonParsed' - ? [programAccount.account.data[0], 'base64'] - : [programAccount.account.data[0], encoding] - : [refineJsonParsedAccountData(programAccount.account.data), 'jsonParsed']; - const pubkey = programAccount.pubkey; - const responseBase = { - ...programAccount.account, - address: pubkey, - encoding: responseEncoding, - }; - return typeof refinedData === 'object' && 'meta' in refinedData - ? { - ...responseBase, - data: refinedData.data, - meta: refinedData.meta, - } - : { - ...responseBase, - data: refinedData, - }; - }); +/* Normalizes RPC optional configs to use GraphQL API defaults */ +function normalizeArgs({ + commitment = 'confirmed', + dataSlice, + encoding = 'jsonParsed', + filters, + minContextSlot, + programAddress, +}: ProgramAccountsQueryArgs) { + return { commitment, dataSlice, encoding, filters, minContextSlot, programAddress }; } -export async function loadProgramAccounts(rpc: Rpc, { programAddress, ...config }: ReturnType) { - const { encoding } = config; - +/* Load a program's accounts from the RPC, transform them, then return them */ +async function loadProgramAccounts(rpc: Rpc, { programAddress, ...config }: ReturnType) { const programAccounts = await rpc .getProgramAccounts(programAddress, config as Parameters[1]) .send() @@ -65,9 +38,13 @@ export async function loadProgramAccounts(rpc: Rpc, { programAddress, ...config throw e; }); - const queryResponse = processQueryResponse({ encoding, programAccounts }); - - return queryResponse; + return programAccounts.map(programAccount => + transformLoadedAccount({ + account: programAccount.account, + address: programAccount.pubkey, + encoding: config.encoding, + }) + ); } function createProgramAccountsBatchLoadFn(rpc: Rpc) { @@ -83,8 +60,9 @@ export function createProgramAccountsLoader(rpc: Rpc) { const loader = new DataLoader(createProgramAccountsBatchLoadFn(rpc), { cacheKeyFn: fastStableStringify }); return { load: async (args: ProgramAccountsQueryArgs, info?: GraphQLResolveInfo) => { - // If a user only requests the program's address, don't call the RPC or the cache if (onlyPresentFieldRequested('programAddress', info)) { + // If a user only requests the program's address, + // don't call the RPC or the cache return { programAddress: args.programAddress }; } return loader.load(normalizeArgs(args)); diff --git a/packages/rpc-graphql/src/loaders/transformers/account.ts b/packages/rpc-graphql/src/loaders/transformers/account.ts new file mode 100644 index 000000000000..e5022abb514a --- /dev/null +++ b/packages/rpc-graphql/src/loaders/transformers/account.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Address } from '@solana/addresses'; + +import { AccountQueryArgs } from '../../schema/account'; + +function transformParsedAccountData(parsedAccountData: any) { + const { + parsed: { info: result, type: accountType }, + program: programName, + programId, + } = parsedAccountData; + // Tells GraphQL which account type has been + // returned by the RPC. + result.accountType = accountType; + result.programId = programId; + // Tells GraphQL which program the returned + // account belongs to. + result.programName = programName; + return result; +} + +export function transformLoadedAccount({ + account, + address, + encoding, +}: { + account: any; + address: Address; + encoding: AccountQueryArgs['encoding']; +}) { + const [ + // The account's data, either encoded or parsed. + data, + // Tells GraphQL which encoding has been returned + // by the RPC. + responseEncoding, + ] = Array.isArray(account.data) + ? encoding === 'jsonParsed' + ? // The requested encoding is jsonParsed, + // but the data could not be parsed. + // Defaults to base64 encoding. + [{ data: account.data[0] }, 'base64'] + : // The requested encoding is base58, + // base64, or base64+zstd. + [{ data: account.data[0] }, encoding] + : // The account data was returned as an object, + // so it was parsed successfully. + [transformParsedAccountData(account.data), 'jsonParsed']; + account.address = address; + account.encoding = responseEncoding; + account.ownerProgram = account.owner; + return { + ...account, + ...data, + }; +} diff --git a/packages/rpc-graphql/src/schema/account.ts b/packages/rpc-graphql/src/schema/account.ts index 65046a6a9f9d..06ea95abacc1 100644 --- a/packages/rpc-graphql/src/schema/account.ts +++ b/packages/rpc-graphql/src/schema/account.ts @@ -16,10 +16,10 @@ export const accountTypeDefs = /* GraphQL */ ` # Account interface interface Account { address: Address - encoding: AccountEncoding executable: Boolean lamports: BigInt - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt } @@ -27,10 +27,10 @@ export const accountTypeDefs = /* GraphQL */ ` type AccountBase58 implements Account { address: Address data: Base58EncodedBytes - encoding: AccountEncoding executable: Boolean lamports: BigInt - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt } @@ -38,10 +38,10 @@ export const accountTypeDefs = /* GraphQL */ ` type AccountBase64 implements Account { address: Address data: Base64EncodedBytes - encoding: AccountEncoding executable: Boolean lamports: BigInt - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt } @@ -49,99 +49,73 @@ export const accountTypeDefs = /* GraphQL */ ` type AccountBase64Zstd implements Account { address: Address data: Base64ZstdEncodedBytes - encoding: AccountEncoding executable: Boolean lamports: BigInt - owner: Account - rentEpoch: BigInt - } - - # Interface for JSON-parsed meta - type JsonParsedAccountMeta { - program: String + ownerProgram: Account space: BigInt - type: String - } - interface AccountJsonParsed { - meta: JsonParsedAccountMeta + rentEpoch: BigInt } # A nonce account type NonceAccountFeeCalculator { lamportsPerSignature: String } - type NonceAccountData { + type NonceAccount implements Account { + address: Address + executable: Boolean + lamports: BigInt + ownerProgram: Account + space: BigInt + rentEpoch: BigInt authority: Account blockhash: String feeCalculator: NonceAccountFeeCalculator } - type NonceAccount implements Account & AccountJsonParsed { + + # A lookup table account + type LookupTableAccount implements Account { address: Address - data: NonceAccountData - encoding: AccountEncoding executable: Boolean lamports: BigInt - meta: JsonParsedAccountMeta - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt - } - - # A lookup table account - type LookupTableAccountData { - addresses: [String] + addresses: [Address] authority: Account deactivationSlot: String lastExtendedSlot: String lastExtendedSlotStartIndex: Int } - type LookupTableAccount implements Account & AccountJsonParsed { + + # A mint account + type MintAccount implements Account { address: Address - data: LookupTableAccountData - encoding: AccountEncoding executable: Boolean lamports: BigInt - meta: JsonParsedAccountMeta - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt - } - - # A mint account - type MintAccountData { decimals: Int freezeAuthority: Account isInitialized: Boolean mintAuthority: Account supply: String } - type MintAccount implements Account & AccountJsonParsed { + + # A token account + type TokenAccount implements Account { address: Address - data: MintAccountData - encoding: AccountEncoding executable: Boolean lamports: BigInt - meta: JsonParsedAccountMeta - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt - } - - # A token account - type TokenAccountData { isNative: Boolean mint: Account owner: Account state: String tokenAmount: TokenAmount } - type TokenAccount implements Account & AccountJsonParsed { - address: Address - data: TokenAccountData - encoding: AccountEncoding - executable: Boolean - lamports: BigInt - meta: JsonParsedAccountMeta - owner: Account - rentEpoch: BigInt - } # A stake account type StakeAccountDataMetaAuthorized { @@ -169,19 +143,15 @@ export const accountTypeDefs = /* GraphQL */ ` creditsObserved: BigInt delegation: StakeAccountDataStakeDelegation } - type StakeAccountData { - meta: StakeAccountDataMeta - stake: StakeAccountDataStake - } - type StakeAccount implements Account & AccountJsonParsed { + type StakeAccount implements Account { address: Address - data: StakeAccountData - encoding: AccountEncoding executable: Boolean lamports: BigInt - meta: JsonParsedAccountMeta - owner: Account + ownerProgram: Account + space: BigInt rentEpoch: BigInt + meta: StakeAccountDataMeta + stake: StakeAccountDataStake } # A vote account @@ -202,32 +172,28 @@ export const accountTypeDefs = /* GraphQL */ ` confirmationCount: Int slot: BigInt } - type VoteAccountData { + type VoteAccount implements Account { + address: Address + executable: Boolean + lamports: BigInt + ownerProgram: Account + space: BigInt + rentEpoch: BigInt authorizedVoters: [VoteAccountDataAuthorizedVoter] authorizedWithdrawer: Account commission: Int epochCredits: [VoteAccountDataEpochCredit] lastTimestamp: VoteAccountDataLastTimestamp node: Account - priorVoters: [String] + priorVoters: [Address] rootSlot: BigInt votes: [VoteAccountDataVote] } - type VoteAccount implements Account & AccountJsonParsed { - address: Address - data: VoteAccountData - encoding: AccountEncoding - executable: Boolean - lamports: BigInt - meta: JsonParsedAccountMeta - owner: Account - rentEpoch: BigInt - } `; export const accountResolvers = { Account: { - __resolveType(account: { encoding: string; meta: { program: string; type: string } }) { + __resolveType(account: { encoding: string; programName: string; accountType: string }) { if (account.encoding === 'base58') { return 'AccountBase58'; } @@ -238,22 +204,22 @@ export const accountResolvers = { return 'AccountBase64Zstd'; } if (account.encoding === 'jsonParsed') { - if (account.meta.program === 'nonce') { + if (account.programName === 'nonce') { return 'NonceAccount'; } - if (account.meta.type === 'mint' && account.meta.program === 'spl-token') { + if (account.accountType === 'mint' && account.programName === 'spl-token') { return 'MintAccount'; } - if (account.meta.type === 'account' && account.meta.program === 'spl-token') { + if (account.accountType === 'account' && account.programName === 'spl-token') { return 'TokenAccount'; } - if (account.meta.program === 'stake') { + if (account.programName === 'stake') { return 'StakeAccount'; } - if (account.meta.type === 'vote' && account.meta.program === 'vote') { + if (account.accountType === 'vote' && account.programName === 'vote') { return 'VoteAccount'; } - if (account.meta.type === 'lookupTable' && account.meta.program === 'address-lookup-table') { + if (account.accountType === 'lookupTable' && account.programName === 'address-lookup-table') { return 'LookupTableAccount'; } } @@ -261,39 +227,31 @@ export const accountResolvers = { }, }, AccountBase58: { - owner: resolveAccount('owner'), + ownerProgram: resolveAccount('ownerProgram'), }, AccountBase64: { - owner: resolveAccount('owner'), + ownerProgram: resolveAccount('ownerProgram'), }, AccountBase64Zstd: { - owner: resolveAccount('owner'), - }, - NonceAccountData: { - authority: resolveAccount('authority'), + ownerProgram: resolveAccount('ownerProgram'), }, NonceAccount: { - owner: resolveAccount('owner'), - }, - LookupTableAccountData: { authority: resolveAccount('authority'), + ownerProgram: resolveAccount('ownerProgram'), }, LookupTableAccount: { - owner: resolveAccount('owner'), + authority: resolveAccount('authority'), + ownerProgram: resolveAccount('ownerProgram'), }, - MintAccountData: { + MintAccount: { freezeAuthority: resolveAccount('freezeAuthority'), mintAuthority: resolveAccount('mintAuthority'), - }, - MintAccount: { - owner: resolveAccount('owner'), - }, - TokenAccountData: { - mint: resolveAccount('mint'), - owner: resolveAccount('owner'), + ownerProgram: resolveAccount('ownerProgram'), }, TokenAccount: { + mint: resolveAccount('mint'), owner: resolveAccount('owner'), + ownerProgram: resolveAccount('ownerProgram'), }, StakeAccountDataMetaAuthorized: { staker: resolveAccount('staker'), @@ -306,16 +264,14 @@ export const accountResolvers = { voter: resolveAccount('voter'), }, StakeAccount: { - owner: resolveAccount('owner'), + ownerProgram: resolveAccount('ownerProgram'), }, VoteAccountDataAuthorizedVoter: { authorizedVoter: resolveAccount('authorizedVoter'), }, - VoteAccountData: { + VoteAccount: { authorizedWithdrawer: resolveAccount('authorizedWithdrawer'), node: resolveAccount('nodePubkey'), - }, - VoteAccount: { - owner: resolveAccount('owner'), + ownerProgram: resolveAccount('ownerProgram'), }, };