{"_id":"@atlaschain/rpc-graphql","name":"@atlaschain/rpc-graphql","dist-tags":{"latest":"3.0.0"},"versions":{"3.0.0":{"name":"@atlaschain/rpc-graphql","version":"3.0.0","description":"A library for resolving GraphQl query calls to the Atlas JSON RPC API","exports":{"edge-light":{"import":"./dist/index.node.mjs","require":"./dist/index.node.cjs"},"workerd":{"import":"./dist/index.node.mjs","require":"./dist/index.node.cjs"},"browser":{"import":"./dist/index.browser.mjs","require":"./dist/index.browser.cjs"},"node":{"import":"./dist/index.node.mjs","require":"./dist/index.node.cjs"},"react-native":"./dist/index.native.mjs","types":"./dist/types/index.d.ts"},"browser":{"./dist/index.node.cjs":"./dist/index.browser.cjs","./dist/index.node.mjs":"./dist/index.browser.mjs"},"main":"./dist/index.node.cjs","module":"./dist/index.node.mjs","react-native":"./dist/index.native.mjs","types":"./dist/types/index.d.ts","type":"commonjs","sideEffects":false,"keywords":["blockchain","atlas","web3"],"author":{"name":"Atlas Chain Foundation"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/anza-xyz/kit.git"},"bugs":{"url":"https://github.com/anza-xyz/kit/issues"},"browserslist":["supports bigint and not dead","maintained node versions"],"dependencies":{"@graphql-tools/schema":"^10.0.25","dataloader":"^2.2.3","graphql":"^16.11.0","@atlaschain/codecs-strings":"3.0.0","@atlaschain/fast-stable-stringify":"3.0.0"},"peerDependencies":{"typescript":">=5.3.3"},"engines":{"node":">=20.18.0"},"scripts":{"compile:js":"tsup --config build-scripts/tsup.config.package.ts","compile:typedefs":"tsc -p ./tsconfig.declarations.json","dev":"jest -c ../../node_modules/@atlaschain/test-config/jest-dev.config.ts --globalSetup @atlaschain/test-config/test-validator-setup.js --globalTeardown @atlaschain/test-config/test-validator-teardown.js --rootDir . --watch","publish-impl":"npm view $npm_package_name@$npm_package_version > /dev/null 2>&1 || (pnpm publish --tag ${PUBLISH_TAG:-canary} --access public --no-git-checks && (([ -n \"${GITHUB_OUTPUT:-}\" ] && echo 'published=true' >> \"$GITHUB_OUTPUT\") || true) && (([ \"$PUBLISH_TAG\" != \"canary\" ] && ../build-scripts/maybe-tag-latest.ts $npm_package_name@$npm_package_version) || true))","publish-packages":"pnpm prepublishOnly && pnpm publish-impl","style:fix":"pnpm eslint --fix src && pnpm prettier --log-level warn --ignore-unknown --write ./*","test:lint":"TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@atlaschain/test-config/jest-lint.config.ts --rootDir . --silent","test:prettier":"TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@atlaschain/test-config/jest-prettier.config.ts --rootDir . --silent","test:treeshakability:browser":"agadoo dist/index.browser.mjs","test:treeshakability:native":"agadoo dist/index.native.mjs","test:treeshakability:node":"agadoo dist/index.node.mjs","test:typecheck":"tsc --noEmit","test:unit:browser":"TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@atlaschain/test-config/jest-unit.config.browser.ts --globalSetup @atlaschain/test-config/test-validator-setup.js --globalTeardown @atlaschain/test-config/test-validator-teardown.js --rootDir . --silent","test:unit:node":"TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@atlaschain/test-config/jest-unit.config.node.ts --globalSetup @atlaschain/test-config/test-validator-setup.js --globalTeardown @atlaschain/test-config/test-validator-teardown.js --rootDir . --silent"},"_id":"@atlaschain/rpc-graphql@3.0.0","homepage":"https://github.com/anza-xyz/kit#readme","_integrity":"sha512-oi7LdZDEk571omHeyKL+VMes8iuQqBZ/sZSpuwMVgV26fieHubhj9HwIzjuGOxrkra9lDXerRlg2iIplSyZQXQ==","_resolved":"/private/var/folders/q8/nr55p0wd491c6fjmbky17kd00000gn/T/33b121d1050af1c20e5a78bead4ced8f/atlaschain-rpc-graphql-3.0.0.tgz","_from":"file:atlaschain-rpc-graphql-3.0.0.tgz","_nodeVersion":"22.12.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-oi7LdZDEk571omHeyKL+VMes8iuQqBZ/sZSpuwMVgV26fieHubhj9HwIzjuGOxrkra9lDXerRlg2iIplSyZQXQ==","shasum":"4e05c9787c3481db4ebe3b89a9c9d2f0a357b438","tarball":"https://registry.npmjs.org/@atlaschain/rpc-graphql/-/rpc-graphql-3.0.0.tgz","fileCount":5,"unpackedSize":66084,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCA9AgdXPdMe2awf+9ilSZR+ItuK5sPTcVh7udRaPsOZAIhAOPEVlG3OKMWCn8U+VIjf1jtKbzfSB/piQulbaGF+fDe"}]},"_npmUser":{"name":"atlaschain","email":"jq@atlaschain.org"},"directories":{},"maintainers":[{"name":"atlaschain","email":"jq@atlaschain.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rpc-graphql_3.0.0_1764611553016_0.5381528875951578"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-01T17:52:32.915Z","3.0.0":"2025-12-01T17:52:33.224Z","modified":"2025-12-01T17:52:33.530Z"},"maintainers":[{"name":"atlaschain","email":"jq@atlaschain.org"}],"description":"A library for resolving GraphQl query calls to the Atlas JSON RPC API","homepage":"https://github.com/anza-xyz/kit#readme","keywords":["blockchain","atlas","web3"],"repository":{"type":"git","url":"git+https://github.com/anza-xyz/kit.git"},"author":{"name":"Atlas Chain Foundation"},"bugs":{"url":"https://github.com/anza-xyz/kit/issues"},"license":"MIT","readme":"# @atlas/rpc-graphql\n\nThis package defines a GraphQL client resolver built on top of the\n[Atlas JSON-RPC](https://docs.atlas.com/api/http).\n\nA client resolver in this context is simply a client-side RPC interface\ndesigned to give application developers the ability to use GraphQL to interact\nwith data on the Atlas blockchain.\n\nThe resolver presents developers with a new schema for working with Atlas data\n(see [Schema](#schema)), as well as new features only possible with GraphQL.\nAdditionally, the resolver is designed to make highly-optimized use of the\nAtlas JSON RPC, balancing RPC requests, batch loading, and caching\n(see [RPC Optimizations](#rpc-optimizations)).\n\nGraphQL is a query language for your API, and a server-side runtime for\nexecuting queries using a type system you define for your data.\n\n<img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/GraphQL_Logo.svg/1024px-GraphQL_Logo.svg.png?20161105194737\" alt=\"graphql-icon\" width=\"24\" align=\"center\"/> [**GraphQL**](https://graphql.org/learn/)\n\n# Quick Start\n\nThe RPC-GraphQL client requires an RPC client, as defined by the package\n`@atlas/rpc-spec`. Such a client is available in `@atlas/kit:2.0` or\ncan be created manually with a custom implementation.\n\n```ts\nRpc<TRpcMethods>;\n```\n\nThe RPC-GraphQL requires an RPC client with the following API methods available\nfor use in order to properly execute all queries.\n\n```ts\nRpc<GetAccountInfoApi & GetBlockApi & GetMultipleAccountsApi & GetProgramAccountsApi & GetTransactionApi>;\n```\n\nTo initialize the RPC-GraphQL client, simple use `createAtlasRpcGraphQL`.\n\n```ts\nimport { createAtlasRpc } from '@atlas/rpc';\n\n// Create the RPC client\nconst rpc = createAtlasRpc('https://api.devnet.atlas.com');\n\n// Create the RPC-GraphQL client\nconst rpcGraphQL = createAtlasRpcGraphQL(rpc);\n```\n\nThe `RpcGraphQL` type supports one method `query` which accepts a string\nquery source and an optional `variableValues` parameter - which is an object\ncontaining any variables to pipe into the query string.\n\nYou can define queries with hard-coded parameters.\n\n```ts\nconst source = `\n    query myQuery {\n        account(address: \"AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca\") {\n            lamports\n        }\n    }\n`;\n\nconst result = await rpcGraphQL.query(source);\n```\n\n```\ndata: {\n    account: {\n        lamports: 10290815n,\n    },\n}\n```\n\nYou can also pass the variable values.\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            lamports\n        }\n    }\n`;\n\nconst variableValues = {\n    address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    account: {\n        lamports: 10290815n,\n    },\n}\n```\n\nQueries with variable values can also be re-used!\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            lamports\n        }\n    }\n`;\n\nconst lamportsAccountA = await rpcGraphQL.query(source, {\n    address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n});\n\nconst lamportsAccountB = await rpcGraphQL.query(source, {\n    address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk',\n});\n```\n\n# Schema\n\nAtlas data can be categorized into three main types:\n\n- Accounts\n- Transactions\n- Blocks\n\nThese types encompass everything that can be queried from the Atlas ledger.\n\n## Accounts\n\nThe `Account` interface contains common fields across all accounts.\n\n```graphql\ninterface Account {\n    address: Address\n    data(encoding: AccountEncoding!, dataSlice: DataSlice): String\n    executable: Boolean\n    lamports: BigInt\n    ownerProgram: Account\n    space: BigInt\n}\n```\n\nAny account can be queried by these fields without specifying the specific\naccount type.\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            executable\n            lamports\n        }\n    }\n`;\n\nconst variableValues = {\n    address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    account: {\n        executable: false,\n        lamports: 10290815n,\n    },\n}\n```\n\n### Querying Account Data\n\nQuerying accounts by their encoded data (`base58`, `base64`, `base64+zstd`) is\nstill fully supported.\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            data(encoding: BASE_64)\n        }\n    }\n`;\n\nconst variableValues = {\n    address: 'CcYNb7WqpjaMrNr7B1mapaNfWctZRH7LyAjWRLBGt1Fk',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    account: {\n        data: 'dGVzdCBkYXRh',\n    },\n}\n```\n\n### Querying Specific Account Types\n\nA set of specific parsed account types are supported in GraphQL.\n\n- `GenericAccount`: A generic base account type\n- `NonceAccount`: A nonce account\n- `LookupTableAccount`: An address lookup table account\n- `MintAccount`: An SPL mint\n- `TokenAccount`: An SPL token account\n- `StakeAccount`: A stake account\n- `VoteAccount`: A vote account\n\nYou can choose how to handle querying of specific account types. For example,\nyou might _only_ want specifically any account that matches `MintAccount`.\n\n```ts\nconst maybeMintAddresses = [\n    'J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ',\n    'JAbWqZ7S2c6jomQr8ofAYBo257bE1QJtHwbX1yWc2osZ',\n    '2AQ4CSNu6zNUZsUq4aLNUSjyrLv4qFFXQuKs5RTHbg2Y',\n    'EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b',\n];\n\nconst mintAccounts = [];\n\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            ... on MintAccount {\n                data {\n                    decimals\n                    isInitialized\n                    mintAuthority\n                    supply\n                }\n            }\n        }\n    }\n`;\n\nfor (const address of maybeMintAddresses) {\n    const result = await rpcGraphQL.query(source, { address });\n    if (result != null) {\n        const {\n            data: {\n                account: { data: mintInfo },\n            },\n        } = result;\n        mintAccounts.push(mintInfo);\n    }\n}\n```\n\nMaybe you want to handle both mints _and_ token accounts.\n\n```ts\nconst mintOrTokenAccountAddresses = [\n    'J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ',\n    'JAbWqZ7S2c6jomQr8ofAYBo257bE1QJtHwbX1yWc2osZ',\n    '2AQ4CSNu6zNUZsUq4aLNUSjyrLv4qFFXQuKs5RTHbg2Y',\n    'EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b',\n];\n\nconst mintAccounts = [];\nconst tokenAccounts = [];\n\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            ... on MintAccount {\n                __typename\n                decimals\n                isInitialized\n                supply\n            }\n            ... on TokenAccount {\n                __typename\n                isNative\n                mint\n                state\n            }\n        }\n    }\n`;\n\nfor (const address of mintOrTokenAccountAddresses) {\n    const result = await rpcGraphQL.query(source, { address });\n    if (result != null) {\n        const {\n            data: { account: accountParsedData },\n        } = result;\n        if (accountParsedData.__typename === 'MintAccount') {\n            mintAccounts.push(accountParsedInfo);\n        } else {\n            tokenAccounts.push(accountParsedInfo);\n        }\n    }\n}\n```\n\n### Querying Program Accounts\n\nAnother account-based query that can be performed with RPC-GraphQL is the\n`programAccounts` query. The response will be a list of `Account` types as\ndefined above.\n\n```ts\nconst source = `\n    query myQuery($programAddress: String!) {\n        programAccounts(programAddress: $address) {\n            executable\n            lamports\n        }\n    }\n`;\n\nconst variableValues = {\n    programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    programAccounts: [\n        {\n            executable: false,\n            lamports: 10290815n,\n        },\n        {\n            executable: false,\n            lamports: 10290815n,\n        },\n        /* .. */\n    ]\n}\n```\n\nAccount data encoding in `base58`, `base64`, and `base64+zstd` is also\nsupported with this query, as well as `dataSlice` and `filter`.\n\n```ts\nconst source = `\n    query myQuery($programAddress: String!) {\n        programAccounts(programAddress: $programAddress) {\n            data(encoding: BASE_64, dataSlice: { length: 5, offset: 0 })\n        }\n    }\n`;\n\nconst variableValues = {\n    programAddress: 'DXngmJfjurhnAwbMPgpUGPH6qNvetCKRJ6PiD4ag4PTj',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    programAccounts: [\n        {\n            data: 'dGVzdCA=',\n        },\n        /* .. */\n    ],\n}\n```\n\nAlthough specific parsed account types are directly tied to the program which\nowns them, it's still possible to handle various specific account types within\nthe same program accounts response.\n\n```ts\nconst source = `\n    query myQuery($programAddress: String!) {\n        programAccounts(programAddress: $address) {\n            ... on MintAccount {\n                __typename\n                decimals\n                isInitialized\n                mintAuthority\n                supply\n            }\n            ... on TokenAccount {\n                __typename\n                isNative\n                mint\n                owner\n                state\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    programAddress: 'AmtpVzo6H6qQCP9dH9wfu5hfa8kKaAFpTJ4aamPYR6V6',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n\nconst { mints, tokenAccounts } = result.data.programAccounts.reduce(\n    (acc: { mints: any[]; tokenAccounts: any[] }, account) => {\n        if (account.__typename === 'MintAccount') {\n            acc.mints.push(accountParsedInfo);\n        } else {\n            acc.tokenAccounts.push(accountParsedInfo);\n        }\n        return acc;\n    },\n    { mints: [], tokenAccounts: [] },\n);\n```\n\n### Nested Account Queries\n\nNotice the `owner` field of the `Account` interface is also an `Account`\ninterface. This powers nested queries against the `owner` field of an account.\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            address\n            owner {\n                address\n                executable\n                lamports\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    account: {\n        address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n        owner: {\n            address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n            executable: true,\n            lamports: 10290815n,\n        },\n    },\n}\n```\n\nAs you can see, simply defining a nested query with RPC-GraphQL will augment\nthe multiple RPC calls and parsing code required to gather the necessary\ninformation!\n\nYou can nest queries as far as you want!\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            address\n            owner {\n                address\n                owner {\n                    address\n                    owner {\n                        address\n                    }\n                }\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    account: {\n        address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n        owner: {\n            address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',\n            owner: {\n                address: 'BPFLoader2111111111111111111111111111111111',\n                owner: {\n                    address: 'NativeLoader1111111111111111111111111111111',\n                },\n            },\n        },\n    },\n}\n```\n\nNested queries can also be applied to specific account types.\n\n```ts\nconst source = `\n    query myQuery($address: String!) {\n        account(address: $address) {\n            ... on MintAccount {\n                address\n                data {\n                    mintAuthority {\n                        address\n                        lamports\n                    }\n                }\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    account: {\n        address: 'AyGCwnwxQMCqaU4ixReHt8h5W4dwmxU7eM3BEQBdWVca',\n        data: {\n            mintAuthority: {\n                address: 'DpfJkNonoVB3sor9H9ceajhex4XHVPrDAGAq2ahdG4JZ',\n                lamports: 10290815n,\n            }\n        },\n    },\n}\n```\n\nNested account queries are also supported on `programAccounts` queries.\n\n## Transactions\n\nThe `Transaction` type contains common fields across all transactions.\n\n```graphql\ntype Transaction {\n    blockTime: BigInt\n    data(encoding: TransactionEncoding!): String\n    message: TransactionMessage\n    meta: TransactionMeta\n    signatures: [Signature]\n    slot: Slot\n    version: String\n}\n```\n\nNote that unlike accounts, the `Transaction` type is not an interface, so the\nbase response type of a transaction query remains constant. However, the list\nof instructions contained in a parsed transaction are returned as the\n`TransactionInstruction` interface, which can be queried by specific type.\nSee [Querying Specific Transaction Instruction Types](#querying-specific-transaction-instruction-types).\n\n```graphql\ninterface TransactionInstruction {\n    programId: Address\n}\n```\n\nA transaction can be queried by the `transaction` query.\n\n```ts\nconst source = `\n    query myQuery($signature: String!) {\n        transaction(signature: $signature) {\n            blockTime\n            meta {\n                computeUnitsConsumed\n                logMessages\n            }\n            slot\n        }\n    }\n`;\n\nconst variableValues = {\n    signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    transaction: {\n        blockTime: 230860412n,\n        meta: {\n            computeUnitsConsumed: 120000n,\n            logMessages: [\n                \"Program 8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz invoke [1]\",\n                \"Program 8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz consumed 2164 of 452155 compute units\",\n                \"Program 8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz success\",\n                \"Program ComputeBudget111111111111111111111111111111 invoke [1]\",\n                \"Program ComputeBudget111111111111111111111111111111 success\"\n            ]\n        },\n        slot: 230860693n,\n    },\n}\n```\n\n### Querying Transaction Data\n\nQuerying encoded transaction data (`base58`, `base64`) is fully supported.\n\n```ts\nconst source = `\n    query myQuery($signature: String!, $commitment: Commitment) {\n        transaction(signature: $signature, commitment: $commitment) {\n            data(encoding: BASE_64)\n        }\n    }\n`;\n\nconst variableValues = {\n    signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',\n    commitment: 'confirmed',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\n{\n  \"data\": {\n    \"transaction\": {\n      \"data\": \"AbgFjqLTBtoAaHXexSN1OYXf+UNox6qe3JcyCmEwE57iUHxCkHp8zKTJVznd6nLtUFNMYJWHCtMb+yPjk7QIxAQBAAEDeXJtpS2Z1gsH6tc7L28L9gg8yFx3qU401pHXj4vK/skUvD7y/LnapfCdSx3FfTguy49UDQVvGgOK0ix/P42YuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5uE0ATTHEABQrIB1+aoEdYJxvQthXPLHFxSH2y+ACK4BAgIAAQwCAAAAAMqaOwAAAAA=\"\n    }\n  }\n}\n```\n\n### Querying Specific Transaction Instruction Types\n\nAs mentioned above, parsed transactions return a list of instructions that\nimplement the `TransactionInstruction` interface. These instructions can be\nqueried by specific instruction types.\n\nInstructions for the following programs are supported.\n\n- Address Lookup Table\n- BPF Loader\n- BPF Upgradeable Loader\n- Stake\n- SPL Associated Token\n- SPL Memo\n- SPL Token\n- System\n- Vote\n\nAdditionally, the `GenericInstruction` type is the base parsed instruction type.\n\n```graphql\ntype GenericInstruction implements TransactionInstruction {\n    accounts: [Address]\n    data: Base64EncodedBytes\n    programId: Address\n}\n```\n\nSpecific transaction instruction types can be queried within a `Transaction`\nresponse like so.\n\n```ts\nconst source = `\n    query myQuery($signature: String!, $commitment: Commitment) {\n        transaction(signature: $signature, commitment: $commitment) {\n            message {\n                instructions {\n                    ... on CreateAccountInstruction {\n                        lamports\n                        programId\n                        space\n                    }\n                }\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',\n    commitment: 'confirmed',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    transaction: {\n        message: {\n            instructions: [\n                {\n                    lamports: 890880n,\n                    programId: '11111111111111111111111111111111',\n                    space: 0n,\n                },\n                /* .. */\n            ]\n        },\n    },\n}\n```\n\n### Nested Transaction Queries\n\nSince transactions have a relatively large number of data points, they are\nparticularly useful for nested queries!\n\nSimilar to nested querying accounts, it's possible to nest queries inside your\ntransaction queries to look up other objects, such as accounts, as they appear\nin the transaction response.\n\n```ts\nconst source = `\n    query myQuery($signature: String!, $commitment: Commitment) {\n        transaction(signature: $signature, commitment: $commitment) {\n            message {\n                instructions {\n                    ... on SplTokenTransferInstruction {\n                        amount\n                        authority {\n                            # Account\n                            address\n                            lamports\n                        }\n                        destination {\n                            # Account\n                            ... on TokenAccount {\n                                address\n                                mint {\n                                    ... on MintAccount {\n                                        # Account\n                                        address\n                                        decimals\n                                    }\n                                }\n                                owner {\n                                    # Account\n                                    address\n                                    lamports\n                                }\n                            }\n                        }\n                        source {\n                            # Account\n                            ... on TokenAccount {\n                                address\n                                mint {\n                                    ... on MintAccount {\n                                        # Account\n                                        address\n                                        decimals\n                                    }\n                                }\n                                owner {\n                                    # Account\n                                    address\n                                    lamports\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    signature: '63zkpxATgAwXRGFQZPDESTw2m4uZQ99sX338ibgKtTcgG6v34E3MSS3zckCwJHrimS71cvei6h1Bn1K1De53BNWC',\n    commitment: 'confirmed',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    transaction: {\n        message: {\n            instructions: [\n                {\n                    amount: '50',\n                    authority: {\n                        address: 'AHPPMhzDQix9sKULBqeaQ5BUZgrKdz8tg6DzPxsofB12',\n                        lamports: 890880n,\n                    },\n                    destination: {\n                        address: '2W8mUY75zxqwAcpirn75r3Cc7TStMirFyHwKqo13fmB1',\n                        mint: {\n                            address: '8poKMotB2cEYVv5sbjrdyssASZj1vwYCe7GJFeXo2QP7',\n                            decimals: 6,\n                        },\n                        owner: {\n                            address: '7tRxJ2znbTFpwW9XaMMiDsXDudoPEUXRcpDpm8qjWgAZ',\n                            lamports: 890880n,\n                        }\n                    },\n                    source: {\n                        address: 'BqFCPqXUm4cq6jaZZx1TDTvUR1wdEuNNwAHBEVR6mJhM',\n                        mint: {\n                            address: '8poKMotB2cEYVv5sbjrdyssASZj1vwYCe7GJFeXo2QP7',\n                            decimals: 6,\n                        },\n                        owner: {\n                            address: '3dPmVLMD7PC5faZNyJUH9WFrUxAsbjydJfoozwmR1wDG',\n                            lamports: e890880n,\n                        }\n                    }\n                },\n                /* .. */\n            ]\n        }\n    }\n}\n```\n\n## Blocks\n\nThe `Block` type contains common fields across all blocks.\n\n```graphql\ntype Block {\n    blockhash: String\n    blockHeight: BigInt\n    blockTime: BigInt\n    parentSlot: Slot\n    previousBlockhash: String\n    rewards: [Reward]\n    signatures: [Signature]\n    transactions: [Transaction]\n}\n```\n\nJust like the `programAccounts` query will return a list of `Account` types, on\nwhich you can perform many operations, the `block` query will return a list of\n`Transaction` types, however blocks also contain their own high-level data\nfields, such as `blockhash` and `blockTime`.\n\n```ts\nconst source = `\n    query myQuery($slot: BigInt!, $commitment: Commitment) {\n        block(slot: $slot, commitment: $commitment) {\n            blockHeight\n            blockhash\n            parentSlot\n            rewards {\n                commission\n                lamports\n                rewardType\n            }\n            transactions {\n                message {\n                    instructions {\n                        ... on CreateAccountInstruction {\n                            lamports\n                            programId\n                            space\n                        }\n                    }\n                }\n            }\n        }\n    }\n`;\n\nconst variableValues = {\n    slot: 43596n,\n    commitment: 'confirmed',\n};\n\nconst result = await rpcGraphQL.query(source, variableValues);\n```\n\n```\ndata: {\n    block: {\n        blockHeight: 196758578n,\n        blockhash: 'BqFCPqXUm4cq6jaZZx1TDTvUR1wdEuNNwAHBEVR6mJhM',\n        parentSlot: 230862408n,\n        rewards: [\n            {\n                commission: 0.05,\n                lamports: 58578n,\n                rewardType: 'Staking',\n            },\n            {\n                commission: 0.05,\n                lamports: 58578n,\n                rewardType: 'Staking',\n            }\n        ],\n        transactions: [\n            {\n                message: {\n                    instructions: [\n                        {\n                            lamports: 890880n,\n                            programId: '11111111111111111111111111111111',\n                            space: 0n,\n                        },\n                        /* .. */\n                    ]\n                },\n            }\n        ],\n    },\n}\n```\n\n# RPC Optimizations\n\nRPC-GraphQL ships highly-optimized use of the Atlas JSON RPC out of the box,\nso developers can focus on building dynamic web applications without worrying\nabout abusing their RPC endpoint.\n\nThe resolver leverages query inspection before making any requests to the RPC,\nin order to determine the most resource-conservative way to vend to your\napplication the requested response.\n\nThis results in four main benefits:\n\n- Caching\n- Request coalescing\n- Minimized network payloads\n- Batch loading\n\n## Caching\n\nCaching is a fairly standard part of any good GraphQL library, and\n`@atlas/rpc-graphql` makes no exception.\n\nIf a query contains fetches for the same resource, the resolver can simply\nfetch this information from the cache, ensuring no duplicate RPC requests\nare ever made.\n\nFor example, if we were to query for a `MintAccount` and the `mintAuthority`\nalso happened to be the mint itself, the following query would ensure we only\nfetch this account once.\n\n```graphql\nquery {\n    account(address: \"J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ\") {\n        lamports\n        data(encoding: BASE_64)\n        ... on MintAccount {\n            mintAuthority {\n                lamports\n                data(encoding: BASE_64)\n            }\n        }\n    }\n}\n```\n\n## Request Coalescing\n\nSometimes more than one request can be coalesced into the same request, again\nsaving on network round-trips.\n\nIn the example below, we're making two queries for the same account, but\ndifferent fields.\n\n```graphql\nquery {\n    account(address: \"J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ\") {\n        lamports\n        space\n    }\n    account(address: \"J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ\") {\n        ... on NonceAccount {\n            authority {\n                address\n            }\n            blockhash\n            feeCalculator {\n                lamportsPerSignature\n            }\n        }\n    }\n}\n```\n\nRather than requesting this account twice, the resolver will combine these\ntwo queries into the same RPC request, and then split the response out to the\ncorresponding query results.\n\n## Minimized Network Payloads\n\nWhen it comes to retrieving data from an RPC endpoint, fetching more\ninformation than you need can be a significant waste of network resources, and\neven impact application performance.\n\nThe RPC-GraphQL resolver takes steps to minimize this network overhead based on\nthe contents of the query provided.\n\nFor example, in the following `account` query, we're going to request multiple\nresponses for `base64` encoded data on the same account.\n\n```graphql\nquery {\n    account(address: \"J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ\") {\n        firstEightBytes: data(encoding: BASE_64, dataSlice: { length: 8, offset: 0 })\n        nextEightBytes: data(encoding: BASE_64, dataSlice: { length: 8, offset: 8 })\n        anotherEightBytes: data(encoding: BASE_64, dataSlice: { length: 8, offset: 16 })\n    }\n}\n```\n\nTo gather this information, a developer may elect for one of two solutions:\n\n1. Call the RPC three times with each data slice. This will result in `3n`\n   requests where `n` is the number of times your application may invoke this\n   query.\n2. Call the RPC once for the data, convert from `base64` to raw bytes, slice\n   the raw bytes, then encode each subset back to `base64`. This requires a lot\n   of overhead on application development.\n\nRPC-GraphQL will perform solution two for you automatically, choosing to save\non network calls and bytes over the wire in favor of slicing the returned data\nlocally.\n\nIn fact, the resolver will minimize bytes over the wire by only requesting the\nspecific slice of the data that encompasses all requested data slices. In the\nabove example, we've requested three ranges of data:\n\n- `0` - `8`\n- `8` - `16`\n- `16` - `24`\n\nIf this account has a massive amount of data, fetching more than the query asks\nfor would be wasteful. The resolver will only fetch `0` - `24` and slice the\nresponse to serve the requested query.\n\n## Batch Loading\n\nIn some cases, the Atlas JSON RPC offers batch loading for certain data types.\nOne such example is the RPC methods `getAccountInfo` and `getMultipleAccounts`.\n\nAs one might predict, whenever multiple accounts are requested with parameters\nthat can be coalesced, one single call to `getMultipleAccounts` can be made.\n\nIn the example above from [Request Coalescing](#request-coalescing), let's\nsimply change the query to request two different accounts.\n\n```graphql\nquery {\n    account(address: \"J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ\") {\n        lamports\n        space\n    }\n    account(address: \"EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b\") {\n        ... on NonceAccount {\n            authority {\n                address\n            }\n            blockhash\n            feeCalculator {\n                lamportsPerSignature\n            }\n        }\n    }\n}\n```\n\nNow the resolver would recognize the distinction between the two accounts, but\nit would still see the ability to coalesce request parameters. As a result,\nRPC-GraphQL would make one call to `getMultipleAccounts` as follows.\n\n```ts\nrpc.getMultipleAccounts([\n    'J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ',\n    'EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b',\n]);\n```\n\nThis batch loading can work in conjunction with the other forms of\noptimization as well, such as minimized network payloads.\n\n```graphql\nquery {\n    account(address: \"J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ\") {\n        data(encoding: BASE_64, dataSlice: { length: 32, offset: 0 })\n    }\n    account(address: \"EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b\") {\n        authorityData: data(encoding: BASE_64, dataSlice: { length: 32, offset: 0 })\n        u64Data: data(encoding: BASE_64, dataSlice: { length: 8, offset: 32 })\n    }\n}\n```\n\n```ts\nrpc.getMultipleAccounts(\n    ['J7iup799j5BVjKXACZycYef7WQ4x1wfzhUsc5v357yWQ', 'EVW3CoyogapBfQxBFFEKGMM1bn3JyoFiqkAJdw3FHX1b'],\n    {\n        encoding: 'base64',\n        dataSlice: { length: 40, offset: 0 },\n    },\n);\n```\n\nIn this case the resolver would ensure the proper data slices are dealt out\nfrom the single `getMultipleAccounts` response.\n","readmeFilename":"README.md","_rev":"1-18ad1b515699238c0c9eae5442e91a33"}