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

feat: refactor lit protocol provider #1512

Merged
merged 31 commits into from
Dec 13, 2024
Merged
Changes from 11 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
650095e
feat: integrate Lit Protocol with enhanced testing and configuration …
rodrigopavezi Dec 5, 2024
153667e
fix: readme
rodrigopavezi Dec 5, 2024
0a4a75d
Update .circleci/config.yml
rodrigopavezi Dec 5, 2024
a64801f
fix: build
rodrigopavezi Dec 5, 2024
7eb71e1
fix: build giving more memory
rodrigopavezi Dec 5, 2024
1b3f85e
fix: memory issu
rodrigopavezi Dec 5, 2024
11a4e86
fix: out of memory issue
rodrigopavezi Dec 6, 2024
0229d47
chore: upgrade lit protocol sdk version
rodrigopavezi Dec 6, 2024
b953258
fix: package lint
rodrigopavezi Dec 6, 2024
c48b7f6
fix: as per review
rodrigopavezi Dec 6, 2024
14a6aed
Update packages/lit-protocol-cipher/README.md
rodrigopavezi Dec 6, 2024
e1d6c49
fix: revert memory change
rodrigopavezi Dec 9, 2024
42c83d5
Update packages/lit-protocol-cipher/src/lit-protocol-cipher-provider.ts
rodrigopavezi Dec 9, 2024
50aca1a
Update README.md
rodrigopavezi Dec 9, 2024
e64f15b
fix: rename LitProtocolCipherProvider
rodrigopavezi Dec 9, 2024
c73fb44
fix: update lit integration test
rodrigopavezi Dec 9, 2024
c216c24
fix: duplicate files
rodrigopavezi Dec 10, 2024
0a481cc
Merge branch 'master' into refactor/lit-protocol-provider
rodrigopavezi Dec 10, 2024
e48d2ee
fix: tests
rodrigopavezi Dec 10, 2024
af6c986
Merge branch 'refactor/lit-protocol-provider' of https://github.com/R…
rodrigopavezi Dec 10, 2024
8ba492f
Merge branch 'master' into refactor/lit-protocol-provider
rodrigopavezi Dec 10, 2024
605154e
refactor: add lit-protocol-cipher tsconfig and rename provider class
rodrigopavezi Dec 11, 2024
7fb3bae
refactor: enhance encryption parameter validation and condition creation
rodrigopavezi Dec 13, 2024
586467d
Merge branch 'master' into refactor/lit-protocol-provider
rodrigopavezi Dec 13, 2024
5b89fac
chore: update @lit-protocol packages to version 7.0.2
rodrigopavezi Dec 13, 2024
c19db75
fix: add crypto module for Node.js compatibility in jest config
rodrigopavezi Dec 13, 2024
f7c4825
chore: reorder test script execution in integration-test package.json
rodrigopavezi Dec 13, 2024
c3c771a
Update packages/integration-test/test/lit-protocol.test.ts
rodrigopavezi Dec 13, 2024
4975d24
fix: format
rodrigopavezi Dec 13, 2024
4100d89
fix: test timeouts
rodrigopavezi Dec 13, 2024
a847618
fix: per review
rodrigopavezi Dec 13, 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
26 changes: 7 additions & 19 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@ references:
image_name: &image_name 'cimg/python:3.7'
node_image: &node_image
image: cimg/node:18.18
environment:
NODE_OPTIONS: '--max-old-space-size=8192'
ipfs_image: &ipfs_image
image: requestnetwork/request-ipfs:v0.13.0
ganache_image: &ganache_image
@@ -60,6 +62,7 @@ jobs:
build:
docker:
- *node_image
resource_class: large
working_directory: *working_directory
steps:
- checkout
@@ -76,23 +79,8 @@ jobs:
paths:
- ~/.cache/yarn
- run:
name: Build types
command: yarn workspace @requestnetwork/types run build
- run:
name: Build utils
command: yarn workspace @requestnetwork/utils run build
- run:
name: Build currency
command: yarn workspace @requestnetwork/currency run build
- run:
name: Generate Smart Contract types
command: yarn workspace @requestnetwork/smart-contracts run build
- run:
name: Generate Payment Detection queries
command: yarn workspace @requestnetwork/payment-detection run codegen
- run:
name: Build all packages (tsc)
command: yarn build:tsc
name: Build all packages
command: yarn build --skip-nx-cache

- persist_to_workspace:
root: *working_directory
@@ -391,7 +379,7 @@ jobs:
- run: *step_graph_deploy
- run:
name: 'Start request-node'
command: 'yarn workspace @requestnetwork/request-node run start'
command: 'yarn start:request-node'
background: true
- run: *step_wait_for_node
- run:
@@ -496,7 +484,7 @@ jobs:
- run: *step_graph_deploy
- run:
name: 'Start request-node'
command: 'yarn workspace @requestnetwork/request-node run start'
command: 'yarn start:request-node'
background: true
- run: *step_wait_for_node
- run:
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -27,12 +27,14 @@
"publish-manual-prerelease": "lerna publish prerelease --conventional-commits --exact",
"publish-prerelease": "yarn lerna publish --preid development --skip-git --yes --canary",
"deploy:contracts": "yarn workspace @requestnetwork/smart-contracts deploy",
"start:request-node": "yarn workspace @requestnetwork/request-node start",
"start:request-node": "LIT_PROTOCOL_NETWORK=datil-dev yarn workspace @requestnetwork/request-node start",
"test": "lerna run test --concurrency=1",
"format": "prettier . -w",
"format:check": "prettier . -c",
"link:all": "for d in packages/*; do cd $d; yarn link; cd -; done",
"unlink:all": "for d in packages/*; do cd $d; yarn unlink; cd -; done"
"link:all-npm": "for d in packages/*; do cd $d; npm link; cd -; done",
"unlink:all-npm": "for d in packages/*; do cd $d; npm unlink; cd -; done",
"link:all-yarn": "for d in packages/*; do cd $d; yarn link; cd -; done",
"unlink:all-yarn": "for d in packages/*; do cd $d; yarn unlink; cd -; done"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "4.18.0",
5 changes: 3 additions & 2 deletions packages/integration-test/package.json
Original file line number Diff line number Diff line change
@@ -29,15 +29,16 @@
"build": "tsc -b tsconfig.build.json",
"clean": "rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo",
"lint": "eslint \"test/**/*.ts\"",
"test": "run-s test:node test:layers",
"test": "run-s test:node test:layers test:lit",
"test:scheduled": "run-s test:erc20 test:any test:erc777 test:eth test:btc ",
"test:layers": "jest test/layers.test.ts --forceExit",
"test:node": "jest test/node-client.test.ts --forceExit",
"test:any": "jest test/scheduled/any*.test.ts --forceExit",
"test:eth": "jest test/scheduled/eth*.test.ts --forceExit",
"test:erc20": "jest test/scheduled/erc20*.test.ts --forceExit",
"test:erc777": "jest test/scheduled/erc777*.test.ts --forceExit",
"test:btc": "jest test/scheduled/btc.test.ts --forceExit"
"test:btc": "jest test/scheduled/btc.test.ts --forceExit",
"test:lit": "jest test/lit-protocol.test.ts --forceExit"
},
"devDependencies": {
"@requestnetwork/advanced-logic": "0.47.0",
239 changes: 239 additions & 0 deletions packages/integration-test/test/lit-protocol.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
import { EthereumPrivateKeySignatureProvider } from '@requestnetwork/epk-signature';
import { LitProtocolProvider } from '@requestnetwork/lit-protocol-cipher';
import { RequestNetwork, Types, Utils } from '@requestnetwork/request-client.js';
import { ethers } from 'ethers';
import { LitNodeClient } from '@lit-protocol/lit-node-client';

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

async function waitForConfirmation(request: any, maxAttempts = 10, delayMs = 1000): Promise<void> {
let attempts = 0;
while (attempts < maxAttempts) {
try {
const data = await request.getData();
if (
data.state === Types.RequestLogic.STATE.CREATED ||
data.state === Types.RequestLogic.STATE.PENDING
) {
console.log(`Request confirmed with state: ${data.state}`);
return;
}
console.log(
`Attempt ${attempts + 1}: Request not confirmed yet. Current state: ${data.state}`,
);
} catch (error) {
console.log(`Attempt ${attempts + 1} failed:`, error);
}
await sleep(delayMs);
attempts++;
}
throw new Error(`Request not confirmed after ${maxAttempts} attempts`);
}

describe('Lit Protocol Integration Tests', () => {
let requestNetwork: RequestNetwork;
let litProvider: LitProtocolProvider;
let epkSignatureProvider: EthereumPrivateKeySignatureProvider;
let userWallet: ethers.Wallet;
let litClient: LitNodeClient;

const nodeConnectionConfig = {
baseURL: 'http://localhost:3000',
headers: {
'Content-Type': 'application/json',
},
};

beforeAll(async () => {
// Create wallet
userWallet = ethers.Wallet.createRandom();

// Initialize signature provider
epkSignatureProvider = new EthereumPrivateKeySignatureProvider({
method: Types.Signature.METHOD.ECDSA,
privateKey: userWallet.privateKey,
});

// Initialize Lit Protocol client
litClient = new LitNodeClient({
litNetwork: 'datil-dev',
alertWhenUnauthorized: false,
debug: false,
});

// Initialize Lit Protocol provider
litProvider = new LitProtocolProvider(litClient, nodeConnectionConfig);
await litProvider.initializeClient();
await litProvider.enableDecryption(true);
await litProvider.getSessionSignatures(userWallet, userWallet.address);

// Initialize Request Network client
requestNetwork = new RequestNetwork({
nodeConnectionConfig,
signatureProvider: epkSignatureProvider,
cipherProvider: litProvider,
});
}, 30000);

afterAll(async () => {
try {
// Get all pending promises
const promises = [];
if (litProvider) {
promises.push(litProvider.disconnectClient());
promises.push(litProvider.disconnectWallet());
}
if (litClient) {
promises.push(litClient.disconnect());
}

// Wait for all cleanup operations to complete
await Promise.all(promises);
} catch (error) {
console.error('Cleanup error:', error);
}
});

it('should encrypt and decrypt data directly', async () => {
const testData = 'test encryption';
const encryptionParams = [
{
key: userWallet.address,
method: Types.Encryption.METHOD.KMS,
},
];

const encrypted = await litProvider.encrypt(testData, { encryptionParams });
expect(encrypted).toBeDefined();
expect(encrypted?.ciphertext).toBeDefined();
expect(encrypted?.dataToEncryptHash).toBeDefined();

const decrypted = await litProvider.decrypt(encrypted!, { encryptionParams });
expect(decrypted).toBe(testData);
});

it('should create and encrypt a request', async () => {
const requestParams = {
requestInfo: {
currency: {
type: Types.RequestLogic.CURRENCY.ETH,
value: '0x0000000000000000000000000000000000000000',
network: 'sepolia',
},
expectedAmount: ethers.utils.parseEther('0.1').toString(),
payee: {
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
value: userWallet.address,
},
payer: {
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
value: '0xb07D2398d2004378cad234DA0EF14f1c94A530e4',
},
timestamp: Utils.getCurrentTimestampInSecond(),
},
paymentNetwork: {
id: Types.Extension.PAYMENT_NETWORK_ID.ETH_FEE_PROXY_CONTRACT,
parameters: {
paymentNetworkName: 'sepolia',
paymentAddress: userWallet.address,
feeAddress: '0x0000000000000000000000000000000000000000',
feeAmount: '0',
tokenAddress: '0x0000000000000000000000000000000000000000',
},
},
contentData: {
meta: {
format: 'rnf_invoice',
version: '0.0.3',
},
creationDate: new Date().toISOString(),
invoiceNumber: 'INV-2023-001',
invoiceItems: [
{
name: 'Test Service',
quantity: 1,
unitPrice: ethers.utils.parseEther('0.1').toString(),
discount: '0',
tax: {
type: 'percentage',
amount: '0',
},
currency: 'ETH',
},
],
},
signer: {
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
value: userWallet.address,
},
};

const encryptionParams = [
{
key: userWallet.address,
method: Types.Encryption.METHOD.KMS,
},
];

const encryptedRequest = await requestNetwork._createEncryptedRequest(
requestParams as Types.ICreateRequestParameters,
encryptionParams,
);

await waitForConfirmation(encryptedRequest, 15, 2000);

const requestData = await encryptedRequest.getData();
expect(requestData).toBeDefined();
expect([Types.RequestLogic.STATE.CREATED, Types.RequestLogic.STATE.PENDING]).toContain(
requestData.state,
);

// Wait for any pending operations to complete
await new Promise((resolve) => setTimeout(resolve, 1000));
});

it('should handle encryption errors gracefully', async () => {
const invalidEncryptionParams = [
{
key: '',
method: Types.Encryption.METHOD.KMS,
},
];

// Mock the validation function to throw an error
const originalValidation = litProvider['getLitAccessControlConditions'];
try {
litProvider['getLitAccessControlConditions'] = jest.fn().mockImplementation(() => {
throw new Error('Invalid encryption parameter at index 0: missing key');
});

await expect(async () => {
await litProvider.encrypt('test data', { encryptionParams: invalidEncryptionParams });
}).rejects.toThrow('Invalid encryption parameter at index 0: missing key');
} finally {
// Restore original validation
litProvider['getLitAccessControlConditions'] = originalValidation;
}
});

it('should handle decryption errors gracefully', async () => {
const invalidEncryptedData = {
ciphertext: 'invalid-ciphertext',
dataToEncryptHash: 'invalid-hash',
};

await expect(
litProvider.decrypt(invalidEncryptedData, {
encryptionParams: [
{
key: userWallet.address,
method: Types.Encryption.METHOD.KMS,
},
],
}),
).rejects.toThrow();

// Wait for any pending operations to complete
await new Promise((resolve) => setTimeout(resolve, 1000));
});
});
30 changes: 22 additions & 8 deletions packages/lit-protocol-cipher/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# @requestnetwork/lit-protocol-cipher

Lit Protocol Provider.
Lit Protocol Provider for Request Network.

`@requestnetwork/lit-protocol-cipher` is a typescript library part of the [Request Network protocol](https://github.com/RequestNetwork/requestNetwork).
`@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.

## Installation

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

## Usage

The `LitProvider` class provides encryption and decryption capabilities using the Lit Protocol. Here's how to implement and use it:
The `LitProtocolProvider` class provides encryption and decryption capabilities using the Lit Protocol. Here's how to implement and use it:

```typescript
import { ethers } from 'ethers';
import LitProvider from './LitProvider';
import { LitProtocolProvider } from '@requestnetwork/lit-protocol-cipher';
import { LIT_NETWORKS } from '@lit-protocol/types';
import { LitNodeClient } from '@lit-protocol/lit-node-client';

// Initialize the provider
const litProvider = new LitProvider(
'ethereum', // chain
LIT_NETWORKS.MAINNET, // network
const litProvider = new LitProtocolProvider(
new LitNodeClient({
litNetwork: LIT_NETWORKS.datil,
}),
{
nodeUrl: 'https://your-request-network-node.com',
baseURL: 'https://gnosis.gateway.request.network',
headers: {
'Content-Type': 'application/json',
},
}, // nodeConnectionConfig
);

// Initialize the client
await litProvider.initializeClient();

// Enable decryption
await litProvider.enableDecryption(true);

// Example usage with wallet connection
async function example() {
try {
@@ -75,6 +86,9 @@ async function example() {
await litProvider.disconnectWallet();
} catch (error) {
console.error('Error:', error);
} finally {
// Disconnect wallet when done
await litProvider.disconnectWallet();
}
}

Loading