Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add signMessage and signTransaction Lit Action exports for Wrapped Keys #504

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
597e106
WIP
spacesailor24 Jun 7, 2024
5a59aed
WIP
spacesailor24 Jun 11, 2024
a840ca1
Merge branch 'feature/lit-3125-sdk-for-wrapping-up-walletx-2' into wy…
spacesailor24 Jun 11, 2024
d2cd7c5
Undo LA rename
spacesailor24 Jun 11, 2024
d857535
Debugging dist file path resolution
spacesailor24 Jun 11, 2024
87f2f69
Merge branch 'feature/lit-3125-sdk-for-wrapping-up-walletx-2' into wy…
spacesailor24 Jun 11, 2024
64a5930
Remove bundled solana LAs
spacesailor24 Jun 14, 2024
b277753
Replace Solana LA with IPFS CIDs
spacesailor24 Jun 14, 2024
4ecd120
Merge branch 'feature/lit-3125-sdk-for-wrapping-up-walletx-2' into wy…
spacesailor24 Jun 14, 2024
4fdf8a3
WIP
spacesailor24 Jun 14, 2024
7ec6dc3
Fix LA and test for sign message
spacesailor24 Jun 14, 2024
edb781c
Init test sign tx. Update LA
spacesailor24 Jun 14, 2024
33a848f
Remove extra line from gitignore
spacesailor24 Jun 14, 2024
dbb9631
Remove extra file
spacesailor24 Jun 14, 2024
68d0c91
Undo rename of litActions file
spacesailor24 Jun 14, 2024
46579e1
Undo changes to wrapped-keys.ts
spacesailor24 Jun 14, 2024
84f344b
Rename Ethereum LA file
spacesailor24 Jun 14, 2024
3051354
Update packages/wrapped-keys/src/lib/litActions/solana/src/signMessag…
spacesailor24 Jun 15, 2024
31c8735
Update packages/wrapped-keys/src/lib/litActions/solana/src/signTransa…
spacesailor24 Jun 15, 2024
c20ef71
Update packages/wrapped-keys/src/lib/litActions/solana/src/signMessag…
spacesailor24 Jun 15, 2024
ca469da
Update packages/wrapped-keys/src/lib/litActions/solana/src/signTransa…
spacesailor24 Jun 15, 2024
80b2ebb
Update packages/wrapped-keys/src/lib/litActions/solana/src/signMessag…
spacesailor24 Jun 15, 2024
d60fba9
Ran prettier
spacesailor24 Jun 15, 2024
25d303f
Merge branch 'wyatt/add-solana-actions' of github.com:LIT-Protocol/js…
spacesailor24 Jun 15, 2024
23d8298
Add **/*/dist to prettierignore
spacesailor24 Jun 15, 2024
c538a1e
Use getEoaSessionSigs helper
spacesailor24 Jun 15, 2024
97dbc40
feat: Accept ipfsCid param for signMessage
DashKash54 Jun 19, 2024
d490657
feat: Update Solana tx signing to accept serialized tx string + new S…
DashKash54 Jun 19, 2024
501f229
Merge branch 'feature/lit-3125-sdk-for-wrapping-up-walletx-2' into wy…
DashKash54 Jun 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
/tmp
/packages/*/dist
.nx
tools
tools
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved
**/*/dist
4 changes: 4 additions & 0 deletions local-tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ import { testFailImportWrappedKeysWithMaxExpirySessionSig } from './tests/testFa
import { testFailImportWrappedKeysWithInvalidSessionSig } from './tests/testFailImportWrappedKeysWithInvalidSessionSig';
import { testFailImportWrappedKeysWithExpiredSessionSig } from './tests/testFailImportWrappedKeysWithExpiredSessionSig';
import { testExportWrappedKey } from './tests/testExportWrappedKey';
import { testSignMessageWithSolanaEncryptedKey } from './tests/testSignMessageWithSolanaEncryptedKey';
import { testSignTransactionWithSolanaEncryptedKey } from './tests/testSignTransactionWithSolanaEncryptedKey';
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved

(async () => {
console.log('[𐬺🧪 Tinny𐬺] Running tests...');
Expand Down Expand Up @@ -129,6 +131,8 @@ import { testExportWrappedKey } from './tests/testExportWrappedKey';
testFailImportWrappedKeysWithInvalidSessionSig,
testFailImportWrappedKeysWithExpiredSessionSig,
testExportWrappedKey,
testSignMessageWithSolanaEncryptedKey,
testSignTransactionWithSolanaEncryptedKey,
};

const eoaSessionSigsTests = {
Expand Down
4 changes: 2 additions & 2 deletions local-tests/tests/testEthereumSignMessageGeneratedKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const testEthereumSignMessageGeneratedKey = async (
const signature = await signMessageWithEncryptedKey({
pkpSessionSigs: pkpSessionSigsSigning,
litActionCode: signMessageWithEthereumEncryptedKeyLitAction,
unsignedMessage: unsignedStringMessage,
messageToSign: unsignedStringMessage,
litNodeClient: devEnv.litNodeClient,
});

Expand All @@ -74,7 +74,7 @@ export const testEthereumSignMessageGeneratedKey = async (
const signatureBinary = await signMessageWithEncryptedKey({
pkpSessionSigs: pkpSessionSigsSigning,
litActionCode: signMessageWithEthereumEncryptedKeyLitAction,
unsignedMessage: unsignedBinaryMessage,
messageToSign: unsignedBinaryMessage,
litNodeClient: devEnv.litNodeClient,
});

Expand Down
4 changes: 2 additions & 2 deletions local-tests/tests/testEthereumSignMessageWrappedKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const testEthereumSignMessageWrappedKey = async (
const signature = await signMessageWithEncryptedKey({
pkpSessionSigs: pkpSessionSigsSigning,
litActionCode: signMessageWithEthereumEncryptedKeyLitAction,
unsignedMessage: unsignedStringMessage,
messageToSign: unsignedStringMessage,
litNodeClient: devEnv.litNodeClient,
});

Expand All @@ -75,7 +75,7 @@ export const testEthereumSignMessageWrappedKey = async (
const signatureBinary = await signMessageWithEncryptedKey({
pkpSessionSigs: pkpSessionSigsSigning,
litActionCode: signMessageWithEthereumEncryptedKeyLitAction,
unsignedMessage: unsignedBinaryMessage,
messageToSign: unsignedBinaryMessage,
litNodeClient: devEnv.litNodeClient,
});

Expand Down
82 changes: 82 additions & 0 deletions local-tests/tests/testSignMessageWithSolanaEncryptedKey.ts
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import {
importPrivateKey,
signMessageWithEncryptedKey,
signMessageWithSolanaEncryptedKeyLitActionIpfsCid,
} from '@lit-protocol/wrapped-keys';
import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
import nacl from 'tweetnacl';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';

/**
* Test Commands:
* ✅ NETWORK=cayenne yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
* ✅ NETWORK=manzano yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
* ✅ NETWORK=localchain yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
*/
export const testSignMessageWithSolanaEncryptedKey = async (
devEnv: TinnyEnvironment
) => {
const alice = await devEnv.createRandomPerson();

const pkpSessionSigs = await getPkpSessionSigs(
devEnv,
alice,
null,
new Date(Date.now() + 1000 * 60 * 10).toISOString()
); // 10 mins expiry

console.log(pkpSessionSigs);

const solanaKeypair = Keypair.generate();
const privateKey = Buffer.from(solanaKeypair.secretKey).toString('hex');

const pkpAddress = await importPrivateKey({
pkpSessionSigs,
privateKey,
litNodeClient: devEnv.litNodeClient,
});

const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress;
if (pkpAddress !== alicePkpAddress) {
throw new Error(
`Received address: ${pkpAddress} doesn't match Alice's PKP address: ${alicePkpAddress}`
);
}

const pkpSessionSigsSigning = await getPkpSessionSigs(
devEnv,
alice,
null,
new Date(Date.now() + 1000 * 60 * 10).toISOString()
); // 10 mins expiry

console.log(pkpSessionSigsSigning);

const messageToSign = 'This is a test message';

const signature = await signMessageWithEncryptedKey({
pkpSessionSigs: pkpSessionSigsSigning,
ipfsCid: signMessageWithSolanaEncryptedKeyLitActionIpfsCid,
messageToSign,
litNodeClient: devEnv.litNodeClient,
});

console.log('signature');
console.log(signature);

const signatureIsValidForPublicKey = nacl.sign.detached.verify(
Buffer.from(messageToSign),
bs58.decode(signature),
solanaKeypair.publicKey.toBuffer()
);

if (!signatureIsValidForPublicKey)
throw new Error(
`signature: ${signature} doesn't validate for the Solana public key: ${solanaKeypair.publicKey.toString()}`
);

log('✅ testSignMessageWithSolanaEncryptedKey');
};
110 changes: 110 additions & 0 deletions local-tests/tests/testSignTransactionWithSolanaEncryptedKey.ts
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import {
SolanaLitTransaction,
importPrivateKey,
signTransactionWithEncryptedKey,
signTransactionWithSolanaEncryptedKeyLitActionIpfsCid,
} from '@lit-protocol/wrapped-keys';
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
Transaction,
clusterApiUrl,
} from '@solana/web3.js';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';

/**
* Test Commands:
* ✅ NETWORK=cayenne yarn test:local --filter=testSignTransactionWithSolanaEncryptedKey
* ✅ NETWORK=manzano yarn test:local --filter=testSignTransactionWithSolanaEncryptedKey
* ✅ NETWORK=localchain yarn test:local --filter=testSignTransactionWithSolanaEncryptedKey
*/
export const testSignTransactionWithSolanaEncryptedKey = async (
devEnv: TinnyEnvironment
) => {
const alice = await devEnv.createRandomPerson();

const pkpSessionSigs = await getPkpSessionSigs(
devEnv,
alice,
null,
new Date(Date.now() + 1000 * 60 * 10).toISOString()
); // 10 mins expiry

console.log(pkpSessionSigs);

const solanaKeypair = Keypair.generate();
const privateKey = Buffer.from(solanaKeypair.secretKey).toString('hex');

const pkpAddress = await importPrivateKey({
pkpSessionSigs,
privateKey,
litNodeClient: devEnv.litNodeClient,
});

const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress;
if (pkpAddress !== alicePkpAddress) {
throw new Error(
`Received address: ${pkpAddress} doesn't match Alice's PKP address: ${alicePkpAddress}`
);
}

const pkpSessionSigsSigning = await getPkpSessionSigs(
devEnv,
alice,
null,
new Date(Date.now() + 1000 * 60 * 10).toISOString()
); // 10 mins expiry

const solanaTransaction = new Transaction();
solanaTransaction.add(
SystemProgram.transfer({
fromPubkey: solanaKeypair.publicKey,
toPubkey: new PublicKey(solanaKeypair.publicKey),
lamports: LAMPORTS_PER_SOL / 100, // Transfer 0.01 SOL
})
);
solanaTransaction.feePayer = solanaKeypair.publicKey;
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved

const solanaConnection = new Connection(clusterApiUrl('devnet'), 'confirmed');
const { blockhash } = await solanaConnection.getLatestBlockhash();
solanaTransaction.recentBlockhash = blockhash;
DashKash54 marked this conversation as resolved.
Show resolved Hide resolved

const serializedTransaction = solanaTransaction
.serialize({
requireAllSignatures: false, // should be false as we're not signing the message
verifySignatures: false, // should be false as we're not signing the message
})
.toString('base64');

const unsignedTransaction: SolanaLitTransaction = {
serializedTransaction,
chain: 'devnet',
};

const signedTx = await signTransactionWithEncryptedKey({
pkpSessionSigs: pkpSessionSigsSigning,
ipfsCid: signTransactionWithSolanaEncryptedKeyLitActionIpfsCid,
unsignedTransaction,
broadcast: false,
litNodeClient: devEnv.litNodeClient,
});

console.log('signedTx');
console.log(signedTx);

const signatureBuffer = Buffer.from(signedTx, 'base64');
solanaTransaction.addSignature(solanaKeypair.publicKey, signatureBuffer);

if (!solanaTransaction.verifySignatures()) {
throw new Error(
`Signature: ${signedTx} doesn't validate for the Solana transaction.`
);
}

log('✅ testSignMessageWithSolanaEncryptedKey');
};
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
"@nx/plugin": "17.3.0",
"@nx/react": "17.3.0",
"@nx/web": "17.3.0",
"@solana/web3.js": "^1.92.2",
"@swc/core": "1.3.107",
"@synthetixio/synpress": "^2.3.3",
"@tableland/sdk": "^4.5.3",
Expand All @@ -166,6 +167,7 @@
"@typescript-eslint/parser": "6.21.0",
"babel-jest": "27.5.1",
"body-parser": "^1.20.2",
"buffer": "^6.0.3",
"chalk": "^5.3.0",
"cypress": "11.0.1",
"cypress-metamask": "^1.0.5-development",
Expand All @@ -184,6 +186,7 @@
"eslint-plugin-react-hooks": "4.6.0",
"ethereum-abi-types-generator": "^1.3.2",
"express": "^4.18.2",
"ipfs-unixfs-importer": "12.0.1",
"inquirer": "^9.2.21",
"jest": "27.5.1",
"lerna": "^5.4.3",
Expand All @@ -203,8 +206,7 @@
"ts-jest": "29.1.2",
"ts-node": "10.9.1",
"typedoc": "^0.23.10",
"typescript": "~4.7.2",
"ipfs-unixfs-importer": "12.0.1"
"typescript": "~4.7.2"
},
"workspaces": [
"packages/*"
Expand Down
2 changes: 2 additions & 0 deletions packages/wrapped-keys/buffer.shim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { Buffer } from 'buffer';
globalThis.Buffer = Buffer;
15 changes: 15 additions & 0 deletions packages/wrapped-keys/esbuild.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const esbuild = require('esbuild');

(async () => {
await esbuild.build({
entryPoints: [
'./src/lib/litActions/solana/src/signTransactionWithSolanaEncryptedKey.js',
'./src/lib/litActions/solana/src/signMessageWithSolanaEncryptedKey.js',
],
bundle: true,
minify: true,
sourcemap: false,
outdir: './src/lib/litActions/solana/dist',
inject: ['./buffer.shim.js'],
});
})();
4 changes: 4 additions & 0 deletions packages/wrapped-keys/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
"genReact": false
},
"version": "6.0.2-wrapped-keys.beta.1",
"scripts": {
"bundle": "yarn node ./esbuild.config.js",
"postinstall": "yarn bundle"
},
"main": "./dist/src/index.js",
"typings": "./dist/src/index.d.ts"
}
8 changes: 7 additions & 1 deletion packages/wrapped-keys/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export * from './lib/wrapped-keys';
export * from './lib/litActions';
export * from './lib/litActions/ethereum';
export * from './lib/interfaces';

export const signTransactionWithSolanaEncryptedKeyLitActionIpfsCid =
'QmSi9GL2weCFEP1SMAUw5PDpZRr436Zt3tLUNrSECPA5dT';

export const signMessageWithSolanaEncryptedKeyLitActionIpfsCid =
'QmYQC6cd4EMvyB4XPkfEEAwNXJupRZWU5JsTCUrjey4ovp';
16 changes: 10 additions & 6 deletions packages/wrapped-keys/src/lib/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,36 @@ export interface ExportPrivateKeyResponse {

export interface SignMessageWithEncryptedKeyParams {
pkpSessionSigs: SessionSigsMap;
litActionCode: string; // TODO!: Update to use ipfsCid only when the Lit Actions are published
unsignedMessage: string | Uint8Array;
litActionCode?: string; // TODO!: Update to use ipfsCid only when the Lit Actions are published
ipfsCid?: string;
messageToSign: string | Uint8Array;
litNodeClient: ILitNodeClient;
}

export interface SignTransactionWithEncryptedKeyParams<T> {
pkpSessionSigs: SessionSigsMap;
litActionCode: string; // TODO!: Update to use ipfsCid only when the Lit Actions are published
litActionCode?: string; // TODO!: Update to use ipfsCid only when the Lit Actions are published
ipfsCid?: string;
unsignedTransaction: T;
broadcast: boolean;
litNodeClient: ILitNodeClient;
}

interface BaseLitTransaction {
toAddress: string;
value: string;
chain: string;
}

export interface EthereumLitTransaction extends BaseLitTransaction {
toAddress: string;
value: string;
chainId: number;
gasPrice?: string;
gasLimit?: number;
dataHex?: string;
}

export interface SolanaLitTransaction extends BaseLitTransaction {}
export interface SolanaLitTransaction extends BaseLitTransaction {
serializedTransaction: string;
}

export type LitTransaction = EthereumLitTransaction | SolanaLitTransaction;
Loading
Loading