@solana/signers 2.0.0-experimental.4c1874d → 2.0.0-experimental.65e87b8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +38 -17
  2. package/dist/index.browser.cjs +37 -14
  3. package/dist/index.browser.cjs.map +1 -1
  4. package/dist/index.browser.js +37 -15
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.development.js +39 -14
  7. package/dist/index.development.js.map +1 -1
  8. package/dist/index.native.js +37 -15
  9. package/dist/index.native.js.map +1 -1
  10. package/dist/index.node.cjs +37 -14
  11. package/dist/index.node.cjs.map +1 -1
  12. package/dist/index.node.js +37 -15
  13. package/dist/index.node.js.map +1 -1
  14. package/dist/index.production.min.js +14 -13
  15. package/dist/types/account-signer-meta.d.ts.map +1 -0
  16. package/dist/types/deduplicate-signers.d.ts.map +1 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/index.d.ts.map +1 -0
  19. package/dist/types/keypair-signer.d.ts.map +1 -0
  20. package/dist/types/message-modifying-signer.d.ts +3 -1
  21. package/dist/types/message-modifying-signer.d.ts.map +1 -0
  22. package/dist/types/message-partial-signer.d.ts +3 -2
  23. package/dist/types/message-partial-signer.d.ts.map +1 -0
  24. package/dist/types/message-signer.d.ts.map +1 -0
  25. package/dist/types/noop-signer.d.ts +8 -0
  26. package/dist/types/noop-signer.d.ts.map +1 -0
  27. package/dist/types/sign-transaction.d.ts +13 -3
  28. package/dist/types/sign-transaction.d.ts.map +1 -0
  29. package/dist/types/signable-message.d.ts.map +1 -0
  30. package/dist/types/transaction-modifying-signer.d.ts +3 -1
  31. package/dist/types/transaction-modifying-signer.d.ts.map +1 -0
  32. package/dist/types/transaction-partial-signer.d.ts +3 -2
  33. package/dist/types/transaction-partial-signer.d.ts.map +1 -0
  34. package/dist/types/transaction-sending-signer.d.ts +3 -1
  35. package/dist/types/transaction-sending-signer.d.ts.map +1 -0
  36. package/dist/types/transaction-signer.d.ts.map +1 -0
  37. package/dist/types/types.d.ts +3 -0
  38. package/dist/types/types.d.ts.map +1 -0
  39. package/package.json +5 -5
package/README.md CHANGED
@@ -336,25 +336,37 @@ assertIsKeyPairSigner({ address: address('1234..5678') }); // ❌ Throws an erro
336
336
 
337
337
  ## Creating Noop signers
338
338
 
339
- ### Functions
340
-
341
- #### `createNoopSigner()`
342
-
343
- _Coming soon..._
344
-
345
- Creates a Noop (No-Operation) signer from a given address. It will return an implementation of both the `MessagePartialSigner` and `TransactionPartialSigner` interfaces that do not sign anything. Namely, signing a transaction or a message will return an empty `SignatureDictionary`.
339
+ For 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`.
346
340
 
347
341
  This signer may be useful:
348
342
 
349
343
  - For testing purposes.
350
344
  - 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.
351
345
 
346
+ ### Types
347
+
348
+ #### `NoopSigner<TAddress>`
349
+
350
+ Defines a Noop (No-Operation) signer.
351
+
352
+ ```ts
353
+ const myNoopSigner: NoopSigner;
354
+ myNoopSigner satisfies MessagePartialSigner;
355
+ myNoopSigner satisfies TransactionPartialSigner;
356
+ ```
357
+
358
+ ### Functions
359
+
360
+ #### `createNoopSigner()`
361
+
362
+ Creates a Noop (No-Operation) signer from a given address.
363
+
352
364
  ```ts
353
365
  import { createNoopSigner } from '@solana/signers';
354
366
 
355
- const myAddress = address('1234..5678');
356
- const myNoopSigner = createNoopSigner(myAddress);
357
- // ^ MessagePartialSigner<'1234..5678'> & TransactionPartialSigner<'1234..5678'>
367
+ const myNoopSigner = createNoopSigner(address('1234..5678'));
368
+ const [myMessageSignatures] = await myNoopSigner.signMessages([myMessage]); // <- Empty signature dictionary.
369
+ const [myTransactionSignatures] = await myNoopSigner.signTransactions([myTransaction]); // <- Empty signature dictionary.
358
370
  ```
359
371
 
360
372
  ## Storing transaction signers inside instruction account metas
@@ -440,10 +452,13 @@ If a composite signer implements both interfaces, it will be used as a modifying
440
452
  const mySignedTransaction = partiallySignTransactionWithSigners(myTransaction);
441
453
  ```
442
454
 
443
- It also accepts an additional array of signers that will be merged with the ones extracted from the transaction, if any.
455
+ It also accepts an optional `AbortSignal` and an additional array of signers that will be merged with the ones extracted from the transaction, if any.
444
456
 
445
457
  ```ts
446
- const mySignedTransaction = partiallySignTransactionWithSigners(myTransaction, [myOtherSigner]);
458
+ const mySignedTransaction = partiallySignTransactionWithSigners(myTransaction, {
459
+ abortSignal: myAbortController.signal,
460
+ signers: [myOtherSigner],
461
+ });
447
462
  ```
448
463
 
449
464
  Finally, note that this function ignores `TransactionSendingSigners` as it does not send the transaction. See the `signAndSendTransactionWithSigners` function below for more details on how to use sending signers.
@@ -455,8 +470,11 @@ This function works the same as the `partiallySignTransactionWithSigners` functi
455
470
  ```ts
456
471
  const mySignedTransaction = signTransactionWithSigners(myTransaction);
457
472
 
458
- // With additional signers.
459
- const mySignedTransaction = signTransactionWithSigners(myTransaction, [myOtherSigner]);
473
+ // With additional config.
474
+ const mySignedTransaction = signTransactionWithSigners(myTransaction, {
475
+ abortSignal: myAbortController.signal,
476
+ signers: [myOtherSigner],
477
+ });
460
478
 
461
479
  // We now know the transaction is fully signed.
462
480
  mySignedTransaction satisfies IFullySignedTransaction;
@@ -469,8 +487,11 @@ Extracts all signers inside the provided transaction and uses them to sign it be
469
487
  ```ts
470
488
  const myTransactionSignature = signAndSendTransactionWithSigners(myTransaction);
471
489
 
472
- // With additional signers.
473
- const myTransactionSignature = signAndSendTransactionWithSigners(myTransaction, [myOtherSigner]);
490
+ // With additional config.
491
+ const myTransactionSignature = signAndSendTransactionWithSigners(myTransaction, {
492
+ abortSignal: myAbortController.signal,
493
+ signers: [myOtherSigner],
494
+ });
474
495
  ```
475
496
 
476
497
  Similarly to the `partiallySignTransactionWithSigners` function, it first uses all `TransactionModifyingSigners` sequentially before using all `TransactionPartialSigners` in parallel. It then sends the transaction using the first `TransactionSendingSigner` it finds. Any other sending signer that does not implement another transaction signer interface will be ignored.
@@ -484,7 +505,7 @@ const fallbackSender = async (transaction: CompilableTransaction) => {
484
505
  return getBase58Encoder().encode(signature);
485
506
  };
486
507
 
487
- const myTransactionSignature = signAndSendTransactionWithSigners(myTransaction, [], fallbackSender);
508
+ const myTransactionSignature = signAndSendTransactionWithSigners(myTransaction, { fallbackSender });
488
509
  ```
489
510
 
490
511
  Here 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:
@@ -10,6 +10,10 @@ function deduplicateSigners(signers) {
10
10
  signers.forEach((signer) => {
11
11
  if (!deduplicated[signer.address]) {
12
12
  deduplicated[signer.address] = signer;
13
+ } else if (deduplicated[signer.address] !== signer) {
14
+ throw new Error(
15
+ `Multiple distinct signers were identified for address "${signer.address}". Please ensure that you are using the same signer instance for each address.`
16
+ );
13
17
  }
14
18
  });
15
19
  return Object.values(deduplicated);
@@ -95,6 +99,16 @@ function assertIsMessageSigner(value) {
95
99
  }
96
100
  }
97
101
 
102
+ // src/noop-signer.ts
103
+ function createNoopSigner(address) {
104
+ const out = {
105
+ address,
106
+ signMessages: async (messages) => messages.map(() => Object.freeze({})),
107
+ signTransactions: async (transactions) => transactions.map(() => Object.freeze({}))
108
+ };
109
+ return Object.freeze(out);
110
+ }
111
+
98
112
  // src/transaction-modifying-signer.ts
99
113
  function isTransactionModifyingSigner(value) {
100
114
  return "modifyAndSignTransactions" in value && typeof value.modifyAndSignTransactions === "function";
@@ -126,39 +140,45 @@ function assertIsTransactionSigner(value) {
126
140
  }
127
141
 
128
142
  // src/sign-transaction.ts
129
- async function partiallySignTransactionWithSigners(transaction, signers = []) {
143
+ async function partiallySignTransactionWithSigners(transaction, config = {}) {
144
+ const signers = config.signers ?? [];
130
145
  const { partialSigners, modifyingSigners } = categorizeTransactionSigners(
131
146
  deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers]),
132
147
  { identifySendingSigner: false }
133
148
  );
134
- return signModifyingAndPartialTransactionSigners(transaction, modifyingSigners, partialSigners);
149
+ return signModifyingAndPartialTransactionSigners(transaction, modifyingSigners, partialSigners, config.abortSignal);
135
150
  }
136
- async function signTransactionWithSigners(transaction, signers = []) {
137
- const signedTransaction = await partiallySignTransactionWithSigners(transaction, signers);
151
+ async function signTransactionWithSigners(transaction, config = {}) {
152
+ const signedTransaction = await partiallySignTransactionWithSigners(transaction, config);
138
153
  transactions.assertTransactionIsFullySigned(signedTransaction);
139
154
  return signedTransaction;
140
155
  }
141
- async function signAndSendTransactionWithSigners(transaction, signers = [], fallbackSender) {
156
+ async function signAndSendTransactionWithSigners(transaction, config = {}) {
157
+ const signers = config.signers ?? [];
158
+ const abortSignal = config.abortSignal;
142
159
  const { partialSigners, modifyingSigners, sendingSigner } = categorizeTransactionSigners(
143
160
  deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers])
144
161
  );
162
+ abortSignal?.throwIfAborted();
145
163
  const signedTransaction = await signModifyingAndPartialTransactionSigners(
146
164
  transaction,
147
165
  modifyingSigners,
148
- partialSigners
166
+ partialSigners,
167
+ abortSignal
149
168
  );
150
169
  if (sendingSigner) {
151
- const [signature] = await sendingSigner.signAndSendTransactions([signedTransaction]);
170
+ abortSignal?.throwIfAborted();
171
+ const [signature] = await sendingSigner.signAndSendTransactions([signedTransaction], { abortSignal });
152
172
  return signature;
153
173
  }
154
- if (fallbackSender) {
174
+ if (config.fallbackSender) {
155
175
  transactions.assertTransactionIsFullySigned(signedTransaction);
156
- return fallbackSender(signedTransaction);
176
+ return config.fallbackSender(signedTransaction);
157
177
  }
158
178
  throw new Error("No TransactionSendingSigner was identified and no fallback sender was provided.");
159
179
  }
160
- function categorizeTransactionSigners(signers, options) {
161
- const identifySendingSigner = options?.identifySendingSigner ?? true;
180
+ function categorizeTransactionSigners(signers, config = {}) {
181
+ const identifySendingSigner = config.identifySendingSigner ?? true;
162
182
  const sendingSigner = identifySendingSigner ? identifyTransactionSendingSigner(signers) : null;
163
183
  const otherSigners = signers.filter(
164
184
  (signer) => signer !== sendingSigner && (isTransactionModifyingSigner(signer) || isTransactionPartialSigner(signer))
@@ -188,14 +208,16 @@ function identifyTransactionModifyingSigners(signers) {
188
208
  return nonPartialSigners;
189
209
  return [modifyingSigners[0]];
190
210
  }
191
- async function signModifyingAndPartialTransactionSigners(transaction, modifyingSigners = [], partialSigners = []) {
211
+ async function signModifyingAndPartialTransactionSigners(transaction, modifyingSigners = [], partialSigners = [], abortSignal) {
192
212
  const modifiedTransaction = await modifyingSigners.reduce(async (transaction2, modifyingSigner) => {
193
- const [tx] = await modifyingSigner.modifyAndSignTransactions([await transaction2]);
213
+ abortSignal?.throwIfAborted();
214
+ const [tx] = await modifyingSigner.modifyAndSignTransactions([await transaction2], { abortSignal });
194
215
  return Object.freeze(tx);
195
216
  }, Promise.resolve(transaction));
217
+ abortSignal?.throwIfAborted();
196
218
  const signatureDictionaries = await Promise.all(
197
219
  partialSigners.map(async (partialSigner) => {
198
- const [signatures] = await partialSigner.signTransactions([modifiedTransaction]);
220
+ const [signatures] = await partialSigner.signTransactions([modifiedTransaction], { abortSignal });
199
221
  return signatures;
200
222
  })
201
223
  );
@@ -227,6 +249,7 @@ exports.assertIsTransactionModifyingSigner = assertIsTransactionModifyingSigner;
227
249
  exports.assertIsTransactionPartialSigner = assertIsTransactionPartialSigner;
228
250
  exports.assertIsTransactionSendingSigner = assertIsTransactionSendingSigner;
229
251
  exports.assertIsTransactionSigner = assertIsTransactionSigner;
252
+ exports.createNoopSigner = createNoopSigner;
230
253
  exports.createSignableMessage = createSignableMessage;
231
254
  exports.createSignerFromKeyPair = createSignerFromKeyPair;
232
255
  exports.generateKeyPairSigner = generateKeyPairSigner;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/deduplicate-signers.ts","../src/account-signer-meta.ts","../src/keypair-signer.ts","../src/message-partial-signer.ts","../src/transaction-partial-signer.ts","../src/message-modifying-signer.ts","../src/message-signer.ts","../src/sign-transaction.ts","../src/transaction-modifying-signer.ts","../src/transaction-sending-signer.ts","../src/transaction-signer.ts","../../text-encoding-impl/src/index.browser.ts","../src/signable-message.ts"],"names":["transaction","TextDecoder","TextEncoder"],"mappings":"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","sourcesContent":["import { Address } from '@solana/addresses';\n\nimport { MessageSigner } from './message-signer';\nimport { TransactionSigner } from './transaction-signer';\n\n/** Removes all duplicated signers from a provided array by comparing their addresses. */\nexport function deduplicateSigners<TSigner extends MessageSigner | TransactionSigner>(\n signers: readonly TSigner[]\n): readonly TSigner[] {\n const deduplicated: Record<Address, TSigner> = {};\n signers.forEach(signer => {\n if (!deduplicated[signer.address]) {\n deduplicated[signer.address] = signer;\n }\n });\n return Object.values(deduplicated);\n}\n","import { AccountRole, IAccountLookupMeta, IAccountMeta, IInstruction } from '@solana/instructions';\nimport { BaseTransaction, TransactionVersion } from '@solana/transactions';\n\nimport { deduplicateSigners } from './deduplicate-signers';\nimport { TransactionSigner } from './transaction-signer';\n\n/** An extension of the IAccountMeta type that keeps track of its transaction signer. */\nexport interface IAccountSignerMeta<\n TAddress extends string = string,\n TSigner extends TransactionSigner = TransactionSigner\n> extends IAccountMeta<TAddress> {\n readonly role: AccountRole.READONLY_SIGNER | AccountRole.WRITABLE_SIGNER;\n readonly signer: TSigner;\n}\n\n/** A variation of the IInstruction type that allows IAccountSignerMeta in its accounts array. */\ntype IAccountMetaWithWithSigner<TSigner extends TransactionSigner = TransactionSigner> =\n | IAccountMeta\n | IAccountLookupMeta\n | IAccountSignerMeta<string, TSigner>;\nexport type IInstructionWithSigners<\n TProgramAddress extends string = string,\n TSigner extends TransactionSigner = TransactionSigner,\n TAccounts extends readonly IAccountMetaWithWithSigner<TSigner>[] = readonly IAccountMetaWithWithSigner<TSigner>[]\n> = IInstruction<TProgramAddress, TAccounts>;\n\n/** Extract all signers from an instruction that may contain IAccountSignerMeta accounts. */\nexport function getSignersFromInstruction<TSigner extends TransactionSigner = TransactionSigner>(\n instruction: IInstructionWithSigners<string, TSigner>\n): readonly TSigner[] {\n return deduplicateSigners(\n (instruction.accounts ?? []).flatMap(account => ('signer' in account ? account.signer : []))\n );\n}\n\n/** Extract all signers from a transaction that may contain IAccountSignerMeta accounts. */\nexport function getSignersFromTransaction<\n TSigner extends TransactionSigner = TransactionSigner,\n TInstruction extends IInstructionWithSigners<string, TSigner> = IInstructionWithSigners<string, TSigner>\n>(transaction: BaseTransaction<TransactionVersion, TInstruction>): readonly TSigner[] {\n return deduplicateSigners(transaction.instructions.flatMap(getSignersFromInstruction));\n}\n","import { Address, getAddressFromPublicKey } from '@solana/addresses';\nimport { generateKeyPair, signBytes } from '@solana/keys';\nimport { partiallySignTransaction } from '@solana/transactions';\n\nimport { isMessagePartialSigner, MessagePartialSigner } from './message-partial-signer';\nimport { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';\n\n/** Defines a signer capable of signing messages and transactions using a CryptoKeyPair. */\nexport type KeyPairSigner<TAddress extends string = string> = MessagePartialSigner<TAddress> &\n TransactionPartialSigner<TAddress> & { keyPair: CryptoKeyPair };\n\n/** Checks whether the provided value implements the {@link KeyPairSigner} interface. */\nexport function isKeyPairSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is KeyPairSigner<TAddress> {\n return (\n 'keyPair' in value &&\n typeof value.keyPair === 'object' &&\n isMessagePartialSigner(value) &&\n isTransactionPartialSigner(value)\n );\n}\n\n/** Asserts that the provided value implements the {@link KeyPairSigner} interface. */\nexport function assertIsKeyPairSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is KeyPairSigner<TAddress> {\n if (!isKeyPairSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the KeyPairSigner interface');\n }\n}\n\n/** Creates a KeyPairSigner from the provided Crypto KeyPair. */\nexport async function createSignerFromKeyPair(keyPair: CryptoKeyPair): Promise<KeyPairSigner> {\n const address = await getAddressFromPublicKey(keyPair.publicKey);\n const out: KeyPairSigner = {\n address,\n keyPair,\n signMessages: messages =>\n Promise.all(\n messages.map(async message =>\n Object.freeze({ [address]: await signBytes(keyPair.privateKey, message.content) })\n )\n ),\n signTransactions: transactions =>\n Promise.all(\n transactions.map(async transaction => {\n const signedTransaction = await partiallySignTransaction([keyPair], transaction);\n return Object.freeze({ [address]: signedTransaction.signatures[address] });\n })\n ),\n };\n\n return Object.freeze(out);\n}\n\n/** Securely generates a signer capable of signing messages and transactions using a Crypto KeyPair. */\nexport async function generateKeyPairSigner(): Promise<KeyPairSigner> {\n return createSignerFromKeyPair(await generateKeyPair());\n}\n","import { Address } from '@solana/addresses';\n\nimport { SignableMessage } from './signable-message';\nimport { SignatureDictionary } from './types';\n\n/** Defines a signer capable of signing messages. */\nexport type MessagePartialSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n signMessages(messages: readonly SignableMessage[]): Promise<readonly SignatureDictionary[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link MessagePartialSigner} interface. */\nexport function isMessagePartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is MessagePartialSigner<TAddress> {\n return 'signMessages' in value && typeof value.signMessages === 'function';\n}\n\n/** Asserts that the provided value implements the {@link MessagePartialSigner} interface. */\nexport function assertIsMessagePartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is MessagePartialSigner<TAddress> {\n if (!isMessagePartialSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the MessagePartialSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\nimport { CompilableTransaction } from '@solana/transactions';\n\nimport { SignatureDictionary } from './types';\n\n/** Defines a signer capable of signing transactions. */\nexport type TransactionPartialSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n signTransactions(transactions: readonly CompilableTransaction[]): Promise<readonly SignatureDictionary[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link TransactionPartialSigner} interface. */\nexport function isTransactionPartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionPartialSigner<TAddress> {\n return 'signTransactions' in value && typeof value.signTransactions === 'function';\n}\n\n/** Asserts that the provided value implements the {@link TransactionPartialSigner} interface. */\nexport function assertIsTransactionPartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionPartialSigner<TAddress> {\n if (!isTransactionPartialSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the TransactionPartialSigner interface');\n }\n}\n","import { Address, isAddress } from '@solana/addresses';\n\nimport { SignableMessage } from './signable-message';\n\n/** Defines a signer capable of signing messages. */\nexport type MessageModifyingSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n modifyAndSignMessages(messages: readonly SignableMessage[]): Promise<readonly SignableMessage[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link MessageModifyingSigner} interface. */\nexport function isMessageModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is MessageModifyingSigner<TAddress> {\n return (\n isAddress(value.address) &&\n 'modifyAndSignMessages' in value &&\n typeof value.modifyAndSignMessages === 'function'\n );\n}\n\n/** Asserts that the provided value implements the {@link MessageModifyingSigner} interface. */\nexport function assertIsMessageModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is MessageModifyingSigner<TAddress> {\n if (!isMessageModifyingSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the MessageModifyingSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\n\nimport { isMessageModifyingSigner, MessageModifyingSigner } from './message-modifying-signer';\nimport { isMessagePartialSigner, MessagePartialSigner } from './message-partial-signer';\n\n/** Defines a signer capable of signing messages. */\nexport type MessageSigner<TAddress extends string = string> =\n | MessagePartialSigner<TAddress>\n | MessageModifyingSigner<TAddress>;\n\n/** Checks whether the provided value implements the {@link MessageSigner} interface. */\nexport function isMessageSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is MessageSigner<TAddress> {\n return isMessagePartialSigner(value) || isMessageModifyingSigner(value);\n}\n\n/** Asserts that the provided value implements the {@link MessageSigner} interface. */\nexport function assertIsMessageSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is MessageSigner<TAddress> {\n if (!isMessageSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement any of the MessageSigner interfaces');\n }\n}\n","import { SignatureBytes } from '@solana/keys';\nimport {\n assertTransactionIsFullySigned,\n CompilableTransaction,\n IFullySignedTransaction,\n ITransactionWithSignatures,\n TransactionVersion,\n} from '@solana/transactions';\n\nimport { getSignersFromTransaction, IInstructionWithSigners } from './account-signer-meta';\nimport { deduplicateSigners } from './deduplicate-signers';\nimport { isTransactionModifyingSigner, TransactionModifyingSigner } from './transaction-modifying-signer';\nimport { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';\nimport { isTransactionSendingSigner, TransactionSendingSigner } from './transaction-sending-signer';\nimport { isTransactionSigner, TransactionSigner } from './transaction-signer';\n\ntype CompilableTransactionWithSigners = CompilableTransaction<\n TransactionVersion,\n IInstructionWithSigners<string, TransactionSigner>\n> &\n Partial<ITransactionWithSignatures>;\n\n/**\n * Signs a transaction using any signers that may be stored in IAccountSignerMeta instruction accounts\n * as well as any signers provided explicitly to this function.\n * It will ignore TransactionSendingSigners since this function does not send the transaction.\n */\nexport async function partiallySignTransactionWithSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n signers: readonly TransactionSigner[] = []\n): Promise<TTransaction & ITransactionWithSignatures> {\n const { partialSigners, modifyingSigners } = categorizeTransactionSigners(\n deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers]),\n { identifySendingSigner: false }\n );\n\n return signModifyingAndPartialTransactionSigners(transaction, modifyingSigners, partialSigners);\n}\n\n/**\n * Signs a transaction using any signers that may be stored in IAccountSignerMeta instruction accounts\n * as well as any signers provided explicitly to this function.\n * It will assert that the transaction is fully signed before returning.\n * It will ignore TransactionSendingSigners since this function does not send the transaction.\n */\nexport async function signTransactionWithSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n signers: readonly TransactionSigner[] = []\n): Promise<TTransaction & IFullySignedTransaction> {\n const signedTransaction = await partiallySignTransactionWithSigners(transaction, signers);\n assertTransactionIsFullySigned(signedTransaction);\n return signedTransaction;\n}\n\n/**\n * Signs and sends a transaction using any signers that may be stored in IAccountSignerMeta\n * instruction accounts as well as any signers provided explicitly to this function.\n * It will identify a single TransactionSendingSigners to use for sending the transaction, if any.\n * Otherwise, it will send the transaction using the provided fallbackSender.\n */\nexport async function signAndSendTransactionWithSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n signers: readonly TransactionSigner[] = [],\n fallbackSender?: (transaction: TTransaction & IFullySignedTransaction) => Promise<SignatureBytes>\n): Promise<SignatureBytes> {\n const { partialSigners, modifyingSigners, sendingSigner } = categorizeTransactionSigners(\n deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers])\n );\n\n const signedTransaction = await signModifyingAndPartialTransactionSigners(\n transaction,\n modifyingSigners,\n partialSigners\n );\n\n if (sendingSigner) {\n const [signature] = await sendingSigner.signAndSendTransactions([signedTransaction]);\n return signature;\n }\n\n if (fallbackSender) {\n assertTransactionIsFullySigned(signedTransaction);\n return fallbackSender(signedTransaction);\n }\n\n // TODO: Coded error.\n throw new Error('No TransactionSendingSigner was identified and no fallback sender was provided.');\n}\n\n/**\n * Identifies each provided TransactionSigner and categorizes them into their respective types.\n * When a signer implements multiple interface, it will try to used to most powerful interface\n * but fallback to the least powerful interface when necessary.\n * For instance, if a signer implements TransactionSendingSigner and TransactionModifyingSigner,\n * it will be categorized as a TransactionSendingSigner if and only if no other signers implement\n * the TransactionSendingSigner interface.\n */\nfunction categorizeTransactionSigners(\n signers: readonly TransactionSigner[],\n options?: { identifySendingSigner: boolean }\n): Readonly<{\n modifyingSigners: readonly TransactionModifyingSigner[];\n partialSigners: readonly TransactionPartialSigner[];\n sendingSigner: TransactionSendingSigner | null;\n}> {\n // Identify the unique sending signer that should be used.\n const identifySendingSigner = options?.identifySendingSigner ?? true;\n const sendingSigner = identifySendingSigner ? identifyTransactionSendingSigner(signers) : null;\n\n // Now, focus on the other signers.\n // I.e. the modifying or partial signers that are not the identified sending signer.\n // Note that any other sending only signers will be discarded.\n const otherSigners = signers.filter(\n (signer): signer is TransactionModifyingSigner | TransactionPartialSigner =>\n signer !== sendingSigner && (isTransactionModifyingSigner(signer) || isTransactionPartialSigner(signer))\n );\n\n // Identify the modifying signers from the other signers.\n const modifyingSigners = identifyTransactionModifyingSigners(otherSigners);\n\n // Use any remaining signers as partial signers.\n const partialSigners = otherSigners\n .filter(isTransactionPartialSigner)\n .filter(signer => !(modifyingSigners as typeof otherSigners).includes(signer));\n\n return Object.freeze({ modifyingSigners, partialSigners, sendingSigner });\n}\n\n/** Identifies the best signer to use as a TransactionSendingSigner, if any */\nfunction identifyTransactionSendingSigner(signers: readonly TransactionSigner[]): TransactionSendingSigner | null {\n // Ensure there are any TransactionSendingSigners in the first place.\n const sendingSigners = signers.filter(isTransactionSendingSigner);\n if (sendingSigners.length === 0) return null;\n\n // Prefer sending signers that do not offer other interfaces.\n const sendingOnlySigners = sendingSigners.filter(\n signer => !isTransactionModifyingSigner(signer) && !isTransactionPartialSigner(signer)\n );\n if (sendingOnlySigners.length > 0) {\n return sendingOnlySigners[0];\n }\n\n // Otherwise, choose any sending signer.\n return sendingSigners[0];\n}\n\n/** Identifies the best signers to use as TransactionModifyingSigners, if any */\nfunction identifyTransactionModifyingSigners(\n signers: readonly (TransactionModifyingSigner | TransactionPartialSigner)[]\n): readonly TransactionModifyingSigner[] {\n // Ensure there are any TransactionModifyingSigner in the first place.\n const modifyingSigners = signers.filter(isTransactionModifyingSigner);\n if (modifyingSigners.length === 0) return [];\n\n // Prefer modifying signers that do not offer partial signing.\n const nonPartialSigners = modifyingSigners.filter(signer => !isTransactionPartialSigner(signer));\n if (nonPartialSigners.length > 0) return nonPartialSigners;\n\n // Otherwise, choose only one modifying signer (whichever).\n return [modifyingSigners[0]];\n}\n\n/**\n * Signs a transaction using the provided TransactionModifyingSigners\n * sequentially followed by the TransactionPartialSigners in parallel.\n */\nasync function signModifyingAndPartialTransactionSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n modifyingSigners: readonly TransactionModifyingSigner[] = [],\n partialSigners: readonly TransactionPartialSigner[] = []\n): Promise<TTransaction & ITransactionWithSignatures> {\n // Handle modifying signers sequentially.\n const modifiedTransaction = await modifyingSigners.reduce(async (transaction, modifyingSigner) => {\n const [tx] = await modifyingSigner.modifyAndSignTransactions([await transaction]);\n return Object.freeze(tx);\n }, Promise.resolve(transaction) as Promise<TTransaction>);\n\n // Handle partial signers in parallel.\n const signatureDictionaries = await Promise.all(\n partialSigners.map(async partialSigner => {\n const [signatures] = await partialSigner.signTransactions([modifiedTransaction]);\n return signatures;\n })\n );\n const signedTransaction: TTransaction & ITransactionWithSignatures = {\n ...modifiedTransaction,\n signatures: Object.freeze(\n signatureDictionaries.reduce((signatures, signatureDictionary) => {\n return { ...signatures, ...signatureDictionary };\n }, modifiedTransaction.signatures ?? {})\n ),\n };\n\n return Object.freeze(signedTransaction);\n}\n","import { Address } from '@solana/addresses';\nimport { CompilableTransaction } from '@solana/transactions';\n\n/** Defines a signer capable of signing transactions. */\nexport type TransactionModifyingSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n modifyAndSignTransactions<TTransaction extends CompilableTransaction>(\n transactions: readonly TTransaction[]\n ): Promise<readonly TTransaction[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link TransactionModifyingSigner} interface. */\nexport function isTransactionModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionModifyingSigner<TAddress> {\n return 'modifyAndSignTransactions' in value && typeof value.modifyAndSignTransactions === 'function';\n}\n\n/** Asserts that the provided value implements the {@link TransactionModifyingSigner} interface. */\nexport function assertIsTransactionModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionModifyingSigner<TAddress> {\n if (!isTransactionModifyingSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the TransactionModifyingSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\nimport { SignatureBytes } from '@solana/keys';\nimport { CompilableTransaction } from '@solana/transactions';\n\n/** Defines a signer capable of signing and sending transactions simultaneously. */\nexport type TransactionSendingSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n signAndSendTransactions(transactions: readonly CompilableTransaction[]): Promise<readonly SignatureBytes[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link TransactionSendingSigner} interface. */\nexport function isTransactionSendingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionSendingSigner<TAddress> {\n return 'signAndSendTransactions' in value && typeof value.signAndSendTransactions === 'function';\n}\n\n/** Asserts that the provided value implements the {@link TransactionSendingSigner} interface. */\nexport function assertIsTransactionSendingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionSendingSigner<TAddress> {\n if (!isTransactionSendingSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the TransactionSendingSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\n\nimport { isTransactionModifyingSigner, TransactionModifyingSigner } from './transaction-modifying-signer';\nimport { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';\nimport { isTransactionSendingSigner, TransactionSendingSigner } from './transaction-sending-signer';\n\n/** Defines a signer capable of signing transactions. */\nexport type TransactionSigner<TAddress extends string = string> =\n | TransactionPartialSigner<TAddress>\n | TransactionModifyingSigner<TAddress>\n | TransactionSendingSigner<TAddress>;\n\n/** Checks whether the provided value implements the {@link TransactionSigner} interface. */\nexport function isTransactionSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionSigner<TAddress> {\n return (\n isTransactionPartialSigner(value) || isTransactionModifyingSigner(value) || isTransactionSendingSigner(value)\n );\n}\n\n/** Asserts that the provided value implements the {@link TransactionSigner} interface. */\nexport function assertIsTransactionSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionSigner<TAddress> {\n if (!isTransactionSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement any of the TransactionSigner interfaces');\n }\n}\n","export const TextDecoder = globalThis.TextDecoder;\nexport const TextEncoder = globalThis.TextEncoder;\n","import { TextEncoder } from 'text-encoding-impl';\n\nimport { SignatureDictionary } from './types';\n\n/** Defines a message that needs signing and its current set of signatures if any. */\nexport type SignableMessage = Readonly<{\n content: Uint8Array;\n signatures: SignatureDictionary;\n}>;\n\n/**\n * Creates a signable message from a provided content.\n * If a string is provided, it will be UTF-8 encoded.\n */\nexport function createSignableMessage(\n content: string | Uint8Array,\n signatures: SignatureDictionary = {}\n): SignableMessage {\n return Object.freeze({\n content: typeof content === 'string' ? new TextEncoder().encode(content) : content,\n signatures: Object.freeze({ ...signatures }),\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/deduplicate-signers.ts","../src/account-signer-meta.ts","../src/keypair-signer.ts","../src/message-partial-signer.ts","../src/transaction-partial-signer.ts","../src/message-modifying-signer.ts","../src/message-signer.ts","../src/noop-signer.ts","../src/sign-transaction.ts","../src/transaction-modifying-signer.ts","../src/transaction-sending-signer.ts","../src/transaction-signer.ts","../../text-encoding-impl/src/index.browser.ts","../src/signable-message.ts"],"names":["transaction","TextDecoder","TextEncoder"],"mappings":"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","sourcesContent":["import { Address } from '@solana/addresses';\n\nimport { MessageSigner } from './message-signer';\nimport { TransactionSigner } from './transaction-signer';\n\n/** Removes all duplicated signers from a provided array by comparing their addresses. */\nexport function deduplicateSigners<TSigner extends MessageSigner | TransactionSigner>(\n signers: readonly TSigner[]\n): readonly TSigner[] {\n const deduplicated: Record<Address, TSigner> = {};\n signers.forEach(signer => {\n if (!deduplicated[signer.address]) {\n deduplicated[signer.address] = signer;\n } else if (deduplicated[signer.address] !== signer) {\n // TODO: Coded error.\n throw new Error(\n `Multiple distinct signers were identified for address \"${signer.address}\". ` +\n `Please ensure that you are using the same signer instance for each address.`\n );\n }\n });\n return Object.values(deduplicated);\n}\n","import { AccountRole, IAccountLookupMeta, IAccountMeta, IInstruction } from '@solana/instructions';\nimport { BaseTransaction, TransactionVersion } from '@solana/transactions';\n\nimport { deduplicateSigners } from './deduplicate-signers';\nimport { TransactionSigner } from './transaction-signer';\n\n/** An extension of the IAccountMeta type that keeps track of its transaction signer. */\nexport interface IAccountSignerMeta<\n TAddress extends string = string,\n TSigner extends TransactionSigner = TransactionSigner\n> extends IAccountMeta<TAddress> {\n readonly role: AccountRole.READONLY_SIGNER | AccountRole.WRITABLE_SIGNER;\n readonly signer: TSigner;\n}\n\n/** A variation of the IInstruction type that allows IAccountSignerMeta in its accounts array. */\ntype IAccountMetaWithWithSigner<TSigner extends TransactionSigner = TransactionSigner> =\n | IAccountMeta\n | IAccountLookupMeta\n | IAccountSignerMeta<string, TSigner>;\nexport type IInstructionWithSigners<\n TProgramAddress extends string = string,\n TSigner extends TransactionSigner = TransactionSigner,\n TAccounts extends readonly IAccountMetaWithWithSigner<TSigner>[] = readonly IAccountMetaWithWithSigner<TSigner>[]\n> = IInstruction<TProgramAddress, TAccounts>;\n\n/** Extract all signers from an instruction that may contain IAccountSignerMeta accounts. */\nexport function getSignersFromInstruction<TSigner extends TransactionSigner = TransactionSigner>(\n instruction: IInstructionWithSigners<string, TSigner>\n): readonly TSigner[] {\n return deduplicateSigners(\n (instruction.accounts ?? []).flatMap(account => ('signer' in account ? account.signer : []))\n );\n}\n\n/** Extract all signers from a transaction that may contain IAccountSignerMeta accounts. */\nexport function getSignersFromTransaction<\n TSigner extends TransactionSigner = TransactionSigner,\n TInstruction extends IInstructionWithSigners<string, TSigner> = IInstructionWithSigners<string, TSigner>\n>(transaction: BaseTransaction<TransactionVersion, TInstruction>): readonly TSigner[] {\n return deduplicateSigners(transaction.instructions.flatMap(getSignersFromInstruction));\n}\n","import { Address, getAddressFromPublicKey } from '@solana/addresses';\nimport { generateKeyPair, signBytes } from '@solana/keys';\nimport { partiallySignTransaction } from '@solana/transactions';\n\nimport { isMessagePartialSigner, MessagePartialSigner } from './message-partial-signer';\nimport { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';\n\n/** Defines a signer capable of signing messages and transactions using a CryptoKeyPair. */\nexport type KeyPairSigner<TAddress extends string = string> = MessagePartialSigner<TAddress> &\n TransactionPartialSigner<TAddress> & { keyPair: CryptoKeyPair };\n\n/** Checks whether the provided value implements the {@link KeyPairSigner} interface. */\nexport function isKeyPairSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is KeyPairSigner<TAddress> {\n return (\n 'keyPair' in value &&\n typeof value.keyPair === 'object' &&\n isMessagePartialSigner(value) &&\n isTransactionPartialSigner(value)\n );\n}\n\n/** Asserts that the provided value implements the {@link KeyPairSigner} interface. */\nexport function assertIsKeyPairSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is KeyPairSigner<TAddress> {\n if (!isKeyPairSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the KeyPairSigner interface');\n }\n}\n\n/** Creates a KeyPairSigner from the provided Crypto KeyPair. */\nexport async function createSignerFromKeyPair(keyPair: CryptoKeyPair): Promise<KeyPairSigner> {\n const address = await getAddressFromPublicKey(keyPair.publicKey);\n const out: KeyPairSigner = {\n address,\n keyPair,\n signMessages: messages =>\n Promise.all(\n messages.map(async message =>\n Object.freeze({ [address]: await signBytes(keyPair.privateKey, message.content) })\n )\n ),\n signTransactions: transactions =>\n Promise.all(\n transactions.map(async transaction => {\n const signedTransaction = await partiallySignTransaction([keyPair], transaction);\n return Object.freeze({ [address]: signedTransaction.signatures[address] });\n })\n ),\n };\n\n return Object.freeze(out);\n}\n\n/** Securely generates a signer capable of signing messages and transactions using a Crypto KeyPair. */\nexport async function generateKeyPairSigner(): Promise<KeyPairSigner> {\n return createSignerFromKeyPair(await generateKeyPair());\n}\n","import { Address } from '@solana/addresses';\n\nimport { SignableMessage } from './signable-message';\nimport { BaseSignerConfig, SignatureDictionary } from './types';\n\nexport type MessagePartialSignerConfig = BaseSignerConfig;\n\n/** Defines a signer capable of signing messages. */\nexport type MessagePartialSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n signMessages(\n messages: readonly SignableMessage[],\n config?: MessagePartialSignerConfig\n ): Promise<readonly SignatureDictionary[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link MessagePartialSigner} interface. */\nexport function isMessagePartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is MessagePartialSigner<TAddress> {\n return 'signMessages' in value && typeof value.signMessages === 'function';\n}\n\n/** Asserts that the provided value implements the {@link MessagePartialSigner} interface. */\nexport function assertIsMessagePartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is MessagePartialSigner<TAddress> {\n if (!isMessagePartialSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the MessagePartialSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\nimport { CompilableTransaction } from '@solana/transactions';\n\nimport { BaseSignerConfig, SignatureDictionary } from './types';\n\nexport type TransactionPartialSignerConfig = BaseSignerConfig;\n\n/** Defines a signer capable of signing transactions. */\nexport type TransactionPartialSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n signTransactions(\n transactions: readonly CompilableTransaction[],\n config?: TransactionPartialSignerConfig\n ): Promise<readonly SignatureDictionary[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link TransactionPartialSigner} interface. */\nexport function isTransactionPartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionPartialSigner<TAddress> {\n return 'signTransactions' in value && typeof value.signTransactions === 'function';\n}\n\n/** Asserts that the provided value implements the {@link TransactionPartialSigner} interface. */\nexport function assertIsTransactionPartialSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionPartialSigner<TAddress> {\n if (!isTransactionPartialSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the TransactionPartialSigner interface');\n }\n}\n","import { Address, isAddress } from '@solana/addresses';\n\nimport { SignableMessage } from './signable-message';\nimport { BaseSignerConfig } from './types';\n\nexport type MessageModifyingSignerConfig = BaseSignerConfig;\n\n/** Defines a signer capable of signing messages. */\nexport type MessageModifyingSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n modifyAndSignMessages(\n messages: readonly SignableMessage[],\n config?: MessageModifyingSignerConfig\n ): Promise<readonly SignableMessage[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link MessageModifyingSigner} interface. */\nexport function isMessageModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is MessageModifyingSigner<TAddress> {\n return (\n isAddress(value.address) &&\n 'modifyAndSignMessages' in value &&\n typeof value.modifyAndSignMessages === 'function'\n );\n}\n\n/** Asserts that the provided value implements the {@link MessageModifyingSigner} interface. */\nexport function assertIsMessageModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is MessageModifyingSigner<TAddress> {\n if (!isMessageModifyingSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the MessageModifyingSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\n\nimport { isMessageModifyingSigner, MessageModifyingSigner } from './message-modifying-signer';\nimport { isMessagePartialSigner, MessagePartialSigner } from './message-partial-signer';\n\n/** Defines a signer capable of signing messages. */\nexport type MessageSigner<TAddress extends string = string> =\n | MessagePartialSigner<TAddress>\n | MessageModifyingSigner<TAddress>;\n\n/** Checks whether the provided value implements the {@link MessageSigner} interface. */\nexport function isMessageSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is MessageSigner<TAddress> {\n return isMessagePartialSigner(value) || isMessageModifyingSigner(value);\n}\n\n/** Asserts that the provided value implements the {@link MessageSigner} interface. */\nexport function assertIsMessageSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is MessageSigner<TAddress> {\n if (!isMessageSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement any of the MessageSigner interfaces');\n }\n}\n","import { Address } from '@solana/addresses';\n\nimport { MessagePartialSigner } from './message-partial-signer';\nimport { TransactionPartialSigner } from './transaction-partial-signer';\n\n/** Defines a no-operation signer that pretends to partially sign messages and transactions. */\nexport type NoopSigner<TAddress extends string = string> = MessagePartialSigner<TAddress> &\n TransactionPartialSigner<TAddress>;\n\n/** Creates a NoopSigner from the provided Address. */\nexport function createNoopSigner(address: Address): NoopSigner {\n const out: NoopSigner = {\n address,\n signMessages: async messages => messages.map(() => Object.freeze({})),\n signTransactions: async transactions => transactions.map(() => Object.freeze({})),\n };\n\n return Object.freeze(out);\n}\n","import { SignatureBytes } from '@solana/keys';\nimport {\n assertTransactionIsFullySigned,\n CompilableTransaction,\n IFullySignedTransaction,\n ITransactionWithSignatures,\n TransactionVersion,\n} from '@solana/transactions';\n\nimport { getSignersFromTransaction, IInstructionWithSigners } from './account-signer-meta';\nimport { deduplicateSigners } from './deduplicate-signers';\nimport { isTransactionModifyingSigner, TransactionModifyingSigner } from './transaction-modifying-signer';\nimport { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';\nimport { isTransactionSendingSigner, TransactionSendingSigner } from './transaction-sending-signer';\nimport { isTransactionSigner, TransactionSigner } from './transaction-signer';\n\ntype CompilableTransactionWithSigners = CompilableTransaction<\n TransactionVersion,\n IInstructionWithSigners<string, TransactionSigner>\n> &\n Partial<ITransactionWithSignatures>;\n\n/**\n * Signs a transaction using any signers that may be stored in IAccountSignerMeta instruction accounts\n * as well as any signers provided explicitly to this function.\n * It will ignore TransactionSendingSigners since this function does not send the transaction.\n */\nexport async function partiallySignTransactionWithSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n config: {\n abortSignal?: AbortSignal;\n signers?: readonly TransactionSigner[];\n } = {}\n): Promise<TTransaction & ITransactionWithSignatures> {\n const signers = config.signers ?? [];\n const { partialSigners, modifyingSigners } = categorizeTransactionSigners(\n deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers]),\n { identifySendingSigner: false }\n );\n\n return signModifyingAndPartialTransactionSigners(transaction, modifyingSigners, partialSigners, config.abortSignal);\n}\n\n/**\n * Signs a transaction using any signers that may be stored in IAccountSignerMeta instruction accounts\n * as well as any signers provided explicitly to this function.\n * It will assert that the transaction is fully signed before returning.\n * It will ignore TransactionSendingSigners since this function does not send the transaction.\n */\nexport async function signTransactionWithSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n config: {\n abortSignal?: AbortSignal;\n signers?: readonly TransactionSigner[];\n } = {}\n): Promise<TTransaction & IFullySignedTransaction> {\n const signedTransaction = await partiallySignTransactionWithSigners(transaction, config);\n assertTransactionIsFullySigned(signedTransaction);\n return signedTransaction;\n}\n\n/**\n * Signs and sends a transaction using any signers that may be stored in IAccountSignerMeta\n * instruction accounts as well as any signers provided explicitly to this function.\n * It will identify a single TransactionSendingSigners to use for sending the transaction, if any.\n * Otherwise, it will send the transaction using the provided fallbackSender.\n */\nexport async function signAndSendTransactionWithSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n config: {\n abortSignal?: AbortSignal;\n fallbackSender?: (transaction: TTransaction & IFullySignedTransaction) => Promise<SignatureBytes>;\n signers?: readonly TransactionSigner[];\n } = {}\n): Promise<SignatureBytes> {\n const signers = config.signers ?? [];\n const abortSignal = config.abortSignal;\n const { partialSigners, modifyingSigners, sendingSigner } = categorizeTransactionSigners(\n deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers])\n );\n\n abortSignal?.throwIfAborted();\n const signedTransaction = await signModifyingAndPartialTransactionSigners(\n transaction,\n modifyingSigners,\n partialSigners,\n abortSignal\n );\n\n if (sendingSigner) {\n abortSignal?.throwIfAborted();\n const [signature] = await sendingSigner.signAndSendTransactions([signedTransaction], { abortSignal });\n return signature;\n }\n\n if (config.fallbackSender) {\n assertTransactionIsFullySigned(signedTransaction);\n return config.fallbackSender(signedTransaction);\n }\n\n // TODO: Coded error.\n throw new Error('No TransactionSendingSigner was identified and no fallback sender was provided.');\n}\n\n/**\n * Identifies each provided TransactionSigner and categorizes them into their respective types.\n * When a signer implements multiple interface, it will try to used to most powerful interface\n * but fallback to the least powerful interface when necessary.\n * For instance, if a signer implements TransactionSendingSigner and TransactionModifyingSigner,\n * it will be categorized as a TransactionSendingSigner if and only if no other signers implement\n * the TransactionSendingSigner interface.\n */\nfunction categorizeTransactionSigners(\n signers: readonly TransactionSigner[],\n config: { identifySendingSigner?: boolean } = {}\n): Readonly<{\n modifyingSigners: readonly TransactionModifyingSigner[];\n partialSigners: readonly TransactionPartialSigner[];\n sendingSigner: TransactionSendingSigner | null;\n}> {\n // Identify the unique sending signer that should be used.\n const identifySendingSigner = config.identifySendingSigner ?? true;\n const sendingSigner = identifySendingSigner ? identifyTransactionSendingSigner(signers) : null;\n\n // Now, focus on the other signers.\n // I.e. the modifying or partial signers that are not the identified sending signer.\n // Note that any other sending only signers will be discarded.\n const otherSigners = signers.filter(\n (signer): signer is TransactionModifyingSigner | TransactionPartialSigner =>\n signer !== sendingSigner && (isTransactionModifyingSigner(signer) || isTransactionPartialSigner(signer))\n );\n\n // Identify the modifying signers from the other signers.\n const modifyingSigners = identifyTransactionModifyingSigners(otherSigners);\n\n // Use any remaining signers as partial signers.\n const partialSigners = otherSigners\n .filter(isTransactionPartialSigner)\n .filter(signer => !(modifyingSigners as typeof otherSigners).includes(signer));\n\n return Object.freeze({ modifyingSigners, partialSigners, sendingSigner });\n}\n\n/** Identifies the best signer to use as a TransactionSendingSigner, if any */\nfunction identifyTransactionSendingSigner(signers: readonly TransactionSigner[]): TransactionSendingSigner | null {\n // Ensure there are any TransactionSendingSigners in the first place.\n const sendingSigners = signers.filter(isTransactionSendingSigner);\n if (sendingSigners.length === 0) return null;\n\n // Prefer sending signers that do not offer other interfaces.\n const sendingOnlySigners = sendingSigners.filter(\n signer => !isTransactionModifyingSigner(signer) && !isTransactionPartialSigner(signer)\n );\n if (sendingOnlySigners.length > 0) {\n return sendingOnlySigners[0];\n }\n\n // Otherwise, choose any sending signer.\n return sendingSigners[0];\n}\n\n/** Identifies the best signers to use as TransactionModifyingSigners, if any */\nfunction identifyTransactionModifyingSigners(\n signers: readonly (TransactionModifyingSigner | TransactionPartialSigner)[]\n): readonly TransactionModifyingSigner[] {\n // Ensure there are any TransactionModifyingSigner in the first place.\n const modifyingSigners = signers.filter(isTransactionModifyingSigner);\n if (modifyingSigners.length === 0) return [];\n\n // Prefer modifying signers that do not offer partial signing.\n const nonPartialSigners = modifyingSigners.filter(signer => !isTransactionPartialSigner(signer));\n if (nonPartialSigners.length > 0) return nonPartialSigners;\n\n // Otherwise, choose only one modifying signer (whichever).\n return [modifyingSigners[0]];\n}\n\n/**\n * Signs a transaction using the provided TransactionModifyingSigners\n * sequentially followed by the TransactionPartialSigners in parallel.\n */\nasync function signModifyingAndPartialTransactionSigners<\n TTransaction extends CompilableTransactionWithSigners = CompilableTransactionWithSigners\n>(\n transaction: TTransaction,\n modifyingSigners: readonly TransactionModifyingSigner[] = [],\n partialSigners: readonly TransactionPartialSigner[] = [],\n abortSignal?: AbortSignal\n): Promise<TTransaction & ITransactionWithSignatures> {\n // Handle modifying signers sequentially.\n const modifiedTransaction = await modifyingSigners.reduce(async (transaction, modifyingSigner) => {\n abortSignal?.throwIfAborted();\n const [tx] = await modifyingSigner.modifyAndSignTransactions([await transaction], { abortSignal });\n return Object.freeze(tx);\n }, Promise.resolve(transaction) as Promise<TTransaction>);\n\n // Handle partial signers in parallel.\n abortSignal?.throwIfAborted();\n const signatureDictionaries = await Promise.all(\n partialSigners.map(async partialSigner => {\n const [signatures] = await partialSigner.signTransactions([modifiedTransaction], { abortSignal });\n return signatures;\n })\n );\n const signedTransaction: TTransaction & ITransactionWithSignatures = {\n ...modifiedTransaction,\n signatures: Object.freeze(\n signatureDictionaries.reduce((signatures, signatureDictionary) => {\n return { ...signatures, ...signatureDictionary };\n }, modifiedTransaction.signatures ?? {})\n ),\n };\n\n return Object.freeze(signedTransaction);\n}\n","import { Address } from '@solana/addresses';\nimport { CompilableTransaction } from '@solana/transactions';\n\nimport { BaseSignerConfig } from './types';\n\nexport type TransactionModifyingSignerConfig = BaseSignerConfig;\n\n/** Defines a signer capable of signing transactions. */\nexport type TransactionModifyingSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n modifyAndSignTransactions<TTransaction extends CompilableTransaction>(\n transactions: readonly TTransaction[],\n config?: TransactionModifyingSignerConfig\n ): Promise<readonly TTransaction[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link TransactionModifyingSigner} interface. */\nexport function isTransactionModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionModifyingSigner<TAddress> {\n return 'modifyAndSignTransactions' in value && typeof value.modifyAndSignTransactions === 'function';\n}\n\n/** Asserts that the provided value implements the {@link TransactionModifyingSigner} interface. */\nexport function assertIsTransactionModifyingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionModifyingSigner<TAddress> {\n if (!isTransactionModifyingSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the TransactionModifyingSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\nimport { SignatureBytes } from '@solana/keys';\nimport { CompilableTransaction } from '@solana/transactions';\n\nimport { BaseSignerConfig } from './types';\n\nexport type TransactionSendingSignerConfig = BaseSignerConfig;\n\n/** Defines a signer capable of signing and sending transactions simultaneously. */\nexport type TransactionSendingSigner<TAddress extends string = string> = Readonly<{\n address: Address<TAddress>;\n signAndSendTransactions(\n transactions: readonly CompilableTransaction[],\n config?: TransactionSendingSignerConfig\n ): Promise<readonly SignatureBytes[]>;\n}>;\n\n/** Checks whether the provided value implements the {@link TransactionSendingSigner} interface. */\nexport function isTransactionSendingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionSendingSigner<TAddress> {\n return 'signAndSendTransactions' in value && typeof value.signAndSendTransactions === 'function';\n}\n\n/** Asserts that the provided value implements the {@link TransactionSendingSigner} interface. */\nexport function assertIsTransactionSendingSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionSendingSigner<TAddress> {\n if (!isTransactionSendingSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement the TransactionSendingSigner interface');\n }\n}\n","import { Address } from '@solana/addresses';\n\nimport { isTransactionModifyingSigner, TransactionModifyingSigner } from './transaction-modifying-signer';\nimport { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';\nimport { isTransactionSendingSigner, TransactionSendingSigner } from './transaction-sending-signer';\n\n/** Defines a signer capable of signing transactions. */\nexport type TransactionSigner<TAddress extends string = string> =\n | TransactionPartialSigner<TAddress>\n | TransactionModifyingSigner<TAddress>\n | TransactionSendingSigner<TAddress>;\n\n/** Checks whether the provided value implements the {@link TransactionSigner} interface. */\nexport function isTransactionSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): value is TransactionSigner<TAddress> {\n return (\n isTransactionPartialSigner(value) || isTransactionModifyingSigner(value) || isTransactionSendingSigner(value)\n );\n}\n\n/** Asserts that the provided value implements the {@link TransactionSigner} interface. */\nexport function assertIsTransactionSigner<TAddress extends string>(value: {\n address: Address<TAddress>;\n [key: string]: unknown;\n}): asserts value is TransactionSigner<TAddress> {\n if (!isTransactionSigner(value)) {\n // TODO: Coded error.\n throw new Error('The provided value does not implement any of the TransactionSigner interfaces');\n }\n}\n","export const TextDecoder = globalThis.TextDecoder;\nexport const TextEncoder = globalThis.TextEncoder;\n","import { TextEncoder } from 'text-encoding-impl';\n\nimport { SignatureDictionary } from './types';\n\n/** Defines a message that needs signing and its current set of signatures if any. */\nexport type SignableMessage = Readonly<{\n content: Uint8Array;\n signatures: SignatureDictionary;\n}>;\n\n/**\n * Creates a signable message from a provided content.\n * If a string is provided, it will be UTF-8 encoded.\n */\nexport function createSignableMessage(\n content: string | Uint8Array,\n signatures: SignatureDictionary = {}\n): SignableMessage {\n return Object.freeze({\n content: typeof content === 'string' ? new TextEncoder().encode(content) : content,\n signatures: Object.freeze({ ...signatures }),\n });\n}\n"]}
@@ -8,6 +8,10 @@ function deduplicateSigners(signers) {
8
8
  signers.forEach((signer) => {
9
9
  if (!deduplicated[signer.address]) {
10
10
  deduplicated[signer.address] = signer;
11
+ } else if (deduplicated[signer.address] !== signer) {
12
+ throw new Error(
13
+ `Multiple distinct signers were identified for address "${signer.address}". Please ensure that you are using the same signer instance for each address.`
14
+ );
11
15
  }
12
16
  });
13
17
  return Object.values(deduplicated);
@@ -93,6 +97,16 @@ function assertIsMessageSigner(value) {
93
97
  }
94
98
  }
95
99
 
100
+ // src/noop-signer.ts
101
+ function createNoopSigner(address) {
102
+ const out = {
103
+ address,
104
+ signMessages: async (messages) => messages.map(() => Object.freeze({})),
105
+ signTransactions: async (transactions) => transactions.map(() => Object.freeze({}))
106
+ };
107
+ return Object.freeze(out);
108
+ }
109
+
96
110
  // src/transaction-modifying-signer.ts
97
111
  function isTransactionModifyingSigner(value) {
98
112
  return "modifyAndSignTransactions" in value && typeof value.modifyAndSignTransactions === "function";
@@ -124,39 +138,45 @@ function assertIsTransactionSigner(value) {
124
138
  }
125
139
 
126
140
  // src/sign-transaction.ts
127
- async function partiallySignTransactionWithSigners(transaction, signers = []) {
141
+ async function partiallySignTransactionWithSigners(transaction, config = {}) {
142
+ const signers = config.signers ?? [];
128
143
  const { partialSigners, modifyingSigners } = categorizeTransactionSigners(
129
144
  deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers]),
130
145
  { identifySendingSigner: false }
131
146
  );
132
- return signModifyingAndPartialTransactionSigners(transaction, modifyingSigners, partialSigners);
147
+ return signModifyingAndPartialTransactionSigners(transaction, modifyingSigners, partialSigners, config.abortSignal);
133
148
  }
134
- async function signTransactionWithSigners(transaction, signers = []) {
135
- const signedTransaction = await partiallySignTransactionWithSigners(transaction, signers);
149
+ async function signTransactionWithSigners(transaction, config = {}) {
150
+ const signedTransaction = await partiallySignTransactionWithSigners(transaction, config);
136
151
  assertTransactionIsFullySigned(signedTransaction);
137
152
  return signedTransaction;
138
153
  }
139
- async function signAndSendTransactionWithSigners(transaction, signers = [], fallbackSender) {
154
+ async function signAndSendTransactionWithSigners(transaction, config = {}) {
155
+ const signers = config.signers ?? [];
156
+ const abortSignal = config.abortSignal;
140
157
  const { partialSigners, modifyingSigners, sendingSigner } = categorizeTransactionSigners(
141
158
  deduplicateSigners([...getSignersFromTransaction(transaction).filter(isTransactionSigner), ...signers])
142
159
  );
160
+ abortSignal?.throwIfAborted();
143
161
  const signedTransaction = await signModifyingAndPartialTransactionSigners(
144
162
  transaction,
145
163
  modifyingSigners,
146
- partialSigners
164
+ partialSigners,
165
+ abortSignal
147
166
  );
148
167
  if (sendingSigner) {
149
- const [signature] = await sendingSigner.signAndSendTransactions([signedTransaction]);
168
+ abortSignal?.throwIfAborted();
169
+ const [signature] = await sendingSigner.signAndSendTransactions([signedTransaction], { abortSignal });
150
170
  return signature;
151
171
  }
152
- if (fallbackSender) {
172
+ if (config.fallbackSender) {
153
173
  assertTransactionIsFullySigned(signedTransaction);
154
- return fallbackSender(signedTransaction);
174
+ return config.fallbackSender(signedTransaction);
155
175
  }
156
176
  throw new Error("No TransactionSendingSigner was identified and no fallback sender was provided.");
157
177
  }
158
- function categorizeTransactionSigners(signers, options) {
159
- const identifySendingSigner = options?.identifySendingSigner ?? true;
178
+ function categorizeTransactionSigners(signers, config = {}) {
179
+ const identifySendingSigner = config.identifySendingSigner ?? true;
160
180
  const sendingSigner = identifySendingSigner ? identifyTransactionSendingSigner(signers) : null;
161
181
  const otherSigners = signers.filter(
162
182
  (signer) => signer !== sendingSigner && (isTransactionModifyingSigner(signer) || isTransactionPartialSigner(signer))
@@ -186,14 +206,16 @@ function identifyTransactionModifyingSigners(signers) {
186
206
  return nonPartialSigners;
187
207
  return [modifyingSigners[0]];
188
208
  }
189
- async function signModifyingAndPartialTransactionSigners(transaction, modifyingSigners = [], partialSigners = []) {
209
+ async function signModifyingAndPartialTransactionSigners(transaction, modifyingSigners = [], partialSigners = [], abortSignal) {
190
210
  const modifiedTransaction = await modifyingSigners.reduce(async (transaction2, modifyingSigner) => {
191
- const [tx] = await modifyingSigner.modifyAndSignTransactions([await transaction2]);
211
+ abortSignal?.throwIfAborted();
212
+ const [tx] = await modifyingSigner.modifyAndSignTransactions([await transaction2], { abortSignal });
192
213
  return Object.freeze(tx);
193
214
  }, Promise.resolve(transaction));
215
+ abortSignal?.throwIfAborted();
194
216
  const signatureDictionaries = await Promise.all(
195
217
  partialSigners.map(async (partialSigner) => {
196
- const [signatures] = await partialSigner.signTransactions([modifiedTransaction]);
218
+ const [signatures] = await partialSigner.signTransactions([modifiedTransaction], { abortSignal });
197
219
  return signatures;
198
220
  })
199
221
  );
@@ -217,6 +239,6 @@ function createSignableMessage(content, signatures = {}) {
217
239
  });
218
240
  }
219
241
 
220
- export { assertIsKeyPairSigner, assertIsMessageModifyingSigner, assertIsMessagePartialSigner, assertIsMessageSigner, assertIsTransactionModifyingSigner, assertIsTransactionPartialSigner, assertIsTransactionSendingSigner, assertIsTransactionSigner, createSignableMessage, createSignerFromKeyPair, generateKeyPairSigner, getSignersFromInstruction, getSignersFromTransaction, isKeyPairSigner, isMessageModifyingSigner, isMessagePartialSigner, isMessageSigner, isTransactionModifyingSigner, isTransactionPartialSigner, isTransactionSendingSigner, isTransactionSigner, partiallySignTransactionWithSigners, signAndSendTransactionWithSigners, signTransactionWithSigners };
242
+ export { assertIsKeyPairSigner, assertIsMessageModifyingSigner, assertIsMessagePartialSigner, assertIsMessageSigner, assertIsTransactionModifyingSigner, assertIsTransactionPartialSigner, assertIsTransactionSendingSigner, assertIsTransactionSigner, createNoopSigner, createSignableMessage, createSignerFromKeyPair, generateKeyPairSigner, getSignersFromInstruction, getSignersFromTransaction, isKeyPairSigner, isMessageModifyingSigner, isMessagePartialSigner, isMessageSigner, isTransactionModifyingSigner, isTransactionPartialSigner, isTransactionSendingSigner, isTransactionSigner, partiallySignTransactionWithSigners, signAndSendTransactionWithSigners, signTransactionWithSigners };
221
243
  //# sourceMappingURL=out.js.map
222
244
  //# sourceMappingURL=index.browser.js.map