Skip to content

Commit dfbc148

Browse files
author
Josh Long
committed
Merge branch 'feature/lit-2921-js-sdk-migrate-to-jest' of github.com:LIT-Protocol/js-sdk into feat/long-running-epoch-testing
2 parents b9dfe68 + f595894 commit dfbc148

File tree

113 files changed

+2453
-896
lines changed

Some content is hidden

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

113 files changed

+2453
-896
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#Default reviewers
2-
* @joshLong145 @Ansonhkg
2+
* @Ansonhkg

jest.setup.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require('dotenv').config({ path: '../../.env' });
2+
console.log('loaded configuration from .env');
13
const crypto = require('crypto');
24

35
global.TextEncoder = require('util').TextEncoder;

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
33
"useNx": true,
44
"useWorkspaces": true,
5-
"version": "6.5.3"
5+
"version": "6.10.0"
66
}
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 } = 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+
};
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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 { batchGenerateKeysWithLitAction } from '../../../packages/wrapped-keys/src/lib/lit-actions-client';
6+
import { getLitActionCodeOrCidCommon } from '../../../packages/wrapped-keys/src/lib/lit-actions-client/utils';
7+
import {
8+
getFirstSessionSig,
9+
getKeyTypeFromNetwork,
10+
getPkpAccessControlCondition,
11+
getPkpAddressFromSessionSig,
12+
} from '../../../packages/wrapped-keys/src/lib/api/utils';
13+
import { listEncryptedKeyMetadata } from '../../../packages/wrapped-keys/src/lib/api';
14+
15+
const { storeEncryptedKeyBatch } = api;
16+
17+
/**
18+
* Test Commands:
19+
* ✅ NETWORK=datil-dev yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
20+
* ✅ NETWORK=datil-test yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
21+
* ✅ NETWORK=localchain yarn test:local --filter=testSignMessageWithSolanaEncryptedKey
22+
*/
23+
export const testFailBatchGeneratePrivateKeysAtomic = async (
24+
devEnv: TinnyEnvironment
25+
) => {
26+
const alice = await devEnv.createRandomPerson();
27+
28+
try {
29+
const pkpSessionSigsSigning = await getPkpSessionSigs(
30+
devEnv,
31+
alice,
32+
null,
33+
new Date(Date.now() + 1000 * 60 * 10).toISOString()
34+
); // 10 mins expiry
35+
36+
const solanaMessageToSign = 'This is a test solana message';
37+
const evmMessageToSign = 'This is a test evm message';
38+
39+
const sessionSig = getFirstSessionSig(pkpSessionSigsSigning);
40+
const pkpAddress = getPkpAddressFromSessionSig(sessionSig);
41+
42+
const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress);
43+
44+
const { litActionCode, litActionIpfsCid } = getLitActionCodeOrCidCommon(
45+
'batchGenerateEncryptedKeys'
46+
);
47+
48+
const actionResults = await batchGenerateKeysWithLitAction({
49+
litNodeClient: devEnv.litNodeClient,
50+
litActionIpfsCid: litActionCode ? undefined : litActionIpfsCid,
51+
litActionCode: litActionCode ? litActionCode : undefined,
52+
accessControlConditions: [allowPkpAddressToDecrypt],
53+
actions: [
54+
{
55+
network: 'evm',
56+
signMessageParams: { messageToSign: evmMessageToSign },
57+
generateKeyParams: { memo: 'Test evm key' },
58+
},
59+
{
60+
network: 'solana',
61+
signMessageParams: { messageToSign: solanaMessageToSign },
62+
generateKeyParams: { memo: 'Test solana key' },
63+
},
64+
],
65+
pkpSessionSigs: pkpSessionSigsSigning,
66+
});
67+
68+
const keyParamsBatch = actionResults.map((keyData) => {
69+
const { generateEncryptedPrivateKey, network } = keyData;
70+
return {
71+
...generateEncryptedPrivateKey,
72+
keyType: getKeyTypeFromNetwork(network),
73+
};
74+
});
75+
76+
// Intentional failure to persist due to missing publicKey
77+
delete keyParamsBatch[0].publicKey;
78+
79+
try {
80+
await storeEncryptedKeyBatch({
81+
pkpSessionSigs: pkpSessionSigsSigning,
82+
litNodeClient: devEnv.litNodeClient,
83+
keyBatch: keyParamsBatch,
84+
});
85+
86+
throw new Error(
87+
'storeEncryptedKeyBatch() succeeded but we expected it to fail!'
88+
);
89+
} catch (err) {
90+
// We expect `storeEncryptedKeyBatch` to fail w/ a specific error
91+
if (
92+
err.message.includes(
93+
'storeEncryptedKeyBatch() succeeded but we expected it to fail!'
94+
) ||
95+
!err.message.includes(
96+
'keyParamsBatch[0]: Missing "publicKey" parameter in request'
97+
)
98+
) {
99+
throw err;
100+
}
101+
102+
try {
103+
const keys = await listEncryptedKeyMetadata({
104+
litNodeClient: devEnv.litNodeClient,
105+
pkpSessionSigs: pkpSessionSigsSigning,
106+
});
107+
108+
console.error(
109+
'Got a value back we shouldnt have from listEncryptedKeyMetadata()',
110+
keys
111+
);
112+
113+
throw new Error(
114+
'Expected `listEncryptedKeyMetadata() to fail, but it didnt!`'
115+
);
116+
} catch (err) {
117+
if (err.message.includes('No keys exist for pkpAddress')) {
118+
log('✅ testFailBatchGeneratePrivateKeysAtomic');
119+
} else {
120+
throw err;
121+
}
122+
}
123+
}
124+
} catch (err) {
125+
console.log(err.message, err, err.stack);
126+
throw err;
127+
} finally {
128+
devEnv.releasePrivateKeyFromUser(alice);
129+
}
130+
};

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"@cosmjs/proto-signing": "0.30.1",
4444
"@cosmjs/stargate": "0.30.1",
4545
"@dotenvx/dotenvx": "^1.6.4",
46-
"@lit-protocol/accs-schemas": "^0.0.12",
46+
"@lit-protocol/accs-schemas": "^0.0.15",
4747
"@lit-protocol/contracts": "^0.0.63",
4848
"@metamask/eth-sig-util": "5.0.2",
4949
"@mysten/sui.js": "^0.37.1",
@@ -58,7 +58,6 @@
5858
"@walletconnect/utils": "2.9.2",
5959
"@walletconnect/web3wallet": "1.8.8",
6060
"ajv": "^8.12.0",
61-
"axios": "^0.27.2",
6261
"base64url": "^3.0.1",
6362
"bitcoinjs-lib": "^6.1.0",
6463
"bs58": "^5.0.0",
@@ -102,6 +101,7 @@
102101
"@types/secp256k1": "^4.0.6",
103102
"@typescript-eslint/eslint-plugin": "6.21.0",
104103
"@typescript-eslint/parser": "6.21.0",
104+
"axios": "^1.6.0",
105105
"babel-jest": "27.5.1",
106106
"body-parser": "^1.20.2",
107107
"buffer": "^6.0.3",
@@ -122,6 +122,7 @@
122122
"eslint-plugin-react-hooks": "4.6.0",
123123
"ethereum-abi-types-generator": "^1.3.2",
124124
"express": "^4.18.2",
125+
"form-data": "^4.0.0",
125126
"inquirer": "^9.2.21",
126127
"ipfs-unixfs-importer": "12.0.1",
127128
"jest": "29.7.0",

packages/access-control-conditions/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"tags": [
2222
"universal"
2323
],
24-
"version": "6.5.3",
24+
"version": "6.10.0",
2525
"main": "./dist/src/index.js",
2626
"typings": "./dist/src/index.d.ts"
2727
}

packages/auth-browser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"tags": [
3131
"browser"
3232
],
33-
"version": "6.5.3",
33+
"version": "6.10.0",
3434
"main": "./dist/src/index.js",
3535
"typings": "./dist/src/index.d.ts"
3636
}

0 commit comments

Comments
 (0)