Skip to content

Commit 2cca281

Browse files
rodrigopavezicoderabbitai[bot]MantisClone
authored
feat: refactor lit protocol provider (#1512)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: MantisClone <david.huntmateo@request.network>
1 parent 1873e14 commit 2cca281

File tree

18 files changed

+614
-315
lines changed

18 files changed

+614
-315
lines changed

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@
2828
"publish-manual-prerelease": "lerna publish prerelease --conventional-commits --conventional-prerelease --exact --no-git-tag-version --no-push --preid next --no-verify-access --dist-tag next",
2929
"publish-prerelease": "FORCE_PUBLISH=$(lerna changed --json | jq '. | map(.name) | join (\",\")' -r) && echo $FORCE_PUBLISH && lerna publish --conventional-commits --conventional-prerelease --exact --no-git-tag-version --no-push --preid next --no-verify-access --dist-tag next --yes --force-publish=${FORCE_PUBLISH}",
3030
"deploy:contracts": "yarn workspace @requestnetwork/smart-contracts deploy",
31-
"start:request-node": "yarn workspace @requestnetwork/request-node start",
31+
"start:request-node": "LIT_PROTOCOL_NETWORK=datil-dev yarn workspace @requestnetwork/request-node start",
3232
"test": "lerna run test",
3333
"format": "prettier . -w",
3434
"format:check": "prettier . -c",
35-
"link:all": "for d in packages/*; do cd $d; yarn link; cd -; done",
36-
"unlink:all": "for d in packages/*; do cd $d; yarn unlink; cd -; done"
35+
"link:all-npm": "for d in packages/*; do cd $d; npm link; cd -; done",
36+
"unlink:all-npm": "for d in packages/*; do cd $d; npm unlink; cd -; done",
37+
"link:all-yarn": "for d in packages/*; do cd $d; yarn link; cd -; done",
38+
"unlink:all-yarn": "for d in packages/*; do cd $d; yarn unlink; cd -; done"
3739
},
3840
"devDependencies": {
3941
"@typescript-eslint/eslint-plugin": "4.18.0",

packages/ethereum-storage/test/ipfs-manager.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import IpfsManager from '../src/ipfs-manager';
33
import { setupServer } from 'msw/node';
44
import { HttpResponse, delay, http } from 'msw';
55

6+
jest.setTimeout(30000);
67
const testErrorHandling: StorageTypes.IIpfsErrorHandlingConfiguration = {
78
delayBetweenRetries: 0,
89
maxRetries: 0,

packages/integration-test/jest.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// The error ReferenceError: crypto is not defined occurs because the Node.js environment needs the crypto module to be explicitly available.
2+
// For Node.js versions before 19, you need to add the crypto global explicitly.
3+
const { webcrypto } = require('crypto');
4+
global.crypto = webcrypto;
5+
16
const jestCommonConfig = require('../../jest.config');
27

38
/** @type {import('jest').Config} */

packages/integration-test/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,19 @@
2929
"build": "tsc -b tsconfig.build.json",
3030
"clean": "rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo",
3131
"lint": "eslint \"test/**/*.ts\"",
32-
"test": "run-s test:node test:layers",
32+
"test": "run-s test:lit test:node test:layers",
3333
"test:scheduled": "run-s test:erc20 test:any test:erc777 test:eth test:btc ",
3434
"test:layers": "jest test/layers.test.ts --forceExit",
3535
"test:node": "jest test/node-client.test.ts --forceExit",
3636
"test:any": "jest test/scheduled/any*.test.ts --forceExit",
3737
"test:eth": "jest test/scheduled/eth*.test.ts --forceExit",
3838
"test:erc20": "jest test/scheduled/erc20*.test.ts --forceExit",
3939
"test:erc777": "jest test/scheduled/erc777*.test.ts --forceExit",
40-
"test:btc": "jest test/scheduled/btc.test.ts --forceExit"
40+
"test:btc": "jest test/scheduled/btc.test.ts --forceExit",
41+
"test:lit": "jest test/lit-protocol.test.ts --forceExit"
4142
},
4243
"devDependencies": {
44+
"@lit-protocol/lit-node-client": "7.0.2",
4345
"@requestnetwork/advanced-logic": "0.47.0",
4446
"@requestnetwork/currency": "0.21.0",
4547
"@requestnetwork/data-access": "0.38.0",
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import { EthereumPrivateKeySignatureProvider } from '@requestnetwork/epk-signature';
2+
import { LitProtocolCipherProvider } from '@requestnetwork/lit-protocol-cipher';
3+
import { RequestNetwork, Types, Utils } from '@requestnetwork/request-client.js';
4+
import { ethers } from 'ethers';
5+
import { LitNodeClient } from '@lit-protocol/lit-node-client';
6+
7+
jest.setTimeout(30000);
8+
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
9+
10+
async function waitForConfirmation(request: any, maxAttempts = 10, delayMs = 1000): Promise<void> {
11+
let attempts = 0;
12+
while (attempts < maxAttempts) {
13+
try {
14+
const data = await request.getData();
15+
if (data.state === Types.RequestLogic.STATE.CREATED) {
16+
console.log(`Request confirmed with state: ${data.state}`);
17+
return;
18+
}
19+
console.log(
20+
`Attempt ${attempts + 1}: Request not confirmed yet. Current state: ${data.state}`,
21+
);
22+
} catch (error) {
23+
console.log(`Attempt ${attempts + 1} failed:`, error);
24+
}
25+
await sleep(delayMs);
26+
attempts++;
27+
}
28+
throw new Error(`Request not confirmed after ${maxAttempts} attempts`);
29+
}
30+
31+
describe('Lit Protocol Integration Tests', () => {
32+
let requestNetwork: RequestNetwork;
33+
let litProvider: LitProtocolCipherProvider;
34+
let epkSignatureProvider: EthereumPrivateKeySignatureProvider;
35+
let userWallet: ethers.Wallet;
36+
let litClient: LitNodeClient;
37+
38+
const nodeConnectionConfig = {
39+
baseURL: 'http://localhost:3000',
40+
headers: {
41+
'Content-Type': 'application/json',
42+
},
43+
};
44+
45+
beforeAll(async () => {
46+
// Create wallet
47+
userWallet = new ethers.Wallet(
48+
'0x7b595b2bb732edddc4d4fe758ae528c7a748c40f0f6220f4494e214f15c5bfeb',
49+
);
50+
51+
// Initialize signature provider
52+
epkSignatureProvider = new EthereumPrivateKeySignatureProvider({
53+
method: Types.Signature.METHOD.ECDSA,
54+
privateKey: userWallet.privateKey,
55+
});
56+
57+
// Initialize Lit Protocol client
58+
litClient = new LitNodeClient({
59+
litNetwork: 'datil-dev',
60+
alertWhenUnauthorized: false,
61+
debug: false,
62+
});
63+
64+
// Initialize Lit Protocol provider
65+
litProvider = new LitProtocolCipherProvider(litClient, nodeConnectionConfig);
66+
await litProvider.initializeClient();
67+
await litProvider.enableDecryption(true);
68+
await litProvider.getSessionSignatures(userWallet, userWallet.address);
69+
70+
// Initialize Request Network client
71+
requestNetwork = new RequestNetwork({
72+
nodeConnectionConfig,
73+
signatureProvider: epkSignatureProvider,
74+
cipherProvider: litProvider,
75+
});
76+
}, 30000);
77+
78+
afterAll(async () => {
79+
try {
80+
// Get all pending promises
81+
const promises = [];
82+
if (litProvider) {
83+
promises.push(litProvider.disconnectClient());
84+
promises.push(litProvider.disconnectWallet());
85+
}
86+
if (litClient) {
87+
promises.push(litClient.disconnect());
88+
}
89+
90+
// Wait for all cleanup operations to complete
91+
await Promise.all(promises);
92+
} catch (error) {
93+
console.error('Cleanup error:', error);
94+
}
95+
});
96+
97+
it('should encrypt and decrypt data directly', async () => {
98+
const testData = 'test encryption';
99+
const encryptionParams = [
100+
{
101+
key: userWallet.address,
102+
method: Types.Encryption.METHOD.KMS,
103+
},
104+
];
105+
106+
const encrypted = await litProvider.encrypt(testData, { encryptionParams });
107+
expect(encrypted).toBeDefined();
108+
expect(encrypted?.ciphertext).toBeDefined();
109+
expect(encrypted?.dataToEncryptHash).toBeDefined();
110+
111+
const decrypted = await litProvider.decrypt(encrypted!, { encryptionParams });
112+
expect(decrypted).toBe(testData);
113+
});
114+
115+
it('should create and encrypt a request', async () => {
116+
const requestParams = {
117+
requestInfo: {
118+
currency: {
119+
type: Types.RequestLogic.CURRENCY.ETH,
120+
value: '0x0000000000000000000000000000000000000000',
121+
network: 'sepolia',
122+
},
123+
expectedAmount: ethers.utils.parseEther('0.1').toString(),
124+
payee: {
125+
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
126+
value: userWallet.address,
127+
},
128+
payer: {
129+
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
130+
value: '0xb07D2398d2004378cad234DA0EF14f1c94A530e4',
131+
},
132+
timestamp: Utils.getCurrentTimestampInSecond(),
133+
},
134+
paymentNetwork: {
135+
id: Types.Extension.PAYMENT_NETWORK_ID.ETH_FEE_PROXY_CONTRACT,
136+
parameters: {
137+
paymentNetworkName: 'sepolia',
138+
paymentAddress: userWallet.address,
139+
feeAddress: '0x0000000000000000000000000000000000000000',
140+
feeAmount: '0',
141+
tokenAddress: '0x0000000000000000000000000000000000000000',
142+
},
143+
},
144+
contentData: {
145+
meta: {
146+
format: 'rnf_invoice',
147+
version: '0.0.3',
148+
},
149+
creationDate: new Date().toISOString(),
150+
invoiceNumber: 'INV-2023-001',
151+
invoiceItems: [
152+
{
153+
name: 'Test Service',
154+
quantity: 1,
155+
unitPrice: ethers.utils.parseEther('0.1').toString(),
156+
discount: '0',
157+
tax: {
158+
type: 'percentage',
159+
amount: '0',
160+
},
161+
currency: 'ETH',
162+
},
163+
],
164+
},
165+
signer: {
166+
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
167+
value: userWallet.address,
168+
},
169+
};
170+
171+
const encryptionParams = [
172+
{
173+
key: userWallet.address,
174+
method: Types.Encryption.METHOD.KMS,
175+
},
176+
];
177+
178+
const encryptedRequest = await requestNetwork._createEncryptedRequest(
179+
requestParams as Types.ICreateRequestParameters,
180+
encryptionParams,
181+
);
182+
183+
await waitForConfirmation(encryptedRequest, 15, 2000);
184+
185+
const requestData = await encryptedRequest.getData();
186+
expect(requestData).toBeDefined();
187+
expect([Types.RequestLogic.STATE.CREATED]).toContain(requestData.state);
188+
});
189+
190+
it('should handle encryption errors gracefully', async () => {
191+
const invalidEncryptionParams = [
192+
{
193+
key: '',
194+
method: Types.Encryption.METHOD.KMS,
195+
},
196+
];
197+
198+
await expect(
199+
litProvider.encrypt('test data', { encryptionParams: invalidEncryptionParams }),
200+
).rejects.toThrow(/invalid.*key/i);
201+
});
202+
203+
it('should handle decryption errors gracefully', async () => {
204+
const invalidEncryptedData = {
205+
ciphertext: 'invalid-ciphertext',
206+
dataToEncryptHash: 'invalid-hash',
207+
};
208+
209+
await expect(
210+
litProvider.decrypt(invalidEncryptedData, {
211+
encryptionParams: [
212+
{
213+
key: userWallet.address,
214+
method: Types.Encryption.METHOD.KMS,
215+
},
216+
],
217+
}),
218+
).rejects.toThrow();
219+
});
220+
});

packages/integration-test/tsconfig.build.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
{ "path": "../ethereum-storage/tsconfig.build.json" },
1313
{ "path": "../epk-decryption/tsconfig.build.json" },
1414
{ "path": "../epk-signature/tsconfig.build.json" },
15+
{ "path": "../lit-protocol-cipher/tsconfig.build.json" },
1516
{ "path": "../multi-format/tsconfig.build.json" },
1617
{ "path": "../payment-processor/tsconfig.build.json" },
1718
{ "path": "../request-logic/tsconfig.build.json" },

packages/lit-protocol-cipher/README.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# @requestnetwork/lit-protocol-cipher
22

3-
Lit Protocol Provider.
3+
Lit Protocol Provider for Request Network.
44

5-
`@requestnetwork/lit-protocol-cipher` is a typescript library part of the [Request Network protocol](https://github.com/RequestNetwork/requestNetwork).
5+
`@requestnetwork/lit-protocol-cipher` is a typescript library part of the [Request Network protocol](https://github.com/RequestNetwork/requestNetwork) that provides encryption and decryption capabilities using the Lit Protocol.
66

77
## Installation
88

@@ -12,22 +12,33 @@ npm install @requestnetwork/lit-protocol-cipher
1212

1313
## Usage
1414

15-
The `LitProvider` class provides encryption and decryption capabilities using the Lit Protocol. Here's how to implement and use it:
15+
The `LitProtocolCipherProvider` class provides encryption and decryption capabilities using the Lit Protocol. Here's how to implement and use it:
1616

1717
```typescript
1818
import { ethers } from 'ethers';
19-
import LitProvider from './LitProvider';
19+
import { LitProtocolCipherProvider } from '@requestnetwork/lit-protocol-cipher';
2020
import { LIT_NETWORKS } from '@lit-protocol/types';
21+
import { LitNodeClient } from '@lit-protocol/lit-node-client';
2122

2223
// Initialize the provider
23-
const litProvider = new LitProvider(
24-
'ethereum', // chain
25-
LIT_NETWORKS.MAINNET, // network
24+
const litProvider = new LitProtocolCipherProvider(
25+
new LitNodeClient({
26+
litNetwork: LIT_NETWORKS.datil,
27+
}),
2628
{
27-
nodeUrl: 'https://your-request-network-node.com',
29+
baseURL: 'https://gnosis.gateway.request.network',
30+
headers: {
31+
'Content-Type': 'application/json',
32+
},
2833
}, // nodeConnectionConfig
2934
);
3035

36+
// Initialize the client
37+
await litProvider.initializeClient();
38+
39+
// Enable decryption
40+
await litProvider.enableDecryption(true);
41+
3142
// Example usage with wallet connection
3243
async function example() {
3344
try {
@@ -70,11 +81,11 @@ async function example() {
7081
const parsedData = JSON.parse(decryptedData);
7182
console.log('Decrypted data:', parsedData);
7283
}
73-
74-
// Disconnect wallet when done
75-
await litProvider.disconnectWallet();
7684
} catch (error) {
7785
console.error('Error:', error);
86+
} finally {
87+
// Disconnect wallet when done
88+
await litProvider.disconnectWallet();
7889
}
7990
}
8091

packages/lit-protocol-cipher/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@
4040
"test:watch": "yarn test --watch"
4141
},
4242
"dependencies": {
43-
"@lit-protocol/auth-helpers": "7.0.0",
44-
"@lit-protocol/constants": "7.0.0",
43+
"@lit-protocol/auth-helpers": "7.0.2",
44+
"@lit-protocol/constants": "7.0.2",
4545
"@lit-protocol/contracts": "0.0.74",
46-
"@lit-protocol/encryption": "7.0.0",
47-
"@lit-protocol/lit-node-client": "7.0.0",
48-
"@lit-protocol/lit-node-client-nodejs": "7.0.0",
49-
"@lit-protocol/types": "7.0.0",
46+
"@lit-protocol/encryption": "7.0.2",
47+
"@lit-protocol/lit-node-client": "7.0.2",
48+
"@lit-protocol/lit-node-client-nodejs": "7.0.2",
49+
"@lit-protocol/types": "7.0.2",
5050
"@requestnetwork/request-client.js": "0.52.0",
5151
"@requestnetwork/types": "0.47.0",
5252
"@walletconnect/modal": "2.7.0",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { default as LitProtocolProvider } from './lit-protocol-cipher-provider';
1+
export { default as LitProtocolCipherProvider } from './lit-protocol-cipher-provider';

0 commit comments

Comments
 (0)