{"_id":"@atlaschain/signers","name":"@atlaschain/signers","dist-tags":{"latest":"3.0.0"},"versions":{"3.0.0":{"name":"@atlaschain/signers","version":"3.0.0","description":"An abstraction layer over signing messages and transactions in Atlas","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":{"@atlaschain/addresses":"3.0.0","@atlaschain/codecs-core":"3.0.0","@atlaschain/instructions":"3.0.0","@atlaschain/errors":"3.0.0","@atlaschain/nominal-types":"3.0.1","@atlaschain/keys":"3.0.0","@atlaschain/transaction-messages":"3.0.0","@atlaschain/transactions":"3.0.0"},"peerDependencies":{"typescript":">=5.3.3"},"engines":{"node":">=20.18.0"},"scripts":{"compile:docs":"typedoc","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 --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 --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 --rootDir . --silent"},"_id":"@atlaschain/signers@3.0.0","homepage":"https://github.com/anza-xyz/kit#readme","_integrity":"sha512-j4FbXDzR+NcKm9+wHEZrldTV2FJR6nlU64s9JwLcBm4r/bJfwLMJaebsz5KNnKuhvRPDkz1WwFpoLLzr0bk/XQ==","_resolved":"/private/var/folders/q8/nr55p0wd491c6fjmbky17kd00000gn/T/6eee97e25e42d6d1fac9f74ad9c2c997/atlaschain-signers-3.0.0.tgz","_from":"file:atlaschain-signers-3.0.0.tgz","_nodeVersion":"22.12.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-j4FbXDzR+NcKm9+wHEZrldTV2FJR6nlU64s9JwLcBm4r/bJfwLMJaebsz5KNnKuhvRPDkz1WwFpoLLzr0bk/XQ==","shasum":"d68f121579d566b60a5f225d89f619a6d3acb5a7","tarball":"https://registry.npmjs.org/@atlaschain/signers/-/signers-3.0.0.tgz","fileCount":5,"unpackedSize":64850,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAn5bdFCFw9hTRwqGNK07fUOrVRQoMyUkoCLejENBk1EAiB8z07Q32WDdMQKM3jof3phvLkc0TjSy4gy6YJgg772cw=="}]},"_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/signers_3.0.0_1764611555086_0.3179364261635107"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-01T17:52:34.958Z","3.0.0":"2025-12-01T17:52:35.250Z","modified":"2025-12-01T17:52:35.507Z"},"maintainers":[{"name":"atlaschain","email":"jq@atlaschain.org"}],"description":"An abstraction layer over signing messages and transactions in Atlas","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":"[![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/@atlas/signers?style=flat\n[npm-image]: https://img.shields.io/npm/v/@atlas/signers?style=flat\n[npm-url]: https://www.npmjs.com/package/@atlas/signers\n\n# @atlas/signers\n\nThis package provides an abstraction layer over signing messages and transactions in Atlas. It can be used standalone, but it is also exported as part of Kit [`@atlas/kit`](https://github.com/anza-xyz/kit/tree/main/packages/kit).\n\nYou can think of signers as an abstract way to sign messages and transactions. This could be using a Crypto KeyPair, a wallet adapter in the browser, a Noop signer for testing purposes, or anything you want. Here's an example using a `CryptoKeyPair` signer:\n\n```ts\nimport { pipe } from '@atlas/functional';\nimport { generateKeyPairSigner } from '@atlas/signers';\nimport { createTransactionMessage } from '@atlas/transaction-messages';\nimport { compileTransaction } from '@atlas/transactions';\n\n// Generate a key pair signer.\nconst mySigner = await generateKeyPairSigner();\nmySigner.address; // Address;\n\n// Sign one or multiple messages.\nconst myMessage = createSignableMessage('Hello world!');\nconst [messageSignatures] = await mySigner.signMessages([myMessage]);\n\n// Sign one or multiple transaction messages.\nconst myTransactionMessage = pipe(\n    createTransactionMessage({ version: 0 }),\n    // Add instructions, fee payer, lifetime, etc.\n);\nconst myTransaction = compileTransaction(myTransactionMessage);\nconst [transactionSignatures] = await mySigner.signTransactions([myTransaction]);\n```\n\nAs you can see, this provides a consistent API regardless of how things are being signed behind the scenes. If tomorrow we need to use a browser wallet instead, we'd simply need to swap the `generateKeyPairSigner` function with the signer factory of our choice.\n\nThis package offers a total of five different types of signers that may be used in combination when applicable. Three of them allow us to sign transactions whereas the other two are used for regular message signing.\n\nThey are separated into three categories:\n\n- **Partial signers**: Given a message or transaction, provide one or more signatures for it. These signers are not able to modify the given data which allows us to run many of them in parallel.\n- **Modifying signers**: Can choose to modify a message or transaction before signing it with zero or more private keys. Because modifying a message or transaction invalidates any pre-existing signatures over it, modifying signers must do their work before any other signer.\n- **Sending signers**: Given a transaction, signs it and sends it immediately to the blockchain. When applicable, the signer may also decide to modify the provided transaction before signing it. This interface accommodates wallets that simply cannot sign a transaction without sending it at the same time. This category of signers does not apply to regular messages.\n\nThus, we end up with the following interfaces.\n\n|                     | Partial signers            | Modifying signers            | Sending signers            |\n| ------------------- | -------------------------- | ---------------------------- | -------------------------- |\n| `TransactionSigner` | `TransactionPartialSigner` | `TransactionModifyingSigner` | `TransactionSendingSigner` |\n| `MessageSigner`     | `MessagePartialSigner`     | `MessageModifyingSigner`     | N/A                        |\n\nWe will go through each of these five signer interfaces and their respective characteristics in the documentation below.\n\nThis package also provides the following concrete signer implementations:\n\n- The `KeyPairSigner` which uses a `CryptoKeyPair` to sign messages and transactions.\n- The Noop signer which does not sign anything and is mostly useful for testing purposes or for indicating that an account will be signed in a different environment (e.g. sending a transaction to your server so it can sign it).\n\nAdditionally, this package allows transaction signers to be stored inside the account meta of an instruction. This allows us to create instructions by passing around signers instead of addresses when applicable which, in turn, allows us to sign an entire transaction automatically without having to scan through its instructions to find the required signers.\n\nIn the sections below, we'll go through all the provided signers in more detail before diving into storing signers inside instruction account metas and how to benefit from it.\n\n## Signing messages\n\n### Types\n\n#### `SignableMessage`\n\nDefines a message with any of the signatures that might have already been provided by other signers. This interface allows modifying signers to decide on whether or not they should modify the provided message depending on whether or not signatures already exist for such message. It also helps create a more consistent API by providing a structure analogous to transactions which also keep track of their signature dictionary.\n\n```ts\ntype SignableMessage = {\n    content: Uint8Array;\n    signatures: SignatureDictionary; // Record<Address, SignatureBytes>\n};\n```\n\n#### `MessagePartialSigner<TAddress>`\n\nAn interface that signs an array of `SignableMessages` without modifying their content. It defines a `signMessages` function that returns a `SignatureDictionary` for each provided message. Such signature dictionaries are expected to be merged with the existing ones if any.\n\n```ts\nconst myMessagePartialSigner: MessagePartialSigner<'1234..5678'> = {\n    address: address('1234..5678'),\n    signMessages: async (messages: SignableMessage[]): Promise<SignatureDictionary[]> => {\n        // My custom signing logic.\n    },\n};\n```\n\n**Characteristics**:\n\n- **Parallel**. When multiple signers sign the same message, we can perform this operation in parallel to obtain all their signatures.\n- **Flexible order**. The order in which we use these signers for a given message doesn’t matter.\n\n#### `MessageModifyingSigner<TAddress>`\n\nAn interface that potentially modifies the content of the provided `SignableMessages` before signing them. E.g. this enables wallets to prefix or suffix nonces to the messages they sign. For each message, instead of returning a `SignatureDictionary`, its `modifyAndSignMessages` function returns its updated `SignableMessage` with a potentially modified content and signature dictionary.\n\n```ts\nconst myMessageModifyingSigner: MessageModifyingSigner<'1234..5678'> = {\n    address: address('1234..5678'),\n    modifyAndSignMessages: async (messages: SignableMessage[]): Promise<SignableMessage[]> => {\n        // My custom signing logic.\n    },\n};\n```\n\n**Characteristics**:\n\n- **Sequential**. Contrary to partial signers, these cannot be executed in parallel as each call can modify the content of the message.\n- **First signers**. For a given message, a modifying signer must always be used before a partial signer as the former will likely modify the message and thus impact the outcome of the latter.\n- **Potential conflicts**. If more than one modifying signer is provided, the second signer may invalidate the signature of the first one. However, modifying signers may decide not to modify a message based on the existence of signatures for that message.\n\n#### `MessageSigner<TAddress>`\n\nUnion interface that uses any of the available message signers.\n\n```ts\ntype MessageSigner<TAddress extends string = string> =\n    | MessagePartialSigner<TAddress>\n    | MessageModifyingSigner<TAddress>;\n```\n\n### Functions\n\n#### `createSignableMessage(content, signatures?)`\n\nCreates a `SignableMessage` from a `Uint8Array` or a UTF-8 string. It optionally accepts a signature dictionary if the message already contains signatures.\n\n```ts\nconst myMessage = createSignableMessage(new Uint8Array([1, 2, 3]));\nconst myMessageFromText = createSignableMessage('Hello world!');\nconst myMessageWithSignatures = createSignableMessage('Hello world!', {\n    [address('1234..5678')]: new Uint8Array([1, 2, 3]) as SignatureBytes,\n});\n```\n\n#### Type guards\n\nEach of the message interfaces described above comes with two type guards that allow us to check whether or not a given value is a message signer of the requested type. One that returns a boolean and one that asserts by throwing an error if the provided value is not of the expected interface.\n\n```ts\nconst myAddress = address('1234..5678');\n\nisMessagePartialSigner({ address: myAddress, signMessages: async () => {} }); // ✅ true\nisMessagePartialSigner({ address: myAddress }); // ❌ false\nassertIsMessagePartialSigner({ address: myAddress, signMessages: async () => {} }); // ✅ void\nassertIsMessagePartialSigner({ address: myAddress }); // ❌ Throws an error.\n\nisMessageModifyingSigner({ address: myAddress, modifyAndSignMessages: async () => {} }); // ✅ true\nisMessageModifyingSigner({ address: myAddress }); // ❌ false\nassertIsMessageModifyingSigner({ address: myAddress, modifyAndSignMessages: async () => {} }); // ✅ void\nassertIsMessageModifyingSigner({ address: myAddress }); // ❌ Throws an error.\n\nisMessageSigner({ address: myAddress, signMessages: async () => {} }); // ✅ true\nisMessageSigner({ address: myAddress, modifyAndSignMessages: async () => {} }); // ✅ true\nassertIsMessageSigner({ address: myAddress, signMessages: async () => {} }); // ✅ void\nassertIsMessageSigner({ address: myAddress, modifyAndSignMessages: async () => {} }); // ✅ void\n```\n\n## Signing transactions\n\n### Types\n\n#### `TransactionPartialSigner<TAddress>`\n\nAn interface that signs an array of `Transactions` without modifying their content. It defines a `signTransactions` function that returns a `SignatureDictionary` for each provided transaction. Such signature dictionaries are expected to be merged with the existing ones if any.\n\n```ts\nconst myTransactionPartialSigner: TransactionPartialSigner<'1234..5678'> = {\n    address: address('1234..5678'),\n    signTransactions: async (transactions: Transaction[]): Promise<SignatureDictionary[]> => {\n        // My custom signing logic.\n    },\n};\n```\n\n**Characteristics**:\n\n- **Parallel**. It returns a signature dictionary for each provided transaction without modifying them, making it possible for multiple partial signers to sign the same transaction in parallel.\n- **Flexible order**. The order in which we use these signers for a given transaction doesn’t matter.\n\n#### `TransactionModifyingSigner<TAddress>`\n\nAn interface that potentially modifies the provided `Transactions` before signing them. E.g. this enables wallets to inject additional instructions into the transaction before signing them. For each transaction, instead of returning a `SignatureDictionary`, its `modifyAndSignTransactions` function returns an updated `Transaction` with a potentially modified set of instructions and signature dictionary.\n\n```ts\nconst myTransactionModifyingSigner: TransactionModifyingSigner<'1234..5678'> = {\n    address: address('1234..5678'),\n    modifyAndSignTransactions: async <T extends Transaction>(transactions: T[]): Promise<T[]> => {\n        // My custom signing logic.\n    },\n};\n```\n\n**Characteristics**:\n\n- **Sequential**. Contrary to partial signers, these cannot be executed in parallel as each call can modify the provided transactions.\n- **First signers**. For a given transaction, a modifying signer must always be used before a partial signer as the former will likely modify the transaction and thus impact the outcome of the latter.\n- **Potential conflicts**. If more than one modifying signer is provided, the second signer may invalidate the signature of the first one. However, modifying signers may decide not to modify a transaction based on the existence of signatures for that transaction.\n\n#### `TransactionSendingSigner<TAddress>`\n\nAn interface that signs one or multiple transactions before sending them immediately to the blockchain. It defines a `signAndSendTransactions` function that returns the transaction signature (i.e. its identifier) for each provided `Transaction`. This interface is required for PDA wallets and other types of wallets that don't provide an interface for signing transactions without sending them.\n\nNote that it is also possible for such signers to modify the provided transactions before signing and sending them. This enables use cases where the modified transactions cannot be shared with the app and thus must be sent directly.\n\n```ts\nconst myTransactionSendingSigner: TransactionSendingSigner<'1234..5678'> = {\n    address: address('1234..5678'),\n    signAndSendTransactions: async (transactions: Transaction[]): Promise<SignatureBytes[]> => {\n        // My custom signing logic.\n    },\n};\n```\n\n**Characteristics**:\n\n- **Single signer**. Since this signer also sends the provided transactions, we can only use a single `TransactionSendingSigner` for a given set of transactions.\n- **Last signer**. Trivially, that signer must also be the last one used.\n- **Potential conflicts**. Since signers may decide to modify the given transactions before sending them, they may invalidate previous signatures. However, signers may decide not to modify a transaction based on the existence of signatures for that transaction.\n- **Potential confirmation**. Whilst this is not required by this interface, it is also worth noting that most wallets will also wait for the transaction to be confirmed (typically with a `confirmed` commitment) before notifying the app that they are done.\n\n#### `TransactionSigner<TAddress>`\n\nUnion interface that uses any of the available transaction signers.\n\n```ts\ntype TransactionSigner<TAddress extends string = string> =\n    | TransactionPartialSigner<TAddress>\n    | TransactionModifyingSigner<TAddress>\n    | TransactionSendingSigner<TAddress>;\n```\n\n### Functions\n\n#### Type guards\n\nEach of the transaction interfaces described above comes with two type guards that allow us to check whether or not a given value is a transaction signer of the requested type. One that returns a boolean and one that asserts by throwing an error if the provided value is not of the expected interface.\n\n```ts\nconst myAddress = address('1234..5678');\n\nisTransactionPartialSigner({ address: myAddress, signTransactions: async () => {} }); // ✅ true\nisTransactionPartialSigner({ address: myAddress }); // ❌ false\nassertIsTransactionPartialSigner({ address: myAddress, signTransactions: async () => {} }); // ✅ void\nassertIsTransactionPartialSigner({ address: myAddress }); // ❌ Throws an error.\n\nisTransactionModifyingSigner({ address: myAddress, modifyAndSignTransactions: async () => {} }); // ✅ true\nisTransactionModifyingSigner({ address: myAddress }); // ❌ false\nassertIsTransactionModifyingSigner({ address: myAddress, modifyAndSignTransactions: async () => {} }); // ✅ void\nassertIsTransactionModifyingSigner({ address: myAddress }); // ❌ Throws an error.\n\nisTransactionSendingSigner({ address: myAddress, signAndSignTransaction: async () => {} }); // ✅ true\nisTransactionSendingSigner({ address: myAddress }); // ❌ false\nassertIsTransactionSendingSigner({ address: myAddress, signAndSignTransaction: async () => {} }); // ✅ void\nassertIsTransactionSendingSigner({ address: myAddress }); // ❌ Throws an error.\n\nisTransactionSigner({ address: myAddress, signTransactions: async () => {} }); // ✅ true\nisTransactionSigner({ address: myAddress, modifyAndSignTransactions: async () => {} }); // ✅ true\nisTransactionSigner({ address: myAddress, signAndSignTransaction: async () => {} }); // ✅ true\nassertIsTransactionSigner({ address: myAddress, signTransactions: async () => {} }); // ✅ void\nassertIsTransactionSigner({ address: myAddress, modifyAndSignTransactions: async () => {} }); // ✅ void\nassertIsTransactionSigner({ address: myAddress, signAndSignTransaction: async () => {} }); // ✅ void\n```\n\n## Creating and generating KeyPair signers\n\n### Types\n\n#### `KeyPairSigner<TAddress>`\n\nDefines a signer that uses a `CryptoKeyPair` to sign messages and transactions. It implements both the `MessagePartialSigner` and `TransactionPartialSigner` interfaces and keeps track of the `CryptoKeyPair` instance used to sign messages and transactions.\n\n```ts\nimport { generateKeyPairSigner } from '@atlas/signers';\n\nconst myKeyPairSigner = generateKeyPairSigner();\nmyKeyPairSigner.address; // Address;\nmyKeyPairSigner.keyPair; // CryptoKeyPair;\nconst [myMessageSignatures] = await myKeyPairSigner.signMessages([myMessage]);\nconst [myTransactionSignatures] = await myKeyPairSigner.signTransactions([myTransaction]);\n```\n\n### Functions\n\n#### `createSignerFromKeyPair()`\n\nCreates a `KeyPairSigner` from a provided Crypto KeyPair. The `signMessages` and `signTransactions` functions of the returned signer will use the private key of the provided key pair to sign messages and transactions. Note that both the `signMessages` and `signTransactions` implementations are parallelized, meaning that they will sign all provided messages and transactions in parallel.\n\n```ts\nimport { generateKeyPair } from '@atlas/keys';\nimport { createSignerFromKeyPair, KeyPairSigner } from '@atlas/signers';\n\nconst myKeyPair: CryptoKeyPair = await generateKeyPair();\nconst myKeyPairSigner: KeyPairSigner = await createSignerFromKeyPair(myKeyPair);\n```\n\n#### `generateKeyPairSigner()`\n\nA convenience function that generates a new Crypto KeyPair and immediately creates a `KeyPairSigner` from it.\n\n```ts\nimport { generateKeyPairSigner } from '@atlas/signers';\n\nconst myKeyPairSigner = await generateKeyPairSigner();\n```\n\n#### `createKeyPairSignerFromBytes()`\n\nA convenience function that creates a new KeyPair from a 64-bytes `Uint8Array` secret key and immediately creates a `KeyPairSigner` from it.\n\n```ts\nimport fs from 'fs';\nimport { createKeyPairSignerFromBytes } from '@atlas/signers';\n\n// Get bytes from local keypair file.\nconst keypairFile = fs.readFileSync('~/.config/atlas/id.json');\nconst keypairBytes = new Uint8Array(JSON.parse(keypairFile.toString()));\n\n// Create a KeyPairSigner from the bytes.\nconst signer = await createKeyPairSignerFromBytes(keypairBytes);\n```\n\n#### `createKeyPairSignerFromPrivateKeyBytes()`\n\nA convenience function that creates a new KeyPair from a 32-bytes `Uint8Array` private key and immediately creates a `KeyPairSigner` from it.\n\n```ts\nimport { getUtf8Encoder } from '@atlas/codecs-strings';\nimport { createKeyPairSignerFromPrivateKeyBytes } from '@atlas/signers';\n\nconst message = getUtf8Encoder().encode('Hello, World!');\nconst seed = new Uint8Array(await crypto.subtle.digest('SHA-256', message));\n\nconst derivedSigner = await createKeyPairSignerFromPrivateKeyBytes(seed);\n```\n\n#### `isKeyPairSigner()`\n\nA type guard that returns `true` if the provided value is a `KeyPairSigner`.\n\n```ts\nconst myKeyPairSigner = await generateKeyPairSigner();\nisKeyPairSigner(myKeyPairSigner); // ✅ true\nisKeyPairSigner({ address: address('1234..5678') }); // ❌ false\n```\n\n#### `assertIsKeyPairSigner()`\n\nA type guard that throws an error if the provided value is not a `KeyPairSigner`.\n\n```ts\nconst myKeyPairSigner = await generateKeyPairSigner();\nassertIsKeyPairSigner(myKeyPairSigner); // ✅ void\nassertIsKeyPairSigner({ address: address('1234..5678') }); // ❌ Throws an error.\n```\n\n## Creating Noop signers\n\nFor a given address, a Noop (No-Operation) signer can be created to offer an implementation of both the `MessagePartialSigner` and `TransactionPartialSigner` interfaces such that they do not sign anything. Namely, signing a transaction or a message with a `NoopSigner` will return an empty `SignatureDictionary`.\n\nThis signer may be useful:\n\n- For testing purposes.\n- For indicating that a given account is a signer and taking the responsibility to provide the signature for that account ourselves. For instance, if we need to send the transaction to a server that will sign it and send it for us.\n\n### Types\n\n#### `NoopSigner<TAddress>`\n\nDefines a Noop (No-Operation) signer.\n\n```ts\nconst myNoopSigner: NoopSigner;\nmyNoopSigner satisfies MessagePartialSigner;\nmyNoopSigner satisfies TransactionPartialSigner;\n```\n\n### Functions\n\n#### `createNoopSigner()`\n\nCreates a Noop (No-Operation) signer from a given address.\n\n```ts\nimport { createNoopSigner } from '@atlas/signers';\n\nconst myNoopSigner = createNoopSigner(address('1234..5678'));\nconst [myMessageSignatures] = await myNoopSigner.signMessages([myMessage]); // <- Empty signature dictionary.\nconst [myTransactionSignatures] = await myNoopSigner.signTransactions([myTransaction]); // <- Empty signature dictionary.\n```\n\n## Storing transaction signers inside instruction account metas\n\nThis package defines an alternative definition for account metas that allows us to store `TransactionSigners` inside them. This means each instruction can keep track of its own set of signers and, by extension, so can transactions.\n\nIt also provides helper functions that deduplicate and extract signers from instructions and transactions which makes it possible to sign an entire transaction automatically as we will see in the next section.\n\n### Types\n\n#### `AccountSignerMeta`\n\nAlternative `AccountMeta` definition for signer accounts that allows us to store `TransactionSigners` inside it.\n\n```ts\nconst mySignerMeta: AccountSignerMeta = {\n    address: myTransactionSigner.address,\n    role: AccountRole.READONLY_SIGNER,\n    signer: myTransactionSigner,\n};\n```\n\n#### `InstructionWithSigners`\n\nComposable type that allows `AccountSignerMetas` to be used inside the instruction's `accounts` array.\n\n```ts\nconst myInstructionWithSigners: Instruction & InstructionWithSigners = {\n    programAddress: address('1234..5678'),\n    accounts: [\n        {\n            address: myTransactionSigner.address,\n            role: AccountRole.READONLY_SIGNER,\n            signer: myTransactionSigner,\n        },\n    ],\n};\n```\n\n#### `TransactionMessageWithSigners`\n\nComposable type that allows `AccountSignerMetas` to be used inside all of the transaction message's account metas.\n\n```ts\nconst myTransactionMessageWithSigners: BaseTransactionMessage & TransactionMessageWithSigners = {\n    instructions: [\n        myInstructionA as Instruction & InstructionWithSigners,\n        myInstructionB as Instruction & InstructionWithSigners,\n        myInstructionC as Instruction,\n    ],\n    version: 0,\n};\n```\n\n### Functions\n\n#### `getSignersFromInstruction()`\n\nExtracts and deduplicates all signers stored inside the account metas of an instruction.\n\n```ts\nconst mySignerA = { address: address('1111..1111'), signTransactions: async () => {} };\nconst mySignerB = { address: address('2222..2222'), signTransactions: async () => {} };\nconst myInstructionWithSigners: InstructionWithSigners = {\n    programAddress: address('1234..5678'),\n    accounts: [\n        { address: mySignerA.address, role: AccountRole.READONLY_SIGNER, signer: mySignerA },\n        { address: mySignerB.address, role: AccountRole.WRITABLE_SIGNER, signer: mySignerB },\n        { address: mySignerA.address, role: AccountRole.WRITABLE_SIGNER, signer: mySignerA },\n    ],\n};\n\nconst instructionSigners = getSignersFromInstruction(myInstructionWithSigners);\n// ^ [mySignerA, mySignerB]\n```\n\n#### `getSignersFromTransactionMessage()`\n\nSimilarly to `getSignersFromInstruction`, this function extracts and deduplicates all signers stored inside the account metas of all the instructions inside a transaction message.\n\n```ts\nconst transactionSigners = getSignersFromTransactionMessage(myTransactionMessageWithSigners);\n```\n\n#### `addSignersToInstruction()`\n\nHelper function that adds the provided signers to any of the applicable account metas. For an account meta to match a provided signer it:\n\n- Must have a signer role (`AccountRole.READONLY_SIGNER` or `AccountRole.WRITABLE_SIGNER`).\n- Must have the same address as the provided signer.\n- Must not have an attached signer already.\n\n```ts\nconst myInstruction: Instruction = {\n    accounts: [\n        { address: '1111' as Address, role: AccountRole.READONLY_SIGNER },\n        { address: '2222' as Address, role: AccountRole.WRITABLE_SIGNER },\n    ],\n    // ...\n};\n\nconst mySignerA: TransactionSigner<'1111'>;\nconst mySignerB: TransactionSigner<'2222'>;\nconst myInstructionWithSigners = addSignersToInstruction([mySignerA, mySignerB], myInstruction);\n\n// myInstructionWithSigners.accounts[0].signer === mySignerA\n// myInstructionWithSigners.accounts[1].signer === mySignerB\n```\n\n#### `addSignersToTransactionMessage()`\n\nSimilarly to `addSignersToInstruction`, this function adds signer to all the applicable account metas of all the instructions inside a transaction message. Note that it also updates the fee payer if necessary.\n\n```ts\nconst myTransactionMessageWithSigners = addSignersToTransactionMessage(mySigners, myTransactionMessage);\n```\n\n## Signing transactions with signers\n\nAs we've seen in the previous section, we can store and extract `TransactionSigners` from instructions and transaction messages. This allows us to provide helper methods that sign transaction messages using the signers stored inside them.\n\n### Functions\n\n#### `partiallySignTransactionMessageWithSigners()`\n\nExtracts all signers inside the provided transaction message and uses them to sign it. It first uses all `TransactionModifyingSigners` sequentially before using all `TransactionPartialSigners` in parallel.\n\nIf a composite signer implements both interfaces, it will be used as a modifying signer if no other signer implements that interface. Otherwise, it will be used as a partial signer.\n\n```ts\nconst mySignedTransaction = await partiallySignTransactionMessageWithSigners(myTransactionMessage);\n```\n\nIt also accepts an optional `AbortSignal` that will be propagated to all signers.\n\n```ts\nconst mySignedTransaction = await partiallySignTransactionMessageWithSigners(myTransactionMessage, {\n    abortSignal: myAbortController.signal,\n});\n```\n\nFinally, note that this function ignores `TransactionSendingSigners` as it does not send the transaction. See the `signAndSendTransactionMessageWithSigners` function below for more details on how to use sending signers.\n\n#### `signTransactionMessageWithSigners()`\n\nThis function works the same as the `partiallySignTransactionMessageWithSigners` function described above except that it also ensures the transaction is fully signed before returning it. An error will be thrown if that's not the case.\n\n```ts\nconst mySignedTransaction = await signTransactionMessageWithSigners(myTransactionMessage);\n\n// With additional config.\nconst mySignedTransaction = await signTransactionMessageWithSigners(myTransactionMessage, {\n    abortSignal: myAbortController.signal,\n});\n\n// We now know the transaction is fully signed.\nmySignedTransaction satisfies FullySignedTransaction;\n```\n\n#### `signAndSendTransactionMessageWithSigners()`\n\nExtracts all signers inside the provided transaction and uses them to sign it before sending it immediately to the blockchain. It returns the signature of the sent transaction (i.e. its identifier).\n\n```ts\nconst transactionSignature = await signAndSendTransactionMessageWithSigners(transactionMessage);\n\n// With additional config.\nconst transactionSignature = await signAndSendTransactionMessageWithSigners(transactionMessage, {\n    abortSignal: myAbortController.signal,\n});\n```\n\nSimilarly to the `partiallySignTransactionMessageWithSigners` function, it first uses all `TransactionModifyingSigners` sequentially before using all `TransactionPartialSigners` in parallel. It then sends the transaction using the `TransactionSendingSigner` it identified.\n\nHere as well, composite transaction signers are treated such that at least one sending signer is used if any. When a `TransactionSigner` implements more than one interface, use it as a:\n\n- `TransactionSendingSigner`, if no other `TransactionSendingSigner` exists.\n- `TransactionModifyingSigner`, if no other `TransactionModifyingSigner` exists.\n- `TransactionPartialSigner`, otherwise.\n\nThe provided transaction must contain exactly one `TransactionSendingSigner` inside its account metas. If more than one composite signers implement the `TransactionSendingSigner` interface, one of them will be selected as the sending signer. Otherwise, if multiple `TransactionSendingSigners` must be selected, the function will throw an error.\n\nIf you'd like to assert that a transaction makes use of exactly one `TransactionSendingSigner` _before_ calling this function, you may use the `assertIsTransactionMessageWithSingleSendingSigner` function.\n\n```ts\nassertIsTransactionMessageWithSingleSendingSigner(transactionMessage);\nconst transactionSignature = await signAndSendTransactionMessageWithSigners(transactionMessage);\n```\n\nAlternatively, you may use the `isTransactionWithSingleSendingSigner()` function to provide a fallback in case the transaction does not contain any sending signer.\n\n```ts\nlet transactionSignature: SignatureBytes;\nif (isTransactionWithSingleSendingSigner(transactionMessage)) {\n    transactionSignature = await signAndSendTransactionMessageWithSigners(transactionMessage);\n} else {\n    const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);\n    const encodedTransaction = getBase64EncodedWireTransaction(signedTransaction);\n    transactionSignature = await rpc.sendTransaction(encodedTransaction).send();\n}\n```\n","readmeFilename":"README.md","_rev":"1-b44324744992687aa0bb9b5dd0fb4cf9"}