{"id":21870003,"url":"https://github.com/solana-developers/helpers","last_synced_at":"2026-02-16T06:35:12.535Z","repository":{"id":192843759,"uuid":"687531456","full_name":"solana-developers/helpers","owner":"solana-developers","description":"JS/TS helpers for Solana","archived":false,"fork":false,"pushed_at":"2025-03-20T14:59:21.000Z","size":345,"stargazers_count":131,"open_issues_count":10,"forks_count":29,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-10-19T01:33:50.086Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@solana-developers/helpers","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solana-developers.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-05T14:44:45.000Z","updated_at":"2025-10-16T18:16:25.000Z","dependencies_parsed_at":"2023-12-19T02:41:35.051Z","dependency_job_id":"84118402-91d7-4c27-9618-b8c4e2dd853b","html_url":"https://github.com/solana-developers/helpers","commit_stats":null,"previous_names":["solana-developers/node-helpers"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/solana-developers/helpers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solana-developers%2Fhelpers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solana-developers%2Fhelpers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solana-developers%2Fhelpers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solana-developers%2Fhelpers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solana-developers","download_url":"https://codeload.github.com/solana-developers/helpers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solana-developers%2Fhelpers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29501919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T05:57:17.024Z","status":"ssl_error","status_checked_at":"2026-02-16T05:56:49.929Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T06:09:55.704Z","updated_at":"2026-02-16T06:35:12.519Z","avatar_url":"https://github.com/solana-developers.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Solana web3.js v1 helpers\n\nThe `@solana-developers/helpers` package contains Solana helper functions, for use in the browser\nand/or node.js, made by the Solana Foundation's\n[Developer Relations team](https://x.com/solana_devs) and contributions from\n[Anza](https://anza.xyz), [Turbin3](https://turbin3.com/),\n[Unboxed Software](https://beunboxed.com/), and [StarAtlas](https://staratlas.com/).\n\n\u003e [!IMPORTANT]  \n\u003e `@solana-developers/helpers` is for Solana web3.js version 1. The updated version of this package\n\u003e which is compatible with Solana web3.js version 2 is called `gill`. Learn more here:\n\u003e\n\u003e - npm registry - https://www.npmjs.com/package/gill\n\u003e - source repository - https://github.com/solana-foundation/gill\n\n## What can I do with this module?\n\n### Account \u0026 Keypair Management:\n\n[Make multiple keypairs at once](#make-multiple-keypairs-at-once)\n\n[Get a keypair from a keypair file](#get-a-keypair-from-a-keypair-file)\n\n[Get a keypair from an environment variable](#get-a-keypair-from-an-environment-variable)\n\n[Add a new keypair to an env file](#add-a-new-keypair-to-an-env-file)\n\n[Load or create a keypair and airdrop to it if needed](#load-or-create-a-keypair-and-airdrop-to-it-if-needed)\n\n### Token Operations:\n\n[Make a token mint with metadata](#make-a-token-mint-with-metadata)\n\n[Create multiple accounts with balances of different tokens in a single step](#create-users-mints-and-token-accounts-in-a-single-step)\n\n### Transaction \u0026 Compute Management:\n\n[Confirm a transaction](#confirm-a-transaction)\n\n[Get the logs for a transaction](#get-the-logs-for-a-transaction)\n\n[Get simulated compute units (CUs) for transaction instructions](#get-simulated-compute-units-cus-for-transaction-instructions)\n\n[Get an airdrop if your balance is below some amount](#get-an-airdrop-if-your-balance-is-below-some-amount)\n\n### Error Handling \u0026 Utilities:\n\n[Resolve a custom error message](#resolve-a-custom-error-message)\n\n[Get a Solana Explorer link for a transaction, address, or block](#get-a-solana-explorer-link-for-a-transaction-address-or-block)\n\n### Anchor Program Interaction:\n\n[Parse account data with IDL](#parse-account-data-with-idl)\n\n[Parse transaction events](#parse-transaction-events)\n\n[Decode Anchor transaction](#decode-anchor-transaction)\n\n## Installation\n\n```bash\nnpm i @solana-developers/helpers\n```\n\n## Contributing\n\nPRs are very much welcome! Read the\n[CONTRIBUTING guidelines for the Solana course](https://github.com/Unboxed-Software/solana-course/blob/main/CONTRIBUTING.md#code)\nthen send a PR!\n\n## Helpers for the browser and node.js\n\n### Make multiple keypairs at once\n\nUsage:\n\n```typescript\nmakeKeypairs(amount);\n```\n\nIn some situations - like making tests for your onchain programs - you might need to make lots of\nkeypairs at once. You can use `makeKeypairs()` combined with JS destructuring to quickly create\nmultiple variables with distinct keypairs.\n\n```typescript\nconst [sender, recipient] = makeKeypairs(2);\n```\n\n### Make a token mint with metadata\n\nThe `makeTokenMint` makes a new token mint. A token mint is effectively the factory that produces\ntoken of a particular type. So if you want to make a new token, this is the right function for you!\n\nUnlike older tools, the function uses Token Extensions Metadata and Metadata Pointer to put all\nmetadata into the Mint Account, without needing an external Metadata account. If you don't know what\nthat means, just know that things are simpler than they used to be!\n\nParameters\n\n- `connection`: Connection.\n- `mintAuthority`: Keypair of the account that can make new tokens.\n- `name`: string, name of the token.\n- `symbol`: string, like a ticker symbol. Usually in all-caps.\n- `decimals`: number, how many decimal places the new token will have.\n- `uri`: string, URI to a JSON file containing at minimum a value for `image`.\n- `additionalMetadata`: additional metadata as either `Record\u003cstring, string\u003e` or\n  `Array\u003c[string, string]\u003e`(optional).\n- `updateAuthority`: PublicKey (optional) - public key of the account that can update the token.\n- `freezeAuthority`: PublicKey (optional) - public key of the freeze account, default to `null`\n\n```typescript\nconst mintAddress = await makeTokenMint(\n  connection,\n  mintAuthority,\n  \"Unit test token\",\n  \"TEST\",\n  9,\n  \"https://raw.githubusercontent.com/solana-developers/professional-education/main/labs/sample-token-metadata.json\",\n);\n```\n\n### Create users, mints and token accounts in a single step\n\nFrequently, tests for onchain programs need to make not just users with SOL, but also token mints\nand give each user some balance of each token. To save this boilerplate,\n`createAccountsMintsAndTokenAccounts()` handles making user keypairs, giving them SOL, making mints,\ncreating associated token accounts, and minting tokens directly to the associated token accounts.\n\nEg, to make two new users, and two tokens:\n\n- the first user with million of the first token, none of the second token, and 1 SOL\n- the second user with none of the first token, 1 million of the second token, and 1 SOL\n\nJust run:\n\n```typescript\nconst usersMintsAndTokenAccounts = await createAccountsMintsAndTokenAccounts(\n  [\n    [1_000_000_000, 0], // User 0 has 1_000_000_000 of token A and 0 of token B\n    [0, 1_000_000_000], // User 1 has 0 of token A and 1_000_000_000 of token B\n  ],\n  1 * LAMPORTS_PER_SOL,\n  connection,\n  payer,\n);\n```\n\nThe returned `usersMintsAndTokenAccounts` will be an object of the form:\n\n```\n{\n  users: \u003cArray\u003cKeypair\u003e\u003e\n  mints: \u003cArray\u003cKeypair\u003e\u003e,\n  tokenAccounts: \u003cArray\u003cArray\u003e\u003cPublicKey\u003e\u003e\u003e\n}\n```\n\ntokenAccounts are indexed by the user, then the mint. Eg, the ATA of `user[0]` for `mint[0]` is\n`tokenAccounts[0][0]`.\n\n### Resolve a custom error message\n\nUsage:\n\n```typescript\ngetCustomErrorMessage(programErrors, errorMessage);\n```\n\nSometimes Solana transactions throw an error with a message like:\n\n\u003e failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom\n\u003e program error: 0x10\n\nUsage:\n\n```typescript\ngetCustomErrorMessage();\n```\n\nAllows you to turn this message into a more readable message from the custom program, like:\n\n\u003e This token mint cannot freeze accounts\n\nJust:\n\n- Get the errors from the specific program's `error.rs` file - for example, there are\n  [the errors for the Token Program](https://github.com/solana-labs/solana-program-library/blob/master/token/program/src/error.rs)\n\n- Save the errors into an array\n\n```typescript\n// Token program errors\n// https://github.com/solana-labs/solana-program-library/blob/master/token/program/src/error.rs\nconst tokenProgramErrors = [\n  \"Lamport balance below rent-exempt threshold\",\n  \"Insufficient funds\",\n  \"Invalid Mint\",\n  \"Account not associated with this Mint\",\n  \"Owner does not match\",\n  \"Fixed supply\",\n  \"Already in use\",\n  \"Invalid number of provided signers\",\n  \"Invalid number of required signers\",\n  \"State is unititialized\",\n  \"Instruction does not support native tokens\",\n  \"Non-native account can only be closed if its balance is zero\",\n  \"Invalid instruction\",\n  \"State is invalid for requested operation\",\n  \"Operation overflowed\",\n  \"Account does not support specified authority type\",\n  \"This token mint cannot freeze accounts\",\n  \"Account is frozen\",\n  \"The provided decimals value different from the Mint decimals\",\n  \"Instruction does not support non-native tokens\",\n];\n```\n\nThen run:\n\n```typescript\nconst errorMessage = getCustomErrorMessage(\n  tokenProgramErrors,\n  \"failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom program error: 0x10\",\n);\n```\n\nAnd `errorMessage` will now be:\n\n```typescript\n\"This token mint cannot freeze accounts\";\n```\n\n### Get an airdrop if your balance is below some amount\n\nUsage:\n\n```typescript\nairdropIfRequired(connection, publicKey, lamports, maximumBalance);\n```\n\nRequest and confirm an airdrop in one step. As soon as the `await` returns, the airdropped tokens\nwill be ready to use, and the new balance of tokens will be returned. The `maximumBalance` is used\nto avoid errors caused by unnecessarily asking for SOL when there's already enough in the account,\nand makes `airdropIfRequired()` very handy in scripts that run repeatedly.\n\nTo ask for 0.5 SOL, if the balance is below 1 SOL, use:\n\n```typescript\nconst newBalance = await airdropIfRequired(\n  connection,\n  keypair.publicKey,\n  0.5 * LAMPORTS_PER_SOL,\n  1 * LAMPORTS_PER_SOL,\n);\n```\n\n### Get a Solana Explorer link for a transaction, address, or block\n\nUsage:\n\n```typescript\ngetExplorerLink(type, identifier, clusterName);\n```\n\nGet an explorer link for an `address`, `block` or `transaction` (`tx` works too).\n\n```typescript\ngetExplorerLink(\"address\", \"dDCQNnDmNbFVi8cQhKAgXhyhXeJ625tvwsunRyRc7c8\", \"mainnet-beta\");\n```\n\nWill return `\"https://explorer.solana.com/address/dDCQNnDmNbFVi8cQhKAgXhyhXeJ625tvwsunRyRc7c8\"`. The\ncluster name isn't included since mainnet-beta is the default.\n\n```typescript\ngetExplorerLink(\"address\", \"dDCQNnDmNbFVi8cQhKAgXhyhXeJ625tvwsunRyRc7c8\", \"devnet\");\n```\n\nWill return\n`\"https://explorer.solana.com/address/dDCQNnDmNbFVi8cQhKAgXhyhXeJ625tvwsunRyRc7c8?cluster=devnet\"`\n\n```typescript\ngetExplorerLink(\"block\", \"241889720\", \"mainnet-beta\");\n```\n\nWill return `\"https://explorer.solana.com/block/241889720\"`\n\n### Confirm a transaction\n\nUsage:\n\n```typescript\nconfirmTransaction(connection, transaction);\n```\n\nConfirm a transaction, and also gets the recent blockhash required to confirm it.\n\n```typescript\nawait confirmTransaction(connection, transaction);\n```\n\n### Get the logs for a transaction\n\nUsage:\n\n```typescript\ngetLogs(connection, transaction);\n```\n\nGet the logs for a transaction signature:\n\n```typescript\nconst logs = await getLogs(connection, transaction);\n```\n\nThe `logs` will be an array of strings, eg:\n\n```typescript\n[\n  \"Program 11111111111111111111111111111111 invoke [1]\",\n  \"Program 11111111111111111111111111111111 success\",\n];\n```\n\nThis a good way to assert your onchain programs return particular logs during unit tests.\n\n### Get simulated compute units (CUs) for transaction instructions\n\nUsage:\n\n```typescript\ngetSimulationComputeUnits(connection, instructions, payer, lookupTables);\n```\n\nGet the compute units required for an array of instructions. Create your instructions:\n\n```typescript\nconst sendSol = SystemProgram.transfer({\n  fromPubkey: payer.publicKey,\n  toPubkey: recipient,\n  lamports: 1_000_000,\n});\n```\n\nThen use `getSimulationComputeUnits` to get the number of compute units the instructions will use:\n\n```typescript\nconst units = await getSimulationComputeUnits(connection, [sendSol], payer.publicKey);\n```\n\nYou can then use `ComputeBudgetProgram.setComputeUnitLimit({ units })` as the first instruction in\nyour transaction. See\n[How to Request Optimal Compute Budget](https://solana.com/developers/guides/advanced/how-to-request-optimal-compute)\nfor more information on compute units.\n\n### `addComputeInstructions`\n\nAdds compute unit instructions for a transaction if they don't already exist:\n\n```typescript\nconst updatedInstructions = await addComputeInstructions(\n  connection,\n  instructions,\n  lookupTables,\n  payer.publicKey,\n  10000, // priority fee default 10000 microLamports\n  { multiplier: 1.1 }, // compute unit buffer default adds 10%\n);\n\n// Returns instructions array with:\n// 1. setComputeUnitPrice instruction (if not present)\n// 2. setComputeUnitLimit instruction based on simulation (if not present)\n// The limit is calculated by simulating the transaction and adding the specified buffer\n```\n\nThis function:\n\n1. Adds priority fee instruction if not present\n2. Simulates transaction to determine required compute units\n3. Adds compute unit limit instruction with buffer\n4. Returns the updated instructions array\n\n## Node.js specific helpers\n\n### Get a keypair from a keypair file\n\nUsage:\n\n```typescript\ngetKeypairFromFile(filename);\n```\n\nGets a keypair from a file - the format must be the same as\n[Solana CLI](https://docs.anza.xyz/cli/wallets/file-system) uses, ie, a JSON array of numbers:\n\nTo load the default keypair `~/.config/solana/id.json`, just run:\n\n```typescript\nconst keyPair = await getKeypairFromFile();\n```\n\nor to load a specific file:\n\n```typescript\nconst keyPair = await getKeypairFromFile(\"somefile.json\");\n```\n\nor using home dir expansion:\n\n```typescript\nconst keyPair = await getKeypairFromFile(\"~/code/solana/demos/steve.json\");\n```\n\n### Get a keypair from an environment variable\n\nUsage:\n\n```typescript\ngetKeypairFromEnvironment(environmentVariable);\n```\n\nGets a keypair from a secret key stored in an environment variable. This is typically used to load\nsecret keys from\n[env files](https://stackoverflow.com/questions/68267862/what-is-an-env-or-dotenv-file-exactly).\n\n```typescript\nconst keypair = await getKeypairFromEnvironment(\"SECRET_KEY\");\n```\n\n### Add a new keypair to an env file\n\nUsage:\n\n```typescript\naddKeypairToEnvFile(keypair, environmentVariable, envFileName);\n```\n\nSaves a keypair to the environment file.\n\n```typescript\nawait addKeypairToEnvFile(testKeypair, \"SECRET_KEY\");\n```\n\nor to specify a file name:\n\n```typescript\nawait addKeypairToEnvFile(testKeypair, \"SECRET_KEY\", \".env.local\");\n```\n\nThis will also reload the env file.\n\n### Load or create a keypair and airdrop to it if needed\n\nUsage:\n\n```typescript\ninitializeKeypair(connection, options);\n```\n\nLoads in a keypair from the filesystem, or environment and then airdrops to it if needed.\n\nHow the keypair is initialized is dependent on the `initializeKeypairOptions`:\n\n```typescript\ninterface initializeKeypairOptions {\n  envFileName?: string;\n  envVariableName?: string;\n  airdropAmount?: number | null;\n  minimumBalance?: number;\n  keypairPath?: string;\n}\n```\n\nBy default, the keypair will be retrieved from the `.env` file. If a `.env` file does not exist,\nthis function will create one with a new keypair under the optional `envVariableName`.\n\nTo load the keypair from the filesystem, pass in the `keypairPath`. When set, loading a keypair from\nthe filesystem will take precedence over loading from the `.env` file.\n\nIf `airdropAmount` amount is set to something other than `null` or `0`, this function will then\ncheck the account's balance. If the balance is below the `minimumBalance`, it will airdrop the\naccount `airdropAmount`.\n\nTo initialize a keypair from the `.env` file, and airdrop it 1 sol if it's beneath 0.5 sol:\n\n```typescript\nconst keypair = await initializeKeypair(connection);\n```\n\nTo initialize a keypair from the `.env` file under a different variable name:\n\n```typescript\nconst keypair = await initializeKeypair(connection, {\n  envVariableName: \"TEST_KEYPAIR\",\n});\n```\n\nTo initialize a keypair from the filesystem, and airdrop it 3 sol:\n\n```typescript\nconst keypair = await initializeKeypair(connection, {\n  keypairPath: \"~/.config/solana/id.json\",\n  airdropAmount: LAMPORTS_PER_SOL * 3,\n});\n```\n\nThe default options are as follows:\n\n```typescript\nconst DEFAULT_AIRDROP_AMOUNT = 1 * LAMPORTS_PER_SOL;\nconst DEFAULT_MINIMUM_BALANCE = 0.5 * LAMPORTS_PER_SOL;\nconst DEFAULT_ENV_KEYPAIR_VARIABLE_NAME = \"PRIVATE_KEY\";\n```\n\n## Secret key format\n\nSecret keys can be read in either the more compact base58 format\n(`base58.encode(randomKeypair.secretKey);`), like:\n\n```bash\n# A random secret key for demo purposes\nSECRET_KEY=QqKYBnj5mcgUsS4vrCeyMczbTyV1SMrr7SjSAPj7JGFtxfrgD8AWU8NciwHNCbmkscbvj4HdeEen42GDBSHCj1N\n```\n\nOr the longer, 'array of numbers' format `JSON.stringify(Object.values(randomKeypair.secretKey));`:\n\n```bash\n# A random secret key for demo purposes\nSECRET_KEY=[112,222,91,246,55,109,221,4,23,148,251,127,212,180,44,249,182,139,18,13,209,208,6,7,193,210,186,249,148,237,237,1,70,118,1,153,238,134,239,75,187,96,101,138,147,130,181,71,22,82,44,217,194,122,59,208,134,119,98,53,136,108,44,105]\n```\n\nWe always save keys using the 'array of numbers' format, since most other Solana apps (like the CLI\nSDK and Rust tools) use the 'array of numbers' format.\n\n## Development\n\nTo run tests, open a terminal tab, and run:\n\n```bash\nsolana-test-validator\n```\n\nThen in a different tab, run:\n\n```bash\nnpm run test\n```\n\nThe tests use the\n[node native test runner](https://blog.logrocket.com/exploring-node-js-native-test-runner/).\n\nIf you'd like to run a single test, use:\n\n```bash\nesrun --node-test-name-pattern=\"getCustomErrorMessage\" src/index.test.ts\n```\n\nTo just run tests matching the name `getCustomErrorMessage`.\n\n### Transaction Utilities\n\n#### `sendTransaction`\n\nSends a transaction with compute unit optimization and automatic retries. This function:\n\n1. Automatically sets compute units based on simulation\n2. Adds priority fees for faster processing\n3. Handles retries and confirmation\n4. Provides detailed status updates\n\n```typescript\nconst signature = await sendTransaction(connection, transaction, [payer]);\n```\n\nThe function is also customizable if you do not like the defaults:\n\n```typescript\nconst signature = await sendTransaction(\n  connection,\n  transaction,\n  [payer],\n  10000, // priority fee in microLamports\n  {\n    computeUnitBuffer: { multiplier: 1.1 }, // add 10% buffer to compute units\n    onStatusUpdate: (status) =\u003e console.log(status),\n    commitment: \"confirmed\",\n    maxRetries: 10,\n    initialDelayMs: 2000,\n  },\n);\n```\n\nThe function will:\n\n- Skip compute preparation if transaction is already signed\n- Skip compute preparation if transaction already has compute budget instructions\n- Add compute budget instructions if needed\n- Handle retries and confirmation automatically\n- Provide status updates: \"created\" → \"signed\" → \"sent\" → \"confirmed\"\n\nFor RPC providers that support priority fees:\n\n- Helius: minimum 10000 microLamports\n- Triton: see their\n  [priority fee API](https://docs.triton.one/chains/solana/improved-priority-fees-api)\n- Quicknode: see their\n  [priority fee estimation](https://www.quicknode.com/docs/solana/qn_estimatePriorityFees)\n\n#### `sendVersionedTransaction`\n\nSends a versioned transaction with compute unit optimization and automatic retries.\n\n```typescript\nasync function sendVersionedTransaction(\n  connection: Connection,\n  instructions: Array\u003cTransactionInstruction\u003e,\n  signers: Keypair[],\n  priorityFee: number = 10000,\n  lookupTables?: Array\u003cAddressLookupTableAccount\u003e | [],\n  options?: SendTransactionOptions \u0026 {\n    computeUnitBuffer?: ComputeUnitBuffer;\n  },\n): Promise\u003cstring\u003e;\n```\n\nExample:\n\n```typescript\nconst signature = await sendVersionedTransaction(\n  connection,\n  instructions,\n  [payer],\n  10000,\n  lookupTables,\n  {\n    computeUnitBuffer: { multiplier: 1.1 },\n    onStatusUpdate: (status) =\u003e console.log(status),\n  },\n);\n```\n\n#### `createLookupTable`\n\nCreates a new address lookup table and extends it with additional addresses.\n\n```typescript\nasync function createLookupTable(\n  connection: Connection,\n  sender: Keypair,\n  additionalAddresses: PublicKey[],\n  priorityFee: number = 10000,\n): Promise\u003c[PublicKey, AddressLookupTableAccount]\u003e;\n```\n\nExample:\n\n```typescript\nconst [lookupTableAddress, lookupTableAccount] = await createLookupTable(connection, payer, [\n  account1.publicKey,\n  account2.publicKey,\n  account3.publicKey,\n]);\n// Can either cache the lookup table address and lookup table account for reuse, or use them directly\nconst signature = await sendVersionedTransaction(\n  connection,\n  instructions,\n  [payer],\n  10000,\n  [lookupTableAccount],\n  {\n    onStatusUpdate: (status) =\u003e console.log(status),\n  },\n);\n```\n\nThese utilities help with:\n\n- Creating and sending versioned transactions\n- Managing compute units and priority fees\n- Using address lookup tables to fit more accounts in a single transaction\n- Automatic transaction retries and status updates\n\n## Anchor IDL Utilities\n\n### Loading IDLs\n\nGet an IDL from a local file:\n\n```typescript\nconst idl = await getIdlByPath(\"./idl/program.json\");\n```\n\nOr fetch it from the chain:\n\n```typescript\nconst idl = await getIdlByProgramId(\n  new PublicKey(\"verifycLy8mB96wd9wqq3WDXQwM4oU6r42Th37Db9fC\"),\n  connection,\n);\n```\n\n### Parse Account Data\n\nUsage:\n\n```typescript\nconst idl = await getIdlByProgramId(programId, connection);\nconst data = await getIdlParsedAccountData(idl, \"counter\", accountAddress, connection);\n\n// Decoded Data: { count: \u003cBN: 2\u003e }\n```\n\nFetches and parses an account's data using an Anchor IDL file. This is useful when you need to\ndecode account data from Anchor programs.\n\n### Parse Transaction Events\n\nUsage:\n\n```typescript\nconst idl = await getIdlByPath(\"./idl/program.json\");\nconst events = await parseAnchorTransactionEvents(idl, signature, connection);\n\n// Events will be an array of:\n// {\n//   name: \"GameCreated\",\n//   data: { gameId: \"123\", player: \"...\" }\n// }\n```\n\nParses all Anchor events emitted in a transaction. This helps you track and verify program events\nafter transaction execution.\n\n### Decode Anchor Transaction\n\nUsage:\n\n```typescript\nconst idl = await getIdlByProgramId(programId, connection);\nconst decoded = await decodeAnchorTransaction(idl, signature, connection);\n\n// Print human-readable format\nconsole.log(decoded.toString());\n\n// Access specific instruction data\ndecoded.instructions.forEach((ix) =\u003e {\n  console.log(`Instruction: ${ix.name}`);\n  console.log(`Arguments: ${JSON.stringify(ix.data)}`);\n  console.log(`Accounts: ${ix.accounts.map((acc) =\u003e acc.name).join(\", \")}`);\n});\n```\n\nProvides detailed decoding of all Anchor instructions in a transaction, including:\n\n- Instruction names and arguments\n- All involved accounts with their roles (signer/writable)\n- Account data for program-owned accounts\n- Human-readable string representation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolana-developers%2Fhelpers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolana-developers%2Fhelpers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolana-developers%2Fhelpers/lists"}