@hashgraph/hedera-wallet-connect 2.0.4-canary.147c309.0 → 2.0.4-canary.157c336.0
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.
- package/dist/lib/shared/utils.d.ts +2 -29
- package/dist/lib/shared/utils.js +7 -58
- package/package.json +1 -1
|
@@ -275,33 +275,6 @@ export declare const accountAndLedgerFromSession: (session: SessionTypes.Struct)
|
|
|
275
275
|
}[];
|
|
276
276
|
/**
|
|
277
277
|
* Adds an additional signature to an already-signed transaction.
|
|
278
|
-
*
|
|
279
|
-
* This function is critical for multi-signature workflows where a transaction
|
|
280
|
-
* has already been signed by one party (e.g., via WalletConnect) and needs
|
|
281
|
-
* an additional signature from another party (e.g., backend co-signer).
|
|
282
|
-
*
|
|
283
|
-
* IMPORTANT: The standard SDK `.sign()` method does NOT work on reconstructed
|
|
284
|
-
* transactions because it clears the `_transactions` array (Transaction.js:825),
|
|
285
|
-
* which deletes existing signatures. This function uses proto-level manipulation
|
|
286
|
-
* to preserve all existing signatures while adding new ones.
|
|
287
|
-
*
|
|
288
|
-
* This implementation mirrors the signature merging pattern used in
|
|
289
|
-
* `DAppSigner.signTransaction()` (DAppSigner.ts:248-273).
|
|
290
|
-
*
|
|
291
|
-
* @param transaction - Transaction that already has one or more signatures
|
|
292
|
-
* @param privateKey - Private key to create additional signature
|
|
293
|
-
* @returns New transaction instance with all signatures (existing + new)
|
|
294
|
-
*
|
|
295
|
-
* @example
|
|
296
|
-
* ```typescript
|
|
297
|
-
* // Wallet signs first
|
|
298
|
-
* const walletSigned = await signer.signTransaction(transaction)
|
|
299
|
-
*
|
|
300
|
-
* // Backend adds signature
|
|
301
|
-
* const fullySigned = await addSignatureToTransaction(walletSigned, backendPrivateKey)
|
|
302
|
-
*
|
|
303
|
-
* // Now has both signatures
|
|
304
|
-
* await fullySigned.execute(client)
|
|
305
|
-
* ```
|
|
278
|
+
* Uses proto-level manipulation to preserve existing signatures.
|
|
306
279
|
*/
|
|
307
|
-
export declare function addSignatureToTransaction<T extends Transaction>(transaction: T, privateKey:
|
|
280
|
+
export declare function addSignatureToTransaction<T extends Transaction>(transaction: T, privateKey: PrivateKey): Promise<T>;
|
package/dist/lib/shared/utils.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
import { Buffer } from 'buffer';
|
|
21
|
-
import { AccountId,
|
|
21
|
+
import { AccountId, Transaction, LedgerId, Query, } from '@hashgraph/sdk';
|
|
22
22
|
import { proto } from '@hashgraph/proto';
|
|
23
23
|
/**
|
|
24
24
|
* Converts `Transaction` to a Base64-string.
|
|
@@ -420,40 +420,11 @@ export const accountAndLedgerFromSession = (session) => {
|
|
|
420
420
|
};
|
|
421
421
|
/**
|
|
422
422
|
* Adds an additional signature to an already-signed transaction.
|
|
423
|
-
*
|
|
424
|
-
* This function is critical for multi-signature workflows where a transaction
|
|
425
|
-
* has already been signed by one party (e.g., via WalletConnect) and needs
|
|
426
|
-
* an additional signature from another party (e.g., backend co-signer).
|
|
427
|
-
*
|
|
428
|
-
* IMPORTANT: The standard SDK `.sign()` method does NOT work on reconstructed
|
|
429
|
-
* transactions because it clears the `_transactions` array (Transaction.js:825),
|
|
430
|
-
* which deletes existing signatures. This function uses proto-level manipulation
|
|
431
|
-
* to preserve all existing signatures while adding new ones.
|
|
432
|
-
*
|
|
433
|
-
* This implementation mirrors the signature merging pattern used in
|
|
434
|
-
* `DAppSigner.signTransaction()` (DAppSigner.ts:248-273).
|
|
435
|
-
*
|
|
436
|
-
* @param transaction - Transaction that already has one or more signatures
|
|
437
|
-
* @param privateKey - Private key to create additional signature
|
|
438
|
-
* @returns New transaction instance with all signatures (existing + new)
|
|
439
|
-
*
|
|
440
|
-
* @example
|
|
441
|
-
* ```typescript
|
|
442
|
-
* // Wallet signs first
|
|
443
|
-
* const walletSigned = await signer.signTransaction(transaction)
|
|
444
|
-
*
|
|
445
|
-
* // Backend adds signature
|
|
446
|
-
* const fullySigned = await addSignatureToTransaction(walletSigned, backendPrivateKey)
|
|
447
|
-
*
|
|
448
|
-
* // Now has both signatures
|
|
449
|
-
* await fullySigned.execute(client)
|
|
450
|
-
* ```
|
|
423
|
+
* Uses proto-level manipulation to preserve existing signatures.
|
|
451
424
|
*/
|
|
452
425
|
export async function addSignatureToTransaction(transaction, privateKey) {
|
|
453
|
-
// Step 1: Get original transaction bytes (preserves ALL existing signatures)
|
|
454
426
|
const originalBytes = transaction.toBytes();
|
|
455
427
|
const originalList = proto.TransactionList.decode(originalBytes);
|
|
456
|
-
// Step 2: Extract transaction body bytes to sign
|
|
457
428
|
const firstTransaction = originalList.transactionList[0];
|
|
458
429
|
let bodyBytes;
|
|
459
430
|
if (firstTransaction.signedTransactionBytes) {
|
|
@@ -463,48 +434,26 @@ export async function addSignatureToTransaction(transaction, privateKey) {
|
|
|
463
434
|
else {
|
|
464
435
|
bodyBytes = firstTransaction.bodyBytes;
|
|
465
436
|
}
|
|
466
|
-
|
|
467
|
-
const publicKey = privateKey
|
|
468
|
-
const signature = privateKey instanceof PublicKey
|
|
469
|
-
? (() => {
|
|
470
|
-
throw new Error('Cannot sign with PublicKey, PrivateKey required');
|
|
471
|
-
})()
|
|
472
|
-
: await privateKey.sign(bodyBytes);
|
|
473
|
-
// Step 4: Add new signature to ALL transactions in the list
|
|
474
|
-
// Each transaction in the list corresponds to a different node
|
|
437
|
+
const signature = await privateKey.sign(bodyBytes);
|
|
438
|
+
const publicKey = privateKey.publicKey;
|
|
475
439
|
const signedTransactionList = originalList.transactionList.map((tx) => {
|
|
476
|
-
// Create the new signature pair using SDK's internal method
|
|
477
440
|
const newSigPair = publicKey._toProtobufSignature(signature);
|
|
478
|
-
// Check if the transaction has signedTransactionBytes (frozen transactions)
|
|
479
441
|
if (tx.signedTransactionBytes) {
|
|
480
|
-
// Decode the SignedTransaction to access the bodyBytes and existing sigMap
|
|
481
442
|
const signedTx = proto.SignedTransaction.decode(tx.signedTransactionBytes);
|
|
482
443
|
const existingSigMap = signedTx.sigMap || proto.SignatureMap.create({});
|
|
483
|
-
// Merge existing signatures with new signature
|
|
484
444
|
const mergedSigPairs = [...(existingSigMap.sigPair || []), newSigPair];
|
|
485
|
-
// Create updated SignedTransaction with merged signatures
|
|
486
445
|
const updatedSignedTx = proto.SignedTransaction.encode({
|
|
487
446
|
bodyBytes: signedTx.bodyBytes,
|
|
488
|
-
sigMap: proto.SignatureMap.create({
|
|
489
|
-
sigPair: mergedSigPairs,
|
|
490
|
-
}),
|
|
447
|
+
sigMap: proto.SignatureMap.create({ sigPair: mergedSigPairs }),
|
|
491
448
|
}).finish();
|
|
492
|
-
return {
|
|
493
|
-
signedTransactionBytes: updatedSignedTx,
|
|
494
|
-
};
|
|
449
|
+
return { signedTransactionBytes: updatedSignedTx };
|
|
495
450
|
}
|
|
496
451
|
else {
|
|
497
|
-
// Transaction has bodyBytes and sigMap at the top level (not frozen)
|
|
498
452
|
const existingSigMap = tx.sigMap || proto.SignatureMap.create({});
|
|
499
|
-
// Merge existing signatures with new signature
|
|
500
453
|
const mergedSigPairs = [...(existingSigMap.sigPair || []), newSigPair];
|
|
501
454
|
return Object.assign(Object.assign({}, tx), { sigMap: Object.assign(Object.assign({}, existingSigMap), { sigPair: mergedSigPairs }) });
|
|
502
455
|
}
|
|
503
456
|
});
|
|
504
|
-
|
|
505
|
-
const signedBytes = proto.TransactionList.encode({
|
|
506
|
-
transactionList: signedTransactionList,
|
|
507
|
-
}).finish();
|
|
508
|
-
// Step 6: Return reconstructed transaction with all signatures
|
|
457
|
+
const signedBytes = proto.TransactionList.encode({ transactionList: signedTransactionList }).finish();
|
|
509
458
|
return Transaction.fromBytes(signedBytes);
|
|
510
459
|
}
|
package/package.json
CHANGED