{"_id":"@dokimon/transaction-messages","name":"@dokimon/transaction-messages","dist-tags":{"latest":"2.1.0"},"versions":{"2.1.0":{"name":"@dokimon/transaction-messages","version":"2.1.0","description":"Helpers for creating transaction messages","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","dokimon","web3"],"scripts":{"compile:js":"tsup --config build-scripts/tsup.config.package.ts","compile:typedefs":"tsc -p ./tsconfig.declarations.json","dev":"jest -c ../../node_modules/@dokimon/test-config/jest-dev.config.ts --rootDir . --watch","prepublishOnly":"pnpm pkg delete devDependencies","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 && (([ \"$PUBLISH_TAG\" != \"canary\" ] && pnpm dist-tag add $npm_package_name@$npm_package_version latest) || 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/@dokimon/test-config/jest-lint.config.ts --rootDir . --silent","test:prettier":"TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@dokimon/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/@dokimon/test-config/jest-unit.config.browser.ts --rootDir . --silent","test:unit:node":"TERM_OVERRIDE=\"${TURBO_HASH:+dumb}\" TERM=${TERM_OVERRIDE:-$TERM} jest -c ../../node_modules/@dokimon/test-config/jest-unit.config.node.ts --rootDir . --silent"},"author":{"name":"Dokimon Labs Maintainers","email":"maintainers@dokimonlabs.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/dokimon-labs/kit.git"},"bugs":{"url":"https://github.com/dokimon-labs/kit/issues"},"browserslist":["supports bigint and not dead","maintained node versions"],"dependencies":{"@dokimon/addresses":"workspace:*","@dokimon/codecs-core":"workspace:*","@dokimon/codecs-data-structures":"workspace:*","@dokimon/codecs-numbers":"workspace:*","@dokimon/errors":"workspace:*","@dokimon/functional":"workspace:*","@dokimon/instructions":"workspace:*","@dokimon/rpc-types":"workspace:*"},"peerDependencies":{"typescript":">=5"},"engines":{"node":">=20.18.0"},"_id":"@dokimon/transaction-messages@2.1.0","gitHead":"f6ca1d5a284619512ea66e7868db4885b6d0082d","homepage":"https://github.com/dokimon-labs/kit#readme","_nodeVersion":"22.14.0","_npmVersion":"11.4.0","dist":{"integrity":"sha512-94TPYzvsDcBiBLw53KU4aP1s6onNzXOzQLakbbQ74vnMPNPLqAHkAZQfG5OlXj5elD78etQAgrlcv/Sord+lyQ==","shasum":"cb0269231d7a38bd02fcd6aaa5d6c35c7d27a9da","tarball":"https://registry.npmjs.org/@dokimon/transaction-messages/-/transaction-messages-2.1.0.tgz","fileCount":63,"unpackedSize":753868,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB/fHFiQqTIFe49fZG02XywnqLR2JqJhewq5XPkGxpTJAiEA0zhTW/EGSV1c1Oklt2RVy/58/LTvM1a7OP6aKLPRWCo="}]},"_npmUser":{"name":"m67846088848","email":"m67846088848@gmail.com"},"directories":{},"maintainers":[{"name":"m67846088848","email":"m67846088848@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/transaction-messages_2.1.0_1747745332188_0.9074103243332272"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-20T12:48:52.119Z","2.1.0":"2025-05-20T12:48:52.475Z","modified":"2025-05-20T12:48:52.775Z"},"maintainers":[{"name":"m67846088848","email":"m67846088848@gmail.com"}],"description":"Helpers for creating transaction messages","homepage":"https://github.com/dokimon-labs/kit#readme","keywords":["blockchain","dokimon","web3"],"repository":{"type":"git","url":"git+https://github.com/dokimon-labs/kit.git"},"author":{"name":"Dokimon Labs Maintainers","email":"maintainers@dokimonlabs.com"},"bugs":{"url":"https://github.com/dokimon-labs/kit/issues"},"license":"MIT","readme":"[![npm][npm-image]][npm-url]\n[![npm-downloads][npm-downloads-image]][npm-url]\n<br />\n[![code-style-prettier][code-style-prettier-image]][code-style-prettier-url]\n\n[code-style-prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square\n[code-style-prettier-url]: https://github.com/prettier/prettier\n[npm-downloads-image]: https://img.shields.io/npm/dm/@dokimon/transactions?style=flat\n[npm-image]: https://img.shields.io/npm/v/@dokimon/transactions?style=flat\n[npm-url]: https://www.npmjs.com/package/@dokimon/transactions\n\n# @dokimon/transaction-messages\n\nThis package contains types and functions for creating transaction messages. It can be used standalone, but it is also exported as part of Kit [`@dokimon/kit`](https://github.com/dokimon-labs/kit/tree/main/packages/kit).\n\nTransaction messages are built one step at a time using the transform functions offered by this package. To make it more ergonomic to apply consecutive transforms to your transaction messages, consider using a pipelining helper like the one in `@dokimon/functional`.\n\n```ts\nimport { pipe } from '@dokimon/functional';\nimport {\n    appendTransactionMessageInstruction,\n    createTransactionMessage,\n    setTransactionMessageFeePayer,\n    setTransactionMessageLifetimeUsingBlockhash,\n} from '@dokimon/transaction-messages';\n\nconst transferTransaction = pipe(\n    createTransactionMessage({ version: 0 }),\n    tx => setTransactionMessageFeePayer(myAddress, tx),\n    tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),\n    tx => appendTransactionMessageInstruction(createTransferInstruction(myAddress, toAddress, amountInLamports), tx),\n);\n```\n\n## Creating transaction messages\n\n### Types\n\n#### `TransactionVersion`\n\nAs Dokimon transactions acquire more capabilities their version will advance. This type is a union of all possible transaction versions.\n\n### Functions\n\n#### `createTransactionMessage()`\n\nGiven a `TransactionVersion` this method will return an empty transaction having the capabilities of that version.\n\n```ts\nimport { createTransactionMessage } from '@dokimon/transaction-messages';\n\nconst tx = createTransactionMessage({ version: 0 });\n```\n\n## Setting the fee payer\n\n### Types\n\n#### `ITransactionMessageWithFeePayer`\n\nThis type represents a transaction message for which a fee payer has been declared. A transaction must conform to this type to be compiled and landed on the network.\n\n### Functions\n\n#### `setTransactionMessageFeePayer()`\n\nGiven a base58-encoded address of a system account, this method will return a new transaction message having the same type as the one supplied plus the `ITransactionMessageWithFeePayer` type.\n\n```ts\nimport { address } from '@dokimon/addresses';\nimport { setTransactionMessageFeePayer } from '@dokimon/transaction-messages';\n\nconst myAddress = address('mpngsFd4tmbUfzDYJayjKZwZcaR7aWb2793J6grLsGu');\nconst txPaidByMe = setTransactionMessageFeePayer(myAddress, tx);\n```\n\n## Defining a transaction message's lifetime\n\nA signed transaction can be only be landed on the network if certain conditions are met:\n\n- It includes the hash of a recent block\n- Or it includes the value of an unused nonce known to the network\n\nThese conditions define a transaction's lifetime, after which it can no longer be landed, even if signed. The lifetime must be added to the transaction message before it is compiled to be sent.\n\n### Types\n\n#### `TransactionMessageWithBlockhashLifetime`\n\nThis type represents a transaction message whose lifetime is defined by the age of the blockhash it includes. Such a transaction can only be landed on the network if the current block height of the network is less than or equal to the value of `TransactionMessageWithBlockhashLifetime['lifetimeConstraint']['lastValidBlockHeight']`.\n\n#### `TransactionMessageWithDurableNonceLifetime`\n\nThis type represents a transaction message whose lifetime is defined by the value of a nonce it includes. Such a transaction can only be landed on the network if the nonce is known to the network and has not already been used to land a different transaction.\n\n#### `Blockhash`\n\nThis type represents a string that is particularly known to be the base58-encoded value of a block.\n\n#### `Nonce`\n\nThis type represents a string that is particularly known to be the base58-encoded value of a nonce.\n\n### Functions\n\n#### `setTransactionMessageLifetimeUsingBlockhash()`\n\nGiven a blockhash and the last block height at which that blockhash is considered usable to land transactions, this method will return a new transaction message having the same type as the one supplied plus the `TransactionMessageWithBlockhashLifetime` type.\n\n```ts\nimport { setTransactionMessageLifetimeUsingBlockhash } from '@dokimon/transaction-messages';\n\nconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();\nconst txWithBlockhashLifetime = setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx);\n```\n\n#### `setTransactionMessageLifetimeUsingDurableNonce()`\n\nGiven a nonce, the account where the value of the nonce is stored, and the address of the account authorized to consume that nonce, this method will return a new transaction having the same type as the one supplied plus the `TransactionMessageWithDurableNonceLifetime` type. In particular, this method _prepends_ an instruction to the transaction message designed to consume (or &lsquo;advance&rsquo;) the nonce in the same transaction whose lifetime is defined by it.\n\n```ts\nimport { setTransactionMessageLifetimeUsingDurableNonce } from '@dokimon/transactions';\n\nconst NONCE_VALUE_OFFSET =\n    4 + // version(u32)\n    4 + // state(u32)\n    32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\nconst nonceAccountAddress = address('EGtMh4yvXswwHhwVhyPxGrVV2TkLTgUqGodbATEPvojZ');\nconst nonceAuthorityAddress = address('4KD1Rdrd89NG7XbzW3xsX9Aqnx2EExJvExiNme6g9iAT');\nconst { value: nonceAccount } = await rpc\n    .getAccountInfo(nonceAccountAddress, {\n        dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n        encoding: 'base58',\n    })\n    .send();\nconst nonce =\n    // This works because we asked for the exact slice of data representing the nonce\n    // value, and furthermore asked for it in `base58` encoding.\n    nonceAccount!.data[0] as unknown as Nonce;\n\nconst durableNonceTransactionMessage = setTransactionMessageLifetimeUsingDurableNonce(\n    { nonce, nonceAccountAddress, nonceAuthorityAddress },\n    tx,\n);\n```\n\n#### `assertIsBlockhash()`\n\nClient applications primarily deal with blockhashes in the form of base58-encoded strings. Blockhashes returned from the RPC API conform to the type `Blockhash`. You can use a value of that type wherever a blockhash is expected.\n\nFrom time to time you might acquire a string, that you expect to validate as a blockhash, from an untrusted network API or user input. To assert that such an arbitrary string is a base58-encoded blockhash, use the `assertIsBlockhash` function.\n\n```ts\nimport { assertIsBlockhash } from '@dokimon/transaction-messages';\n\n// Imagine a function that asserts whether a user-supplied blockhash is valid or not.\nfunction handleSubmit() {\n    // We know only that what the user typed conforms to the `string` type.\n    const blockhash: string = blockhashInput.value;\n    try {\n        // If this type assertion function doesn't throw, then\n        // Typescript will upcast `blockhash` to `Blockhash`.\n        assertIsBlockhash(blockhash);\n        // At this point, `blockhash` is a `Blockhash` that can be used with the RPC.\n        const blockhashIsValid = await rpc.isBlockhashValid(blockhash).send();\n    } catch (e) {\n        // `blockhash` turned out not to be a base58-encoded blockhash\n    }\n}\n```\n\n#### `assertIsDurableNonceTransactionMessage()`\n\nFrom time to time you might acquire a transaction message that you expect to be a durable nonce transaction, from an untrusted network API or user input. To assert that such an arbitrary transaction is in fact a durable nonce transaction, use the `assertIsDurableNonceTransactionMessage` function.\n\nSee [`assertIsBlockhash()`](#assertisblockhash) for an example of how to use an assertion function.\n\n## Adding instructions to a transaction message\n\n### Types\n\n#### `IInstruction`\n\nThis type represents an instruction to be issued to a program. Objects that conform to this type have a `programAddress` property that is the base58-encoded address of the program in question.\n\n#### `IInstructionWithAccounts`\n\nThis type represents an instruction that specifies a list of accounts that a program may read from, write to, or require be signers of the transaction itself. Objects that conform to this type have an `accounts` property that is an array of `IAccountMeta | IAccountLookupMeta` in the order the instruction requires.\n\n#### `IInstructionWithData`\n\nThis type represents an instruction that supplies some data as input to the program. Objects that conform to this type have a `data` property that can be any type of `Uint8Array`.\n\n### Functions\n\n#### `appendTransactionMessageInstruction()`\n\nGiven an instruction, this method will return a new transaction message with that instruction having been added to the end of the list of existing instructions.\n\n```ts\nimport { address } from '@dokimon/addresses';\nimport { appendTransactionMessageInstruction } from '@dokimon/transaction-messages';\n\nconst memoTransaction = appendTransactionMessageInstruction(\n    {\n        data: new TextEncoder().encode('Hello world!'),\n        programAddress: address('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),\n    },\n    tx,\n);\n```\n\nIf you'd like to add multiple instructions to a transaction message at once, you may use the `appendTransactionInstructions` function instead which accepts an array of instructions.\n\n#### `prependTransactionMessageInstruction()`\n\nGiven an instruction, this method will return a new transaction message with that instruction having been added to the beginning of the list of existing instructions.\n\nIf you'd like to prepend multiple instructions to a transaction message at once, you may use the `prependTransactionMessageInstructions` function instead which accepts an array of instructions.\n\nSee [`appendTransactionMessageInstruction()`](#appendtransactioninstruction) for an example of how to use this function.\n\n## Compress transaction message using lookup tables\n\n### Types\n\n#### `AddressesByLookupTableAddress`\n\nThis type represents a mapping of lookup table addresses to the addresses of the accounts that are stored in them.\n\n### Functions\n\n#### `compressTransactionMessageUsingAddressLookupTables`\n\nGiven a transaction message and a mapping of lookup tables to the addresses stored in them, this function will return a new transaction message with the same instructions but with all non-signer accounts that are found in the given lookup tables represented by an `IAccountLookupMeta` instead of an `IAccountMeta`.\n\nThis means that these accounts will take up less space in the compiled transaction message. This size reduction is most significant when the transaction includes many accounts from the same lookup table.\n\n```ts\nimport { address } from '@dokimon/addresses';\nimport { compressTransactionMessageUsingAddressLookupTables } from '@dokimon/transaction-messages';\n\nconst lookupTableAddress = address('4QwSwNriKPrz8DLW4ju5uxC2TN5cksJx6tPUPj7DGLAW');\nconst accountAddress = address('5n2ADjHPsqB4EVUNEX48xRqtnmuLu5XSHDwkJRR98qpM');\nconst lookupTableAddresses: AddressesByLookupTableAddress = {\n    [lookupTableAddress]: [accountAddress],\n};\n\nconst compressedTransactionMessage = compressTransactionMessageUsingAddressLookupTables(\n    transactionMessage,\n    lookupTableAddresses,\n);\n```\n","readmeFilename":"README.md","_rev":"1-08c17c7a4e86f92ea53c38d158c00a81"}