Skip to content

Commit 8bbb0bf

Browse files
committed
Merge branch 'staging/v7' into feature/lit-3748-naga
2 parents 1adf2d0 + a7d5f6a commit 8bbb0bf

File tree

55 files changed

+1537
-567
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1537
-567
lines changed

local-tests/setup/tinny-environment.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ export class TinnyEnvironment {
188188
return { privateKey: this.processEnvs.PRIVATE_KEYS[index], index }; // Return the key and its index
189189
} else {
190190
console.log('[𐬺🧪 Tinny Environment𐬺] No available keys. Waiting...', {
191-
privateKeys: this.processEnvs.PRIVATE_KEYS,
192191
keysInUse: this.processEnvs.KEY_IN_USE,
193192
}); // Log a message indicating that we are waiting
194193
// Wait for the specified interval before checking again
@@ -448,8 +447,9 @@ export class TinnyEnvironment {
448447
* @throws If there is an error sending the funds.
449448
*/
450449
getFunds = async (walletAddress: string, amount = '0.001') => {
450+
const privateKey = await this.getAvailablePrivateKey();
451+
451452
try {
452-
const privateKey = await this.getAvailablePrivateKey();
453453
const provider = new ethers.providers.JsonRpcBatchProvider(this.rpc);
454454
const wallet = new ethers.Wallet(privateKey.privateKey, provider);
455455

@@ -461,6 +461,9 @@ export class TinnyEnvironment {
461461
await tx.wait();
462462
} catch (e) {
463463
throw new Error(`Failed to send funds to ${walletAddress}: ${e}`);
464+
} finally {
465+
// @ts-expect-error We don't have a user, but this works
466+
this.releasePrivateKeyFromUser({ privateKey });
464467
}
465468
};
466469

local-tests/test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ import { testFailImportWrappedKeysWithExpiredSessionSig } from './tests/wrapped-
102102
import { testExportWrappedKey } from './tests/wrapped-keys/testExportWrappedKey';
103103
import { testSignMessageWithSolanaEncryptedKey } from './tests/wrapped-keys/testSignMessageWithSolanaEncryptedKey';
104104
import { testSignTransactionWithSolanaEncryptedKey } from './tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey';
105+
import { testBatchGeneratePrivateKeys } from './tests/wrapped-keys/testBatchGeneratePrivateKeys';
106+
107+
import { setLitActionsCodeToLocal } from './tests/wrapped-keys/util';
108+
import { testUseEoaSessionSigsToRequestSingleResponse } from './tests/testUseEoaSessionSigsToRequestSingleResponse';
109+
110+
// Use the current LIT action code to test against
111+
setLitActionsCodeToLocal();
105112

106113
(async () => {
107114
console.log('[𐬺🧪 Tinny𐬺] Running tests...');
@@ -116,6 +123,7 @@ import { testSignTransactionWithSolanaEncryptedKey } from './tests/wrapped-keys/
116123
// --filter=WrappedKey
117124
const wrappedKeysTests = {
118125
// -- valid cases
126+
testBatchGeneratePrivateKeys,
119127
testEthereumSignMessageGeneratedKey,
120128
testEthereumBroadcastTransactionGeneratedKey,
121129
testEthereumSignMessageWrappedKey,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { getEoaSessionSigs } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
2+
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
3+
4+
/**
5+
* Test Commands:
6+
* ✅ NETWORK=datil-dev yarn test:local --filter=testUseEoaSessionSigsToRequestSingleResponse
7+
* ✅ NETWORK=datil-test yarn test:local --filter=testUseEoaSessionSigsToRequestSingleResponse
8+
* ✅ NETWORK=datil yarn test:local --filter=testUseEoaSessionSigsToRequestSingleResponse
9+
*/
10+
export const testUseEoaSessionSigsToRequestSingleResponse = async (
11+
devEnv: TinnyEnvironment
12+
) => {
13+
const alice = await devEnv.createRandomPerson();
14+
15+
try {
16+
const eoaSessionSigs = await getEoaSessionSigs(devEnv, alice);
17+
18+
const res = await devEnv.litNodeClient.executeJs({
19+
sessionSigs: eoaSessionSigs,
20+
code: `(async () => {
21+
console.log('hello world')
22+
})();`,
23+
useSingleNode: true,
24+
});
25+
26+
console.log('res:', res);
27+
28+
// Expected output:
29+
// {
30+
// success: true,
31+
// signedData: {},
32+
// decryptedData: {},
33+
// claimData: {},
34+
// response: "",
35+
// logs: "hello world\n",
36+
// }
37+
38+
// -- assertions
39+
if (res.response) {
40+
throw new Error(`Expected "response" to be falsy`);
41+
}
42+
43+
if (!res.logs) {
44+
throw new Error(`Expected "logs" in res`);
45+
}
46+
47+
if (!res.logs.includes('hello world')) {
48+
throw new Error(`Expected "logs" to include 'hello world'`);
49+
}
50+
51+
if (!res.success) {
52+
throw new Error(`Expected "success" in res`);
53+
}
54+
} finally {
55+
devEnv.releasePrivateKeyFromUser(alice);
56+
}
57+
};
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { log } from '@lit-protocol/misc';
2+
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
3+
import { api } from '@lit-protocol/wrapped-keys';
4+
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
5+
import nacl from 'tweetnacl';
6+
import bs58 from 'bs58';
7+
import { ethers } from 'ethers';
8+
import { BatchGeneratePrivateKeysActionResult } from '../../../packages/wrapped-keys/src/lib/types';
9+
10+
const { batchGeneratePrivateKeys, exportPrivateKey } = api;
11+
12+
async function verifySolanaSignature(
13+
solanaResult: BatchGeneratePrivateKeysActionResult,
14+
solanaMessageToSign
15+
) {
16+
const {
17+
signMessage: { signature },
18+
generateEncryptedPrivateKey: { generatedPublicKey },
19+
} = solanaResult;
20+
const signatureIsValidForPublicKey = nacl.sign.detached.verify(
21+
Buffer.from(solanaMessageToSign),
22+
bs58.decode(signature),
23+
bs58.decode(generatedPublicKey)
24+
);
25+
26+
console.log({ signatureIsValidForPublicKey, signature });
27+
if (!signatureIsValidForPublicKey) {
28+
throw new Error(
29+
`signature: ${signature} doesn't validate for the Solana public key: ${generatedPublicKey}`
30+
);
31+
}
32+
}
33+
async function verifyEvmSignature(evmResult, messageToSign) {
34+
function verifyMessageSignature() {
35+
try {
36+
return ethers.utils.verifyMessage(
37+
messageToSign,
38+
evmResult.signMessage.signature
39+
);
40+
} catch (err) {
41+
throw new Error(
42+
`When validating signed Ethereum message is valid: ${err.message}`
43+
);
44+
}
45+
}
46+
47+
const walletAddress = ethers.utils.computeAddress(
48+
evmResult.generateEncryptedPrivateKey.generatedPublicKey
49+
);
50+
51+
const recoveredAddress = verifyMessageSignature();
52+
53+
console.log({
54+
recoveredAddress,
55+
walletAddress,
56+
signature: evmResult.signMessage.signature,
57+
});
58+
if (recoveredAddress !== walletAddress) {
59+
throw new Error(
60+
"Recovered address from verifyMessage doesn't match the wallet address"
61+
);
62+
}
63+
}
64+
65+
/**
66+
* Test Commands:
67+
* ✅ NETWORK=datil-dev yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
68+
* ✅ NETWORK=datil-test yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
69+
* ✅ NETWORK=localchain yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
70+
*/
71+
export const testBatchGeneratePrivateKeys = async (
72+
devEnv: TinnyEnvironment
73+
) => {
74+
const alice = await devEnv.createRandomPerson();
75+
76+
try {
77+
const pkpSessionSigsSigning = await getPkpSessionSigs(
78+
devEnv,
79+
alice,
80+
null,
81+
new Date(Date.now() + 1000 * 60 * 10).toISOString()
82+
); // 10 mins expiry
83+
84+
const solanaMessageToSign = 'This is a test solana message';
85+
const evmMessageToSign = 'This is a test evm message';
86+
const { results } = await batchGeneratePrivateKeys({
87+
pkpSessionSigs: pkpSessionSigsSigning,
88+
actions: [
89+
{
90+
network: 'evm',
91+
signMessageParams: { messageToSign: evmMessageToSign },
92+
generateKeyParams: { memo: 'Test evm key' },
93+
},
94+
{
95+
network: 'solana',
96+
signMessageParams: { messageToSign: solanaMessageToSign },
97+
generateKeyParams: { memo: 'Test solana key' },
98+
},
99+
],
100+
litNodeClient: devEnv.litNodeClient,
101+
});
102+
103+
if (results.length !== 2) {
104+
throw new Error(
105+
`Incorrect # of results; expected 2, got ${results.length}`
106+
);
107+
}
108+
109+
if (
110+
results[0].generateEncryptedPrivateKey.memo !== 'Test evm key' ||
111+
results[1].generateEncryptedPrivateKey.memo !== 'Test solana key'
112+
) {
113+
throw new Error(
114+
'Results not in order sent; expected evm as first result, solana as second'
115+
);
116+
}
117+
118+
if (
119+
!results[0].signMessage.signature ||
120+
!results[1].signMessage.signature
121+
) {
122+
throw new Error('Missing message signature in response');
123+
}
124+
125+
console.log('solana verify sig');
126+
await verifySolanaSignature(results[1], solanaMessageToSign);
127+
128+
console.log('evm verify sig');
129+
await verifyEvmSignature(results[0], evmMessageToSign);
130+
console.log('results', results);
131+
132+
log('✅ testBatchGenerateEncryptedKeys');
133+
} catch (err) {
134+
console.log(err.message, err, err.stack);
135+
throw err;
136+
} finally {
137+
devEnv.releasePrivateKeyFromUser(alice);
138+
}
139+
};

local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,7 @@ export const testFailEthereumSignTransactionWrappedKeyWithInvalidParam = async (
7070
id,
7171
});
7272
} catch (e: any) {
73-
if (
74-
e.message.includes(
75-
'Error executing the Signing Lit Action: Error: When signing transaction- invalid hexlify value'
76-
)
77-
) {
73+
if (e.message.includes('invalid hexlify value')) {
7874
console.log('✅ THIS IS EXPECTED: ', e);
7975
console.log(e.message);
8076
console.log(

local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,7 @@ export const testFailEthereumSignTransactionWrappedKeyWithMissingParam = async (
6666
id,
6767
});
6868
} catch (e: any) {
69-
if (
70-
e.message.includes(
71-
'Error executing the Signing Lit Action: Error: Missing required field: toAddress'
72-
)
73-
) {
69+
if (e.message.includes('Missing required field: toAddress')) {
7470
console.log('✅ THIS IS EXPECTED: ', e);
7571
console.log(e.message);
7672
console.log(

local-tests/tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
clusterApiUrl,
1212
} from '@solana/web3.js';
1313
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
14+
import { ethers } from 'ethers';
1415

1516
const { importPrivateKey, signTransactionWithEncryptedKey } = api;
1617

@@ -125,7 +126,7 @@ export const testSignTransactionWithSolanaEncryptedKey = async (
125126
// const confirmation = await solanaConnection.confirmTransaction(signedTx);
126127
// console.log(confirmation); // { context: { slot: 321490379 }, value: { err: null } }
127128

128-
const signatureBuffer = Buffer.from(signedTx, 'base64');
129+
const signatureBuffer = Buffer.from(ethers.utils.base58.decode(signedTx));
129130
solanaTransaction.addSignature(solanaKeypair.publicKey, signatureBuffer);
130131

131132
if (!solanaTransaction.verifySignatures()) {

local-tests/tests/wrapped-keys/util.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,50 @@
11
import { LIT_NETWORKS_KEYS } from '@lit-protocol/types';
22
import { LIT_CHAINS } from '@lit-protocol/constants';
33
import { ethers } from 'ethers';
4-
import { EthereumLitTransaction } from '@lit-protocol/wrapped-keys';
4+
import { config } from '@lit-protocol/wrapped-keys';
5+
import {
6+
litActionRepositoryCommon,
7+
litActionRepository,
8+
} from '@lit-protocol/wrapped-keys-lit-actions';
9+
10+
import type {
11+
LitActionCodeRepository,
12+
LitActionCodeRepositoryCommon,
13+
EthereumLitTransaction,
14+
} from '@lit-protocol/wrapped-keys';
15+
16+
const emptyLitActionRepositoryCommon: LitActionCodeRepositoryCommon = {
17+
batchGenerateEncryptedKeys: '',
18+
};
19+
20+
const emptyLitActionRepository: LitActionCodeRepository = {
21+
signTransaction: {
22+
evm: '',
23+
solana: '',
24+
},
25+
signMessage: {
26+
evm: '',
27+
solana: '',
28+
},
29+
generateEncryptedKey: {
30+
evm: '',
31+
solana: '',
32+
},
33+
exportPrivateKey: {
34+
evm: '',
35+
solana: '',
36+
},
37+
};
38+
39+
export function resetLitActionsCode() {
40+
config.setLitActionsCodeCommon(emptyLitActionRepositoryCommon);
41+
config.setLitActionsCode(emptyLitActionRepository);
42+
}
43+
44+
export function setLitActionsCodeToLocal() {
45+
config.setLitActionsCodeCommon(litActionRepositoryCommon);
46+
config.setLitActionsCode(litActionRepository);
47+
}
548

649
export function getChainForNetwork(network: LIT_NETWORKS_KEYS): {
750
chain: string;

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"@cosmjs/proto-signing": "0.30.1",
4141
"@cosmjs/stargate": "0.30.1",
4242
"@dotenvx/dotenvx": "^1.6.4",
43-
"@lit-protocol/accs-schemas": "^0.0.13",
43+
"@lit-protocol/accs-schemas": "^0.0.14",
4444
"@lit-protocol/contracts": "^0.0.63",
4545
"@metamask/eth-sig-util": "5.0.2",
4646
"@mysten/sui.js": "^0.37.1",
@@ -91,6 +91,7 @@
9191
"@types/secp256k1": "^4.0.6",
9292
"@typescript-eslint/eslint-plugin": "6.21.0",
9393
"@typescript-eslint/parser": "6.21.0",
94+
"axios": "^1.6.0",
9495
"babel-jest": "27.5.1",
9596
"buffer": "^6.0.3",
9697
"chalk": "^5.3.0",

packages/constants/src/lib/constants/constants.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,17 @@ export const LIT_CHAINS: LITChain<LITEVMChain> = {
759759
type: null,
760760
vmType: 'EVM',
761761
},
762+
storyProtocolTestnet: {
763+
contractAddress: null,
764+
chainId: 1513,
765+
name: 'Story Protocol Testnet',
766+
symbol: 'IP',
767+
decimals: 18,
768+
rpcUrls: ['https://testnet.storyrpc.io'],
769+
blockExplorerUrls: ['https://testnet.storyscan.xyz'],
770+
type: null,
771+
vmType: 'EVM',
772+
},
762773
};
763774

764775
/**

0 commit comments

Comments
 (0)