Skip to content

Commit 9d336f0

Browse files
Merge pull request #739 from kouraf/feature/add-versioned-transaction-solana-signature
Feature: added versioned transaction solana signature
2 parents 5fd2674 + b9eb88c commit 9d336f0

File tree

6 files changed

+49
-8
lines changed

6 files changed

+49
-8
lines changed

packages/wrapped-keys-lit-actions/src/lib/internal/solana/signTransaction.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Connection,
55
Keypair,
66
Transaction,
7+
VersionedTransaction,
78
} from '@solana/web3.js';
89

910
// Solana transactions are pre-serialized; much simpler API than ethereum transactions
@@ -31,7 +32,7 @@ export function validateUnsignedTransaction(
3132
}
3233
}
3334

34-
function signTransaction({
35+
function signLegacyTransaction({
3536
solanaKeyPair,
3637
transaction,
3738
}: {
@@ -45,18 +46,36 @@ function signTransaction({
4546
throw new Error('Transaction signature is null');
4647
}
4748

48-
return { signature: ethers.utils.base58.encode(transaction.signature) };
49+
return ethers.utils.base58.encode(transaction.signature);
4950
} catch (err: unknown) {
5051
throw new Error(`When signing transaction - ${(err as Error).message}`);
5152
}
5253
}
54+
function signVersionedTransaction({
55+
solanaKeyPair,
56+
transaction,
57+
}: {
58+
solanaKeyPair: Keypair;
59+
transaction: VersionedTransaction;
60+
}) {
61+
try {
62+
transaction.sign([solanaKeyPair]);
63+
64+
if (!transaction.signatures.length) {
65+
throw new Error('Transaction signature is null');
66+
}
5367

68+
return ethers.utils.base58.encode(transaction.signatures[0]);
69+
} catch (err: unknown) {
70+
throw new Error(`When signing transaction - ${(err as Error).message}`);
71+
}
72+
}
5473
async function sendTransaction({
5574
chain,
5675
transaction,
5776
}: {
5877
chain: Cluster;
59-
transaction: Transaction;
78+
transaction: Transaction | VersionedTransaction;
6079
}) {
6180
try {
6281
const solanaConnection = new Connection(clusterApiUrl(chain), 'confirmed');
@@ -70,20 +89,32 @@ export async function signTransactionSolanaKey({
7089
broadcast,
7190
privateKey,
7291
unsignedTransaction,
92+
versionedTransaction,
7393
}: {
7494
broadcast: boolean;
7595
privateKey: string;
7696
unsignedTransaction: UnsignedTransaction;
97+
versionedTransaction?: boolean;
7798
}) {
7899
// Be sure you call validateUnsignedTransaction(unsignedTransaction); before calling this method!
79100

80101
const solanaKeyPair = Keypair.fromSecretKey(Buffer.from(privateKey, 'hex'));
81102

82-
const transaction = Transaction.from(
83-
Buffer.from(unsignedTransaction.serializedTransaction, 'base64')
84-
);
85-
86-
const { signature } = signTransaction({ transaction, solanaKeyPair });
103+
let transaction;
104+
let signature;
105+
if (versionedTransaction) {
106+
const swapTransactionBuf = Buffer.from(
107+
unsignedTransaction.serializedTransaction,
108+
'base64'
109+
);
110+
transaction = VersionedTransaction.deserialize(swapTransactionBuf);
111+
signature = signVersionedTransaction({ transaction, solanaKeyPair });
112+
} else {
113+
transaction = Transaction.from(
114+
Buffer.from(unsignedTransaction.serializedTransaction, 'base64')
115+
);
116+
signature = signLegacyTransaction({ transaction, solanaKeyPair });
117+
}
87118

88119
if (!broadcast) {
89120
return signature;

packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/solana/signTransactionWithEncryptedSolanaKey.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface SignTransactionWithEncryptedSolanaKeyParams {
1212
dataToEncryptHash: string; // The hash of the data to encrypt
1313
unsignedTransaction: UnsignedTransaction;
1414
broadcast: boolean; // Flag to determine if the transaction should be broadcasted
15+
versionedTransaction?: boolean; // Flag to determine if the transaction is a versioned one or a legacy one
1516
}
1617

1718
/**
@@ -28,6 +29,7 @@ export async function signTransactionWithEncryptedSolanaKey({
2829
dataToEncryptHash,
2930
unsignedTransaction,
3031
broadcast,
32+
versionedTransaction,
3133
}: SignTransactionWithEncryptedSolanaKeyParams): Promise<string> {
3234
validateUnsignedTransaction(unsignedTransaction);
3335

@@ -41,5 +43,6 @@ export async function signTransactionWithEncryptedSolanaKey({
4143
broadcast,
4244
privateKey,
4345
unsignedTransaction,
46+
versionedTransaction,
4447
});
4548
}

packages/wrapped-keys-lit-actions/src/lib/self-executing-actions/solana/signTransactionWithEncryptedSolanaKey.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ declare const ciphertext: SignTransactionWithEncryptedSolanaKeyParams['ciphertex
1111
declare const dataToEncryptHash: SignTransactionWithEncryptedSolanaKeyParams['dataToEncryptHash'];
1212
declare const unsignedTransaction: SignTransactionWithEncryptedSolanaKeyParams['unsignedTransaction'];
1313
declare const broadcast: SignTransactionWithEncryptedSolanaKeyParams['broadcast'];
14+
declare const versionedTransaction: SignTransactionWithEncryptedSolanaKeyParams['versionedTransaction'];
1415

1516
(async () =>
1617
litActionHandler(async () =>
@@ -20,5 +21,6 @@ declare const broadcast: SignTransactionWithEncryptedSolanaKeyParams['broadcast'
2021
dataToEncryptHash,
2122
unsignedTransaction,
2223
broadcast,
24+
versionedTransaction,
2325
})
2426
))();

packages/wrapped-keys/src/lib/api/sign-transaction-with-encrypted-key.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { SignTransactionWithEncryptedKeyParams } from '../types';
1212
* Signs a transaction inside the Lit Action using the previously persisted wrapped key associated with the current LIT PK.
1313
* This method fetches the encrypted key from the wrapped keys service, then executes a Lit Action that decrypts the key inside the LIT action and uses
1414
* the decrypted key to sign the provided transaction
15+
* use `versionedTransaction: true` to sign a versioned transaction and `false` for a legacy one
1516
* Optionally, if you pass `broadcast: true`, the LIT action will also submit the signed transaction to the associated RPC endpoint on your behalf
1617
*
1718
* @param { SignTransactionWithEncryptedKeyParams } params Parameters required to sign the requested transaction

packages/wrapped-keys/src/lib/lit-actions-client/sign-transaction.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ interface SignTransactionWithLitActionParams {
2121
storedKeyMetadata: StoredKeyData;
2222
accessControlConditions: AccessControlConditions;
2323
broadcast: boolean;
24+
versionedTransaction?: boolean;
2425
}
2526

2627
export async function signTransactionWithLitAction({
@@ -32,6 +33,7 @@ export async function signTransactionWithLitAction({
3233
pkpSessionSigs,
3334
storedKeyMetadata: { ciphertext, dataToEncryptHash, pkpAddress },
3435
unsignedTransaction,
36+
versionedTransaction,
3537
}: SignTransactionWithLitActionParams): Promise<string> {
3638
const result = await litNodeClient.executeJs({
3739
sessionSigs: pkpSessionSigs,
@@ -44,6 +46,7 @@ export async function signTransactionWithLitAction({
4446
unsignedTransaction,
4547
broadcast,
4648
accessControlConditions,
49+
versionedTransaction,
4750
},
4851
ipfsOptions: {
4952
overwriteCode:

packages/wrapped-keys/src/lib/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ export interface SignTransactionParamsSupportedSolana
291291
extends SignTransactionParams {
292292
unsignedTransaction: SerializedTransaction;
293293
network: Extract<Network, 'solana'>;
294+
versionedTransaction?: boolean;
294295
}
295296

296297
/** @typedef SignTransactionWithEncryptedKeyParams

0 commit comments

Comments
 (0)