diff --git a/.ctx/generate-local-network-context.md b/.ctx/generate-local-network-context.md
new file mode 100644
index 0000000000..604854131b
--- /dev/null
+++ b/.ctx/generate-local-network-context.md
@@ -0,0 +1,35 @@
+# Generating Local Network Context for Lit Protocol
+
+The Lit network contexts, which include smart contract addresses and ABIs, typically come from the `@lit-protocol/contracts` package (a separate repository at https://github.com/LIT-Protocol/lit-contracts/). However, these contexts are designed for established networks.
+
+## Local Network Setup
+
+For local development (running Lit nodes on your machine), you need to generate a `networkContext.json` file in the `lit-assets` directory. This is typically done by running the deploy script after starting your local Anvil chain.
+
+## Version Compatibility Changes
+
+In version 7 or earlier, you could simply copy and paste the `networkContext.json` file, and it would work when setting the network to `custom` when running with Tinny (E2E test suite).
+
+However, in version 8, we've optimised by removing redundant and unused ABIs from the JSON file and enforced strongly typed ABIs. This optimization introduced an additional conversion layer that extracts only the necessary ABI methods, which must be run manually for local network contexts.
+
+## Generating Custom Context
+
+To generate the proper context:
+
+1. Locate the `getCustomContext` file in the network-specific folder (in this case, `vNaga/naga-develop` folder)
+2. Use the `generateSignaturesFromContext` helper function from the `@lit-protocol/contracts` repository
+
+Here's an example of how to use this function:
+
+```ts
+import { generateSignaturesFromContext } from '@lit-protocol/contracts/custom-network-signatures';
+
+await generateSignaturesFromContext({
+ jsonFilePath:
+ '/Users/anson/Projects/lit-assets/blockchain/contracts/networkContext.json', // in lit assets repo
+ networkName: 'naga-develop',
+ outputDir: './naga-develop-signatures',
+ useScriptDirectory: true,
+ callerPath: import.meta.url,
+});
+```
diff --git a/.ctx/v7-to-v8-migration-notes.md b/.ctx/v7-to-v8-migration-notes.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/.gitignore b/.gitignore
index 16c59f020c..e53043ad0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,4 +77,6 @@ local-tests/build
packages/wrapped-keys-lit-actions/src/generated
digest
-generate-digest.ts
\ No newline at end of file
+generate-digest.ts
+
+.cursor/rules
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 69a63afb63..a0883a5f11 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,8 +3,8 @@
"todo-tree.tree.scanMode": "workspace",
"conventionalCommits.scopes": [
"contracts-sdk",
- "lit-node-client-nodejs",
- "core",
+ "lit-node-client",
+ "core"
],
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#2f7c47",
@@ -52,4 +52,4 @@
// ]
// }
// ]
-}
\ No newline at end of file
+}
diff --git a/README.md b/README.md
index 147bb24a8e..9984acab2b 100644
--- a/README.md
+++ b/README.md
@@ -50,38 +50,37 @@ yarn add @lit-protocol/lit-node-client
-| Package | Category | Download |
-| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| [@lit-protocol/lit-node-client-nodejs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client-nodejs) |  |
|
-| [@lit-protocol/lit-node-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client) |  |
|
+| Package | Category | Download |
+| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [@lit-protocol/lit-node-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client) |  |
|
If you're a tech-savvy user and wish to utilize only specific submodules that our main module relies upon, you can find individual packages listed below. This way, you can import only the necessary packages that cater to your specific use case::
-| Package | Category | Download |
-| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| [@lit-protocol/access-control-conditions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions) |  |
|
-| [@lit-protocol/auth-helpers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-helpers) |  |
|
-| [@lit-protocol/constants](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/constants) |  |
|
-| [@lit-protocol/contracts-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/contracts-sdk) |  |
|
-| [@lit-protocol/core](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/core) |  |
|
-| [@lit-protocol/crypto](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/crypto) |  |
|
-| [@lit-protocol/encryption](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/encryption) |  |
|
-| [@lit-protocol/event-listener](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/event-listener) |  |
|
-| [@lit-protocol/logger](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/logger) |  |
|
-| [@lit-protocol/misc](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc) |  |
|
-| [@lit-protocol/nacl](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/nacl) |  |
|
-| [@lit-protocol/pkp-base](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-base) |  |
|
-| [@lit-protocol/pkp-cosmos](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-cosmos) |  |
|
-| [@lit-protocol/pkp-ethers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-ethers) |  |
|
-| [@lit-protocol/pkp-sui](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-sui) |  |
|
-| [@lit-protocol/pkp-walletconnect](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-walletconnect) |  |
|
-| [@lit-protocol/types](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/types) |  |
|
-| [@lit-protocol/uint8arrays](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/uint8arrays) |  |
|
-| [@lit-protocol/wasm](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wasm) |  |
|
-| [@lit-protocol/wrapped-keys](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wrapped-keys) |  |
|
-| [@lit-protocol/wrapped-keys-lit-actions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wrapped-keys-lit-actions) |  |
|
-| [@lit-protocol/auth-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-browser) |  |
|
-| [@lit-protocol/misc-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc-browser) |  |
|
+| Package | Category | Download |
+| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [@lit-protocol/access-control-conditions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions) |  |
|
+| [@lit-protocol/access-control-conditions-schemas](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions-schemas) |  |
|
+| [@lit-protocol/auth](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth) |  |
|
+| [@lit-protocol/auth-helpers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-helpers) |  |
|
+| [@lit-protocol/constants](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/constants) |  |
|
+| [@lit-protocol/contracts-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/contracts-sdk) |  |
|
+| [@lit-protocol/core](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/core) |  |
|
+| [@lit-protocol/crypto](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/crypto) |  |
|
+| [@lit-protocol/event-listener](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/event-listener) |  |
|
+| [@lit-protocol/lit-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-client) |  |
|
+| [@lit-protocol/logger](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/logger) |  |
|
+| [@lit-protocol/networks](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/networks) |  |
|
+| [@lit-protocol/pkp-base](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-base) |  |
|
+| [@lit-protocol/pkp-cosmos](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-cosmos) |  |
|
+| [@lit-protocol/pkp-ethers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-ethers) |  |
|
+| [@lit-protocol/pkp-sui](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-sui) |  |
|
+| [@lit-protocol/pkp-walletconnect](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-walletconnect) |  |
|
+| [@lit-protocol/schemas](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/schemas) |  |
|
+| [@lit-protocol/types](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/types) |  |
|
+| [@lit-protocol/wasm](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wasm) |  |
|
+| [@lit-protocol/wrapped-keys](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wrapped-keys) |  |
|
+| [@lit-protocol/wrapped-keys-lit-actions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wrapped-keys-lit-actions) |  |
|
+| [@lit-protocol/misc-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc-browser) |  |
|
@@ -100,7 +99,7 @@ If you're a tech-savvy user and wish to utilize only specific submodules that ou
## Prerequisite
-- node (v19.x or above)
+- node (v20.x or above)
- rust (v1.70.00 or above)
- [wasm-pack](https://github.com/rustwasm/wasm-pack)
diff --git a/jest.setup.js b/jest.setup.js
index f44e2a7ef9..d2f1c82f82 100644
--- a/jest.setup.js
+++ b/jest.setup.js
@@ -3,3 +3,22 @@ const crypto = require('crypto');
global.TextEncoder = require('util').TextEncoder;
global.TextDecoder = require('util').TextDecoder;
global.crypto = crypto;
+
+if (!global.crypto.subtle) {
+ global.crypto.subtle = {
+ digest: async (algorithm, data) => {
+ const algo = algorithm.toLowerCase().replace('-', '');
+ const hash = crypto.createHash(algo);
+ hash.update(Buffer.from(data));
+ return hash.digest().buffer;
+ },
+ };
+}
+
+// If this is not included, you will get the following error when running it in Jest:
+// (Error) Details: Request is not defined
+// The problem is that Jest is running in a Node.js environment where the global Request API (part of the Fetch API) might not be available or properly configured. Bun, on the other hand, has this API built into its runtime by default, which is why it works.
+const { default: fetch, Request, Response } = require('node-fetch');
+global.fetch = fetch;
+global.Request = Request;
+global.Response = Response;
diff --git a/local-tests/README.md b/local-tests/README.md
index 8196ddc46b..de531ce201 100644
--- a/local-tests/README.md
+++ b/local-tests/README.md
@@ -122,21 +122,3 @@ The `TinnyPerson` class encapsulates various functionalities to manage wallet op
| `createCapacityDelegationAuthSig(addresses)` | Mints a Capacity Credits NFT and creates an authentication signature for delegating capacity, which can be used to authorize other addresses to use the minted credits. |
##
-
-# esbuild benchmark
-
-```ts
-// test-bundle-speed.ts
-export const testBundleSpeed = async (devEnv: TinnyEnvironment) => {
- const a = await import('@lit-protocol/lit-node-client');
- const b = await import('@lit-protocol/contracts-sdk');
- const c = await import('@lit-protocol/auth-helpers');
- const d = await import('@lit-protocol/constants');
- const e = await import('@lit-protocol/lit-auth-client');
-
- console.log(a, b, c, d, e);
-};
-// ----------------
-// Build time: 77ms
-// ----------------
-```
diff --git a/local-tests/package.json b/local-tests/package.json
index d4d06845a8..da3ef632ae 100644
--- a/local-tests/package.json
+++ b/local-tests/package.json
@@ -81,16 +81,14 @@
"synthetix-js": "^2.74.1",
"tslib": "^2.3.0",
"tweetnacl": "^1.0.3",
- "tweetnacl-util": "^0.15.1",
"uint8arrays": "^4.0.3",
"@openagenda/verror": "^3.1.4",
"ipfs-unixfs-importer": "12.0.1",
"@solana/web3.js": "^1.95.3",
"bech32": "^2.0.0",
"pako": "^2.1.0",
- "@lit-protocol/misc": "^7.0.0",
- "@lit-protocol/lit-node-client": "^7.0.0",
- "@lit-protocol/lit-auth-client": "^7.0.0",
+ "@lit-protocol/lit-node-client": "8.0.0-alpha.0",
+ "@lit-protocol/auth": "8.0.0-alpha.0",
"@lit-protocol/contracts": "^0.0.71"
}
}
diff --git a/local-tests/setup/networkContext.json b/local-tests/setup/networkContext.json
index e2e4f67f5f..82da5e588a 100644
--- a/local-tests/setup/networkContext.json
+++ b/local-tests/setup/networkContext.json
@@ -1,6 +1,6 @@
{
"Allowlist": {
- "address": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
+ "address": "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
"abi": [
{
"inputs": [],
@@ -231,7 +231,7 @@
"name": "Allowlist"
},
"LITToken": {
- "address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
+ "address": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"abi": [
{
"inputs": [
@@ -1279,7 +1279,7 @@
"name": "LITToken"
},
"Multisender": {
- "address": "0x4826533B4897376654Bb4d4AD88B7faFD0C98528",
+ "address": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029",
"abi": [
{
"anonymous": false,
@@ -1388,7 +1388,7 @@
"name": "Multisender"
},
"PKPHelper": {
- "address": "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc",
+ "address": "0x04C89607413713Ec9775E14b954286519d836FEf",
"abi": [
{
"inputs": [
@@ -2370,7 +2370,7 @@
"name": "PKPHelper"
},
"PKPNFT": {
- "address": "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
+ "address": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
"abi": [
{
"inputs": [
@@ -2895,6 +2895,19 @@
"name": "Transfer",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newTrustedForwarder",
+ "type": "address"
+ }
+ ],
+ "name": "TrustedForwarderSet",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
@@ -3168,6 +3181,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getTrustedForwarder",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "initialize",
@@ -3433,6 +3459,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "forwarder",
+ "type": "address"
+ }
+ ],
+ "name": "setTrustedForwarder",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -3574,7 +3613,7 @@
"name": "PKPNFT"
},
"PKPNFTMetadata": {
- "address": "0x5eb3Bc0a489C5A8288765d2336659EbCA68FCd00",
+ "address": "0x82e01223d51Eb87e16A03E24687EDF0F294da6f1",
"abi": [
{
"inputs": [
@@ -3732,7 +3771,7 @@
"name": "PKPNFTMetadata"
},
"PKPPermissions": {
- "address": "0xFD471836031dc5108809D173A067e8486B9047A3",
+ "address": "0xdbC43Ba45381e02825b14322cDdd15eC4B3164E6",
"abi": [
{
"inputs": [
@@ -4286,6 +4325,19 @@
"name": "RootHashUpdated",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newTrustedForwarder",
+ "type": "address"
+ }
+ ],
+ "name": "TrustedForwarderSet",
+ "type": "event"
+ },
{
"inputs": [
{
@@ -4687,6 +4739,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getTrustedForwarder",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -4945,6 +5010,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "forwarder",
+ "type": "address"
+ }
+ ],
+ "name": "setTrustedForwarder",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -5022,7 +5100,7 @@
"name": "PKPPermissions"
},
"PubkeyRouter": {
- "address": "0x70e0bA845a1A0F2DA3359C97E0285013525FFC49",
+ "address": "0x809d550fca64d94Bd9F66E60752A544199cfAC3D",
"abi": [
{
"inputs": [
@@ -5545,6 +5623,19 @@
"name": "ToggleEvent",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newTrustedForwarder",
+ "type": "address"
+ }
+ ],
+ "name": "TrustedForwarderSet",
+ "type": "event"
+ },
{
"inputs": [
{
@@ -5814,6 +5905,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getTrustedForwarder",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -5948,6 +6052,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "forwarder",
+ "type": "address"
+ }
+ ],
+ "name": "setTrustedForwarder",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -5982,7 +6099,7 @@
"name": "PubkeyRouter"
},
"Staking": {
- "address": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
+ "address": "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
"abi": [
{
"inputs": [
@@ -6375,11 +6492,6 @@
"stateMutability": "nonpayable",
"type": "function"
},
- {
- "inputs": [],
- "name": "CallerNotOwner",
- "type": "error"
- },
{
"inputs": [
{
@@ -6404,6 +6516,25 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
+ }
+ ],
+ "name": "getCurrentRealmIdForStakerAddress",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -6423,6 +6554,38 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
+ }
+ ],
+ "name": "getShawdowRealmIdForStakerAddress",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getUnassignedStakerAddresses",
+ "outputs": [
+ {
+ "internalType": "address[]",
+ "name": "",
+ "type": "address[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "getUnassignedValidators",
@@ -6471,18 +6634,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator[]",
@@ -6588,6 +6776,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "numRealms",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -6642,18 +6843,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator",
@@ -6664,11 +6890,31 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "CallerNotOwner",
+ "type": "error"
+ },
{
"inputs": [],
"name": "CallerNotOwnerOrDevopsAdmin",
"type": "error"
},
+ {
+ "inputs": [],
+ "name": "CannotStakeZero",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "InvalidNewSharePrice",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "InvalidSlashPercentage",
+ "type": "error"
+ },
{
"inputs": [
{
@@ -6680,6 +6926,22 @@
"name": "MustBeInNextValidatorSetLockedOrReadyForNextEpochState",
"type": "error"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "validator",
+ "type": "address"
+ },
+ {
+ "internalType": "address[]",
+ "name": "validatorsInNextEpoch",
+ "type": "address[]"
+ }
+ ],
+ "name": "ValidatorIsNotInNextEpoch",
+ "type": "error"
+ },
{
"anonymous": false,
"inputs": [
@@ -6975,13 +7237,13 @@
{
"indexed": false,
"internalType": "uint256",
- "name": "newMaxTripleCount",
+ "name": "newMaxPresignCount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
- "name": "newMinTripleCount",
+ "name": "newMinPresignCount",
"type": "uint256"
},
{
@@ -6993,7 +7255,7 @@
{
"indexed": false,
"internalType": "uint256",
- "name": "newMaxTripleConcurrency",
+ "name": "newMaxPresignConcurrency",
"type": "uint256"
},
{
@@ -7012,11 +7274,43 @@
{
"indexed": false,
"internalType": "address",
- "name": "newStakingTokenAddress",
+ "name": "newResolverContractAddress",
"type": "address"
}
],
- "name": "StakingTokenSet",
+ "name": "ResolverContractAddressSet",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "staker",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Staked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newStakingTokenAddress",
+ "type": "address"
+ }
+ ],
+ "name": "StakingTokenSet",
"type": "event"
},
{
@@ -7032,6 +7326,32 @@
"name": "StateChanged",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "staker",
+ "type": "address"
+ }
+ ],
+ "name": "ValidatorBanned",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "staker",
+ "type": "address"
+ }
+ ],
+ "name": "ValidatorKickedFromNextEpoch",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
@@ -7045,6 +7365,32 @@
"name": "ValidatorRejoinedNextEpoch",
"type": "event"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "staker",
+ "type": "address"
+ }
+ ],
+ "name": "addPermittedStaker",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "addRealm",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -7110,14 +7456,37 @@
{
"inputs": [
{
- "internalType": "address",
- "name": "validatorStakerAddress",
- "type": "address"
+ "internalType": "uint256",
+ "name": "source_realmId",
+ "type": "uint256"
},
{
"internalType": "uint256",
- "name": "amountToPenalize",
+ "name": "target_realmId",
"type": "uint256"
+ },
+ {
+ "internalType": "address[]",
+ "name": "target_validators",
+ "type": "address[]"
+ }
+ ],
+ "name": "adminSetupShadowSplicing",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "percentage",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
}
],
"name": "adminSlashValidator",
@@ -7148,6 +7517,24 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseRewardPool",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -7174,6 +7561,50 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseRewardPool",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "staker",
+ "type": "address"
+ }
+ ],
+ "name": "removePermittedStaker",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ }
+ ],
+ "name": "removeRealm",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -7317,6 +7748,16 @@
"internalType": "uint256",
"name": "minSelfStakeTimelock",
"type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minValidatorCountToClampMinimumThreshold",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minThresholdToClampAt",
+ "type": "uint256"
}
],
"internalType": "struct LibStakingStorage.GlobalConfig",
@@ -7329,6 +7770,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newResolverAddress",
+ "type": "address"
+ }
+ ],
+ "name": "setContractResolver",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -7458,6 +7912,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "bool",
+ "name": "permittedStakersOn",
+ "type": "bool"
+ }
+ ],
+ "name": "setPermittedStakersOn",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -7474,12 +7941,12 @@
},
{
"internalType": "uint256",
- "name": "maxTripleCount",
+ "name": "maxPresignCount",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "minTripleCount",
+ "name": "minPresignCount",
"type": "uint256"
},
{
@@ -7489,13 +7956,18 @@
},
{
"internalType": "uint256",
- "name": "maxTripleConcurrency",
+ "name": "maxPresignConcurrency",
"type": "uint256"
},
{
"internalType": "bool",
"name": "rpcHealthcheckEnabled",
"type": "bool"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minEpochForRewards",
+ "type": "uint256"
}
],
"internalType": "struct LibStakingStorage.RealmConfig",
@@ -7508,6 +7980,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "newTotalSupply",
+ "type": "uint256"
+ }
+ ],
+ "name": "setTokenTotalSupplyStandIn",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [],
"name": "CallerNotContract",
@@ -7523,11 +8008,6 @@
"name": "CannotModifyUnfrozen",
"type": "error"
},
- {
- "inputs": [],
- "name": "CannotStakeZero",
- "type": "error"
- },
{
"inputs": [],
"name": "CannotWithdrawFrozen",
@@ -7560,11 +8040,6 @@
"name": "InsufficientSelfStake",
"type": "error"
},
- {
- "inputs": [],
- "name": "InvalidNewSharePrice",
- "type": "error"
- },
{
"inputs": [],
"name": "InvalidRatio",
@@ -7675,6 +8150,11 @@
"name": "TimeLockNotMet",
"type": "error"
},
+ {
+ "inputs": [],
+ "name": "TooSoonToWithdraw",
+ "type": "error"
+ },
{
"inputs": [
{
@@ -7692,11 +8172,29 @@
{
"indexed": false,
"internalType": "address",
- "name": "newResolverContractAddress",
+ "name": "stakerAddress",
"type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "rewards",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "fromEpoch",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "toEpoch",
+ "type": "uint256"
}
],
- "name": "ResolverContractAddressSet",
+ "name": "FixedCostRewardsClaimed",
"type": "event"
},
{
@@ -7809,19 +8307,44 @@
"anonymous": false,
"inputs": [
{
- "indexed": true,
+ "indexed": false,
"internalType": "address",
- "name": "staker",
+ "name": "newTrustedForwarder",
+ "type": "address"
+ }
+ ],
+ "name": "TrustedForwarderSet",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "stakerAddress",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
- "name": "amount",
+ "name": "rewards",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "fromEpoch",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "toEpoch",
"type": "uint256"
}
],
- "name": "Staked",
+ "name": "ValidatorCommissionClaimed",
"type": "event"
},
{
@@ -7856,37 +8379,6 @@
"name": "Withdrawn",
"type": "event"
},
- {
- "inputs": [
- {
- "internalType": "address",
- "name": "staker",
- "type": "address"
- }
- ],
- "name": "addPermittedStaker",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [
- {
- "internalType": "uint256",
- "name": "percentage",
- "type": "uint256"
- },
- {
- "internalType": "address",
- "name": "stakerAddress",
- "type": "address"
- }
- ],
- "name": "adminSlashValidator",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
- },
{
"inputs": [
{
@@ -7925,6 +8417,24 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxNumberOfEpochsToClaim",
+ "type": "uint256"
+ }
+ ],
+ "name": "claimFixedCostRewards",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -7941,6 +8451,11 @@
"internalType": "uint256",
"name": "stakeRecordId",
"type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxNumberOfEpochsToClaim",
+ "type": "uint256"
}
],
"name": "claimStakeRewards",
@@ -7949,7 +8464,18 @@
"type": "function"
},
{
- "inputs": [],
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxNumberOfEpochsToClaim",
+ "type": "uint256"
+ }
+ ],
"name": "claimValidatorCommission",
"outputs": [],
"stateMutability": "nonpayable",
@@ -8023,7 +8549,17 @@
},
{
"internalType": "uint256",
- "name": "totalRewards",
+ "name": "totalStakeRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "validatorFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "validatorCommission",
"type": "uint256"
},
{
@@ -8074,46 +8610,89 @@
},
{
"internalType": "uint256",
- "name": "stakeRecordId",
+ "name": "rewardEpochNumber",
"type": "uint256"
- },
+ }
+ ],
+ "name": "getRewardEpochView",
+ "outputs": [
{
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "epochEnd",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "totalStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "totalStakeRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "validatorFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "validatorCommission",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "slope",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "slopeIncrease",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "validatorSharePrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "stakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "validatorSharePriceAtLastUpdate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "initial",
+ "type": "bool"
+ }
+ ],
+ "internalType": "struct LibStakingStorage.RewardEpoch",
+ "name": "",
+ "type": "tuple"
}
],
- "name": "increaseStakeRecordAmount",
- "outputs": [],
- "stateMutability": "nonpayable",
+ "stateMutability": "view",
"type": "function"
},
{
- "inputs": [
- {
- "internalType": "uint256",
- "name": "realmId",
- "type": "uint256"
- },
+ "inputs": [],
+ "name": "getTrustedForwarder",
+ "outputs": [
{
"internalType": "address",
- "name": "stakerAddress",
+ "name": "",
"type": "address"
- },
- {
- "internalType": "uint256",
- "name": "stakeRecordId",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "newTimeLock",
- "type": "uint256"
}
],
- "name": "increaseStakeRecordTimelock",
- "outputs": [],
- "stateMutability": "nonpayable",
+ "stateMutability": "view",
"type": "function"
},
{
@@ -8125,25 +8704,25 @@
},
{
"internalType": "uint256",
- "name": "rewardEpochNumber",
+ "name": "stakeRecordId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "additionalAmount",
"type": "uint256"
}
],
- "name": "initializeRewardEpoch",
+ "name": "increaseStakeRecordAmount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
- {
- "internalType": "uint256",
- "name": "realmId",
- "type": "uint256"
- },
{
"internalType": "address",
- "name": "userStakerAddress",
+ "name": "stakerAddress",
"type": "address"
},
{
@@ -8152,12 +8731,12 @@
"type": "uint256"
},
{
- "internalType": "address",
- "name": "newStakerAddress",
- "type": "address"
+ "internalType": "uint256",
+ "name": "additionalTimeLock",
+ "type": "uint256"
}
],
- "name": "migrateStakeRecord",
+ "name": "increaseStakeRecordTimelock",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
@@ -8166,80 +8745,76 @@
"inputs": [
{
"internalType": "address",
- "name": "staker",
+ "name": "stakerAddress",
"type": "address"
- }
- ],
- "name": "removePermittedStaker",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [
+ },
{
- "internalType": "address",
- "name": "newResolverAddress",
- "type": "address"
- }
- ],
- "name": "setContractResolver",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [
+ "internalType": "uint256",
+ "name": "rewardEpochNumber",
+ "type": "uint256"
+ },
{
"internalType": "bool",
- "name": "permittedStakersOn",
+ "name": "isInitial",
"type": "bool"
}
],
- "name": "setPermittedStakersOn",
+ "name": "initializeRewardEpoch",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
{
"internalType": "address",
- "name": "stakerAddress",
+ "name": "operatorAddressToMigrateFrom",
"type": "address"
},
{
"internalType": "uint256",
- "name": "rate",
+ "name": "stakeRecordId",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddressToMigrateTo",
+ "type": "address"
}
],
- "name": "setValidatorComissionRate",
+ "name": "migrateStakeRecord",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
- {
- "internalType": "uint256",
- "name": "percentage",
- "type": "uint256"
- },
{
"internalType": "address",
- "name": "stakerAddress",
+ "name": "forwarder",
"type": "address"
}
],
- "name": "slashValidator",
- "outputs": [
+ "name": "setTrustedForwarder",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{
"internalType": "uint256",
- "name": "",
+ "name": "rate",
"type": "uint256"
}
],
+ "name": "setValidatorCommissionRate",
+ "outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
@@ -8307,25 +8882,6 @@
"stateMutability": "nonpayable",
"type": "function"
},
- {
- "inputs": [
- {
- "internalType": "uint256",
- "name": "realmId",
- "type": "uint256"
- }
- ],
- "name": "updateRewardEpoch",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "currentRewardEpoch",
- "type": "uint256"
- }
- ],
- "stateMutability": "nonpayable",
- "type": "function"
- },
{
"inputs": [
{
@@ -8419,6 +8975,11 @@
"name": "CouldNotMapNodeAddressToStakerAddress",
"type": "error"
},
+ {
+ "inputs": [],
+ "name": "InvalidAttestedAddress",
+ "type": "error"
+ },
{
"inputs": [
{
@@ -8575,6 +9136,11 @@
"name": "SignaledReadyForWrongEpochNumber",
"type": "error"
},
+ {
+ "inputs": [],
+ "name": "StakerAddressMismatch",
+ "type": "error"
+ },
{
"inputs": [
{
@@ -8602,6 +9168,17 @@
"name": "TryingToWithdrawMoreThanStaked",
"type": "error"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "staker",
+ "type": "address"
+ }
+ ],
+ "name": "ValidatorAlreadyInNextValidatorSet",
+ "type": "error"
+ },
{
"inputs": [
{
@@ -8622,16 +9199,11 @@
"inputs": [
{
"internalType": "address",
- "name": "validator",
+ "name": "staker",
"type": "address"
- },
- {
- "internalType": "address[]",
- "name": "validatorsInNextEpoch",
- "type": "address[]"
}
],
- "name": "ValidatorIsNotInNextEpoch",
+ "name": "ValidatorNotInNextEpoch",
"type": "error"
},
{
@@ -8719,13 +9291,13 @@
{
"indexed": false,
"internalType": "uint256",
- "name": "newMaxTripleCount",
+ "name": "newMaxPresignCount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
- "name": "newMinTripleCount",
+ "name": "newMinPresignCount",
"type": "uint256"
},
{
@@ -8737,7 +9309,7 @@
{
"indexed": false,
"internalType": "uint256",
- "name": "newMaxTripleConcurrency",
+ "name": "newMaxPresignConcurrency",
"type": "uint256"
},
{
@@ -8852,25 +9424,6 @@
"name": "RewardsDurationUpdated",
"type": "event"
},
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "internalType": "address",
- "name": "staker",
- "type": "address"
- },
- {
- "indexed": false,
- "internalType": "uint256",
- "name": "amountBurned",
- "type": "uint256"
- }
- ],
- "name": "ValidatorKickedFromNextEpoch",
- "type": "event"
- },
{
"anonymous": false,
"inputs": [
@@ -9000,39 +9553,27 @@
"internalType": "uint256",
"name": "realmId",
"type": "uint256"
- },
- {
- "internalType": "uint32",
- "name": "ip",
- "type": "uint32"
- },
- {
- "internalType": "uint128",
- "name": "ipv6",
- "type": "uint128"
- },
- {
- "internalType": "uint32",
- "name": "port",
- "type": "uint32"
- },
- {
- "internalType": "address",
- "name": "nodeAddress",
- "type": "address"
- },
+ }
+ ],
+ "name": "requestToJoin",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{
"internalType": "uint256",
- "name": "senderPubKey",
+ "name": "realmId",
"type": "uint256"
},
{
- "internalType": "uint256",
- "name": "receiverPubKey",
- "type": "uint256"
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
}
],
- "name": "requestToJoin",
+ "name": "requestToJoinAsAdmin",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
@@ -9045,29 +9586,27 @@
"type": "uint256"
},
{
- "internalType": "uint32",
- "name": "ip",
- "type": "uint32"
- },
- {
- "internalType": "uint128",
- "name": "ipv6",
- "type": "uint128"
- },
- {
- "internalType": "uint32",
- "name": "port",
- "type": "uint32"
- },
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
+ }
+ ],
+ "name": "requestToJoinAsForShadowSplicing",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{
"internalType": "uint256",
- "name": "senderPubKey",
+ "name": "realmId",
"type": "uint256"
},
{
- "internalType": "uint256",
- "name": "receiverPubKey",
- "type": "uint256"
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
}
],
"name": "requestToJoinAsNode",
@@ -9114,7 +9653,7 @@
},
{
"internalType": "address",
- "name": "nodeAddress",
+ "name": "operatorAddress",
"type": "address"
},
{
@@ -9167,36 +9706,6 @@
"internalType": "uint256",
"name": "amount",
"type": "uint256"
- },
- {
- "internalType": "uint32",
- "name": "ip",
- "type": "uint32"
- },
- {
- "internalType": "uint128",
- "name": "ipv6",
- "type": "uint128"
- },
- {
- "internalType": "uint32",
- "name": "port",
- "type": "uint32"
- },
- {
- "internalType": "address",
- "name": "nodeAddress",
- "type": "address"
- },
- {
- "internalType": "uint256",
- "name": "senderPubKey",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "receiverPubKey",
- "type": "uint256"
}
],
"name": "stakeAndJoin",
@@ -9477,11 +9986,6 @@
"name": "NodeAddressNotFoundForStaker",
"type": "error"
},
- {
- "inputs": [],
- "name": "StakeNotFound",
- "type": "error"
- },
{
"inputs": [
{
@@ -9497,14 +10001,14 @@
"type": "uint256"
},
{
- "internalType": "uint256",
- "name": "rewards",
- "type": "uint256"
+ "internalType": "address[]",
+ "name": "validatorsInCurrentEpoch",
+ "type": "address[]"
},
{
- "internalType": "bool",
- "name": "isStarted",
- "type": "bool"
+ "internalType": "uint256",
+ "name": "actualEpochLength",
+ "type": "uint256"
}
],
"internalType": "struct LibStakingStorage.RewardEpochGlobalStats",
@@ -9512,7 +10016,7 @@
"type": "tuple"
}
],
- "name": "calculateRewardsPerEpoch",
+ "name": "calculateRewardsPerDay",
"outputs": [
{
"internalType": "uint256",
@@ -9687,27 +10191,27 @@
},
{
"internalType": "uint256",
- "name": "endTime",
+ "name": "nextRewardEpochNumber",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "retries",
+ "name": "endTime",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "timeout",
+ "name": "retries",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "startTime",
+ "name": "timeout",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastEpochStart",
+ "name": "startTime",
"type": "uint256"
}
],
@@ -9792,18 +10296,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator[]",
@@ -9843,27 +10372,27 @@
},
{
"internalType": "uint256",
- "name": "endTime",
+ "name": "nextRewardEpochNumber",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "retries",
+ "name": "endTime",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "timeout",
+ "name": "retries",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "startTime",
+ "name": "timeout",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastEpochStart",
+ "name": "startTime",
"type": "uint256"
}
],
@@ -9900,38 +10429,63 @@
},
{
"internalType": "uint256",
- "name": "reward",
+ "name": "reward",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "senderPubKey",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "receiverPubKey",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastActiveEpoch",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "senderPubKey",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "receiverPubKey",
+ "name": "lastRealmId",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastActiveEpoch",
+ "name": "delegatedStakeAmount",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "delegatedStakeWeight",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator[]",
@@ -9961,6 +10515,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getAllValidators",
+ "outputs": [
+ {
+ "internalType": "address[]",
+ "name": "",
+ "type": "address[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "getKeyTypes",
@@ -9993,6 +10560,82 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "user",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
+ }
+ ],
+ "name": "getLastStakeRecord",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "id",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unfreezeStart",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "timeLock",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastUpdateTimestamp",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimed",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "initialSharePrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "loaded",
+ "type": "bool"
+ },
+ {
+ "internalType": "bool",
+ "name": "frozen",
+ "type": "bool"
+ },
+ {
+ "internalType": "address",
+ "name": "attributionAddress",
+ "type": "address"
+ }
+ ],
+ "internalType": "struct LibStakingStorage.StakeRecord",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "getLitCirc",
@@ -10003,7 +10646,25 @@
"type": "uint256"
}
],
- "stateMutability": "pure",
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getLowestRewardEpochNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
"type": "function"
},
{
@@ -10087,6 +10748,25 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getNonShadowValidators",
+ "outputs": [
+ {
+ "internalType": "address[]",
+ "name": "",
+ "type": "address[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -10110,14 +10790,14 @@
"type": "uint256"
},
{
- "internalType": "uint256",
- "name": "rewards",
- "type": "uint256"
+ "internalType": "address[]",
+ "name": "validatorsInCurrentEpoch",
+ "type": "address[]"
},
{
- "internalType": "bool",
- "name": "isStarted",
- "type": "bool"
+ "internalType": "uint256",
+ "name": "actualEpochLength",
+ "type": "uint256"
}
],
"internalType": "struct LibStakingStorage.RewardEpochGlobalStats",
@@ -10147,6 +10827,25 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getShadowValidators",
+ "outputs": [
+ {
+ "internalType": "address[]",
+ "name": "",
+ "type": "address[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -10196,7 +10895,7 @@
},
{
"internalType": "uint256",
- "name": "rewardEpochCheckpoint",
+ "name": "lastRewardEpochClaimed",
"type": "uint256"
},
{
@@ -10213,6 +10912,11 @@
"internalType": "bool",
"name": "frozen",
"type": "bool"
+ },
+ {
+ "internalType": "address",
+ "name": "attributionAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.StakeRecord",
@@ -10291,7 +10995,7 @@
},
{
"internalType": "uint256",
- "name": "rewardEpochCheckpoint",
+ "name": "lastRewardEpochClaimed",
"type": "uint256"
},
{
@@ -10308,6 +11012,11 @@
"internalType": "bool",
"name": "frozen",
"type": "bool"
+ },
+ {
+ "internalType": "address",
+ "name": "attributionAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.StakeRecord[]",
@@ -10326,56 +11035,14 @@
"type": "address"
},
{
- "components": [
- {
- "internalType": "uint256",
- "name": "id",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "unfreezeStart",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "timeLock",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "lastUpdateTimestamp",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "rewardEpochCheckpoint",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "initialSharePrice",
- "type": "uint256"
- },
- {
- "internalType": "bool",
- "name": "loaded",
- "type": "bool"
- },
- {
- "internalType": "bool",
- "name": "frozen",
- "type": "bool"
- }
- ],
- "internalType": "struct LibStakingStorage.StakeRecord",
- "name": "stakeRecord",
- "type": "tuple"
+ "internalType": "uint256",
+ "name": "recordId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "userStakerAddress",
+ "type": "address"
},
{
"internalType": "uint256",
@@ -10430,7 +11097,7 @@
},
{
"internalType": "uint256",
- "name": "rewardEpochCheckpoint",
+ "name": "lastRewardEpochClaimed",
"type": "uint256"
},
{
@@ -10447,6 +11114,11 @@
"internalType": "bool",
"name": "frozen",
"type": "bool"
+ },
+ {
+ "internalType": "address",
+ "name": "attributionAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.StakeRecord",
@@ -10532,7 +11204,7 @@
},
{
"internalType": "uint256",
- "name": "rewardEpochCheckpoint",
+ "name": "lastRewardEpochClaimed",
"type": "uint256"
},
{
@@ -10549,6 +11221,11 @@
"internalType": "bool",
"name": "frozen",
"type": "bool"
+ },
+ {
+ "internalType": "address",
+ "name": "attributionAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.StakeRecord",
@@ -10755,18 +11432,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator[]",
@@ -10831,18 +11533,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator[]",
@@ -10907,18 +11634,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator[]",
@@ -11073,6 +11825,16 @@
"internalType": "uint256",
"name": "minSelfStakeTimelock",
"type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minValidatorCountToClampMinimumThreshold",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minThresholdToClampAt",
+ "type": "uint256"
}
],
"internalType": "struct LibStakingStorage.GlobalConfig",
@@ -11083,6 +11845,30 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "stakerAddress",
+ "type": "address"
+ }
+ ],
+ "name": "isActiveShadowValidator",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -11344,6 +12130,25 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "operatorAddressToStakerAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -11411,12 +12216,12 @@
},
{
"internalType": "uint256",
- "name": "maxTripleCount",
+ "name": "maxPresignCount",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "minTripleCount",
+ "name": "minPresignCount",
"type": "uint256"
},
{
@@ -11426,13 +12231,18 @@
},
{
"internalType": "uint256",
- "name": "maxTripleConcurrency",
+ "name": "maxPresignConcurrency",
"type": "uint256"
},
{
"internalType": "bool",
"name": "rpcHealthcheckEnabled",
"type": "bool"
+ },
+ {
+ "internalType": "uint256",
+ "name": "minEpochForRewards",
+ "type": "uint256"
}
],
"internalType": "struct LibStakingStorage.RealmConfig",
@@ -11488,10 +12298,20 @@
},
{
"inputs": [
+ {
+ "internalType": "uint256",
+ "name": "realmId",
+ "type": "uint256"
+ },
{
"internalType": "address",
"name": "stakerAddress",
"type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "stakerInCurrentValidatorSet",
+ "type": "bool"
}
],
"name": "validatorSelfStakeWillExpire",
@@ -11559,18 +12379,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator",
@@ -11794,6 +12639,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "FORWARDER_CONTRACT",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [],
"name": "HD_KEY_DERIVER_CONTRACT",
@@ -12258,7 +13116,7 @@
"name": "ContractResolver"
},
"PriceFeed": {
- "address": "0x1c85638e118b37167e9298c2268758e058DdfDA0",
+ "address": "0xf953b3A269d80e3eB0F2947630Da976B896A8C5b",
"abi": [
{
"inputs": [
@@ -12692,6 +13550,19 @@
"name": "MaxNetworkPriceSet",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newTrustedForwarder",
+ "type": "address"
+ }
+ ],
+ "name": "TrustedForwarderSet",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
@@ -12736,6 +13607,41 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getNodeCapacityConfig",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "pkpSignMaxConcurrency",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "encSignMaxConcurrency",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "litActionMaxConcurrency",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "globalMaxCapacity",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct LibPriceFeedStorage.NodeCapacityConfig",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -12807,18 +13713,43 @@
},
{
"internalType": "uint256",
- "name": "commission",
+ "name": "commissionRate",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "commissionRate",
+ "name": "lastRewardEpoch",
"type": "uint256"
},
{
"internalType": "uint256",
- "name": "lastRewardEpoch",
+ "name": "lastRealmId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "delegatedStakeWeight",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedFixedCostRewards",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastRewardEpochClaimedCommission",
"type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "operatorAddress",
+ "type": "address"
}
],
"internalType": "struct LibStakingStorage.Validator",
@@ -12852,6 +13783,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getTrustedForwarder",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -12971,7 +13915,60 @@
"type": "uint256[]"
}
],
- "name": "setBaseNetworkPrices",
+ "name": "setBaseNetworkPrices",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "newPrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "productIds",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "setMaxNetworkPrices",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "pkpSignMaxConcurrency",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "encSignMaxConcurrency",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "litActionMaxConcurrency",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "globalMaxCapacity",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct LibPriceFeedStorage.NodeCapacityConfig",
+ "name": "config",
+ "type": "tuple"
+ }
+ ],
+ "name": "setNodeCapacityConfig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
@@ -12979,17 +13976,12 @@
{
"inputs": [
{
- "internalType": "uint256",
- "name": "newPrice",
- "type": "uint256"
- },
- {
- "internalType": "uint256[]",
- "name": "productIds",
- "type": "uint256[]"
+ "internalType": "address",
+ "name": "forwarder",
+ "type": "address"
}
],
- "name": "setMaxNetworkPrices",
+ "name": "setTrustedForwarder",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
@@ -13064,7 +14056,7 @@
"name": "PriceFeed"
},
"Ledger": {
- "address": "0xBEc49fA140aCaA83533fB00A2BB19bDdd0290f25",
+ "address": "0x4C2F7092C2aE51D986bEFEe378e50BD4dB99C901",
"abi": [
{
"inputs": [
@@ -13652,6 +14644,19 @@
"name": "RewardWithdrawRequest",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newTrustedForwarder",
+ "type": "address"
+ }
+ ],
+ "name": "TrustedForwarderSet",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
@@ -13815,6 +14820,19 @@
"stateMutability": "view",
"type": "function"
},
+ {
+ "inputs": [],
+ "name": "getTrustedForwarder",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -13987,6 +15005,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "forwarder",
+ "type": "address"
+ }
+ ],
+ "name": "setTrustedForwarder",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
{
"inputs": [
{
@@ -14054,5 +15085,227 @@
}
],
"name": "Ledger"
+ },
+ "Forwarder": {
+ "address": "0xAA292E8611aDF267e563f334Ee42320aC96D0463",
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "InvalidShortString",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "SignatureDoesNotMatch",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "str",
+ "type": "string"
+ }
+ ],
+ "name": "StringTooLong",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "TransactionRevertedSilently",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "EIP712DomainChanged",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "eip712Domain",
+ "outputs": [
+ {
+ "internalType": "bytes1",
+ "name": "fields",
+ "type": "bytes1"
+ },
+ {
+ "internalType": "string",
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "version",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "chainId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "verifyingContract",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "salt",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "extensions",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "gas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct Forwarder.ForwardRequest",
+ "name": "req",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "execute",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "",
+ "type": "bytes"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "gas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct Forwarder.ForwardRequest",
+ "name": "req",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "verify",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "name": "Forwarder"
}
}
diff --git a/local-tests/setup/session-sigs/get-eoa-session-sigs.ts b/local-tests/setup/session-sigs/get-eoa-session-sigs.ts
index 3e54717b58..f6eb049974 100644
--- a/local-tests/setup/session-sigs/get-eoa-session-sigs.ts
+++ b/local-tests/setup/session-sigs/get-eoa-session-sigs.ts
@@ -9,7 +9,6 @@ import {
AuthSig,
LitResourceAbilityRequest,
} from '@lit-protocol/types';
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import {
LIT_ABILITY,
diff --git a/local-tests/setup/session-sigs/get-pkp-session-sigs.ts b/local-tests/setup/session-sigs/get-pkp-session-sigs.ts
index ae4fb06dca..5e1152242f 100644
--- a/local-tests/setup/session-sigs/get-pkp-session-sigs.ts
+++ b/local-tests/setup/session-sigs/get-pkp-session-sigs.ts
@@ -3,7 +3,6 @@ import {
type AuthenticationContext,
LitResourceAbilityRequest,
} from '@lit-protocol/types';
-import { log } from '@lit-protocol/misc';
import {
LIT_ABILITY,
CENTRALISATION_BY_NETWORK,
@@ -43,7 +42,7 @@ export const getPkpAuthContext = (
}),
});
- log('[getPkpAuthContext]: ', authContext);
+ console.log('[getPkpAuthContext]: ', authContext);
return authContext;
};
diff --git a/local-tests/setup/tinny-environment.ts b/local-tests/setup/tinny-environment.ts
index 0891664665..c38e5851f6 100644
--- a/local-tests/setup/tinny-environment.ts
+++ b/local-tests/setup/tinny-environment.ts
@@ -1,5 +1,6 @@
import { LitContracts } from '@lit-protocol/contracts-sdk';
import { LitNodeClient } from '@lit-protocol/lit-node-client';
+import { getChildLogger } from '@lit-protocol/logger';
import {
AuthSig,
LitContractContext,
@@ -8,7 +9,6 @@ import {
import { ProcessEnvs, TinnyEnvConfig } from './tinny-config';
import { TinnyPerson } from './tinny-person';
-import { createSiweMessage, generateAuthSig } from '@lit-protocol/auth-helpers';
import {
CENTRALISATION_BY_NETWORK,
LIT_NETWORK,
@@ -20,7 +20,9 @@ import { ethers, Signer } from 'ethers';
import { ShivaClient, TestnetClient } from './shiva-client';
import { toErrorWithMessage } from './tinny-utils';
-console.log('checking env', process.env['DEBUG']);
+const logger = getChildLogger({ module: 'tinny-environment' });
+
+logger.info({ msg: 'checking env', env: process.env['DEBUG'] });
const DEFAULT_ANVIL_PRIVATE_KEYS = [
'0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',
@@ -49,7 +51,7 @@ export class TinnyEnvironment {
DEBUG: process.env['DEBUG'] === 'true',
REQUEST_PER_KILOSECOND:
parseInt(process.env['REQUEST_PER_KILOSECOND']) ||
- (process.env['NETWORK'] as LIT_NETWORK_VALUES) === 'datil-dev'
+ (process.env['NETWORK'] as LIT_NETWORK_VALUES) === LIT_NETWORK.NagaDev
? 1
: 200,
LIT_RPC_URL: process.env['LIT_RPC_URL'],
@@ -147,10 +149,10 @@ export class TinnyEnvironment {
);
}
- console.log(
- '[𐬺🧪 Tinny Environment𐬺] Done configuring environment current config: ',
- this.processEnvs
- );
+ logger.info({
+ msg: '[𐬺🧪 Tinny Environment𐬺] Done configuring environment current config: ',
+ processEnvs: this.processEnvs,
+ });
}
world: Map = new Map();
@@ -183,11 +185,12 @@ export class TinnyEnvironment {
if (index !== -1) {
// If an available key is found
this.processEnvs.KEY_IN_USE[index] = true; // Mark the key as in use
- // console.log('[𐬺🧪 Tinny Environment𐬺] 🔑 Selected key at index', index); // Log a message indicating that we have selected a key
+ // logger.info({ msg: '[𐬺🧪 Tinny Environment𐬺] 🔑 Selected key at index', index }); // Log a message indicating that we have selected a key
return { privateKey: this.processEnvs.PRIVATE_KEYS[index], index }; // Return the key and its index
} else {
- console.log('[𐬺🧪 Tinny Environment𐬺] No available keys. Waiting...', {
+ logger.info({
+ msg: '[𐬺🧪 Tinny Environment𐬺] No available keys. Waiting...',
keysInUse: this.processEnvs.KEY_IN_USE,
}); // Log a message indicating that we are waiting
// Wait for the specified interval before checking again
@@ -205,9 +208,9 @@ export class TinnyEnvironment {
releasePrivateKeyFromUser(user: TinnyPerson) {
const index = this.processEnvs.PRIVATE_KEYS.indexOf(user.privateKey);
this.processEnvs.KEY_IN_USE[index] = false;
- // console.log(
- // `[𐬺🧪 Tinny Environment𐬺] 🪽 Released key at index ${index}. Thank you for your service!`
- // );
+ // logger.info({
+ // msg: `[𐬺🧪 Tinny Environment𐬺] 🪽 Released key at index ${index}. Thank you for your service!`
+ // });
}
/**
@@ -216,9 +219,9 @@ export class TinnyEnvironment {
*/
releasePrivateKey(index: number) {
this.processEnvs.KEY_IN_USE[index] = false;
- // console.log(
- // `[𐬺🧪 Tinny Environment𐬺] 🪽 Released key at index ${index}. Thank you for your service!`
- // );
+ // logger.info({
+ // msg: `[𐬺🧪 Tinny Environment𐬺] 🪽 Released key at index ${index}. Thank you for your service!`
+ // });
}
/**
@@ -234,9 +237,9 @@ export class TinnyEnvironment {
*/
async setupLitNodeClient() {
- console.log('[𐬺🧪 Tinny Environment𐬺] Setting up LitNodeClient');
+ logger.info({ msg: '[𐬺🧪 Tinny Environment𐬺] Setting up LitNodeClient' });
- console.log('this.network:', this.network);
+ logger.info({ msg: 'network', network: this.network });
const centralisation = CENTRALISATION_BY_NETWORK[this.network];
if (this.network === LIT_NETWORK.Custom || centralisation === 'unknown') {
@@ -324,7 +327,7 @@ export class TinnyEnvironment {
* @throws Error if the name is not provided.
*/
async createNewPerson(name: string) {
- console.log('[𐬺🧪 Tinny Environment𐬺] Creating new person:', name);
+ logger.info({ msg: '[𐬺🧪 Tinny Environment𐬺] Creating new person', name });
if (!name) {
throw new Error('Name is required');
}
@@ -373,7 +376,7 @@ export class TinnyEnvironment {
async init() {
try {
if (this.processEnvs.NO_SETUP) {
- console.log('[𐬺🧪 Tinny Environment𐬺] Skipping setup');
+ logger.info({ msg: '[𐬺🧪 Tinny Environment𐬺] Skipping setup' });
return;
}
if (this.network === LIT_NETWORK.Custom && this.processEnvs.USE_SHIVA) {
@@ -381,9 +384,9 @@ export class TinnyEnvironment {
// wait for the testnet to be active before we start the tests.
let state = await this.testnet.pollTestnetForActive();
if (state === `UNKNOWN`) {
- console.log(
- 'Testnet state found to be Unknown meaning there was an error with testnet creation. shutting down'
- );
+ logger.info({
+ msg: 'Testnet state found to be Unknown meaning there was an error with testnet creation. shutting down',
+ });
throw new Error(`Error while creating testnet, aborting test run`);
}
@@ -398,10 +401,10 @@ export class TinnyEnvironment {
await this.setupSuperCapacityDelegationAuthSig();
} catch (e) {
const err = toErrorWithMessage(e);
- console.log(
- `[𐬺🧪 Tinny Environment𐬺] Failed to init() tinny ${err.message}`
- );
- console.log(err.stack);
+ logger.error({
+ msg: `[𐬺🧪 Tinny Environment𐬺] Failed to init() tinny ${err.message}`,
+ stack: err.stack,
+ });
process.exit(1);
}
}
@@ -417,7 +420,7 @@ export class TinnyEnvironment {
) {
await this.testnet.stopTestnet();
} else {
- console.log('skipping testnet shutdown.');
+ logger.info('skipping testnet shutdown.');
}
}
//============= END SHIVA ENDPOINTS =============
@@ -498,9 +501,9 @@ export class TinnyEnvironment {
// get wallet balance
const balance = await wallet.getBalance();
- console.log('this.rpc:', rpc);
- console.log('this.wallet.address', wallet.address);
- console.log('Balance:', balance.toString());
+ logger.info({ msg: 'this.rpc:', rpc });
+ logger.info({ msg: 'this.wallet.address', address: wallet.address });
+ logger.info({ msg: 'Balance:', balance: balance.toString() });
const transferTx = await wallet.sendTransaction({
to: capacityCreditWallet.address,
@@ -520,7 +523,7 @@ export class TinnyEnvironment {
}
if (!this.contractsClient) {
- console.log('❗️Contracts client not initialized');
+ logger.info('❗️Contracts client not initialized');
process.exit();
}
@@ -537,7 +540,7 @@ export class TinnyEnvironment {
};
async mintSuperCapacityDelegationAuthSig(wallet: Signer) {
- console.log(
+ logger.info(
'[𐬺🧪 Tinny Environment𐬺] Mint a Capacity Credits NFT and get a capacity delegation authSig with it'
);
@@ -552,9 +555,9 @@ export class TinnyEnvironment {
).capacityDelegationAuthSig;
} catch (e: any) {
if (e.message.includes(`Can't allocate capacity beyond the global max`)) {
- console.log('❗️Skipping capacity delegation auth sig setup.', e);
+ logger.info('❗️Skipping capacity delegation auth sig setup.', e);
} else {
- console.log(
+ logger.info(
'❗️Error while setting up capacity delegation auth sig',
e
);
diff --git a/local-tests/setup/tinny-person.ts b/local-tests/setup/tinny-person.ts
index 9d1fad5cc0..1890d59a0e 100644
--- a/local-tests/setup/tinny-person.ts
+++ b/local-tests/setup/tinny-person.ts
@@ -1,19 +1,19 @@
-import {
- AuthSig,
- generateAuthSig,
- createSiweMessage,
-} from '@lit-protocol/auth-helpers';
+import { generateAuthSig, createSiweMessage } from '@lit-protocol/auth-helpers';
import { LitContracts } from '@lit-protocol/contracts-sdk';
import {
AuthMethod,
+ AuthSig,
BaseSiweMessage,
LitContractContext,
} from '@lit-protocol/types';
import { ethers } from 'ethers';
import { PKPInfo, TinnyEnvConfig } from './tinny-config';
-import { EthWalletProvider } from '@lit-protocol/lit-auth-client';
import { AUTH_METHOD_SCOPE, LIT_NETWORK } from '@lit-protocol/constants';
+import { authenticators } from '@lit-protocol/auth';
+
+const { MetamaskAuthenticator } = authenticators;
+
export class TinnyPerson {
public privateKey: string;
public wallet: ethers.Wallet;
@@ -53,7 +53,7 @@ export class TinnyPerson {
}
async getAuthMethodId(): Promise {
- return EthWalletProvider.authMethodId(this.authMethod);
+ return MetamaskAuthenticator.authMethodId(this.authMethod);
}
/**
@@ -116,7 +116,7 @@ export class TinnyPerson {
console.log(
'[𐬺🧪 Tinny Person𐬺] Crafting an authMethod from the authSig for the eth wallet auth method...'
);
- this.authMethod = await EthWalletProvider.authenticate({
+ this.authMethod = await MetamaskAuthenticator.authenticate({
signer: this.wallet,
litNodeClient: this.envConfig.litNodeClient,
});
diff --git a/local-tests/test.ts b/local-tests/test.ts
index cb1a898ec4..f4ef5e7a81 100644
--- a/local-tests/test.ts
+++ b/local-tests/test.ts
@@ -1,293 +1,27 @@
-import { TinnyEnvironment } from './setup/tinny-environment';
-import { runInBand, runTestsParallel } from './setup/tinny-operations';
-
-// import { testBundleSpeed } from './tests/test-bundle-speed';
-// import { testExample } from './tests/test-example';
-
-import { testUseEoaSessionSigsToExecuteJsSigningInParallel } from './tests/testUseEoaSessionSigsToExecuteJsSigningInParallel';
-import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning';
-import { testUseValidLitActionCodeGeneratedSessionSigsToPkpSign } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToPkpSign';
-import { testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning } from './tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning';
-
-import { testUseEoaSessionSigsToEncryptDecryptFile } from './tests/testUseEoaSessionSigsToEncryptDecryptFile';
-import { testUseEoaSessionSigsToEncryptDecryptString } from './tests/testUseEoaSessionSigsToEncryptDecryptString';
-import { testUseEoaSessionSigsToEncryptDecryptUint8Array } from './tests/testUseEoaSessionSigsToEncryptDecryptUint8Array';
-import { testUseEoaSessionSigsToExecuteJsClaimKeys } from './tests/testUseEoaSessionSigsToExecuteJsClaimKeys';
-import { testUseEoaSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUseEoaSessionSigsToExecuteJsClaimMultipleKeys';
-import { testUseEoaSessionSigsToExecuteJsConsoleLog } from './tests/testUseEoaSessionSigsToExecuteJsConsoleLog';
-import { testUseEoaSessionSigsToExecuteJsJsonResponse } from './tests/testUseEoaSessionSigsToExecuteJsJsonResponse';
-import { testUseEoaSessionSigsToExecuteJsSigning } from './tests/testUseEoaSessionSigsToExecuteJsSigning';
-import { testUseEoaSessionSigsToPkpSign } from './tests/testUseEoaSessionSigsToPkpSign';
-import { testUseEoaSessionSigsToRequestSingleResponse } from './tests/testUseEoaSessionSigsToRequestSingleResponse';
-
-import { testUseInvalidLitActionCodeToGenerateSessionSigs } from './tests/testUseInvalidLitActionCodeToGenerateSessionSigs';
-import { testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString';
-import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel';
-
-import { testUsePkpSessionSigsToEncryptDecryptFile } from './tests/testUsePkpSessionSigsToEncryptDecryptFile';
-import { testUsePkpSessionSigsToEncryptDecryptString } from './tests/testUsePkpSessionSigsToEncryptDecryptString';
-import { testUsePkpSessionSigsToExecuteJsClaimKeys } from './tests/testUsePkpSessionSigsToExecuteJsClaimKeys';
-import { testUsePkpSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUsePkpSessionSigsToExecuteJsClaimMultipleKeys';
-import { testUsePkpSessionSigsToExecuteJsConsoleLog } from './tests/testUsePkpSessionSigsToExecuteJsConsoleLog';
-import { testUsePkpSessionSigsToExecuteJsJsonResponse } from './tests/testUsePkpSessionSigsToExecuteJsJsonResponse';
-import { testUsePkpSessionSigsToExecuteJsSigning } from './tests/testUsePkpSessionSigsToExecuteJsSigning';
-import { testUsePkpSessionSigsToExecuteJsSigningInParallel } from './tests/testUsePkpSessionSigsToExecuteJsSigningInParallel';
-import { testUsePkpSessionSigsToPkpSign } from './tests/testUsePkpSessionSigsToPkpSign';
-
-import { testUseInvalidLitActionIpfsCodeToGenerateSessionSigs } from './tests/testUseInvalidLitActionIpfsCodeToGenerateSessionSigs';
-import { testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile';
-import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys';
-import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys';
-import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog';
-import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse';
-import { testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign } from './tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign';
-import { testPkpEthersWithEoaSessionSigsToEthSign } from './tests/testPkpEthersWithEoaSessionSigsToEthSign';
-import { testPkpEthersWithEoaSessionSigsToEthSignTransaction } from './tests/testPkpEthersWithEoaSessionSigsToEthSignTransaction';
-import { testPkpEthersWithEoaSessionSigsToPersonalSign } from './tests/testPkpEthersWithEoaSessionSigsToPersonalSign';
-import { testPkpEthersWithEoaSessionSigsToSendTx } from './tests/testPkpEthersWithEoaSessionSigsToSendTx';
-import { testPkpEthersWithEoaSessionSigsToSignMessage } from './tests/testPkpEthersWithEoaSessionSigsToSignMessage';
-import { testPkpEthersWithEoaSessionSigsToSignWithAuthContext } from './tests/testPkpEthersWithEoaSessionSigsToSignWithAuthContext';
-import { testPkpEthersWithPkpSessionSigsToEthSign } from './tests/testPkpEthersWithPkpSessionSigsToEthSign';
-import { testPkpEthersWithPkpSessionSigsToPersonalSign } from './tests/testPkpEthersWithPkpSessionSigsToPersonalSign';
-import { testPkpEthersWithPkpSessionSigsToSendTx } from './tests/testPkpEthersWithPkpSessionSigsToSendTx';
-import { testPkpEthersWithPkpSessionSigsToSignMessage } from './tests/testPkpEthersWithPkpSessionSigsToSignMessage';
-
-import { testPkpEthersWithEoaSessionSigsToEthSignTypedData } from './tests/testPkpEthersWithEoaSessionSigsToEthSignTypedData';
-import { testPkpEthersWithEoaSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithEoaSessionSigsToEthSignTypedDataUtil';
-import { testPkpEthersWithEoaSessionSigsToEthSignTypedDataV1 } from './tests/testPkpEthersWithEoaSessionSigsToEthSignTypedDataV1';
-import { testPkpEthersWithEoaSessionSigsToEthSignTypedDataV3 } from './tests/testPkpEthersWithEoaSessionSigsToEthSignTypedDataV3';
-import { testPkpEthersWithEoaSessionSigsToEthSignTypedDataV4 } from './tests/testPkpEthersWithEoaSessionSigsToEthSignTypedDataV4';
-import { testPkpEthersWithLitActionSessionSigsToEthSign } from './tests/testPkpEthersWithLitActionSessionSigsToEthSign';
-import { testPkpEthersWithLitActionSessionSigsToEthSignTransaction } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTransaction';
-import { testPkpEthersWithLitActionSessionSigsToEthSignTypedData } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedData';
-import { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil';
-import { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV1 } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV1';
-import { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV3 } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV3';
-import { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV4 } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV4';
-import { testPkpEthersWithLitActionSessionSigsToPersonalSign } from './tests/testPkpEthersWithLitActionSessionSigsToPersonalSign';
-import { testPkpEthersWithLitActionSessionSigsToSendTx } from './tests/testPkpEthersWithLitActionSessionSigsToSendTx';
-import { testPkpEthersWithLitActionSessionSigsToSignMessage } from './tests/testPkpEthersWithLitActionSessionSigsToSignMessage';
-import { testPkpEthersWithPkpSessionSigsToEthSignTransaction } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTransaction';
-import { testPkpEthersWithPkpSessionSigsToEthSignTypedData } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTypedData';
-import { testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil';
-import { testPkpEthersWithPkpSessionSigsToEthSignTypedDataV1 } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTypedDataV1';
-import { testPkpEthersWithPkpSessionSigsToEthSignTypedDataV3 } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTypedDataV3';
-import { testPkpEthersWithPkpSessionSigsToEthSignTypedDataV4 } from './tests/testPkpEthersWithPkpSessionSigsToEthSignTypedDataV4';
-
-import { testUseCustomAuthSessionSigsToPkpSignExecuteJs } from './tests/testUseCustomAuthSessionSigsToPkpSignExecuteJs';
+import { setLoggerOptions, logger } from '@lit-protocol/logger';
-import { testExecuteJsBroadcastAndCollect } from './tests/testExecuteJsBroadcastAndCollect';
-import { testExecuteJsDecryptAndCombine } from './tests/testExecuteJsDecryptAndCombine';
-import { testExecuteJsSignAndCombineEcdsa } from './tests/testExecuteJsSignAndCombineEcdsa';
-import { testRelayer } from './tests/testRelayer';
-
-// import { testEthereumSignMessageGeneratedKey } from './tests/wrapped-keys/testEthereumSignMessageGeneratedKey';
-// import { testEthereumBroadcastTransactionGeneratedKey } from './tests/wrapped-keys/testEthereumBroadcastTransactionGeneratedKey';
-// import { testEthereumSignMessageWrappedKey } from './tests/wrapped-keys/testEthereumSignMessageWrappedKey';
-// import { testFailEthereumSignTransactionWrappedKeyInvalidDecryption } from './tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyInvalidDecryption';
-// import { testEthereumSignTransactionWrappedKey } from './tests/wrapped-keys/testEthereumSignTransactionWrappedKey';
-// import { testFailEthereumSignTransactionWrappedKeyWithInvalidParam } from './tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithInvalidParam';
-// import { testFailEthereumSignTransactionWrappedKeyWithMissingParam } from './tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithMissingParam';
-// import { testEthereumBroadcastTransactionWrappedKey } from './tests/wrapped-keys/testEthereumBroadcastTransactionWrappedKey';
-// import { testEthereumBroadcastWrappedKeyWithFetchGasParams } from './tests/wrapped-keys/testEthereumBroadcastWrappedKeyWithFetchGasParams';
-// import { testImportWrappedKey } from './tests/wrapped-keys/testImportWrappedKey';
-// import { testGenerateEthereumWrappedKey } from './tests/wrapped-keys/testGenerateEthereumWrappedKey';
-// import { testGenerateSolanaWrappedKey } from './tests/wrapped-keys/testGenerateSolanaWrappedKey';
-// import { testFailImportWrappedKeysWithSamePrivateKey } from './tests/wrapped-keys/testFailImportWrappedKeysWithSamePrivateKey';
-// import { testFailImportWrappedKeysWithEoaSessionSig } from './tests/wrapped-keys/testFailImportWrappedKeysWithEoaSessionSig';
-// import { testFailImportWrappedKeysWithMaxExpirySessionSig } from './tests/wrapped-keys/testFailImportWrappedKeysWithMaxExpirySessionSig';
-// import { testFailImportWrappedKeysWithInvalidSessionSig } from './tests/wrapped-keys/testFailImportWrappedKeysWithInvalidSessionSig';
-// import { testFailImportWrappedKeysWithExpiredSessionSig } from './tests/wrapped-keys/testFailImportWrappedKeysWithExpiredSessionSig';
-// import { testExportWrappedKey } from './tests/wrapped-keys/testExportWrappedKey';
-// import { testSignMessageWithSolanaEncryptedKey } from './tests/wrapped-keys/testSignMessageWithSolanaEncryptedKey';
-// import { testSignTransactionWithSolanaEncryptedKey } from './tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey';
-// import { testBatchGeneratePrivateKeys } from './tests/wrapped-keys/testBatchGeneratePrivateKeys';
-// import { testFailBatchGeneratePrivateKeysAtomic } from './tests/wrapped-keys/testFailStoreEncryptedKeyBatchIsAtomic';
+setLoggerOptions({
+ transport: {
+ target: 'pino-pretty',
+ },
+});
+import { TinnyEnvironment } from './setup/tinny-environment';
+import { runInBand, runTestsParallel } from './setup/tinny-operations';
+import { tinnyTests } from './tests';
import { setLitActionsCodeToLocal } from './tests/wrapped-keys/util';
// Use the current LIT action code to test against
setLitActionsCodeToLocal();
(async () => {
- console.log('[𐬺🧪 Tinny𐬺] Running tests...');
+ logger.info({ msg: '[𐬺🧪 Tinny𐬺] Running tests...' });
const devEnv = new TinnyEnvironment();
await devEnv.init();
- const relayerTests = {
- testRelayer,
- };
-
- // --filter=WrappedKey
- const wrappedKeysTests = {
- // // -- valid cases
- // testBatchGeneratePrivateKeys,
- // testEthereumSignMessageGeneratedKey,
- // testEthereumBroadcastTransactionGeneratedKey,
- // testEthereumSignMessageWrappedKey,
- // testEthereumSignTransactionWrappedKey,
- // testEthereumBroadcastTransactionWrappedKey,
- // testEthereumBroadcastWrappedKeyWithFetchGasParams,
- //
- // // -- generate wrapped keys
- // testGenerateEthereumWrappedKey,
- // testGenerateSolanaWrappedKey,
- //
- // // -- import wrapped keys
- // testImportWrappedKey,
- //
- // // -- export wrapped keys
- // testExportWrappedKey,
- //
- // // -- solana wrapped keys
- // testSignMessageWithSolanaEncryptedKey,
- // testSignTransactionWithSolanaEncryptedKey,
- //
- // // -- invalid cases
- // testFailEthereumSignTransactionWrappedKeyWithMissingParam,
- // testFailEthereumSignTransactionWrappedKeyWithInvalidParam,
- // testFailEthereumSignTransactionWrappedKeyInvalidDecryption,
- // testFailBatchGeneratePrivateKeysAtomic,
- //
- // // -- import wrapped keys
- // testFailImportWrappedKeysWithSamePrivateKey,
- // testFailImportWrappedKeysWithEoaSessionSig,
- // testFailImportWrappedKeysWithMaxExpirySessionSig,
- // testFailImportWrappedKeysWithInvalidSessionSig,
- // testFailImportWrappedKeysWithExpiredSessionSig,
- };
-
- const eoaSessionSigsTests = {
- testUseEoaSessionSigsToExecuteJsSigning,
- testUseEoaSessionSigsToRequestSingleResponse,
- testUseEoaSessionSigsToPkpSign,
- testUseEoaSessionSigsToExecuteJsSigningInParallel,
- testUseEoaSessionSigsToExecuteJsClaimKeys,
- testUseEoaSessionSigsToExecuteJsClaimMultipleKeys,
- testUseEoaSessionSigsToExecuteJsJsonResponse,
- testUseEoaSessionSigsToExecuteJsConsoleLog,
- testUseEoaSessionSigsToEncryptDecryptString,
- testUseEoaSessionSigsToEncryptDecryptUint8Array,
- testUseEoaSessionSigsToEncryptDecryptFile,
- };
-
- const pkpSessionSigsTests = {
- testUsePkpSessionSigsToExecuteJsSigning,
- testUsePkpSessionSigsToPkpSign,
- testUsePkpSessionSigsToExecuteJsSigningInParallel,
- testUsePkpSessionSigsToExecuteJsClaimKeys,
- testUsePkpSessionSigsToExecuteJsClaimMultipleKeys,
- testUsePkpSessionSigsToExecuteJsJsonResponse,
- testUsePkpSessionSigsToExecuteJsConsoleLog,
- testUsePkpSessionSigsToEncryptDecryptString,
- testUsePkpSessionSigsToEncryptDecryptFile,
- };
-
- const litActionSessionSigsTests = {
- testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning,
- testUseValidLitActionCodeGeneratedSessionSigsToPkpSign,
- testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel,
- testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys,
- testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys,
- testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse,
- testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog,
- testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString,
- testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile,
-
- // -- invalid cases
- testUseInvalidLitActionIpfsCodeToGenerateSessionSigs,
-
- // -- custom auth methods
- testUseCustomAuthSessionSigsToPkpSignExecuteJs,
- };
-
- const litActionIpfsIdSessionSigsTests = {
- testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign,
- testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning,
-
- // -- invalid cases
- testUseInvalidLitActionCodeToGenerateSessionSigs,
- };
-
- const eip1271AuthSigTests = {
- // testKeccakEip1271AuthSigToEncryptDecryptString,
- // testShaEip1271AuthSigToEncryptDecryptString,
- };
-
- const pkpEthersTest = {
- eoaSessionSigs: {
- testPkpEthersWithEoaSessionSigsToSignWithAuthContext,
- testPkpEthersWithEoaSessionSigsToSignMessage,
- testPkpEthersWithEoaSessionSigsToEthSign,
- testPkpEthersWithEoaSessionSigsToPersonalSign,
- testPkpEthersWithEoaSessionSigsToSendTx,
- testPkpEthersWithEoaSessionSigsToEthSignTransaction,
- testPkpEthersWithEoaSessionSigsToEthSignTypedDataV1,
- testPkpEthersWithEoaSessionSigsToEthSignTypedDataV3,
- testPkpEthersWithEoaSessionSigsToEthSignTypedDataV4,
- testPkpEthersWithEoaSessionSigsToEthSignTypedData,
- testPkpEthersWithEoaSessionSigsToEthSignTypedDataUtil,
- },
- pkpSessionSigs: {
- testPkpEthersWithPkpSessionSigsToSignMessage,
- testPkpEthersWithPkpSessionSigsToEthSign,
- testPkpEthersWithPkpSessionSigsToPersonalSign,
- testPkpEthersWithPkpSessionSigsToSendTx,
- testPkpEthersWithPkpSessionSigsToEthSignTransaction,
- testPkpEthersWithPkpSessionSigsToEthSignTypedDataV1,
- testPkpEthersWithPkpSessionSigsToEthSignTypedDataV3,
- testPkpEthersWithPkpSessionSigsToEthSignTypedDataV4,
- testPkpEthersWithPkpSessionSigsToEthSignTypedData,
- testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil,
- },
- litActionSessionSigs: {
- testPkpEthersWithLitActionSessionSigsToSignMessage,
- testPkpEthersWithLitActionSessionSigsToEthSign,
- testPkpEthersWithLitActionSessionSigsToPersonalSign,
- testPkpEthersWithLitActionSessionSigsToSendTx,
- testPkpEthersWithLitActionSessionSigsToEthSignTransaction,
- testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV1,
- testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV3,
- testPkpEthersWithLitActionSessionSigsToEthSignTypedDataV4,
- testPkpEthersWithLitActionSessionSigsToEthSignTypedData,
- testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil,
- },
- };
-
- const litActionCombiningTests = {
- ecdsaSignAndCombine: {
- testExecuteJsSignAndCombineEcdsa,
- },
- decryptAndCombine: {
- testExecuteJsDecryptAndCombine,
- },
- broadcastAndCombine: {
- testExecuteJsBroadcastAndCollect,
- },
- };
-
const testConfig = {
- tests: {
- // testExample,
- // testBundleSpeed,
- ...eoaSessionSigsTests,
- ...pkpSessionSigsTests,
- ...litActionSessionSigsTests,
- ...litActionIpfsIdSessionSigsTests,
- ...eip1271AuthSigTests,
-
- ...pkpEthersTest.eoaSessionSigs,
- ...pkpEthersTest.pkpSessionSigs,
- ...pkpEthersTest.litActionSessionSigs,
-
- ...litActionCombiningTests.broadcastAndCombine,
- ...litActionCombiningTests.decryptAndCombine,
- ...litActionCombiningTests.ecdsaSignAndCombine,
-
- ...relayerTests,
- ...wrappedKeysTests,
- },
+ tests: tinnyTests,
devEnv,
};
diff --git a/local-tests/tests.ts b/local-tests/tests.ts
index ed882cd6d6..19ef4e873c 100644
--- a/local-tests/tests.ts
+++ b/local-tests/tests.ts
@@ -1,3 +1,4 @@
+import { testUseEoaSessionSigsToRequestSingleResponse } from './tests/testUseEoaSessionSigsToRequestSingleResponse';
import { testUseEoaSessionSigsToExecuteJsSigning } from './tests/testUseEoaSessionSigsToExecuteJsSigning';
import { testUseEoaSessionSigsToPkpSign } from './tests/testUseEoaSessionSigsToPkpSign';
import { testUsePkpSessionSigsToExecuteJsSigning } from './tests/testUsePkpSessionSigsToExecuteJsSigning';
@@ -10,24 +11,17 @@ import { testUseEoaSessionSigsToExecuteJsClaimKeys } from './tests/testUseEoaSes
import { testUseEoaSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUseEoaSessionSigsToExecuteJsClaimMultipleKeys';
import { testUseEoaSessionSigsToExecuteJsJsonResponse } from './tests/testUseEoaSessionSigsToExecuteJsJsonResponse';
import { testUseEoaSessionSigsToExecuteJsConsoleLog } from './tests/testUseEoaSessionSigsToExecuteJsConsoleLog';
-import { testUseEoaSessionSigsToEncryptDecryptString } from './tests/testUseEoaSessionSigsToEncryptDecryptString';
-import { testUseEoaSessionSigsToEncryptDecryptUint8Array } from './tests/testUseEoaSessionSigsToEncryptDecryptUint8Array';
-import { testUsePkpSessionSigsToEncryptDecryptString } from './tests/testUsePkpSessionSigsToEncryptDecryptString';
-import { testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString';
import { testUseInvalidLitActionCodeToGenerateSessionSigs } from './tests/testUseInvalidLitActionCodeToGenerateSessionSigs';
-import { testUseEoaSessionSigsToEncryptDecryptFile } from './tests/testUseEoaSessionSigsToEncryptDecryptFile';
import { testUsePkpSessionSigsToExecuteJsSigningInParallel } from './tests/testUsePkpSessionSigsToExecuteJsSigningInParallel';
import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel';
import { testUsePkpSessionSigsToExecuteJsClaimKeys } from './tests/testUsePkpSessionSigsToExecuteJsClaimKeys';
import { testUsePkpSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUsePkpSessionSigsToExecuteJsClaimMultipleKeys';
import { testUsePkpSessionSigsToExecuteJsJsonResponse } from './tests/testUsePkpSessionSigsToExecuteJsJsonResponse';
import { testUsePkpSessionSigsToExecuteJsConsoleLog } from './tests/testUsePkpSessionSigsToExecuteJsConsoleLog';
-import { testUsePkpSessionSigsToEncryptDecryptFile } from './tests/testUsePkpSessionSigsToEncryptDecryptFile';
import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys';
import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys';
import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse';
import { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog';
-import { testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile';
import { testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign } from './tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign';
import { testUseInvalidLitActionIpfsCodeToGenerateSessionSigs } from './tests/testUseInvalidLitActionIpfsCodeToGenerateSessionSigs';
import { testPkpEthersWithEoaSessionSigsToSignMessage } from './tests/testPkpEthersWithEoaSessionSigsToSignMessage';
@@ -64,7 +58,6 @@ import { testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil } from './tests/t
import { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil';
import { testUseCustomAuthSessionSigsToPkpSignExecuteJs } from './tests/testUseCustomAuthSessionSigsToPkpSignExecuteJs';
import { testExecuteJsSignAndCombineEcdsa } from './tests/testExecuteJsSignAndCombineEcdsa';
-import { testExecuteJsDecryptAndCombine } from './tests/testExecuteJsDecryptAndCombine';
import { testExecuteJsBroadcastAndCollect } from './tests/testExecuteJsBroadcastAndCollect';
import { testRelayer } from './tests/testRelayer';
@@ -103,24 +96,17 @@ export { testUseEoaSessionSigsToExecuteJsClaimKeys } from './tests/testUseEoaSes
export { testUseEoaSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUseEoaSessionSigsToExecuteJsClaimMultipleKeys';
export { testUseEoaSessionSigsToExecuteJsJsonResponse } from './tests/testUseEoaSessionSigsToExecuteJsJsonResponse';
export { testUseEoaSessionSigsToExecuteJsConsoleLog } from './tests/testUseEoaSessionSigsToExecuteJsConsoleLog';
-export { testUseEoaSessionSigsToEncryptDecryptString } from './tests/testUseEoaSessionSigsToEncryptDecryptString';
-export { testUseEoaSessionSigsToEncryptDecryptUint8Array } from './tests/testUseEoaSessionSigsToEncryptDecryptUint8Array';
-export { testUsePkpSessionSigsToEncryptDecryptString } from './tests/testUsePkpSessionSigsToEncryptDecryptString';
-export { testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString';
export { testUseInvalidLitActionCodeToGenerateSessionSigs } from './tests/testUseInvalidLitActionCodeToGenerateSessionSigs';
-export { testUseEoaSessionSigsToEncryptDecryptFile } from './tests/testUseEoaSessionSigsToEncryptDecryptFile';
export { testUsePkpSessionSigsToExecuteJsSigningInParallel } from './tests/testUsePkpSessionSigsToExecuteJsSigningInParallel';
export { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel';
export { testUsePkpSessionSigsToExecuteJsClaimKeys } from './tests/testUsePkpSessionSigsToExecuteJsClaimKeys';
export { testUsePkpSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUsePkpSessionSigsToExecuteJsClaimMultipleKeys';
export { testUsePkpSessionSigsToExecuteJsJsonResponse } from './tests/testUsePkpSessionSigsToExecuteJsJsonResponse';
export { testUsePkpSessionSigsToExecuteJsConsoleLog } from './tests/testUsePkpSessionSigsToExecuteJsConsoleLog';
-export { testUsePkpSessionSigsToEncryptDecryptFile } from './tests/testUsePkpSessionSigsToEncryptDecryptFile';
export { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimKeys';
export { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys';
export { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse';
export { testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog';
-export { testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile } from './tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile';
export { testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign } from './tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign';
export { testUseInvalidLitActionIpfsCodeToGenerateSessionSigs } from './tests/testUseInvalidLitActionIpfsCodeToGenerateSessionSigs';
@@ -163,7 +149,6 @@ export { testPkpEthersWithPkpSessionSigsToEthSignTypedDataUtil } from './tests/t
export { testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil } from './tests/testPkpEthersWithLitActionSessionSigsToEthSignTypedDataUtil';
export { testUseCustomAuthSessionSigsToPkpSignExecuteJs } from './tests/testUseCustomAuthSessionSigsToPkpSignExecuteJs';
export { testExecuteJsSignAndCombineEcdsa } from './tests/testExecuteJsSignAndCombineEcdsa';
-export { testExecuteJsDecryptAndCombine } from './tests/testExecuteJsDecryptAndCombine';
export { testExecuteJsBroadcastAndCollect } from './tests/testExecuteJsBroadcastAndCollect';
export { testRelayer } from './tests/testRelayer';
@@ -197,7 +182,7 @@ const relayerTests = {
// --filter=WrappedKey
const wrappedKeysTests = {
- // -- valid cases
+ // // -- valid cases
// testBatchGeneratePrivateKeys,
// testEthereumSignMessageGeneratedKey,
// testEthereumBroadcastTransactionGeneratedKey,
@@ -205,22 +190,22 @@ const wrappedKeysTests = {
// testEthereumSignTransactionWrappedKey,
// testEthereumBroadcastTransactionWrappedKey,
// testEthereumBroadcastWrappedKeyWithFetchGasParams,
- // -- generate wrapped keys
+ // // -- generate wrapped keys
// testGenerateEthereumWrappedKey,
// testGenerateSolanaWrappedKey,
- // -- import wrapped keys
+ // // -- import wrapped keys
// testImportWrappedKey,
- // -- export wrapped keys
+ // // -- export wrapped keys
// testExportWrappedKey,
- // -- solana wrapped keys
+ // // -- solana wrapped keys
// testSignMessageWithSolanaEncryptedKey,
// testSignTransactionWithSolanaEncryptedKey,
- // -- invalid cases
+ // // -- invalid cases
// testFailEthereumSignTransactionWrappedKeyWithMissingParam,
// testFailEthereumSignTransactionWrappedKeyWithInvalidParam,
// testFailEthereumSignTransactionWrappedKeyInvalidDecryption,
// testFailBatchGeneratePrivateKeysAtomic,
- // -- import wrapped keys
+ // // -- import wrapped keys
// testFailImportWrappedKeysWithSamePrivateKey,
// testFailImportWrappedKeysWithEoaSessionSig,
// testFailImportWrappedKeysWithMaxExpirySessionSig,
@@ -230,15 +215,13 @@ const wrappedKeysTests = {
const eoaSessionSigsTests = {
testUseEoaSessionSigsToExecuteJsSigning,
+ testUseEoaSessionSigsToRequestSingleResponse,
testUseEoaSessionSigsToPkpSign,
testUseEoaSessionSigsToExecuteJsSigningInParallel,
testUseEoaSessionSigsToExecuteJsClaimKeys,
testUseEoaSessionSigsToExecuteJsClaimMultipleKeys,
testUseEoaSessionSigsToExecuteJsJsonResponse,
testUseEoaSessionSigsToExecuteJsConsoleLog,
- testUseEoaSessionSigsToEncryptDecryptString,
- testUseEoaSessionSigsToEncryptDecryptUint8Array,
- testUseEoaSessionSigsToEncryptDecryptFile,
};
const pkpSessionSigsTests = {
@@ -249,8 +232,6 @@ const pkpSessionSigsTests = {
testUsePkpSessionSigsToExecuteJsClaimMultipleKeys,
testUsePkpSessionSigsToExecuteJsJsonResponse,
testUsePkpSessionSigsToExecuteJsConsoleLog,
- testUsePkpSessionSigsToEncryptDecryptString,
- testUsePkpSessionSigsToEncryptDecryptFile,
};
const litActionSessionSigsTests = {
@@ -261,8 +242,6 @@ const litActionSessionSigsTests = {
testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsClaimMultipleKeys,
testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsJsonResponse,
testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsConsoleLog,
- testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString,
- testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile,
// -- invalid cases
testUseInvalidLitActionIpfsCodeToGenerateSessionSigs,
@@ -288,6 +267,11 @@ const bareAuthSigTests = {
// testCosmosAuthSigToEncryptDecryptString,
};
+const eip1271AuthSigTests = {
+ // testKeccakEip1271AuthSigToEncryptDecryptString,
+ // testShaEip1271AuthSigToEncryptDecryptString,
+};
+
const pkpEthersTest = {
eoaSessionSigs: {
testPkpEthersWithEoaSessionSigsToSignWithAuthContext,
@@ -332,9 +316,6 @@ const litActionCombiningTests = {
ecdsaSignAndCombine: {
testExecuteJsSignAndCombineEcdsa,
},
- decryptAndCombine: {
- testExecuteJsDecryptAndCombine,
- },
broadcastAndCombine: {
testExecuteJsBroadcastAndCollect,
},
@@ -347,6 +328,7 @@ export const tinnyTests = {
...pkpSessionSigsTests,
...litActionSessionSigsTests,
...litActionIpfsIdSessionSigsTests,
+ ...eip1271AuthSigTests,
...bareAuthSigTests,
...pkpEthersTest.eoaSessionSigs,
@@ -354,7 +336,6 @@ export const tinnyTests = {
...pkpEthersTest.litActionSessionSigs,
...litActionCombiningTests.broadcastAndCombine,
- ...litActionCombiningTests.decryptAndCombine,
...litActionCombiningTests.ecdsaSignAndCombine,
...relayerTests,
diff --git a/local-tests/tests/test-bundle-speed.ts b/local-tests/tests/test-bundle-speed.ts
index 703b9017f3..f7eb09c867 100644
--- a/local-tests/tests/test-bundle-speed.ts
+++ b/local-tests/tests/test-bundle-speed.ts
@@ -9,7 +9,7 @@ export const testBundleSpeed = async (devEnv: TinnyEnvironment) => {
const b = await import('@lit-protocol/contracts-sdk');
const c = await import('@lit-protocol/auth-helpers');
const d = await import('@lit-protocol/constants');
- const e = await import('@lit-protocol/lit-auth-client');
+ const e = await import('@lit-protocol/auth');
console.log(a, b, c, d, e);
};
diff --git a/local-tests/tests/test-example.ts b/local-tests/tests/test-example.ts
deleted file mode 100644
index 7cf55fd939..0000000000
--- a/local-tests/tests/test-example.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { getEoaSessionSigs } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
-import { getLitActionSessionSigs } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
-import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
-
-import { LIT_NETWORK } from '@lit-protocol/constants';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-
-export const testExample = async (devEnv: TinnyEnvironment) => {
- // Note: This test will be skipped if we are testing on the DatilDev network
- devEnv.setUnavailable(LIT_NETWORK.DatilDev);
-
- const alice = await devEnv.createRandomPerson();
-
- const aliceEoaSessionSigs = await getEoaSessionSigs(devEnv, alice);
-
- const aliceExecuteJsRes = await devEnv.litNodeClient.executeJs({
- sessionSigs: aliceEoaSessionSigs,
- code: `(async () => {
- const sigShare = await LitActions.signEcdsa({
- toSign: dataToSign,
- publicKey,
- sigName: "sig",
- });
- })();`,
- jsParams: {
- dataToSign: alice.loveLetter,
- publicKey: alice.pkp.publicKey,
- },
- });
-
- console.log('aliceExecuteJsRes:', aliceExecuteJsRes);
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- // console.log('aliceEoaSessionSigs: ', aliceEoaSessionSigs);
-
- // const alicePkpSessionSigs = await getPkpSessionSigs(devEnv, alice);
- // console.log('alicePkpSessionSigs: ', alicePkpSessionSigs);
-
- // const aliceLitActionSessionSigs = await getLitActionSessionSigs(
- // devEnv,
- // alice
- // );
- // console.log('aliceLitActionSessionSigs: ', aliceLitActionSessionSigs);
-};
diff --git a/local-tests/tests/testExecuteJsDecryptAndCombine.ts b/local-tests/tests/testExecuteJsDecryptAndCombine.ts
deleted file mode 100644
index 5022f9f252..0000000000
--- a/local-tests/tests/testExecuteJsDecryptAndCombine.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { LIT_NETWORK } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { getLitActionAuthContext } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
- * ✅ NETWORK=custom yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
- *
- */
-export const testExecuteJsDecryptAndCombine = async (
- devEnv: TinnyEnvironment
-) => {
- const alice = await devEnv.createRandomPerson();
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.authMethodOwnedPkp.ethAddress,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const res = await devEnv.litNodeClient.executeJs({
- authContext: getLitActionAuthContext(devEnv, alice),
- code: `(async () => {
- const resp = await Lit.Actions.decryptAndCombine({
- accessControlConditions,
- ciphertext,
- dataToEncryptHash,
- authSig: null,
- chain: 'ethereum',
- });
- Lit.Actions.setResponse({
- response: resp
- });
- })();`,
- jsParams: {
- accessControlConditions: accs,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- ciphertext: encryptRes.ciphertext,
- },
- });
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (res.response !== 'Hello world') {
- throw new Error('content does not match what was expected');
- }
-};
diff --git a/local-tests/tests/testRelayer.ts b/local-tests/tests/testRelayer.ts
index 6b07955bc8..57c6b148ab 100644
--- a/local-tests/tests/testRelayer.ts
+++ b/local-tests/tests/testRelayer.ts
@@ -1,7 +1,8 @@
-import { log } from '@lit-protocol/misc';
import { ClaimRequest, ClientClaimProcessor } from '@lit-protocol/types';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { EthWalletProvider, LitRelay } from '@lit-protocol/lit-auth-client';
+import { authenticators, LitRelay } from '@lit-protocol/auth';
+
+const { MetamaskAuthenticator } = authenticators;
/**
* Test Commands:
@@ -18,20 +19,6 @@ export const testRelayer = async (devEnv: TinnyEnvironment) => {
relayUrl: LitRelay.getRelayUrl(devEnv.network),
relayApiKey: 'test-api-key',
});
- const ethWalletProvider = new EthWalletProvider({
- relay: litRelay,
- litNodeClient: devEnv.litNodeClient,
- });
-
- const pkps = await ethWalletProvider.fetchPKPsThroughRelayer(
- alice.authMethod
- );
-
- if (pkps.length <= 0) {
- throw new Error('No PKPs found');
- } else {
- console.log('✅ 1. [testRelayer] /fetch-pkps-by-auth-method works');
- }
// -- test claims
const claimRequest: ClaimRequest = {
@@ -102,5 +89,5 @@ export const testRelayer = async (devEnv: TinnyEnvironment) => {
}
});
- log('✅ 2. [testRelayer] Claim works');
+ console.log('✅ 2. [testRelayer] Claim works');
};
diff --git a/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptFile.ts b/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptFile.ts
deleted file mode 100644
index 18b76d5a58..0000000000
--- a/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptFile.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString, decryptToFile } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=datil-test yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=custom yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptFile
- */
-export const testUseEoaSessionSigsToEncryptDecryptFile = async (
- devEnv: TinnyEnvironment
-) => {
- const alice = await devEnv.createRandomPerson();
- const message = 'Hello world';
- const blob = new Blob([message], { type: 'text/plain' });
- const blobArray = new Uint8Array(await blob.arrayBuffer());
-
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.wallet.address,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // await 5 seconds for the encryption to be mined
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decriptedFile = await decryptToFile(
- {
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- authContext: getEoaAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (blobArray.length !== decriptedFile.length) {
- throw new Error(
- `decrypted file should match the original file but received ${decriptedFile}`
- );
- }
- for (let i = 0; i < blobArray.length; i++) {
- if (blobArray[i] !== decriptedFile[i]) {
- throw new Error(`decrypted file should match the original file`);
- }
- }
-
- console.log('decriptedFile:', decriptedFile);
-};
diff --git a/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptString.ts b/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptString.ts
deleted file mode 100644
index 0b7a6676d3..0000000000
--- a/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptString.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-// DEBUG=true LIT_RPC_URL=https://yellowstone-rpc.litprotocol.com NETWORK=custom yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptString
-import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString, decryptToString } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptString
- * ✅ NETWORK=datil-test yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptString
- * ✅ NETWORK=custom yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptString
- */
-export const testUseEoaSessionSigsToEncryptDecryptString = async (
- devEnv: TinnyEnvironment
-) => {
- const alice = await devEnv.createRandomPerson();
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.wallet.address,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // await 5 seconds for the encryption to be mined
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decryptRes = await decryptToString(
- {
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- authContext: getEoaAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (decryptRes !== 'Hello world') {
- throw new Error(
- `Expected decryptRes to be 'Hello world' but got ${decryptRes}`
- );
- }
-};
diff --git a/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptUint8Array.ts b/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptUint8Array.ts
deleted file mode 100644
index 20e29dba02..0000000000
--- a/local-tests/tests/testUseEoaSessionSigsToEncryptDecryptUint8Array.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import {
- encryptUint8Array,
- decryptToUint8Array,
-} from '@lit-protocol/encryption';
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptUint8Array
- * ✅ NETWORK=datil-test yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptUint8Array
- * ✅ NETWORK=custom yarn test:local --filter=testUseEoaSessionSigsToEncryptDecryptUint8Array
- */
-export const testUseEoaSessionSigsToEncryptDecryptUint8Array = async (
- devEnv: TinnyEnvironment
-) => {
- const alice = await devEnv.createRandomPerson();
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.wallet.address,
- });
-
- const message = 'Hello world';
- const messageToEncrypt = uint8arrayFromString(message, 'utf8');
-
- const encryptRes = await encryptUint8Array(
- {
- accessControlConditions: accs,
- dataToEncrypt: messageToEncrypt,
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // await 5 seconds for the encryption to be mined
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decryptRes = await decryptToUint8Array(
- {
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- authContext: getEoaAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
- const decryptResString = uint8arrayToString(decryptRes, 'utf8');
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (decryptResString !== message) {
- throw new Error(
- `Expected decryptRes to be 'Hello world' but got ${decryptRes}`
- );
- }
-};
diff --git a/local-tests/tests/testUseEoaSessionSigsToExecuteJsClaimKeys.ts b/local-tests/tests/testUseEoaSessionSigsToExecuteJsClaimKeys.ts
index 9fb521bd90..ba0b98a7da 100644
--- a/local-tests/tests/testUseEoaSessionSigsToExecuteJsClaimKeys.ts
+++ b/local-tests/tests/testUseEoaSessionSigsToExecuteJsClaimKeys.ts
@@ -1,13 +1,5 @@
-// import { LitContracts } from '@lit-protocol/contracts-sdk';
-// import { log } from '@lit-protocol/misc';
-// import {
-// ClaimRequest,
-// ClaimResult,
-// ClientClaimProcessor,
-// } from '@lit-protocol/types';
import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
/**
* ## Scenario:
@@ -174,5 +166,5 @@ export const testUseEoaSessionSigsToExecuteJsClaimKeys = async (
// }
// });
- log('✅ testUseEoaSessionSigsToExecuteJsClaimKeys');
+ console.log('✅ testUseEoaSessionSigsToExecuteJsClaimKeys');
};
diff --git a/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigning.ts b/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigning.ts
index 415572de85..cc17a962d8 100644
--- a/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigning.ts
+++ b/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigning.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -62,5 +61,5 @@ export const testUseEoaSessionSigsToExecuteJsSigning = async (
throw new Error(`Expected "publicKey" in res.signatures.sig`);
}
- log('✅ testUseEoaSessionSigsToExecuteJsSigning');
+ console.log('✅ testUseEoaSessionSigsToExecuteJsSigning');
};
diff --git a/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigningInParallel.ts b/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigningInParallel.ts
index a3782ebbcd..ca2894abaa 100644
--- a/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigningInParallel.ts
+++ b/local-tests/tests/testUseEoaSessionSigsToExecuteJsSigningInParallel.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -14,7 +13,7 @@ export const testUseEoaSessionSigsToExecuteJsSigningInParallel = async (
const alice = await devEnv.createRandomPerson();
const fn = async (index: number) => {
- log(`Index: ${index}`);
+ console.log(`Index: ${index}`);
return await devEnv.litNodeClient.executeJs({
authContext: getEoaAuthContext(devEnv, alice),
@@ -34,7 +33,7 @@ export const testUseEoaSessionSigsToExecuteJsSigningInParallel = async (
const res = await Promise.all([fn(1), fn(2), fn(3)]);
devEnv.releasePrivateKeyFromUser(alice);
- log('res:', res);
+ console.log('res:', res);
// -- Expected output:
// [
@@ -114,5 +113,5 @@ export const testUseEoaSessionSigsToExecuteJsSigningInParallel = async (
}
});
- log('✅ testUseEoaSessionSigsToExecuteJsSigningInParallel');
+ console.log('✅ testUseEoaSessionSigsToExecuteJsSigningInParallel');
};
diff --git a/local-tests/tests/testUseEoaSessionSigsToPkpSign.ts b/local-tests/tests/testUseEoaSessionSigsToPkpSign.ts
index 0431da2142..852c1da223 100644
--- a/local-tests/tests/testUseEoaSessionSigsToPkpSign.ts
+++ b/local-tests/tests/testUseEoaSessionSigsToPkpSign.ts
@@ -1,6 +1,5 @@
import { ethers } from 'ethers';
-import { log } from '@lit-protocol/misc';
import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -82,5 +81,5 @@ export const testUseEoaSessionSigsToPkpSign = async (
);
}
- log('✅ testUseEoaSessionSigsToPkpSign');
+ console.log('✅ testUseEoaSessionSigsToPkpSign');
};
diff --git a/local-tests/tests/testUsePkpSessionSigsToEncryptDecryptFile.ts b/local-tests/tests/testUsePkpSessionSigsToEncryptDecryptFile.ts
deleted file mode 100644
index d854df3574..0000000000
--- a/local-tests/tests/testUsePkpSessionSigsToEncryptDecryptFile.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import { getPkpAuthContext } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString, decryptToFile } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUsePkpSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=datil-test yarn test:local --filter=testUsePkpSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=custom yarn test:local --filter=testUsePkpSessionSigsToEncryptDecryptFile
- */
-export const testUsePkpSessionSigsToEncryptDecryptFile = async (
- devEnv: TinnyEnvironment
-) => {
- const alice = await devEnv.createRandomPerson();
-
- const message = 'Hello world';
- const blob = new Blob([message], { type: 'text/plain' });
- const blobArray = new Uint8Array(await blob.arrayBuffer());
-
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.authMethodOwnedPkp.ethAddress,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // await 5 seconds for the encryption to be mined
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decriptedFile = await decryptToFile(
- {
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- authContext: getPkpAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (blobArray.length !== decriptedFile.length) {
- throw new Error(
- `decrypted file should match the original file but received ${decriptedFile}`
- );
- }
- for (let i = 0; i < blobArray.length; i++) {
- if (blobArray[i] !== decriptedFile[i]) {
- throw new Error(`decrypted file should match the original file`);
- }
- }
-
- console.log('decriptedFile:', decriptedFile);
-};
diff --git a/local-tests/tests/testUsePkpSessionSigsToEncryptDecryptString.ts b/local-tests/tests/testUsePkpSessionSigsToEncryptDecryptString.ts
deleted file mode 100644
index 54c8c76207..0000000000
--- a/local-tests/tests/testUsePkpSessionSigsToEncryptDecryptString.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import { getPkpAuthContext } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString, decryptToString } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUsePkpSessionSigsToEncryptDecryptString
- * ✅ NETWORK=datil-test yarn test:local --filter=testUsePkpSessionSigsToEncryptDecryptString
- * ✅ NETWORK=custom yarn test:local --filter=testUsePkpSessionSigsToEncryptDecryptString
- */
-export const testUsePkpSessionSigsToEncryptDecryptString = async (
- devEnv: TinnyEnvironment
-) => {
- const alice = await devEnv.createRandomPerson();
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.authMethodOwnedPkp.ethAddress,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decryptRes = await decryptToString(
- {
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- authContext: getPkpAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (decryptRes !== 'Hello world') {
- throw new Error(
- `Expected decryptRes to be 'Hello world' but got ${decryptRes}`
- );
- }
-};
diff --git a/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigning.ts b/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigning.ts
index 982dbe0142..53a17cc73a 100644
--- a/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigning.ts
+++ b/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigning.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { getPkpAuthContext } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -76,5 +75,5 @@ export const testUsePkpSessionSigsToExecuteJsSigning = async (
throw new Error(`Expected "recid" to be parseable as a number`);
}
- log('✅ res:', res);
+ console.log('✅ res:', res);
};
diff --git a/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigningInParallel.ts b/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigningInParallel.ts
index 28b467e4c8..ec530e2950 100644
--- a/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigningInParallel.ts
+++ b/local-tests/tests/testUsePkpSessionSigsToExecuteJsSigningInParallel.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { getPkpAuthContext } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -14,7 +13,7 @@ export const testUsePkpSessionSigsToExecuteJsSigningInParallel = async (
const alice = await devEnv.createRandomPerson();
const fn = async (index: number) => {
- log(`Index: ${index}`);
+ console.log(`Index: ${index}`);
return await devEnv.litNodeClient.executeJs({
authContext: getPkpAuthContext(devEnv, alice),
@@ -35,7 +34,7 @@ export const testUsePkpSessionSigsToExecuteJsSigningInParallel = async (
devEnv.releasePrivateKeyFromUser(alice);
const res = await Promise.all([fn(1), fn(2), fn(3)]);
- log('res:', res);
+ console.log('res:', res);
// -- Expected output:
// [
@@ -115,5 +114,5 @@ export const testUsePkpSessionSigsToExecuteJsSigningInParallel = async (
}
});
- log('✅ testUsePkpSessionSigsToExecuteJsSigningInParallel');
+ console.log('✅ testUsePkpSessionSigsToExecuteJsSigningInParallel');
};
diff --git a/local-tests/tests/testUsePkpSessionSigsToPkpSign.ts b/local-tests/tests/testUsePkpSessionSigsToPkpSign.ts
index 3f54db9f58..87c369b059 100644
--- a/local-tests/tests/testUsePkpSessionSigsToPkpSign.ts
+++ b/local-tests/tests/testUsePkpSessionSigsToPkpSign.ts
@@ -1,6 +1,5 @@
import { ethers } from 'ethers';
-import { log } from '@lit-protocol/misc';
import { getPkpAuthContext } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -88,5 +87,5 @@ export const testUsePkpSessionSigsToPkpSign = async (
// );
}
- log('✅ res:', res);
+ console.log('✅ res:', res);
};
diff --git a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile.ts b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile.ts
deleted file mode 100644
index e5772f31a9..0000000000
--- a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import { getPkpAuthContext } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString, decryptToFile } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=datil-test yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=custom yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile
- */
-export const testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptFile =
- async (devEnv: TinnyEnvironment) => {
- const alice = await devEnv.createRandomPerson();
-
- const message = 'Hello world';
- const blob = new Blob([message], { type: 'text/plain' });
- const blobArray = new Uint8Array(await blob.arrayBuffer());
-
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.authMethodOwnedPkp.ethAddress,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // await 5 seconds for the encryption to be mined
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decriptedFile = await decryptToFile(
- {
- authContext: getPkpAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (blobArray.length !== decriptedFile.length) {
- throw new Error(
- `decrypted file should match the original file but received ${decriptedFile}`
- );
- }
- for (let i = 0; i < blobArray.length; i++) {
- if (blobArray[i] !== decriptedFile[i]) {
- throw new Error(`decrypted file should match the original file`);
- }
- }
-
- console.log('decriptedFile:', decriptedFile);
- };
diff --git a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString.ts b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString.ts
deleted file mode 100644
index b066bdcbf2..0000000000
--- a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { LIT_ABILITY } from '@lit-protocol/constants';
-import { ILitNodeClient } from '@lit-protocol/types';
-import { AccessControlConditions } from 'local-tests/setup/accs/accs';
-import { LitAccessControlConditionResource } from '@lit-protocol/auth-helpers';
-import { getLitActionAuthContext } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
-import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
-import { log } from '@lit-protocol/misc';
-import { encryptString, decryptToString } from '@lit-protocol/encryption';
-
-/**
- * Test Commands:
- * ✅ NETWORK=datil-dev yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
- * ✅ NETWORK=custom yarn test:local --filter=testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString
- *
- */
-export const testUseValidLitActionCodeGeneratedSessionSigsToEncryptDecryptString =
- async (devEnv: TinnyEnvironment) => {
- const alice = await devEnv.createRandomPerson();
- // set access control conditions for encrypting and decrypting
- const accs = AccessControlConditions.getEvmBasicAccessControlConditions({
- userAddress: alice.authMethodOwnedPkp.ethAddress,
- });
-
- const encryptRes = await encryptString(
- {
- accessControlConditions: accs,
- dataToEncrypt: 'Hello world',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- log('encryptRes:', encryptRes);
-
- // -- Expected output:
- // {
- // ciphertext: "pSP1Rq4xdyLBzSghZ3DtTtHp2UL7/z45U2JDOQho/WXjd2ntr4IS8BJfqJ7TC2U4CmktrvbVT3edoXJgFqsE7vy9uNrBUyUSTuUdHLfDVMIgh4a7fqMxsdQdkWZjHign3JOaVBihtOjAF5VthVena28D",
- // dataToEncryptHash: "64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c",
- // }
-
- // -- assertions
- if (!encryptRes.ciphertext) {
- throw new Error(`Expected "ciphertext" in encryptRes`);
- }
-
- if (!encryptRes.dataToEncryptHash) {
- throw new Error(`Expected "dataToEncryptHash" to in encryptRes`);
- }
-
- const accsResourceString =
- await LitAccessControlConditionResource.generateResourceString(
- accs,
- encryptRes.dataToEncryptHash
- );
-
- // -- Decrypt the encrypted string
- const decryptRes = await decryptToString(
- {
- accessControlConditions: accs,
- ciphertext: encryptRes.ciphertext,
- dataToEncryptHash: encryptRes.dataToEncryptHash,
- authContext: getLitActionAuthContext(devEnv, alice, [
- {
- resource: new LitAccessControlConditionResource(accsResourceString),
- ability: LIT_ABILITY.AccessControlConditionDecryption,
- },
- ]),
- chain: 'ethereum',
- },
- devEnv.litNodeClient as unknown as ILitNodeClient
- );
-
- devEnv.releasePrivateKeyFromUser(alice);
-
- if (decryptRes !== 'Hello world') {
- throw new Error(
- `Expected decryptRes to be 'Hello world' but got ${decryptRes}`
- );
- }
- };
diff --git a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning.ts b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning.ts
index 3191ae21ef..3d68cc4412 100644
--- a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning.ts
+++ b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning.ts
@@ -1,6 +1,6 @@
import { LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers';
-import { log } from '@lit-protocol/misc';
import { LIT_ABILITY } from '@lit-protocol/constants';
+
import { getLitActionAuthContext } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -74,5 +74,5 @@ export const testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigning =
throw new Error(`Expected "publicKey" in res.signatures.sig`);
}
- log('✅ res:', res);
+ console.log('✅ res:', res);
};
diff --git a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel.ts b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel.ts
index 867098a092..138f15cc38 100644
--- a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel.ts
+++ b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInParallel.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { getLitActionAuthContext } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -12,7 +11,7 @@ export const testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInPa
const alice = await devEnv.createRandomPerson();
const fn = async (index: number) => {
- log(`Index: ${index}`);
+ console.log(`Index: ${index}`);
return await devEnv.litNodeClient.executeJs({
authContext: getLitActionAuthContext(devEnv, alice),
@@ -33,7 +32,7 @@ export const testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInPa
devEnv.releasePrivateKeyFromUser(alice);
const res = await Promise.all([fn(1), fn(2), fn(3)]);
- log('res:', res);
+ console.log('res:', res);
// -- Expected output:
// [
@@ -113,5 +112,5 @@ export const testUseValidLitActionCodeGeneratedSessionSigsToExecuteJsSigningInPa
}
});
- log('✅ testUsePkpSessionSigsToExecuteJsSigningInParallel');
+ console.log('✅ testUsePkpSessionSigsToExecuteJsSigningInParallel');
};
diff --git a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToPkpSign.ts b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToPkpSign.ts
index b59abac7cc..b60f2ed78a 100644
--- a/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToPkpSign.ts
+++ b/local-tests/tests/testUseValidLitActionCodeGeneratedSessionSigsToPkpSign.ts
@@ -1,6 +1,5 @@
import { ethers } from 'ethers';
-import { log } from '@lit-protocol/misc';
import { getLitActionAuthContext } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -78,5 +77,5 @@ export const testUseValidLitActionCodeGeneratedSessionSigsToPkpSign = async (
);
}
- log('✅ res:', res);
+ console.log('✅ res:', res);
};
diff --git a/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning.ts b/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning.ts
index ab92a4127e..09762db841 100644
--- a/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning.ts
+++ b/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning.ts
@@ -1,6 +1,6 @@
import { LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers';
-import { log } from '@lit-protocol/misc';
import { LIT_ABILITY } from '@lit-protocol/constants';
+
import { getLitActionAuthContextUsingIpfsId } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -73,5 +73,5 @@ export const testUseValidLitActionIpfsCodeGeneratedSessionSigsToExecuteJsSigning
throw new Error(`Expected "publicKey" in res.signatures.sig`);
}
- log('✅ res:', res);
+ console.log('✅ res:', res);
};
diff --git a/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign.ts b/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign.ts
index 94fd353569..205fbe329a 100644
--- a/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign.ts
+++ b/local-tests/tests/testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign.ts
@@ -1,6 +1,5 @@
import { ethers } from 'ethers';
-import { log } from '@lit-protocol/misc';
import { getLitActionAuthContextUsingIpfsId } from 'local-tests/setup/session-sigs/get-lit-action-session-sigs';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -78,5 +77,5 @@ export const testUseValidLitActionIpfsCodeGeneratedSessionSigsToPkpSign =
);
}
- log('✅ res:', res);
+ console.log('✅ res:', res);
};
diff --git a/local-tests/tests/wrapped-keys/testBatchGeneratePrivateKeys.ts b/local-tests/tests/wrapped-keys/testBatchGeneratePrivateKeys.ts
index b2c40701bf..486750a7ca 100644
--- a/local-tests/tests/wrapped-keys/testBatchGeneratePrivateKeys.ts
+++ b/local-tests/tests/wrapped-keys/testBatchGeneratePrivateKeys.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
@@ -129,7 +128,7 @@ export const testBatchGeneratePrivateKeys = async (
await verifyEvmSignature(results[0], evmMessageToSign);
console.log('results', results);
- log('✅ testBatchGenerateEncryptedKeys');
+ console.log('✅ testBatchGenerateEncryptedKeys');
} catch (err) {
console.log(err.message, err, err.stack);
throw err;
diff --git a/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionGeneratedKey.ts b/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionGeneratedKey.ts
index 3df75c6de5..3a32b2ea98 100644
--- a/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionGeneratedKey.ts
+++ b/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionGeneratedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys';
@@ -75,7 +74,7 @@ export const testEthereumBroadcastTransactionGeneratedKey = async (
throw new Error(`signedTx isn't hex: ${signedTx}`);
}
- log('✅ testEthereumBroadcastTransactionGeneratedKey');
+ console.log('✅ testEthereumBroadcastTransactionGeneratedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionWrappedKey.ts b/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionWrappedKey.ts
index c10593c782..47e678506d 100644
--- a/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testEthereumBroadcastTransactionWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys';
@@ -80,7 +79,7 @@ export const testEthereumBroadcastTransactionWrappedKey = async (
throw new Error(`signedTx isn't hex: ${signedTx}`);
}
- log('✅ testEthereumBroadcastTransactionWrappedKey');
+ console.log('✅ testEthereumBroadcastTransactionWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts b/local-tests/tests/wrapped-keys/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts
index 75804f35cb..6fa8268183 100644
--- a/local-tests/tests/wrapped-keys/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts
+++ b/local-tests/tests/wrapped-keys/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys';
@@ -84,7 +83,7 @@ export const testEthereumBroadcastWrappedKeyWithFetchGasParams = async (
throw new Error(`signedTx isn't hex: ${signedTx}`);
}
- log('✅ testEthereumBroadcastWrappedKeyWithDefaultGasParams');
+ console.log('✅ testEthereumBroadcastWrappedKeyWithDefaultGasParams');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testEthereumSignMessageGeneratedKey.ts b/local-tests/tests/wrapped-keys/testEthereumSignMessageGeneratedKey.ts
index e85336caad..8318421c65 100644
--- a/local-tests/tests/wrapped-keys/testEthereumSignMessageGeneratedKey.ts
+++ b/local-tests/tests/wrapped-keys/testEthereumSignMessageGeneratedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
@@ -90,7 +89,7 @@ export const testEthereumSignMessageGeneratedKey = async (
);
}
- log('✅ testEthereumSignMessageGeneratedKey');
+ console.log('✅ testEthereumSignMessageGeneratedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testEthereumSignMessageWrappedKey.ts b/local-tests/tests/wrapped-keys/testEthereumSignMessageWrappedKey.ts
index 08594ace4d..d95afdba41 100644
--- a/local-tests/tests/wrapped-keys/testEthereumSignMessageWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testEthereumSignMessageWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
@@ -94,7 +93,7 @@ export const testEthereumSignMessageWrappedKey = async (
);
}
- log('✅ testEthereumSignMessageWrappedKey');
+ console.log('✅ testEthereumSignMessageWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testEthereumSignTransactionWrappedKey.ts b/local-tests/tests/wrapped-keys/testEthereumSignTransactionWrappedKey.ts
index ac6c6bc983..6e0f83a3a1 100644
--- a/local-tests/tests/wrapped-keys/testEthereumSignTransactionWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testEthereumSignTransactionWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
@@ -76,7 +75,7 @@ export const testEthereumSignTransactionWrappedKey = async (
throw new Error(`signedTx isn't hex: ${signedTx}`);
}
- log('✅ testEthereumSignTransactionWrappedKey');
+ console.log('✅ testEthereumSignTransactionWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testExportWrappedKey.ts b/local-tests/tests/wrapped-keys/testExportWrappedKey.ts
index 50f41c142b..f59b562023 100644
--- a/local-tests/tests/wrapped-keys/testExportWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testExportWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from '../../setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { getPkpSessionSigs } from '../../setup/session-sigs/get-pkp-session-sigs';
@@ -64,7 +63,7 @@ export const testExportWrappedKey = async (devEnv: TinnyEnvironment) => {
);
}
- log('✅ testExportWrappedKey');
+ console.log('✅ testExportWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts b/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts
index b62bc52c84..e13011e78e 100644
--- a/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts
+++ b/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts
@@ -1,8 +1,6 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
-import { encryptString } from '@lit-protocol/encryption';
import { LIT_PREFIX } from 'packages/wrapped-keys/src/lib/constants';
import { LIT_ACTION_CID_REPOSITORY } from '../../../packages/wrapped-keys/src/lib/lit-actions-client/constants';
import { getBaseTransactionForNetwork } from './util';
@@ -25,13 +23,11 @@ export const testFailEthereumSignTransactionWrappedKeyInvalidDecryption =
const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress;
const decryptionAccessControlCondition =
getPkpAccessControlCondition(alicePkpAddress);
- const { ciphertext, dataToEncryptHash } = await encryptString(
- {
+ const { ciphertext, dataToEncryptHash } =
+ await devEnv.litNodeClient.encrypt({
accessControlConditions: [decryptionAccessControlCondition],
- dataToEncrypt: LIT_PREFIX + privateKey,
- },
- devEnv.litNodeClient
- );
+ dataToEncrypt: Buffer.from(LIT_PREFIX + privateKey, 'utf8'),
+ });
const pkpSessionSigsSigning = await getPkpSessionSigs(
devEnv,
@@ -79,7 +75,9 @@ export const testFailEthereumSignTransactionWrappedKeyInvalidDecryption =
}
}
- log('✅ testFailEthereumSignTransactionWrappedKeyInvalidDecryption');
+ console.log(
+ '✅ testFailEthereumSignTransactionWrappedKeyInvalidDecryption'
+ );
} finally {
devEnv.releasePrivateKeyFromUser(alice);
devEnv.releasePrivateKeyFromUser(bob);
diff --git a/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts b/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts
index 88b98abbf5..4ee61c0b86 100644
--- a/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts
+++ b/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys';
@@ -82,7 +81,7 @@ export const testFailEthereumSignTransactionWrappedKeyWithInvalidParam = async (
}
}
- log('✅ testFailEthereumSignTransactionWrappedKeyWithInvalidParam');
+ console.log('✅ testFailEthereumSignTransactionWrappedKeyWithInvalidParam');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts b/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts
index adb2b76a35..cec8b565e2 100644
--- a/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts
+++ b/local-tests/tests/wrapped-keys/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { ethers } from 'ethers';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
@@ -77,7 +76,7 @@ export const testFailEthereumSignTransactionWrappedKeyWithMissingParam = async (
}
}
- log('✅ testFailEthereumSignTransactionWrappedKeyWithMissingParam');
+ console.log('✅ testFailEthereumSignTransactionWrappedKeyWithMissingParam');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testFailStoreEncryptedKeyBatchIsAtomic.ts b/local-tests/tests/wrapped-keys/testFailStoreEncryptedKeyBatchIsAtomic.ts
index 7716838387..073c500588 100644
--- a/local-tests/tests/wrapped-keys/testFailStoreEncryptedKeyBatchIsAtomic.ts
+++ b/local-tests/tests/wrapped-keys/testFailStoreEncryptedKeyBatchIsAtomic.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
@@ -115,7 +114,7 @@ export const testFailBatchGeneratePrivateKeysAtomic = async (
);
} catch (err) {
if (err.message.includes('No keys exist for pkpAddress')) {
- log('✅ testFailBatchGeneratePrivateKeysAtomic');
+ console.log('✅ testFailBatchGeneratePrivateKeysAtomic');
} else {
throw err;
}
diff --git a/local-tests/tests/wrapped-keys/testGenerateEthereumWrappedKey.ts b/local-tests/tests/wrapped-keys/testGenerateEthereumWrappedKey.ts
index 5f0c22aa37..743d926692 100644
--- a/local-tests/tests/wrapped-keys/testGenerateEthereumWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testGenerateEthereumWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
@@ -65,7 +64,7 @@ export const testGenerateEthereumWrappedKey = async (
);
}
- log('✅ testGenerateEthereumWrappedKey');
+ console.log('✅ testGenerateEthereumWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testGenerateSolanaWrappedKey.ts b/local-tests/tests/wrapped-keys/testGenerateSolanaWrappedKey.ts
index 1bcb239ce2..532bdcd112 100644
--- a/local-tests/tests/wrapped-keys/testGenerateSolanaWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testGenerateSolanaWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
@@ -102,7 +101,7 @@ export const testGenerateSolanaWrappedKey = async (
);
}
- log('✅ testGenerateSolanaWrappedKey');
+ console.log('✅ testGenerateSolanaWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testImportWrappedKey.ts b/local-tests/tests/wrapped-keys/testImportWrappedKey.ts
index 9c2bdfd00c..d3fe9b7da1 100644
--- a/local-tests/tests/wrapped-keys/testImportWrappedKey.ts
+++ b/local-tests/tests/wrapped-keys/testImportWrappedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs';
@@ -53,7 +52,7 @@ export const testImportWrappedKey = async (devEnv: TinnyEnvironment) => {
);
}
- log('✅ testImportWrappedKey');
+ console.log('✅ testImportWrappedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testSignMessageWithSolanaEncryptedKey.ts b/local-tests/tests/wrapped-keys/testSignMessageWithSolanaEncryptedKey.ts
index b182f3e27d..a00ffbde5e 100644
--- a/local-tests/tests/wrapped-keys/testSignMessageWithSolanaEncryptedKey.ts
+++ b/local-tests/tests/wrapped-keys/testSignMessageWithSolanaEncryptedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { api } from '@lit-protocol/wrapped-keys';
import { Keypair } from '@solana/web3.js';
@@ -77,7 +76,7 @@ export const testSignMessageWithSolanaEncryptedKey = async (
`signature: ${signature} doesn't validate for the Solana public key: ${solanaKeypair.publicKey.toString()}`
);
- log('✅ testSignMessageWithSolanaEncryptedKey');
+ console.log('✅ testSignMessageWithSolanaEncryptedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/local-tests/tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey.ts b/local-tests/tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey.ts
index 138d2c5b53..bd9af84d06 100644
--- a/local-tests/tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey.ts
+++ b/local-tests/tests/wrapped-keys/testSignTransactionWithSolanaEncryptedKey.ts
@@ -1,4 +1,3 @@
-import { log } from '@lit-protocol/misc';
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
import { SerializedTransaction, api } from '@lit-protocol/wrapped-keys';
import {
@@ -135,7 +134,7 @@ export const testSignTransactionWithSolanaEncryptedKey = async (
);
}
- log('✅ testSignMessageWithSolanaEncryptedKey');
+ console.log('✅ testSignMessageWithSolanaEncryptedKey');
} finally {
devEnv.releasePrivateKeyFromUser(alice);
}
diff --git a/package.json b/package.json
index 60518533c8..f0f93e9b49 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"publish:staging": "yarn node ./tools/scripts/pub.mjs --tag staging",
"build:tinny": "node ./local-tests/build.mjs",
"publish:tinny": "cd ./local-tests && npm publish",
+ "gen:context": "bun run packages/networks/src/lib/networks/vNaga/local-develop/getCustomContext.ts",
"gen:docs": "node ./tools/scripts/gen-doc.mjs",
"gen:readme": "yarn node ./tools/scripts/gen-readme.mjs",
"tools": "yarn node ./tools/scripts/tools.mjs",
@@ -40,9 +41,10 @@
"@cosmjs/proto-signing": "0.30.1",
"@cosmjs/stargate": "0.30.1",
"@dotenvx/dotenvx": "^1.6.4",
- "@lit-protocol/contracts": "^0.0.86",
+ "@lit-protocol/contracts": "^0.1.7",
"@metamask/eth-sig-util": "5.0.2",
"@mysten/sui.js": "^0.37.1",
+ "@noble/curves": "^1.8.1",
"@openagenda/verror": "^3.1.4",
"@simplewebauthn/browser": "^7.2.0",
"@simplewebauthn/typescript-types": "^7.0.0",
@@ -54,21 +56,26 @@
"abitype": "^1.0.8",
"base64url": "^3.0.1",
"bech32": "^2.0.0",
+ "bs58": "^6.0.0",
"cbor-web": "^9.0.2",
"cross-fetch": "3.1.8",
"date-and-time": "^2.4.1",
"depd": "^2.0.0",
+ "elysia": "^1.2.25",
"ethers": "^5.7.1",
"jose": "^4.14.4",
"micromodal": "^0.4.10",
"multiformats": "^9.7.1",
"pako": "^2.1.0",
+ "pino": "^9.6.0",
+ "pino-pretty": "^13.0.0",
"siwe": "^2.3.2",
"siwe-recap": "0.0.2-alpha.0",
+ "stytch": "^12.4.0",
"tslib": "^2.7.0",
"tweetnacl": "^1.0.3",
- "tweetnacl-util": "^0.15.1",
"uint8arrays": "^4.0.3",
+ "wagmi": "^2.14.13",
"zod": "^3.24.2",
"zod-validation-error": "^3.4.0"
},
@@ -88,7 +95,7 @@
"@types/depd": "^1.1.36",
"@types/events": "^3.0.3",
"@types/jest": "27.4.1",
- "@types/node": "18.19.18",
+ "@types/node": "20",
"@types/secp256k1": "^4.0.6",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
@@ -111,13 +118,15 @@
"eslint-plugin-jsx-a11y": "6.9.0",
"inquirer": "^9.2.21",
"ipfs-unixfs-importer": "12.0.1",
- "jest": "27.5.1",
+ "jest": "^29.2.2",
+ "jest-environment-jsdom": "^29.7.0",
"lerna": "^5.4.3",
"live-server": "^1.2.2",
"node-fetch": "^2.6.1",
"node-localstorage": "^3.0.5",
"nx": "17.3.0",
"path": "^0.12.7",
+ "pino-pretty": "^13.0.0",
"prettier": "^2.6.2",
"ts-jest": "29.2.5",
"typedoc": "^0.26.6",
diff --git a/packages/access-control-conditions-schemas/project.json b/packages/access-control-conditions-schemas/project.json
index 683b67e7f8..91e13e6dac 100644
--- a/packages/access-control-conditions-schemas/project.json
+++ b/packages/access-control-conditions-schemas/project.json
@@ -30,7 +30,7 @@
]
}
},
- "testPackage": {
+ "test": {
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/packages/access-control-conditions-schemas"
diff --git a/packages/access-control-conditions/src/index.ts b/packages/access-control-conditions/src/index.ts
index ac7cbe3e77..1b512cc351 100644
--- a/packages/access-control-conditions/src/index.ts
+++ b/packages/access-control-conditions/src/index.ts
@@ -1,3 +1,4 @@
+export * from './lib/booleanExpressions';
export * from './lib/canonicalFormatter';
export * from './lib/hashing';
export * from './lib/humanizer';
diff --git a/packages/misc/src/lib/utils.ts b/packages/access-control-conditions/src/lib/booleanExpressions.ts
similarity index 82%
rename from packages/misc/src/lib/utils.ts
rename to packages/access-control-conditions/src/lib/booleanExpressions.ts
index ea7ef45536..f01e53c7d2 100644
--- a/packages/misc/src/lib/utils.ts
+++ b/packages/access-control-conditions/src/lib/booleanExpressions.ts
@@ -1,3 +1,4 @@
+import { OperatorAccSchema } from '@lit-protocol/access-control-conditions-schemas';
import {
AccessControlConditions,
EvmContractConditions,
@@ -5,9 +6,8 @@ import {
UnifiedAccessControlConditions,
} from '@lit-protocol/types';
-export function isTokenOperator(token: any): boolean {
- const OPERATORS = ['and', 'or']; // Only permissible boolean operators on the nodes
- return token.hasOwnProperty('operator') && OPERATORS.includes(token.operator);
+export function isTokenOperator(token: unknown): boolean {
+ return OperatorAccSchema.safeParse(token).success;
}
export function isValidBooleanExpression(
diff --git a/packages/access-control-conditions/src/lib/canonicalFormatter.spec.ts b/packages/access-control-conditions/src/lib/canonicalFormatter.spec.ts
index d0f36b7146..b3e925539e 100644
--- a/packages/access-control-conditions/src/lib/canonicalFormatter.spec.ts
+++ b/packages/access-control-conditions/src/lib/canonicalFormatter.spec.ts
@@ -1,4 +1,6 @@
+import { InvalidAccessControlConditions } from '@lit-protocol/constants';
import { ConditionItem } from '@lit-protocol/types';
+
import {
canonicalUnifiedAccessControlConditionFormatter,
canonicalSolRpcConditionFormatter,
@@ -11,7 +13,7 @@ import {
// ---------- Test Cases ----------
describe('canonicalFormatter.ts', () => {
it('should format canonical unified access control (ETH + SOLANA Wallet Addresses with "AND" operator)', async () => {
- const EXPECTED_INPUT: Array = [
+ const EXPECTED_INPUT: ConditionItem[] = [
{
conditionType: 'evmBasic',
contractAddress: '',
@@ -74,19 +76,14 @@ describe('canonicalFormatter.ts', () => {
},
];
- const test =
- canonicalUnifiedAccessControlConditionFormatter(EXPECTED_INPUT);
-
- expect(test).toStrictEqual(EXPECTED_OUTPUT);
+ expect(
+ canonicalUnifiedAccessControlConditionFormatter(EXPECTED_INPUT)
+ ).toStrictEqual(EXPECTED_OUTPUT);
});
it('should FAIL to format canonical unified access control if key "conditionType" doesnt exist', async () => {
- console.log = jest.fn();
-
- let test;
-
- try {
- test = canonicalUnifiedAccessControlConditionFormatter([
+ expect(() =>
+ canonicalUnifiedAccessControlConditionFormatter([
{
contractAddress: '',
standardContractType: '',
@@ -98,84 +95,60 @@ describe('canonicalFormatter.ts', () => {
value: '0x3B5dD260598B7579A0b015A1F3BBF322aDC499A2',
},
},
- ]);
- } catch (e) {
- console.log(e);
- }
-
- expect((console.log as any).mock.calls[0][0].message).toContain(
+ ])
+ ).toThrow(
'You passed an invalid access control condition that is missing or has a wrong'
);
});
it('should FAIL to format canonical unified access control (key: foo, value: bar)', async () => {
- console.log = jest.fn();
-
- const MOCK_ACCS_UNKNOWN_KEY: any = [
- {
- foo: 'bar',
- },
- {
- conditionType: 'evmBasic',
- contractAddress: '',
- standardContractType: '',
- chain: 'ethereum',
- method: '',
- parameters: [':userAddress'],
- returnValueTest: {
- comparator: '=',
- value: '0x3B5dD260598B7579A0b015A1F3BBF322aDC499A2',
+ expect(() =>
+ canonicalUnifiedAccessControlConditionFormatter([
+ {
+ // @ts-expect-error we are testing
+ foo: 'bar',
},
- },
- ];
-
- try {
- test = canonicalUnifiedAccessControlConditionFormatter(
- MOCK_ACCS_UNKNOWN_KEY
- );
- } catch (e) {
- console.log(e);
- }
-
- expect((console.log as any).mock.calls[0][0].name).toBe(
- 'InvalidAccessControlConditions'
- );
+ {
+ conditionType: 'evmBasic',
+ contractAddress: '',
+ standardContractType: '',
+ chain: 'ethereum',
+ method: '',
+ parameters: [':userAddress'],
+ returnValueTest: {
+ comparator: '=',
+ value: '0x3B5dD260598B7579A0b015A1F3BBF322aDC499A2',
+ },
+ },
+ ])
+ ).toThrow(InvalidAccessControlConditions);
});
it('should throw error when format canonical sol rpc condition', async () => {
- console.log = jest.fn();
-
- const MOCK_ACCS_UNKNOWN_KEY: any = [
- {
- foo: 'bar',
- },
- {
- conditionType: 'evmBasic',
- contractAddress: '',
- standardContractType: '',
- chain: 'ethereum',
- method: '',
- parameters: [':userAddress'],
- returnValueTest: {
- comparator: '=',
- value: '0x3B5dD260598B7579A0b015A1F3BBF322aDC499A2',
+ expect(() =>
+ canonicalSolRpcConditionFormatter([
+ {
+ // @ts-expect-error we are testing
+ foo: 'bar',
},
- },
- ];
-
- try {
- test = canonicalSolRpcConditionFormatter(MOCK_ACCS_UNKNOWN_KEY);
- } catch (e) {
- console.log(e);
- }
-
- expect((console.log as any).mock.calls[0][0].name).toBe(
- 'InvalidAccessControlConditions'
- );
+ {
+ conditionType: 'evmBasic',
+ contractAddress: '',
+ standardContractType: '',
+ chain: 'ethereum',
+ method: '',
+ parameters: [':userAddress'],
+ returnValueTest: {
+ comparator: '=',
+ value: '0x3B5dD260598B7579A0b015A1F3BBF322aDC499A2',
+ },
+ },
+ ])
+ ).toThrow(InvalidAccessControlConditions);
});
it('should call "canonicalAccessControlConditionFormatter" in node.js', () => {
- const params: any = [];
+ const params = [] as never[];
const OUTPUT = canonicalAccessControlConditionFormatter(params);
@@ -183,7 +156,7 @@ describe('canonicalFormatter.ts', () => {
});
it('should call canonicalEVMContractConditionFormatter in node.js', () => {
- const params: any = [];
+ const params = [] as never[];
const OUTPUT = canonicalEVMContractConditionFormatter(params);
@@ -191,7 +164,7 @@ describe('canonicalFormatter.ts', () => {
});
it('should call canonicalCosmosConditionFormatter in node.js', () => {
- const params: any = [];
+ const params = [] as never[];
const OUTPUT = canonicalCosmosConditionFormatter(params);
@@ -199,11 +172,8 @@ describe('canonicalFormatter.ts', () => {
});
it('should call canonicalResourceIdFormatter in node.js', () => {
- const params: any = [];
-
- const OUTPUT = canonicalResourceIdFormatter(params);
-
- // const res = (console.log as any).mock.calls[0][0];
+ // @ts-expect-error we are testing
+ const OUTPUT = canonicalResourceIdFormatter({});
expect(OUTPUT.baseUrl).toBe(undefined);
});
diff --git a/packages/access-control-conditions/src/lib/canonicalFormatter.ts b/packages/access-control-conditions/src/lib/canonicalFormatter.ts
index a10b4181c8..69640b855a 100644
--- a/packages/access-control-conditions/src/lib/canonicalFormatter.ts
+++ b/packages/access-control-conditions/src/lib/canonicalFormatter.ts
@@ -142,7 +142,7 @@ export const canonicalUnifiedAccessControlConditionFormatter = (
* @returns { any[] | OperatorAcc | AccsSOLV2Params | any }
*/
export const canonicalSolRpcConditionFormatter = (
- cond: ConditionItem,
+ cond: ConditionItem | ConditionItem[],
requireV2Conditions: boolean = false
): any[] | OperatorAcc | ConditionItem | AccsSOLV2Params | any => {
// -- if is array
@@ -186,7 +186,7 @@ export const canonicalSolRpcConditionFormatter = (
cond,
},
},
- 'Solana RPC Conditions have changed and there are some new fields you must include in your condition. Check the docs here: https://developer.litprotocol.com/AccessControlConditions/solRpcConditions'
+ 'Solana RPC Conditions have changed and there are some new fields you must include in your condition. Check the docs here: https://developer.litprotocol.com/AccessControlConditions/solRpcConditions'
);
}
@@ -415,7 +415,7 @@ export const canonicalEVMContractConditionFormatter = (
* @returns
*/
export const canonicalCosmosConditionFormatter = (
- cond: ConditionItem
+ cond: ConditionItem | ConditionItem[]
): any[] | OperatorAcc | AccsCOSMOSParams | any => {
// -- if it's an array
if (Array.isArray(cond)) {
diff --git a/packages/access-control-conditions/src/lib/hashing.spec.ts b/packages/access-control-conditions/src/lib/hashing.spec.ts
index ead036529f..9281186890 100644
--- a/packages/access-control-conditions/src/lib/hashing.spec.ts
+++ b/packages/access-control-conditions/src/lib/hashing.spec.ts
@@ -51,7 +51,6 @@ describe('hashing.ts', () => {
},
},
]);
- // console.log(typeof OUTPUT);
expect(new Uint8Array(OUTPUT).length).toBe(32);
});
@@ -63,7 +62,6 @@ describe('hashing.ts', () => {
role: '',
extraData: '',
});
- // console.log(typeof OUTPUT);
expect(new Uint8Array(OUTPUT).length).toBe(32);
});
@@ -75,7 +73,6 @@ describe('hashing.ts', () => {
role: '',
extraData: '',
});
- // console.log(typeof OUTPUT);
expect(OUTPUT).toBe(
'5b36d72f2145af3617e5da2a8a626f9f42e64ed14340622bdfe1a6f0702b9e8d'
);
@@ -96,7 +93,6 @@ describe('hashing.ts', () => {
},
},
]);
- // console.log(typeof OUTPUT);
expect(typeof OUTPUT).toBe('object');
});
@@ -152,7 +148,6 @@ describe('hashing.ts', () => {
},
},
]);
- // console.log(typeof OUTPUT);
expect(typeof OUTPUT).toBe('object');
});
@@ -172,7 +167,6 @@ describe('hashing.ts', () => {
},
},
]);
- // console.log(typeof OUTPUT);
expect(typeof OUTPUT).toBe('object');
});
});
diff --git a/packages/access-control-conditions/src/lib/hashing.ts b/packages/access-control-conditions/src/lib/hashing.ts
index eecf844836..e936f145e5 100644
--- a/packages/access-control-conditions/src/lib/hashing.ts
+++ b/packages/access-control-conditions/src/lib/hashing.ts
@@ -1,5 +1,5 @@
import { InvalidAccessControlConditions } from '@lit-protocol/constants';
-import { log } from '@lit-protocol/misc';
+import { logger } from '@lit-protocol/logger';
import {
AccessControlConditions,
EvmContractConditions,
@@ -10,7 +10,6 @@ import {
SupportedJsonRequests,
UnifiedAccessControlConditions,
} from '@lit-protocol/types';
-import { uint8arrayToString } from '@lit-protocol/uint8arrays';
import {
canonicalAccessControlConditionFormatter,
@@ -77,7 +76,7 @@ import {
// const hash = await hashUnifiedAccessControlConditions(unifiedAccs);
-// return uint8arrayToString(new Uint8Array(hash), 'base16');
+// return Buffer.from(new Uint8Array(hash), 'hex');
// };
/**
@@ -90,12 +89,15 @@ import {
export const hashUnifiedAccessControlConditions = (
unifiedAccessControlConditions: UnifiedAccessControlConditions
): Promise => {
- log('unifiedAccessControlConditions:', unifiedAccessControlConditions);
+ logger.info({
+ msg: 'unifiedAccessControlConditions',
+ unifiedAccessControlConditions,
+ });
const conditions = unifiedAccessControlConditions.map((condition) => {
return canonicalUnifiedAccessControlConditionFormatter(condition);
});
- log('conditions:', conditions);
+ logger.info({ msg: 'conditions', conditions });
// check if there's any undefined in the conditions
const hasUndefined = conditions.some((c) => c === undefined);
@@ -122,7 +124,7 @@ export const hashUnifiedAccessControlConditions = (
}
const toHash = JSON.stringify(conditions);
- log('Hashing unified access control conditions: ', toHash);
+ logger.info({ msg: 'Hashing unified access control conditions', toHash });
const encoder = new TextEncoder();
const data = encoder.encode(toHash);
@@ -161,7 +163,7 @@ export const hashResourceIdForSigning = async (
resourceId: JsonSigningResourceId
): Promise => {
const hashed = await hashResourceId(resourceId);
- return uint8arrayToString(new Uint8Array(hashed), 'base16');
+ return Buffer.from(new Uint8Array(hashed)).toString('hex');
};
/**
@@ -181,7 +183,7 @@ export const hashAccessControlConditions = (
);
const toHash = JSON.stringify(conds);
- log('Hashing access control conditions: ', toHash);
+ logger.info({ msg: 'Hashing access control conditions', toHash });
const encoder = new TextEncoder();
const data = encoder.encode(toHash);
@@ -205,7 +207,7 @@ export const hashEVMContractConditions = (
);
const toHash = JSON.stringify(conds);
- log('Hashing evm contract conditions: ', toHash);
+ logger.info({ msg: 'Hashing evm contract conditions', toHash });
const encoder = new TextEncoder();
const data = encoder.encode(toHash);
return crypto.subtle.digest('SHA-256', data);
@@ -228,7 +230,7 @@ export const hashSolRpcConditions = (
);
const toHash = JSON.stringify(conds);
- log('Hashing sol rpc conditions: ', toHash);
+ logger.info({ msg: 'Hashing sol rpc conditions', toHash });
const encoder = new TextEncoder();
const data = encoder.encode(toHash);
@@ -301,34 +303,43 @@ export const getFormattedAccessControlConditions = (
formattedAccessControlConditions = accessControlConditions.map((c) =>
canonicalAccessControlConditionFormatter(c)
);
- log(
- 'formattedAccessControlConditions',
- JSON.stringify(formattedAccessControlConditions)
- );
+ logger.info({
+ msg: 'formattedAccessControlConditions',
+ formattedAccessControlConditions: JSON.stringify(
+ formattedAccessControlConditions
+ ),
+ });
} else if (evmContractConditions) {
formattedEVMContractConditions = evmContractConditions.map((c) =>
canonicalEVMContractConditionFormatter(c)
);
- log(
- 'formattedEVMContractConditions',
- JSON.stringify(formattedEVMContractConditions)
- );
+ logger.info({
+ msg: 'formattedEVMContractConditions',
+ formattedEVMContractConditions: JSON.stringify(
+ formattedEVMContractConditions
+ ),
+ });
} else if (solRpcConditions) {
// FIXME: ConditionItem is too narrow, or `solRpcConditions` is too wide
// eslint-disable-next-line @typescript-eslint/no-explicit-any
formattedSolRpcConditions = solRpcConditions.map((c: any) =>
canonicalSolRpcConditionFormatter(c)
);
- log('formattedSolRpcConditions', JSON.stringify(formattedSolRpcConditions));
+ logger.info({
+ msg: 'formattedSolRpcConditions',
+ formattedSolRpcConditions: JSON.stringify(formattedSolRpcConditions),
+ });
} else if (unifiedAccessControlConditions) {
formattedUnifiedAccessControlConditions =
unifiedAccessControlConditions.map((c) =>
canonicalUnifiedAccessControlConditionFormatter(c)
);
- log(
- 'formattedUnifiedAccessControlConditions',
- JSON.stringify(formattedUnifiedAccessControlConditions)
- );
+ logger.info({
+ msg: 'formattedUnifiedAccessControlConditions',
+ formattedUnifiedAccessControlConditions: JSON.stringify(
+ formattedUnifiedAccessControlConditions
+ ),
+ });
} else {
error = true;
}
diff --git a/packages/access-control-conditions/src/lib/humanizer.spec.ts b/packages/access-control-conditions/src/lib/humanizer.spec.ts
index baa6e092a1..cace7f2697 100644
--- a/packages/access-control-conditions/src/lib/humanizer.spec.ts
+++ b/packages/access-control-conditions/src/lib/humanizer.spec.ts
@@ -1,5 +1,3 @@
-import * as humanizer from './humanizer';
-import { humanizeAccessControlConditions } from './humanizer';
import {
AccsCOSMOSParams,
AccsEVMParams,
@@ -7,6 +5,9 @@ import {
UnifiedAccessControlConditions,
} from '@lit-protocol/types';
+import * as humanizer from './humanizer';
+import { humanizeAccessControlConditions } from './humanizer';
+
// ---------- Test Cases ----------
describe('humanizer.ts', () => {
it('should format sol', () => {
@@ -60,7 +61,7 @@ describe('humanizer.ts', () => {
expect(OUTPUT).toBe('at most');
});
it('should humanizeEvmBasicAccessControlConditions', async () => {
- const INPUT: Array = [
+ const INPUT: AccsEVMParams[] = [
{
contractAddress: '0x7C7757a9675f06F3BE4618bB68732c4aB25D2e88',
functionName: 'balanceOf',
@@ -108,7 +109,7 @@ describe('humanizer.ts', () => {
});
it('should humanizeSolRpcConditions', async () => {
- const INPUT: Array = [
+ const INPUT: AccsSOLV2Params[] = [
{
method: 'getTokenAccountBalance',
params: ['tn2WEWk4Kqj157XsSdmBBcjWumVhkyJECXCKPq9ReL9'],
@@ -134,7 +135,7 @@ describe('humanizer.ts', () => {
});
it('should humanizeCosmosConditions', async () => {
- const INPUT: Array = [
+ const INPUT: AccsCOSMOSParams[] = [
{
conditionType: 'cosmos',
path: '/cosmos/bank/v1beta1/balances/:userAddress',
diff --git a/packages/access-control-conditions/src/lib/humanizer.ts b/packages/access-control-conditions/src/lib/humanizer.ts
index 40de46aae7..1c99c4b8ca 100644
--- a/packages/access-control-conditions/src/lib/humanizer.ts
+++ b/packages/access-control-conditions/src/lib/humanizer.ts
@@ -1,7 +1,13 @@
+import { Contract } from '@ethersproject/contracts';
+import { JsonRpcProvider } from '@ethersproject/providers';
import { formatEther, formatUnits } from 'ethers/lib/utils';
-import { InvalidUnifiedConditionType } from '@lit-protocol/constants';
-import { decimalPlaces, log } from '@lit-protocol/misc';
+import {
+ LIT_CHAINS,
+ LitEVMChainKeys,
+ InvalidUnifiedConditionType,
+} from '@lit-protocol/constants';
+import { logger } from '@lit-protocol/logger';
import {
AccessControlConditions,
AccsCOSMOSParams,
@@ -11,6 +17,51 @@ import {
UnifiedAccessControlConditions,
} from '@lit-protocol/types';
+export const ERC20ABI = [
+ {
+ constant: true,
+ inputs: [],
+ name: 'decimals',
+ outputs: [
+ {
+ name: '',
+ type: 'uint8',
+ },
+ ],
+ payable: false,
+ stateMutability: 'view',
+ type: 'function',
+ },
+];
+
+/**
+ *
+ * Get the number of decimal places in a token
+ *
+ * @property { string } contractAddress The token contract address
+ * @property { LitEVMChainKeys } chain The chain on which the token is deployed
+ *
+ * @returns { number } The number of decimal places in the token
+ */
+export const decimalPlaces = async ({
+ contractAddress,
+ chain,
+}: {
+ contractAddress: string;
+ chain: LitEVMChainKeys;
+}): Promise => {
+ const rpcUrl = LIT_CHAINS[chain].rpcUrls[0] as string;
+
+ const web3 = new JsonRpcProvider({
+ url: rpcUrl,
+ skipFetchSetup: true,
+ });
+
+ const contract = new Contract(contractAddress, ERC20ABI, web3);
+
+ return await contract['decimals']();
+};
+
/**
*
* Format SOL number using Ether Units
@@ -58,7 +109,7 @@ export const humanizeComparator = (comparator: string): string | undefined => {
const selected: string | undefined = list[comparator];
if (!selected) {
- log(`Unregonized comparator ${comparator}`);
+ logger.info(`Unrecognized comparator ${comparator}`);
return;
}
@@ -84,9 +135,9 @@ export const humanizeEvmBasicAccessControlConditions = async ({
tokenList?: (any | string)[];
myWalletAddress?: string;
}): Promise => {
- log('humanizing evm basic access control conditions');
- log('myWalletAddress', myWalletAddress);
- log('accessControlConditions', accessControlConditions);
+ logger.info('humanizing evm basic access control conditions');
+ logger.info({ msg: 'myWalletAddress', myWalletAddress });
+ logger.info({ msg: 'accessControlConditions', accessControlConditions });
let fixedConditions = accessControlConditions;
@@ -230,10 +281,10 @@ export const humanizeEvmBasicAccessControlConditions = async ({
chain: acc.chain,
});
} catch (e) {
- console.log(`Failed to get decimals for ${acc.contractAddress}`);
+ logger.info(`Failed to get decimals for ${acc.contractAddress}`); // is this safe to fail and continue?
}
}
- log('decimals', decimals);
+ logger.info({ msg: 'decimals', decimals });
return `Owns ${humanizeComparator(
acc.returnValueTest.comparator
)} ${formatUnits(acc.returnValueTest.value, decimals)} of ${
@@ -284,9 +335,9 @@ export const humanizeEvmContractConditions = async ({
tokenList?: (any | string)[];
myWalletAddress?: string;
}): Promise => {
- log('humanizing evm contract conditions');
- log('myWalletAddress', myWalletAddress);
- log('evmContractConditions', evmContractConditions);
+ logger.info('humanizing evm contract conditions');
+ logger.info({ msg: 'myWalletAddress', myWalletAddress });
+ logger.info({ msg: 'evmContractConditions', evmContractConditions });
const promises = await Promise.all(
evmContractConditions.map(async (acc: any) => {
@@ -345,9 +396,9 @@ export const humanizeSolRpcConditions = async ({
tokenList?: (any | string)[];
myWalletAddress?: string;
}): Promise => {
- log('humanizing sol rpc conditions');
- log('myWalletAddress', myWalletAddress);
- log('solRpcConditions', solRpcConditions);
+ logger.info('humanizing sol rpc conditions');
+ logger.info({ msg: 'myWalletAddress', myWalletAddress });
+ logger.info({ msg: 'solRpcConditions', solRpcConditions });
const promises = await Promise.all(
solRpcConditions.map(async (acc: any) => {
@@ -419,9 +470,9 @@ export const humanizeCosmosConditions = async ({
tokenList?: (any | string)[];
myWalletAddress?: string;
}): Promise => {
- log('humanizing cosmos conditions');
- log('myWalletAddress', myWalletAddress);
- log('cosmosConditions', cosmosConditions);
+ logger.info('humanizing cosmos conditions');
+ logger.info({ msg: 'myWalletAddress', myWalletAddress });
+ logger.info({ msg: 'cosmosConditions', cosmosConditions });
const promises = await Promise.all(
cosmosConditions.map(async (acc: any) => {
diff --git a/packages/access-control-conditions/src/lib/validator.ts b/packages/access-control-conditions/src/lib/validator.ts
index ac4819d75d..78f6245a4a 100644
--- a/packages/access-control-conditions/src/lib/validator.ts
+++ b/packages/access-control-conditions/src/lib/validator.ts
@@ -1,5 +1,3 @@
-import { fromError, isZodErrorLike } from 'zod-validation-error';
-
import {
EvmBasicConditionsSchema,
EvmContractConditionsSchema,
@@ -7,7 +5,7 @@ import {
SolRpcConditionsSchema,
UnifiedConditionsSchema,
} from '@lit-protocol/access-control-conditions-schemas';
-import { InvalidArgumentException } from '@lit-protocol/constants';
+import { applySchemaWithValidation } from '@lit-protocol/schemas';
import {
AccessControlConditions,
EvmContractConditions,
@@ -16,30 +14,6 @@ import {
UnifiedAccessControlConditions,
} from '@lit-protocol/types';
-function formatZodError(accs: unknown, e: unknown): never {
- throw new InvalidArgumentException(
- {
- info: {
- accs,
- },
- cause: isZodErrorLike(e) ? fromError(e) : e,
- },
- 'Invalid access control conditions. Check error cause for more details.'
- );
-}
-
-async function validateSchema(
- accs: T,
- schema: { parse: (arg: unknown) => void }
-): Promise {
- try {
- schema.parse(accs);
- } catch (e) {
- formatZodError(accs, e);
- }
- return true;
-}
-
/**
* Validates Multiple access control conditions schema
* @param { MultipleAccessControlConditions } accs
@@ -47,7 +21,13 @@ async function validateSchema(
export const validateAccessControlConditions = async (
accs: MultipleAccessControlConditions
): Promise => {
- return validateSchema(accs, MultipleAccessControlConditionsSchema);
+ applySchemaWithValidation(
+ 'validateAccessControlConditions',
+ accs,
+ MultipleAccessControlConditionsSchema
+ );
+
+ return true;
};
/**
@@ -57,7 +37,13 @@ export const validateAccessControlConditions = async (
export const validateAccessControlConditionsSchema = async (
accs: AccessControlConditions
): Promise => {
- return validateSchema(accs, EvmBasicConditionsSchema);
+ applySchemaWithValidation(
+ 'validateAccessControlConditionsSchema',
+ accs,
+ EvmBasicConditionsSchema
+ );
+
+ return true;
};
/**
@@ -67,7 +53,13 @@ export const validateAccessControlConditionsSchema = async (
export const validateEVMContractConditionsSchema = async (
accs: EvmContractConditions
): Promise => {
- return validateSchema(accs, EvmContractConditionsSchema);
+ applySchemaWithValidation(
+ 'validateEVMContractConditionsSchema',
+ accs,
+ EvmContractConditionsSchema
+ );
+
+ return true;
};
/**
@@ -77,7 +69,13 @@ export const validateEVMContractConditionsSchema = async (
export const validateSolRpcConditionsSchema = async (
accs: SolRpcConditions
): Promise => {
- return validateSchema(accs, SolRpcConditionsSchema);
+ applySchemaWithValidation(
+ 'validateSolRpcConditionsSchema',
+ accs,
+ SolRpcConditionsSchema
+ );
+
+ return true;
};
/**
@@ -87,5 +85,11 @@ export const validateSolRpcConditionsSchema = async (
export const validateUnifiedAccessControlConditionsSchema = async (
accs: UnifiedAccessControlConditions
): Promise => {
- return validateSchema(accs, UnifiedConditionsSchema);
+ applySchemaWithValidation(
+ 'validateUnifiedAccessControlConditionsSchema',
+ accs,
+ UnifiedConditionsSchema
+ );
+
+ return true;
};
diff --git a/packages/auth-browser/README.md b/packages/auth-browser/README.md
deleted file mode 100644
index 4daea68c8c..0000000000
--- a/packages/auth-browser/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Quick Start
-
-This submodule provides functionalities from various modules within the Lit SDK, enabling users to authenticate in the browser and connect to different blockchain networks (Ethereum, Cosmos, and Solana) with convenience, while also providing a function to disconnect from the Ethereum network.
-
-### node.js / browser
-
-```
-yarn add @lit-protocol/auth-browser
-```
-
-## Generate an authSig with long expiration
-
-```
-const expiration = new Date(Date.now() + 1000 * 60 * 60 * 99999).toISOString();
-
-const authSig = LitJsSdk_authBrowser.checkAndSignAuthMessage({chain: 'ethereum', expiration: expiration});
-
-```
diff --git a/packages/auth-browser/jest.config.ts b/packages/auth-browser/jest.config.ts
deleted file mode 100644
index d194f8fec2..0000000000
--- a/packages/auth-browser/jest.config.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable */
-export default {
- displayName: 'auth-browser',
- preset: '../../jest.preset.js',
- transform: {
- '^.+\\.[tj]s$': [
- 'babel-jest',
- {
- cwd: '/Users/anson/Projects/js-sdk-master/packages/auth-browser',
- },
- ],
- },
- transformIgnorePatterns: ['node_modules/(?!(@walletconnect)/)'],
- moduleFileExtensions: ['ts', 'js', 'html'],
- coverageDirectory: '../../coverage/packages/auth-browser',
- setupFilesAfterEnv: ['../../jest.setup.js'],
-};
diff --git a/packages/auth-browser/package.json b/packages/auth-browser/package.json
deleted file mode 100644
index 26e3ae2a49..0000000000
--- a/packages/auth-browser/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "name": "@lit-protocol/auth-browser",
- "license": "MIT",
- "homepage": "https://github.com/Lit-Protocol/js-sdk",
- "repository": {
- "type": "git",
- "url": "https://github.com/LIT-Protocol/js-sdk"
- },
- "keywords": [
- "library"
- ],
- "bugs": {
- "url": "https://github.com/LIT-Protocol/js-sdk/issues"
- },
- "type": "commonjs",
- "publishConfig": {
- "access": "public",
- "directory": "../../dist/packages/auth-browser"
- },
- "gitHead": "0d7334c2c55f448e91fe32f29edc5db8f5e09e4b",
- "peerDependencies": {
- "@walletconnect/ethereum-provider": "2.9.2",
- "@walletconnect/modal": "2.6.1",
- "siwe": "^2.0.5",
- "tweetnacl": "^1.0.3",
- "tweetnacl-util": "^0.13.3",
- "util": "^0.12.4",
- "web-vitals": "^3.0.4",
- "@lit-protocol/contracts": "^0.0.74"
- },
- "tags": [
- "browser"
- ],
- "version": "8.0.0-alpha.0",
- "main": "./dist/src/index.js",
- "typings": "./dist/src/index.d.ts"
-}
diff --git a/packages/auth-browser/src/index.ts b/packages/auth-browser/src/index.ts
deleted file mode 100644
index 281927d608..0000000000
--- a/packages/auth-browser/src/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './lib/auth-browser';
-
-// -- all the chains you can connect to
-export * as ethConnect from './lib/chains/eth';
-export { disconnectWeb3 } from './lib/chains/eth';
diff --git a/packages/auth-browser/src/lib/auth-browser.ts b/packages/auth-browser/src/lib/auth-browser.ts
deleted file mode 100644
index 75be28f20c..0000000000
--- a/packages/auth-browser/src/lib/auth-browser.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import {
- ALL_LIT_CHAINS,
- UnsupportedChainException,
- VMTYPE,
-} from '@lit-protocol/constants';
-import { AuthCallbackParams, AuthSig } from '@lit-protocol/types';
-
-import { checkAndSignEVMAuthMessage } from './chains/eth';
-
-/**
- * !! NOTE !!
- * This function is purely used for crafting the authSig for access control conditions & decryption. For SessionSigs, you can pass the `authSig` as `jsParams`
- * or Eth Wallet Auth Method for `signSessionKey` and claiming, but you won't be able to use this to add resource ability requests in the SIWE message. Instead, you should provide your own signer to the authNeededCallback parameter for the getSessionSigs method.
- *
- * Check for an existing cryptographic authentication signature and create one of it does not exist. This is used to prove ownership of a given crypto wallet address to the Lit nodes. The result is stored in LocalStorage so the user doesn't have to sign every time they perform an operation.
- *
- * @param { AuthCallbackParams }
- *
- * @returns { AuthSig } The AuthSig created or retrieved
- */
-export const checkAndSignAuthMessage = ({
- chain,
- resources,
- switchChain,
- expiration,
- uri,
- walletConnectProjectId,
- nonce,
-}: AuthCallbackParams): Promise => {
- const chainInfo = ALL_LIT_CHAINS[chain];
-
- // -- validate: if chain info not found
- if (!chainInfo) {
- throw new UnsupportedChainException(
- {
- info: {
- chain,
- },
- },
- `Unsupported chain selected. Please select one of: %s`,
- Object.keys(ALL_LIT_CHAINS)
- );
- }
-
- if (!expiration) {
- // set default of 1 week
- expiration = new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toISOString();
- }
-
- // -- check and sign auth message based on chain
- if (chainInfo.vmType === VMTYPE.EVM) {
- return checkAndSignEVMAuthMessage({
- chain,
- resources,
- switchChain,
- expiration,
- uri,
- walletConnectProjectId,
- nonce,
- });
- }
-
- // Else, throw an error
- throw new UnsupportedChainException(
- {
- info: {
- chain,
- },
- },
- `vmType not found for this chain: %s. This should not happen. Unsupported chain selected. Please select one of: %s`,
- chain,
- Object.keys(ALL_LIT_CHAINS)
- );
-};
diff --git a/packages/auth-browser/tsconfig.spec.json b/packages/auth-browser/tsconfig.spec.json
deleted file mode 100644
index 855f604fb0..0000000000
--- a/packages/auth-browser/tsconfig.spec.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "../../dist/out-tsc",
- "module": "commonjs",
- "types": ["jest", "node"]
- },
- "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"],
- "exclude": ["node_modules", "tmp"]
-}
diff --git a/packages/auth-helpers/src/lib/generate-auth-sig.ts b/packages/auth-helpers/src/lib/generate-auth-sig.ts
index 49692f89c8..4cb56c3a5e 100644
--- a/packages/auth-helpers/src/lib/generate-auth-sig.ts
+++ b/packages/auth-helpers/src/lib/generate-auth-sig.ts
@@ -1,6 +1,8 @@
-import { AuthSig, SignerLike } from '@lit-protocol/types';
import { ethers } from 'ethers';
+import { InvalidArgumentException } from '@lit-protocol/constants';
+import { AuthSig, SignerLike } from '@lit-protocol/types';
+
/**
* Generate an AuthSig object using the signer.
*
@@ -26,7 +28,16 @@ export const generateAuthSig = async ({
algo?: 'ed25519';
}): Promise => {
if (!signer?.signMessage) {
- throw new Error('signer does not have a signMessage method');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ signer,
+ address,
+ algo,
+ },
+ },
+ 'signer does not have a signMessage method'
+ );
}
const signature = await signer.signMessage(toSign);
@@ -41,7 +52,16 @@ export const generateAuthSig = async ({
// If address is still not available, throw an error
if (!address) {
- throw new Error('address is required');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ signer,
+ address,
+ algo,
+ },
+ },
+ 'address is required'
+ );
}
return {
diff --git a/packages/auth-helpers/src/lib/models.ts b/packages/auth-helpers/src/lib/models.ts
index 6a59af56b0..22b63326c9 100644
--- a/packages/auth-helpers/src/lib/models.ts
+++ b/packages/auth-helpers/src/lib/models.ts
@@ -1,13 +1,3 @@
-import { LIT_ABILITY_VALUES } from '@lit-protocol/constants';
-import { ILitResource } from '@lit-protocol/types';
-
-// This is here to prevent circular dependency issue
-export interface AuthSig {
- sig: any;
- derivedVia: string;
- signedMessage: string;
- address: string;
-}
export type PlainJSON =
| boolean
| number
@@ -18,18 +8,3 @@ export type AttenuationsObject = {
[key: string]: { [key: string]: Array };
};
export type CID = string;
-
-/**
- * A LIT resource ability is a combination of a LIT resource and a LIT ability.
- * It specifies which LIT specific ability is being requested to be performed
- * on the specified LIT resource.
- *
- * @description This object does NOT guarantee compatibility between the
- * specified LIT resource and the specified LIT ability, and will be validated by
- * the LIT-internal systems.
- */
-export type LitResourceAbilityRequest = {
- resource: ILitResource;
- ability: LIT_ABILITY_VALUES;
- data?: any;
-};
diff --git a/packages/auth-helpers/src/lib/recap/recap-session-capability-object.spec.ts b/packages/auth-helpers/src/lib/recap/recap-session-capability-object.spec.ts
index b2884d1fc9..c506a21825 100644
--- a/packages/auth-helpers/src/lib/recap/recap-session-capability-object.spec.ts
+++ b/packages/auth-helpers/src/lib/recap/recap-session-capability-object.spec.ts
@@ -1,14 +1,16 @@
import { SiweMessage } from 'siwe';
+
import {
LIT_ABILITY,
LIT_RESOURCE_PREFIX,
LIT_NAMESPACE,
LIT_RECAP_ABILITY,
} from '@lit-protocol/constants';
+
import { LitAccessControlConditionResource } from '../resources';
import { RecapSessionCapabilityObject } from './recap-session-capability-object';
-const isClass = (v: any) => {
+const isClass = (v: unknown) => {
return typeof v === 'function' && /^\s*class\s+/.test(v.toString());
};
diff --git a/packages/auth-helpers/src/lib/recap/recap-session-capability-object.ts b/packages/auth-helpers/src/lib/recap/recap-session-capability-object.ts
index e9956278e7..847dc69d67 100644
--- a/packages/auth-helpers/src/lib/recap/recap-session-capability-object.ts
+++ b/packages/auth-helpers/src/lib/recap/recap-session-capability-object.ts
@@ -1,24 +1,27 @@
+import { SiweMessage } from 'siwe';
+import { Recap } from 'siwe-recap';
+
import {
InvalidArgumentException,
LIT_ABILITY_VALUES,
} from '@lit-protocol/constants';
-import { ILitResource, ISessionCapabilityObject } from '@lit-protocol/types';
-import depd from 'depd';
-import { SiweMessage } from 'siwe';
-import { Recap } from 'siwe-recap';
-import { AttenuationsObject, CID as CIDString, PlainJSON } from '../models';
-import { sanitizeSiweMessage } from '../siwe/siwe-helper';
+import {
+ AttenuationsObject,
+ CID as CIDString,
+ DefinedJson,
+ ILitResource,
+ ISessionCapabilityObject,
+} from '@lit-protocol/types';
+
import { getRecapNamespaceAndAbility } from './utils';
+import { sanitizeSiweMessage } from '../siwe/siwe-helper';
-const deprecated = depd('lit-js-sdk:auth-recap:session-capability-object');
+export type Restriction = Record;
export class RecapSessionCapabilityObject implements ISessionCapabilityObject {
private _inner: Recap;
- constructor(
- att: AttenuationsObject = {},
- prf: Array | Array = []
- ) {
+ constructor(att: AttenuationsObject = {}, prf: CIDString[] | string[] = []) {
this._inner = new Recap(att, prf);
}
@@ -26,7 +29,7 @@ export class RecapSessionCapabilityObject implements ISessionCapabilityObject {
const recap = Recap.decode_urn(encoded);
return new this(
recap.attenuations,
- recap.proofs.map((cid: any) => cid.toString())
+ recap.proofs.map((cid) => cid.toString())
);
}
@@ -34,7 +37,7 @@ export class RecapSessionCapabilityObject implements ISessionCapabilityObject {
const recap = Recap.extract_and_verify(siwe);
return new this(
recap.attenuations,
- recap.proofs.map((cid: any) => cid.toString())
+ recap.proofs.map((cid) => cid.toString())
);
}
@@ -42,8 +45,8 @@ export class RecapSessionCapabilityObject implements ISessionCapabilityObject {
return this._inner.attenuations;
}
- get proofs(): Array {
- return this._inner.proofs.map((cid: any) => cid.toString());
+ get proofs(): CIDString[] {
+ return this._inner.proofs.map((cid) => cid.toString());
}
get statement(): string {
@@ -56,9 +59,9 @@ export class RecapSessionCapabilityObject implements ISessionCapabilityObject {
addAttenuation(
resource: string,
- namespace: string = '*',
- name: string = '*',
- restriction: { [key: string]: PlainJSON } = {}
+ namespace = '*',
+ name = '*',
+ restriction: Restriction = {}
) {
return this._inner.addAttenuation(resource, namespace, name, restriction);
}
@@ -75,7 +78,7 @@ export class RecapSessionCapabilityObject implements ISessionCapabilityObject {
addCapabilityForResource(
litResource: ILitResource,
ability: LIT_ABILITY_VALUES,
- data = {}
+ data: Restriction = {}
): void {
// Validate Lit ability is compatible with the Lit resource.
if (!litResource.isValidLitAbility(ability)) {
diff --git a/packages/auth-helpers/src/lib/resources.ts b/packages/auth-helpers/src/lib/resources.ts
index 1c729f4bab..a5a494a9ce 100644
--- a/packages/auth-helpers/src/lib/resources.ts
+++ b/packages/auth-helpers/src/lib/resources.ts
@@ -7,7 +7,6 @@ import {
LIT_RESOURCE_PREFIX_VALUES,
} from '@lit-protocol/constants';
import { AccessControlConditions, ILitResource } from '@lit-protocol/types';
-import { uint8arrayToString } from '@lit-protocol/uint8arrays';
import { formatPKPResource } from './utils';
abstract class LitResourceBase {
@@ -73,9 +72,8 @@ export class LitAccessControlConditionResource
}
const hashedAccs = await hashAccessControlConditions(accs);
- const hashedAccsStr = uint8arrayToString(
- new Uint8Array(hashedAccs),
- 'base16'
+ const hashedAccsStr = Buffer.from(new Uint8Array(hashedAccs)).toString(
+ 'hex'
);
const resourceString = `${hashedAccsStr}/${dataToEncryptHash}`;
diff --git a/packages/auth-helpers/src/lib/session-capability-object.ts b/packages/auth-helpers/src/lib/session-capability-object.ts
index babdd3cc75..4e766e559c 100644
--- a/packages/auth-helpers/src/lib/session-capability-object.ts
+++ b/packages/auth-helpers/src/lib/session-capability-object.ts
@@ -1,5 +1,7 @@
import { SiweMessage } from 'siwe';
+
import { ISessionCapabilityObject } from '@lit-protocol/types';
+
import { AttenuationsObject, CID } from './models';
import { RecapSessionCapabilityObject } from './recap/recap-session-capability-object';
@@ -19,7 +21,7 @@ import { RecapSessionCapabilityObject } from './recap/recap-session-capability-o
*/
export function newSessionCapabilityObject(
attenuations: AttenuationsObject = {},
- proof: Array = []
+ proof: CID[] = []
): ISessionCapabilityObject {
return new RecapSessionCapabilityObject(attenuations, proof);
}
diff --git a/packages/auth-helpers/src/lib/siwe/create-siwe-message.ts b/packages/auth-helpers/src/lib/siwe/create-siwe-message.ts
index 55c5f6525a..c50faace1d 100644
--- a/packages/auth-helpers/src/lib/siwe/create-siwe-message.ts
+++ b/packages/auth-helpers/src/lib/siwe/create-siwe-message.ts
@@ -1,5 +1,6 @@
import { SiweMessage } from 'siwe';
+import { InvalidArgumentException } from '@lit-protocol/constants';
import {
BaseSiweMessage,
CapacityDelegationFields,
@@ -23,7 +24,14 @@ export const createSiweMessage = async (
): Promise => {
// -- validations
if (!params.walletAddress) {
- throw new Error('walletAddress is required');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'walletAddress is required'
+ );
}
const ONE_WEEK_FROM_NOW = new Date(
@@ -62,11 +70,12 @@ export const createSiweMessage = async (
// resource: new LitRLIResource(ccParams.capacityTokenId ?? '*'),
// ability: LIT_ABILITY.RateLimitIncreaseAuth,
- // @ts-ignore - TODO: new resource to be used
+ // @ts-expect-error - TODO: new resource to be used
resource: null,
- // @ts-ignore - TODO: new ability to be used
+ // @ts-expect-error - TODO: new ability to be used
ability: null,
+ // @ts-expect-error Complaining because of index signature in destination
data: capabilities,
},
];
@@ -75,7 +84,14 @@ export const createSiweMessage = async (
// -- add recap resources if needed
if (params.resources) {
if (!params.litNodeClient) {
- throw new Error('litNodeClient is required');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'litNodeClient is required'
+ );
}
siweMessage = await addRecapToSiweMessage({
@@ -112,7 +128,14 @@ export const createSiweMessageWithCapacityDelegation = async (
params: WithCapacityDelegation
) => {
if (!params.litNodeClient) {
- throw new Error('litNodeClient is required');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'litNodeClient is required'
+ );
}
return createSiweMessage({
diff --git a/packages/auth-helpers/src/lib/siwe/siwe-helper.ts b/packages/auth-helpers/src/lib/siwe/siwe-helper.ts
index 8a4f63404c..918d2bc6d8 100644
--- a/packages/auth-helpers/src/lib/siwe/siwe-helper.ts
+++ b/packages/auth-helpers/src/lib/siwe/siwe-helper.ts
@@ -1,5 +1,9 @@
import { SiweMessage } from 'siwe';
+import {
+ InvalidArgumentException,
+ UnknownError,
+} from '@lit-protocol/constants';
import {
CapacityDelegationFields,
CapacityDelegationRequest,
@@ -8,6 +12,7 @@ import {
ISessionCapabilityObject,
LitResourceAbilityRequest,
} from '@lit-protocol/types';
+
import { RecapSessionCapabilityObject } from '../recap/recap-session-capability-object';
/**
@@ -87,11 +92,27 @@ export const addRecapToSiweMessage = async ({
litNodeClient: ILitNodeClient;
}) => {
if (!resources || resources.length < 1) {
- throw new Error('resources is required');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ resources,
+ siweMessage,
+ },
+ },
+ 'resources is required'
+ );
}
if (!litNodeClient) {
- throw new Error('litNodeClient is required');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ resources,
+ siweMessage,
+ },
+ },
+ 'litNodeClient is required'
+ );
}
for (const request of resources) {
@@ -102,7 +123,7 @@ export const addRecapToSiweMessage = async ({
recapObject.addCapabilityForResource(
request.resource,
request.ability,
- request.data || null
+ request.data
);
const verified = recapObject.verifyCapabilitiesForResource(
@@ -111,7 +132,13 @@ export const addRecapToSiweMessage = async ({
);
if (!verified) {
- throw new Error(
+ throw new UnknownError(
+ {
+ info: {
+ recapObject,
+ request,
+ },
+ },
`Failed to verify capabilities for resource: "${request.resource}" and ability: "${request.ability}`
);
}
diff --git a/packages/auth-helpers/src/lib/utils.ts b/packages/auth-helpers/src/lib/utils.ts
index da935f6a7c..f65f33faa6 100644
--- a/packages/auth-helpers/src/lib/utils.ts
+++ b/packages/auth-helpers/src/lib/utils.ts
@@ -1,3 +1,5 @@
+import { InvalidArgumentException } from '@lit-protocol/constants';
+
/**
* Formats the resource ID to a 32-byte hex string.
*
@@ -21,7 +23,14 @@ export function formatPKPResource(resource: string): string {
// Throw an error if the resource length exceeds 64 characters
if (fixedResource.length > 64) {
- throw new Error('Resource ID exceeds 64 characters (32 bytes) in length.');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ resource,
+ },
+ },
+ 'Resource ID exceeds 64 characters (32 bytes) in length.'
+ );
}
/**
diff --git a/packages/auth-browser/.babelrc b/packages/auth/.babelrc
similarity index 100%
rename from packages/auth-browser/.babelrc
rename to packages/auth/.babelrc
diff --git a/packages/auth-browser/.eslintrc.json b/packages/auth/.eslintrc.json
similarity index 100%
rename from packages/auth-browser/.eslintrc.json
rename to packages/auth/.eslintrc.json
diff --git a/packages/auth/README.md b/packages/auth/README.md
new file mode 100644
index 0000000000..395853033d
--- /dev/null
+++ b/packages/auth/README.md
@@ -0,0 +1,15 @@
+# Quick Start
+
+This module provides management of auth methods that are used to control LIT PKPs, and authorization primitives.
+
+### AuthManager
+
+An AuthManager works with `authenticators` (migrated from: @lit-protocol/lit-auth-client) to generate auth material using various methods (see: authenticators documentation).
+
+The `AuthManager` then uses that auth material to create session credentials, and caches the resulting credentials for use with LIT network services. It also validates auth material and session material, and will attempt to get new auth material any time it detects that existing cached credentials have expired.
+
+### node.js / browser
+
+```
+yarn add @lit-protocol/auth
+```
diff --git a/packages/lit-node-client-nodejs/jest.config.ts b/packages/auth/jest.config.ts
similarity index 53%
rename from packages/lit-node-client-nodejs/jest.config.ts
rename to packages/auth/jest.config.ts
index 5cd97335e7..144dabf42b 100644
--- a/packages/lit-node-client-nodejs/jest.config.ts
+++ b/packages/auth/jest.config.ts
@@ -1,6 +1,6 @@
/* eslint-disable */
export default {
- displayName: 'lit-node-client-nodejs',
+ displayName: 'auth',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
@@ -11,6 +11,11 @@ export default {
'^.+\\.[t]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
- coverageDirectory: '../../coverage/packages/lit-node-client-nodejs',
+ coverageDirectory: '../../coverage/packages/auth',
+ moduleNameMapper: {
+ '^ipfs-unixfs-importer':
+ 'node_modules/ipfs-unixfs-importer/dist/index.min.js',
+ '^blockstore-core': 'node_modules/blockstore-core/dist/index.min.js',
+ },
setupFilesAfterEnv: ['../../jest.setup.js'],
};
diff --git a/packages/encryption/package.json b/packages/auth/package.json
similarity index 82%
rename from packages/encryption/package.json
rename to packages/auth/package.json
index 0c7e2461a7..8af8f27aa2 100644
--- a/packages/encryption/package.json
+++ b/packages/auth/package.json
@@ -1,5 +1,5 @@
{
- "name": "@lit-protocol/encryption",
+ "name": "@lit-protocol/auth",
"license": "MIT",
"homepage": "https://github.com/Lit-Protocol/js-sdk",
"repository": {
@@ -15,12 +15,15 @@
"type": "commonjs",
"publishConfig": {
"access": "public",
- "directory": "../../dist/packages/encryption"
+ "directory": "../../dist/packages/auth"
},
"gitHead": "0d7334c2c55f448e91fe32f29edc5db8f5e09e4b",
"tags": [
"universal"
],
+ "peerDependencies": {
+ "tslib": "^2.3.0"
+ },
"browser": {
"crypto": false,
"stream": false
diff --git a/packages/misc/project.json b/packages/auth/project.json
similarity index 57%
rename from packages/misc/project.json
rename to packages/auth/project.json
index 30a9e012c5..e024850b05 100644
--- a/packages/misc/project.json
+++ b/packages/auth/project.json
@@ -1,17 +1,17 @@
{
- "name": "misc",
+ "name": "auth",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
- "sourceRoot": "packages/misc/src",
+ "sourceRoot": "packages/auth/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
- "outputPath": "dist/packages/misc",
- "main": "packages/misc/src/index.ts",
- "tsConfig": "packages/misc/tsconfig.lib.json",
- "assets": ["packages/misc/*.md"],
+ "outputPath": "dist/packages/auth",
+ "main": "packages/auth/src/index.ts",
+ "tsConfig": "packages/auth/tsconfig.lib.json",
+ "assets": ["packages/auth/*.md"],
"updateBuildableProjectDepsInPackageJson": true
}
},
@@ -19,14 +19,14 @@
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
- "lintFilePatterns": ["packages/misc/**/*.ts"]
+ "lintFilePatterns": ["packages/auth/**/*.ts"]
}
},
"test": {
"executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/packages/misc"],
+ "outputs": ["{workspaceRoot}/coverage/packages/auth"],
"options": {
- "jestConfig": "packages/misc/jest.config.ts",
+ "jestConfig": "packages/auth/jest.config.ts",
"passWithNoTests": true
}
}
diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts
new file mode 100644
index 0000000000..d0942dafb3
--- /dev/null
+++ b/packages/auth/src/index.ts
@@ -0,0 +1,15 @@
+import { getAuthManager } from './lib/auth-manager';
+import * as authenticators from './lib/authenticators';
+import { LitRelay } from './lib/authenticators';
+import { localStorage } from './lib/storage';
+
+import type { LitAuthStorageProvider } from './lib/storage/types';
+import type { LitAuthData } from './lib/types';
+
+export type { LitAuthStorageProvider, LitAuthData };
+
+export const storagePlugins = { localStorage };
+
+export { authenticators, getAuthManager, LitRelay };
+
+export { getAuthIdByAuthMethod } from './lib/authenticators/utils';
diff --git a/packages/auth/src/lib/auth-manager.ts b/packages/auth/src/lib/auth-manager.ts
new file mode 100644
index 0000000000..8ce1d540d0
--- /dev/null
+++ b/packages/auth/src/lib/auth-manager.ts
@@ -0,0 +1,31 @@
+import { generateSessionKeyPair } from '@lit-protocol/crypto';
+
+import type { LitAuthStorageProvider } from './storage/types';
+import type { LitAuthData } from './types';
+
+interface LitAuthManagerConfig {
+ storage: LitAuthStorageProvider;
+}
+
+async function tryGetCachedAuthData() {
+ // Use `storage` to see if there is cached auth data
+ // If error thrown trying to get it, error to caller or ??
+}
+
+async function tryGetAuthMethodFromAuthenticator() {
+ // Use authenticator `getAuthMethod()` method to get a new auth method
+}
+
+function validateAuthData(authData: LitAuthData) {
+ // Validate auth data is not expired, and is well-formed
+}
+
+async function signSessionKey({ storage }: LitAuthManagerConfig) {
+ // Use LitNodeClient to signSessionKey with AuthData
+}
+
+export function getAuthManager({ storage }: LitAuthManagerConfig) {
+ return {
+ getAuthContext() {},
+ };
+}
diff --git a/packages/lit-auth-client/src/lib/providers/AppleProvider.ts b/packages/auth/src/lib/authenticators/AppleAuthenticator.ts
similarity index 95%
rename from packages/lit-auth-client/src/lib/providers/AppleProvider.ts
rename to packages/auth/src/lib/authenticators/AppleAuthenticator.ts
index 3a6ef00e9a..661c17d637 100644
--- a/packages/lit-auth-client/src/lib/providers/AppleProvider.ts
+++ b/packages/auth/src/lib/authenticators/AppleAuthenticator.ts
@@ -1,24 +1,26 @@
-import {
- AuthMethod,
- BaseProviderOptions,
- OAuthProviderOptions,
-} from '@lit-protocol/types';
+import { ethers } from 'ethers';
+import * as jose from 'jose';
+
import {
AUTH_METHOD_TYPE,
UnauthorizedException,
UnknownError,
} from '@lit-protocol/constants';
+import {
+ AuthMethod,
+ BaseProviderOptions,
+ OAuthProviderOptions,
+} from '@lit-protocol/types';
+
+import { BaseAuthenticator } from './BaseAuthenticator';
import {
prepareLoginUrl,
parseLoginParams,
getStateParam,
decode,
-} from '../utils';
-import { BaseProvider } from './BaseProvider';
-import { ethers } from 'ethers';
-import * as jose from 'jose';
+} from './utils';
-export default class AppleProvider extends BaseProvider {
+export class AppleAuthenticator extends BaseAuthenticator {
/**
* The redirect URI that Lit's login server should send the user back to
*/
@@ -140,7 +142,7 @@ export default class AppleProvider extends BaseProvider {
* @returns {Promise} - Auth method id
*/
public async getAuthMethodId(authMethod: AuthMethod): Promise {
- return AppleProvider.authMethodId(authMethod);
+ return AppleAuthenticator.authMethodId(authMethod);
}
public static async authMethodId(authMethod: AuthMethod): Promise {
const tokenPayload = jose.decodeJwt(authMethod.accessToken);
diff --git a/packages/lit-auth-client/src/lib/providers/BaseProvider.ts b/packages/auth/src/lib/authenticators/BaseAuthenticator.ts
similarity index 97%
rename from packages/lit-auth-client/src/lib/providers/BaseProvider.ts
rename to packages/auth/src/lib/authenticators/BaseAuthenticator.ts
index ce8cc5c313..659fefdfc9 100644
--- a/packages/lit-auth-client/src/lib/providers/BaseProvider.ts
+++ b/packages/auth/src/lib/authenticators/BaseAuthenticator.ts
@@ -1,11 +1,9 @@
-import depd from 'depd';
import { ethers } from 'ethers';
import {
AUTH_METHOD_TYPE_VALUES,
InvalidArgumentException,
LitNodeClientNotReadyError,
- ParamsMissingError,
UnknownError,
} from '@lit-protocol/constants';
import { LitContracts } from '@lit-protocol/contracts-sdk';
@@ -22,11 +20,9 @@ import {
MintRequestBody,
} from '@lit-protocol/types';
-import { validateMintRequestBody } from '../validators';
+import { validateMintRequestBody } from './validators';
-const deprecated = depd('lit-js-sdk:auth-browser:base-provider');
-
-export abstract class BaseProvider {
+export abstract class BaseAuthenticator {
/**
* Relay server to subsidize minting of PKPs
*/
@@ -65,7 +61,7 @@ export abstract class BaseProvider {
*/
abstract getAuthMethodId(
authMethod: AuthMethod,
- options?: any
+ options?: unknown
): Promise;
/**
diff --git a/packages/lit-auth-client/src/lib/providers/DiscordProvider.ts b/packages/auth/src/lib/authenticators/DiscordAuthenticator.ts
similarity index 98%
rename from packages/lit-auth-client/src/lib/providers/DiscordProvider.ts
rename to packages/auth/src/lib/authenticators/DiscordAuthenticator.ts
index 27911e9e20..9103893ad5 100644
--- a/packages/lit-auth-client/src/lib/providers/DiscordProvider.ts
+++ b/packages/auth/src/lib/authenticators/DiscordAuthenticator.ts
@@ -1,24 +1,26 @@
-import {
- AuthMethod,
- BaseProviderOptions,
- OAuthProviderOptions,
-} from '@lit-protocol/types';
+import { ethers } from 'ethers';
+
import {
AUTH_METHOD_TYPE,
UnauthorizedException,
UnknownError,
} from '@lit-protocol/constants';
-import { BaseProvider } from './BaseProvider';
+import {
+ AuthMethod,
+ BaseProviderOptions,
+ OAuthProviderOptions,
+} from '@lit-protocol/types';
+
+import { BaseAuthenticator } from './BaseAuthenticator';
import {
prepareLoginUrl,
parseLoginParams,
getStateParam,
decode,
LIT_LOGIN_GATEWAY,
-} from '../utils';
-import { ethers } from 'ethers';
+} from './utils';
-export default class DiscordProvider extends BaseProvider {
+export class DiscordAuthenticator extends BaseAuthenticator {
/**
* The redirect URI that Lit's login server should send the user back to
*/
diff --git a/packages/lit-auth-client/src/lib/providers/GoogleProvider.ts b/packages/auth/src/lib/authenticators/GoogleAuthenticator.ts
similarity index 96%
rename from packages/lit-auth-client/src/lib/providers/GoogleProvider.ts
rename to packages/auth/src/lib/authenticators/GoogleAuthenticator.ts
index 34f7b8ba2d..81bab7844f 100644
--- a/packages/lit-auth-client/src/lib/providers/GoogleProvider.ts
+++ b/packages/auth/src/lib/authenticators/GoogleAuthenticator.ts
@@ -12,16 +12,16 @@ import {
OAuthProviderOptions,
} from '@lit-protocol/types';
+import { BaseAuthenticator } from './BaseAuthenticator';
import {
prepareLoginUrl,
parseLoginParams,
getStateParam,
decode,
LIT_LOGIN_GATEWAY,
-} from '../utils';
-import { BaseProvider } from './BaseProvider';
+} from './utils';
-export default class GoogleProvider extends BaseProvider {
+export class GoogleAuthenticator extends BaseAuthenticator {
/**
* The redirect URI that Lit's login server should send the user back to
*/
@@ -211,7 +211,7 @@ export default class GoogleProvider extends BaseProvider {
* @returns {Promise} - Auth method id
*/
public async getAuthMethodId(authMethod: AuthMethod): Promise {
- return GoogleProvider.authMethodId(authMethod);
+ return GoogleAuthenticator.authMethodId(authMethod);
}
public static async authMethodId(authMethod: AuthMethod): Promise {
diff --git a/packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts b/packages/auth/src/lib/authenticators/WebAuthnAuthenticator.ts
similarity index 81%
rename from packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts
rename to packages/auth/src/lib/authenticators/WebAuthnAuthenticator.ts
index 3bdad5f431..957579b06f 100644
--- a/packages/lit-auth-client/src/lib/providers/WebAuthnProvider.ts
+++ b/packages/auth/src/lib/authenticators/WebAuthnAuthenticator.ts
@@ -1,26 +1,29 @@
import {
- AuthMethod,
- BaseProviderOptions,
- MintRequestBody,
- WebAuthnProviderOptions,
-} from '@lit-protocol/types';
+ PublicKeyCredentialCreationOptionsJSON,
+ UserVerificationRequirement,
+ RegistrationResponseJSON,
+} from '@simplewebauthn/typescript-types';
+import base64url from 'base64url';
+import { ethers } from 'ethers';
+
import {
AUTH_METHOD_TYPE,
+ InvalidArgumentException,
RemovedFunctionError,
UnknownError,
WrongParamFormat,
} from '@lit-protocol/constants';
-import { ethers } from 'ethers';
import {
- PublicKeyCredentialCreationOptionsJSON,
- UserVerificationRequirement,
-} from '@simplewebauthn/typescript-types';
-import base64url from 'base64url';
-import { getRPIdFromOrigin, parseAuthenticatorData } from '../utils';
-import { BaseProvider } from './BaseProvider';
-import { RegistrationResponseJSON } from '@simplewebauthn/typescript-types';
+ AuthMethod,
+ BaseProviderOptions,
+ MintRequestBody,
+ WebAuthnProviderOptions,
+} from '@lit-protocol/types';
-export default class WebAuthnProvider extends BaseProvider {
+import { BaseAuthenticator } from './BaseAuthenticator';
+import { getRPIdFromOrigin, parseAuthenticatorData } from './utils';
+
+export class WebAuthnAuthenticator extends BaseAuthenticator {
/**
* Name of relying party. Defaults to "lit"
*/
@@ -68,7 +71,7 @@ export default class WebAuthnProvider extends BaseProvider {
// Get auth method pub key
const authMethodPubkey =
- WebAuthnProvider.getPublicKeyFromRegistration(attResp);
+ WebAuthnAuthenticator.getPublicKeyFromRegistration(attResp);
// Format args for relay server
const defaultArgs = {
@@ -176,7 +179,7 @@ export default class WebAuthnProvider extends BaseProvider {
* @returns {Promise} - Auth method id
*/
public async getAuthMethodId(authMethod: AuthMethod): Promise {
- return WebAuthnProvider.authMethodId(authMethod, this.rpName);
+ return WebAuthnAuthenticator.authMethodId(authMethod, this.rpName);
}
public static async authMethodId(
@@ -228,8 +231,8 @@ export default class WebAuthnProvider extends BaseProvider {
// Parse the buffer to reconstruct the object
// Buffer is COSE formatted, utilities decode the buffer into json, and extract the public key information
- const authenticationResponse: any =
- parseAuthenticatorData(attestationBuffer);
+ const authenticationResponse = parseAuthenticatorData(attestationBuffer);
+ assertAuthenticationResponse(authenticationResponse);
// Public key in cose format to register the auth method
const publicKeyCoseBuffer: Buffer = authenticationResponse
@@ -251,3 +254,39 @@ export default class WebAuthnProvider extends BaseProvider {
return publicKey;
}
}
+
+function assertAuthenticationResponse(
+ authenticationResponse: unknown
+): asserts authenticationResponse is {
+ attestedCredentialData: {
+ credentialPublicKey: Buffer;
+ };
+} {
+ /* eslint-disable @typescript-eslint/no-explicit-any */
+ if (
+ typeof authenticationResponse !== 'object' ||
+ authenticationResponse === null ||
+ !('attestedCredentialData' in authenticationResponse) ||
+ typeof (authenticationResponse as any).attestedCredentialData !==
+ 'object' ||
+ (authenticationResponse as any).attestedCredentialData === null ||
+ !(
+ 'credentialPublicKey' in
+ (authenticationResponse as any).attestedCredentialData
+ ) ||
+ !(
+ (authenticationResponse as any).attestedCredentialData
+ .credentialPublicKey instanceof Buffer
+ )
+ ) {
+ throw new InvalidArgumentException(
+ {
+ info: {
+ authenticationResponse,
+ },
+ },
+ 'authenticationResponse does not match the expected structure: { attestedCredentialData: { credentialPublicKey: Buffer } }'
+ );
+ }
+ /* eslint-enable @typescript-eslint/no-explicit-any */
+}
diff --git a/packages/auth/src/lib/authenticators/index.ts b/packages/auth/src/lib/authenticators/index.ts
new file mode 100644
index 0000000000..546fc49925
--- /dev/null
+++ b/packages/auth/src/lib/authenticators/index.ts
@@ -0,0 +1,29 @@
+import { LitRelay } from '../relay';
+import { AppleAuthenticator } from './AppleAuthenticator';
+import { DiscordAuthenticator } from './DiscordAuthenticator';
+import { GoogleAuthenticator } from './GoogleAuthenticator';
+import { MetamaskAuthenticator } from './metamask';
+import {
+ StytchOtpAuthenticator,
+ StytchAuthFactorOtpAuthenticator,
+} from './stytch';
+import {
+ isSignInRedirect,
+ getProviderFromUrl,
+ getAuthIdByAuthMethod,
+} from './utils';
+import { WebAuthnAuthenticator } from './WebAuthnAuthenticator';
+
+export {
+ AppleAuthenticator,
+ DiscordAuthenticator,
+ MetamaskAuthenticator,
+ GoogleAuthenticator,
+ StytchAuthFactorOtpAuthenticator,
+ StytchOtpAuthenticator,
+ WebAuthnAuthenticator,
+ isSignInRedirect,
+ getProviderFromUrl,
+ getAuthIdByAuthMethod,
+ LitRelay,
+};
diff --git a/packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts b/packages/auth/src/lib/authenticators/metamask/MetamaskAuthenticator.ts
similarity index 88%
rename from packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts
rename to packages/auth/src/lib/authenticators/metamask/MetamaskAuthenticator.ts
index c1d1afd3d4..46afd01b1c 100644
--- a/packages/lit-auth-client/src/lib/providers/EthWalletProvider.ts
+++ b/packages/auth/src/lib/authenticators/metamask/MetamaskAuthenticator.ts
@@ -8,11 +8,8 @@ import {
LitEVMChainKeys,
WrongParamFormat,
} from '@lit-protocol/constants';
-import {
- LitNodeClient,
- checkAndSignAuthMessage,
-} from '@lit-protocol/lit-node-client';
-import { log } from '@lit-protocol/misc';
+import { LitNodeClient } from '@lit-protocol/lit-node-client';
+import { getChildLogger } from '@lit-protocol/logger';
import {
AuthMethod,
AuthSig,
@@ -21,14 +18,18 @@ import {
EthWalletAuthenticateOptions,
} from '@lit-protocol/types';
-import { BaseProvider } from './BaseProvider';
+import { BaseAuthenticator } from '../BaseAuthenticator';
+import { checkAndSignEVMAuthMessage } from './eth';
interface DomainAndOrigin {
domain?: string;
origin?: string;
}
-export default class EthWalletProvider extends BaseProvider {
+export class MetamaskAuthenticator extends BaseAuthenticator {
+ private static readonly _logger = getChildLogger({
+ module: 'MetamaskAuthenticator',
+ });
/**
* The domain from which the signing request is made
*/
@@ -41,7 +42,8 @@ export default class EthWalletProvider extends BaseProvider {
constructor(options: EthWalletProviderOptions & BaseProviderOptions) {
super(options);
- const { domain, origin } = EthWalletProvider.getDomainAndOrigin(options);
+ const { domain, origin } =
+ MetamaskAuthenticator.getDomainAndOrigin(options);
this.domain = domain;
this.origin = origin;
}
@@ -52,7 +54,7 @@ export default class EthWalletProvider extends BaseProvider {
domain = options.domain || window.location.hostname;
origin = options.origin || window.location.origin;
} catch (e) {
- log(
+ MetamaskAuthenticator._logger.error(
'⚠️ Error getting "domain" and "origin" from window object, defaulting to "localhost" and "http://localhost"'
);
domain = options.domain || 'localhost';
@@ -85,7 +87,7 @@ export default class EthWalletProvider extends BaseProvider {
);
}
- return EthWalletProvider.authenticate({
+ return MetamaskAuthenticator.authenticate({
signer: options,
address: options.address,
chain: options.chain,
@@ -109,7 +111,7 @@ export default class EthWalletProvider extends BaseProvider {
* @param {string} [options.origin] - Origin from which the signing request is made
* @returns {Promise} - Auth method object containing the auth signature
* @static
- * @memberof EthWalletProvider
+ * @memberof MetamaskAuthenticator
*
* @example
* ```typescript
@@ -170,7 +172,7 @@ export default class EthWalletProvider extends BaseProvider {
expiration || new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString();
const { domain: resolvedDomain, origin: resolvedOrigin } =
- EthWalletProvider.getDomainAndOrigin({ domain, origin });
+ MetamaskAuthenticator.getDomainAndOrigin({ domain, origin });
// Prepare Sign in with Ethereum message
const preparedMessage: Partial = {
@@ -196,7 +198,7 @@ export default class EthWalletProvider extends BaseProvider {
address: address,
};
} else {
- authSig = await checkAndSignAuthMessage({
+ authSig = await checkAndSignEVMAuthMessage({
chain,
nonce: await litNodeClient.getLatestBlockhash(),
});
@@ -218,7 +220,7 @@ export default class EthWalletProvider extends BaseProvider {
* @returns {Promise} - Auth method id
*/
public async getAuthMethodId(authMethod: AuthMethod): Promise {
- return EthWalletProvider.authMethodId(authMethod);
+ return MetamaskAuthenticator.authMethodId(authMethod);
}
public static async authMethodId(authMethod: AuthMethod): Promise {
diff --git a/packages/auth-browser/src/lib/connect-modal/modal.ts b/packages/auth/src/lib/authenticators/metamask/connect-modal/modal.ts
similarity index 99%
rename from packages/auth-browser/src/lib/connect-modal/modal.ts
rename to packages/auth/src/lib/authenticators/metamask/connect-modal/modal.ts
index 8d23d1691a..0d3bf49f59 100644
--- a/packages/auth-browser/src/lib/connect-modal/modal.ts
+++ b/packages/auth/src/lib/authenticators/metamask/connect-modal/modal.ts
@@ -1,3 +1,4 @@
+/* eslint-disable */
// @ts-nocheck
// node_modules/micromodal/dist/micromodal.es.js
import { NoWalletException } from '@lit-protocol/constants';
diff --git a/packages/auth-browser/src/lib/chains/eth.ts b/packages/auth/src/lib/authenticators/metamask/eth.ts
similarity index 71%
rename from packages/auth-browser/src/lib/chains/eth.ts
rename to packages/auth/src/lib/authenticators/metamask/eth.ts
index 32393f09e5..79dceffc3b 100644
--- a/packages/auth-browser/src/lib/chains/eth.ts
+++ b/packages/auth/src/lib/authenticators/metamask/eth.ts
@@ -1,55 +1,43 @@
import { Buffer as BufferPolyfill } from 'buffer';
-import depd from 'depd';
import { hexlify } from '@ethersproject/bytes';
import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers';
import { toUtf8Bytes } from '@ethersproject/strings';
-
-// import WalletConnectProvider from '@walletconnect/ethereum-provider';
import { verifyMessage } from '@ethersproject/wallet';
import {
EthereumProvider,
default as WalletConnectProvider,
} from '@walletconnect/ethereum-provider';
+import depd from 'depd';
import { ethers } from 'ethers';
import { getAddress } from 'ethers/lib/utils';
import { SiweMessage } from 'siwe';
-// @ts-ignore: If importing 'nacl' directly, the built files will use .default instead
-import * as nacl from 'tweetnacl';
-import * as naclUtil from 'tweetnacl-util';
-
-// @ts-ignore: If importing 'nacl' directly, the built files will use .default instead
import {
ConstantValues,
ConstantKeys,
- EITHER_TYPE,
- ELeft,
- ERight,
- IEither,
+ Environment,
InvalidSignatureError,
LIT_CHAINS,
LOCAL_STORAGE_KEYS,
- LocalStorageItemNotFoundException,
UnknownError,
UnsupportedChainException,
WrongNetworkException,
WrongParamFormat,
LIT_CHAINS_KEYS,
} from '@lit-protocol/constants';
+import { validateSessionSig } from '@lit-protocol/lit-node-client';
+import { getChildLogger, logger } from '@lit-protocol/logger';
import {
- isBrowser,
- isNode,
- log,
- numberToHex,
- validateSessionSig,
-} from '@lit-protocol/misc';
-import { getStorageItem } from '@lit-protocol/misc-browser';
+ getStorageItem,
+ setStorageItem,
+ removeStorageItem,
+} from '@lit-protocol/misc-browser';
import { AuthCallbackParams, AuthSig } from '@lit-protocol/types';
-import LitConnectModal from '../connect-modal/modal';
+import LitConnectModal from './connect-modal/modal';
-const deprecated = depd('lit-js-sdk:auth-browser:index');
+const deprecated = depd('lit-js-sdk:auth:metamask-authenticator:index');
if (globalThis && typeof globalThis.Buffer === 'undefined') {
globalThis.Buffer = BufferPolyfill;
@@ -168,35 +156,27 @@ export const chainHexIdToChainName = (chainHexId: string): void | string => {
* Get chain id of the current network
* @param { string } chain
* @param { Web3Provider } web3
- * @returns { Promise }
+ * @returns { Promise }
*/
export const getChainId = async (
chain: string,
web3: Web3Provider
-): Promise> => {
- let resultOrError: IEither;
-
+): Promise => {
try {
- const resp = await web3.getNetwork();
- resultOrError = ERight(resp.chainId);
+ const network = await web3.getNetwork();
+ return network.chainId;
} catch (e) {
- // couldn't get chainId. throw the incorrect network error
- log('getNetwork threw an exception', e);
-
- resultOrError = ELeft(
- new WrongNetworkException(
- {
- info: {
- chain,
- },
+ throw new WrongNetworkException(
+ {
+ info: {
+ chain,
},
- `Incorrect network selected. Please switch to the %s network in your wallet and try again.`,
- chain
- )
+ cause: e,
+ },
+ `Incorrect network selected. Please switch to the %s network in your wallet and try again.`,
+ chain
);
}
-
- return resultOrError;
};
/**
@@ -225,7 +205,10 @@ export function isSignedMessageExpired(signedMessage: string) {
*
* @returns { boolean }
*/
-export const getMustResign = (authSig: AuthSig, resources: any): boolean => {
+export const getMustResign = (
+ authSig: AuthSig,
+ resources: unknown
+): boolean => {
let mustResign!: boolean;
// if it's not expired, then we don't need to resign
@@ -235,23 +218,30 @@ export const getMustResign = (authSig: AuthSig, resources: any): boolean => {
try {
const parsedSiwe = new SiweMessage(authSig.signedMessage);
- log('parsedSiwe.resources', parsedSiwe.resources);
+ logger.info({
+ msg: 'parsedSiwe.resources',
+ resources: parsedSiwe.resources,
+ });
if (JSON.stringify(parsedSiwe.resources) !== JSON.stringify(resources)) {
- log(
+ logger.info(
'signing auth message because resources differ from the resources in the auth sig'
);
mustResign = true;
}
if (parsedSiwe.address !== getAddress(parsedSiwe.address)) {
- log(
- 'signing auth message because parsedSig.address is not equal to the same address but checksummed. This usually means the user had a non-checksummed address saved and so they need to re-sign.'
+ logger.info(
+ 'signing auth message because parsedSig.address is not equal to the same address but checksummed. This usually means the user had a non-checksummed address saved and so they need to re-sign.'
);
mustResign = true;
}
- } catch (e) {
- log('error parsing siwe sig. making the user sign again: ', e);
+ } catch (error) {
+ logger.error({
+ function: 'getMustResign',
+ msg: 'error parsing siwe sig. Making the user sign again',
+ error,
+ });
mustResign = true;
}
@@ -298,8 +288,8 @@ export const connectWeb3 = async ({
walletConnectProjectId,
}: ConnectWeb3): Promise => {
// -- check if it's nodejs
- if (isNode()) {
- log('connectWeb3 is not supported in nodejs.');
+ if (Environment.isNode) {
+ logger.info('connectWeb3 is not supported in nodejs.');
return { web3: null, account: null };
}
@@ -322,20 +312,20 @@ export const connectWeb3 = async ({
},
};
- if (isBrowser()) {
+ if (Environment.isBrowser) {
litWCProvider = wcProvider;
}
}
- log('getting provider via lit connect modal');
+ logger.info('getting provider via lit connect modal');
const dialog = new LitConnectModal({ providerOptions });
const provider = await dialog.getWalletProvider();
- log('got provider');
+ logger.info('got provider');
- // @ts-ignore
+ // @ts-expect-error provider is not typed
const web3 = new Web3Provider(provider);
// trigger metamask popup
@@ -343,19 +333,19 @@ export const connectWeb3 = async ({
deprecated(
'@deprecated soon to be removed. - trying to enable provider. this will trigger the metamask popup.'
);
- // @ts-ignore
+ // @ts-expect-error provider is not typed
await provider.enable();
- } catch (e) {
- log(
- "error enabling provider but swallowed it because it's not important. most wallets use a different function now to enable the wallet so you can ignore this error, because those other methods will be tried.",
- e
- );
+ } catch (error) {
+ logger.info({
+ msg: "error enabling provider but swallowed it because it's not important. Most wallets use a different function now to enable the wallet so you can ignore this error, those other methods will be tried.",
+ error,
+ });
}
- log('listing accounts');
+ logger.info('listing accounts');
const accounts = await web3.listAccounts();
- log('accounts', accounts);
+ logger.info({ msg: 'accounts', accounts });
const account = ethers.utils.getAddress(accounts[0]);
return { web3, account };
@@ -364,23 +354,22 @@ export const connectWeb3 = async ({
/**
* @browserOnly
* Delete any saved AuthSigs from local storage. Takes no params and returns
- * nothing. This will also clear out the WalletConnect cache in local storage.
+ * nothing. This will also clear out the WalletConnect cache in localstorage.
* We often run this function as a result of the user pressing a "Logout" button.
*
* @return { void }
*/
export const disconnectWeb3 = (): void => {
- if (isNode()) {
- log('disconnectWeb3 is not supported in nodejs.');
+ if (Environment.isNode) {
+ logger.info('disconnectWeb3 is not supported in nodejs.');
return;
}
- // @ts-ignore
- if (isBrowser() && litWCProvider) {
+ if (Environment.isBrowser && litWCProvider) {
try {
litWCProvider.disconnect();
} catch (err) {
- log(
+ logger.info(
'Attempted to disconnect global WalletConnectProvider for lit-connect-modal',
err
);
@@ -389,11 +378,8 @@ export const disconnectWeb3 = (): void => {
const storage = LOCAL_STORAGE_KEYS;
- localStorage.removeItem(storage.AUTH_SIGNATURE);
- localStorage.removeItem(storage.AUTH_SOL_SIGNATURE);
- localStorage.removeItem(storage.AUTH_COSMOS_SIGNATURE);
- localStorage.removeItem(storage.WEB3_PROVIDER);
- localStorage.removeItem(storage.WALLET_SIGNATURE);
+ removeStorageItem(storage.AUTH_SIGNATURE);
+ removeStorageItem(storage.WALLET_SIGNATURE);
};
/**
@@ -412,10 +398,11 @@ export const checkAndSignEVMAuthMessage = async ({
walletConnectProjectId,
nonce,
}: AuthCallbackParams): Promise => {
- // -- check if it's nodejs
- if (isNode()) {
- log(
- 'checkAndSignEVMAuthMessage is not supported in nodejs. You can create a SIWE on your own using the SIWE package.'
+ const logger = getChildLogger({ function: 'checkAndSignEVMAuthMessage' });
+ // -- check if it's Node.js
+ if (Environment.isNode) {
+ logger.info(
+ 'checkAndSignEVMAuthMessage is not supported in nodejs. You can create a SIWE on your own using the SIWE package.'
);
return {
sig: '',
@@ -426,7 +413,7 @@ export const checkAndSignEVMAuthMessage = async ({
}
// --- scoped methods ---
- const _throwIncorrectNetworkError = (error: any) => {
+ const _throwIncorrectNetworkError = (error: any): never => {
if (error.code === WALLET_ERROR.NO_SUCH_METHOD) {
throw new WrongNetworkException(
{
@@ -450,45 +437,28 @@ export const checkAndSignEVMAuthMessage = async ({
walletConnectProjectId,
});
- log(`got web3 and account: ${account}`);
+ logger.info(`got web3 and account: ${account}`);
// -- 2. prepare all required variables
- const currentChainIdOrError = await getChainId(chain, web3);
+ let currentChainId = await getChainId(chain, web3);
const selectedChainId: number = selectedChain.chainId;
- const selectedChainIdHex: string = numberToHex(selectedChainId);
- let authSigOrError = getStorageItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
-
- log('currentChainIdOrError:', currentChainIdOrError);
- log('selectedChainId:', selectedChainId);
- log('selectedChainIdHex:', selectedChainIdHex);
- log('authSigOrError:', authSigOrError);
-
- // -- 3. check all variables before executing business logic
- if (currentChainIdOrError.type === EITHER_TYPE.ERROR) {
- throw new UnknownError(
- {
- info: {
- chainId: chain,
- },
- cause: currentChainIdOrError.result,
- },
- 'Unknown error when getting chain id'
- );
- }
-
- log('chainId from web3', currentChainIdOrError);
- log(
- `checkAndSignAuthMessage with chainId ${currentChainIdOrError} and chain set to ${chain} and selectedChain is `,
- selectedChain
- );
+ const selectedChainIdHex: string = `0x${selectedChainId.toString(16)}`;
+
+ logger.info({ msg: 'currentChainId', currentChainId });
+ logger.info({ msg: 'selectedChainId', selectedChainId });
+ logger.info({ msg: 'selectedChainIdHex', selectedChainIdHex });
+ logger.info({
+ msg: `checkAndSignAuthMessage with chainId ${currentChainId} and chain set to ${chain} and selectedChain is `,
+ selectedChain,
+ });
// -- 4. case: (current chain id is NOT equal to selected chain) AND is set to switch chain
- if (currentChainIdOrError.result !== selectedChainId && switchChain) {
+ if (currentChainId !== selectedChainId && switchChain) {
const provider = web3.provider as any;
// -- (case) if able to switch chain id
try {
- log('trying to switch to chainId', selectedChainIdHex);
+ logger.info({ msg: 'trying to switch to chainId', selectedChainIdHex });
await provider.request({
method: 'wallet_switchEthereumChain',
@@ -497,7 +467,7 @@ export const checkAndSignEVMAuthMessage = async ({
// -- (case) if unable to switch chain
} catch (switchError: any) {
- log('error switching to chainId', switchError);
+ logger.error({ msg: 'error switching to chainId', switchError });
// -- (error case)
if (
@@ -522,7 +492,7 @@ export const checkAndSignEVMAuthMessage = async ({
method: 'wallet_addEthereumChain',
params: data,
});
- } catch (addError: any) {
+ } catch (addError) {
_throwIncorrectNetworkError(addError);
}
} else {
@@ -531,17 +501,27 @@ export const checkAndSignEVMAuthMessage = async ({
}
// we may have switched the chain to the selected chain. set the chainId accordingly
- currentChainIdOrError.result = selectedChain.chainId;
+ currentChainId = selectedChain.chainId;
}
+ let authSig: AuthSig | undefined;
// -- 5. case: Lit auth signature is NOT in the local storage
- log('checking if sig is in local storage');
-
- if (authSigOrError.type === EITHER_TYPE.ERROR) {
- log('signing auth message because sig is not in local storage');
+ try {
+ logger.info('checking if sig is in local storage');
+ const authSigString = getStorageItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
+ authSig = JSON.parse(authSigString);
+ } catch (error) {
+ logger.warn({
+ msg: 'Could not get sig from local storage',
+ error,
+ });
+ }
+ if (!authSig) {
try {
- const authSig = await _signAndGetAuth({
+ logger.info('signing auth message because sig is not in local storage');
+
+ authSig = await _signAndGetAuth({
web3,
account,
chainId: selectedChain.chainId,
@@ -550,12 +530,7 @@ export const checkAndSignEVMAuthMessage = async ({
uri,
nonce,
});
-
- authSigOrError = {
- type: EITHER_TYPE.SUCCESS,
- result: JSON.stringify(authSig),
- };
- } catch (e: any) {
+ } catch (e) {
throw new UnknownError(
{
info: {
@@ -571,20 +546,14 @@ export const checkAndSignEVMAuthMessage = async ({
'Could not get authenticated message'
);
}
-
- // Log new authSig
- log('5. authSigOrError:', authSigOrError);
}
// -- 6. case: Lit auth signature IS in the local storage
- const authSigString: string = authSigOrError.result;
- let authSig = JSON.parse(authSigString);
-
- log('6. authSig:', authSig);
+ logger.info({ msg: 'authSig', authSig });
// -- 7. case: when we are NOT on the right wallet address
if (account.toLowerCase() !== authSig.address.toLowerCase()) {
- log(
+ logger.info(
'signing auth message because account is not the same as the address in the auth sig'
);
authSig = await _signAndGetAuth({
@@ -596,7 +565,7 @@ export const checkAndSignEVMAuthMessage = async ({
uri,
nonce,
});
- log('7. authSig:', authSig);
+ logger.info({ msg: 'authSig', authSig });
// -- 8. case: we are on the right wallet, but need to check the resources of the sig and re-sign if they don't match
} else {
@@ -613,7 +582,7 @@ export const checkAndSignEVMAuthMessage = async ({
nonce,
});
}
- log('8. mustResign:', mustResign);
+ logger.info({ msg: 'mustResign', mustResign });
}
// -- 9. finally, if the authSig is expired, re-sign
@@ -622,10 +591,10 @@ export const checkAndSignEVMAuthMessage = async ({
if (isSignedMessageExpired(authSig.signedMessage) || !checkAuthSig.isValid) {
if (!checkAuthSig.isValid) {
- log(`Invalid AuthSig: ${checkAuthSig.errors.join(', ')}`);
+ logger.info(`Invalid AuthSig: ${checkAuthSig.errors.join(', ')}`);
}
- log('9. authSig expired!, resigning..');
+ logger.info('authSig expired!, resigning..');
authSig = await _signAndGetAuth({
web3,
@@ -664,23 +633,8 @@ const _signAndGetAuth = async ({
nonce,
});
- const authSigOrError = getStorageItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
-
- if (authSigOrError.type === 'ERROR') {
- throw new LocalStorageItemNotFoundException(
- {
- info: {
- storageKey: LOCAL_STORAGE_KEYS.AUTH_SIGNATURE,
- },
- },
- 'Failed to get authSig from local storage'
- );
- }
-
- const authSig: AuthSig =
- typeof authSigOrError.result === 'string'
- ? JSON.parse(authSigOrError.result)
- : authSigOrError.result;
+ const authSigString = getStorageItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
+ const authSig: AuthSig = JSON.parse(authSigString);
return authSig;
};
@@ -703,8 +657,8 @@ export const signAndSaveAuthMessage = async ({
nonce,
}: signAndSaveAuthParams): Promise => {
// check if it's nodejs
- if (isNode()) {
- log('checkAndSignEVMAuthMessage is not supported in nodejs.');
+ if (Environment.isNode) {
+ logger.info('checkAndSignEVMAuthMessage is not supported in nodejs.');
return {
sig: '',
derivedVia: '',
@@ -752,25 +706,10 @@ export const signAndSaveAuthMessage = async ({
};
// -- 4. store auth and a keypair in localstorage for communication with sgx
- if (isBrowser()) {
- localStorage.setItem(
- LOCAL_STORAGE_KEYS.AUTH_SIGNATURE,
- JSON.stringify(authSig)
- );
- }
- const commsKeyPair = nacl.box.keyPair();
-
- if (isBrowser()) {
- localStorage.setItem(
- LOCAL_STORAGE_KEYS.KEY_PAIR,
- JSON.stringify({
- publicKey: naclUtil.encodeBase64(commsKeyPair.publicKey),
- secretKey: naclUtil.encodeBase64(commsKeyPair.secretKey),
- })
- );
+ if (Environment.isBrowser) {
+ setStorageItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE, JSON.stringify(authSig));
}
- log(`generated and saved ${LOCAL_STORAGE_KEYS.KEY_PAIR}`);
return authSig;
};
@@ -787,9 +726,9 @@ export const signMessage = async ({
web3,
account,
}: SignMessageParams): Promise => {
- // check if it's nodejs
- if (isNode()) {
- log('signMessage is not supported in nodejs.');
+ // check if it's Node.js
+ if (Environment.isNode) {
+ logger.info('signMessage is not supported in nodejs.');
return {
signature: '',
address: '',
@@ -798,22 +737,22 @@ export const signMessage = async ({
// -- validate
if (!web3 || !account) {
- log(`web3: ${web3} OR ${account} not found. Connecting web3..`);
+ logger.info(`web3: ${web3} OR ${account} not found. Connecting web3..`);
const res = await connectWeb3({ chainId: 1 });
web3 = res.web3;
account = res.account;
}
- log('pausing...');
+ logger.info('pausing...');
await new Promise((resolve) => setTimeout(resolve, 500));
- log('signing with ', account);
+ logger.info({ msg: 'signing with ', account });
const signature = await signMessageAsync(web3.getSigner(), account, body);
const address = verifyMessage(body, signature).toLowerCase();
- log('Signature: ', signature);
- log('recovered address: ', address);
+ logger.info({ msg: 'Signature', signature });
+ logger.info({ msg: 'recovered address', address });
if (address.toLowerCase() !== account.toLowerCase()) {
const msg = `ruh roh, the user signed with a different address (${address}) then they're using with web3 (${account}). This will lead to confusion.`;
@@ -850,8 +789,8 @@ export const signMessageAsync = async (
message: string
): Promise => {
// check if it's nodejs
- if (isNode()) {
- log('signMessageAsync is not supported in nodejs.');
+ if (Environment.isNode) {
+ logger.warn('signMessageAsync is not supported in nodejs.');
return null;
}
@@ -859,23 +798,25 @@ export const signMessageAsync = async (
if (signer instanceof JsonRpcSigner) {
try {
- log('Signing with personal_sign');
+ logger.info('Signing with personal_sign');
const signature = await signer.provider.send('personal_sign', [
hexlify(messageBytes),
address.toLowerCase(),
]);
return signature;
- } catch (e: any) {
- log(
- 'Signing with personal_sign failed, trying signMessage as a fallback'
- );
- if (e.message.includes('personal_sign')) {
+ } catch (error: any) {
+ logger.warn({
+ function: 'signMessageAsync',
+ msg: 'Signing with personal_sign failed, trying signMessage as a fallback',
+ error,
+ });
+ if (error.message.includes('personal_sign')) {
return await signer.signMessage(messageBytes);
}
- throw e;
+ throw error;
}
} else {
- log('signing with signMessage');
+ logger.info('signing with signMessage');
return await signer.signMessage(messageBytes);
}
};
diff --git a/packages/auth/src/lib/authenticators/metamask/index.ts b/packages/auth/src/lib/authenticators/metamask/index.ts
new file mode 100644
index 0000000000..d42f9e5022
--- /dev/null
+++ b/packages/auth/src/lib/authenticators/metamask/index.ts
@@ -0,0 +1,3 @@
+import { MetamaskAuthenticator } from './MetamaskAuthenticator';
+
+export { MetamaskAuthenticator };
diff --git a/packages/auth-browser/src/lib/lit-connect-modal.d.ts b/packages/auth/src/lib/authenticators/metamask/lit-connect-modal.d.ts
similarity index 100%
rename from packages/auth-browser/src/lib/lit-connect-modal.d.ts
rename to packages/auth/src/lib/authenticators/metamask/lit-connect-modal.d.ts
diff --git a/packages/lit-auth-client/src/lib/providers/StytchAuthFactorOtp.ts b/packages/auth/src/lib/authenticators/stytch/StytchAuthFactorOtpAuthenticator.ts
similarity index 89%
rename from packages/lit-auth-client/src/lib/providers/StytchAuthFactorOtp.ts
rename to packages/auth/src/lib/authenticators/stytch/StytchAuthFactorOtpAuthenticator.ts
index 7f4dc25751..8e35a6467a 100644
--- a/packages/lit-auth-client/src/lib/providers/StytchAuthFactorOtp.ts
+++ b/packages/auth/src/lib/authenticators/stytch/StytchAuthFactorOtpAuthenticator.ts
@@ -12,19 +12,18 @@ import {
StytchToken,
} from '@lit-protocol/types';
-import { BaseProvider } from './BaseProvider';
+import { BaseAuthenticator } from '../BaseAuthenticator';
import {
FactorParser,
emailOtpAuthFactorParser,
smsOtpAuthFactorParser,
totpAuthFactorParser,
whatsAppOtpAuthFactorParser,
-} from './StytchAuthFactors';
+} from './parsers';
-export default class StytchAuthFactorOtpProvider<
+export class StytchAuthFactorOtpAuthenticator<
T extends FactorParser
-> extends BaseProvider {
- private _params: StytchOtpProviderOptions;
+> extends BaseAuthenticator {
private _factor: T;
private static _provider: string = 'https://stytch.com/session';
@@ -34,7 +33,6 @@ export default class StytchAuthFactorOtpProvider<
factor: T
) {
super(params);
- this._params = config;
this._factor = factor;
}
@@ -66,13 +64,16 @@ export default class StytchAuthFactorOtpProvider<
}
const parsedToken: StytchToken =
- StytchAuthFactorOtpProvider._parseJWT(accessToken);
- const factorParser = StytchAuthFactorOtpProvider._resolveAuthFactor(
+ StytchAuthFactorOtpAuthenticator._parseJWT(accessToken);
+ const factorParser = StytchAuthFactorOtpAuthenticator._resolveAuthFactor(
this._factor
);
try {
- factorParser.parser(parsedToken, StytchAuthFactorOtpProvider._provider);
+ factorParser.parser(
+ parsedToken,
+ StytchAuthFactorOtpAuthenticator._provider
+ );
} catch (e) {
reject(e);
}
@@ -93,7 +94,7 @@ export default class StytchAuthFactorOtpProvider<
* @returns {Promise} - Auth method id
*/
public async getAuthMethodId(authMethod: AuthMethod): Promise {
- return StytchAuthFactorOtpProvider.authMethodId(authMethod);
+ return StytchAuthFactorOtpAuthenticator.authMethodId(authMethod);
}
/**
@@ -109,7 +110,7 @@ export default class StytchAuthFactorOtpProvider<
return new Promise((resolve, reject) => {
const accessToken = authMethod.accessToken;
const parsedToken: StytchToken =
- StytchAuthFactorOtpProvider._parseJWT(accessToken);
+ StytchAuthFactorOtpAuthenticator._parseJWT(accessToken);
let factor: FactorParser = 'email';
switch (authMethod.authMethodType) {
case AUTH_METHOD_TYPE.StytchEmailFactorOtp:
@@ -144,7 +145,7 @@ export default class StytchAuthFactorOtpProvider<
}
private static _resolveAuthFactor(factor: FactorParser): {
- parser: Function;
+ parser: (parsedToken: StytchToken, provider: string) => string;
authMethodType: AUTH_METHOD_TYPE_VALUES;
} {
switch (factor) {
diff --git a/packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts b/packages/auth/src/lib/authenticators/stytch/StytchOtpAuthenticator.ts
similarity index 90%
rename from packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts
rename to packages/auth/src/lib/authenticators/stytch/StytchOtpAuthenticator.ts
index ee69ae999a..6eab48436f 100644
--- a/packages/lit-auth-client/src/lib/providers/StytchOtpProvider.ts
+++ b/packages/auth/src/lib/authenticators/stytch/StytchOtpAuthenticator.ts
@@ -9,9 +9,9 @@ import {
StytchOtpProviderOptions,
} from '@lit-protocol/types';
-import { BaseProvider } from './BaseProvider';
+import { BaseAuthenticator } from '../BaseAuthenticator';
-export class StytchOtpProvider extends BaseProvider {
+export class StytchOtpAuthenticator extends BaseAuthenticator {
private _params: StytchOtpProviderOptions;
private _provider: string = 'https://stytch.com/session';
@@ -48,7 +48,8 @@ export class StytchOtpProvider extends BaseProvider {
);
}
- const parsedToken: StytchToken = StytchOtpProvider._parseJWT(accessToken);
+ const parsedToken: StytchToken =
+ StytchOtpAuthenticator._parseJWT(accessToken);
const audience = (parsedToken['aud'] as string[])[0];
if (audience != this._params.appId) {
reject(new Error('Parsed application id does not match parameters'));
@@ -92,11 +93,11 @@ export class StytchOtpProvider extends BaseProvider {
* @returns {Promise} - Auth method id
*/
public async getAuthMethodId(authMethod: AuthMethod): Promise {
- return StytchOtpProvider.authMethodId(authMethod);
+ return StytchOtpAuthenticator.authMethodId(authMethod);
}
public static async authMethodId(authMethod: AuthMethod): Promise {
- const tokenBody = StytchOtpProvider._parseJWT(authMethod.accessToken);
+ const tokenBody = StytchOtpAuthenticator._parseJWT(authMethod.accessToken);
const userId = tokenBody['sub'] as string;
const orgId = (tokenBody['aud'] as string[])[0];
const authMethodId = ethers.utils.keccak256(
@@ -124,7 +125,6 @@ export class StytchOtpProvider extends BaseProvider {
}
const body = Buffer.from(parts[1], 'base64');
const parsedBody: StytchToken = JSON.parse(body.toString('ascii'));
- console.log('JWT body: ', parsedBody);
return parsedBody;
}
}
diff --git a/packages/auth/src/lib/authenticators/stytch/index.ts b/packages/auth/src/lib/authenticators/stytch/index.ts
new file mode 100644
index 0000000000..e3a3005202
--- /dev/null
+++ b/packages/auth/src/lib/authenticators/stytch/index.ts
@@ -0,0 +1,4 @@
+import { StytchAuthFactorOtpAuthenticator } from './StytchAuthFactorOtpAuthenticator';
+import { StytchOtpAuthenticator } from './StytchOtpAuthenticator';
+
+export { StytchAuthFactorOtpAuthenticator, StytchOtpAuthenticator };
diff --git a/packages/lit-auth-client/src/lib/providers/StytchAuthFactors.ts b/packages/auth/src/lib/authenticators/stytch/parsers.ts
similarity index 68%
rename from packages/lit-auth-client/src/lib/providers/StytchAuthFactors.ts
rename to packages/auth/src/lib/authenticators/stytch/parsers.ts
index f734ce4f2d..eb9149882d 100644
--- a/packages/lit-auth-client/src/lib/providers/StytchAuthFactors.ts
+++ b/packages/auth/src/lib/authenticators/stytch/parsers.ts
@@ -1,6 +1,14 @@
+import { ethers } from 'ethers';
+
import { WrongParamFormat } from '@lit-protocol/constants';
import { StytchToken } from '@lit-protocol/types';
-import { ethers } from 'ethers';
+
+import type {
+ AuthenticationFactor,
+ AuthenticatorAppFactor,
+ EmailFactor,
+ PhoneNumberFactor,
+} from 'stytch';
export type FactorParser = 'email' | 'sms' | 'whatsApp' | 'totp';
@@ -9,10 +17,9 @@ export const emailOtpAuthFactorParser = (
provider: string
): string => {
const session = parsedToken[provider];
- const authFactors: any[] = session['authentication_factors'];
- let authFactor = authFactors.find((value, _index, _obj) => {
- if (value.email_factor) return value;
- });
+ const authFactors: AuthenticationFactor[] = session['authentication_factors'];
+
+ const authFactor = authFactors.find((value) => !!value.email_factor);
if (!authFactor) {
throw new WrongParamFormat(
@@ -25,6 +32,9 @@ export const emailOtpAuthFactorParser = (
'Could not find email authentication info in session'
);
}
+
+ const emailFactor = authFactor.email_factor as EmailFactor;
+
const audience = (parsedToken['aud'] as string[])[0];
if (!audience) {
throw new WrongParamFormat(
@@ -38,7 +48,7 @@ export const emailOtpAuthFactorParser = (
);
}
- const userId = authFactor.email_factor.email_address;
+ const userId = emailFactor.email_address;
const authMethodId = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(
`${userId.toLowerCase()}:${audience.toLowerCase()}`
@@ -53,10 +63,8 @@ export const smsOtpAuthFactorParser = (
provider: string
): string => {
const session = parsedToken[provider];
- const authFactors: any[] = session['authentication_factors'];
- let authFactor = authFactors.find((value, _index, _obj) => {
- if (value.phone_number_factor) return value;
- });
+ const authFactors: AuthenticationFactor[] = session['authentication_factors'];
+ const authFactor = authFactors.find((value) => !!value.phone_number_factor);
if (!authFactor) {
throw new WrongParamFormat(
@@ -66,9 +74,12 @@ export const smsOtpAuthFactorParser = (
provider,
},
},
- 'Could not find email authentication info in session'
+ 'Could not find phone authentication info in session'
);
}
+
+ const phoneNumberFactor = authFactor.phone_number_factor as PhoneNumberFactor;
+
const audience = (parsedToken['aud'] as string[])[0];
if (!audience) {
throw new WrongParamFormat(
@@ -82,7 +93,7 @@ export const smsOtpAuthFactorParser = (
);
}
- const userId = authFactor.phone_number_factor.phone_number;
+ const userId = phoneNumberFactor.phone_number;
const authMethodId = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(
`${userId.toLowerCase()}:${audience.toLowerCase()}`
@@ -97,10 +108,8 @@ export const whatsAppOtpAuthFactorParser = (
provider: string
): string => {
const session = parsedToken[provider];
- const authFactors: any[] = session['authentication_factors'];
- let authFactor = authFactors.find((value, _index, _obj) => {
- if (value.phone_number_factor) return value;
- });
+ const authFactors: AuthenticationFactor[] = session['authentication_factors'];
+ const authFactor = authFactors.find((value) => !!value.phone_number_factor);
if (!authFactor) {
throw new WrongParamFormat(
@@ -110,9 +119,12 @@ export const whatsAppOtpAuthFactorParser = (
provider,
},
},
- 'Could not find email authentication info in session'
+ 'Could not find phone authentication info in session'
);
}
+
+ const phoneNumberFactor = authFactor.phone_number_factor as PhoneNumberFactor;
+
const audience = (parsedToken['aud'] as string[])[0];
if (!audience) {
throw new WrongParamFormat(
@@ -126,7 +138,7 @@ export const whatsAppOtpAuthFactorParser = (
);
}
- const userId = authFactor.phone_number_factor.phone_number;
+ const userId = phoneNumberFactor.phone_number;
const authMethodId = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(
`${userId.toLowerCase()}:${audience.toLowerCase()}`
@@ -141,10 +153,10 @@ export const totpAuthFactorParser = (
provider: string
): string => {
const session = parsedToken[provider];
- const authFactors: any[] = session['authentication_factors'];
- let authFactor = authFactors.find((value, _index, _obj) => {
- if (value.phone_number_factor) return value;
- });
+ const authFactors: AuthenticationFactor[] = session['authentication_factors'];
+ const authFactor = authFactors.find(
+ (value) => !!value.authenticator_app_factor
+ );
if (!authFactor) {
throw new WrongParamFormat(
@@ -154,9 +166,13 @@ export const totpAuthFactorParser = (
provider,
},
},
- 'Could not find email authentication info in session'
+ 'Could not find authenticator app authentication info in session'
);
}
+
+ const authenticatorAppFactor =
+ authFactor.authenticator_app_factor as AuthenticatorAppFactor;
+
const audience = (parsedToken['aud'] as string[])[0];
if (!audience) {
throw new WrongParamFormat(
@@ -170,7 +186,7 @@ export const totpAuthFactorParser = (
);
}
- const userId = authFactor.authenticator_app_factor.totp_id;
+ const userId = authenticatorAppFactor.totp_id;
const authMethodId = ethers.utils.keccak256(
ethers.utils.toUtf8Bytes(
`${userId.toLowerCase()}:${audience.toLowerCase()}`
diff --git a/packages/lit-auth-client/src/lib/utils.ts b/packages/auth/src/lib/authenticators/utils.ts
similarity index 87%
rename from packages/lit-auth-client/src/lib/utils.ts
rename to packages/auth/src/lib/authenticators/utils.ts
index 636986a974..78c912f9d6 100644
--- a/packages/lit-auth-client/src/lib/utils.ts
+++ b/packages/auth/src/lib/authenticators/utils.ts
@@ -5,30 +5,18 @@ import {
InvalidArgumentException,
UnknownError,
} from '@lit-protocol/constants';
-import { getLoggerbyId } from '@lit-protocol/misc';
import { AuthMethod, LoginUrlParams } from '@lit-protocol/types';
-import DiscordProvider from './providers/DiscordProvider';
-import EthWalletProvider from './providers/EthWalletProvider';
-import GoogleProvider from './providers/GoogleProvider';
-import StytchAuthFactorOtpProvider from './providers/StytchAuthFactorOtp';
-import { StytchOtpProvider } from './providers/StytchOtpProvider';
-import WebAuthnProvider from './providers/WebAuthnProvider';
+import { DiscordAuthenticator } from './DiscordAuthenticator';
+import { GoogleAuthenticator } from './GoogleAuthenticator';
+import { MetamaskAuthenticator } from './metamask/MetamaskAuthenticator';
+import { StytchAuthFactorOtpAuthenticator } from './stytch/StytchAuthFactorOtpAuthenticator';
+import { StytchOtpAuthenticator } from './stytch/StytchOtpAuthenticator';
+import { WebAuthnAuthenticator } from './WebAuthnAuthenticator';
export const STATE_PARAM_KEY = 'lit-state-param';
export const LIT_LOGIN_GATEWAY = 'https://login.litgateway.com';
-/**
- * Check if OAuth provider is supported
- *
- * @param provider {string} - Auth provider name
- *
- * @returns {boolean} - True if provider is supported
- */
-export function isSocialLoginSupported(provider: string): boolean {
- return ['google', 'discord'].includes(provider);
-}
-
/**
* Create login url using the parameters provided as arguments when initializing the client
*
@@ -79,11 +67,11 @@ function getLoginRoute(provider: string): string {
/**
* Create query params string from given object
*
- * @param params {any} - Object of query params
+ * @param params {Record} - Object of query params
*
* @returns {string} - Query string
*/
-function createQueryParams(params: any): string {
+function createQueryParams(params: Record): string {
// Strip undefined values from params
const filteredParams = Object.keys(params)
.filter((k) => typeof params[k] !== 'undefined')
@@ -335,11 +323,6 @@ export function unparse(buf: any) {
);
}
-export function log(...args: any) {
- const logger = getLoggerbyId('auth-client');
- logger.debug(...args);
-}
-
/**
* Retrieves the authentication ID based on the provided authentication method.
*
@@ -353,28 +336,27 @@ export async function getAuthIdByAuthMethod(
switch (authMethod.authMethodType) {
case AUTH_METHOD_TYPE.EthWallet:
- authId = await EthWalletProvider.authMethodId(authMethod);
+ authId = await MetamaskAuthenticator.authMethodId(authMethod);
break;
case AUTH_METHOD_TYPE.Discord:
- authId = await DiscordProvider.authMethodId(authMethod);
+ authId = await DiscordAuthenticator.authMethodId(authMethod);
break;
case AUTH_METHOD_TYPE.WebAuthn:
- authId = await WebAuthnProvider.authMethodId(authMethod);
+ authId = await WebAuthnAuthenticator.authMethodId(authMethod);
break;
case AUTH_METHOD_TYPE.GoogleJwt:
- authId = await GoogleProvider.authMethodId(authMethod);
+ authId = await GoogleAuthenticator.authMethodId(authMethod);
break;
case AUTH_METHOD_TYPE.StytchOtp:
- authId = await StytchOtpProvider.authMethodId(authMethod);
+ authId = await StytchOtpAuthenticator.authMethodId(authMethod);
break;
case AUTH_METHOD_TYPE.StytchEmailFactorOtp:
case AUTH_METHOD_TYPE.StytchSmsFactorOtp:
case AUTH_METHOD_TYPE.StytchTotpFactorOtp:
case AUTH_METHOD_TYPE.StytchWhatsAppFactorOtp:
- authId = await StytchAuthFactorOtpProvider.authMethodId(authMethod);
+ authId = await StytchAuthFactorOtpAuthenticator.authMethodId(authMethod);
break;
default:
- log(`unsupported AuthMethodType: ${authMethod.authMethodType}`);
throw new InvalidArgumentException(
{
info: {
diff --git a/packages/lit-auth-client/src/lib/validators.spec.ts b/packages/auth/src/lib/authenticators/validators.spec.ts
similarity index 86%
rename from packages/lit-auth-client/src/lib/validators.spec.ts
rename to packages/auth/src/lib/authenticators/validators.spec.ts
index 91d1419fbb..f821db1bc1 100644
--- a/packages/lit-auth-client/src/lib/validators.spec.ts
+++ b/packages/auth/src/lib/authenticators/validators.spec.ts
@@ -1,8 +1,16 @@
+const errorMock = jest.fn();
+
+jest.mock('pino', () => {
+ return {
+ pino: jest.fn(() => ({
+ error: errorMock,
+ })),
+ };
+});
+
import { validateMintRequestBody } from './validators';
describe('validateMintRequestBody', () => {
- const mockConsoleError = jest.spyOn(console, 'error').mockImplementation();
-
afterEach(() => {
jest.clearAllMocks();
});
@@ -22,13 +30,13 @@ describe('validateMintRequestBody', () => {
sendPkpToItself: true,
};
expect(validateMintRequestBody(customArgs)).toBe(true);
- expect(mockConsoleError).not.toHaveBeenCalled();
+ expect(errorMock).not.toHaveBeenCalled();
});
it('should pass validation when no fields are provided', () => {
const customArgs = {};
expect(validateMintRequestBody(customArgs)).toBe(true);
- expect(mockConsoleError).not.toHaveBeenCalled();
+ expect(errorMock).not.toHaveBeenCalled();
});
it('should pass validation when some fields are provided and correct', () => {
@@ -37,7 +45,7 @@ describe('validateMintRequestBody', () => {
permittedAuthMethodPubkeys: ['pubkey123'],
};
expect(validateMintRequestBody(customArgs)).toBe(true);
- expect(mockConsoleError).not.toHaveBeenCalled();
+ expect(errorMock).not.toHaveBeenCalled();
});
it('should fail validation and log error for incorrect keyType', () => {
@@ -45,7 +53,7 @@ describe('validateMintRequestBody', () => {
keyType: '2', // should be a number
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining('Invalid type for keyType')
);
});
@@ -55,7 +63,7 @@ describe('validateMintRequestBody', () => {
permittedAuthMethodTypes: ['1'], // should be an array of numbers
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining('Invalid type for permittedAuthMethodTypes')
);
});
@@ -65,7 +73,7 @@ describe('validateMintRequestBody', () => {
permittedAuthMethodIds: [123], // should be an array of strings
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining('Invalid type for permittedAuthMethodIds')
);
});
@@ -75,7 +83,7 @@ describe('validateMintRequestBody', () => {
permittedAuthMethodPubkeys: [123], // should be an array of strings
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining('Invalid type for permittedAuthMethodPubkeys')
);
});
@@ -91,7 +99,7 @@ describe('validateMintRequestBody', () => {
addPkpEthAddressAsPermittedAddress: 'true', // should be a boolean
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining(
'Invalid type for addPkpEthAddressAsPermittedAddress'
)
@@ -103,7 +111,7 @@ describe('validateMintRequestBody', () => {
sendPkpToItself: 'true', // should be a boolean
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining('Invalid type for sendPkpToItself')
);
});
@@ -113,7 +121,7 @@ describe('validateMintRequestBody', () => {
extraneousKey: 'unexpected', // This key is not defined in MintRequestBody
};
expect(validateMintRequestBody(customArgs as any)).toBe(false);
- expect(mockConsoleError).toHaveBeenCalledWith(
+ expect(errorMock).toHaveBeenCalledWith(
expect.stringContaining('Invalid key found: extraneousKey')
);
});
diff --git a/packages/lit-auth-client/src/lib/validators.ts b/packages/auth/src/lib/authenticators/validators.ts
similarity index 86%
rename from packages/lit-auth-client/src/lib/validators.ts
rename to packages/auth/src/lib/authenticators/validators.ts
index d7cb27dc2a..f9ccf59147 100644
--- a/packages/lit-auth-client/src/lib/validators.ts
+++ b/packages/auth/src/lib/authenticators/validators.ts
@@ -1,8 +1,10 @@
+import { getChildLogger } from '@lit-protocol/logger';
import { MintRequestBody } from '@lit-protocol/types';
export const validateMintRequestBody = (
customArgs: Partial
): boolean => {
+ const logger = getChildLogger({ function: 'validateMintRequestBody' });
let isValid = true;
const validKeys = [
'keyType',
@@ -17,7 +19,7 @@ export const validateMintRequestBody = (
// Check for any extraneous keys
for (const key of Object.keys(customArgs)) {
if (!validKeys.includes(key)) {
- console.error(
+ logger.error(
`Invalid key found: ${key}. This key is not allowed. Valid keys are: ${validKeys.join(
', '
)}`
@@ -30,7 +32,7 @@ export const validateMintRequestBody = (
customArgs.keyType !== undefined &&
typeof customArgs.keyType !== 'number'
) {
- console.error('Invalid type for keyType: expected a number.');
+ logger.error('Invalid type for keyType: expected a number.');
isValid = false;
}
@@ -41,7 +43,7 @@ export const validateMintRequestBody = (
(type) => typeof type === 'number'
))
) {
- console.error(
+ logger.error(
'Invalid type for permittedAuthMethodTypes: expected an array of numbers.'
);
isValid = false;
@@ -52,7 +54,7 @@ export const validateMintRequestBody = (
(!Array.isArray(customArgs.permittedAuthMethodIds) ||
!customArgs.permittedAuthMethodIds.every((id) => typeof id === 'string'))
) {
- console.error(
+ logger.error(
'Invalid type for permittedAuthMethodIds: expected an array of strings.'
);
isValid = false;
@@ -65,7 +67,7 @@ export const validateMintRequestBody = (
(pubkey) => typeof pubkey === 'string'
))
) {
- console.error(
+ logger.error(
'Invalid type for permittedAuthMethodPubkeys: expected an array of strings.'
);
isValid = false;
@@ -79,8 +81,8 @@ export const validateMintRequestBody = (
Array.isArray(scope) && scope.every((s) => typeof s === 'number')
))
) {
- console.error(
- 'Invalid type for permittedAuthMethodScopes: expected an array of arrays of numberr.'
+ logger.error(
+ 'Invalid type for permittedAuthMethodScopes: expected an array of arrays of number.'
);
isValid = false;
}
@@ -89,7 +91,7 @@ export const validateMintRequestBody = (
customArgs.addPkpEthAddressAsPermittedAddress !== undefined &&
typeof customArgs.addPkpEthAddressAsPermittedAddress !== 'boolean'
) {
- console.error(
+ logger.error(
'Invalid type for addPkpEthAddressAsPermittedAddress: expected a boolean.'
);
isValid = false;
@@ -99,7 +101,7 @@ export const validateMintRequestBody = (
customArgs.sendPkpToItself !== undefined &&
typeof customArgs.sendPkpToItself !== 'boolean'
) {
- console.error('Invalid type for sendPkpToItself: expected a boolean.');
+ logger.error('Invalid type for sendPkpToItself: expected a boolean.');
isValid = false;
}
diff --git a/packages/lit-auth-client/src/lib/relay.ts b/packages/auth/src/lib/relay.ts
similarity index 75%
rename from packages/lit-auth-client/src/lib/relay.ts
rename to packages/auth/src/lib/relay.ts
index cf0951aaca..a55e53a0c6 100644
--- a/packages/lit-auth-client/src/lib/relay.ts
+++ b/packages/auth/src/lib/relay.ts
@@ -9,6 +9,7 @@ import {
InvalidParamType,
NetworkError,
} from '@lit-protocol/constants';
+import { getChildLogger } from '@lit-protocol/logger';
import {
AuthMethod,
MintRequestBody,
@@ -19,13 +20,16 @@ import {
LitRelayConfig,
} from '@lit-protocol/types';
-import WebAuthnProvider from './providers/WebAuthnProvider';
-import { getAuthIdByAuthMethod, log } from './utils';
+import { getAuthIdByAuthMethod } from './authenticators/utils';
+import { WebAuthnAuthenticator } from './authenticators/WebAuthnAuthenticator';
/**
* Class that communicates with Lit relay server
*/
export class LitRelay implements IRelay {
+ private _logger = getChildLogger({
+ module: 'LitRelay',
+ });
/** URL for Lit's relay server */
static getRelayUrl(litNetwork: LIT_NETWORK_VALUES): string {
const relayerUrl = RELAYER_URL_BY_NETWORK[litNetwork];
@@ -71,7 +75,10 @@ export class LitRelay implements IRelay {
this.relayUrl =
config.relayUrl || LitRelay.getRelayUrl(LIT_NETWORK.NagaDev);
this.relayApiKey = config.relayApiKey || '';
- log("Lit's relay server URL:", this.relayUrl);
+ this._logger.info({
+ msg: "Lit's relay server URL",
+ relayUrl: this.relayUrl,
+ });
}
/**
@@ -92,12 +99,25 @@ export class LitRelay implements IRelay {
});
if (response.status < 200 || response.status >= 400) {
- log('Something wrong with the API call', await response.json());
- const err = new Error('Unable to mint PKP through relay server');
- throw err;
+ const responseBody = await response.json();
+ this._logger.info({
+ msg: 'Something wrong with the API call',
+ responseBody,
+ });
+ throw new NetworkError(
+ {
+ info: {
+ route: `${this.relayUrl}${this.mintRoute}`,
+ responseStatus: response.status,
+ responseStatusText: response.statusText,
+ responseBody,
+ },
+ },
+ 'Unable to mint PKP through relay server'
+ );
} else {
const resBody = await response.json();
- log('Successfully initiated minting PKP with relayer');
+ this._logger.info('Successfully initiated minting PKP with relayer');
return resBody;
}
}
@@ -169,7 +189,7 @@ export class LitRelay implements IRelay {
permittedAuthMethodIds.push(id);
if (authMethod.authMethodType === AUTH_METHOD_TYPE.WebAuthn) {
permittedAuthMethodPubkeys.push(
- WebAuthnProvider.getPublicKeyFromRegistration(
+ WebAuthnAuthenticator.getPublicKeyFromRegistration(
JSON.parse(authMethod.accessToken)
)
);
@@ -231,26 +251,47 @@ export class LitRelay implements IRelay {
);
if (response.status < 200 || response.status >= 400) {
- log('Something wrong with the API call', await response.json());
- const err = new Error(
+ const responseBody = await response.json();
+ this._logger.info({
+ msg: 'Something wrong with the API call',
+ responseBody,
+ });
+ throw new NetworkError(
+ {
+ info: {
+ route: `${this.relayUrl}/auth/status/${requestId}`,
+ responseStatus: response.status,
+ responseStatusText: response.statusText,
+ responseBody,
+ },
+ },
`Unable to poll the status of this mint PKP transaction: ${requestId}`
);
- throw err;
}
const resBody = await response.json();
- log('Response OK', { body: resBody });
+ this._logger.info({ msg: 'Response OK', resBody });
if (resBody.error) {
// exit loop since error
- log('Something wrong with the API call', {
+ this._logger.info({
+ msg: 'Something wrong with the API call',
error: resBody.error,
});
- const err = new Error(resBody.error);
- throw err;
+ throw new NetworkError(
+ {
+ info: {
+ route: `${this.relayUrl}/auth/status/${requestId}`,
+ responseStatus: response.status,
+ responseStatusText: response.statusText,
+ resBody,
+ },
+ },
+ resBody.error
+ );
} else if (resBody.status === 'Succeeded') {
// exit loop since success
- log('Successfully authed', { ...resBody });
+ this._logger.info({ msg: 'Successfully authed', resBody });
return resBody;
}
@@ -259,9 +300,14 @@ export class LitRelay implements IRelay {
}
// at this point, polling ended and still no success, set failure status
- // console.error(`Hmm this is taking longer than expected...`);
- const err = new Error('Polling for mint PKP transaction status timed out');
- throw err;
+ throw new NetworkError(
+ {
+ info: {
+ route: `${this.relayUrl}/auth/status/${requestId}`,
+ },
+ },
+ 'Polling for mint PKP transaction status timed out'
+ );
}
/**
@@ -282,13 +328,25 @@ export class LitRelay implements IRelay {
});
if (response.status < 200 || response.status >= 400) {
- console.warn('Something wrong with the API call', await response.json());
- // console.log("Uh oh, something's not quite right.");
- const err = new Error('Unable to fetch PKPs through relay server');
- throw err;
+ const resBody = await response.json();
+ this._logger.warn({
+ msg: 'Something wrong with the API call',
+ resBody,
+ });
+ throw new NetworkError(
+ {
+ info: {
+ route: `${this.relayUrl}${this.fetchRoute}`,
+ responseStatus: response.status,
+ responseStatusText: response.statusText,
+ resBody,
+ },
+ },
+ 'Unable to fetch PKPs through relay server'
+ );
} else {
const resBody = await response.json();
- console.log('Successfully fetched PKPs with relayer');
+ this._logger.info('Successfully fetched PKPs with relayer');
return resBody;
}
}
@@ -312,10 +370,16 @@ export class LitRelay implements IRelay {
},
});
if (response.status < 200 || response.status >= 400) {
- const err = new Error(
+ throw new NetworkError(
+ {
+ info: {
+ route: `${this.relayUrl}${this.fetchRoute}`,
+ responseStatus: response.status,
+ responseStatusText: response.statusText,
+ },
+ },
`Unable to generate registration options: ${response}`
);
- throw err;
}
const registrationOptions = await response.json();
return registrationOptions;
diff --git a/packages/auth/src/lib/storage/index.ts b/packages/auth/src/lib/storage/index.ts
new file mode 100644
index 0000000000..03dc996c44
--- /dev/null
+++ b/packages/auth/src/lib/storage/index.ts
@@ -0,0 +1,3 @@
+import { localStorage } from './localStorage';
+
+export { localStorage };
diff --git a/packages/auth/src/lib/storage/localStorage.spec.ts b/packages/auth/src/lib/storage/localStorage.spec.ts
new file mode 100644
index 0000000000..6b706a270d
--- /dev/null
+++ b/packages/auth/src/lib/storage/localStorage.spec.ts
@@ -0,0 +1,131 @@
+import { localStorage as createLocalStorage } from './localStorage';
+
+import type { LitAuthData } from '../types';
+
+describe('localStorage', () => {
+ let mockLocalStorage: WindowLocalStorage['localStorage'];
+
+ beforeEach(() => {
+ mockLocalStorage = (() => {
+ const store = new Map();
+ return {
+ getItem: (key: string) =>
+ store.has(key) ? store.get(key) ?? null : null,
+ setItem: (key: string, value: string) => store.set(key, value),
+ };
+ })() as unknown as WindowLocalStorage['localStorage'];
+ });
+
+ const appName: string = 'testApp';
+ const networkName: string = 'testNetwork';
+ const pkpAddress: string = '0x123';
+ const authData: LitAuthData = {
+ credential: 'abc123',
+ authMethod: 'EthWallet',
+ };
+
+ test('initializes correctly and validates localStorage', () => {
+ expect(() =>
+ createLocalStorage({
+ appName,
+ networkName,
+ localStorage: mockLocalStorage,
+ })
+ ).not.toThrow();
+ });
+
+ test('throws an error if localStorage is missing', () => {
+ expect(() =>
+ // @ts-expect-error Stubbing localstorage for error checking
+ createLocalStorage({ appName, networkName, localStorage: null })
+ ).toThrow('localStorage is not available in this environment');
+ });
+
+ test('writes and reads to/from localStorage correctly', async () => {
+ mockLocalStorage.setItem(
+ `lit-auth:${appName}:${networkName}:${pkpAddress}`,
+ JSON.stringify(authData)
+ );
+ const storage = createLocalStorage({
+ appName,
+ networkName,
+ localStorage: mockLocalStorage,
+ });
+
+ await expect(storage.read({ pkpAddress })).resolves.toEqual(authData);
+ });
+
+ test('returns null when reading nonexistent data', async () => {
+ const storage = createLocalStorage({
+ appName,
+ networkName,
+ localStorage: mockLocalStorage,
+ });
+ const result = await storage.read({ pkpAddress });
+
+ expect(result).toBeNull();
+ });
+
+ test('isolates data between different network names', async () => {
+ const storageNetworkA = createLocalStorage({
+ appName,
+ networkName: 'networkA',
+ localStorage: mockLocalStorage,
+ });
+ const storageNetworkB = createLocalStorage({
+ appName,
+ networkName: 'networkB',
+ localStorage: mockLocalStorage,
+ });
+
+ const authDataNetworkA = { ...authData, credential: 'networkA' };
+ const authDataNetworkB = { ...authData, credential: 'networkB' };
+
+ await storageNetworkA.write({
+ pkpAddress,
+ authData: authDataNetworkA,
+ });
+
+ await expect(storageNetworkA.read({ pkpAddress })).resolves.toEqual(
+ authDataNetworkA
+ );
+ await expect(storageNetworkB.read({ pkpAddress })).resolves.toBeNull();
+
+ await storageNetworkB.write({
+ pkpAddress,
+ authData: authDataNetworkB,
+ });
+
+ await expect(storageNetworkA.read({ pkpAddress })).resolves.toEqual(
+ authDataNetworkA
+ );
+ await expect(storageNetworkB.read({ pkpAddress })).resolves.toEqual(
+ authDataNetworkB
+ );
+ });
+
+ test('isolates data between different app names', async () => {
+ const storageAppA = createLocalStorage({
+ appName: 'appA',
+ networkName,
+ localStorage: mockLocalStorage,
+ });
+ const storageAppB = createLocalStorage({
+ appName: 'appB',
+ networkName,
+ localStorage: mockLocalStorage,
+ });
+
+ const authDataNetworkB = { ...authData, credential: 'networkB' };
+
+ await storageAppA.write({ pkpAddress, authData });
+ await expect(storageAppA.read({ pkpAddress })).resolves.toEqual(authData);
+ await expect(storageAppB.read({ pkpAddress })).resolves.toBeNull();
+
+ await storageAppB.write({ pkpAddress, authData: authDataNetworkB });
+ await expect(storageAppB.read({ pkpAddress })).resolves.toEqual(
+ authDataNetworkB
+ );
+ await expect(storageAppA.read({ pkpAddress })).resolves.toEqual(authData);
+ });
+});
diff --git a/packages/auth/src/lib/storage/localStorage.ts b/packages/auth/src/lib/storage/localStorage.ts
new file mode 100644
index 0000000000..c3fdf9a7f4
--- /dev/null
+++ b/packages/auth/src/lib/storage/localStorage.ts
@@ -0,0 +1,102 @@
+import type { LitAuthStorageProvider } from './types';
+import type { LitAuthData } from '../types';
+
+const LOCALSTORAGE_LIT_AUTH_PREFIX = 'lit-auth';
+
+interface LocalStorageConfig {
+ appName: string;
+ localStorage?: WindowLocalStorage['localStorage'];
+ networkName: string;
+}
+
+function assertLocalstorageValid(
+ localStorage: unknown
+): asserts localStorage is WindowLocalStorage['localStorage'] {
+ if (!localStorage) {
+ throw new Error('localStorage is not available in this environment');
+ }
+
+ if (typeof localStorage !== 'object') {
+ throw new Error('localStorage is not an object');
+ }
+
+ if (
+ !('getItem' in localStorage) ||
+ typeof localStorage.getItem !== 'function'
+ ) {
+ throw new Error('localStorage does not have `getItem` method');
+ }
+
+ if (
+ !('setItem' in localStorage) ||
+ typeof localStorage.setItem !== 'function'
+ ) {
+ throw new Error('localStorage does not have `setItem` method');
+ }
+}
+
+/**
+ * Builds a lookup key for localStorage based on the provided parameters.
+ * Ensures that all auth data loaded for a given PKP is for the expected LIT network
+ * in cases where the same environment may be used to communicate w/ multiple networks
+ *
+ * @param {object} params - The parameters required to build the lookup key.
+ * @param {string} params.appName - The name of the application; used to store different auth material for the same PKP on the same domain
+ * @param {string} params.networkName - The name of the network; used to store different auth material per LIT network
+ * @param {string} params.pkpAddress - The LIT PKP address.
+ *
+ * @returns {string} The generated lookup key for localStorage.
+ *
+ * @private
+ */
+function buildLookupKey({
+ appName,
+ networkName,
+ pkpAddress,
+}: {
+ appName: string;
+ networkName: string;
+ pkpAddress: string;
+}): string {
+ return `${LOCALSTORAGE_LIT_AUTH_PREFIX}:${appName}:${networkName}:${pkpAddress}`;
+}
+
+export function localStorage({
+ appName,
+ networkName,
+ localStorage = globalThis.localStorage,
+}: LocalStorageConfig): LitAuthStorageProvider {
+ assertLocalstorageValid(localStorage);
+
+ return {
+ config: { appName, networkName, localStorage },
+
+ async write({ pkpAddress, authData }) {
+ localStorage.setItem(
+ buildLookupKey({
+ appName,
+ networkName,
+ pkpAddress,
+ }),
+ JSON.stringify(authData)
+ );
+ },
+
+ async read({ pkpAddress }): Promise {
+ const value = localStorage.getItem(
+ buildLookupKey({
+ appName,
+ networkName,
+ pkpAddress,
+ })
+ );
+
+ if (!value) {
+ // Empty string will be converted to null
+ return null;
+ } else {
+ return JSON.parse(value);
+ }
+ },
+ };
+}
diff --git a/packages/auth/src/lib/storage/types.ts b/packages/auth/src/lib/storage/types.ts
new file mode 100644
index 0000000000..3905bb95fc
--- /dev/null
+++ b/packages/auth/src/lib/storage/types.ts
@@ -0,0 +1,15 @@
+import type { LitAuthData } from '../types';
+
+export interface LitAuthStorageProvider {
+ config: unknown;
+
+ read(
+ params: T,
+ options?: unknown
+ ): Promise;
+
+ write(
+ params: T,
+ options?: unknown
+ ): Promise;
+}
diff --git a/packages/auth/src/lib/types.ts b/packages/auth/src/lib/types.ts
new file mode 100644
index 0000000000..b7347a9ef5
--- /dev/null
+++ b/packages/auth/src/lib/types.ts
@@ -0,0 +1,6 @@
+import { AUTH_METHOD_TYPE } from '@lit-protocol/constants';
+
+export interface LitAuthData {
+ credential: string;
+ authMethod: keyof typeof AUTH_METHOD_TYPE;
+}
diff --git a/packages/encryption/tsconfig.json b/packages/auth/tsconfig.json
similarity index 100%
rename from packages/encryption/tsconfig.json
rename to packages/auth/tsconfig.json
diff --git a/packages/auth-browser/tsconfig.lib.json b/packages/auth/tsconfig.lib.json
similarity index 100%
rename from packages/auth-browser/tsconfig.lib.json
rename to packages/auth/tsconfig.lib.json
diff --git a/packages/auth/tsconfig.spec.json b/packages/auth/tsconfig.spec.json
new file mode 100644
index 0000000000..df5eec354a
--- /dev/null
+++ b/packages/auth/tsconfig.spec.json
@@ -0,0 +1,16 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "ES2022",
+ "types": ["jest", "node"],
+ "allowJs": true
+ },
+ "include": [
+ "jest.config.ts",
+ "**/*.test.ts",
+ "**/*.spec.ts",
+ "**/*.d.ts",
+ "../auth-browser/src/lib/chains/lit-connect-modal.d.ts"
+ ]
+}
diff --git a/packages/constants/babel.config.json b/packages/constants/babel.config.json
deleted file mode 100644
index 158083d278..0000000000
--- a/packages/constants/babel.config.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presets": [
- [
- "@nx/web/babel",
- {
- "useBuiltIns": "usage"
- }
- ]
- ]
-}
diff --git a/packages/constants/package.json b/packages/constants/package.json
index 0b84b2c77c..7c357ec8c1 100644
--- a/packages/constants/package.json
+++ b/packages/constants/package.json
@@ -12,6 +12,7 @@
"bugs": {
"url": "https://github.com/LIT-Protocol/js-sdk/issues"
},
+ "type": "commonjs",
"publishConfig": {
"access": "public",
"directory": "../../dist/packages/constants"
diff --git a/packages/constants/project.json b/packages/constants/project.json
index c270222f93..715e72efb0 100644
--- a/packages/constants/project.json
+++ b/packages/constants/project.json
@@ -15,12 +15,6 @@
"updateBuildableProjectDepsInPackageJson": true
}
},
- "copyJSONFilesToDist": {
- "executor": "nx:run-commands",
- "options": {
- "command": "mkdir -p dist/packages/constants/web/abis && cp ./packages/constants/src/lib/abis/ERC20.json dist/packages/constants/web/abis/ERC20.json && cp ./packages/constants/src/lib/abis/LIT.json dist/packages/constants/web/abis/LIT.json"
- }
- },
"generateDoc": {
"executor": "nx:run-commands",
"options": {
@@ -34,7 +28,7 @@
"lintFilePatterns": ["packages/constants/**/*.ts"]
}
},
- "testPackage": {
+ "test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/packages/constants"],
"options": {
diff --git a/packages/constants/src/index.ts b/packages/constants/src/index.ts
index 940d84a592..2c72a5d0d2 100644
--- a/packages/constants/src/index.ts
+++ b/packages/constants/src/index.ts
@@ -1,22 +1,14 @@
// ----------- Version -----------
export * from './lib/version';
+// ----------- Environment -----------
+export * from './lib/environment';
+
// ----------- Constants -----------
export * from './lib/constants/constants';
export * from './lib/constants/mappers';
export * from './lib/constants/endpoints';
export * from './lib/constants/curves';
-// ----------- Interfaces -----------
-export * from './lib/interfaces/i-errors';
-
// ----------- Errors -----------
export * from './lib/errors';
-
-// ----------- Utils -----------
-export * from './lib/utils/utils';
-
-// ----------- ABIs -----------
-import * as ABI_ERC20 from './lib/abis/ERC20.json';
-
-export { ABI_ERC20 };
diff --git a/packages/constants/src/lib/abis/ERC20.json b/packages/constants/src/lib/abis/ERC20.json
deleted file mode 100644
index b8347e7d73..0000000000
--- a/packages/constants/src/lib/abis/ERC20.json
+++ /dev/null
@@ -1,224 +0,0 @@
-{
- "abi": [
- {
- "constant": true,
- "inputs": [],
- "name": "name",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_spender",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_from",
- "type": "address"
- },
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "decimals",
- "outputs": [
- {
- "name": "",
- "type": "uint8"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "balance",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "symbol",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- },
- {
- "name": "_spender",
- "type": "address"
- }
- ],
- "name": "allowance",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "payable": true,
- "stateMutability": "payable",
- "type": "fallback"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "owner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "spender",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "value",
- "type": "uint256"
- }
- ],
- "name": "Approval",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "from",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "to",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "value",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- }
- ]
-}
diff --git a/packages/constants/src/lib/constants/constants.spec.ts b/packages/constants/src/lib/constants/constants.spec.ts
index 9f204caeaf..c0ea4154e5 100644
--- a/packages/constants/src/lib/constants/constants.spec.ts
+++ b/packages/constants/src/lib/constants/constants.spec.ts
@@ -1,91 +1,13 @@
-// @ts-nocheck
-import {
- LIT_CHAINS,
- LIT_COSMOS_CHAINS,
- LIT_SVM_CHAINS,
- NETWORK_PUB_KEY,
-} from './constants';
+import { LIT_CHAINS, NETWORK_PUB_KEY } from './constants';
describe('constants', () => {
- const MUST_HAVE_EVM_CHAINS: Array = [
- 'ethereum',
- 'polygon',
- 'fantom',
- 'xdai',
- 'bsc',
- 'arbitrum',
- 'avalanche',
- 'fuji',
- 'harmony',
- 'kovan',
- 'mumbai',
- 'goerli',
- 'ropsten',
- 'rinkeby',
- 'cronos',
- 'optimism',
- 'celo',
- 'aurora',
- 'eluvio',
- 'alfajores',
- 'xdc',
- 'evmos',
- 'evmosTestnet',
- 'bscTestnet',
- 'baseGoerli',
- ];
-
- const MUST_HAVE_SOL_CHAINS = ['solana', 'solanaDevnet', 'solanaTestnet'];
- const MUST_HAVE_COSMOS_CHAINS = [
- 'cosmos',
- 'kyve',
- 'evmosCosmos',
- 'evmosCosmosTestnet',
- ];
-
const networkPubKey =
'9971e835a1fe1a4d78e381eebbe0ddc84fde5119169db816900de796d10187f3c53d65c1202ac083d099a517f34a9b62';
- it(`LIT_CHAINS should have ${MUST_HAVE_EVM_CHAINS.toString()}`, () => {
- let total = 0;
-
- MUST_HAVE_EVM_CHAINS.forEach((chain) => {
- if (Object.keys(LIT_CHAINS).includes(chain)) {
- total++;
- }
- });
-
- expect(total).toEqual(Object.keys(LIT_CHAINS).length);
- });
-
it(`Network public key should be ${networkPubKey}`, () => {
expect(NETWORK_PUB_KEY).toEqual(networkPubKey);
});
- it(`LIT_SVM_CHAINS should have ${MUST_HAVE_SOL_CHAINS}`, () => {
- let total = 0;
-
- MUST_HAVE_SOL_CHAINS.forEach((chain) => {
- if (Object.keys(LIT_SVM_CHAINS).includes(chain)) {
- total++;
- }
- });
-
- expect(total).toEqual(Object.keys(LIT_SVM_CHAINS).length);
- });
-
- it(`LIT_COSMOS_CHAINS should have ${MUST_HAVE_COSMOS_CHAINS}`, () => {
- let total = 0;
-
- MUST_HAVE_COSMOS_CHAINS.forEach((chain) => {
- if (Object.keys(LIT_COSMOS_CHAINS).includes(chain)) {
- total++;
- }
- });
-
- expect(total).toEqual(Object.keys(LIT_COSMOS_CHAINS).length);
- });
-
const ethContract = '0xA54F7579fFb3F98bd8649fF02813F575f9b3d353';
it(`Ethereum contract address should be ${ethContract}`, () => {
diff --git a/packages/constants/src/lib/constants/constants.ts b/packages/constants/src/lib/constants/constants.ts
index b58efeeb53..1935d7d3f9 100644
--- a/packages/constants/src/lib/constants/constants.ts
+++ b/packages/constants/src/lib/constants/constants.ts
@@ -1257,11 +1257,8 @@ export const ALL_LIT_CHAINS = {
* Local storage key constants
*/
export const LOCAL_STORAGE_KEYS = {
- AUTH_COSMOS_SIGNATURE: 'lit-auth-cosmos-signature',
AUTH_SIGNATURE: 'lit-auth-signature',
- AUTH_SOL_SIGNATURE: 'lit-auth-sol-signature',
WEB3_PROVIDER: 'lit-web3-provider',
- KEY_PAIR: 'lit-comms-keypair',
SESSION_KEY: 'lit-session-key',
WALLET_SIGNATURE: 'lit-wallet-sig',
} as const;
@@ -1276,14 +1273,6 @@ export const LIT_NETWORKS: Record = {
[LIT_NETWORK.Custom]: [],
} as const;
-// ========== Either Types ==========
-export const EITHER_TYPE = {
- ERROR: 'ERROR',
- SUCCESS: 'SUCCESS',
-} as const;
-export type EITHER_TYPE_TYPE = ConstantKeys;
-export type EITHER_TYPE_VALUES = ConstantValues;
-
// ========== Supported PKP Auth Method Types ==========
export const AUTH_METHOD_TYPE = {
EthWallet: 1,
diff --git a/packages/constants/src/lib/constants/mappers.ts b/packages/constants/src/lib/constants/mappers.ts
index faca47ae28..76ef68c7d9 100644
--- a/packages/constants/src/lib/constants/mappers.ts
+++ b/packages/constants/src/lib/constants/mappers.ts
@@ -1,4 +1,4 @@
-import { _nagaDev } from '@lit-protocol/contracts';
+import { nagaDev } from '@lit-protocol/contracts';
import {
LIT_NETWORK,
@@ -12,9 +12,9 @@ import {
*/
export const NETWORK_CONTEXT_BY_NETWORK: Record<
LIT_NETWORK_VALUES,
- typeof _nagaDev | undefined
+ typeof nagaDev | undefined
> = {
- [LIT_NETWORK.NagaDev]: _nagaDev,
+ [LIT_NETWORK.NagaDev]: nagaDev,
[LIT_NETWORK.Custom]: undefined,
} as const;
diff --git a/packages/constants/src/lib/environment.ts b/packages/constants/src/lib/environment.ts
new file mode 100644
index 0000000000..086b427f30
--- /dev/null
+++ b/packages/constants/src/lib/environment.ts
@@ -0,0 +1,9 @@
+export class Environment {
+ static get isNode(): boolean {
+ return typeof process?.versions?.node !== 'undefined';
+ }
+
+ static get isBrowser(): boolean {
+ return !Environment.isNode;
+ }
+}
diff --git a/packages/constants/src/lib/errors.ts b/packages/constants/src/lib/errors.ts
index 1373866777..8f97de313b 100644
--- a/packages/constants/src/lib/errors.ts
+++ b/packages/constants/src/lib/errors.ts
@@ -208,6 +208,11 @@ export const LIT_ERROR: Record = {
code: 'network_error',
kind: LIT_ERROR_KIND.Unexpected,
},
+ LIT_NETWORK_ERROR: {
+ name: 'LitNetworkError',
+ code: 'lit_network_error',
+ kind: LIT_ERROR_KIND.Unexpected,
+ },
TRANSACTION_ERROR: {
name: 'TransactionError',
code: 'transaction_error',
@@ -300,6 +305,7 @@ export { MultiError };
export const {
AutomationError,
+ CurveTypeNotFoundError,
InitError,
InvalidAccessControlConditions,
InvalidArgumentException,
@@ -310,6 +316,7 @@ export const {
InvalidParamType,
InvalidSignatureError,
InvalidUnifiedConditionType,
+ LitNetworkError,
LitNodeClientBadConfigError,
LitNodeClientNotReadyError,
LocalStorageItemNotFoundException,
@@ -337,5 +344,4 @@ export const {
WasmInitError,
WrongNetworkException,
WrongParamFormat,
- CurveTypeNotFoundError,
} = errorClasses;
diff --git a/packages/constants/src/lib/interfaces/i-errors.ts b/packages/constants/src/lib/interfaces/i-errors.ts
deleted file mode 100644
index 11ccb44c10..0000000000
--- a/packages/constants/src/lib/interfaces/i-errors.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { EITHER_TYPE } from '../constants/constants';
-import { LitError } from '../errors';
-
-/**
- * A standardized way to return either error or success
- */
-export type IEither = IEitherError | IEitherSuccess;
-
-export interface IEitherError {
- type: typeof EITHER_TYPE.ERROR;
- result: LitError;
-}
-
-export interface IEitherSuccess {
- type: typeof EITHER_TYPE.SUCCESS;
- result: T;
-}
diff --git a/packages/constants/src/lib/utils/utils.spec.ts b/packages/constants/src/lib/utils/utils.spec.ts
deleted file mode 100644
index 166b313f0d..0000000000
--- a/packages/constants/src/lib/utils/utils.spec.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { ELeft, ERight } from './utils';
-import { UnknownError } from '../errors';
-
-describe('error handling utils ELeft/Right works', () => {
- const unknownError = new UnknownError({}, 'ERROR');
- const res = ELeft(unknownError);
- const res2 = ERight('ANSWER');
-
- it('returns result on ELeft()', () => {
- expect(res.result).toBe(unknownError);
- });
-
- it('returns type on ELeft()', () => {
- expect(res.type).toBe('ERROR');
- });
-
- it('returns result on ERight()', () => {
- expect(res2.result).toBe('ANSWER');
- });
-
- it('returns type on ERight()', () => {
- expect(res2.type).toBe('SUCCESS');
- });
-});
diff --git a/packages/constants/src/lib/utils/utils.ts b/packages/constants/src/lib/utils/utils.ts
deleted file mode 100644
index 48f98ab987..0000000000
--- a/packages/constants/src/lib/utils/utils.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { EITHER_TYPE } from '../constants/constants';
-import { LitError } from '../errors';
-import { IEitherSuccess, IEitherError } from '../interfaces/i-errors';
-
-/**
- *
- * This method should be used when there's an expected error
- *
- * @param error is the error encountered
- * @returns { IEither }
- */
-export function ELeft(error: LitError): IEitherError {
- return {
- type: EITHER_TYPE.ERROR,
- result: error,
- };
-}
-
-/**
- *
- * This method should be used when there's an expected success outcome
- *
- * @param result is the successful return value
- * @returns
- */
-export function ERight(result: T): IEitherSuccess {
- return {
- type: EITHER_TYPE.SUCCESS,
- result,
- };
-}
diff --git a/packages/constants/tsconfig.lib.json b/packages/constants/tsconfig.lib.json
index a6b1ef35bc..7bfc80f73e 100644
--- a/packages/constants/tsconfig.lib.json
+++ b/packages/constants/tsconfig.lib.json
@@ -3,8 +3,8 @@
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"declaration": true,
- "types": []
+ "types": ["node"]
},
- "include": ["**/*.ts", "src/lib/utils/uint8arrays.ts"],
+ "include": ["**/*.ts"],
"exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"]
}
diff --git a/packages/contracts-sdk/src/lib/auth-utils.ts b/packages/contracts-sdk/src/lib/auth-utils.ts
index 00893ddd83..5d8efe0a8f 100644
--- a/packages/contracts-sdk/src/lib/auth-utils.ts
+++ b/packages/contracts-sdk/src/lib/auth-utils.ts
@@ -245,7 +245,6 @@ function _parseJWT(jwt: string): StytchToken {
}
const body = Buffer.from(parts[1], 'base64');
const parsedBody: StytchToken = JSON.parse(body.toString('ascii'));
- console.log('JWT body: ', parsedBody);
return parsedBody;
}
diff --git a/packages/contracts-sdk/src/lib/contracts-sdk.ts b/packages/contracts-sdk/src/lib/contracts-sdk.ts
index 5443df28f6..b1f6ab4915 100644
--- a/packages/contracts-sdk/src/lib/contracts-sdk.ts
+++ b/packages/contracts-sdk/src/lib/contracts-sdk.ts
@@ -11,11 +11,13 @@ import { computeAddress } from 'ethers/lib/utils';
import {
AUTH_METHOD_SCOPE_VALUES,
AUTH_METHOD_TYPE_VALUES,
+ Environment,
HTTP,
HTTP_BY_NETWORK,
HTTPS,
InitError,
InvalidArgumentException,
+ LitNetworkError,
LIT_NETWORK,
LIT_NETWORK_VALUES,
METAMASK_CHAIN_INFO_BY_NETWORK,
@@ -23,10 +25,11 @@ import {
ParamsMissingError,
RPC_URL_BY_NETWORK,
TransactionError,
+ UnsupportedMethodError,
WrongNetworkException,
} from '@lit-protocol/constants';
-import { Logger, LogManager } from '@lit-protocol/logger';
-import { derivedAddresses, isBrowser, isNode } from '@lit-protocol/misc';
+import { Logger, getChildLogger } from '@lit-protocol/logger';
+import { getStorageItem, setStorageItem } from '@lit-protocol/misc-browser';
import {
ContractName,
EpochInfo,
@@ -42,6 +45,7 @@ import {
} from '@lit-protocol/types';
import { getAuthIdByAuthMethod, stringToArrayify } from './auth-utils';
+import { derivedAddresses } from './helpers/addresses';
import {
CIDParser,
getBytes32FromMultihash,
@@ -75,6 +79,7 @@ const GAS_LIMIT_ADJUSTMENT = ethers.BigNumber.from(100).add(
// The class has a number of properties that represent the smart contract instances, such as accessControlConditionsContract, litTokenContract, pkpNftContract, etc. These smart contract instances are created by passing the contract address, ABI, and provider to the ethers.Contract constructor.
// The class also has a utils object with helper functions for converting between hexadecimal and decimal representation of numbers, as well as functions for working with multihashes and timestamps.
export class LitContracts {
+ private readonly _logger: Logger;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
provider: ethers.providers.StaticJsonRpcProvider | any;
rpc: string;
@@ -103,8 +108,6 @@ export class LitContracts {
'PriceFeed',
];
- static logger: Logger = LogManager.Instance.get('contract-sdk');
-
// make the constructor args optional
constructor(args?: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -124,6 +127,10 @@ export class LitContracts {
debug?: boolean;
network?: LIT_NETWORKS_KEYS;
}) {
+ this._logger = getChildLogger({
+ module: 'LitContracts',
+ ...(args?.debug ? { level: 'debug' } : {}),
+ });
// this.provider = args?.provider;
this.customContext = args?.customContext;
this.rpc = args?.rpc;
@@ -145,18 +152,6 @@ export class LitContracts {
}
}
- /**
- * Logs a message to the console.
- *
- * @param {any} [args] An optional value to log with the message.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- log = (...args: any[]) => {
- if (this.debug) {
- LitContracts.logger.debug(...args);
- }
- };
-
connect = async () => {
// =======================================
// SETTING UP PROVIDER
@@ -168,9 +163,9 @@ export class LitContracts {
let wallet;
let SETUP_DONE = false;
if (this.provider) {
- this.log('Using provided provider');
- } else if (isBrowser() && !this.signer) {
- this.log("----- We're in the browser! -----");
+ this._logger.info('Using provided provider');
+ } else if (Environment.isBrowser && !this.signer) {
+ this._logger.info("----- We're in the browser! -----");
const web3Provider = window.ethereum;
@@ -219,8 +214,8 @@ export class LitContracts {
// ----------------------------------------------
// (Node) Setting up Provider
// ----------------------------------------------
- else if (isNode()) {
- this.log("----- We're in node! -----");
+ else if (Environment.isNode) {
+ this._logger.info("----- We're in node! -----");
this.provider = new ethers.providers.StaticJsonRpcProvider({
url: this.rpc,
skipFetchSetup: true,
@@ -231,7 +226,7 @@ export class LitContracts {
// CUSTOM PRIVATE KEY
// ======================================
if (this.privateKey) {
- this.log('Using your own private key');
+ this._logger.info('Using your own private key');
this.signer = new ethers.Wallet(this.privateKey, this.provider);
this.provider = this.signer.provider;
SETUP_DONE = true;
@@ -244,61 +239,72 @@ export class LitContracts {
(!this.privateKey && this.randomPrivateKey) ||
this.options?.storeOrUseStorageKey
) {
- this.log('THIS.SIGNER:', this.signer);
+ this._logger.info({ msg: 'THIS.SIGNER', signer: this.signer });
const STORAGE_KEY = 'lit-contracts-sdk-private-key';
- this.log("Let's see if you have a private key in your local storage!");
+ this._logger.info(
+ "Let's see if you have a private key in your local storage!"
+ );
// -- find private key in local storage
let storagePrivateKey;
try {
- storagePrivateKey = localStorage.getItem(STORAGE_KEY);
+ storagePrivateKey = getStorageItem(STORAGE_KEY);
} catch (e) {
// swallow
- // this.log('Not a problem.');
+ // this.#logger.info('Not a problem.');
}
// -- (NOT FOUND) no private key found
if (!storagePrivateKey) {
- this.log('Not a problem, we will generate a random private key');
+ this._logger.info(
+ 'Not a problem, we will generate a random private key'
+ );
storagePrivateKey = ethers.utils.hexlify(ethers.utils.randomBytes(32));
}
// -- (FOUND) private key found
else {
- this.log("Found your private key in local storage. Let's use it!");
+ this._logger.info(
+ "Found your private key in local storage. Let's use it!"
+ );
}
this.signer = new ethers.Wallet(storagePrivateKey, this.provider);
- this.log('- Your private key:', storagePrivateKey);
- this.log('- Your address:', await this.signer.getAddress());
- this.log('- this.signer:', this.signer);
- this.log('- this.provider.getSigner():', this.provider.getSigner());
+ this._logger.info({
+ msg: '- Your address',
+ address: await this.signer.getAddress(),
+ });
+ this._logger.info({ msg: '- this.signer', signer: this.signer });
+ this._logger.info({
+ msg: '- this.provider.getSigner()',
+ signer: this.provider.getSigner(),
+ });
// -- (OPTION) store private key in local storage
if (this.options?.storeOrUseStorageKey) {
- this.log(
+ this._logger.info(
"You've set the option to store your private key in local storage."
);
- localStorage.setItem(STORAGE_KEY, storagePrivateKey);
+ setStorageItem(STORAGE_KEY, storagePrivateKey);
}
} else {
// ----------------------------------------
// Ask Metamask to sign
// ----------------------------------------
- if (isBrowser() && wallet && !SETUP_DONE) {
- // this.log('HERE????');
- this.log('this.signer:', this.signer);
+ if (Environment.isBrowser && wallet && !SETUP_DONE) {
+ // this.#logger.info('HERE????');
+ this._logger.info({ msg: 'this.signer', signer: this.signer });
this.signer = wallet.getSigner();
}
}
if (this.signer !== undefined && this.signer !== null) {
if ('litNodeClient' in this.signer && 'rpcProvider' in this.signer) {
- this.log(`
+ this._logger.info(`
// ***********************************************************************************************
// THIS IS A PKP WALLET, USING IT AS A SIGNER AND ITS RPC PROVIDER AS PROVIDER
// ***********************************************************************************************
@@ -309,13 +315,21 @@ export class LitContracts {
}
}
- this.log('Your Signer:', this.signer);
- this.log('Your Provider:', this.provider?.connection);
+ this._logger.info({ msg: 'Your Signer', signer: this.signer });
+ this._logger.info({
+ msg: 'Your Provider',
+ provider: this.provider?.connection,
+ });
if (!this.provider) {
- this.log('No provider found. Will try to use the one from the signer.');
+ this._logger.info(
+ 'No provider found. Will try to use the one from the signer.'
+ );
this.provider = this.signer.provider;
- this.log('Your Provider(from signer):', this.provider?.connection);
+ this._logger.info({
+ msg: 'Your Provider(from signer)',
+ provider: this.provider?.connection,
+ });
}
this.connected = true;
@@ -807,12 +821,7 @@ export class LitContracts {
HTTP; // Fallback to HTTP
// Construct the URL
- const url = `${protocol}${ip}:${port}`;
-
- // Log the constructed URL for debugging
- LitContracts.logger.debug("Validator's URL:", url);
-
- return url;
+ return `${protocol}${ip}:${port}`;
});
}
@@ -868,11 +877,27 @@ export class LitContracts {
const minNodeCountInt = ethers.BigNumber.from(minNodeCount).toNumber();
if (!minNodeCountInt) {
- throw new Error('❌ Minimum validator count is not set');
+ throw new LitNetworkError(
+ {
+ info: {
+ epochInfo,
+ activeValidators: activeUnkickedValidatorStructs.length,
+ minNodeCount: minNodeCountInt,
+ },
+ },
+ '❌ Minimum validator count is not set'
+ );
}
if (activeUnkickedValidatorStructs.length < minNodeCountInt) {
- throw new Error(
+ throw new LitNetworkError(
+ {
+ info: {
+ epochInfo,
+ activeValidators: activeUnkickedValidatorStructs.length,
+ minNodeCount: minNodeCountInt,
+ },
+ },
`❌ Active validator set does not meet the consensus. Required: ${minNodeCountInt} but got: ${activeUnkickedValidatorStructs.length}`
);
}
@@ -1136,13 +1161,13 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
}
const tokenId = events[0].topics[1];
- this.log('tokenId:', tokenId);
+ this._logger.info({ msg: 'tokenId', tokenId });
let tries = 0;
const maxAttempts = 10;
let publicKey = '';
while (tries < maxAttempts) {
publicKey = await pkpNftContract['getPubkey'](tokenId);
- this.log('pkp pub key: ', publicKey);
+ this._logger.info({ msg: 'pkp pub key', publicKey });
if (publicKey !== '0x') {
break;
}
@@ -1377,7 +1402,6 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
* const CID = require('multiformats/cid')
* const ipfsId = 'QmZKLGf3vgYsboM7WVUS9X56cJSdLzQVacNp841wmEDRkW'
* const bytes32 = getBytes32FromMultihash(ipfsId, CID)
- * console.log(bytes32)
*
* @returns {IPFSHash}
*/
@@ -1451,7 +1475,9 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
tokens.push(token);
} catch (e) {
- this.log(`[getTokensByAddress] Ended search on index: ${i}`);
+ this._logger.info(
+ `[getTokensByAddress] Ended search on index: ${i}`
+ );
break;
}
}
@@ -1512,7 +1538,9 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
tokens.push(token);
} catch (e) {
- this.log(`[getTokensByAddress] Ended search on index: ${i}`);
+ this._logger.info(
+ `[getTokensByAddress] Ended search on index: ${i}`
+ );
break;
}
}
@@ -1599,12 +1627,12 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
}
if (this.isPKP) {
- this.log(
+ this._logger.info(
"This is a PKP wallet, so we'll use the PKP wallet to sign the tx"
);
}
- this.log('...signing and sending tx');
+ this._logger.info('...signing and sending tx');
const sentTx = await this._callWithAdjustedOverrides(
pkpNftContract,
@@ -1613,22 +1641,22 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
{ value: mintCost, ...param }
);
- this.log('sentTx:', sentTx);
+ this._logger.info({ msg: 'sentTx', sentTx });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const res: any = await sentTx.wait();
- this.log('res:', res);
+ this._logger.info({ msg: 'res', res });
const events = 'events' in res ? res.events : res.logs;
const tokenIdFromEvent = events[0].topics[1];
- this.log('tokenIdFromEvent:', tokenIdFromEvent);
+ this._logger.info({ msg: 'tokenIdFromEvent', tokenIdFromEvent });
let tries = 0;
const maxAttempts = 10;
let publicKey = '';
while (tries < maxAttempts) {
publicKey = await pkpNftContract['getPubkey'](tokenIdFromEvent);
- this.log('pkp pub key: ', publicKey);
+ this._logger.info({ msg: 'pkp pub key', publicKey });
if (publicKey !== '0x') {
break;
}
@@ -1638,7 +1666,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
});
}
- this.log('public key from token id', publicKey);
+ this._logger.info({ msg: 'public key from token id', publicKey });
if (publicKey.startsWith('0x')) {
publicKey = publicKey.slice(2);
}
@@ -1686,7 +1714,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
const tokenId = events[1].topics[1];
return { tx, res: txRec, tokenId };
} catch (e: unknown) {
- this.log(`[claimAndMint] error: ${(e as Error).message}`);
+ this._logger.info(`[claimAndMint] error: ${(e as Error).message}`);
throw new TransactionError(
{
info: {
@@ -1791,7 +1819,10 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
);
}
- this.log('[getPermittedAddresses] input:', tokenId);
+ this._logger.info({
+ msg: '[getPermittedAddresses] input',
+ tokenId,
+ });
let addresses: string[] = [];
@@ -1811,7 +1842,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
break;
}
} catch (e: unknown) {
- this.log(
+ this._logger.info(
`[getPermittedAddresses] error:`,
(e as Error).message
);
@@ -1878,10 +1909,10 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
break;
}
} catch (e: unknown) {
- this.log(
- `[getPermittedActions] error:`,
- (e as Error).message
- );
+ this._logger.info({
+ msg: `[getPermittedActions] error:`,
+ message: (e as Error).message,
+ });
tries++;
}
}
@@ -1929,11 +1960,14 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
);
}
- this.log('[isPermittedAction] input:', pkpId);
- this.log('[isPermittedAction] input:', ipfsId);
+ this._logger.info({ msg: '[isPermittedAction] input', pkpId });
+ this._logger.info({ msg: '[isPermittedAction] input', ipfsId });
const ipfsHash = this.utils.getBytesFromMultihash(ipfsId);
- this.log('[isPermittedAction] converted:', ipfsHash);
+ this._logger.info({
+ msg: '[isPermittedAction] converted',
+ ipfsHash,
+ });
const bool = await pkpPermissionsContract['isPermittedAction'](
pkpId,
@@ -1990,21 +2024,36 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
);
}
- this.log('[addPermittedAction] input:', pkpId);
+ this._logger.info({ msg: '[addPermittedAction] input', pkpId });
const pubKey = await pubkeyRouterContract['getPubkey'](pkpId);
- this.log('[addPermittedAction] converted:', pubKey);
+ this._logger.info({
+ msg: '[addPermittedAction] converted',
+ pubKey,
+ });
const pubKeyHash = ethers.utils.keccak256(pubKey);
- this.log('[addPermittedAction] converted:', pubKeyHash);
+ this._logger.info({
+ msg: '[addPermittedAction] converted',
+ pubKeyHash,
+ });
const tokenId = ethers.BigNumber.from(pubKeyHash);
- this.log('[addPermittedAction] converted:', tokenId);
+ this._logger.info({
+ msg: '[addPermittedAction] converted',
+ tokenId,
+ });
- this.log('[addPermittedAction] input:', ipfsId);
+ this._logger.info({
+ msg: '[addPermittedAction] input',
+ ipfsId,
+ });
const ipfsIdBytes = this.utils.getBytesFromMultihash(ipfsId);
- this.log('[addPermittedAction] converted:', ipfsIdBytes);
+ this._logger.info({
+ msg: '[addPermittedAction] converted',
+ ipfsIdBytes,
+ });
const tx = await this._callWithAdjustedOverrides(
pkpPermissionsContract,
@@ -2012,7 +2061,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
[tokenId, ipfsIdBytes, [1]]
);
- this.log('[addPermittedAction] output:', tx);
+ this._logger.info({ msg: '[addPermittedAction] output', tx });
return tx;
},
@@ -2057,10 +2106,14 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
);
}
- this.log('[addPermittedAddress] input:', pkpId);
- this.log('[addPermittedAddress] input:', ownerAddress);
-
- this.log('[addPermittedAddress] input:', pkpId);
+ this._logger.info({
+ msg: '[addPermittedAddress] input',
+ pkpId,
+ });
+ this._logger.info({
+ msg: '[addPermittedAddress] input',
+ ownerAddress,
+ });
const tx = await this._callWithAdjustedOverrides(
pkpPermissionsContract,
@@ -2068,7 +2121,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
[pkpId, ownerAddress, [1]]
);
- this.log('[addPermittedAddress] output:', tx);
+ this._logger.info({ msg: '[addPermittedAddress] output', tx });
return tx;
},
@@ -2112,11 +2165,20 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
);
}
- this.log('[revokePermittedAction] input:', pkpId);
- this.log('[revokePermittedAction] input:', ipfsId);
+ this._logger.info({
+ msg: '[revokePermittedAction] input',
+ pkpId,
+ });
+ this._logger.info({
+ msg: '[revokePermittedAction] input',
+ ipfsId,
+ });
const ipfsHash = this.utils.getBytesFromMultihash(ipfsId);
- this.log('[revokePermittedAction] converted:', ipfsHash);
+ this._logger.info({
+ msg: '[revokePermittedAction] converted',
+ ipfsHash,
+ });
const tx = await this._callWithAdjustedOverrides(
pkpPermissionsContract,
@@ -2124,7 +2186,7 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
[pkpId, ipfsHash]
);
- this.log('[revokePermittedAction] output:', tx);
+ this._logger.info({ msg: '[revokePermittedAction] output', tx });
return tx;
},
@@ -2144,9 +2206,9 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
* @return { Promise }
*/
// getIpfsIds: async (solidityIpfsId: string): Promise => {
- // this.log('[getIpfsIds] input:', solidityIpfsId);
+ // this.#logger.info({ msg: '[getIpfsIds] input', solidityIpfsId });
// const ipfsId = this.utils.getMultihashFromBytes(solidityIpfsId);
- // this.log('[getIpfsIds] output:', ipfsId);
+ // this.#logger.info({ msg: '[getIpfsIds] output', ipfsId });
// return ipfsId;
// },
},
@@ -2230,7 +2292,14 @@ https://developer.litprotocol.com/v3/sdk/wallets/auth-methods/#auth-method-scope
): Promise> {
// Check if the method exists on the contract
if (!(method in contract.functions)) {
- throw new Error(
+ throw new UnsupportedMethodError(
+ {
+ info: {
+ network: this.network,
+ contract,
+ method,
+ },
+ },
`Method ${String(method)} does not exist on the contract`
);
}
diff --git a/packages/misc/src/lib/addresses.spec.ts b/packages/contracts-sdk/src/lib/helpers/addresses.spec.ts
similarity index 100%
rename from packages/misc/src/lib/addresses.spec.ts
rename to packages/contracts-sdk/src/lib/helpers/addresses.spec.ts
diff --git a/packages/misc/src/lib/addresses.ts b/packages/contracts-sdk/src/lib/helpers/addresses.ts
similarity index 76%
rename from packages/misc/src/lib/addresses.ts
rename to packages/contracts-sdk/src/lib/helpers/addresses.ts
index 12b6dea8de..34f778328c 100644
--- a/packages/misc/src/lib/addresses.ts
+++ b/packages/contracts-sdk/src/lib/helpers/addresses.ts
@@ -11,77 +11,11 @@ import {
NoWalletException,
ParamsMissingError,
} from '@lit-protocol/constants';
+import { publicKeyCompress } from '@lit-protocol/crypto';
+import { logger } from '@lit-protocol/logger';
+import { getStorageItem, setStorageItem } from '@lit-protocol/misc-browser';
import { DerivedAddresses } from '@lit-protocol/types';
-/**
- * Converts a public key between compressed and uncompressed formats.
- *
- * @param publicKey - Public key as a Buffer (33 bytes compressed or 65 bytes uncompressed)
- * @param compressed - Boolean flag indicating whether the output should be compressed
- * @returns Converted public key as a Buffer
- */
-export function publicKeyConvert(
- publicKey: Buffer,
- compressed: boolean = true
-): Buffer {
- if (compressed) {
- // Compress the public key (if it's not already compressed)
- if (publicKey.length === 65 && publicKey[0] === 0x04) {
- const x = publicKey.subarray(1, 33);
- const y = publicKey.subarray(33, 65);
- const prefix = y[y.length - 1] % 2 === 0 ? 0x02 : 0x03;
- return Buffer.concat([Buffer.from([prefix]), x]);
- }
- } else {
- // Decompress the public key
- if (
- publicKey.length === 33 &&
- (publicKey[0] === 0x02 || publicKey[0] === 0x03)
- ) {
- const x = publicKey.subarray(1);
- const y = decompressY(publicKey[0], x);
- return Buffer.concat([Buffer.from([0x04]), x, y]);
- }
- }
- // Return the original if no conversion is needed
- return publicKey;
-}
-
-/**
- * Decompresses the y-coordinate of a compressed public key.
- *
- * @param prefix - The first byte of the compressed public key (0x02 or 0x03)
- * @param x - The x-coordinate of the public key
- * @returns The decompressed y-coordinate as a Buffer
- */
-function decompressY(prefix: number, x: Buffer): Buffer {
- const p = BigInt(
- '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
- );
- const a = BigInt('0');
- const b = BigInt('7');
-
- const xBigInt = BigInt('0x' + x.toString('hex'));
- const rhs = (xBigInt ** 3n + a * xBigInt + b) % p;
- const yBigInt = modSqrt(rhs, p);
-
- const isEven = yBigInt % 2n === 0n;
- const y = isEven === (prefix === 0x02) ? yBigInt : p - yBigInt;
-
- return Buffer.from(y.toString(16).padStart(64, '0'), 'hex');
-}
-
-/**
- * Computes the modular square root of a number.
- *
- * @param a - The number to find the square root of
- * @param p - The modulus
- * @returns The square root modulo p
- */
-function modSqrt(a: bigint, p: bigint): bigint {
- return a ** ((p + 1n) / 4n) % p;
-}
-
/**
* Derives a Bitcoin address (P2PKH) from a public key.
*
@@ -133,7 +67,7 @@ function deriveCosmosAddress(
// If the Ethereum public key is uncompressed (130 characters), compress it
if (pubKeyBuffer.length === 65 && pubKeyBuffer[0] === 0x04) {
- pubKeyBuffer = Buffer.from(publicKeyConvert(pubKeyBuffer, true));
+ pubKeyBuffer = Buffer.from(publicKeyCompress(pubKeyBuffer));
}
// Hash the compressed public key with SHA-256
@@ -245,13 +179,17 @@ export const derivedAddresses = async (
const CACHE_KEY = 'lit-cached-pkps';
let cachedPkpJSON;
try {
- const cachedPkp = localStorage.getItem(CACHE_KEY);
+ const cachedPkp = getStorageItem(CACHE_KEY);
if (cachedPkp) {
cachedPkpJSON = JSON.parse(cachedPkp);
publicKey = cachedPkpJSON[pkpTokenId];
}
} catch (e) {
- console.error(e);
+ logger.error({
+ function: 'derivedAddresses',
+ msg: `Could not get ${CACHE_KEY} from storage. Continuing...`,
+ error: e,
+ });
}
if (!publicKey) {
@@ -287,18 +225,19 @@ export const derivedAddresses = async (
if (options.cacheContractCall) {
// trying to store key value pair in local storage
try {
- const cachedPkp = localStorage.getItem(CACHE_KEY);
- if (cachedPkp) {
- const cachedPkpJSON = JSON.parse(cachedPkp);
- cachedPkpJSON[pkpTokenId] = publicKey;
- localStorage.setItem(CACHE_KEY, JSON.stringify(cachedPkpJSON));
- } else {
- const cachedPkpJSON: Record = {};
- cachedPkpJSON[pkpTokenId] = publicKey;
- localStorage.setItem(CACHE_KEY, JSON.stringify(cachedPkpJSON));
- }
+ const cachedPkp = getStorageItem(CACHE_KEY);
+ const cachedPkpJSON: Record = cachedPkp
+ ? JSON.parse(cachedPkp)
+ : {};
+
+ cachedPkpJSON[pkpTokenId] = publicKey;
+ setStorageItem(CACHE_KEY, JSON.stringify(cachedPkpJSON));
} catch (e) {
- console.error(e);
+ logger.error({
+ function: 'derivedAddresses',
+ msg: `Could not get ${CACHE_KEY} from storage. Continuing...`,
+ error: e,
+ });
}
}
}
diff --git a/packages/contracts-sdk/src/lib/helpers/getBytes32FromMultihash.ts b/packages/contracts-sdk/src/lib/helpers/getBytes32FromMultihash.ts
index 40e3ddc199..8ac5d63b56 100644
--- a/packages/contracts-sdk/src/lib/helpers/getBytes32FromMultihash.ts
+++ b/packages/contracts-sdk/src/lib/helpers/getBytes32FromMultihash.ts
@@ -30,9 +30,6 @@ export interface CIDParser {
* const CID = require('multiformats/cid')
* const ipfsId = 'QmZKLGf3vgYsboM7WVUS9X56cJSdLzQVacNp841wmEDRkW'
* const {digest, hashFunction, size} = getBytes32FromMultihash(ipfsId, CID)
- * console.log(digest) // string
- * console.log(hashFunction) // number
- * console.log(size) // number
*
* @returns {IPFSHash}
*/
diff --git a/packages/contracts-sdk/src/lib/price-feed-info-manager.ts b/packages/contracts-sdk/src/lib/price-feed-info-manager.ts
index 9c3bf6c0da..39dd0ef07b 100644
--- a/packages/contracts-sdk/src/lib/price-feed-info-manager.ts
+++ b/packages/contracts-sdk/src/lib/price-feed-info-manager.ts
@@ -77,20 +77,6 @@ async function fetchPriceFeedInfo({
}
});
- // console.log(
- // 'getPriceFeedInfo()',
- // util.inspect(
- // {
- // epochId,
- // minNodeCount,
- // networkPrices: {
- // mapByAddress: networkPriceMap,
- // },
- // },
- // { depth: 4 }
- // )
- // );
-
return {
epochId,
minNodeCount,
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 96715e1682..c6f1566eb9 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -1,2 +1,3 @@
+export * from './lib/helpers/endpoint-version';
+export * from './lib/helpers/most-common-value';
export * from './lib/lit-core';
-export * from './lib/endpoint-version';
diff --git a/packages/core/src/lib/endpoint-version.ts b/packages/core/src/lib/helpers/endpoint-version.ts
similarity index 71%
rename from packages/core/src/lib/endpoint-version.ts
rename to packages/core/src/lib/helpers/endpoint-version.ts
index 543d154eee..b2825bff85 100644
--- a/packages/core/src/lib/endpoint-version.ts
+++ b/packages/core/src/lib/helpers/endpoint-version.ts
@@ -1,3 +1,4 @@
+import { NetworkError } from '@lit-protocol/constants';
import { LitEndpoint } from '@lit-protocol/types';
/**
@@ -17,7 +18,15 @@ export const composeLitUrl = (params: {
try {
new URL(params.url);
} catch (error) {
- throw new Error(`[composeLitUrl] Invalid URL: "${params.url}"`);
+ throw new NetworkError(
+ {
+ info: {
+ url: params.url,
+ endpoint: params.endpoint,
+ },
+ },
+ `[composeLitUrl] Invalid URL: "${params.url}"`
+ );
}
const version = params.endpoint.version;
diff --git a/packages/core/src/lib/helpers/most-common-value.test.ts b/packages/core/src/lib/helpers/most-common-value.test.ts
new file mode 100644
index 0000000000..02df45ecf6
--- /dev/null
+++ b/packages/core/src/lib/helpers/most-common-value.test.ts
@@ -0,0 +1,19 @@
+import { mostCommonValue } from './most-common-value';
+
+describe('mostCommonValue', () => {
+ it('should get the most common string in an array', () => {
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 8];
+
+ const mostOccured = mostCommonValue(arr);
+
+ expect(mostOccured).toBe(8);
+ });
+
+ it('should get the last element of the array if every element only appears once', () => {
+ const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
+
+ const mostOccured = mostCommonValue(arr);
+
+ expect(mostOccured).toBe(0);
+ });
+});
diff --git a/packages/core/src/lib/helpers/most-common-value.ts b/packages/core/src/lib/helpers/most-common-value.ts
new file mode 100644
index 0000000000..060dab6878
--- /dev/null
+++ b/packages/core/src/lib/helpers/most-common-value.ts
@@ -0,0 +1,17 @@
+/**
+ *
+ * Find the element that occurs the most in an array
+ *
+ * @template T
+ * @param { T[] } arr
+ * @returns { T } the element that appeared the most
+ */
+export const mostCommonValue = (arr: T[]): T | undefined => {
+ return arr
+ .sort(
+ (a: T, b: T) =>
+ arr.filter((v: T) => v === a).length -
+ arr.filter((v: T) => v === b).length
+ )
+ .pop();
+};
diff --git a/packages/core/src/lib/lit-core.spec.ts b/packages/core/src/lib/lit-core.spec.ts
index b44c455656..3b1082c16f 100644
--- a/packages/core/src/lib/lit-core.spec.ts
+++ b/packages/core/src/lib/lit-core.spec.ts
@@ -1,12 +1,22 @@
import { InvalidEthBlockhash } from '@lit-protocol/constants';
+const logMock = jest.fn();
+
+jest.mock('pino', () => {
+ return {
+ pino: jest.fn(() => ({
+ info: logMock,
+ error: logMock,
+ })),
+ };
+});
+
import { LitCore } from './lit-core';
describe('LitCore', () => {
let core: LitCore;
describe('getLatestBlockhash', () => {
- let originalFetch: typeof fetch;
let originalDateNow: typeof Date.now;
const mockBlockhashUrl =
'https://block-indexer-url.com/get_most_recent_valid_block';
@@ -16,12 +26,11 @@ describe('LitCore', () => {
litNetwork: 'custom',
});
core['_blockHashUrl'] = mockBlockhashUrl;
- originalFetch = fetch;
originalDateNow = Date.now;
+ Date.now = jest.fn().mockReturnValue(1000000);
});
afterEach(() => {
- global.fetch = originalFetch;
Date.now = originalDateNow;
jest.clearAllMocks();
});
diff --git a/packages/core/src/lib/lit-core.ts b/packages/core/src/lib/lit-core.ts
index 7ee0479e72..ff7e003e3a 100644
--- a/packages/core/src/lib/lit-core.ts
+++ b/packages/core/src/lib/lit-core.ts
@@ -2,6 +2,7 @@ import { ethers } from 'ethers';
import {
CENTRALISATION_BY_NETWORK,
+ Environment,
HTTP,
HTTPS,
InitError,
@@ -16,7 +17,6 @@ import {
LIT_NETWORK,
LIT_NETWORKS,
LitNodeClientNotReadyError,
- LOG_LEVEL,
NetworkError,
NodeError,
RPC_URL_BY_NETWORK,
@@ -27,18 +27,7 @@ import {
} from '@lit-protocol/constants';
import { LitContracts } from '@lit-protocol/contracts-sdk';
import { checkSevSnpAttestation, computeHDPubKey } from '@lit-protocol/crypto';
-import {
- bootstrapLogManager,
- isBrowser,
- isNode,
- log,
- logError,
- logErrorWithRequestId,
- logWithRequestId,
- mostCommonString,
- sendRequest,
- setMiscLitConfig,
-} from '@lit-protocol/misc';
+import { Logger, getChildLogger } from '@lit-protocol/logger';
import {
AuthSig,
BlockHashErrorResponse,
@@ -53,7 +42,8 @@ import {
SuccessNodePromises,
} from '@lit-protocol/types';
-import { composeLitUrl } from './endpoint-version';
+import { composeLitUrl } from './helpers/endpoint-version';
+import { mostCommonValue } from './helpers/most-common-value';
import {
CoreNodeConfig,
EpochCache,
@@ -118,6 +108,7 @@ export type LitNodeClientConfigWithDefaults = Required<
};
export class LitCore {
+ private readonly _coreLogger: Logger;
config: LitNodeClientConfigWithDefaults = {
alertWhenUnauthorized: false,
debug: true,
@@ -178,12 +169,10 @@ export class LitCore {
};
}
- // -- set global variables
- setMiscLitConfig(this.config);
- bootstrapLogManager(
- 'core',
- this.config.debug ? LOG_LEVEL.DEBUG : LOG_LEVEL.OFF
- );
+ this._coreLogger = getChildLogger({
+ module: 'LitCore',
+ ...(this.config.debug ? { level: 'debug' } : {}),
+ });
// -- configure local storage if not present
// LitNodeClientNodejs is a base for LitNodeClient
@@ -191,7 +180,7 @@ export class LitCore {
// If the user sets a new storage provider we respect it over our default storage
// If the user sets a new file path, we respect it over the default path.
if (this.config.storageProvider?.provider) {
- log(
+ this._coreLogger.info(
'localstorage api not found, injecting persistence instance found in config'
);
// using Object defineProperty in order to set a property previously defined as readonly.
@@ -200,25 +189,16 @@ export class LitCore {
value: this.config.storageProvider?.provider,
});
} else if (
- isNode() &&
+ Environment.isNode &&
!globalThis.localStorage &&
!this.config.storageProvider?.provider
) {
- log(
+ this._coreLogger.info(
'Looks like you are running in NodeJS and did not provide a storage provider, your sessions will not be cached'
);
}
}
- // ========== Logger utilities ==========
- getLogsForRequestId = (id: string): string[] => {
- return globalThis.logManager.getLogsForId(id);
- };
-
- getRequestIds = (): Set => {
- return globalThis.logManager.LoggerIds;
- };
-
/**
* Retrieves the validator data including staking contract, epoch, minNodeCount, and bootstrapUrls.
* @returns An object containing the validator data.
@@ -262,10 +242,19 @@ export class LitCore {
);
}
- log('[_getValidatorData] epochInfo: ', epochInfo);
- log('[_getValidatorData] minNodeCount: ', minNodeCount);
- log('[_getValidatorData] Bootstrap urls: ', bootstrapUrls);
- log('[_getValidatorData] stakingContract: ', stakingContract.address);
+ this._coreLogger.info({ msg: '[_getValidatorData] epochInfo', epochInfo });
+ this._coreLogger.info({
+ msg: '[_getValidatorData] minNodeCount',
+ minNodeCount,
+ });
+ this._coreLogger.info({
+ msg: '[_getValidatorData] Bootstrap urls',
+ bootstrapUrls,
+ });
+ this._coreLogger.info({
+ msg: '[_getValidatorData] stakingContract',
+ address: stakingContract.address,
+ });
return {
stakingContract,
@@ -289,7 +278,7 @@ export class LitCore {
private async _handleStakingContractStateChange(
state: STAKING_STATES_VALUES
) {
- log(`New state detected: "${state}"`);
+ this._coreLogger.info(`New state detected: "${state}"`);
const validatorData = await this._getValidatorData();
@@ -303,7 +292,7 @@ export class LitCore {
if (CENTRALISATION_BY_NETWORK[this.config.litNetwork] !== 'centralised') {
// We don't need to handle node urls changing on centralised networks, since their validator sets are static
try {
- log(
+ this._coreLogger.info(
'State found to be new validator set locked, checking validator set'
);
const existingNodeUrls: string[] = [...this.config.bootstrapUrls];
@@ -322,11 +311,10 @@ export class LitCore {
The sdk should be able to understand its current execution environment and wait on an active
network request to the previous epoch's node set before changing over.
*/
- log(
- 'Active validator sets changed, new validators ',
+ this._coreLogger.info({
+ msg: 'Active validator sets changed, new validators. Check delta. Starting node connection',
delta,
- 'starting node connection'
- );
+ });
}
await this.connect();
@@ -335,10 +323,10 @@ export class LitCore {
// But for now, our every-30-second network sync will fix things in at most 30s from now.
// this.ready = false; Should we assume core is invalid if we encountered errors refreshing from an epoch change?
const { message = '' } = err as Error;
- logError(
- 'Error while attempting to reconnect to nodes after epoch transition:',
- message
- );
+ this._coreLogger.error({
+ msg: 'Error while attempting to reconnect to nodes after epoch transition',
+ message,
+ });
}
}
}
@@ -359,10 +347,10 @@ export class LitCore {
}
if (this._stakingContract) {
- log(
- 'listening for state change on staking contract: ',
- this._stakingContract.address
- );
+ this._coreLogger.info({
+ msg: 'listening for state change on staking contract',
+ address: this._stakingContract.address,
+ });
// Stash a function instance, because its identity must be consistent for '.off()' usage to work later
this._stakingContractListener = (state: STAKING_STATES_VALUES) => {
@@ -400,8 +388,6 @@ export class LitCore {
this.ready = false;
this._stopListeningForNewEpoch();
- // this._stopNetworkPolling();
- setMiscLitConfig(undefined);
}
_stopListeningForNewEpoch() {
@@ -490,7 +476,7 @@ export class LitCore {
{}
);
if (this.config.litNetwork === LIT_NETWORK.Custom) {
- log('using custom contracts: ', logAddresses);
+ this._coreLogger.info({ msg: 'using custom contracts', logAddresses });
}
}
@@ -517,8 +503,11 @@ export class LitCore {
this.ready = true;
- log(`🔥 lit is ready. "litNodeClient" variable is ready to use globally.`);
- log('current network config', {
+ this._coreLogger.info(
+ `🔥 lit is ready. "litNodeClient" variable is ready to use globally.`
+ );
+ this._coreLogger.info({
+ msg: 'current network config',
networkPubkey: this.networkPubKey,
networkPubKeySet: this.networkPubKeySet,
hdRootPubkeys: this.hdRootPubkeys,
@@ -527,7 +516,7 @@ export class LitCore {
});
// browser only
- if (isBrowser()) {
+ if (Environment.isBrowser) {
document.dispatchEvent(new Event('lit-ready'));
}
}
@@ -562,25 +551,30 @@ export class LitCore {
// node, even though its keys may be "ERR".
// Should we really track servers with ERR as keys?
if (
- keys.serverPubKey === 'ERR' ||
- keys.subnetPubKey === 'ERR' ||
- keys.networkPubKey === 'ERR' ||
- keys.networkPubKeySet === 'ERR'
+ [
+ keys.serverPubKey,
+ keys.subnetPubKey,
+ keys.networkPubKey,
+ keys.networkPubKeySet,
+ ].includes('ERR')
) {
- logErrorWithRequestId(
+ this._coreLogger.error({
requestId,
- 'Error connecting to node. Detected "ERR" in keys',
+ msg: 'Error connecting to node. Detected "ERR" in keys',
url,
- keys
- );
+ keys,
+ });
}
- log(`Handshake with ${url} returned keys: `, keys);
+ this._coreLogger.info({
+ msg: `Handshake with ${url} returned keys: `,
+ keys,
+ });
if (!keys.latestBlockhash) {
- logErrorWithRequestId(
+ this._coreLogger.error({
requestId,
- `Error getting latest blockhash from the node ${url}.`
- );
+ msg: `Error getting latest blockhash from the node ${url}.`,
+ });
}
// We force SEV checks on some networks even if the caller attempts to construct the client with them disabled
@@ -599,12 +593,12 @@ export class LitCore {
}
// actually verify the attestation by checking the signature against AMD certs
- log('Checking attestation against amd certs...');
+ this._coreLogger.info('Checking attestation against amd certs...');
try {
// ensure we won't try to use a node with an invalid attestation response
await checkSevSnpAttestation(attestation, challenge, url);
- log(`Lit Node Attestation verified for ${url}`);
+ this._coreLogger.info(`Lit Node Attestation verified for ${url}`);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
throw new InvalidNodeAttestation(
@@ -617,7 +611,7 @@ export class LitCore {
);
}
} else if (this.config.litNetwork === LIT_NETWORK.Custom) {
- log(
+ this._coreLogger.info(
`Node attestation SEV verification is disabled. You must explicitly set "checkNodeAttestation" to true when using 'custom' network`
);
}
@@ -654,12 +648,7 @@ export class LitCore {
this.config.bootstrapUrls.length
} nodes. Please check your network connection and try again. Note that you can control this timeout with the connectTimeout config option which takes milliseconds.`;
- try {
- throw new InitError({}, msg);
- } catch (e) {
- logErrorWithRequestId(requestId, e);
- reject(e);
- }
+ reject(new InitError({ info: { requestId } }, msg));
}, this.config.connectTimeout);
}),
Promise.all(
@@ -690,17 +679,17 @@ export class LitCore {
serverKeys: Record;
requestId: string;
}): CoreNodeConfig {
- const latestBlockhash = mostCommonString(
+ const latestBlockhash = mostCommonValue(
Object.values(serverKeys).map(
(keysFromSingleNode) => keysFromSingleNode.latestBlockhash
)
);
if (!latestBlockhash) {
- logErrorWithRequestId(
+ this._coreLogger.error({
requestId,
- 'Error getting latest blockhash from the nodes.'
- );
+ msg: 'Error getting latest blockhash from the nodes.',
+ });
throw new InvalidEthBlockhash(
{
@@ -715,22 +704,22 @@ export class LitCore {
// pick the most common public keys for the subnet and network from the bunch, in case some evil node returned a bad key
return {
- subnetPubKey: mostCommonString(
+ subnetPubKey: mostCommonValue(
Object.values(serverKeys).map(
(keysFromSingleNode) => keysFromSingleNode.subnetPubKey
)
)!,
- networkPubKey: mostCommonString(
+ networkPubKey: mostCommonValue(
Object.values(serverKeys).map(
(keysFromSingleNode) => keysFromSingleNode.networkPubKey
)
)!,
- networkPubKeySet: mostCommonString(
+ networkPubKeySet: mostCommonValue(
Object.values(serverKeys).map(
(keysFromSingleNode) => keysFromSingleNode.networkPubKeySet
)
)!,
- hdRootPubkeys: mostCommonString(
+ hdRootPubkeys: mostCommonValue(
Object.values(serverKeys).map(
(keysFromSingleNode) => keysFromSingleNode.hdRootPubkeys
)
@@ -760,7 +749,7 @@ export class LitCore {
testResult,
};
} catch (error) {
- logError(`RPC URL failed: ${url}`);
+ this._coreLogger.error(`RPC URL failed: ${url}`);
}
}
return null;
@@ -781,15 +770,14 @@ export class LitCore {
this.lastBlockHashRetrieved &&
currentTime - this.lastBlockHashRetrieved < blockHashValidityDuration
) {
- log('Blockhash is still valid. No need to sync.');
+ this._coreLogger.info('Blockhash is still valid. No need to sync.');
return;
}
- log(
- 'Syncing state for new blockhash ',
- 'current blockhash: ',
- this.latestBlockhash
- );
+ this._coreLogger.info({
+ msg: 'Syncing state for new blockhash',
+ currentBlockhash: this.latestBlockhash,
+ });
try {
// This fetches from the lit propagation service so nodes will always have it
@@ -821,18 +809,20 @@ export class LitCore {
this.latestBlockhash = blockHashBody.blockhash;
this.lastBlockHashRetrieved = parseInt(timestamp) * 1000;
- log('Done syncing state new blockhash: ', this.latestBlockhash);
+ this._coreLogger.info({
+ msg: 'Done syncing state new blockhash',
+ latestBlockhash: this.latestBlockhash,
+ });
} catch (error: unknown) {
const err = error as BlockHashErrorResponse | Error;
- logError(
- 'Error while attempting to fetch new latestBlockhash:',
- err instanceof Error ? err.message : err.messages,
- 'Reason: ',
- err instanceof Error ? err : err.reason
- );
+ this._coreLogger.error({
+ msg: 'Error while attempting to fetch new latestBlockhash',
+ errorMessage: err instanceof Error ? err.message : err.messages,
+ reason: err instanceof Error ? err : err.reason,
+ });
- log(
+ this._coreLogger.info(
'Attempting to fetch blockhash manually using ethers with fallback RPC URLs...'
);
const { testResult } =
@@ -842,19 +832,23 @@ export class LitCore {
)) || {};
if (!testResult || !testResult.hash) {
- logError('All fallback RPC URLs failed. Unable to retrieve blockhash.');
+ this._coreLogger.error(
+ 'All fallback RPC URLs failed. Unable to retrieve blockhash.'
+ );
return;
}
try {
this.latestBlockhash = testResult.hash;
this.lastBlockHashRetrieved = testResult.timestamp;
- log(
- 'Successfully retrieved blockhash manually: ',
- this.latestBlockhash
- );
+ this._coreLogger.info({
+ msg: 'Successfully retrieved blockhash manually',
+ latestBlockhash: this.latestBlockhash,
+ });
} catch (ethersError) {
- logError('Failed to manually retrieve blockhash using ethers');
+ this._coreLogger.error(
+ 'Failed to manually retrieve blockhash using ethers'
+ );
}
}
}
@@ -898,7 +892,7 @@ export class LitCore {
endpoint: LIT_ENDPOINT.HANDSHAKE,
});
- log(`handshakeWithNode ${urlWithPath}`);
+ this._coreLogger.info(`handshakeWithNode ${urlWithPath}`);
const data = {
clientPublicKey: 'test',
@@ -923,7 +917,7 @@ export class LitCore {
}
if (!epochInfo) {
- log(
+ this._coreLogger.info(
'epochinfo not found. Not a problem, fetching current epoch state from staking contract'
);
try {
@@ -974,6 +968,41 @@ export class LitCore {
}
// ==================== SENDING COMMAND ====================
+ private async _sendRequest(
+ url: string,
+ req: RequestInit,
+ requestId: string
+ ): Promise {
+ try {
+ const response = await fetch(url, req);
+ const isJson = response.headers
+ .get('content-type')
+ ?.includes('application/json');
+
+ const data = isJson ? await response.json() : null;
+
+ if (!response.ok) {
+ // get error message from body or default to response status
+ const error = data || response.status;
+ return Promise.reject(error);
+ }
+
+ return data;
+ } catch (e) {
+ throw new NetworkError(
+ {
+ info: {
+ url,
+ req,
+ requestId,
+ },
+ cause: e,
+ },
+ `Error sending request to ${url}`
+ );
+ }
+ }
+
/**
*
* Send a command to nodes
@@ -998,11 +1027,11 @@ export class LitCore {
delete data.sessionSigs;
}
- logWithRequestId(
+ this._coreLogger.info({
requestId,
- `sendCommandToNode with url ${url} and data`,
- data
- );
+ msg: `sendCommandToNode with url ${url} and data`,
+ data,
+ });
const req: RequestInit = {
method: 'POST',
@@ -1016,7 +1045,7 @@ export class LitCore {
body: JSON.stringify(data),
};
- return sendRequest(url, req, requestId);
+ return this._sendRequest(url, req, requestId);
};
/**
@@ -1137,9 +1166,6 @@ export class LitCore {
minNodeCount
);
- // console.log(`successes: ${JSON.stringify(successes, null, 2)}`)
- // console.log(`errors: ${JSON.stringify(errors, null, 2)}`)
-
// -- case: success (when success responses are more than minNodeCount)
if (successes.length >= minNodeCount) {
return {
@@ -1168,13 +1194,13 @@ export class LitCore {
// -- case: if we're here, then we did not succeed. time to handle and report errors.
const mostCommonError = JSON.parse(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- mostCommonString(errors.map((r: any) => JSON.stringify(r)))!
+ mostCommonValue(errors.map((r: any) => JSON.stringify(r)))!
);
- logErrorWithRequestId(
- requestId || '',
- `most common error: ${JSON.stringify(mostCommonError)}`
- );
+ this._coreLogger.error({
+ requestId,
+ msg: `most common error: ${JSON.stringify(mostCommonError)}`,
+ });
return {
success: false,
@@ -1202,7 +1228,7 @@ export class LitCore {
res.error.errorCode === 'not_authorized') &&
this.config.alertWhenUnauthorized
) {
- log('You are not authorized to access this content');
+ this._coreLogger.info('You are not authorized to access this content');
}
throw new NodeError(
@@ -1241,7 +1267,9 @@ export class LitCore {
sigType: LIT_CURVE_VALUES = LIT_CURVE.EcdsaCaitSith
): Promise => {
if (!this.hdRootPubkeys) {
- logError('root public keys not found, have you connected to the nodes?');
+ this._coreLogger.error(
+ 'root public keys not found, have you connected to the nodes?'
+ );
throw new LitNodeClientNotReadyError(
{},
'root public keys not found, have you connected to the nodes?'
diff --git a/packages/core/src/lib/types.ts b/packages/core/src/lib/types.ts
index b93544addb..bdd7413182 100644
--- a/packages/core/src/lib/types.ts
+++ b/packages/core/src/lib/types.ts
@@ -1,6 +1,7 @@
-import { NodeAttestation } from '@lit-protocol/types';
import { ethers } from 'ethers';
+import { NodeAttestation } from '@lit-protocol/types';
+
export interface SendNodeCommand {
url: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
diff --git a/packages/crypto/src/lib/crypto.spec.ts b/packages/crypto/src/lib/crypto.spec.ts
index 8dd8980e7a..2898dc7e33 100644
--- a/packages/crypto/src/lib/crypto.spec.ts
+++ b/packages/crypto/src/lib/crypto.spec.ts
@@ -1,9 +1,50 @@
-import * as ethers from 'ethers';
+import { ed25519 } from '@noble/curves/ed25519';
+import { ethers } from 'ethers';
import { joinSignature } from 'ethers/lib/utils';
import { SigShare } from '@lit-protocol/types';
-import { combineEcdsaShares } from './crypto';
+import {
+ combineEcdsaShares,
+ generateSessionKeyPair,
+ publicKeyCompress,
+} from './crypto';
+
+describe('generateSessionKeyPair', () => {
+ it('generates a valid key pair where secretKey contains the publicKey', () => {
+ const sessionKeyPair = generateSessionKeyPair();
+
+ const publicKeyBytes = ethers.utils.arrayify(
+ '0x' + sessionKeyPair.publicKey
+ );
+ const secretKeyBytes = ethers.utils.arrayify(
+ '0x' + sessionKeyPair.secretKey
+ );
+
+ expect(secretKeyBytes.length).toBe(64);
+ expect(publicKeyBytes.length).toBe(32);
+
+ const derivedPublicKeyFromSecret = secretKeyBytes.slice(32);
+ expect(derivedPublicKeyFromSecret).toEqual(publicKeyBytes);
+ });
+
+ it('derives public key from secret key', () => {
+ const sessionKeyPair = generateSessionKeyPair();
+
+ const publicKeyBytes = ethers.utils.arrayify(
+ '0x' + sessionKeyPair.publicKey
+ );
+ const secretKeyBytes = ethers.utils.arrayify(
+ '0x' + sessionKeyPair.secretKey
+ );
+
+ const privateKeySeed = secretKeyBytes.slice(0, 32);
+
+ const derivedPublicKey = ed25519.getPublicKey(privateKeySeed);
+
+ expect(derivedPublicKey).toEqual(publicKeyBytes);
+ });
+});
describe('combine ECDSA Shares', () => {
it('Should recombine ECDSA signature shares', async () => {
@@ -67,3 +108,42 @@ describe('combine ECDSA Shares', () => {
expect(recoveredAddr).toEqual(addr);
});
});
+
+describe('publicKeyCompress', () => {
+ const COMPRESSED_PUBLIC_KEY_HEX =
+ '03bc0a563a9ddaf097ef31c3e936dda312acdbe2504953f0ea4ecb94ee737237df';
+ const COMPRESSED_PUBLIC_KEY = Buffer.from(COMPRESSED_PUBLIC_KEY_HEX, 'hex');
+
+ const UNCOMPRESSED_PUBLIC_KEY_HEX =
+ '04bc0a563a9ddaf097ef31c3e936dda312acdbe2504953f0ea4ecb94ee737237dfa2be4f2e38de7540ae64cf362b897d0f93567adc23ce0abc997c18edd269d73b';
+ const UNCOMPRESSED_PUBLIC_KEY = Buffer.from(
+ UNCOMPRESSED_PUBLIC_KEY_HEX,
+ 'hex'
+ );
+
+ it('should return the same compressed key when already compressed', () => {
+ const result = publicKeyCompress(COMPRESSED_PUBLIC_KEY);
+ expect(result).toEqual(COMPRESSED_PUBLIC_KEY);
+ });
+
+ it('should compress an uncompressed public key correctly', () => {
+ const result = publicKeyCompress(UNCOMPRESSED_PUBLIC_KEY);
+ expect(result).toEqual(COMPRESSED_PUBLIC_KEY);
+ });
+
+ it('should throw an error for invalid key length', () => {
+ const invalidKey = Buffer.from('1234567890abcdef', 'hex'); // 8 bytes only
+ expect(() => publicKeyCompress(invalidKey)).toThrow(
+ 'Invalid public key length. Expected 33 (compressed) or 65 (uncompressed) bytes.'
+ );
+ });
+
+ it('should throw an error if uncompressed key does not start with 0x04', () => {
+ // Create a 65-byte buffer with an invalid prefix (not 0x04)
+ const invalidUncompressed = Buffer.alloc(65, 0);
+ invalidUncompressed[0] = 0x05;
+ expect(() => publicKeyCompress(invalidUncompressed)).toThrow(
+ 'Invalid uncompressed public key format: does not start with 0x04.'
+ );
+ });
+});
diff --git a/packages/crypto/src/lib/crypto.ts b/packages/crypto/src/lib/crypto.ts
index 54c46e5f97..613cfabf4d 100644
--- a/packages/crypto/src/lib/crypto.ts
+++ b/packages/crypto/src/lib/crypto.ts
@@ -1,7 +1,9 @@
+import { ed25519 } from '@noble/curves/ed25519';
import { joinSignature, splitSignature } from 'ethers/lib/utils';
import {
InvalidParamType,
+ InvalidSignatureError,
LIT_CURVE,
LIT_CURVE_VALUES,
NetworkError,
@@ -9,13 +11,9 @@ import {
UnknownError,
UnknownSignatureError,
} from '@lit-protocol/constants';
-import { log } from '@lit-protocol/misc';
-import { nacl } from '@lit-protocol/nacl';
+import { logger } from '@lit-protocol/logger';
+import { getStorageItem, setStorageItem } from '@lit-protocol/misc-browser';
import { NodeAttestation, SessionKeyPair, SigShare } from '@lit-protocol/types';
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
import {
blsCombine,
blsDecrypt,
@@ -144,7 +142,13 @@ export const combineSignatureShares = async (
const signature = await blsCombine(sigShares);
if (signature.length !== 192) {
- throw new Error(
+ throw new InvalidSignatureError(
+ {
+ info: {
+ signature,
+ shares,
+ },
+ },
`Signature length is not 192. Got ${signature.length} instead.`
);
}
@@ -300,16 +304,63 @@ export const computeHDPubKey = async (
* @returns { SessionKeyPair } sessionKeyPair
*/
export const generateSessionKeyPair = (): SessionKeyPair => {
- const keyPair = nacl.sign.keyPair();
+ const privateKey = ed25519.utils.randomPrivateKey();
+ const publicKey = ed25519.getPublicKey(privateKey);
+ const combinedSecretKey = new Uint8Array(
+ privateKey.length + publicKey.length
+ );
+ combinedSecretKey.set(privateKey, 0);
+ combinedSecretKey.set(publicKey, privateKey.length);
const sessionKeyPair: SessionKeyPair = {
- publicKey: uint8arrayToString(keyPair.publicKey, 'base16'),
- secretKey: uint8arrayToString(keyPair.secretKey, 'base16'),
+ publicKey: Buffer.from(publicKey).toString('hex'),
+ secretKey: Buffer.from(combinedSecretKey).toString('hex'), // TODO check if concatenated public key is needed
};
return sessionKeyPair;
};
+/**
+ * Converts a public key between compressed and uncompressed formats.
+ *
+ * @param publicKey - Public key as a Buffer (33 bytes compressed or 65 bytes uncompressed)
+ * @returns Converted public key as a Buffer
+ */
+export function publicKeyCompress(publicKey: Buffer): Buffer {
+ // Validate the public key length is either 33 (compressed) or 65 (uncompressed)
+ if (publicKey.length !== 33 && publicKey.length !== 65) {
+ throw new InvalidSignatureError(
+ {
+ info: {
+ publicKey,
+ },
+ },
+ 'Invalid public key length. Expected 33 (compressed) or 65 (uncompressed) bytes.'
+ );
+ }
+
+ // If the key is already compressed (33 bytes), return it unchanged.
+ if (publicKey.length === 33) {
+ return publicKey;
+ }
+
+ if (publicKey[0] !== 0x04) {
+ throw new InvalidSignatureError(
+ {
+ info: {
+ publicKey,
+ },
+ },
+ 'Invalid uncompressed public key format: does not start with 0x04.'
+ );
+ }
+
+ const x = publicKey.subarray(1, 33);
+ const y = publicKey.subarray(33, 65);
+ const prefix = y[y.length - 1] % 2 === 0 ? 0x02 : 0x03;
+ return Buffer.concat([Buffer.from([prefix]), x]);
+}
+
async function doDecrypt(
ciphertextBase64: string,
shares: BlsSignatureShareJsonString[]
@@ -334,7 +385,7 @@ async function doDecrypt(
async function getAmdCert(url: string): Promise {
const proxyUrl = `${LIT_CORS_PROXY}/${url}`;
- log(
+ logger.info(
`[getAmdCert] Fetching AMD cert using proxy URL ${proxyUrl} to manage CORS restrictions and to avoid being rate limited by AMD.`
);
@@ -356,18 +407,26 @@ async function getAmdCert(url: string): Promise {
try {
return await fetchAsUint8Array(proxyUrl);
- } catch (e) {
- log(`[getAmdCert] Failed to fetch AMD cert from proxy:`, e);
+ } catch (error) {
+ logger.error({
+ function: 'getAmdCert',
+ msg: `Failed to fetch AMD cert from proxy`,
+ error,
+ });
}
// Try direct fetch only if proxy fails
- log('[getAmdCert] Attempting to fetch directly without proxy.');
+ logger.info('Attempting to fetch directly without proxy.');
try {
return await fetchAsUint8Array(url);
- } catch (e) {
- log('[getAmdCert] Direct fetch also failed:', e);
- throw e; // Re-throw to signal that both methods failed
+ } catch (error) {
+ logger.error({
+ function: 'getAmdCert',
+ msg: 'Direct fetch also failed',
+ error,
+ });
+ throw error; // Re-throw to signal that both methods failed
}
}
@@ -468,13 +527,13 @@ export const checkSevSnpAttestation = async (
const vcekUrl = await sevSnpGetVcekUrl(report);
// use local storage if we have one available
if (globalThis.localStorage) {
- log('Using local storage for certificate caching');
- vcekCert = localStorage.getItem(vcekUrl);
+ logger.info('Using local storage for certificate caching');
+ vcekCert = getStorageItem(vcekUrl);
if (vcekCert) {
- vcekCert = uint8arrayFromString(vcekCert, 'base64');
+ vcekCert = Buffer.from(vcekCert, 'base64');
} else {
vcekCert = await getAmdCert(vcekUrl);
- localStorage.setItem(vcekUrl, uint8arrayToString(vcekCert, 'base64'));
+ setStorageItem(vcekUrl, Buffer.from(vcekCert).toString('base64'));
}
} else {
const cache = ((
@@ -500,8 +559,3 @@ export const checkSevSnpAttestation = async (
// pass base64 encoded report to wasm wrapper
return sevSnpVerify(report, data, signatures, challenge, vcekCert);
};
-
-declare global {
- // eslint-disable-next-line no-var, @typescript-eslint/no-explicit-any
- var LitNodeClient: any;
-}
diff --git a/packages/encryption/README.md b/packages/encryption/README.md
deleted file mode 100644
index 82cd8d9b38..0000000000
--- a/packages/encryption/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Quick Start
-
-This submodule provides encryption and decryption of contents (string, file, etc.) respectively using a symmetric key, with the encrypted content returned as a Blob and the symmetric key as a Uint8Array
-
-### node.js / browser
-
-```
-yarn add @lit-protocol/encryption
-```
diff --git a/packages/encryption/jest.config.ts b/packages/encryption/jest.config.ts
deleted file mode 100644
index 1787e58530..0000000000
--- a/packages/encryption/jest.config.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/* eslint-disable */
-export default {
- displayName: 'encryption',
- preset: '../../jest.preset.js',
- globals: {
- 'ts-jest': {
- tsconfig: '/tsconfig.spec.json',
- },
- },
- transform: {
- '^.+\\.[t]s$': 'ts-jest',
- },
- moduleFileExtensions: ['ts', 'js', 'html'],
- coverageDirectory: '../../coverage/packages/encryption',
- setupFilesAfterEnv: ['../../jest.setup.js'],
-};
diff --git a/packages/encryption/project.json b/packages/encryption/project.json
deleted file mode 100644
index cf2972ffee..0000000000
--- a/packages/encryption/project.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "encryption",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "sourceRoot": "packages/encryption/src",
- "projectType": "library",
- "targets": {
- "build": {
- "executor": "@nx/js:tsc",
- "outputs": ["{options.outputPath}"],
- "options": {
- "outputPath": "dist/packages/encryption",
- "main": "packages/encryption/src/index.ts",
- "tsConfig": "packages/encryption/tsconfig.lib.json",
- "assets": ["packages/encryption/*.md"],
- "updateBuildableProjectDepsInPackageJson": true
- }
- },
- "lint": {
- "executor": "@nx/linter:eslint",
- "outputs": ["{options.outputFile}"],
- "options": {
- "lintFilePatterns": ["packages/encryption/**/*.ts"]
- }
- },
- "test": {
- "executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/packages/encryption"],
- "options": {
- "jestConfig": "packages/encryption/jest.config.ts",
- "passWithNoTests": true
- }
- },
- "testWatch": {
- "executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/packages/encryption"],
- "options": {
- "jestConfig": "packages/encryption/jest.config.ts",
- "passWithNoTests": true,
- "watch": true
- }
- }
- },
- "tags": []
-}
diff --git a/packages/encryption/src/index.ts b/packages/encryption/src/index.ts
deleted file mode 100644
index 23436519e2..0000000000
--- a/packages/encryption/src/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './lib/encryption';
diff --git a/packages/encryption/src/lib/encryption.spec.ts b/packages/encryption/src/lib/encryption.spec.ts
deleted file mode 100644
index 978d752295..0000000000
--- a/packages/encryption/src/lib/encryption.spec.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import { isValidBooleanExpression } from '@lit-protocol/misc';
-import { AccsDefaultParams } from '@lit-protocol/types';
-
-const conditionA: AccsDefaultParams = {
- contractAddress: '',
- standardContractType: '',
- chain: 'ethereum',
- method: 'eth_getBalance',
- parameters: [':userAddress', 'latest'],
- returnValueTest: {
- comparator: '>=',
- value: '10000000000000',
- },
-};
-
-const conditionB: AccsDefaultParams = {
- contractAddress: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2',
- standardContractType: 'ERC20',
- chain: 'ethereum',
- method: 'balanceOf',
- parameters: [':userAddress'],
- returnValueTest: {
- comparator: '>',
- value: '0',
- },
-};
-
-const groupValid: any = [conditionA, { operator: 'or' }, conditionB];
-
-const groupInvalid: any = [
- conditionA,
- { operator: 'or' },
- conditionB,
- { operator: 'and' },
-];
-
-describe('encryption', () => {
- it('should pass single access control condition', () => {
- expect(isValidBooleanExpression([conditionA])).toBeTruthy();
- });
- it('should pass boolean access control condition', () => {
- expect(
- isValidBooleanExpression([conditionA, { operator: 'or' }, conditionB])
- ).toBeTruthy();
- });
- it('should fail trailing boolean operator', () => {
- expect(
- isValidBooleanExpression([
- conditionA,
- { operator: 'or' },
- conditionB,
- { operator: 'and' },
- ])
- ).toBeFalsy();
- });
- it('should fail consecutive boolean operators', () => {
- expect(
- isValidBooleanExpression([
- conditionA,
- { operator: 'or' },
- { operator: 'and' },
- conditionB,
- ])
- ).toBeFalsy();
- });
- it('should fail only boolean operator', () => {
- expect(isValidBooleanExpression([{ operator: 'or' }])).toBeFalsy();
- });
- it('should fail consecutive boolean conditions', () => {
- expect(isValidBooleanExpression([conditionA, conditionB])).toBeFalsy();
- });
- it('should pass boolean condition and group', () => {
- expect(
- isValidBooleanExpression([conditionA, { operator: 'or' }, groupValid])
- ).toBeTruthy();
- });
- it('should pass boolean group and condition', () => {
- expect(
- isValidBooleanExpression([groupValid, { operator: 'and' }, conditionA])
- ).toBeTruthy();
- });
- it('should pass boolean group and group', () => {
- expect(
- isValidBooleanExpression([groupValid, { operator: 'and' }, groupValid])
- ).toBeTruthy();
- });
- it('should pass group only', () => {
- expect(isValidBooleanExpression([groupValid])).toBeTruthy();
- });
- it('should fail invalid group only', () => {
- expect(isValidBooleanExpression([groupInvalid])).toBeFalsy();
- });
- it('should fail trailing boolean operator with group', () => {
- expect(
- isValidBooleanExpression([groupValid, { operator: 'and' }])
- ).toBeFalsy();
- });
- it('should fail consecutive boolean operators with group', () => {
- expect(
- isValidBooleanExpression([
- groupValid,
- { operator: 'and' },
- { operator: 'or' },
- groupValid,
- ])
- ).toBeFalsy();
- });
- it('should fail boolean with invalid group', () => {
- expect(
- isValidBooleanExpression([groupValid, { operator: 'and' }, groupInvalid])
- ).toBeFalsy();
- });
- it('should fail boolean with invalid group and valid condition', () => {
- expect(
- isValidBooleanExpression([groupInvalid, { operator: 'or' }, conditionB])
- ).toBeFalsy();
- });
- it('should pass boolean condition after group', () => {
- expect(
- isValidBooleanExpression([
- conditionB,
- { operator: 'or' },
- groupValid,
- { operator: 'and' },
- conditionA,
- ])
- ).toBeTruthy();
- });
-});
diff --git a/packages/encryption/src/lib/encryption.ts b/packages/encryption/src/lib/encryption.ts
deleted file mode 100644
index b7377f24b6..0000000000
--- a/packages/encryption/src/lib/encryption.ts
+++ /dev/null
@@ -1,413 +0,0 @@
-import { EITHER_TYPE, InvalidParamType } from '@lit-protocol/constants';
-import { safeParams } from '@lit-protocol/misc';
-import {
- DecryptRequest,
- EncryptFileRequest,
- EncryptResponse,
- EncryptUint8ArrayRequest,
- EncryptStringRequest,
- ILitNodeClient,
- EncryptToJsonPayload,
- EncryptToJsonProps,
- DecryptFromJsonProps,
-} from '@lit-protocol/types';
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
-
-/**
- * Encrypt a string or file using the LIT network public key and serialise all the metadata required to decrypt
- * i.e. accessControlConditions, evmContractConditions, solRpcConditions, unifiedAccessControlConditions & chain to JSON
- *
- * Useful for encrypting/decrypting data in IPFS or other storage without compressing it in a file.
- *
- * @param params { EncryptToJsonProps } - The params required to encrypt either a file or string and serialise it to JSON
- *
- * @returns { Promise } - JSON serialised string of the encrypted data and associated metadata necessary to decrypt it later
- *
- */
-export const encryptToJson = async (
- params: EncryptToJsonProps
-): Promise => {
- const {
- accessControlConditions,
- evmContractConditions,
- solRpcConditions,
- unifiedAccessControlConditions,
- chain,
- string,
- file,
- litNodeClient,
- } = params;
-
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'encryptToJson',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'encryptToJson',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- if (string !== undefined) {
- const { ciphertext, dataToEncryptHash } = await encryptString(
- {
- ...params,
- dataToEncrypt: string,
- },
- litNodeClient
- );
-
- return JSON.stringify({
- ciphertext,
- dataToEncryptHash,
- accessControlConditions,
- evmContractConditions,
- solRpcConditions,
- unifiedAccessControlConditions,
- chain,
- dataType: 'string',
- } as EncryptToJsonPayload);
- } else if (file) {
- const { ciphertext, dataToEncryptHash } = await encryptFile(
- { ...params, file },
- litNodeClient
- );
-
- return JSON.stringify({
- ciphertext,
- dataToEncryptHash,
- accessControlConditions,
- evmContractConditions,
- solRpcConditions,
- unifiedAccessControlConditions,
- chain,
- dataType: 'file',
- } as EncryptToJsonPayload);
- } else {
- throw new InvalidParamType(
- {
- info: {
- params,
- },
- },
- 'You must provide either "file" or "string"'
- );
- }
-};
-
-/**
- *
- * Decrypt & return a previously encrypted string (as a string) or file (as a Uint8Array) using the metadata included
- * in the parsed JSON data
- *
- * @param params { DecryptFromJsonProps } - The params required to decrypt a parsed JSON blob containing appropriate metadata
- *
- * @returns { Promise } - The decrypted `string` or file (as a `Uint8Array`) depending on `dataType` property in the parsed JSON provided
- *
- */
-export async function decryptFromJson(
- params: DecryptFromJsonProps
-): Promise<
- ReturnType | ReturnType
-> {
- const { authContext, parsedJsonData, litNodeClient } = params;
-
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'decryptFromJson',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'decryptFromJson',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- if (parsedJsonData.dataType === 'string') {
- return decryptToString(
- {
- accessControlConditions: parsedJsonData.accessControlConditions,
- evmContractConditions: parsedJsonData.evmContractConditions,
- solRpcConditions: parsedJsonData.solRpcConditions,
- unifiedAccessControlConditions:
- parsedJsonData.unifiedAccessControlConditions,
- ciphertext: parsedJsonData.ciphertext,
- dataToEncryptHash: parsedJsonData.dataToEncryptHash,
- chain: parsedJsonData.chain,
- authContext,
- },
- litNodeClient
- );
- } else if (parsedJsonData.dataType === 'file') {
- return decryptToFile(
- {
- accessControlConditions: parsedJsonData.accessControlConditions,
- evmContractConditions: parsedJsonData.evmContractConditions,
- solRpcConditions: parsedJsonData.solRpcConditions,
- unifiedAccessControlConditions:
- parsedJsonData.unifiedAccessControlConditions,
- ciphertext: parsedJsonData.ciphertext,
- dataToEncryptHash: parsedJsonData.dataToEncryptHash,
- chain: parsedJsonData.chain,
- authContext,
- },
- litNodeClient
- );
- } else {
- throw new InvalidParamType(
- {
- info: {
- dataType: parsedJsonData.dataType,
- params,
- },
- },
- 'dataType of %s is not valid. Must be "string" or "file".',
- parsedJsonData.dataType
- );
- }
-}
-
-// ---------- Local Helpers ----------
-
-/** Encrypt a uint8array. This is used to encrypt any uint8array that is to be locked via the Lit Protocol.
- * @param { EncryptUint8ArrayRequest } params - The params required to encrypt a uint8array
- * @param params.dataToEncrypt - (optional) The uint8array to encrypt
- * @param params.accessControlConditions - (optional) The access control conditions
- * @param params.evmContractConditions - (optional) The EVM contract conditions
- * @param params.solRpcConditions - (optional) The Solana RPC conditions
- * @param params.unifiedAccessControlConditions - The unified access control conditions
- * @param { ILitNodeClient } litNodeClient - The Lit Node Client
- *
- * @returns { Promise } - The encrypted uint8array and the hash of the data that was encrypted
- */
-export const encryptUint8Array = async (
- params: EncryptUint8ArrayRequest,
- litNodeClient: ILitNodeClient
-): Promise => {
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'encryptUint8Array',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- },
- },
- 'Invalid params'
- );
-
- return litNodeClient.encrypt({
- ...params,
- });
-};
-
-/**
- * Decrypt a cyphertext into a Uint8Array that was encrypted with the encryptUint8Array function.
- *
- * @param { DecryptRequest } params - The params required to decrypt a string
- * @param { ILitNodeClient } litNodeClient - The Lit Node Client
- *
- * @returns { Promise } - The decrypted `Uint8Array`
- */
-export const decryptToUint8Array = async (
- params: DecryptRequest,
- litNodeClient: ILitNodeClient
-): Promise => {
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'decrypt',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'decryptToUint8Array',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- const { decryptedData } = await litNodeClient.decrypt(params);
-
- return decryptedData;
-};
-
-/**
- *
- * Encrypt a string. This is used to encrypt any string that is to be locked via the Lit Protocol.
- *
- * @param { EncryptStringRequest } params - The params required to encrypt a string
- * @param params.dataToEncrypt - (optional) The string to encrypt
- * @param params.accessControlConditions - (optional) The access control conditions
- * @param params.evmContractConditions - (optional) The EVM contract conditions
- * @param params.solRpcConditions - (optional) The Solana RPC conditions
- * @param params.unifiedAccessControlConditions - The unified access control conditions
- * @param { ILitNodeClient } litNodeClient - The Lit Node Client
- *
- * @returns { Promise } - The encrypted string and the hash of the string
- */
-export const encryptString = async (
- params: EncryptStringRequest,
- litNodeClient: ILitNodeClient
-): Promise => {
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'encryptString',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'encryptString',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- return litNodeClient.encrypt({
- ...params,
- dataToEncrypt: uint8arrayFromString(params.dataToEncrypt, 'utf8'),
- });
-};
-
-/**
- *
- * Decrypt ciphertext into a string that was encrypted with the encryptString function.
- *
- * @param { DecryptRequest } params - The params required to decrypt a string
- * @param { ILitNodeClient } litNodeClient - The Lit Node Client
-
- * @returns { Promise } - The decrypted string
- */
-export const decryptToString = async (
- params: DecryptRequest,
- litNodeClient: ILitNodeClient
-): Promise => {
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'decrypt',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'decryptToString',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- const { decryptedData } = await litNodeClient.decrypt(params);
-
- return uint8arrayToString(decryptedData, 'utf8');
-};
-
-/**
- *
- * Encrypt a file without doing any compression or packing. This is useful for large files. A 1gb file can be encrypted in only 2 seconds, for example.
- *
- * @param { EncryptFileRequest } params - The params required to encrypt a file
- * @param { ILitNodeClient } litNodeClient - The lit node client to use to encrypt the file
- *
- * @returns { Promise } - The encrypted file and the hash of the file
- */
-export const encryptFile = async (
- params: EncryptFileRequest,
- litNodeClient: ILitNodeClient
-): Promise => {
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'encryptFile',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'encryptFile',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- // encrypt the file
- const fileAsArrayBuffer = await params.file.arrayBuffer();
-
- return litNodeClient.encrypt({
- ...params,
- dataToEncrypt: new Uint8Array(fileAsArrayBuffer),
- });
-};
-
-/**
- *
- * Decrypt a file that was encrypted with the encryptFile function, without doing any uncompressing or unpacking. This is useful for large files. A 1gb file can be decrypted in only 1 second, for example.
- *
- * @param { DecryptRequest } params - The params required to decrypt a file
- * @param { ILitNodeClient } litNodeClient - The lit node client to use to decrypt the file
- *
- * @returns { Promise } - The decrypted file
- */
-export const decryptToFile = async (
- params: DecryptRequest,
- litNodeClient: ILitNodeClient
-): Promise => {
- // -- validate
- const paramsIsSafe = safeParams({
- functionName: 'decrypt',
- params,
- });
-
- if (paramsIsSafe.type === EITHER_TYPE.ERROR)
- throw new InvalidParamType(
- {
- info: {
- params,
- function: 'decryptToFile',
- },
- cause: paramsIsSafe.result,
- },
- 'Invalid params'
- );
-
- const { decryptedData } = await litNodeClient.decrypt(params);
-
- return decryptedData;
-};
diff --git a/packages/event-listener/README.md b/packages/event-listener/README.md
index a6a4ab0d2a..7bbb29e992 100644
--- a/packages/event-listener/README.md
+++ b/packages/event-listener/README.md
@@ -254,6 +254,27 @@ async function bridgeBaseSepoliaUSDCToEthereumSepolia() {
const ethPrivateKey = '0xTHE_PKP_AUTHORIZED_SIGNER_PRIVATE_KEY';
const stateMachine = StateMachine.fromDefinition({
+ // Extend the action respository with a custom action we will define later. For example to send notification to the machine owner on transactions
+ actionRepository: {
+ notify: class NotificationAction extends Action {
+ constructor({
+ stateMachine,
+ customParam,
+ }: {
+ stateMachine: StateMachine;
+ customParam: string;
+ }) {
+ super({
+ debug,
+ function: async () => {
+ const transferData = stateMachine.getFromContext('transfer');
+ console.log('customParam', customParam);
+ console.log('transferData', transferData);
+ },
+ });
+ }
+ },
+ },
privateKey: ethPrivateKey, // Used only for authorization here, minting was done previously
context: {
// We can prepopulate the context, for example setting the pkp here instead of using state.usePkp later
@@ -371,6 +392,11 @@ async function bridgeBaseSepoliaUSDCToEthereumSepolia() {
},
],
},
+ {
+ // Our custom action to notify about the just executed transfer transaction
+ key: 'notify',
+ customParam: 'OUR_CUSTOM_PARAM',
+ },
],
// Going back to waitForFunds to suspend machine if we need more sepolia eth or sepolia USDC
transitions: [{ toState: 'waitForFunds' }],
diff --git a/packages/event-listener/src/index.ts b/packages/event-listener/src/index.ts
index 12fc9ac474..a4dbd4f99e 100644
--- a/packages/event-listener/src/index.ts
+++ b/packages/event-listener/src/index.ts
@@ -1,3 +1,4 @@
+export * from './lib/actions';
export * from './lib/listeners';
export * from './lib/states';
export * from './lib/state-machine';
diff --git a/packages/event-listener/src/lib/actions/index.ts b/packages/event-listener/src/lib/actions/index.ts
index 9291631380..bbe79ead1b 100644
--- a/packages/event-listener/src/lib/actions/index.ts
+++ b/packages/event-listener/src/lib/actions/index.ts
@@ -1,5 +1,18 @@
+import { LitActionAction } from './lit-action';
+import { LogContextAction } from './log-context';
+import { MintPkpAction } from './mint-pkp';
+import { TransactionAction } from './transaction';
+import { ActionConstructor } from '../types';
+
export * from './action';
export * from './lit-action';
export * from './log-context';
export * from './mint-pkp';
export * from './transaction';
+
+export const ACTION_REPOSITORY: Record = {
+ context: LogContextAction,
+ litAction: LitActionAction,
+ transaction: TransactionAction,
+ usePkp: MintPkpAction,
+};
diff --git a/packages/event-listener/src/lib/actions/log-context.ts b/packages/event-listener/src/lib/actions/log-context.ts
index 4196d3e74c..3f383bfd17 100644
--- a/packages/event-listener/src/lib/actions/log-context.ts
+++ b/packages/event-listener/src/lib/actions/log-context.ts
@@ -1,3 +1,5 @@
+import { logger } from '@lit-protocol/logger';
+
import { Action } from './action';
import { StateMachine } from '../state-machine';
@@ -10,10 +12,10 @@ interface LogContextActionParams {
export class LogContextAction extends Action {
constructor(params: LogContextActionParams) {
const logContextFunction = async () => {
- console.log(
- `State Machine context: `,
- params.stateMachine.getFromContext(params.path)
- );
+ logger.info({
+ msg: `State Machine context`,
+ context: params.stateMachine.getFromContext(params.path),
+ });
};
super({
diff --git a/packages/event-listener/src/lib/actions/mint-pkp.ts b/packages/event-listener/src/lib/actions/mint-pkp.ts
index 353b6f79c7..5085a5169d 100644
--- a/packages/event-listener/src/lib/actions/mint-pkp.ts
+++ b/packages/event-listener/src/lib/actions/mint-pkp.ts
@@ -1,3 +1,5 @@
+import { logger } from '@lit-protocol/logger';
+
import { Action } from './action';
import { StateMachine } from '../state-machine';
@@ -12,7 +14,7 @@ export class MintPkpAction extends Action {
const mintingReceipt =
await params.stateMachine.litContracts.pkpNftContractUtils.write.mint();
const pkp = mintingReceipt.pkp;
- params.debug && console.log(`Minted PKP: ${pkp}`);
+ params.debug && logger.info(`Minted PKP: ${pkp}`);
params.stateMachine.setToContext('activePkp', pkp);
};
diff --git a/packages/event-listener/src/lib/listeners/fetch.ts b/packages/event-listener/src/lib/listeners/fetch.ts
index 681cd94bba..74e1c1d06d 100644
--- a/packages/event-listener/src/lib/listeners/fetch.ts
+++ b/packages/event-listener/src/lib/listeners/fetch.ts
@@ -1,3 +1,5 @@
+import { logger } from '@lit-protocol/logger';
+
import { Listener } from './listener';
interface FetchListenerConfig {
@@ -32,7 +34,7 @@ export class FetchListener extends Listener {
this.emit(value);
}
} catch (error) {
- console.error('FetchListener error:', error);
+ logger.error({ msg: 'FetchListener error:', error });
}
}, pollInterval);
},
diff --git a/packages/event-listener/src/lib/litActions.ts b/packages/event-listener/src/lib/litActions.ts
index 1f4d792b7b..805ddf7f7c 100644
--- a/packages/event-listener/src/lib/litActions.ts
+++ b/packages/event-listener/src/lib/litActions.ts
@@ -1,10 +1,12 @@
import { ethers } from 'ethers';
+import { authenticators } from '@lit-protocol/auth';
import { LitActionResource } from '@lit-protocol/auth-helpers';
-import { LIT_ABILITY, LIT_NETWORK } from '@lit-protocol/constants';
-import { EthWalletProvider } from '@lit-protocol/lit-auth-client';
+import { LIT_ABILITY } from '@lit-protocol/constants';
import { LitNodeClient } from '@lit-protocol/lit-node-client';
+const { MetamaskAuthenticator } = authenticators;
+
export const signWithLitActionCode = `(async () => {
const signature = await Lit.Actions.signAndCombineEcdsa({
toSign,
@@ -48,7 +50,7 @@ export async function executeLitAction({
pkpPublicKey,
capabilityAuthSigs: [],
authMethods: [
- await EthWalletProvider.authenticate({
+ await MetamaskAuthenticator.authenticate({
signer: authSigner,
litNodeClient: litNodeClient,
expiration,
diff --git a/packages/event-listener/src/lib/state-machine.ts b/packages/event-listener/src/lib/state-machine.ts
index 049f75f19e..e91571ce7f 100644
--- a/packages/event-listener/src/lib/state-machine.ts
+++ b/packages/event-listener/src/lib/state-machine.ts
@@ -7,14 +7,9 @@ import {
} from '@lit-protocol/constants';
import { LitContracts } from '@lit-protocol/contracts-sdk';
import { LitNodeClient } from '@lit-protocol/lit-node-client';
+import { logger } from '@lit-protocol/logger';
-import {
- Action,
- LitActionAction,
- LogContextAction,
- MintPkpAction,
- TransactionAction,
-} from './actions';
+import { Action, ACTION_REPOSITORY } from './actions';
import { MachineContext } from './context/machine-context';
import {
ContractEventData,
@@ -26,6 +21,7 @@ import {
import { State, StateParams } from './states';
import { CheckFn, Transition } from './transitions';
import {
+ ActionConstructor,
ActionDefinition,
BaseStateMachineParams,
ContextOrLiteral,
@@ -59,6 +55,7 @@ export class StateMachine {
public id: string;
public status: MachineStatus = 'stopped';
+ private readonly actionsRepository: Record;
private states = new Map();
private transitions = new Map>();
private currentState?: State;
@@ -73,6 +70,10 @@ export class StateMachine {
...params.context,
});
+ this.actionsRepository = {
+ ...ACTION_REPOSITORY,
+ ...params.actionRepository,
+ };
this.litNodeClient = params.litNodeClient;
this.litContracts = params.litContracts;
this.privateKey = params.privateKey;
@@ -124,6 +125,10 @@ export class StateMachine {
litContracts: litContractsInstance,
privateKey,
onError,
+ actionRepository: {
+ ...ACTION_REPOSITORY,
+ ...machineConfig.actionRepository,
+ },
});
const stateTransitions = [] as TransitionDefinition[];
@@ -382,17 +387,17 @@ export class StateMachine {
// Aggregate (AND) all listener checks to a single function result
transitionConfig.check = async (values) => {
this.debug &&
- console.log(
- `${transitionDefinition.fromState} -> ${transitionDefinition.toState} values`,
- values
- );
+ logger.info({
+ msg: `${transitionDefinition.fromState} -> ${transitionDefinition.toState} values`,
+ values,
+ });
return Promise.all(checks.map((check) => check(values))).then(
(results) => {
this.debug &&
- console.log(
- `${transitionDefinition.fromState} -> ${transitionDefinition.toState} results`,
- results
- );
+ logger.info({
+ msg: `${transitionDefinition.fromState} -> ${transitionDefinition.toState} results`,
+ results,
+ });
return results.every((result) => result);
}
);
@@ -410,7 +415,7 @@ export class StateMachine {
initialState: string,
onStop?: voidAsyncFunction
): Promise {
- this.debug && console.log('Starting state machine...');
+ this.debug && logger.info('Starting state machine...');
await Promise.all([
this.litContracts.connect(),
@@ -421,7 +426,7 @@ export class StateMachine {
await this.enterState(initialState);
this.status = 'running';
- this.debug && console.log('State machine started');
+ this.debug && logger.info('State machine started');
}
/**
@@ -470,20 +475,21 @@ export class StateMachine {
* Stops the state machine by exiting the current state and not moving to another one.
*/
public async stopMachine(): Promise {
- this.debug && console.log('Stopping state machine...');
+ this.debug && logger.info('Stopping state machine...');
this.status = 'stopped';
await this.exitCurrentState();
await this.onStopCallback?.();
- this.debug && console.log('State machine stopped');
+ this.debug && logger.info('State machine stopped');
}
/**
* Stops listening on the current state's transitions and exits the current state.
*/
private async exitCurrentState(): Promise {
- this.debug && console.log('exitCurrentState', this.currentState?.key);
+ this.debug &&
+ logger.info({ msg: 'exitCurrentState', state: this.currentState?.key });
const currentTransitions =
this.transitions.get(this.currentState?.key ?? '') ??
@@ -514,7 +520,7 @@ export class StateMachine {
`State ${stateKey} not found`
);
}
- this.debug && console.log('enterState', state.key);
+ this.debug && logger.info({ msg: 'enterState', state: state.key });
await state.enter();
const nextTransitions =
this.transitions.get(state.key) ?? new Map();
@@ -542,7 +548,7 @@ export class StateMachine {
);
}
if (this.currentState === nextState) {
- console.warn(
+ logger.warn(
`State ${stateKey} is already active. Skipping state change.`
);
return;
@@ -569,66 +575,18 @@ export class StateMachine {
): voidAsyncFunction {
const actions = [] as Action[];
- actionDefinitions.forEach((action) => {
- switch (action.key) {
- case 'context':
- if (typeof action.log?.path === 'string') {
- actions.push(
- new LogContextAction({
- debug: this.debug,
- stateMachine: this,
- path: action.log.path,
- })
- );
- }
- break;
- case 'litAction':
- actions.push(
- new LitActionAction({
- debug: this.debug,
- stateMachine: this,
- ...action,
- })
- );
- break;
- case 'transaction':
- actions.push(
- new TransactionAction({
- debug: this.debug,
- stateMachine: this,
- ...action,
- })
- );
- break;
- case 'usePkp':
- if ('pkp' in action) {
- this.context.set(
- 'activePkp',
- this.resolveContextPathOrLiteral(action.pkp)
- );
- } else if ('mint' in action) {
- const mintPkpAction = new MintPkpAction({
- debug: this.debug,
- stateMachine: this,
- });
- actions.push(mintPkpAction);
- }
- if (this.debug) {
- const activePkp = this.context.get('activePkp');
- console.log(`Machine configured to use pkp ${activePkp}`);
- }
- break;
- default:
- throw new AutomationError(
- {
- info: {
- action,
- },
- },
- `Unknown action. Check error info.`
- );
+ for (const action of actionDefinitions) {
+ const ActionCtor = this.actionsRepository[action.key];
+ if (!ActionCtor) {
+ throw new AutomationError(
+ { info: { action } },
+ `Action key "${action.key}" not found in action repository`
+ );
}
- });
+ actions.push(
+ new ActionCtor({ debug: this.debug, stateMachine: this, ...action })
+ );
+ }
return async () => {
await Promise.all(actions.map((action) => action.run())).catch((err) => {
@@ -665,7 +623,7 @@ export class StateMachine {
}
// Throwing when stopping could hide above error
- this.stopMachine().catch(console.error);
+ this.stopMachine().catch((error) => logger.error({ error }));
}
}
diff --git a/packages/event-listener/src/lib/states/state.ts b/packages/event-listener/src/lib/states/state.ts
index b9501c62ba..7b712d261b 100644
--- a/packages/event-listener/src/lib/states/state.ts
+++ b/packages/event-listener/src/lib/states/state.ts
@@ -1,3 +1,5 @@
+import { logger } from '@lit-protocol/logger';
+
import { voidAsyncFunction } from '../types';
export interface BaseStateParams {
@@ -29,7 +31,7 @@ export class State {
* Executes the onEnter action for the state.
*/
async enter() {
- this.debug && console.log(`enter ${this.key}`);
+ this.debug && logger.info(`enter ${this.key}`);
await this.onEnter?.();
}
@@ -37,7 +39,7 @@ export class State {
* Executes the onExit action for the state.
*/
async exit() {
- this.debug && console.log(`exit ${this.key}`);
+ this.debug && logger.info(`exit ${this.key}`);
await this.onExit?.();
}
}
diff --git a/packages/event-listener/src/lib/transitions/transition.ts b/packages/event-listener/src/lib/transitions/transition.ts
index 8b7ed60b1c..0306f5db67 100644
--- a/packages/event-listener/src/lib/transitions/transition.ts
+++ b/packages/event-listener/src/lib/transitions/transition.ts
@@ -1,3 +1,5 @@
+import { logger } from '@lit-protocol/logger';
+
import { Listener } from '../listeners';
import { onError } from '../types';
@@ -75,13 +77,13 @@ export class Transition {
*/
async startListening() {
try {
- this.debug && console.log('startListening');
+ this.debug && logger.info('startListening');
await Promise.all(this.listeners.map((listener) => listener.start()));
if (!this.listeners.length) {
// If the transition does not have any listeners it will never emit. Therefore, we "match" automatically on next event loop
setTimeout(() => {
- this.debug && console.log('Transition without listeners: auto match');
+ this.debug && logger.info('Transition without listeners: auto match');
this.onMatch([]);
}, 0);
}
@@ -99,7 +101,7 @@ export class Transition {
*/
async stopListening() {
try {
- this.debug && console.log('stopListening');
+ this.debug && logger.info('stopListening');
this.queue.length = 0; // Flush the queue as there might be more value arrays to check
await Promise.all(this.listeners.map((listener) => listener.stop()));
} catch (e) {
@@ -129,10 +131,10 @@ export class Transition {
const isMatch = this.check ? await this.check(currentValues) : true;
if (isMatch) {
- this.debug && console.log('match', currentValues);
+ this.debug && logger.info({ msg: 'match', values: currentValues });
await this.onMatch?.(currentValues);
} else {
- this.debug && console.log('mismatch', currentValues);
+ this.debug && logger.info({ msg: 'mismatch', values: currentValues });
await this.onMismatch?.(currentValues);
}
}
diff --git a/packages/event-listener/src/lib/types.ts b/packages/event-listener/src/lib/types.ts
index 1ec982857c..cf19f2d8d0 100644
--- a/packages/event-listener/src/lib/types.ts
+++ b/packages/event-listener/src/lib/types.ts
@@ -3,6 +3,7 @@ import { ethers } from 'ethers';
import { LitContracts } from '@lit-protocol/contracts-sdk';
import { LitNodeClient } from '@lit-protocol/lit-node-client';
+import { Action, ActionParams } from './actions/action';
import { BaseTransitionParams } from './transitions';
export type Address = `0x${string}`;
@@ -35,6 +36,13 @@ export interface UpdatesContext {
}
// Action Types
+export type ActionConstructor = new (params: any) => Action;
+
+export interface RawActionDefinition {
+ key: string;
+ [actionProperty: string]: unknown;
+}
+
export interface LitActionActionDefinition {
key: 'litAction';
code?: ContextOrLiteral;
@@ -96,6 +104,7 @@ export interface UseCapacityNFTActionDefinition {
}
export type ActionDefinition =
+ | RawActionDefinition
| ContextActionDefinition
| LitActionActionDefinition
| MintCapacityNFTActionDefinition
@@ -176,6 +185,7 @@ export interface TransitionParams
// Machine Types
export interface BaseStateMachineParams {
+ actionRepository?: Record;
context?: Record;
debug?: boolean;
litContracts: LitContracts;
diff --git a/packages/event-listener/src/lib/utils/chain.ts b/packages/event-listener/src/lib/utils/chain.ts
index 91025ee327..dc94bd4a6c 100644
--- a/packages/event-listener/src/lib/utils/chain.ts
+++ b/packages/event-listener/src/lib/utils/chain.ts
@@ -1,18 +1,36 @@
import { ethers } from 'ethers';
-import { LIT_EVM_CHAINS } from '@lit-protocol/constants';
+import {
+ LIT_EVM_CHAINS,
+ InvalidArgumentException,
+ UnsupportedChainException,
+} from '@lit-protocol/constants';
export function getEvmChain(evmChainId: ethers.BigNumberish) {
const evmChainIdNumber = ethers.BigNumber.from(evmChainId).toNumber();
if (evmChainIdNumber === 0) {
- throw new Error('EVM chainId cannot be 0');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ evmChainId: evmChainIdNumber,
+ },
+ },
+ 'EVM chainId cannot be 0'
+ );
}
const chain = Object.values(LIT_EVM_CHAINS).find(
(chain) => chain.chainId === evmChainIdNumber
);
if (!chain) {
- throw new Error(`EVM chain with chainId ${evmChainId} not found`);
+ throw new UnsupportedChainException(
+ {
+ info: {
+ evmChainId: evmChainIdNumber,
+ },
+ },
+ `EVM chain with chainId ${evmChainId} not found`
+ );
}
return chain;
diff --git a/packages/event-listener/src/lib/utils/erc20.ts b/packages/event-listener/src/lib/utils/erc20.ts
index b1e04abd37..61bc76ab05 100644
--- a/packages/event-listener/src/lib/utils/erc20.ts
+++ b/packages/event-listener/src/lib/utils/erc20.ts
@@ -1,5 +1,7 @@
import { ethers } from 'ethers';
+import { InvalidArgumentException } from '@lit-protocol/constants';
+
import { Address, BalanceTransitionDefinition } from '../types';
export const ERC20ABI = [
@@ -69,7 +71,15 @@ export function getBalanceTransitionCheck(
case '>':
return addressBalance.gt(targetAmount);
default:
- throw new Error(`Unrecognized comparator ${comparator}`);
+ throw new InvalidArgumentException(
+ {
+ info: {
+ comparator,
+ balance,
+ },
+ },
+ `Unrecognized comparator ${comparator}`
+ );
}
};
diff --git a/packages/lit-auth-client/README.md b/packages/lit-auth-client/README.md
deleted file mode 100644
index 989eb9c448..0000000000
--- a/packages/lit-auth-client/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# lit-auth-client
-
-`lit-auth-client` makes it easy to manage PKP authentication with Lit Protocol. This library offers convenient classes for social logins, Ethereum wallet sign-ins, and minting and fetching of PKPs linked to auth methods.
-
-## 📜 API Reference
-
-Check out the [API reference](https://docs.lit-js-sdk-v2.litprotocol.com/modules/lit_auth_client_src.html).
-
-## 📦 Installation
-
-Get started by installing the package:
-
-```bash
-yarn add @lit-protocol/lit-auth-client
-```
-
-## 🙌 Contributing
-
-This library was generated with [Nx](https://nx.dev).
-
-### Building
-
-Run `nx build lit-auth-client` to build the library.
-
-### Running unit tests
-
-Run `nx test lit-auth-client` to execute the unit tests via [Jest](https://jestjs.io).
diff --git a/packages/lit-auth-client/jest.config.ts b/packages/lit-auth-client/jest.config.ts
deleted file mode 100644
index 61d4b7df55..0000000000
--- a/packages/lit-auth-client/jest.config.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable */
-export default {
- displayName: 'lit-auth-client',
- preset: '../../jest.preset.js',
- globals: {
- 'ts-jest': {
- tsconfig: '/tsconfig.spec.json',
- },
- },
- transform: {
- '^.+\\.[tj]s$': 'ts-jest',
- },
- moduleFileExtensions: ['ts', 'js', 'html'],
- coverageDirectory: '../../coverage/packages/lit-auth-client',
- transformIgnorePatterns: ['/node_modules/(?!(@simplewebauthn)/)'],
- setupFilesAfterEnv: ['../../jest.setup.js'],
-};
diff --git a/packages/lit-auth-client/package.json b/packages/lit-auth-client/package.json
deleted file mode 100644
index 2bb9bca246..0000000000
--- a/packages/lit-auth-client/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "name": "@lit-protocol/lit-auth-client",
- "version": "8.0.0-alpha.0",
- "type": "commonjs",
- "license": "MIT",
- "homepage": "https://github.com/Lit-Protocol/js-sdk",
- "repository": {
- "type": "git",
- "url": "https://github.com/LIT-Protocol/js-sdk"
- },
- "keywords": [
- "library"
- ],
- "bugs": {
- "url": "https://github.com/LIT-Protocol/js-sdk/issues"
- },
- "publishConfig": {
- "access": "public",
- "directory": "../../dist/packages/lit-auth-client"
- },
- "browser": {
- "crypto": false,
- "stream": false
- },
- "tags": [
- "vanilla"
- ],
- "peerDependencies": {
- "@simplewebauthn/browser": "^7.2.0",
- "@simplewebauthn/typescript-types": "^7.0.0"
- },
- "main": "./dist/src/index.js",
- "typings": "./dist/src/index.d.ts"
-}
diff --git a/packages/lit-auth-client/src/index.ts b/packages/lit-auth-client/src/index.ts
deleted file mode 100644
index 344070a76f..0000000000
--- a/packages/lit-auth-client/src/index.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import AppleProvider from './lib/providers/AppleProvider';
-import { BaseProvider } from './lib/providers/BaseProvider';
-import DiscordProvider from './lib/providers/DiscordProvider';
-import EthWalletProvider from './lib/providers/EthWalletProvider';
-import GoogleProvider from './lib/providers/GoogleProvider';
-import StytchAuthFactorOtpProvider from './lib/providers/StytchAuthFactorOtp';
-import { StytchOtpProvider } from './lib/providers/StytchOtpProvider';
-import WebAuthnProvider from './lib/providers/WebAuthnProvider';
-import { LitRelay } from './lib/relay';
-import {
- isSignInRedirect,
- getProviderFromUrl,
- getAuthIdByAuthMethod,
-} from './lib/utils';
-
-export {
- AppleProvider,
- BaseProvider,
- DiscordProvider,
- EthWalletProvider,
- GoogleProvider,
- LitRelay,
- StytchOtpProvider,
- StytchAuthFactorOtpProvider,
- WebAuthnProvider,
- isSignInRedirect,
- getProviderFromUrl,
- getAuthIdByAuthMethod,
-};
diff --git a/packages/lit-auth-client/tsconfig.json b/packages/lit-auth-client/tsconfig.json
deleted file mode 100644
index d87cb2e661..0000000000
--- a/packages/lit-auth-client/tsconfig.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "module": "commonjs",
- "forceConsistentCasingInFileNames": true,
- "strict": true,
- "noImplicitOverride": true,
- "noPropertyAccessFromIndexSignature": true,
- "noImplicitReturns": true,
- "noFallthroughCasesInSwitch": true,
- "allowJs": true
- },
- "files": [],
- "include": [],
- "references": [
- {
- "path": "./tsconfig.lib.json"
- },
- {
- "path": "./tsconfig.spec.json"
- }
- ]
-}
diff --git a/packages/lit-auth-client/tsconfig.spec.json b/packages/lit-auth-client/tsconfig.spec.json
deleted file mode 100644
index 546f12877f..0000000000
--- a/packages/lit-auth-client/tsconfig.spec.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "../../dist/out-tsc",
- "module": "commonjs",
- "types": ["jest", "node"]
- },
- "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
-}
diff --git a/packages/encryption/.babelrc b/packages/lit-client/.babelrc
similarity index 100%
rename from packages/encryption/.babelrc
rename to packages/lit-client/.babelrc
diff --git a/packages/encryption/.eslintrc.json b/packages/lit-client/.eslintrc.json
similarity index 100%
rename from packages/encryption/.eslintrc.json
rename to packages/lit-client/.eslintrc.json
diff --git a/packages/lit-client/README.md b/packages/lit-client/README.md
new file mode 100644
index 0000000000..92a790c64b
--- /dev/null
+++ b/packages/lit-client/README.md
@@ -0,0 +1,9 @@
+# Quick Start
+
+This package contains the main API layer for interacting with LIT network nodes and the LIT blockchain.
+
+### node.js / browser
+
+```
+yarn add @lit-protocol/lit-client
+```
diff --git a/packages/lit-client/index.ts b/packages/lit-client/index.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/nacl/jest.config.ts b/packages/lit-client/jest.config.ts
similarity index 77%
rename from packages/nacl/jest.config.ts
rename to packages/lit-client/jest.config.ts
index d97296773f..bdb4deef40 100644
--- a/packages/nacl/jest.config.ts
+++ b/packages/lit-client/jest.config.ts
@@ -1,6 +1,6 @@
/* eslint-disable */
export default {
- displayName: 'nacl',
+ displayName: 'lit-client',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
@@ -11,6 +11,6 @@ export default {
'^.+\\.[t]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
- coverageDirectory: '../../coverage/packages/nacl',
+ coverageDirectory: '../../coverage/packages/lit-client',
setupFilesAfterEnv: ['../../jest.setup.js'],
};
diff --git a/packages/misc/package.json b/packages/lit-client/package.json
similarity index 86%
rename from packages/misc/package.json
rename to packages/lit-client/package.json
index 8ae2d1f91d..15d280ed02 100644
--- a/packages/misc/package.json
+++ b/packages/lit-client/package.json
@@ -1,5 +1,5 @@
{
- "name": "@lit-protocol/misc",
+ "name": "@lit-protocol/lit-client",
"license": "MIT",
"homepage": "https://github.com/Lit-Protocol/js-sdk",
"repository": {
@@ -15,7 +15,7 @@
"type": "commonjs",
"publishConfig": {
"access": "public",
- "directory": "../../dist/packages/misc"
+ "directory": "../../dist/packages/lit-client"
},
"gitHead": "0d7334c2c55f448e91fe32f29edc5db8f5e09e4b",
"tags": [
diff --git a/packages/auth-browser/project.json b/packages/lit-client/project.json
similarity index 53%
rename from packages/auth-browser/project.json
rename to packages/lit-client/project.json
index bdd325457c..84b42582d7 100644
--- a/packages/auth-browser/project.json
+++ b/packages/lit-client/project.json
@@ -1,17 +1,17 @@
{
- "name": "auth-browser",
+ "name": "lit-client",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
- "sourceRoot": "packages/auth-browser/src",
+ "sourceRoot": "packages/lit-client/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
- "outputPath": "dist/packages/auth-browser",
- "main": "packages/auth-browser/src/index.ts",
- "tsConfig": "packages/auth-browser/tsconfig.lib.json",
- "assets": ["packages/auth-browser/*.md"],
+ "outputPath": "dist/packages/lit-client",
+ "main": "packages/lit-client/src/index.ts",
+ "tsConfig": "packages/lit-client/tsconfig.lib.json",
+ "assets": ["packages/lit-client/*.md"],
"updateBuildableProjectDepsInPackageJson": true
}
},
@@ -19,14 +19,14 @@
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
- "lintFilePatterns": ["packages/auth-browser/**/*.ts"]
+ "lintFilePatterns": ["packages/lit-client/**/*.ts"]
}
},
"test": {
"executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/packages/auth-browser"],
+ "outputs": ["{workspaceRoot}/coverage/packages/lit-client"],
"options": {
- "jestConfig": "packages/auth-browser/jest.config.ts",
+ "jestConfig": "packages/lit-client/jest.config.ts",
"passWithNoTests": true
}
}
diff --git a/packages/lit-client/src/index.ts b/packages/lit-client/src/index.ts
new file mode 100644
index 0000000000..8c78392744
--- /dev/null
+++ b/packages/lit-client/src/index.ts
@@ -0,0 +1,4 @@
+// Export our top-level consumer API and types for consumers of the entire lit-client package
+// export `getLitClient({network, authManager, options? })` => { ...api }
+
+export {};
diff --git a/packages/lit-client/src/lib/api/index.ts b/packages/lit-client/src/lib/api/index.ts
new file mode 100644
index 0000000000..7b507e8323
--- /dev/null
+++ b/packages/lit-client/src/lib/api/index.ts
@@ -0,0 +1,3 @@
+// This folder will contain the modules that 'glue together' chain and lit-node-specific behaviours into our top-level `lit-client` interface
+
+export {};
diff --git a/packages/lit-client/src/lib/chain/index.ts b/packages/lit-client/src/lib/chain/index.ts
new file mode 100644
index 0000000000..014da51de2
--- /dev/null
+++ b/packages/lit-client/src/lib/chain/index.ts
@@ -0,0 +1,4 @@
+// Define behaviours / methods / modules that are entirely specific to interacting with LIT blockchains
+// These should be 'thin' methods that basically orchestrate a provided `LitNetwork` + params, and use an internal `LitChainClient` to do what is required
+
+export {};
diff --git a/packages/lit-client/src/lib/index.ts b/packages/lit-client/src/lib/index.ts
new file mode 100644
index 0000000000..d87c4bb696
--- /dev/null
+++ b/packages/lit-client/src/lib/index.ts
@@ -0,0 +1,3 @@
+import * as api from './api';
+
+export { api };
diff --git a/packages/lit-client/src/lib/lit-nodes/index.ts b/packages/lit-client/src/lib/lit-nodes/index.ts
new file mode 100644
index 0000000000..9168eae186
--- /dev/null
+++ b/packages/lit-client/src/lib/lit-nodes/index.ts
@@ -0,0 +1,4 @@
+// Define behaviours / methods / modules that are entirely specific to interacting with LIT nodes
+// These should be 'thin' methods that basically orchestrate a provided `LitNetwork` + params, and use an internal `LitNodeClient` to do what is required
+
+export {};
diff --git a/packages/misc/tsconfig.json b/packages/lit-client/tsconfig.json
similarity index 100%
rename from packages/misc/tsconfig.json
rename to packages/lit-client/tsconfig.json
diff --git a/packages/encryption/tsconfig.lib.json b/packages/lit-client/tsconfig.lib.json
similarity index 100%
rename from packages/encryption/tsconfig.lib.json
rename to packages/lit-client/tsconfig.lib.json
diff --git a/packages/encryption/tsconfig.spec.json b/packages/lit-client/tsconfig.spec.json
similarity index 100%
rename from packages/encryption/tsconfig.spec.json
rename to packages/lit-client/tsconfig.spec.json
diff --git a/packages/lit-node-client-nodejs/.babelrc b/packages/lit-node-client-nodejs/.babelrc
deleted file mode 100644
index 158083d278..0000000000
--- a/packages/lit-node-client-nodejs/.babelrc
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presets": [
- [
- "@nx/web/babel",
- {
- "useBuiltIns": "usage"
- }
- ]
- ]
-}
diff --git a/packages/lit-node-client-nodejs/.eslintrc.json b/packages/lit-node-client-nodejs/.eslintrc.json
deleted file mode 100644
index 9d9c0db55b..0000000000
--- a/packages/lit-node-client-nodejs/.eslintrc.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "extends": ["../../.eslintrc.json"],
- "ignorePatterns": ["!**/*"],
- "overrides": [
- {
- "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
- "rules": {}
- },
- {
- "files": ["*.ts", "*.tsx"],
- "rules": {}
- },
- {
- "files": ["*.js", "*.jsx"],
- "rules": {}
- }
- ]
-}
diff --git a/packages/lit-node-client-nodejs/README.md b/packages/lit-node-client-nodejs/README.md
deleted file mode 100644
index 4f20193e88..0000000000
--- a/packages/lit-node-client-nodejs/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Getting Started
-
-This `LitNodeClientNodeJs` is created solely to run on Node.js.
-
-The usual `checkAndSignAuthMessage` is not included in this package, so you need to add it manually to the constructor if you decide to use it on a browser, or with any custom auth callback.
-
-```js
-import * as LitJsSdkNodeJs from '@lit-protocol/lit-node-client-nodejs';
-import { checkAndSignAuthMessage } from '@lit-protocol/auth-browser';
-
-const client = new LitJsSdkNodeJs.LitNodeClientNodeJs({
- litNetwork: 'serrano',
- defaultAuthCallback: checkAndSignAuthMessage,
-});
-
-await client.connect();
-
-const authSig = await checkAndSignAuthMessage({
- chain: 'ethereum',
-});
-```
diff --git a/packages/lit-node-client-nodejs/package.json b/packages/lit-node-client-nodejs/package.json
deleted file mode 100644
index 55e550786a..0000000000
--- a/packages/lit-node-client-nodejs/package.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "@lit-protocol/lit-node-client-nodejs",
- "type": "commonjs",
- "license": "MIT",
- "homepage": "https://github.com/Lit-Protocol/js-sdk",
- "repository": {
- "type": "git",
- "url": "https://github.com/LIT-Protocol/js-sdk"
- },
- "keywords": [
- "library"
- ],
- "bugs": {
- "url": "https://github.com/LIT-Protocol/js-sdk/issues"
- },
- "publishConfig": {
- "access": "public",
- "directory": "../../dist/packages/lit-node-client-nodejs"
- },
- "browser": {
- "crypto": false,
- "stream": false
- },
- "tags": [
- "nodejs"
- ],
- "version": "8.0.0-alpha.0",
- "main": "./dist/src/index.js",
- "typings": "./dist/src/index.d.ts"
-}
diff --git a/packages/lit-node-client-nodejs/project.json b/packages/lit-node-client-nodejs/project.json
deleted file mode 100644
index 1f41892a20..0000000000
--- a/packages/lit-node-client-nodejs/project.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "lit-node-client-nodejs",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "sourceRoot": "packages/lit-node-client-nodejs/src",
- "projectType": "library",
- "targets": {
- "build": {
- "executor": "@nx/js:tsc",
- "outputs": ["{options.outputPath}"],
- "options": {
- "outputPath": "dist/packages/lit-node-client-nodejs",
- "main": "packages/lit-node-client-nodejs/src/index.ts",
- "tsConfig": "packages/lit-node-client-nodejs/tsconfig.lib.json",
- "assets": ["packages/lit-node-client-nodejs/*.md"],
- "updateBuildableProjectDepsInPackageJson": true
- }
- },
- "lint": {
- "executor": "@nx/linter:eslint",
- "outputs": ["{options.outputFile}"],
- "options": {
- "lintFilePatterns": ["packages/lit-node-client-nodejs/**/*.ts"]
- }
- },
- "test": {
- "executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/packages/lit-node-client-nodejs"],
- "options": {
- "jestConfig": "packages/lit-node-client-nodejs/jest.config.ts",
- "passWithNoTests": true
- }
- },
- "testWatch": {
- "executor": "@nx/jest:jest",
- "outputs": ["{workspaceRoot}/coverage/packages/lit-node-client-nodejs"],
- "options": {
- "jestConfig": "packages/lit-node-client-nodejs/jest.config.ts",
- "watch": true,
- "passWithNoTests": true
- }
- }
- },
- "tags": []
-}
diff --git a/packages/lit-node-client-nodejs/src/index.ts b/packages/lit-node-client-nodejs/src/index.ts
deleted file mode 100644
index bbe72272e2..0000000000
--- a/packages/lit-node-client-nodejs/src/index.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'cross-fetch/dist/node-polyfill.js';
-
-// ==================== Exports ====================
-export * from './lib/lit-node-client-nodejs';
-
-export {
- hashResourceIdForSigning,
- humanizeAccessControlConditions,
-} from '@lit-protocol/access-control-conditions';
-
-export {
- base64StringToBlob,
- blobToBase64String,
-} from '@lit-protocol/misc-browser';
-
-export {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/encode-code.ts b/packages/lit-node-client-nodejs/src/lib/helpers/encode-code.ts
deleted file mode 100644
index 1b45f2c58a..0000000000
--- a/packages/lit-node-client-nodejs/src/lib/helpers/encode-code.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
-
-/**
- * Encodes the given code string into base64 format.
- *
- * @param code - The code string to be encoded.
- * @returns The encoded code string in base64 format.
- */
-export const encodeCode = (code: string) => {
- const _uint8Array = uint8arrayFromString(code, 'utf8');
- const encodedJs = uint8arrayToString(_uint8Array, 'base64');
-
- return encodedJs;
-};
diff --git a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts
deleted file mode 100644
index 8270c1b1f5..0000000000
--- a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts
+++ /dev/null
@@ -1,2125 +0,0 @@
-import { computeAddress } from '@ethersproject/transactions';
-import { ethers } from 'ethers';
-import { SiweMessage } from 'siwe';
-
-import {
- getFormattedAccessControlConditions,
- getHashedAccessControlConditions,
- validateAccessControlConditions,
-} from '@lit-protocol/access-control-conditions';
-import {
- createSiweMessage,
- createSiweMessageWithCapacityDelegation,
- createSiweMessageWithRecaps,
- decode,
- generateAuthSig,
- generateSessionCapabilityObjectWithWildcards,
- LitAccessControlConditionResource,
- LitResourceAbilityRequest,
-} from '@lit-protocol/auth-helpers';
-import {
- AUTH_METHOD_TYPE,
- EITHER_TYPE,
- FALLBACK_IPFS_GATEWAYS,
- GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK,
- InvalidArgumentException,
- InvalidParamType,
- InvalidSessionSigs,
- InvalidSignatureError,
- LIT_CURVE,
- LIT_CURVE_TYPE,
- LIT_ENDPOINT,
- LitNodeClientNotReadyError,
- LOCAL_STORAGE_KEYS,
- ParamNullError,
- ParamsMissingError,
- PRODUCT_IDS,
- SIWE_URI_PREFIX,
- UnknownError,
- UnsupportedMethodError,
- WalletSignatureNotFoundError,
-} from '@lit-protocol/constants';
-import { getNodePrices } from '@lit-protocol/contracts-sdk';
-import { composeLitUrl, LitCore } from '@lit-protocol/core';
-import {
- combineSignatureShares,
- encrypt,
- generateSessionKeyPair,
- verifyAndDecryptWithSignatureShares,
- verifySignature,
-} from '@lit-protocol/crypto';
-import {
- defaultMintClaimCallback,
- findMostCommonResponse,
- formatSessionSigs,
- hexPrefixed,
- log,
- logErrorWithRequestId,
- logWithRequestId,
- mostCommonString,
- normalizeAndStringify,
- removeHexPrefix,
- safeParams,
- validateSessionSigs,
-} from '@lit-protocol/misc';
-import {
- getStorageItem,
- removeStorageItem,
- setStorageItem,
-} from '@lit-protocol/misc-browser';
-import { nacl } from '@lit-protocol/nacl';
-import {
- AuthCallback,
- AuthCallbackParams,
- type AuthenticationContext,
- AuthSig,
- BlsResponseData,
- CapacityCreditsReq,
- CapacityCreditsRes,
- ClaimKeyResponse,
- ClaimProcessor,
- ClaimRequest,
- CustomNetwork,
- DecryptRequest,
- DecryptResponse,
- EncryptionSignRequest,
- EncryptResponse,
- EncryptSdkParams,
- ExecuteJsNoSigningResponse,
- ExecuteJsResponse,
- FormattedMultipleAccs,
- GetWalletSigProps,
- ILitNodeClient,
- JsonExecutionRequest,
- JsonExecutionSdkParams,
- JsonPKPClaimKeyRequest,
- JsonPkpSignRequest,
- JsonPkpSignSdkParams,
- JsonSignSessionKeyRequestV1,
- JsonSignSessionKeyRequestV2,
- LitNodeClientConfig,
- NodeBlsSigningShare,
- NodeCommandResponse,
- NodeSet,
- NodeShare,
- PKPSignEndpointResponse,
- RejectedNodePromises,
- SessionKeyPair,
- SessionSigningTemplate,
- SessionSigsMap,
- Signature,
- SignSessionKeyProp,
- SignSessionKeyResponse,
- SigResponse,
- SuccessNodePromises,
-} from '@lit-protocol/types';
-import { AuthMethod } from '@lit-protocol/types';
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
-
-import { encodeCode } from './helpers/encode-code';
-import { getBlsSignatures } from './helpers/get-bls-signatures';
-import { getClaims } from './helpers/get-claims';
-import { getClaimsList } from './helpers/get-claims-list';
-import { getExpiration } from './helpers/get-expiration';
-import { getMaxPricesForNodeProduct } from './helpers/get-max-prices-for-node-product';
-import { getSignatures } from './helpers/get-signatures';
-import { normalizeArray } from './helpers/normalize-array';
-import { normalizeJsParams } from './helpers/normalize-params';
-import { parseAsJsonOrString } from './helpers/parse-as-json-or-string';
-import { parsePkpSignResponse } from './helpers/parse-pkp-sign-response';
-import { processLitActionResponseStrategy } from './helpers/process-lit-action-response-strategy';
-import { removeDoubleQuotes } from './helpers/remove-double-quotes';
-import { blsSessionSigVerify } from './helpers/validate-bls-session-sig';
-
-export class LitNodeClientNodeJs extends LitCore implements ILitNodeClient {
- /** Tracks the total max price a user is willing to pay for each supported product type
- * This must be distributed across all nodes; each node will get a percentage of this price
- *
- * If the user never sets a max price, it means 'unlimited'
- */
- defaultMaxPriceByProduct: Record = {
- DECRYPTION: BigInt(-1),
- SIGN: BigInt(-1),
- LIT_ACTION: BigInt(-1),
- };
-
- defaultAuthCallback?: (authSigParams: AuthCallbackParams) => Promise;
-
- // ========== Constructor ==========
- constructor(args: LitNodeClientConfig | CustomNetwork) {
- if (!args) {
- throw new ParamsMissingError({}, 'must provide LitNodeClient parameters');
- }
-
- super(args);
-
- if (args !== undefined && args !== null && 'defaultAuthCallback' in args) {
- this.defaultAuthCallback = args.defaultAuthCallback;
- }
- }
-
- setDefaultMaxPrice(product: keyof typeof PRODUCT_IDS, price: bigint) {
- this.defaultMaxPriceByProduct[product] = price;
- }
-
- private _getNodePrices() {
- return getNodePrices({
- realmId: 1,
- litNetwork: this.config.litNetwork,
- networkContext: this.config.contractContext,
- rpcUrl: this.config.rpcUrl,
- nodeProtocol: this.config.nodeProtocol,
- });
- }
- // ========== Rate Limit NFT ==========
-
- // TODO: Add support for browser feature/lit-2321-js-sdk-add-browser-support-for-createCapacityDelegationAuthSig
- createCapacityDelegationAuthSig = async (
- params: CapacityCreditsReq
- ): Promise => {
- // -- validate
- if (!params.dAppOwnerWallet) {
- throw new InvalidParamType(
- {
- info: {
- params,
- },
- },
- 'dAppOwnerWallet must exist'
- );
- }
-
- // Useful log for debugging
- if (!params.delegateeAddresses || params.delegateeAddresses.length === 0) {
- log(
- `[createCapacityDelegationAuthSig] 'delegateeAddresses' is an empty array. It means that no body can use it. However, if the 'delegateeAddresses' field is omitted, It means that the capability will not restrict access based on delegatee list, but it may still enforce other restrictions such as usage limits (uses) and specific NFT IDs (nft_id).`
- );
- }
-
- // -- This is the owner address who holds the Capacity Credits NFT token and wants to delegate its
- // usage to a list of delegatee addresses
- const dAppOwnerWalletAddress = ethers.utils.getAddress(
- await params.dAppOwnerWallet.getAddress()
- );
-
- // -- if it's not ready yet, then connect
- if (!this.ready) {
- await this.connect();
- }
-
- const siweMessage = await createSiweMessageWithCapacityDelegation({
- uri: SIWE_URI_PREFIX.DELEGATION,
- litNodeClient: this,
- walletAddress: dAppOwnerWalletAddress,
- nonce: await this.getLatestBlockhash(),
- expiration: params.expiration,
- domain: params.domain,
- statement: params.statement,
-
- // -- capacity delegation specific configuration
- uses: params.uses,
- delegateeAddresses: params.delegateeAddresses,
- // paymentId: params.paymentId, // CHANGE: Not supported yet
- });
-
- const authSig = await generateAuthSig({
- signer: params.dAppOwnerWallet,
- toSign: siweMessage,
- });
-
- return { capacityDelegationAuthSig: authSig };
- };
-
- // ==================== SESSIONS ====================
- /**
- * Try to get the session key in the local storage,
- * if not, generates one.
- * @return { SessionKeyPair } session key pair
- */
- private _getSessionKey = (): SessionKeyPair => {
- const storageKey = LOCAL_STORAGE_KEYS.SESSION_KEY;
- const storedSessionKeyOrError = getStorageItem(storageKey);
-
- if (
- storedSessionKeyOrError.type === EITHER_TYPE.ERROR ||
- !storedSessionKeyOrError.result ||
- storedSessionKeyOrError.result === ''
- ) {
- console.warn(
- `Storage key "${storageKey}" is missing. Not a problem. Continue...`
- );
-
- // Generate new one
- const newSessionKey = generateSessionKeyPair();
-
- // (TRY) to set to local storage
- try {
- localStorage.setItem(storageKey, JSON.stringify(newSessionKey));
- } catch (e) {
- log(
- `[getSessionKey] Localstorage not available.Not a problem. Continue...`
- );
- }
-
- return newSessionKey;
- } else {
- return JSON.parse(storedSessionKeyOrError.result as string);
- }
- };
-
- /**
- * Get the signature from local storage, if not, generates one
- */
- private _getWalletSig = async ({
- authNeededCallback,
- chain,
- sessionCapabilityObject,
- switchChain,
- expiration,
- sessionKeyUri,
- nonce,
- resourceAbilityRequests,
- litActionCode,
- litActionIpfsId,
- jsParams,
- sessionKey,
- }: GetWalletSigProps): Promise => {
- let walletSig: AuthSig;
-
- const storageKey = LOCAL_STORAGE_KEYS.WALLET_SIGNATURE;
- const storedWalletSigOrError = getStorageItem(storageKey);
-
- // browser: 2 > 2.1 > 3
- // nodejs: 1. > 1.1
-
- // -- (TRY) to get it in the local storage
- // -- IF NOT: Generates one
- log(`getWalletSig - flow starts
- storageKey: ${storageKey}
- storedWalletSigOrError: ${JSON.stringify(storedWalletSigOrError)}
- `);
-
- if (
- storedWalletSigOrError.type === EITHER_TYPE.ERROR ||
- !storedWalletSigOrError.result ||
- storedWalletSigOrError.result == ''
- ) {
- log('getWalletSig - flow 1');
- console.warn(
- `Storage key "${storageKey}" is missing. Not a problem. Continue...`
- );
- if (authNeededCallback) {
- log('getWalletSig - flow 1.1');
-
- const body = {
- chain,
- statement: sessionCapabilityObject?.statement,
- resources: sessionCapabilityObject
- ? [sessionCapabilityObject.encodeAsSiweResource()]
- : undefined,
- ...(switchChain && { switchChain }),
- expiration,
- uri: sessionKeyUri,
- sessionKey: sessionKey,
- nonce,
-
- // for recap
- ...(resourceAbilityRequests && { resourceAbilityRequests }),
-
- // for lit action custom auth
- ...(litActionCode && { litActionCode }),
- ...(litActionIpfsId && { litActionIpfsId }),
- ...(jsParams && { jsParams }),
- };
-
- log('callback body:', body);
-
- walletSig = await authNeededCallback(body);
- } else {
- log('getWalletSig - flow 1.2');
- if (!this.defaultAuthCallback) {
- log('getWalletSig - flow 1.2.1');
- throw new ParamsMissingError(
- {},
- 'No authNeededCallback nor default auth callback provided'
- );
- }
-
- log('getWalletSig - flow 1.2.2');
- walletSig = await this.defaultAuthCallback({
- chain,
- statement: sessionCapabilityObject.statement,
- resources: sessionCapabilityObject
- ? [sessionCapabilityObject.encodeAsSiweResource()]
- : undefined,
- switchChain,
- expiration,
- uri: sessionKeyUri,
- nonce,
- });
- }
-
- log('getWalletSig - flow 1.3');
-
- // (TRY) to set walletSig to local storage
- const storeNewWalletSigOrError = setStorageItem(
- storageKey,
- JSON.stringify(walletSig)
- );
- if (storeNewWalletSigOrError.type === 'ERROR') {
- log('getWalletSig - flow 1.4');
- console.warn(
- `Unable to store walletSig in local storage. Not a problem. Continue...`
- );
- }
- } else {
- log('getWalletSig - flow 2');
- try {
- walletSig = JSON.parse(storedWalletSigOrError.result as string);
- log('getWalletSig - flow 2.1');
- } catch (e) {
- console.warn('Error parsing walletSig', e);
- log('getWalletSig - flow 2.2');
- }
- }
-
- log('getWalletSig - flow 3');
- return walletSig!;
- };
-
- private _authCallbackAndUpdateStorageItem = async ({
- authCallbackParams,
- authCallback,
- }: {
- authCallbackParams: AuthCallbackParams;
- authCallback?: AuthCallback;
- }): Promise => {
- let authSig: AuthSig;
-
- if (authCallback) {
- authSig = await authCallback(authCallbackParams);
- } else {
- if (!this.defaultAuthCallback) {
- throw new ParamsMissingError(
- {},
- 'No authCallback nor default auth callback provided'
- );
- }
- authSig = await this.defaultAuthCallback(authCallbackParams);
- }
-
- // (TRY) to set walletSig to local storage
- const storeNewWalletSigOrError = setStorageItem(
- LOCAL_STORAGE_KEYS.WALLET_SIGNATURE,
- JSON.stringify(authSig)
- );
- if (storeNewWalletSigOrError.type === EITHER_TYPE.SUCCESS) {
- return authSig;
- }
-
- // Setting local storage failed, try to remove the item key.
- console.warn(
- `Unable to store walletSig in local storage. Not a problem. Continuing to remove item key...`
- );
- const removeWalletSigOrError = removeStorageItem(
- LOCAL_STORAGE_KEYS.WALLET_SIGNATURE
- );
- if (removeWalletSigOrError.type === EITHER_TYPE.ERROR) {
- console.warn(
- `Unable to remove walletSig in local storage. Not a problem. Continuing...`
- );
- }
-
- return authSig;
- };
-
- /**
- *
- * Check if a session key needs to be resigned. These are the scenarios where a session key needs to be resigned:
- * 1. The authSig.sig does not verify successfully against the authSig.signedMessage
- * 2. The authSig.signedMessage.uri does not match the sessionKeyUri
- * 3. The authSig.signedMessage does not contain at least one session capability object
- *
- */
- private _checkNeedToResignSessionKey = async ({
- authSig,
- sessionKeyUri,
- resourceAbilityRequests,
- }: {
- authSig: AuthSig;
- sessionKeyUri: string;
- resourceAbilityRequests: LitResourceAbilityRequest[];
- }): Promise => {
- const authSigSiweMessage = new SiweMessage(authSig.signedMessage);
- // We will either have `ed25519` or `LIT_BLS` as we have deviated from the specification of SIWE and use BLS signatures in some cases
- // Here we need to check the `algo` of the SIWE to confirm we can validate the signature as if we attempt to validate the BLS signature here
- // it will fail. If the algo is not defined we can assume that it was an EOA wallet signing the message so we can use SIWE.
- if (authSig.algo === `ed25519` || authSig.algo === undefined) {
- try {
- await authSigSiweMessage.verify(
- { signature: authSig.sig },
- { suppressExceptions: false }
- );
- } catch (e) {
- log(`Error while verifying BLS signature: `, e);
- return true;
- }
- } else if (authSig.algo === `LIT_BLS`) {
- try {
- await blsSessionSigVerify(
- verifySignature,
- this.networkPubKey!,
- authSig,
- authSigSiweMessage
- );
- } catch (e) {
- log(`Error while verifying bls signature: `, e);
- return true;
- }
- } else {
- throw new InvalidSignatureError(
- {
- info: {
- authSig,
- resourceAbilityRequests,
- sessionKeyUri,
- },
- },
- 'Unsupported signature algo for session signature. Expected ed25519 or LIT_BLS received %s',
- authSig.algo
- );
- }
-
- // make sure the sig is for the correct session key
- if (authSigSiweMessage.uri !== sessionKeyUri) {
- log('Need retry because uri does not match');
- return true;
- }
-
- // make sure the authSig contains at least one resource.
- if (
- !authSigSiweMessage.resources ||
- authSigSiweMessage.resources.length === 0
- ) {
- log('Need retry because empty resources');
- return true;
- }
-
- // make sure the authSig contains session capabilities that can be parsed.
- // TODO: we currently only support the first resource being a session capability object.
- const authSigSessionCapabilityObject = decode(
- authSigSiweMessage.resources[0]
- );
-
- // make sure the authSig session capability object describes capabilities that are equal or greater than
- // the abilities requested against the resources in the resource ability requests.
- for (const resourceAbilityRequest of resourceAbilityRequests) {
- if (
- !authSigSessionCapabilityObject.verifyCapabilitiesForResource(
- resourceAbilityRequest.resource,
- resourceAbilityRequest.ability
- )
- ) {
- log('Need retry because capabilities do not match', {
- authSigSessionCapabilityObject,
- resourceAbilityRequest,
- });
- return true;
- }
- }
-
- return false;
- };
-
- private _decryptWithSignatureShares = (
- networkPubKey: string,
- identityParam: Uint8Array,
- ciphertext: string,
- signatureShares: NodeBlsSigningShare[]
- ): Promise => {
- const sigShares = signatureShares.map((s) => s.signatureShare);
-
- return verifyAndDecryptWithSignatureShares(
- networkPubKey,
- identityParam,
- ciphertext,
- sigShares
- );
- };
-
- /**
- * Retrieves the fallback IPFS code for a given IPFS ID.
- *
- * @param gatewayUrl - the gateway url.
- * @param ipfsId - The IPFS ID.
- * @returns The base64-encoded fallback IPFS code.
- * @throws An error if the code retrieval fails.
- */
- private async _getFallbackIpfsCode(
- gatewayUrl: string | undefined,
- ipfsId: string
- ) {
- const allGateways = gatewayUrl
- ? [gatewayUrl, ...FALLBACK_IPFS_GATEWAYS]
- : FALLBACK_IPFS_GATEWAYS;
-
- log(
- `Attempting to fetch code for IPFS ID: ${ipfsId} using fallback IPFS gateways`
- );
-
- for (const url of allGateways) {
- try {
- const response = await fetch(`${url}${ipfsId}`);
-
- if (!response.ok) {
- throw new Error(
- `Failed to fetch code from IPFS gateway ${url}: ${response.status} ${response.statusText}`
- );
- }
-
- const code = await response.text();
- const codeBase64 = Buffer.from(code).toString('base64');
-
- return codeBase64;
- } catch (error) {
- console.error(`Error fetching code from IPFS gateway ${url}`);
- // Continue to the next gateway in the array
- }
- }
-
- throw new Error('All IPFS gateways failed to fetch the code.');
- }
-
- private async executeJsNodeRequest(
- url: string,
- formattedParams: JsonExecutionSdkParams & { sessionSigs: SessionSigsMap },
- requestId: string,
- nodeSet: NodeSet[]
- ) {
- // -- choose the right signature
- const sessionSig = this._getSessionSigByUrl({
- sessionSigs: formattedParams.sessionSigs,
- url,
- });
-
- const reqBody: JsonExecutionRequest = {
- ...formattedParams,
- authSig: sessionSig,
- nodeSet,
- };
-
- const urlWithPath = composeLitUrl({
- url,
- endpoint: LIT_ENDPOINT.EXECUTE_JS,
- });
-
- return this.generatePromise(urlWithPath, reqBody, requestId);
- }
- /**
- *
- * Execute JS on the nodes and combine and return any resulting signatures
- *
- * @param { JsonExecutionSdkParams } params
- *
- * @returns { ExecuteJsResponse }
- *
- */
- executeJs = async (
- params: JsonExecutionSdkParams
- ): Promise => {
- // ========== Validate Params ==========
- if (!this.ready) {
- const message =
- '[executeJs] LitNodeClient is not ready. Please call await litNodeClient.connect() first.';
-
- throw new LitNodeClientNotReadyError({}, message);
- }
-
- const paramsIsSafe = safeParams({
- functionName: 'executeJs',
- params: params,
- });
-
- if (!paramsIsSafe) {
- throw new InvalidParamType(
- {
- info: {
- params,
- },
- },
- 'executeJs params are not valid'
- );
- }
-
- // Format the params
- let formattedParams: JsonExecutionSdkParams = {
- ...params,
- ...(params.jsParams && { jsParams: normalizeJsParams(params.jsParams) }),
- ...(params.code && { code: encodeCode(params.code) }),
- };
-
- // Check if IPFS options are provided and if the code should be fetched from IPFS and overwrite the current code.
- // This will fetch the code from the specified IPFS gateway using the provided ipfsId,
- // and update the params with the fetched code, removing the ipfsId afterward.
- const overwriteCode =
- params.ipfsOptions?.overwriteCode ||
- GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK[this.config.litNetwork];
-
- if (overwriteCode && params.ipfsId) {
- const code = await this._getFallbackIpfsCode(
- params.ipfsOptions?.gatewayUrl,
- params.ipfsId
- );
-
- formattedParams = {
- ...params,
- code: code,
- ipfsId: undefined,
- };
- }
-
- const requestId = this._getNewRequestId();
-
- const userMaxPrices = await this.getMaxPricesForNodeProduct({
- product: 'LIT_ACTION',
- userMaxPrice: params.userMaxPrice,
- });
-
- const targetNodePrices = params.useSingleNode
- ? userMaxPrices.slice(0, 1)
- : userMaxPrices;
-
- const sessionSigs = await this._getSessionSigs({
- ...params.authContext,
- userMaxPrices: targetNodePrices,
- });
-
- const targetNodeUrls = targetNodePrices.map(({ url }) => url);
- // ========== Get Node Promises ==========
- // Handle promises for commands sent to Lit nodes
- const nodePromises = this._getNodePromises(targetNodeUrls, (url: string) =>
- this.executeJsNodeRequest(
- url,
- {
- ...formattedParams,
- sessionSigs,
- },
- requestId,
- this._getNodeSet(targetNodeUrls)
- )
- );
-
- // -- resolve promises
- const res = await this._handleNodePromises(
- nodePromises,
- requestId,
- params.useSingleNode ? 1 : this._getThreshold()
- );
-
- // -- case: promises rejected
- if (!res.success) {
- this._throwNodeError(res, requestId);
- }
-
- // -- case: promises success (TODO: check the keys of "values")
- const responseData = (res as SuccessNodePromises).values;
-
- logWithRequestId(
- requestId,
- 'executeJs responseData from node : ',
- JSON.stringify(responseData, null, 2)
- );
-
- // -- find the responseData that has the most common response
- const mostCommonResponse = findMostCommonResponse(
- responseData
- ) as NodeShare;
-
- const responseFromStrategy = processLitActionResponseStrategy(
- responseData,
- params.responseStrategy ?? { strategy: 'leastCommon' }
- );
- mostCommonResponse.response = responseFromStrategy;
-
- const isSuccess = mostCommonResponse.success;
- const hasSignedData = Object.keys(mostCommonResponse.signedData).length > 0;
- const hasClaimData = Object.keys(mostCommonResponse.claimData).length > 0;
-
- // -- we must also check for claim responses as a user may have submitted for a claim and signatures must be aggregated before returning
- if (isSuccess && !hasSignedData && !hasClaimData) {
- return mostCommonResponse as unknown as ExecuteJsResponse;
- }
-
- // -- in the case where we are not signing anything on Lit action and using it as purely serverless function
- if (!hasSignedData && !hasClaimData) {
- return {
- claims: {},
- signatures: null,
- decryptions: [],
- response: mostCommonResponse.response,
- logs: mostCommonResponse.logs,
- } as ExecuteJsNoSigningResponse;
- }
-
- // ========== Extract shares from response data ==========
-
- // -- 1. combine signed data as a list, and get the signatures from it
- const signedDataList = responseData.map((r) => {
- return removeDoubleQuotes(r.signedData);
- });
-
- logWithRequestId(
- requestId,
- 'signatures shares to combine: ',
- signedDataList
- );
-
- // Flatten the signedDataList by moving the data within the `sig` (or any other key user may choose) object to the top level.
- // The specific key name (`sig`) is irrelevant, as the contents of the object are always lifted directly.
- const key = Object.keys(signedDataList[0])[0]; // Get the first key of the object
-
- const flattenedSignedMessageShares = signedDataList.map((item) => {
- return item[key]; // Return the value corresponding to that key
- });
-
- // -- 2. combine responses as a string, and parse it as JSON if possible
- const parsedResponse = parseAsJsonOrString(mostCommonResponse.response);
-
- // -- 3. combine logs
- const mostCommonLogs: string = mostCommonString(
- responseData.map(
- (r: {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- logs: any;
- }) => r.logs
- )
- );
-
- // -- 4. combine claims
- const claimsList = getClaimsList(responseData);
- const claims = claimsList.length > 0 ? getClaims(claimsList) : undefined;
-
- // ========== Result ==========
- const returnVal: ExecuteJsResponse = {
- claims,
- signatures: hasSignedData
- ? {
- [key]: await getSignatures({
- requestId,
- networkPubKeySet: this.networkPubKeySet,
- threshold: params.useSingleNode ? 1 : this._getThreshold(),
- signedMessageShares: flattenedSignedMessageShares,
- }),
- }
- : {},
- // decryptions: [],
- response: parsedResponse,
- logs: mostCommonLogs,
- };
-
- log('returnVal:', returnVal);
-
- return returnVal;
- };
-
- /**
- * Generates a promise by sending a command to the Lit node
- *
- * @param url - The URL to send the command to.
- * @param params - The parameters to include in the command.
- * @param requestId - The ID of the request.
- * @returns A promise that resolves with the response from the server.
- */
- generatePromise = async (
- url: string,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- params: any,
- requestId: string
- ): Promise => {
- return await this._sendCommandToNode({
- url,
- data: params,
- requestId,
- });
- };
-
- /**
- * Use PKP to sign
- *
- * @param { JsonPkpSignSdkParams } params
- * @param params.toSign - The data to sign
- * @param params.pubKey - The public key to sign with
- * @param params.sessionSigs - The session signatures to use
- * @param params.authMethods - (optional) The auth methods to use
- */
- pkpSign = async (params: JsonPkpSignSdkParams): Promise => {
- // -- validate required params
- const requiredParamKeys = ['toSign', 'pubKey', 'authContext'];
-
- (requiredParamKeys as (keyof JsonPkpSignSdkParams)[]).forEach((key) => {
- if (!params[key]) {
- throw new ParamNullError(
- {
- info: {
- params,
- key,
- },
- },
- `"%s" cannot be undefined, empty, or null. Please provide a valid value.`,
- key
- );
- }
- });
-
- const requestId = this._getNewRequestId();
-
- const targetNodePrices = await this.getMaxPricesForNodeProduct({
- product: 'SIGN',
- userMaxPrice: params.userMaxPrice,
- });
-
- const sessionSigs = await this._getSessionSigs({
- pkpPublicKey: params.pubKey,
- ...params.authContext,
- userMaxPrices: targetNodePrices,
- });
-
- // validate session sigs
- const checkedSessionSigs = validateSessionSigs(sessionSigs);
-
- if (checkedSessionSigs.isValid === false) {
- throw new InvalidSessionSigs(
- {},
- `Invalid sessionSigs. Errors: ${checkedSessionSigs.errors}`
- );
- }
-
- // ========== Get Node Promises ==========
- // Handle promises for commands sent to Lit nodes
-
- const targetNodeUrls = targetNodePrices.map(({ url }) => url);
- const nodePromises = this._getNodePromises(
- targetNodeUrls,
- (url: string) => {
- // -- get the session sig from the url key
- const sessionSig = this._getSessionSigByUrl({
- sessionSigs,
- url,
- });
-
- const reqBody: JsonPkpSignRequest = {
- toSign: normalizeArray(params.toSign),
- pubkey: hexPrefixed(params.pubKey),
- authSig: sessionSig,
-
- // -- optional params - no longer allowed in >= Naga?
- // ...(params.authContext.authMethods &&
- // params.authContext.authMethods.length > 0 && {
- // authMethods: params.authContext.authMethods,
- // }),
-
- // nodeSet: thresholdNodeSet,
- nodeSet: this._getNodeSet(targetNodeUrls),
- signingScheme: 'EcdsaK256Sha256',
- };
-
- logWithRequestId(requestId, 'reqBody:', reqBody);
-
- const urlWithPath = composeLitUrl({
- url,
- endpoint: LIT_ENDPOINT.PKP_SIGN,
- });
-
- return this.generatePromise(urlWithPath, reqBody, requestId);
- }
- );
-
- const res = await this._handleNodePromises(
- nodePromises,
- requestId,
- this._getThreshold()
- );
-
- // ========== Handle Response ==========
- if (!res.success) {
- this._throwNodeError(res, requestId);
- }
-
- const responseData = (res as SuccessNodePromises)
- .values;
-
- logWithRequestId(
- requestId,
- 'pkpSign responseData',
- JSON.stringify(responseData)
- );
-
- // clean up the response data (as there are double quotes & snake cases in the response)
- const signedMessageShares = parsePkpSignResponse(responseData);
-
- try {
- const signatures = await getSignatures({
- requestId,
- networkPubKeySet: this.networkPubKeySet,
- threshold: this._getThreshold(),
- signedMessageShares: signedMessageShares,
- });
-
- logWithRequestId(requestId, `signature combination`, signatures);
-
- return signatures;
- } catch (e) {
- console.error('Error getting signature', e);
- throw e;
- }
- };
-
- /**
- * Encrypt data using the LIT network public key.
- * See more: https://developer.litprotocol.com/sdk/access-control/encryption
- *
- * @param { EncryptSdkParams } params
- * @param params.dataToEncrypt - The data to encrypt
- * @param params.accessControlConditions - (optional) The access control conditions for the data
- * @param params.evmContractConditions - (optional) The EVM contract conditions for the data
- * @param params.solRpcConditions - (optional) The Solidity RPC conditions for the data
- * @param params.unifiedAccessControlConditions - (optional) The unified access control conditions for the data
- *
- * @return { Promise } The encrypted ciphertext and the hash of the data
- *
- * @throws { Error } if the LIT node client is not ready
- * @throws { Error } if the subnetPubKey is null
- */
- encrypt = async (params: EncryptSdkParams): Promise => {
- // ========== Validate Params ==========
- // -- validate if it's ready
- if (!this.ready) {
- throw new LitNodeClientNotReadyError(
- {},
- '6 LitNodeClient is not ready. Please call await litNodeClient.connect() first.'
- );
- }
-
- // -- validate if this.subnetPubKey is null
- if (!this.subnetPubKey) {
- throw new LitNodeClientNotReadyError({}, 'subnetPubKey cannot be null');
- }
-
- const paramsIsSafe = safeParams({
- functionName: 'encrypt',
- params,
- });
-
- if (!paramsIsSafe) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
- );
- }
-
- // ========== Validate Access Control Conditions Schema ==========
- await validateAccessControlConditions(params);
-
- // ========== Hashing Access Control Conditions =========
- // hash the access control conditions
- const hashOfConditions: ArrayBuffer | undefined =
- await getHashedAccessControlConditions(params);
-
- if (!hashOfConditions) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
- );
- }
-
- const hashOfConditionsStr = uint8arrayToString(
- new Uint8Array(hashOfConditions),
- 'base16'
- );
-
- // ========== Hashing Private Data ==========
- // hash the private data
- const hashOfPrivateData = await crypto.subtle.digest(
- 'SHA-256',
- params.dataToEncrypt
- );
- const hashOfPrivateDataStr = uint8arrayToString(
- new Uint8Array(hashOfPrivateData),
- 'base16'
- );
-
- // ========== Assemble identity parameter ==========
- const identityParam = this._getIdentityParamForEncryption(
- hashOfConditionsStr,
- hashOfPrivateDataStr
- );
-
- // ========== Encrypt ==========
- const ciphertext = await encrypt(
- this.subnetPubKey,
- params.dataToEncrypt,
- uint8arrayFromString(identityParam, 'utf8')
- );
-
- return { ciphertext, dataToEncryptHash: hashOfPrivateDataStr };
- };
-
- /**
- *
- * Decrypt ciphertext with the LIT network.
- *
- */
- decrypt = async (params: DecryptRequest): Promise => {
- const { authContext, authSig, chain, ciphertext, dataToEncryptHash } =
- params;
-
- // ========== Validate Params ==========
- // -- validate if it's ready
- if (!this.ready) {
- throw new LitNodeClientNotReadyError(
- {},
- '6 LitNodeClient is not ready. Please call await litNodeClient.connect() first.'
- );
- }
-
- // -- validate if this.subnetPubKey is null
- if (!this.subnetPubKey) {
- throw new LitNodeClientNotReadyError({}, 'subnetPubKey cannot be null');
- }
-
- const paramsIsSafe = safeParams({
- functionName: 'decrypt',
- params,
- });
-
- if (!paramsIsSafe) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'Parameter validation failed.'
- );
- }
-
- // ========== Hashing Access Control Conditions =========
- // hash the access control conditions
- const hashOfConditions: ArrayBuffer | undefined =
- await getHashedAccessControlConditions(params);
-
- if (!hashOfConditions) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
- );
- }
-
- const hashOfConditionsStr = uint8arrayToString(
- new Uint8Array(hashOfConditions),
- 'base16'
- );
-
- // ========== Formatting Access Control Conditions =========
- const {
- error,
- formattedAccessControlConditions,
- formattedEVMContractConditions,
- formattedSolRpcConditions,
- formattedUnifiedAccessControlConditions,
- }: FormattedMultipleAccs = getFormattedAccessControlConditions(params);
-
- if (error) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
- );
- }
-
- // ========== Assemble identity parameter ==========
- const identityParam = this._getIdentityParamForEncryption(
- hashOfConditionsStr,
- dataToEncryptHash
- );
-
- log('identityParam', identityParam);
-
- let sessionSigs: SessionSigsMap = {};
- const userMaxPrices = await this.getMaxPricesForNodeProduct({
- product: 'DECRYPTION',
- userMaxPrice: params.userMaxPrice,
- });
-
- if (!authSig) {
- if (!authContext) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'Missing auth context; you must provide either authSig or authContext.'
- );
- }
-
- sessionSigs = await this._getSessionSigs({
- ...authContext,
- userMaxPrices,
- });
- }
-
- // ========== Get Network Signature ==========
- const requestId = this._getNewRequestId();
- const nodePromises = this._getNodePromises(
- userMaxPrices.map(({ url }) => url),
- (url: string) => {
- // -- if session key is available, use it
- const authSigToSend = authSig ? authSig : sessionSigs[url];
-
- if (!authSigToSend) {
- throw new InvalidArgumentException(
- {
- info: {
- params,
- },
- },
- 'authSig is required'
- );
- }
-
- const reqBody: EncryptionSignRequest = {
- accessControlConditions: formattedAccessControlConditions,
- evmContractConditions: formattedEVMContractConditions,
- solRpcConditions: formattedSolRpcConditions,
- unifiedAccessControlConditions:
- formattedUnifiedAccessControlConditions,
- dataToEncryptHash,
- chain,
- authSig: authSigToSend,
- epoch: this.currentEpochNumber!,
- };
-
- const urlWithParh = composeLitUrl({
- url,
- endpoint: LIT_ENDPOINT.ENCRYPTION_SIGN,
- });
-
- return this.generatePromise(urlWithParh, reqBody, requestId);
- }
- );
-
- // -- resolve promises
- const res = await this._handleNodePromises(
- nodePromises,
- requestId,
- this._getThreshold()
- );
-
- // -- case: promises rejected
- if (!res.success) {
- this._throwNodeError(res, requestId);
- }
-
- const signatureShares: NodeBlsSigningShare[] = (
- res as SuccessNodePromises
- ).values;
-
- logWithRequestId(requestId, 'signatureShares', signatureShares);
-
- // ========== Result ==========
- const decryptedData = await this._decryptWithSignatureShares(
- this.subnetPubKey,
- uint8arrayFromString(identityParam, 'utf8'),
- ciphertext,
- signatureShares
- );
-
- return { decryptedData };
- };
-
- private _getIdentityParamForEncryption = (
- hashOfConditionsStr: string,
- hashOfPrivateDataStr: string
- ): string => {
- return new LitAccessControlConditionResource(
- `${hashOfConditionsStr}/${hashOfPrivateDataStr}`
- ).getResourceKey();
- };
-
- /** ============================== SESSION ============================== */
-
- /**
- * Sign a session public key using a PKP, which generates an authSig.
- * @returns {Object} An object containing the resulting signature.
- */
- private _signSessionKey = async (
- params: SignSessionKeyProp
- ): Promise => {
- log(`[signSessionKey] params:`, params);
-
- // ========== Validate Params ==========
- // -- validate: If it's NOT ready
- if (!this.ready) {
- throw new LitNodeClientNotReadyError(
- {},
- '[signSessionKey] ]LitNodeClient is not ready. Please call await litNodeClient.connect() first.'
- );
- }
-
- // -- construct SIWE message that will be signed by node to generate an authSig.
- const _expiration =
- params.expiration ||
- new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
-
- // Try to get it from local storage, if not generates one~
- const sessionKey: SessionKeyPair =
- params.sessionKey ?? this._getSessionKey();
- const sessionKeyUri = this._getSessionKeyUri(sessionKey.publicKey);
-
- log(
- `[signSessionKey] sessionKeyUri is not found in params, generating a new one`,
- sessionKeyUri
- );
-
- if (!sessionKeyUri) {
- throw new InvalidParamType(
- {
- info: {
- params,
- },
- },
- '[signSessionKey] sessionKeyUri is not defined. Please provide a sessionKeyUri or a sessionKey.'
- );
- }
-
- // Compute the address from the public key if it's provided. Otherwise, the node will compute it.
- const pkpEthAddress = (function () {
- // prefix '0x' if it's not already prefixed
- params.pkpPublicKey = hexPrefixed(params.pkpPublicKey!);
-
- if (params.pkpPublicKey) return computeAddress(params.pkpPublicKey);
-
- // This will be populated by the node, using dummy value for now.
- return '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
- })();
-
- let siwe_statement = 'Lit Protocol PKP session signature';
- if (params.statement) {
- siwe_statement += ' ' + params.statement;
- log(`[signSessionKey] statement found in params: "${params.statement}"`);
- }
-
- let siweMessage;
-
- const siweParams = {
- domain: params?.domain || globalThis.location?.host || 'litprotocol.com',
- walletAddress: pkpEthAddress,
- statement: siwe_statement,
- uri: sessionKeyUri,
- version: '1',
- chainId: params.chainId ?? 1,
- expiration: _expiration,
- nonce: await this.getLatestBlockhash(),
- };
-
- if (params.resourceAbilityRequests) {
- siweMessage = await createSiweMessageWithRecaps({
- ...siweParams,
- resources: params.resourceAbilityRequests,
- litNodeClient: this,
- });
- } else {
- siweMessage = await createSiweMessage(siweParams);
- }
-
- // This may seem a bit weird because we usually only care about prices for sessionSigs...
- // But this also ensures we use the cheapest nodes and takes care of getting the minNodeCount of node URLs for the operation
- const targetNodePrices = await this.getMaxPricesForNodeProduct({
- product: 'LIT_ACTION',
- });
-
- // ========== Get Node Promises ==========
- // -- fetch shares from nodes
- const body: JsonSignSessionKeyRequestV2 = {
- nodeSet: this._getNodeSet(targetNodePrices.map(({ url }) => url)),
- sessionKey: sessionKeyUri,
- authMethods: params.authMethods,
- ...(params?.pkpPublicKey && { pkpPublicKey: params.pkpPublicKey }),
- siweMessage: siweMessage,
- curveType: LIT_CURVE.BLS,
-
- // -- custom auths
- ...(params?.litActionIpfsId && {
- litActionIpfsId: params.litActionIpfsId,
- }),
- ...(params?.litActionCode && { code: params.litActionCode }),
- ...(params?.jsParams && { jsParams: params.jsParams }),
- ...(this.currentEpochNumber && { epoch: this.currentEpochNumber }),
- signingScheme: LIT_CURVE.BLS,
- };
-
- log(`[signSessionKey] body:`, body);
-
- const requestId = this._getNewRequestId();
- logWithRequestId(requestId, 'signSessionKey body', body);
-
- const targetNodeUrls = targetNodePrices.map(({ url }) => url);
- const nodePromises = this._getNodePromises(
- targetNodeUrls,
- (url: string) => {
- const reqBody: JsonSignSessionKeyRequestV1 = body;
-
- const urlWithPath = composeLitUrl({
- url,
- endpoint: LIT_ENDPOINT.SIGN_SESSION_KEY,
- });
-
- return this.generatePromise(urlWithPath, reqBody, requestId);
- }
- );
-
- // -- resolve promises
- let res;
- try {
- res = await this._handleNodePromises(
- nodePromises,
- requestId,
- this._getThreshold()
- );
- log('signSessionKey node promises:', res);
- } catch (e) {
- logErrorWithRequestId(requestId, e);
- throw new UnknownError(
- {
- info: {
- requestId,
- },
- cause: e,
- },
- 'Error when handling node promises'
- );
- }
-
- logWithRequestId(requestId, 'handleNodePromises res:', res);
-
- // -- case: promises rejected
- if (!res.success) {
- this._throwNodeError(res as RejectedNodePromises, requestId);
- return {} as SignSessionKeyResponse;
- }
-
- const responseData: BlsResponseData[] = res.values as BlsResponseData[];
- logWithRequestId(
- requestId,
- '[signSessionKey] responseData',
- JSON.stringify(responseData, null, 2)
- );
-
- // ========== Extract shares from response data ==========
- // -- 1. combine signed data as a list, and get the signatures from it
- const curveType = responseData[0]?.curveType;
-
- if (curveType === 'ECDSA') {
- throw new Error(
- 'The ECDSA curve type is not supported in this version. Please use version 6.x.x instead.'
- );
- }
-
- log(`[signSessionKey] curveType is "${curveType}"`);
-
- const signedDataList = responseData.map((s) => s.dataSigned);
-
- if (signedDataList.length <= 0) {
- const err = `[signSessionKey] signedDataList is empty.`;
- log(err);
- throw new InvalidSignatureError(
- {
- info: {
- requestId,
- responseData,
- signedDataList,
- },
- },
- err
- );
- }
-
- logWithRequestId(
- requestId,
- '[signSessionKey] signedDataList',
- signedDataList
- );
-
- // -- checking if we have enough shares.
- const validatedSignedDataList = this._validateSignSessionKeyResponseData(
- responseData,
- requestId,
- this._getThreshold()
- );
-
- const blsSignedData: BlsResponseData[] = validatedSignedDataList;
-
- const sigType = mostCommonString(blsSignedData.map((s) => s.curveType));
- log(`[signSessionKey] sigType:`, sigType);
-
- const signatureShares = getBlsSignatures(blsSignedData);
-
- log(`[signSessionKey] signatureShares:`, signatureShares);
-
- const blsCombinedSignature = await combineSignatureShares(signatureShares);
-
- log(`[signSessionKey] blsCombinedSignature:`, blsCombinedSignature);
-
- const publicKey = removeHexPrefix(params.pkpPublicKey);
- log(`[signSessionKey] publicKey:`, publicKey);
-
- const dataSigned = mostCommonString(blsSignedData.map((s) => s.dataSigned));
- log(`[signSessionKey] dataSigned:`, dataSigned);
-
- const mostCommonSiweMessage = mostCommonString(
- blsSignedData.map((s) => s.siweMessage)
- );
-
- log(`[signSessionKey] mostCommonSiweMessage:`, mostCommonSiweMessage);
-
- const signedMessage = normalizeAndStringify(mostCommonSiweMessage!);
-
- log(`[signSessionKey] signedMessage:`, signedMessage);
-
- const signSessionKeyRes: SignSessionKeyResponse = {
- authSig: {
- sig: JSON.stringify({
- ProofOfPossession: blsCombinedSignature,
- }),
- algo: 'LIT_BLS',
- derivedVia: 'lit.bls',
- signedMessage,
- address: computeAddress(hexPrefixed(publicKey)),
- },
- pkpPublicKey: publicKey,
- };
-
- return signSessionKeyRes;
- };
-
- getSignSessionKeyShares = async (
- url: string,
- params: {
- body: {
- sessionKey: string;
- authMethods: AuthMethod[];
- pkpPublicKey?: string;
- authSig?: AuthSig;
- siweMessage: string;
- };
- },
- requestId: string
- ) => {
- log('getSignSessionKeyShares');
- const urlWithPath = composeLitUrl({
- url,
- endpoint: LIT_ENDPOINT.SIGN_SESSION_KEY,
- });
- return await this._sendCommandToNode({
- url: urlWithPath,
- data: params.body,
- requestId,
- });
- };
-
- getMaxPricesForNodeProduct = async ({
- userMaxPrice,
- product,
- }: {
- userMaxPrice?: bigint;
- product: keyof typeof PRODUCT_IDS;
- }) => {
- log('getMaxPricesForNodeProduct()', { product });
- const getUserMaxPrice = () => {
- if (userMaxPrice) {
- log('getMaxPricesForNodeProduct(): User provided maxPrice of', {
- userMaxPrice,
- });
- return userMaxPrice;
- }
-
- if (this.defaultMaxPriceByProduct[product] === -1n) {
- log(
- `getMaxPricesForNodeProduct(): No user-provided maxPrice and no defaultMaxPrice set for ${product}; setting to max value`
- );
-
- return 340_282_366_920_938_463_463_374_607_431_768_211_455n; // Rust U128 max
- }
- return this.defaultMaxPriceByProduct[product];
- };
-
- console.log('getMaxPricesForNodeProduct():', {});
- return getMaxPricesForNodeProduct({
- nodePrices: await this._getNodePrices(),
- userMaxPrice: getUserMaxPrice(),
- productId: PRODUCT_IDS[product],
- numRequiredNodes: this._getThreshold(),
- });
- };
-
- /**
- *
- * Retrieves or generates sessionSigs (think access token) for accessing Lit Network resources.
- *
- * How this function works on a high level:
- * 1. Generate or retrieve [session keys](https://v6-api-doc-lit-js-sdk.vercel.app/interfaces/types_src.SessionKeyPair.html) (a public and private key pair)
- * 2. Generate or retrieve the [`AuthSig`](https://v6-api-doc-lit-js-sdk.vercel.app/interfaces/types_src.AuthSig.html) that specifies the session [abilities](https://v6-api-doc-lit-js-sdk.vercel.app/enums/auth_helpers_src.LitAbility.html)
- * 3. Sign the specific resources with the session key
- *
- * The process follows these steps:
- * 1. Retrieves or generates a session key pair (Ed25519) for the user's device. The session key is either fetched from local storage or newly created if not found. The key does not expire.
- * 2. Generates an authentication signature (`authSig`) by signing an ERC-5573 "Sign-in with Ethereum" message, which includes resource ability requests, capabilities, expiration, the user's device session public key, and a nonce. The `authSig` is retrieved from local storage, and if it has expired, the user will be prompted to re-sign.
- * 3. Uses the session private key to sign the session public key along with the resource ability requests, capabilities, issuedAt, and expiration details. This creates a device-generated signature.
- * 4. Constructs the session signatures (`sessionSigs`) by including the device-generated signature and the original message. The `sessionSigs` provide access to Lit Network features such as `executeJs` and `pkpSign`.
- *
- * See Sequence Diagram: https://www.plantuml.com/plantuml/uml/VPH1RnCn48Nl_XLFlT1Av00eGkm15QKLWY8K9K9SO-rEar4sjcLFalBl6NjJAuaMRl5utfjlPjQvJsAZx7UziQtuY5-9eWaQufQ3TOAR77cJy407Rka6zlNdHTRouUbIzSEtjiTIBUswg5v_NwMnuAVlA9KKFPN3I0x9qSSj7bqNF3iPykl9c4o9oUSJMuElv2XQ8IHAYRt3bluWM8wuVUpUJwVlFjsP8JUh5B_1DyV2AYdD6DjhLsTQTaYd3W3ad28SGWqM997fG5ZrB9DJqOaALuRwH1TMpik8tIYze-E8OrPKU5I6cMqtem2kCqOhr4vdaRAvtSjcoMkTo68scKu_Vi1EPMfrP_xVtj7sFMaHNg-6GVqk0MW0z18uKdVULTvDWtdqko28b7KktvUB2hKOBd1asU2QgDfTzrj7T4bLPdv6TR0zLwPQKkkZpIRTY4CTMbrBpg_VKuXyi49beUAHqIlirOUrL2zq9JPPdpRR5OMLVQGoGlLcjyRyQNv6MHz4W_fG42W--xWhUfNyOxiLL1USS6lRLeyAkYLNjrkVJuClm_qp5I8Lq0krUw7lwIt2DgY9oiozrjA_Yhy0
- *
- * Note: When generating session signatures for different PKPs or auth methods,
- * be sure to call disconnectWeb3 to clear auth signatures stored in local storage
- *
- * @param { AuthenticationContext } params
- *
- * An example of how this function is used can be found in the Lit developer-guides-code repository [here](https://github.com/LIT-Protocol/developer-guides-code/tree/master/session-signatures/getSessionSigs).
- *
- */
- private _getSessionSigs = async (
- params: AuthenticationContext & {
- userMaxPrices: { url: string; price: bigint }[];
- }
- ): Promise => {
- // -- prepare
- // Try to get it from local storage, if not generates one~
- const sessionKey = params.sessionKey ?? this._getSessionKey();
-
- const sessionKeyUri = this._getSessionKeyUri(sessionKey.publicKey);
-
- // First get or generate the session capability object for the specified resources.
- const sessionCapabilityObject = params.sessionCapabilityObject
- ? params.sessionCapabilityObject
- : await generateSessionCapabilityObjectWithWildcards(
- params.resourceAbilityRequests.map((r) => r.resource)
- );
- const expiration = params.expiration || getExpiration();
-
- // -- (TRY) to get the wallet signature
- let authSig = await this._getWalletSig({
- authNeededCallback: params.authNeededCallback,
- chain: params.chain || 'ethereum',
- sessionCapabilityObject,
- switchChain: params.switchChain,
- expiration: expiration,
- sessionKey: sessionKey,
- sessionKeyUri: sessionKeyUri,
- nonce: await this.getLatestBlockhash(),
-
- // -- for recap
- resourceAbilityRequests: params.resourceAbilityRequests,
-
- // -- optional fields
- ...(params.litActionCode && { litActionCode: params.litActionCode }),
- ...(params.litActionIpfsId && {
- litActionIpfsId: params.litActionIpfsId,
- }),
- ...(params.jsParams && { jsParams: params.jsParams }),
- });
-
- const needToResignSessionKey = await this._checkNeedToResignSessionKey({
- authSig,
- sessionKeyUri,
- resourceAbilityRequests: params.resourceAbilityRequests,
- });
-
- // -- (CHECK) if we need to resign the session key
- if (needToResignSessionKey) {
- log('need to re-sign session key. Signing...');
- authSig = await this._authCallbackAndUpdateStorageItem({
- authCallback: params.authNeededCallback,
- authCallbackParams: {
- chain: params.chain || 'ethereum',
- statement: sessionCapabilityObject.statement,
- resources: [sessionCapabilityObject.encodeAsSiweResource()],
- switchChain: params.switchChain,
- expiration,
- sessionKey: sessionKey,
- uri: sessionKeyUri,
- nonce: await this.getLatestBlockhash(),
- resourceAbilityRequests: params.resourceAbilityRequests,
-
- // -- optional fields
- ...(params.litActionCode && { litActionCode: params.litActionCode }),
- ...(params.litActionIpfsId && {
- litActionIpfsId: params.litActionIpfsId,
- }),
- ...(params.jsParams && { jsParams: params.jsParams }),
- },
- });
- }
-
- if (
- authSig.address === '' ||
- authSig.derivedVia === '' ||
- authSig.sig === '' ||
- authSig.signedMessage === ''
- ) {
- throw new WalletSignatureNotFoundError(
- {
- info: {
- authSig,
- },
- },
- 'No wallet signature found'
- );
- }
-
- // ===== AFTER we have Valid Signed Session Key =====
- // - Let's sign the resources with the session key
- // - 5 minutes is the default expiration for a session signature
- // - Because we can generate a new session sig every time the user wants to access a resource without prompting them to sign with their wallet
- const sessionExpiration =
- expiration ?? new Date(Date.now() + 1000 * 60 * 5).toISOString();
-
- const capabilities = params.capabilityAuthSigs
- ? [
- ...(params.capabilityAuthSigs ?? []),
- params.capabilityAuthSigs,
- authSig,
- ]
- : [...(params.capabilityAuthSigs ?? []), authSig];
-
- // This is the template that will be combined with the node address as a single object, then signed by the session key
- // so that the node can verify the session signature
- const sessionSigningTemplate = {
- sessionKey: sessionKey.publicKey,
- resourceAbilityRequests: params.resourceAbilityRequests,
- capabilities,
- issuedAt: new Date().toISOString(),
- expiration: sessionExpiration,
- };
-
- const sessionSigs: SessionSigsMap = {};
-
- // console.log(
- // 'getSessionSigs()',
- // util.inspect(
- // {
- // userMaxPrices: params.userMaxPrices,
- // },
- // { depth: 4 }
- // )
- // );
-
- params.userMaxPrices.forEach(({ url: nodeAddress, price }) => {
- const toSign: SessionSigningTemplate = {
- ...sessionSigningTemplate,
- nodeAddress,
- maxPrice: price.toString(),
- };
-
- log(`Setting maxprice for ${nodeAddress} to `, price.toString());
-
- const signedMessage = JSON.stringify(toSign);
-
- const uint8arrayKey = uint8arrayFromString(
- sessionKey.secretKey,
- 'base16'
- );
-
- const uint8arrayMessage = uint8arrayFromString(signedMessage, 'utf8');
- const signature = nacl.sign.detached(uint8arrayMessage, uint8arrayKey);
-
- sessionSigs[nodeAddress] = {
- sig: uint8arrayToString(signature, 'base16'),
- derivedVia: 'litSessionSignViaNacl',
- signedMessage: signedMessage,
- address: sessionKey.publicKey,
- algo: 'ed25519',
- };
- });
-
- log('sessionSigs:', sessionSigs);
-
- try {
- const formattedSessionSigs = formatSessionSigs(
- JSON.stringify(sessionSigs)
- );
- log(formattedSessionSigs);
- } catch (e) {
- // swallow error
- log('Error formatting session signatures: ', e);
- }
-
- return sessionSigs;
- };
-
- /**
- * Retrieves the PKP sessionSigs.
- *
- * @param params - The parameters for retrieving the PKP sessionSigs.
- * @returns A promise that resolves to the PKP sessionSigs.
- * @throws An error if any of the required parameters are missing or if `litActionCode` and `ipfsId` exist at the same time.
- */
- getPkpAuthContext = (params: AuthenticationContext) => {
- const chain = params?.chain || 'ethereum';
-
- return {
- chain,
- ...params,
- authNeededCallback: async (props: AuthCallbackParams) => {
- // -- validate
- if (!props.expiration) {
- throw new ParamsMissingError(
- {
- info: {
- props,
- },
- },
- '[getPkpSessionSigs/callback] expiration is required'
- );
- }
-
- if (!props.resources) {
- throw new ParamsMissingError(
- {
- info: {
- props,
- },
- },
- '[getPkpSessionSigs/callback]resources is required'
- );
- }
-
- if (!props.resourceAbilityRequests) {
- throw new ParamsMissingError(
- {
- info: {
- props,
- },
- },
- '[getPkpSessionSigs/callback]resourceAbilityRequests is required'
- );
- }
-
- // lit action code and ipfs id cannot exist at the same time
- if (props.litActionCode && props.litActionIpfsId) {
- throw new UnsupportedMethodError(
- {
- info: {
- props,
- },
- },
- '[getPkpSessionSigs/callback]litActionCode and litActionIpfsId cannot exist at the same time'
- );
- }
-
- // Check if IPFS options are provided and if the code should be fetched from IPFS and overwrite the current code.
- // This will fetch the code from the specified IPFS gateway using the provided ipfsId,
- // and update the params with the fetched code, removing the ipfsId afterward.
- const overwriteCode =
- params.ipfsOptions?.overwriteCode ||
- GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK[this.config.litNetwork];
-
- if (overwriteCode && props.litActionIpfsId) {
- const code = await this._getFallbackIpfsCode(
- params.ipfsOptions?.gatewayUrl,
- props.litActionIpfsId
- );
-
- props = {
- ...props,
- litActionCode: code,
- litActionIpfsId: undefined,
- };
- }
-
- /**
- * We must provide an empty array for authMethods even if we are not using any auth methods.
- * So that the nodes can serialize the request correctly.
- */
- const authMethods = params.authMethods || [];
-
- const response = await this._signSessionKey({
- sessionKey: props.sessionKey,
- statement: props.statement || 'Some custom statement.',
- authMethods: [...authMethods],
- pkpPublicKey: params.pkpPublicKey,
- expiration: props.expiration,
- resources: props.resources,
- chainId: 1,
-
- // -- required fields
- resourceAbilityRequests: props.resourceAbilityRequests,
-
- // -- optional fields
- ...(props.litActionCode && { litActionCode: props.litActionCode }),
- ...(props.litActionIpfsId && {
- litActionIpfsId: props.litActionIpfsId,
- }),
- ...(props.jsParams && { jsParams: props.jsParams }),
- });
-
- return response.authSig;
- },
- };
- };
-
- /**
- *
- * Get Session Key URI eg. lit:session:0x1234
- *
- * @param publicKey is the public key of the session key
- * @returns { string } the session key uri
- */
- private _getSessionKeyUri = (publicKey: string): string => {
- return SIWE_URI_PREFIX.SESSION_KEY + publicKey;
- };
-
- /**
- * Authenticates an Auth Method for claiming a Programmable Key Pair (PKP).
- * A {@link MintCallback} can be defined for custom on chain interactions
- * by default the callback will forward to a relay server for minting on chain.
- * @param {ClaimKeyRequest} params an Auth Method and {@link MintCallback}
- * @returns {Promise}
- */
- async claimKeyId(
- params: ClaimRequest
- ): Promise {
- if (!this.ready) {
- const message =
- 'LitNodeClient is not ready. Please call await litNodeClient.connect() first.';
- throw new LitNodeClientNotReadyError({}, message);
- }
-
- if (params.authMethod.authMethodType == AUTH_METHOD_TYPE.WebAuthn) {
- throw new LitNodeClientNotReadyError(
- {},
- 'Unsupported auth method type. Webauthn, and Lit Actions are not supported for claiming'
- );
- }
-
- const requestId = this._getNewRequestId();
-
- // This may seem a bit weird because we usually only care about prices for sessionSigs...
- // But this also ensures we use the cheapest nodes and takes care of getting the minNodeCount of node URLs for the operation
- const targetNodePrices = await this.getMaxPricesForNodeProduct({
- product: 'LIT_ACTION',
- });
-
- const targetNodeUrls = targetNodePrices.map(({ url }) => url);
-
- const nodePromises = this._getNodePromises(
- targetNodeUrls,
- (url: string) => {
- if (!params.authMethod) {
- throw new ParamsMissingError(
- {
- info: {
- params,
- },
- },
- 'authMethod is required'
- );
- }
-
- const reqBody: JsonPKPClaimKeyRequest = {
- authMethod: params.authMethod,
- };
-
- const urlWithPath = composeLitUrl({
- url,
- endpoint: LIT_ENDPOINT.PKP_CLAIM,
- });
-
- return this.generatePromise(urlWithPath, reqBody, requestId);
- }
- );
-
- const responseData = await this._handleNodePromises(
- nodePromises,
- requestId,
- this._getThreshold()
- );
-
- if (responseData.success) {
- const nodeSignatures: Signature[] = responseData.values.map((r) => {
- const sig = ethers.utils.splitSignature(`0x${r.signature}`);
- return {
- r: sig.r,
- s: sig.s,
- v: sig.v,
- };
- });
-
- logWithRequestId(
- requestId,
- `responseData: ${JSON.stringify(responseData, null, 2)}`
- );
-
- const derivedKeyId = responseData.values[0].derivedKeyId;
-
- const pubkey = await this.computeHDPubKey(derivedKeyId);
- logWithRequestId(
- requestId,
- `pubkey ${pubkey} derived from key id ${derivedKeyId}`
- );
-
- const relayParams = params as ClaimRequest<'relay'>;
-
- let mintTx = '';
- if (params.mintCallback && 'signer' in params) {
- mintTx = await params.mintCallback(
- {
- derivedKeyId,
- authMethodType: params.authMethod.authMethodType,
- signatures: nodeSignatures,
- pubkey,
- signer: (params as ClaimRequest<'client'>).signer,
- ...relayParams,
- },
- this.config.litNetwork
- );
- } else {
- mintTx = await defaultMintClaimCallback(
- {
- derivedKeyId,
- authMethodType: params.authMethod.authMethodType,
- signatures: nodeSignatures,
- pubkey,
- ...relayParams,
- },
- this.config.litNetwork
- );
- }
-
- return {
- signatures: nodeSignatures,
- claimedKeyId: derivedKeyId,
- pubkey,
- mintTx,
- };
- } else {
- throw new UnknownError(
- {
- info: {
- requestId,
- responseData,
- },
- },
- `Claim request has failed. Request trace id: lit_%s`,
- requestId
- );
- }
- }
-
- /**
- * Note: ✨ This is to check data integrity of the response from the signSessionKey endpoint.
- * As sometimes the response data structure has changed and we need to update the required fields.
- * Validates the response data from the signSessionKey endpoint.
- * Each response data item must have all required fields and valid ProofOfPossession.
- *
- * @param responseData - Array of BlsResponseData to validate
- * @param requestId - Request ID for logging and error reporting
- * @param threshold - Minimum number of valid responses needed
- * @returns Filtered array of valid BlsResponseData
- * @throws InvalidSignatureError if validation fails
- */
- private _validateSignSessionKeyResponseData(
- responseData: BlsResponseData[],
- requestId: string,
- threshold: number
- ): BlsResponseData[] {
- // each of this field cannot be empty
- const requiredFields = [
- 'signatureShare',
- 'curveType',
- 'siweMessage',
- 'dataSigned',
- 'blsRootPubkey',
- 'result',
- ];
-
- // -- checking if we have enough shares.
- const validatedSignedDataList = responseData
- .map((data: BlsResponseData) => {
- // check if all required fields are present
- for (const field of requiredFields) {
- const key: keyof BlsResponseData = field as keyof BlsResponseData;
-
- if (
- data[key] === undefined ||
- data[key] === null ||
- data[key] === ''
- ) {
- log(
- `Invalid signed data. "${field}" is missing. Not a problem, we only need ${threshold} nodes to sign the session key.`
- );
- return null;
- }
- }
-
- if (!data.signatureShare.ProofOfPossession) {
- const err = `Invalid signed data. "ProofOfPossession" is missing.`;
- log(err);
- throw new InvalidSignatureError(
- {
- info: {
- requestId,
- responseData,
- data,
- },
- },
- err
- );
- }
-
- return data;
- })
- .filter((item) => item !== null);
-
- logWithRequestId(
- requestId,
- 'validated length:',
- validatedSignedDataList.length
- );
- logWithRequestId(requestId, 'minimum threshold:', threshold);
-
- if (validatedSignedDataList.length < threshold) {
- throw new InvalidSignatureError(
- {
- info: {
- requestId,
- responseData,
- validatedSignedDataList,
- threshold,
- },
- },
- `not enough nodes signed the session key. Expected ${threshold}, got ${validatedSignedDataList.length}`
- );
- }
-
- return validatedSignedDataList as BlsResponseData[];
- }
-}
diff --git a/packages/lit-node-client-nodejs/tsconfig.json b/packages/lit-node-client-nodejs/tsconfig.json
deleted file mode 100644
index afa40e9075..0000000000
--- a/packages/lit-node-client-nodejs/tsconfig.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "module": "commonjs",
- "forceConsistentCasingInFileNames": true,
- "strict": true,
- "noImplicitOverride": true,
- "noPropertyAccessFromIndexSignature": true,
- "noImplicitReturns": true,
- "noFallthroughCasesInSwitch": true,
- "lib": ["ES2021", "DOM"]
- },
- "files": [],
- "include": [],
- "references": [
- {
- "path": "./tsconfig.lib.json"
- },
- {
- "path": "./tsconfig.spec.json"
- }
- ]
-}
diff --git a/packages/lit-node-client-nodejs/tsconfig.lib.json b/packages/lit-node-client-nodejs/tsconfig.lib.json
deleted file mode 100644
index e85ef50f65..0000000000
--- a/packages/lit-node-client-nodejs/tsconfig.lib.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "outDir": "../../dist/out-tsc",
- "declaration": true,
- "types": []
- },
- "include": ["**/*.ts"],
- "exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"]
-}
diff --git a/packages/lit-node-client/README.md b/packages/lit-node-client/README.md
index 86ee2ff17e..6e8a8d65b7 100644
--- a/packages/lit-node-client/README.md
+++ b/packages/lit-node-client/README.md
@@ -1,9 +1,21 @@
-# Quick Start
+# Getting Started
-This module is the main module of this monorepo. It sets a default authentication callback using the `checkAndSignAuthMessage` function from the auth-browser submodule, which is designed to work in both browser and Node.js environments, facilitating interaction with Lit nodes.
+This `LitNodeClient` is created solely to run on Node.js.
-### node.js / browser
+The usual `checkAndSignAuthMessage` is not included in this package, so you need to add it manually to the constructor if you decide to use it on a browser, or with any custom auth callback.
-```
-yarn add @lit-protocol/lit-node-client
+```js
+import * as LitJsSdkNodeJs from '@lit-protocol/lit-node-client';
+import { checkAndSignAuthMessage } from '@lit-protocol/auth-browser';
+
+const client = new LitJsSdkNodeJs.LitNodeClient({
+ litNetwork: 'serrano',
+ defaultAuthCallback: checkAndSignAuthMessage,
+});
+
+await client.connect();
+
+const authSig = await checkAndSignAuthMessage({
+ chain: 'ethereum',
+});
```
diff --git a/packages/lit-node-client/jest.config.ts b/packages/lit-node-client/jest.config.ts
index bf0a9ac9bb..d3310ee7a7 100644
--- a/packages/lit-node-client/jest.config.ts
+++ b/packages/lit-node-client/jest.config.ts
@@ -12,10 +12,5 @@ export default {
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/packages/lit-node-client',
- moduleNameMapper: {
- '^ipfs-unixfs-importer':
- 'node_modules/ipfs-unixfs-importer/dist/index.min.js',
- '^blockstore-core': 'node_modules/blockstore-core/dist/index.min.js',
- },
setupFilesAfterEnv: ['../../jest.setup.js'],
};
diff --git a/packages/lit-node-client/package.json b/packages/lit-node-client/package.json
index 014864e988..3b4b2e99c1 100644
--- a/packages/lit-node-client/package.json
+++ b/packages/lit-node-client/package.json
@@ -1,5 +1,6 @@
{
"name": "@lit-protocol/lit-node-client",
+ "type": "commonjs",
"license": "MIT",
"homepage": "https://github.com/Lit-Protocol/js-sdk",
"repository": {
@@ -12,22 +13,17 @@
"bugs": {
"url": "https://github.com/LIT-Protocol/js-sdk/issues"
},
- "type": "commonjs",
"publishConfig": {
"access": "public",
"directory": "../../dist/packages/lit-node-client"
},
- "gitHead": "0d7334c2c55f448e91fe32f29edc5db8f5e09e4b",
- "tags": [
- "universal"
- ],
- "peerDependencies": {
- "tslib": "^2.3.0"
- },
"browser": {
"crypto": false,
"stream": false
},
+ "tags": [
+ "nodejs"
+ ],
"version": "8.0.0-alpha.0",
"main": "./dist/src/index.js",
"typings": "./dist/src/index.d.ts"
diff --git a/packages/lit-node-client/project.json b/packages/lit-node-client/project.json
index 4aee11d45d..ca972315e5 100644
--- a/packages/lit-node-client/project.json
+++ b/packages/lit-node-client/project.json
@@ -29,6 +29,15 @@
"jestConfig": "packages/lit-node-client/jest.config.ts",
"passWithNoTests": true
}
+ },
+ "testWatch": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/packages/lit-node-client"],
+ "options": {
+ "jestConfig": "packages/lit-node-client/jest.config.ts",
+ "watch": true,
+ "passWithNoTests": true
+ }
}
},
"tags": []
diff --git a/packages/lit-node-client/src/index.ts b/packages/lit-node-client/src/index.ts
index 534a93b50a..b98ea523c1 100644
--- a/packages/lit-node-client/src/index.ts
+++ b/packages/lit-node-client/src/index.ts
@@ -1,10 +1,11 @@
+import 'cross-fetch/dist/node-polyfill.js';
+
// ==================== Exports ====================
export * from './lib/lit-node-client';
export {
- checkAndSignAuthMessage,
- ethConnect,
- disconnectWeb3,
-} from '@lit-protocol/auth-browser';
+ hashResourceIdForSigning,
+ humanizeAccessControlConditions,
+} from '@lit-protocol/access-control-conditions';
-export * from '@lit-protocol/lit-node-client-nodejs';
+export { validateSessionSig } from './lib/helpers/session-sigs-validator';
diff --git a/packages/lit-node-client/src/lib/helpers/assemble-most-common-response.test.ts b/packages/lit-node-client/src/lib/helpers/assemble-most-common-response.test.ts
new file mode 100644
index 0000000000..bd27d12437
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/assemble-most-common-response.test.ts
@@ -0,0 +1,159 @@
+import { assembleMostCommonResponse } from './assemble-most-common-response';
+
+describe('assembleMostCommonResponse', () => {
+ it('should return an empty object when given an empty array', () => {
+ const responses: object[] = [];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({});
+ });
+
+ it('should return the correct most common values for simple objects', () => {
+ const responses = [
+ { color: 'red', size: 'large' },
+ { color: 'blue', size: 'medium' },
+ { color: 'red', size: 'large' },
+ { color: 'red', size: 'small' },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ color: 'red', size: 'large' });
+ });
+
+ it('should handle objects with different keys', () => {
+ const responses = [
+ { name: 'Alice', age: 30 },
+ { name: 'Bob', city: 'New York' },
+ { name: 'Alice', city: 'Los Angeles' },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ name: 'Alice', age: 30, city: 'Los Angeles' });
+ });
+
+ it('should handle nested objects correctly', () => {
+ const responses = [
+ {
+ address: { city: 'New York', country: 'USA' },
+ status: 'active',
+ },
+ {
+ address: { city: 'Los Angeles', country: 'USA' },
+ status: 'inactive',
+ },
+ {
+ address: { city: 'New York', country: 'Canada' },
+ status: 'active',
+ },
+ {
+ address: { city: 'New York', country: 'USA' },
+ status: 'active',
+ },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({
+ address: { city: 'New York', country: 'USA' },
+ status: 'active',
+ });
+ });
+
+ it('should handle undefined and empty string values', () => {
+ const responses = [
+ { name: 'Alice', value: undefined },
+ { name: 'Bob', value: 'test' },
+ { name: 'Alice', value: '' },
+ { name: 'Alice', value: 'test' },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ name: 'Alice', value: 'test' });
+ });
+
+ it('should handle undefined and empty string values in nested object', () => {
+ const responses = [
+ { person: { name: 'Alice', value: undefined } },
+ { person: { name: 'Bob', value: 'test' } },
+ { person: { name: 'Alice', value: '' } },
+ { person: { name: 'Alice', value: 'test' } },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ person: { name: 'Alice', value: 'test' } });
+ });
+
+ it('should return undefined if all values are undefined or empty string', () => {
+ const responses = [
+ { name: 'Alice', value: undefined },
+ { name: 'Bob', value: '' },
+ { name: 'Alice', value: undefined },
+ { name: 'Alice', value: '' },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ name: 'Alice', value: undefined });
+ });
+
+ it('should handle nested object with different depth', () => {
+ const responses = [
+ { data: { level1: { level2: 'value1' } } },
+ { data: { level1: 'value2' } },
+ { data: { level1: { level2: 'value1' } } },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ data: { level1: { level2: 'value1' } } });
+ });
+
+ it('should handle arrays of different types', () => {
+ const responses = [
+ { name: 'Alice', tags: ['tag1', 'tag2'] },
+ { name: 'Bob', tags: ['tag2', 'tag3'] },
+ { name: 'Alice', tags: ['tag1', 'tag2'] },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ name: 'Alice', tags: ['tag1', 'tag2'] });
+ });
+ it('should handle arrays with mixed value types', () => {
+ const responses = [
+ {
+ name: 'Alice',
+ value: 10,
+ other: true,
+ values: [1, 2, '3'],
+ },
+ {
+ name: 'Bob',
+ value: 10,
+ other: false,
+ values: [2, 3, '4'],
+ },
+ {
+ name: 'Alice',
+ value: 10,
+ other: true,
+ values: [1, 2, '3'],
+ },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({
+ name: 'Alice',
+ value: 10,
+ other: true,
+ values: [1, 2, '3'],
+ });
+ });
+
+ it('should handle ties by choosing the last encountered value', () => {
+ const responses = [
+ { color: 'red', size: 'small' },
+ { color: 'blue', size: 'large' },
+ { color: 'red', size: 'large' },
+ { color: 'blue', size: 'small' },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ color: 'blue', size: 'small' });
+ });
+ it('should handle ties in nested objects by choosing the last encountered value', () => {
+ const responses = [
+ { data: { color: 'red', size: 'small' } },
+ { data: { color: 'blue', size: 'large' } },
+ { data: { color: 'red', size: 'large' } },
+ { data: { color: 'blue', size: 'small' } },
+ ];
+ const result = assembleMostCommonResponse(responses);
+ expect(result).toEqual({ data: { color: 'blue', size: 'small' } });
+ });
+});
diff --git a/packages/lit-node-client/src/lib/helpers/assemble-most-common-response.ts b/packages/lit-node-client/src/lib/helpers/assemble-most-common-response.ts
new file mode 100644
index 0000000000..f710df35bd
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/assemble-most-common-response.ts
@@ -0,0 +1,37 @@
+import { mostCommonValue } from '@lit-protocol/core';
+
+export const assembleMostCommonResponse = (responses: object[]): object => {
+ const result: Record = {};
+
+ // Aggregate all values for each key across all responses
+ const keys = new Set(responses.flatMap(Object.keys));
+
+ for (const key of keys) {
+ const values = responses.map(
+ (response: Record) => response[key]
+ );
+
+ // Filter out undefined first and unmatching type values after before processing
+ const definedValues = values.filter(
+ (value) => value !== undefined && value !== ''
+ );
+ const valuesType = mostCommonValue(
+ definedValues.map((value) => typeof value)
+ );
+ const filteredValues = values.filter(
+ (value) => typeof value === valuesType
+ );
+
+ if (filteredValues.length === 0) {
+ result[key] = undefined; // or set a default value if needed
+ } else if (valuesType === 'object' && !Array.isArray(filteredValues[0])) {
+ // Recursive case for objects
+ result[key] = assembleMostCommonResponse(filteredValues);
+ } else {
+ // Most common element from filtered values
+ result[key] = mostCommonValue(filteredValues);
+ }
+ }
+
+ return result;
+};
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/encode-code.test.ts b/packages/lit-node-client/src/lib/helpers/encode-code.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/encode-code.test.ts
rename to packages/lit-node-client/src/lib/helpers/encode-code.test.ts
diff --git a/packages/lit-node-client/src/lib/helpers/encode-code.ts b/packages/lit-node-client/src/lib/helpers/encode-code.ts
new file mode 100644
index 0000000000..a8090b82d7
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/encode-code.ts
@@ -0,0 +1,9 @@
+/**
+ * Encodes the given code string into base64 format.
+ *
+ * @param code - The code string to be encoded.
+ * @returns The encoded code string in base64 format.
+ */
+export const encodeCode = (code: string) => {
+ return Buffer.from(code, 'utf8').toString('base64');
+};
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-bls-signatures.test.ts b/packages/lit-node-client/src/lib/helpers/get-bls-signatures.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-bls-signatures.test.ts
rename to packages/lit-node-client/src/lib/helpers/get-bls-signatures.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-bls-signatures.ts b/packages/lit-node-client/src/lib/helpers/get-bls-signatures.ts
similarity index 63%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-bls-signatures.ts
rename to packages/lit-node-client/src/lib/helpers/get-bls-signatures.ts
index dcfdcecc1e..3d8ce64ed1 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/get-bls-signatures.ts
+++ b/packages/lit-node-client/src/lib/helpers/get-bls-signatures.ts
@@ -1,4 +1,4 @@
-import { log } from '@lit-protocol/misc';
+import { InvalidArgumentException } from '@lit-protocol/constants';
import { BlsResponseData, BlsSignatureShare } from '@lit-protocol/types';
/**
@@ -11,7 +11,14 @@ export function getBlsSignatures(
responseData: BlsResponseData[]
): BlsSignatureShare[] {
if (!responseData) {
- throw new Error('[getBlsSignatures] No data provided');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ responseData,
+ },
+ },
+ '[getBlsSignatures] No data provided'
+ );
}
const signatureShares = responseData.map((s) => ({
@@ -21,10 +28,15 @@ export function getBlsSignatures(
},
}));
- log(`[getBlsSignatures] signatureShares:`, signatureShares);
-
if (!signatureShares || signatureShares.length <= 0) {
- throw new Error('[getBlsSignatures] No signature shares provided');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ signatureShares,
+ },
+ },
+ '[getBlsSignatures] No signature shares provided'
+ );
}
return signatureShares;
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-claims-list.test.ts b/packages/lit-node-client/src/lib/helpers/get-claims-list.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-claims-list.test.ts
rename to packages/lit-node-client/src/lib/helpers/get-claims-list.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-claims-list.ts b/packages/lit-node-client/src/lib/helpers/get-claims-list.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-claims-list.ts
rename to packages/lit-node-client/src/lib/helpers/get-claims-list.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-claims.test.ts b/packages/lit-node-client/src/lib/helpers/get-claims.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-claims.test.ts
rename to packages/lit-node-client/src/lib/helpers/get-claims.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-claims.ts b/packages/lit-node-client/src/lib/helpers/get-claims.ts
similarity index 99%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-claims.ts
rename to packages/lit-node-client/src/lib/helpers/get-claims.ts
index 8bc984efe4..56eb8a0392 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/get-claims.ts
+++ b/packages/lit-node-client/src/lib/helpers/get-claims.ts
@@ -1,6 +1,7 @@
-import { Signature } from '@lit-protocol/types';
import { ethers } from 'ethers';
+import { Signature } from '@lit-protocol/types';
+
/**
* Retrieves the claims from an array of objects and organizes them into a record.
* Each claim is associated with its corresponding signatures and derived key ID.
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-expiration.ts b/packages/lit-node-client/src/lib/helpers/get-expiration.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-expiration.ts
rename to packages/lit-node-client/src/lib/helpers/get-expiration.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-max-prices-for-node-product.ts b/packages/lit-node-client/src/lib/helpers/get-max-prices-for-node-product.ts
similarity index 96%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-max-prices-for-node-product.ts
rename to packages/lit-node-client/src/lib/helpers/get-max-prices-for-node-product.ts
index e0e8c5bfb3..f657edfe78 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/get-max-prices-for-node-product.ts
+++ b/packages/lit-node-client/src/lib/helpers/get-max-prices-for-node-product.ts
@@ -55,8 +55,6 @@ export function getMaxPricesForNodeProduct({
* our request to fail if the price on some of the nodes is higher than we think it was, as long as it's not
* drastically different than we expect it to be
*/
- // console.log('totalBaseCost:', totalBaseCost);
- // console.log('userMaxPrice:', userMaxPrice);
const excessBalance = userMaxPrice - totalBaseCost;
// Map matching the keys from `nodePrices`, but w/ the per-node maxPrice computed based on `userMaxPrice`
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-max-prices-for-nodes.test.ts b/packages/lit-node-client/src/lib/helpers/get-max-prices-for-nodes.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-max-prices-for-nodes.test.ts
rename to packages/lit-node-client/src/lib/helpers/get-max-prices-for-nodes.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-signatures.test.ts b/packages/lit-node-client/src/lib/helpers/get-signatures.test.ts
similarity index 95%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-signatures.test.ts
rename to packages/lit-node-client/src/lib/helpers/get-signatures.test.ts
index a0177e3227..d776abf761 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/get-signatures.test.ts
+++ b/packages/lit-node-client/src/lib/helpers/get-signatures.test.ts
@@ -1,7 +1,4 @@
-import {
- EcdsaSignedMessageShareParsed,
- SigResponse,
-} from '@lit-protocol/types';
+import { EcdsaSignedMessageShareParsed } from '@lit-protocol/types';
import { getSignatures } from './get-signatures';
@@ -51,8 +48,6 @@ describe('getSignatures', () => {
requestId,
});
- console.log('signatures:', signatures);
-
expect(signatures).toHaveProperty('publicKey');
expect(signatures).toHaveProperty('r');
expect(signatures).toHaveProperty('recid');
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/get-signatures.ts b/packages/lit-node-client/src/lib/helpers/get-signatures.ts
similarity index 80%
rename from packages/lit-node-client-nodejs/src/lib/helpers/get-signatures.ts
rename to packages/lit-node-client/src/lib/helpers/get-signatures.ts
index 77941e63b5..bb50181fe5 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/get-signatures.ts
+++ b/packages/lit-node-client/src/lib/helpers/get-signatures.ts
@@ -1,24 +1,18 @@
-import { joinSignature } from 'ethers/lib/utils';
-
import {
CURVE_GROUP_BY_CURVE_TYPE,
LIT_CURVE_VALUES,
+ InvalidArgumentException,
NoValidShares,
ParamNullError,
- UnknownSignatureError,
UnknownSignatureType,
CurveTypeNotFoundError,
} from '@lit-protocol/constants';
+import { mostCommonValue } from '@lit-protocol/core';
import { combineEcdsaShares } from '@lit-protocol/crypto';
-import {
- logErrorWithRequestId,
- logWithRequestId,
- mostCommonString,
-} from '@lit-protocol/misc';
+import { logger } from '@lit-protocol/logger';
import {
EcdsaSignedMessageShareParsed,
SigResponse,
- SigShare,
} from '@lit-protocol/types';
/**
@@ -42,7 +36,8 @@ export const getSignatures = async (params: {
signedMessageShares: EcdsaSignedMessageShareParsed[];
requestId: string;
}): Promise => {
- let { networkPubKeySet, threshold, signedMessageShares, requestId } = params;
+ const { networkPubKeySet, threshold, signedMessageShares, requestId } =
+ params;
if (networkPubKeySet === null) {
throw new ParamNullError(
@@ -56,10 +51,11 @@ export const getSignatures = async (params: {
}
if (signedMessageShares.length < threshold) {
- logErrorWithRequestId(
+ logger.error({
+ function: 'getSignatures',
requestId,
- `not enough nodes to get the signatures. Expected ${threshold}, got ${signedMessageShares.length}`
- );
+ msg: `not enough nodes to get the signatures. Expected ${threshold}, got ${signedMessageShares.length}`,
+ });
throw new NoValidShares(
{
@@ -105,15 +101,24 @@ export const getSignatures = async (params: {
// -- combine
const combinedSignature = await combineEcdsaShares(signedMessageShares);
- const _publicKey = mostCommonString(
+ const _publicKey = mostCommonValue(
signedMessageShares.map((s) => s.publicKey)
);
- const _dataSigned = mostCommonString(
+ const _dataSigned = mostCommonValue(
signedMessageShares.map((s) => s.dataSigned)
);
if (!_publicKey || !_dataSigned) {
- throw new Error('No valid publicKey or dataSigned found');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ requestId,
+ publicKey: _publicKey,
+ dataSigned: _dataSigned,
+ },
+ },
+ 'No valid publicKey or dataSigned found'
+ );
}
const sigResponse: SigResponse = {
diff --git a/packages/lit-node-client/src/lib/helpers/hex.test.ts b/packages/lit-node-client/src/lib/helpers/hex.test.ts
new file mode 100644
index 0000000000..b857529b1d
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/hex.test.ts
@@ -0,0 +1,55 @@
+import { numberToHex, hexPrefixed, removeHexPrefix } from './hex';
+
+describe('Hex Helpers', () => {
+ describe('numberToHex', () => {
+ it('should convert a number to a hex string prefixed with 0x', () => {
+ expect(numberToHex(255)).toBe('0xff');
+ });
+
+ it('should convert zero correctly', () => {
+ expect(numberToHex(0)).toBe('0x0');
+ });
+
+ it('should convert a larger number correctly', () => {
+ expect(numberToHex(4095)).toBe('0xfff');
+ });
+ });
+
+ describe('hexPrefixed', () => {
+ it('should return the string unchanged if it already has 0x prefix', () => {
+ expect(hexPrefixed('0xabcdef')).toBe('0xabcdef');
+ });
+
+ it('should add 0x prefix if not present', () => {
+ expect(hexPrefixed('abcdef')).toBe('0xabcdef');
+ });
+
+ it('should add 0x prefix to an empty string', () => {
+ expect(hexPrefixed('')).toBe('0x');
+ });
+ });
+
+ describe('removeHexPrefix', () => {
+ it('should remove the hex prefix from a string that starts with 0x', () => {
+ const input = '0xabcdef';
+ const expectedOutput = 'abcdef';
+ expect(removeHexPrefix(input)).toBe(expectedOutput);
+ });
+
+ it('should return the string unchanged if no 0x prefix is present', () => {
+ const input = 'abcdef';
+ const expectedOutput = 'abcdef';
+ expect(removeHexPrefix(input)).toBe(expectedOutput);
+ });
+
+ it('should not remove prefix if it is uppercase 0X (not valid)', () => {
+ // The helper checks only for lowercase '0x'
+ const input = '0XABCDEF';
+ expect(removeHexPrefix(input)).toBe('0XABCDEF');
+ });
+
+ it('should handle an empty string', () => {
+ expect(removeHexPrefix('')).toBe('');
+ });
+ });
+});
diff --git a/packages/lit-node-client/src/lib/helpers/hex.ts b/packages/lit-node-client/src/lib/helpers/hex.ts
new file mode 100644
index 0000000000..e451013de8
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/hex.ts
@@ -0,0 +1,38 @@
+import { Hex } from '@lit-protocol/types';
+
+/**
+ *
+ * Convert number to hex
+ * @param { number } v
+ * @return { string } hex value prefixed with 0x
+ */
+export const numberToHex = (v: number): Hex => {
+ return `0x${v.toString(16)}`;
+};
+
+/**
+ * Adds a '0x' prefix to a string if it doesn't already have one.
+ * @param str - The input string.
+ * @returns The input string with a '0x' prefix.
+ */
+export const hexPrefixed = (str: string): Hex => {
+ if (str.startsWith('0x')) {
+ return str as Hex;
+ }
+
+ return ('0x' + str) as Hex;
+};
+
+/**
+ * Removes the '0x' prefix from a hexadecimal string if it exists.
+ *
+ * @param str - The input string.
+ * @returns The input string with the '0x' prefix removed, if present.
+ */
+export const removeHexPrefix = (str: string) => {
+ if (str.startsWith('0x')) {
+ return str.slice(2);
+ }
+
+ return str;
+};
diff --git a/packages/lit-node-client/src/lib/helpers/mint-claim-callback.ts b/packages/lit-node-client/src/lib/helpers/mint-claim-callback.ts
new file mode 100644
index 0000000000..494787764b
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/mint-claim-callback.ts
@@ -0,0 +1,95 @@
+import {
+ InvalidArgumentException,
+ LIT_NETWORK,
+ LIT_NETWORK_VALUES,
+ NetworkError,
+ RELAYER_URL_BY_NETWORK,
+ WrongNetworkException,
+} from '@lit-protocol/constants';
+import { logger } from '@lit-protocol/logger';
+import {
+ ClaimResult,
+ MintCallback,
+ RelayClaimProcessor,
+} from '@lit-protocol/types';
+
+/**
+ * Checks if the given LIT_NETWORK value is supported.
+ * @param litNetwork - The Lit Network value to check.
+ * @throws {Error} - Throws an error if the Lit Network value is not supported.
+ */
+export function isSupportedLitNetwork(
+ litNetwork: LIT_NETWORK_VALUES
+): asserts litNetwork is LIT_NETWORK_VALUES {
+ const supportedNetworks = Object.values(LIT_NETWORK);
+
+ if (!supportedNetworks.includes(litNetwork)) {
+ throw new WrongNetworkException(
+ {
+ info: {
+ litNetwork,
+ supportedNetworks,
+ },
+ },
+ `Unsupported LitNetwork! (${supportedNetworks.join('|')}) are supported.`
+ );
+ }
+}
+
+export const defaultMintClaimCallback: MintCallback<
+ RelayClaimProcessor
+> = async (
+ params: ClaimResult,
+ network: LIT_NETWORK_VALUES = LIT_NETWORK.NagaDev
+): Promise => {
+ isSupportedLitNetwork(network);
+
+ const AUTH_CLAIM_PATH = '/auth/claim';
+
+ const relayUrl: string = params.relayUrl || RELAYER_URL_BY_NETWORK[network];
+
+ if (!relayUrl) {
+ throw new InvalidArgumentException(
+ {
+ info: {
+ network,
+ relayUrl,
+ },
+ },
+ 'No relayUrl provided and no default relayUrl found for network'
+ );
+ }
+
+ const relayUrlWithPath = relayUrl + AUTH_CLAIM_PATH;
+
+ const response = await fetch(relayUrlWithPath, {
+ method: 'POST',
+ body: JSON.stringify(params),
+ headers: {
+ 'api-key': params.relayApiKey
+ ? params.relayApiKey
+ : '67e55044-10b1-426f-9247-bb680e5fe0c8_relayer',
+ 'Content-Type': 'application/json',
+ },
+ });
+
+ if (response.status < 200 || response.status >= 400) {
+ const errResp = (await response.json()) ?? '';
+ const errStmt = `An error occurred requesting "/auth/claim" endpoint ${JSON.stringify(
+ errResp
+ )}`;
+ logger.warn(errStmt);
+ throw new NetworkError(
+ {
+ info: {
+ response,
+ errResp,
+ },
+ },
+ `An error occurred requesting "/auth/claim" endpoint`
+ );
+ }
+
+ const body = await response.json();
+ return body.requestId;
+};
diff --git a/packages/lit-node-client/src/lib/helpers/normalize-and-stringify.test.ts b/packages/lit-node-client/src/lib/helpers/normalize-and-stringify.test.ts
new file mode 100644
index 0000000000..0d720c3390
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/normalize-and-stringify.test.ts
@@ -0,0 +1,78 @@
+import { normalizeAndStringify } from './normalize-and-stringify';
+
+describe('normalizeAndStringify', () => {
+ it('should return a non-JSON string unchanged', () => {
+ const input = 'Hello, world!';
+ expect(normalizeAndStringify(input)).toBe(input);
+ });
+
+ it('should parse and stringify a valid JSON object', () => {
+ const input = '{"a": "b"}';
+ // JSON.stringify removes spaces so the output will be: {"a":"b"}
+ expect(normalizeAndStringify(input)).toBe('{"a":"b"}');
+ });
+
+ it('should parse and stringify a valid JSON array', () => {
+ const input = '[1, 2, 3]';
+ expect(normalizeAndStringify(input)).toBe('[1,2,3]');
+ });
+
+ it('should normalize an overly escaped JSON object', () => {
+ // The input string is overly escaped.
+ // The literal here represents: {\"a\":\"b\"}
+ const input = '{\\"a\\":\\"b\\"}';
+ expect(normalizeAndStringify(input)).toBe('{"a":"b"}');
+ });
+
+ it('should normalize an overly escaped JSON array', () => {
+ // The literal represents: [\"a\",\"b\"]
+ const input = '[\\"a\\",\\"b\\"]';
+ expect(normalizeAndStringify(input)).toBe('["a","b"]');
+ });
+
+ it('should return a malformed JSON string as is', () => {
+ // Even though it starts with '{', it's not valid JSON and cannot be normalized.
+ const input = '{not a json}';
+ expect(normalizeAndStringify(input)).toBe(input);
+ });
+
+ it('should return an empty string unchanged', () => {
+ const input = '';
+ expect(normalizeAndStringify(input)).toBe('');
+ });
+
+ it('should recursively normalize multiple levels of escaping', () => {
+ // This input is escaped twice:
+ // The literal represents: {\\\"a\\\":\\\"b\\\"}
+ // After one unescape, it becomes: {\"a\":\"b\"} which is still not valid JSON,
+ // so it needs a second unescape to yield valid JSON {"a":"b"}.
+ const input = '{\\\\\\"a\\\\\\":\\\\\\"b\\\\\\"}';
+ expect(normalizeAndStringify(input)).toBe('{"a":"b"}');
+ });
+
+ describe('double escaped JSON string', () => {
+ test('A doubly escaped JSON string', () => {
+ const doublyEscapedJson = '{\\"key\\": \\"value\\"}';
+ expect(normalizeAndStringify(doublyEscapedJson)).toBe('{"key":"value"}');
+ });
+
+ test('A triply escaped JSON string', () => {
+ const triplyEscapedJson = '{\\\\\\"key\\\\\\": \\\\\\"value\\\\\\"}';
+ expect(normalizeAndStringify(triplyEscapedJson)).toBe('{"key":"value"}');
+ });
+
+ test('A correctly escaped JSON string (for comparison)', () => {
+ const correctlyEscapedJson = '{"key":"value"}';
+ expect(normalizeAndStringify(correctlyEscapedJson)).toBe(
+ '{"key":"value"}'
+ );
+ });
+
+ test('regular siwe message', () => {
+ const regularString =
+ 'litprotocol.com wants you to sign in with your Ethereum account:\\n0x3edB...';
+
+ expect(normalizeAndStringify(regularString)).toBe(regularString);
+ });
+ });
+});
diff --git a/packages/lit-node-client/src/lib/helpers/normalize-and-stringify.ts b/packages/lit-node-client/src/lib/helpers/normalize-and-stringify.ts
new file mode 100644
index 0000000000..a10312b2e6
--- /dev/null
+++ b/packages/lit-node-client/src/lib/helpers/normalize-and-stringify.ts
@@ -0,0 +1,37 @@
+/**
+ * Attempts to normalize a string by unescaping it until it can be parsed as a JSON object,
+ * then stringifies it exactly once. If the input is a regular string that does not represent
+ * a JSON object or array, the function will return it as is without modification.
+ * This function is designed to handle cases where strings might be excessively escaped due
+ * to multiple layers of encoding, ensuring that JSON data is stored in a consistent and
+ * predictable format, and regular strings are left unchanged.
+ *
+ * @param input The potentially excessively escaped string.
+ * @return A string that is either the JSON.stringify version of the original JSON object
+ * or the original string if it does not represent a JSON object or array.
+ */
+export function normalizeAndStringify(input: string): string {
+ try {
+ // Directly return the string if it's not in a JSON format
+ if (!input.startsWith('{') && !input.startsWith('[')) {
+ return input;
+ }
+
+ // Attempt to parse the input as JSON
+ const parsed = JSON.parse(input);
+
+ // If parsing succeeds, return the stringified version of the parsed JSON
+ return JSON.stringify(parsed);
+ } catch (error) {
+ // If parsing fails, it might be due to extra escaping
+ const unescaped = input.replace(/\\(.)/g, '$1');
+
+ // If unescaping doesn't change the string, return it as is
+ if (input === unescaped) {
+ return input;
+ }
+
+ // Otherwise, recursively call the function with the unescaped string
+ return normalizeAndStringify(unescaped);
+ }
+}
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/normalize-array.test.ts b/packages/lit-node-client/src/lib/helpers/normalize-array.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/normalize-array.test.ts
rename to packages/lit-node-client/src/lib/helpers/normalize-array.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/normalize-array.ts b/packages/lit-node-client/src/lib/helpers/normalize-array.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/normalize-array.ts
rename to packages/lit-node-client/src/lib/helpers/normalize-array.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/normalize-params.test.ts b/packages/lit-node-client/src/lib/helpers/normalize-params.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/normalize-params.test.ts
rename to packages/lit-node-client/src/lib/helpers/normalize-params.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/normalize-params.ts b/packages/lit-node-client/src/lib/helpers/normalize-params.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/normalize-params.ts
rename to packages/lit-node-client/src/lib/helpers/normalize-params.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/parse-as-json-or-string.test.ts b/packages/lit-node-client/src/lib/helpers/parse-as-json-or-string.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/parse-as-json-or-string.test.ts
rename to packages/lit-node-client/src/lib/helpers/parse-as-json-or-string.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/parse-as-json-or-string.ts b/packages/lit-node-client/src/lib/helpers/parse-as-json-or-string.ts
similarity index 61%
rename from packages/lit-node-client-nodejs/src/lib/helpers/parse-as-json-or-string.ts
rename to packages/lit-node-client/src/lib/helpers/parse-as-json-or-string.ts
index c980d2fea7..790f6f2b1b 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/parse-as-json-or-string.ts
+++ b/packages/lit-node-client/src/lib/helpers/parse-as-json-or-string.ts
@@ -1,4 +1,4 @@
-import { log } from '@lit-protocol/misc';
+import { logger } from '@lit-protocol/logger';
/**
* Parses a response string into a JS object.
@@ -12,10 +12,11 @@ export const parseAsJsonOrString = (
try {
return JSON.parse(responseString);
} catch (e) {
- log(
- '[parseResponses] Error parsing response as json. Swallowing and returning as string.',
- responseString
- );
+ logger.warn({
+ function: 'parseAsJsonOrString',
+ msg: 'Error parsing response as json. Swallowing and returning as string.',
+ responseString,
+ });
return responseString;
}
};
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/parse-pkp-sign-response.test.ts b/packages/lit-node-client/src/lib/helpers/parse-pkp-sign-response.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/parse-pkp-sign-response.test.ts
rename to packages/lit-node-client/src/lib/helpers/parse-pkp-sign-response.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/parse-pkp-sign-response.ts b/packages/lit-node-client/src/lib/helpers/parse-pkp-sign-response.ts
similarity index 93%
rename from packages/lit-node-client-nodejs/src/lib/helpers/parse-pkp-sign-response.ts
rename to packages/lit-node-client/src/lib/helpers/parse-pkp-sign-response.ts
index 1261842705..9d594a7b0f 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/parse-pkp-sign-response.ts
+++ b/packages/lit-node-client/src/lib/helpers/parse-pkp-sign-response.ts
@@ -1,3 +1,4 @@
+import { InvalidArgumentException } from '@lit-protocol/constants';
import {
EcdsaSignedMessageShareParsed,
PKPSignEndpointResponse,
@@ -76,7 +77,14 @@ export const parsePkpSignResponse = (
: signatureShare;
if (!resolvedShare || typeof resolvedShare !== 'object') {
- throw new Error('Invalid signatureShare structure.');
+ throw new InvalidArgumentException(
+ {
+ info: {
+ signatureShare,
+ },
+ },
+ 'Invalid signatureShare structure.'
+ );
}
const camelCaseShare = convertKeysToCamelCase(resolvedShare);
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/pocess-lit-action-response-strategy.spec.ts b/packages/lit-node-client/src/lib/helpers/pocess-lit-action-response-strategy.spec.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/pocess-lit-action-response-strategy.spec.ts
rename to packages/lit-node-client/src/lib/helpers/pocess-lit-action-response-strategy.spec.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/process-lit-action-response-strategy.ts b/packages/lit-node-client/src/lib/helpers/process-lit-action-response-strategy.ts
similarity index 65%
rename from packages/lit-node-client-nodejs/src/lib/helpers/process-lit-action-response-strategy.ts
rename to packages/lit-node-client/src/lib/helpers/process-lit-action-response-strategy.ts
index 4d725ffeda..34f9117921 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/process-lit-action-response-strategy.ts
+++ b/packages/lit-node-client/src/lib/helpers/process-lit-action-response-strategy.ts
@@ -1,20 +1,16 @@
-import {
- LitActionResponseStrategy,
- ResponseStrategy,
- NodeShare,
-} from '@lit-protocol/types';
-import { log, logError } from '@lit-protocol/misc';
+import { logger } from '@lit-protocol/logger';
+import { LitActionResponseStrategy, NodeShare } from '@lit-protocol/types';
/**
* Finds the most and least common object within an of objects array
- * @param responses any[]
- * @returns an object which contains both the least and most occuring item in the array
+ * @param responses T[]
+ * @returns an object which contains both the least and most occurring T items in the array
*/
-const _findFrequency = (responses: string[]): { min: any; max: any } => {
+const _findFrequency = (responses: T[]): { min: T; max: T } => {
const sorted = responses.sort(
- (a: any, b: any) =>
- responses.filter((v: any) => v === a).length -
- responses.filter((v: any) => v === b).length
+ (a, b) =>
+ responses.filter((v) => v === a).length -
+ responses.filter((v) => v === b).length
);
return { min: sorted[0], max: sorted[sorted?.length - 1] };
@@ -23,7 +19,7 @@ const _findFrequency = (responses: string[]): { min: any; max: any } => {
export const processLitActionResponseStrategy = (
responses: NodeShare[],
strategy: LitActionResponseStrategy
-): any => {
+) => {
const executionResponses = responses.map((nodeResp) => {
return nodeResp.response;
});
@@ -38,33 +34,34 @@ export const processLitActionResponseStrategy = (
strategy?.customFilter(executionResponses);
return customResponseFilterResult;
} else {
- logError(
+ logger.error(
'Custom filter specified for response strategy but none found. using most common'
);
}
} catch (e) {
- logError(
- 'Error while executing custom response filter, defaulting to most common',
- (e as Error).toString()
- );
+ logger.error({
+ function: 'processLitActionResponseStrategy',
+ msg: 'Error while executing custom response filter, defaulting to most common',
+ error: (e as Error).toString(),
+ });
}
}
- let respFrequency = _findFrequency(copiedExecutionResponses);
+ const respFrequency = _findFrequency(copiedExecutionResponses);
if (strategy?.strategy === 'leastCommon') {
- log(
+ logger.info(
'strategy found to be most common, taking most common response from execution results'
);
return respFrequency.min;
} else if (strategy?.strategy === 'mostCommon') {
- log(
+ logger.info(
'strategy found to be most common, taking most common response from execution results'
);
return respFrequency.max;
} else {
- log(
+ logger.info(
'no strategy found, using least common response object from execution results'
);
- respFrequency.min;
+ return respFrequency.min;
}
};
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/remove-double-quotes.test.ts b/packages/lit-node-client/src/lib/helpers/remove-double-quotes.test.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/remove-double-quotes.test.ts
rename to packages/lit-node-client/src/lib/helpers/remove-double-quotes.test.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/remove-double-quotes.ts b/packages/lit-node-client/src/lib/helpers/remove-double-quotes.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/remove-double-quotes.ts
rename to packages/lit-node-client/src/lib/helpers/remove-double-quotes.ts
diff --git a/packages/misc/src/lib/helper/session-sigs-reader.test.ts b/packages/lit-node-client/src/lib/helpers/session-sigs-reader.test.ts
similarity index 100%
rename from packages/misc/src/lib/helper/session-sigs-reader.test.ts
rename to packages/lit-node-client/src/lib/helpers/session-sigs-reader.test.ts
diff --git a/packages/misc/src/lib/helper/session-sigs-reader.ts b/packages/lit-node-client/src/lib/helpers/session-sigs-reader.ts
similarity index 85%
rename from packages/misc/src/lib/helper/session-sigs-reader.ts
rename to packages/lit-node-client/src/lib/helpers/session-sigs-reader.ts
index 6b8c63e95b..99c66792fd 100644
--- a/packages/misc/src/lib/helper/session-sigs-reader.ts
+++ b/packages/lit-node-client/src/lib/helpers/session-sigs-reader.ts
@@ -1,3 +1,6 @@
+import { InvalidArgumentException } from '@lit-protocol/constants';
+import { logger } from '@lit-protocol/logger';
+
import { parseSignedMessage } from './session-sigs-validator';
function formatDuration(start: Date, end: Date): string {
@@ -33,7 +36,7 @@ function formatStatus(expirationDate: Date, currentDate: Date): string {
/**
* Convert this format:
* {"lit-ratelimitincrease://25364":{"Auth/Auth":[{"nft_id":["25364"]}]}}
- * to human readable format
+ * to human-readable format
*/
function humanReadableAtt(obj: any, indentLevel: number = 0): string {
const indent = ' '.repeat(indentLevel * 2);
@@ -73,7 +76,15 @@ export function formatSessionSigs(
} catch (error: unknown) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error';
- throw new Error(`Invalid JSON format for signedMessage: ${errorMessage}`);
+ throw new InvalidArgumentException(
+ {
+ info: {
+ signedMessage,
+ firstNodeSignedMessage: firstNode.signedMessage,
+ },
+ },
+ `Invalid JSON format for signedMessage: ${errorMessage}`
+ );
}
const currentDate = new Date(currentTime);
@@ -88,7 +99,14 @@ export function formatSessionSigs(
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error';
- throw new Error(`Error parsing issuedAt or expiration: ${errorMessage}`);
+ throw new InvalidArgumentException(
+ {
+ info: {
+ signedMessage,
+ },
+ },
+ `Error parsing issuedAt or expiration: ${errorMessage}`
+ );
}
result += '* Outer expiration:\n';
@@ -111,7 +129,11 @@ export function formatSessionSigs(
attenuation = humanReadableAtt(jsonRecap.att, 6);
} catch (e) {
// swallow error
- console.log('Error parsing attenuation::', e);
+ logger.info({
+ function: 'formatSessionSigs',
+ msg: 'Error parsing attenuation',
+ error: e,
+ });
}
const capIssuedAt = new Date(parsedCapMessage['Issued At'] || '');
diff --git a/packages/misc/src/lib/helper/session-sigs-validator.spec.ts b/packages/lit-node-client/src/lib/helpers/session-sigs-validator.spec.ts
similarity index 99%
rename from packages/misc/src/lib/helper/session-sigs-validator.spec.ts
rename to packages/lit-node-client/src/lib/helpers/session-sigs-validator.spec.ts
index ddc906323c..24a7c1680a 100644
--- a/packages/misc/src/lib/helper/session-sigs-validator.spec.ts
+++ b/packages/lit-node-client/src/lib/helpers/session-sigs-validator.spec.ts
@@ -1,4 +1,5 @@
import { AuthSig } from '@lit-protocol/types';
+
import { validateSessionSigs } from './session-sigs-validator';
describe('validateSessionSigs', () => {
diff --git a/packages/misc/src/lib/helper/session-sigs-validator.ts b/packages/lit-node-client/src/lib/helpers/session-sigs-validator.ts
similarity index 100%
rename from packages/misc/src/lib/helper/session-sigs-validator.ts
rename to packages/lit-node-client/src/lib/helpers/session-sigs-validator.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/validate-bls-session-sig.ts b/packages/lit-node-client/src/lib/helpers/validate-bls-session-sig.ts
similarity index 88%
rename from packages/lit-node-client-nodejs/src/lib/helpers/validate-bls-session-sig.ts
rename to packages/lit-node-client/src/lib/helpers/validate-bls-session-sig.ts
index 55b5f0cd41..0c7641c75d 100644
--- a/packages/lit-node-client-nodejs/src/lib/helpers/validate-bls-session-sig.ts
+++ b/packages/lit-node-client/src/lib/helpers/validate-bls-session-sig.ts
@@ -1,12 +1,9 @@
-import { log } from '@lit-protocol/misc';
-import { AuthSig } from '@lit-protocol/types';
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
import { ethers } from 'ethers';
import { SiweError, SiweErrorType, SiweMessage } from 'siwe';
+import { InvalidArgumentException } from '@lit-protocol/constants';
+import { AuthSig } from '@lit-protocol/types';
+
const LIT_SESSION_SIGNED_MESSAGE_PREFIX = 'lit_session:';
/**
@@ -29,8 +26,8 @@ export const blsSessionSigVerify = async (
authSig: AuthSig,
authSigSiweMessage: SiweMessage
): Promise => {
- let sigJson = JSON.parse(authSig.sig);
- // we do not nessesarly need to use ethers here but was a quick way
+ const sigJson = JSON.parse(authSig.sig);
+ // we do not necessarily need to use ethers here but was a quick way
// to get verification working.
const eip191Hash = ethers.utils.hashMessage(authSig.signedMessage);
const prefixedStr =
@@ -43,7 +40,12 @@ export const blsSessionSigVerify = async (
const checkTime = new Date();
if (!authSigSiweMessage.expirationTime || !authSigSiweMessage.issuedAt) {
- throw new Error(
+ throw new InvalidArgumentException(
+ {
+ info: {
+ authSigSiweMessage,
+ },
+ },
'Invalid SIWE message. Missing expirationTime or issuedAt.'
);
}
diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/validate-bls-session-sigs.spec.ts b/packages/lit-node-client/src/lib/helpers/validate-bls-session-sigs.spec.ts
similarity index 100%
rename from packages/lit-node-client-nodejs/src/lib/helpers/validate-bls-session-sigs.spec.ts
rename to packages/lit-node-client/src/lib/helpers/validate-bls-session-sigs.spec.ts
diff --git a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.spec.ts b/packages/lit-node-client/src/lib/lit-node-client.spec.ts
similarity index 53%
rename from packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.spec.ts
rename to packages/lit-node-client/src/lib/lit-node-client.spec.ts
index 379ad6049c..d8c64b332a 100644
--- a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.spec.ts
+++ b/packages/lit-node-client/src/lib/lit-node-client.spec.ts
@@ -1,34 +1,27 @@
-// @ts-nocheck
-
-// This will prevent it logging the following
-// [Lit-JS-SDK v2.2.39] ✅ [BLS SDK] wasmExports loaded
-// [Lit-JS-SDK v2.2.39] ✅ [ECDSA SDK NodeJS] wasmECDSA loaded.
-global.jestTesting = true;
-
import { LIT_NETWORK } from '@lit-protocol/constants';
-import { LitNodeClientNodeJs } from './lit-node-client-nodejs';
+import { LitNodeClient } from './lit-node-client';
-const isClass = (v) => {
+const isClass = (v: unknown) => {
return typeof v === 'function' && /^\s*class\s+/.test(v.toString());
};
-describe('LitNodeClientNodeJs', () => {
+describe('LitNodeClient', () => {
// --start;
- it('imported { LitNodeClientNodeJs } is a class', async () => {
- expect(isClass(LitNodeClientNodeJs)).toBe(true);
+ it('imported { LitNodeClient } is a class', async () => {
+ expect(isClass(LitNodeClient)).toBe(true);
});
- it('should be able to instantiate a new LitNodeClientNodeJs to custom', async () => {
- const litNodeClient = new LitNodeClientNodeJs({
+ it('should be able to instantiate a new LitNodeClient to custom', async () => {
+ const litNodeClient = new LitNodeClient({
litNetwork: LIT_NETWORK.Custom,
});
expect(litNodeClient).toBeDefined();
});
- it('should be able to instantiate a new LitNodeClientNodeJs to naga dev', async () => {
- const litNodeClient = new LitNodeClientNodeJs({
+ it('should be able to instantiate a new LitNodeClient to naga dev', async () => {
+ const litNodeClient = new LitNodeClient({
litNetwork: LIT_NETWORK.NagaDev,
});
expect(litNodeClient).toBeDefined();
@@ -38,7 +31,7 @@ describe('LitNodeClientNodeJs', () => {
const tmp = globalThis.localStorage;
Object.defineProperty(globalThis, 'localStorage', { value: undefined });
const ls = require('node-localstorage').LocalStorage;
- const litNodeClient = new LitNodeClientNodeJs({
+ const litNodeClient = new LitNodeClient({
litNetwork: LIT_NETWORK.Custom,
storageProvider: {
provider: new ls('./storage.test.db'),
diff --git a/packages/lit-node-client/src/lib/lit-node-client.ts b/packages/lit-node-client/src/lib/lit-node-client.ts
index 716be94e98..1f8f13bf36 100644
--- a/packages/lit-node-client/src/lib/lit-node-client.ts
+++ b/packages/lit-node-client/src/lib/lit-node-client.ts
@@ -1,56 +1,2093 @@
-import { checkAndSignAuthMessage } from '@lit-protocol/auth-browser';
-import { EITHER_TYPE } from '@lit-protocol/constants';
-import { LitNodeClientNodeJs } from '@lit-protocol/lit-node-client-nodejs';
-import { isNode, log } from '@lit-protocol/misc';
-import { getStorageItem } from '@lit-protocol/misc-browser';
-import { CustomNetwork, LitNodeClientConfig } from '@lit-protocol/types';
-
-/**
- * You can find all these available networks in the `constants` package
- *
- * @example
- *
- * ```
- * import { LIT_NETWORK } from '@lit-protocol/constants';
- *
- * const litNodeClient = new LitNodeClient({
- litNetwork: LIT_NETWORK.DatilTest,
- });
- * ```
- */
-export class LitNodeClient extends LitNodeClientNodeJs {
+import { computeAddress } from '@ethersproject/transactions';
+import { ed25519 } from '@noble/curves/ed25519';
+import { ethers } from 'ethers';
+import { SiweMessage } from 'siwe';
+
+import {
+ getFormattedAccessControlConditions,
+ getHashedAccessControlConditions,
+} from '@lit-protocol/access-control-conditions';
+import {
+ createSiweMessage,
+ createSiweMessageWithCapacityDelegation,
+ createSiweMessageWithRecaps,
+ decode,
+ generateAuthSig,
+ generateSessionCapabilityObjectWithWildcards,
+ LitAccessControlConditionResource,
+} from '@lit-protocol/auth-helpers';
+import {
+ AUTH_METHOD_TYPE,
+ FALLBACK_IPFS_GATEWAYS,
+ GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK,
+ InvalidArgumentException,
+ InvalidParamType,
+ InvalidSessionSigs,
+ InvalidSignatureError,
+ LIT_CURVE,
+ LIT_CURVE_TYPE,
+ LIT_ENDPOINT,
+ LitNetworkError,
+ LitNodeClientNotReadyError,
+ LOCAL_STORAGE_KEYS,
+ NetworkError,
+ ParamNullError,
+ ParamsMissingError,
+ PRODUCT_IDS,
+ SIWE_URI_PREFIX,
+ UnknownError,
+ UnsupportedMethodError,
+ WalletSignatureNotFoundError,
+} from '@lit-protocol/constants';
+import { getNodePrices } from '@lit-protocol/contracts-sdk';
+import { composeLitUrl, mostCommonValue, LitCore } from '@lit-protocol/core';
+import {
+ combineSignatureShares,
+ encrypt,
+ generateSessionKeyPair,
+ verifyAndDecryptWithSignatureShares,
+ verifySignature,
+} from '@lit-protocol/crypto';
+import { Logger, getChildLogger } from '@lit-protocol/logger';
+import {
+ getStorageItem,
+ removeStorageItem,
+ setStorageItem,
+} from '@lit-protocol/misc-browser';
+import {
+ applySchemaWithValidation,
+ DecryptRequestSchema,
+ EncryptRequestSchema,
+ JsonExecutionSdkParamsBaseSchema,
+} from '@lit-protocol/schemas';
+import {
+ AuthCallback,
+ AuthCallbackParams,
+ type AuthenticationContext,
+ AuthSig,
+ BlsResponseData,
+ CapacityCreditsReq,
+ CapacityCreditsRes,
+ ClaimKeyResponse,
+ ClaimProcessor,
+ ClaimRequest,
+ CustomNetwork,
+ DecryptRequest,
+ DecryptResponse,
+ EncryptionSignRequest,
+ EncryptResponse,
+ EncryptSdkParams,
+ ExecuteJsNoSigningResponse,
+ ExecuteJsResponse,
+ FormattedMultipleAccs,
+ GetWalletSigProps,
+ ILitNodeClient,
+ JsonExecutionRequest,
+ JsonExecutionSdkParams,
+ JsonPKPClaimKeyRequest,
+ JsonPkpSignRequest,
+ JsonPkpSignSdkParams,
+ JsonSignSessionKeyRequestV1,
+ JsonSignSessionKeyRequestV2,
+ LitNodeClientConfig,
+ LitResourceAbilityRequest,
+ NodeBlsSigningShare,
+ NodeCommandResponse,
+ NodeSet,
+ NodeShare,
+ PKPSignEndpointResponse,
+ RejectedNodePromises,
+ SessionKeyPair,
+ SessionSigningTemplate,
+ SessionSigsMap,
+ Signature,
+ SignSessionKeyProp,
+ SignSessionKeyResponse,
+ SigResponse,
+ SuccessNodePromises,
+} from '@lit-protocol/types';
+import { AuthMethod } from '@lit-protocol/types';
+
+import { assembleMostCommonResponse } from './helpers/assemble-most-common-response';
+import { encodeCode } from './helpers/encode-code';
+import { getBlsSignatures } from './helpers/get-bls-signatures';
+import { getClaims } from './helpers/get-claims';
+import { getClaimsList } from './helpers/get-claims-list';
+import { getExpiration } from './helpers/get-expiration';
+import { getMaxPricesForNodeProduct } from './helpers/get-max-prices-for-node-product';
+import { getSignatures } from './helpers/get-signatures';
+import { hexPrefixed, removeHexPrefix } from './helpers/hex';
+import { defaultMintClaimCallback } from './helpers/mint-claim-callback';
+import { normalizeAndStringify } from './helpers/normalize-and-stringify';
+import { normalizeArray } from './helpers/normalize-array';
+import { normalizeJsParams } from './helpers/normalize-params';
+import { parseAsJsonOrString } from './helpers/parse-as-json-or-string';
+import { parsePkpSignResponse } from './helpers/parse-pkp-sign-response';
+import { processLitActionResponseStrategy } from './helpers/process-lit-action-response-strategy';
+import { removeDoubleQuotes } from './helpers/remove-double-quotes';
+import { formatSessionSigs } from './helpers/session-sigs-reader';
+import { validateSessionSigs } from './helpers/session-sigs-validator';
+import { blsSessionSigVerify } from './helpers/validate-bls-session-sig';
+
+export class LitNodeClient extends LitCore implements ILitNodeClient {
+ private readonly _litNodeLogger: Logger;
+ /** Tracks the total max price a user is willing to pay for each supported product type
+ * This must be distributed across all nodes; each node will get a percentage of this price
+ *
+ * If the user never sets a max price, it means 'unlimited'
+ */
+ defaultMaxPriceByProduct: Record = {
+ DECRYPTION: BigInt(-1),
+ SIGN: BigInt(-1),
+ LIT_ACTION: BigInt(-1),
+ };
+
+ defaultAuthCallback?: (authSigParams: AuthCallbackParams) => Promise;
+
+ // ========== Constructor ==========
constructor(args: LitNodeClientConfig | CustomNetwork) {
- super({
- ...args,
- defaultAuthCallback: checkAndSignAuthMessage,
+ if (!args) {
+ throw new ParamsMissingError({}, 'must provide LitNodeClient parameters');
+ }
+
+ super(args);
+
+ this._litNodeLogger = getChildLogger({
+ module: 'LitNodeClient',
+ ...(this.config.debug ? { level: 'debug' } : {}),
});
- // -- override configs
- this._overrideConfigsFromLocalStorage();
+ if (args !== undefined && args !== null && 'defaultAuthCallback' in args) {
+ this.defaultAuthCallback = args.defaultAuthCallback;
+ }
+ }
+
+ setDefaultMaxPrice(product: keyof typeof PRODUCT_IDS, price: bigint) {
+ this.defaultMaxPriceByProduct[product] = price;
+ }
+
+ private _getNodePrices() {
+ return getNodePrices({
+ realmId: 1,
+ litNetwork: this.config.litNetwork,
+ networkContext: this.config.contractContext,
+ rpcUrl: this.config.rpcUrl,
+ nodeProtocol: this.config.nodeProtocol,
+ });
}
+ // ========== Rate Limit NFT ==========
+
+ // TODO: Add support for browser feature/lit-2321-js-sdk-add-browser-support-for-createCapacityDelegationAuthSig
+ createCapacityDelegationAuthSig = async (
+ params: CapacityCreditsReq
+ ): Promise => {
+ // -- validate
+ if (!params.dAppOwnerWallet) {
+ throw new InvalidParamType(
+ {
+ info: {
+ params,
+ },
+ },
+ 'dAppOwnerWallet must exist'
+ );
+ }
+
+ // Useful log for debugging
+ if (!params.delegateeAddresses || params.delegateeAddresses.length === 0) {
+ this._litNodeLogger.info(
+ `[createCapacityDelegationAuthSig] 'delegateeAddresses' is an empty array. It means that no body can use it. However, if the 'delegateeAddresses' field is omitted, It means that the capability will not restrict access based on delegatee list, but it may still enforce other restrictions such as usage limits (uses) and specific NFT IDs (nft_id).`
+ );
+ }
+
+ // -- This is the owner address who holds the Capacity Credits NFT token and wants to delegate its
+ // usage to a list of delegatee addresses
+ const dAppOwnerWalletAddress = ethers.utils.getAddress(
+ await params.dAppOwnerWallet.getAddress()
+ );
+
+ // -- if it's not ready yet, then connect
+ if (!this.ready) {
+ await this.connect();
+ }
+
+ const siweMessage = await createSiweMessageWithCapacityDelegation({
+ uri: SIWE_URI_PREFIX.DELEGATION,
+ litNodeClient: this,
+ walletAddress: dAppOwnerWalletAddress,
+ nonce: await this.getLatestBlockhash(),
+ expiration: params.expiration,
+ domain: params.domain,
+ statement: params.statement,
+
+ // -- capacity delegation specific configuration
+ uses: params.uses,
+ delegateeAddresses: params.delegateeAddresses,
+ // paymentId: params.paymentId, // CHANGE: Not supported yet
+ });
+
+ const authSig = await generateAuthSig({
+ signer: params.dAppOwnerWallet,
+ toSign: siweMessage,
+ });
+
+ return { capacityDelegationAuthSig: authSig };
+ };
+
+ // ==================== SESSIONS ====================
+ /**
+ * Try to get the session key in the local storage,
+ * if not, generates one.
+ * @return { SessionKeyPair } session key pair
+ */
+ private _getSessionKey = (): SessionKeyPair => {
+ const storageKey = LOCAL_STORAGE_KEYS.SESSION_KEY;
+
+ try {
+ const storedSessionKeyString = getStorageItem(storageKey);
+ return JSON.parse(storedSessionKeyString);
+ } catch (e) {
+ this._litNodeLogger.warn({
+ msg: `Couldn't get session key from local storage key "${storageKey}". Not a problem. Continue...`,
+ error: e,
+ });
+ }
+
+ this._litNodeLogger.info('Generating new session key...');
+ // Generate new one
+ const newSessionKey = generateSessionKeyPair();
+
+ try {
+ setStorageItem(storageKey, JSON.stringify(newSessionKey));
+ } catch (e) {
+ this._litNodeLogger.info(
+ `Localstorage not available. Not a problem. Continue...`
+ );
+ }
+
+ return newSessionKey;
+ };
+
+ /**
+ * Get the signature from local storage, if not, generates one
+ */
+ private _getWalletSig = async ({
+ authNeededCallback,
+ chain,
+ sessionCapabilityObject,
+ switchChain,
+ expiration,
+ sessionKeyUri,
+ nonce,
+ resourceAbilityRequests,
+ litActionCode,
+ litActionIpfsId,
+ jsParams,
+ sessionKey,
+ }: GetWalletSigProps): Promise => {
+ let walletSig: AuthSig | undefined;
+
+ const storageKey = LOCAL_STORAGE_KEYS.WALLET_SIGNATURE;
+
+ // -- (TRY) to get it in the local storage
+ // -- IF NOT: Generates one
+ this._litNodeLogger.info(
+ `getWalletSig - fetching from storageKey: ${storageKey}`
+ );
+
+ try {
+ const walletSigString = getStorageItem(storageKey);
+ walletSig = JSON.parse(walletSigString);
+ } catch (e) {
+ this._litNodeLogger.warn({
+ msg: `Could not get wallet sig from storage key "${storageKey}"`,
+ error: e,
+ });
+ }
+
+ if (!walletSig) {
+ if (authNeededCallback) {
+ this._litNodeLogger.info(
+ 'getWalletSig - generating with authNeededCallback'
+ );
+
+ const body = {
+ chain,
+ statement: sessionCapabilityObject?.statement,
+ resources: sessionCapabilityObject
+ ? [sessionCapabilityObject.encodeAsSiweResource()]
+ : undefined,
+ ...(switchChain && { switchChain }),
+ expiration,
+ uri: sessionKeyUri,
+ sessionKey: sessionKey,
+ nonce,
+
+ // for recap
+ ...(resourceAbilityRequests && { resourceAbilityRequests }),
+
+ // for lit action custom auth
+ ...(litActionCode && { litActionCode }),
+ ...(litActionIpfsId && { litActionIpfsId }),
+ ...(jsParams && { jsParams }),
+ };
+
+ this._litNodeLogger.info({ msg: 'callback body', body });
+
+ walletSig = await authNeededCallback(body);
+ } else if (this.defaultAuthCallback) {
+ this._litNodeLogger.info(
+ 'getWalletSig - generating with defaultAuthCallback'
+ );
+ walletSig = await this.defaultAuthCallback({
+ chain,
+ statement: sessionCapabilityObject.statement,
+ resources: sessionCapabilityObject
+ ? [sessionCapabilityObject.encodeAsSiweResource()]
+ : undefined,
+ switchChain,
+ expiration,
+ uri: sessionKeyUri,
+ nonce,
+ });
+ } else {
+ throw new ParamsMissingError(
+ {},
+ 'getWalletSig - No authNeededCallback nor default auth callback provided'
+ );
+ }
+
+ // If localStorage, authNeededCallback or defaultAuthCallback didn't fail, walletSig is defined by it
+ this._litNodeLogger.info({ msg: 'getWalletSig - walletSig', walletSig });
+
+ // (TRY) to set walletSig to local storage
+ try {
+ setStorageItem(storageKey, JSON.stringify(walletSig));
+ } catch (e) {
+ this._litNodeLogger.warn({
+ msg: `Unable to store walletSig in local storage. Not a problem. Continue...`,
+ error: e,
+ });
+ }
+ }
+
+ return walletSig;
+ };
+
+ private _authCallbackAndUpdateStorageItem = async ({
+ authCallbackParams,
+ authCallback,
+ }: {
+ authCallbackParams: AuthCallbackParams;
+ authCallback?: AuthCallback;
+ }): Promise => {
+ let authSig: AuthSig;
+
+ if (authCallback) {
+ authSig = await authCallback(authCallbackParams);
+ } else {
+ if (!this.defaultAuthCallback) {
+ throw new ParamsMissingError(
+ {},
+ 'No authCallback nor default auth callback provided'
+ );
+ }
+ authSig = await this.defaultAuthCallback(authCallbackParams);
+ }
+
+ // (TRY) to set walletSig to local storage
+ try {
+ setStorageItem(
+ LOCAL_STORAGE_KEYS.WALLET_SIGNATURE,
+ JSON.stringify(authSig)
+ );
+ return authSig;
+ } catch (e) {
+ // Setting local storage failed, try to remove the item key.
+ this._litNodeLogger.warn({
+ msg: `Unable to store walletSig in local storage. Not a problem. Continuing to remove item key...`,
+ error: e,
+ });
+ }
+
+ try {
+ removeStorageItem(LOCAL_STORAGE_KEYS.WALLET_SIGNATURE);
+ } catch (e) {
+ // Ignore error and continue
+ this._litNodeLogger.warn({
+ msg: `Unable to remove walletSig in local storage. Not a problem. Continuing...`,
+ error: e,
+ });
+ }
+
+ return authSig;
+ };
/**
*
- * (Browser Only) Get the config from browser local storage and override default config
+ * Check if a session key needs to be resigned. These are the scenarios where a session key needs to be resigned:
+ * 1. The authSig.sig does not verify successfully against the authSig.signedMessage
+ * 2. The authSig.signedMessage.uri does not match the sessionKeyUri
+ * 3. The authSig.signedMessage does not contain at least one session capability object
*
- * @returns { void }
+ */
+ private _checkNeedToResignSessionKey = async ({
+ authSig,
+ sessionKeyUri,
+ resourceAbilityRequests,
+ }: {
+ authSig: AuthSig;
+ sessionKeyUri: string;
+ resourceAbilityRequests: LitResourceAbilityRequest[];
+ }): Promise => {
+ const authSigSiweMessage = new SiweMessage(authSig.signedMessage);
+ // We will either have `ed25519` or `LIT_BLS` as we have deviated from the specification of SIWE and use BLS signatures in some cases
+ // Here we need to check the `algo` of the SIWE to confirm we can validate the signature as if we attempt to validate the BLS signature here
+ // it will fail. If the algo is not defined we can assume that it was an EOA wallet signing the message so we can use SIWE.
+ if (authSig.algo === `ed25519` || authSig.algo === undefined) {
+ try {
+ await authSigSiweMessage.verify(
+ { signature: authSig.sig },
+ { suppressExceptions: false }
+ );
+ } catch (e) {
+ this._litNodeLogger.error({
+ msg: `Error while verifying BLS signature: `,
+ e,
+ });
+ return true;
+ }
+ } else if (authSig.algo === `LIT_BLS`) {
+ try {
+ await blsSessionSigVerify(
+ verifySignature,
+ this.networkPubKey!,
+ authSig,
+ authSigSiweMessage
+ );
+ } catch (e) {
+ this._litNodeLogger.error({
+ msg: `Error while verifying bls signature: `,
+ e,
+ });
+ return true;
+ }
+ } else {
+ throw new InvalidSignatureError(
+ {
+ info: {
+ authSig,
+ resourceAbilityRequests,
+ sessionKeyUri,
+ },
+ },
+ 'Unsupported signature algo for session signature. Expected ed25519 or LIT_BLS received %s',
+ authSig.algo
+ );
+ }
+
+ // make sure the sig is for the correct session key
+ if (authSigSiweMessage.uri !== sessionKeyUri) {
+ this._litNodeLogger.info('Need retry because uri does not match');
+ return true;
+ }
+
+ // make sure the authSig contains at least one resource.
+ if (
+ !authSigSiweMessage.resources ||
+ authSigSiweMessage.resources.length === 0
+ ) {
+ this._litNodeLogger.info('Need retry because empty resources');
+ return true;
+ }
+
+ // make sure the authSig contains session capabilities that can be parsed.
+ // TODO: we currently only support the first resource being a session capability object.
+ const authSigSessionCapabilityObject = decode(
+ authSigSiweMessage.resources[0]
+ );
+
+ // make sure the authSig session capability object describes capabilities that are equal or greater than
+ // the abilities requested against the resources in the resource ability requests.
+ for (const resourceAbilityRequest of resourceAbilityRequests) {
+ if (
+ !authSigSessionCapabilityObject.verifyCapabilitiesForResource(
+ resourceAbilityRequest.resource,
+ resourceAbilityRequest.ability
+ )
+ ) {
+ this._litNodeLogger.info({
+ msg: 'Need retry because capabilities do not match',
+ authSigSessionCapabilityObject,
+ resourceAbilityRequest,
+ });
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ private _decryptWithSignatureShares = (
+ networkPubKey: string,
+ identityParam: Uint8Array,
+ ciphertext: string,
+ signatureShares: NodeBlsSigningShare[]
+ ): Promise => {
+ const sigShares = signatureShares.map((s) => s.signatureShare);
+
+ return verifyAndDecryptWithSignatureShares(
+ networkPubKey,
+ identityParam,
+ ciphertext,
+ sigShares
+ );
+ };
+
+ /**
+ * Retrieves the fallback IPFS code for a given IPFS ID.
*
+ * @param gatewayUrl - the gateway url.
+ * @param ipfsId - The IPFS ID.
+ * @returns The base64-encoded fallback IPFS code.
+ * @throws An error if the code retrieval fails.
*/
- private _overrideConfigsFromLocalStorage = (): void => {
- if (isNode()) return;
+ private async _getFallbackIpfsCode(
+ gatewayUrl: string | undefined,
+ ipfsId: string
+ ) {
+ const allGateways = gatewayUrl
+ ? [gatewayUrl, ...FALLBACK_IPFS_GATEWAYS]
+ : FALLBACK_IPFS_GATEWAYS;
- const storageKey = 'LitNodeClientConfig';
- const storageConfigOrError = getStorageItem(storageKey);
+ this._litNodeLogger.info(
+ `Attempting to fetch code for IPFS ID: ${ipfsId} using fallback IPFS gateways`
+ );
- // -- validate
- if (storageConfigOrError.type === EITHER_TYPE.ERROR) {
- log(`Storage key "${storageKey}" is missing. `);
- return;
+ for (const url of allGateways) {
+ try {
+ const response = await fetch(`${url}${ipfsId}`);
+
+ if (!response.ok) {
+ throw new NetworkError(
+ {
+ info: {
+ ipfsId,
+ gatewayUrl: url,
+ responseStatus: response.status,
+ responseStatusText: response.statusText,
+ },
+ },
+ `Failed to fetch code from IPFS gateway ${url}: ${response.status} ${response.statusText}`
+ );
+ }
+
+ const code = await response.text();
+ const codeBase64 = Buffer.from(code).toString('base64');
+
+ return codeBase64;
+ } catch (error) {
+ this._litNodeLogger.error(
+ `Error fetching code from IPFS gateway ${url}`
+ );
+ // Continue to the next gateway in the array
+ }
+ }
+
+ throw new NetworkError(
+ {
+ info: {
+ ipfsId,
+ gatewayUrl,
+ },
+ },
+ 'All IPFS gateways failed to fetch the code.'
+ );
+ }
+
+ private async executeJsNodeRequest(
+ url: string,
+ formattedParams: JsonExecutionSdkParams & { sessionSigs: SessionSigsMap },
+ requestId: string,
+ nodeSet: NodeSet[]
+ ) {
+ // -- choose the right signature
+ const sessionSig = this._getSessionSigByUrl({
+ sessionSigs: formattedParams.sessionSigs,
+ url,
+ });
+
+ const reqBody: JsonExecutionRequest = {
+ ...formattedParams,
+ authSig: sessionSig,
+ nodeSet,
+ };
+
+ const urlWithPath = composeLitUrl({
+ url,
+ endpoint: LIT_ENDPOINT.EXECUTE_JS,
+ });
+
+ return this.generatePromise(urlWithPath, reqBody, requestId);
+ }
+
+ /**
+ *
+ * Execute JS on the nodes and combine and return any resulting signatures
+ *
+ * @param { JsonExecutionSdkParams } params
+ *
+ * @returns { ExecuteJsResponse }
+ *
+ */
+ executeJs = async (
+ params: JsonExecutionSdkParams
+ ): Promise => {
+ // ========== Validate Params ==========
+ const _params = applySchemaWithValidation(
+ 'executeJs',
+ params,
+ JsonExecutionSdkParamsBaseSchema
+ );
+
+ if (!this.ready) {
+ const message =
+ '[executeJs] LitNodeClient is not ready. Please call await litNodeClient.connect() first.';
+
+ throw new LitNodeClientNotReadyError({}, message);
+ }
+
+ // Format the params
+ let formattedParams: JsonExecutionSdkParams = {
+ ..._params,
+ ...(_params.jsParams && {
+ jsParams: normalizeJsParams(_params.jsParams),
+ }),
+ ...(_params.code && { code: encodeCode(_params.code) }),
+ };
+
+ // Check if IPFS options are provided and if the code should be fetched from IPFS and overwrite the current code.
+ // This will fetch the code from the specified IPFS gateway using the provided ipfsId,
+ // and update the params with the fetched code, removing the ipfsId afterward.
+ const overwriteCode =
+ _params.ipfsOptions?.overwriteCode ||
+ GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK[this.config.litNetwork];
+
+ if (overwriteCode && _params.ipfsId) {
+ const code = await this._getFallbackIpfsCode(
+ _params.ipfsOptions?.gatewayUrl,
+ _params.ipfsId
+ );
+
+ formattedParams = {
+ ..._params,
+ code: code,
+ ipfsId: undefined,
+ };
+ }
+
+ const requestId = this._getNewRequestId();
+
+ const userMaxPrices = await this.getMaxPricesForNodeProduct({
+ product: 'LIT_ACTION',
+ userMaxPrice: _params.userMaxPrice,
+ });
+
+ const targetNodePrices = _params.useSingleNode
+ ? userMaxPrices.slice(0, 1)
+ : userMaxPrices;
+
+ const sessionSigs = await this._getSessionSigs({
+ ..._params.authContext,
+ userMaxPrices: targetNodePrices,
+ });
+
+ const targetNodeUrls = targetNodePrices.map(({ url }) => url);
+ // ========== Get Node Promises ==========
+ // Handle promises for commands sent to Lit nodes
+ const nodePromises = this._getNodePromises(targetNodeUrls, (url: string) =>
+ this.executeJsNodeRequest(
+ url,
+ {
+ ...formattedParams,
+ sessionSigs,
+ },
+ requestId,
+ this._getNodeSet(targetNodeUrls)
+ )
+ );
+
+ // -- resolve promises
+ const res = await this._handleNodePromises(
+ nodePromises,
+ requestId,
+ _params.useSingleNode ? 1 : this._getThreshold()
+ );
+
+ // -- case: promises rejected
+ if (!res.success) {
+ this._throwNodeError(res, requestId);
+ }
+
+ // -- case: promises success (TODO: check the keys of "values")
+ const responseData = (res as SuccessNodePromises).values;
+
+ this._litNodeLogger.info({
+ requestId,
+ responseData,
+ });
+
+ // -- find the responseData that has the most common response
+ const mostCommonResponse = assembleMostCommonResponse(
+ responseData
+ ) as NodeShare;
+
+ const responseFromStrategy = processLitActionResponseStrategy(
+ responseData,
+ _params.responseStrategy ?? { strategy: 'leastCommon' }
+ );
+ mostCommonResponse.response = responseFromStrategy;
+
+ const isSuccess = mostCommonResponse.success;
+ const hasSignedData = Object.keys(mostCommonResponse.signedData).length > 0;
+ const hasClaimData = Object.keys(mostCommonResponse.claimData).length > 0;
+
+ // -- we must also check for claim responses as a user may have submitted for a claim and signatures must be aggregated before returning
+ if (isSuccess && !hasSignedData && !hasClaimData) {
+ return mostCommonResponse as unknown as ExecuteJsResponse;
+ }
+
+ // -- in the case where we are not signing anything on Lit action and using it as purely serverless function
+ if (!hasSignedData && !hasClaimData) {
+ return {
+ claims: {},
+ signatures: null,
+ decryptions: [],
+ response: mostCommonResponse.response,
+ logs: mostCommonResponse.logs,
+ } as ExecuteJsNoSigningResponse;
+ }
+
+ // ========== Extract shares from response data ==========
+
+ // -- 1. combine signed data as a list, and get the signatures from it
+ const signedDataList = responseData.map((r) => {
+ return removeDoubleQuotes(r.signedData);
+ });
+
+ this._litNodeLogger.info({
+ requestId,
+ msg: 'signatures shares to combine',
+ signedDataList,
+ });
+
+ // Flatten the signedDataList by moving the data within the `sig` (or any other key user may choose) object to the top level.
+ // The specific key name (`sig`) is irrelevant, as the contents of the object are always lifted directly.
+ const key = Object.keys(signedDataList[0])[0]; // Get the first key of the object
+
+ const flattenedSignedMessageShares = signedDataList.map((item) => {
+ return item[key]; // Return the value corresponding to that key
+ });
+
+ // -- 2. combine responses as a string, and parse it as JSON if possible
+ const parsedResponse = parseAsJsonOrString(mostCommonResponse.response);
+
+ // -- 3. combine logs
+ const mostCommonLogs: string = mostCommonValue(
+ responseData.map(
+ (r: {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ logs: any;
+ }) => r.logs
+ )
+ );
+
+ // -- 4. combine claims
+ const claimsList = getClaimsList(responseData);
+ const claims = claimsList.length > 0 ? getClaims(claimsList) : undefined;
+
+ // ========== Result ==========
+ const returnVal: ExecuteJsResponse = {
+ claims,
+ signatures: hasSignedData
+ ? {
+ [key]: await getSignatures({
+ requestId,
+ networkPubKeySet: this.networkPubKeySet,
+ threshold: _params.useSingleNode ? 1 : this._getThreshold(),
+ signedMessageShares: flattenedSignedMessageShares,
+ }),
+ }
+ : {},
+ // decryptions: [],
+ response: parsedResponse,
+ logs: mostCommonLogs,
+ };
+
+ this._litNodeLogger.info({ msg: 'returnVal', returnVal });
+
+ return returnVal;
+ };
+
+ /**
+ * Generates a promise by sending a command to the Lit node
+ *
+ * @param url - The URL to send the command to.
+ * @param params - The parameters to include in the command.
+ * @param requestId - The ID of the request.
+ * @returns A promise that resolves with the response from the server.
+ */
+ generatePromise = async (
+ url: string,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ params: any,
+ requestId: string
+ ): Promise => {
+ return await this._sendCommandToNode({
+ url,
+ data: params,
+ requestId,
+ });
+ };
+
+ /**
+ * Use PKP to sign
+ *
+ * @param { JsonPkpSignSdkParams } params
+ * @param params.toSign - The data to sign
+ * @param params.pubKey - The public key to sign with
+ * @param params.sessionSigs - The session signatures to use
+ * @param params.authMethods - (optional) The auth methods to use
+ */
+ pkpSign = async (params: JsonPkpSignSdkParams): Promise => {
+ // -- validate required params
+ const requiredParamKeys = ['toSign', 'pubKey', 'authContext'];
+
+ (requiredParamKeys as (keyof JsonPkpSignSdkParams)[]).forEach((key) => {
+ if (!params[key]) {
+ throw new ParamNullError(
+ {
+ info: {
+ params,
+ key,
+ },
+ },
+ `"%s" cannot be undefined, empty, or null. Please provide a valid value.`,
+ key
+ );
+ }
+ });
+
+ const requestId = this._getNewRequestId();
+
+ const targetNodePrices = await this.getMaxPricesForNodeProduct({
+ product: 'SIGN',
+ userMaxPrice: params.userMaxPrice,
+ });
+
+ const sessionSigs = await this._getSessionSigs({
+ pkpPublicKey: params.pubKey,
+ ...params.authContext,
+ userMaxPrices: targetNodePrices,
+ });
+
+ // validate session sigs
+ const checkedSessionSigs = validateSessionSigs(sessionSigs);
+
+ if (checkedSessionSigs.isValid === false) {
+ throw new InvalidSessionSigs(
+ {},
+ `Invalid sessionSigs. Errors: ${checkedSessionSigs.errors}`
+ );
+ }
+
+ // ========== Get Node Promises ==========
+ // Handle promises for commands sent to Lit nodes
+
+ const targetNodeUrls = targetNodePrices.map(({ url }) => url);
+ const nodePromises = this._getNodePromises(
+ targetNodeUrls,
+ (url: string) => {
+ // -- get the session sig from the url key
+ const sessionSig = this._getSessionSigByUrl({
+ sessionSigs,
+ url,
+ });
+
+ const reqBody: JsonPkpSignRequest = {
+ toSign: normalizeArray(params.toSign),
+ pubkey: hexPrefixed(params.pubKey),
+ authSig: sessionSig,
+
+ // -- optional params - no longer allowed in >= Naga?
+ // ...(params.authContext.authMethods &&
+ // params.authContext.authMethods.length > 0 && {
+ // authMethods: params.authContext.authMethods,
+ // }),
+
+ // nodeSet: thresholdNodeSet,
+ nodeSet: this._getNodeSet(targetNodeUrls),
+ signingScheme: 'EcdsaK256Sha256',
+ };
+
+ this._litNodeLogger.info({ requestId, reqBody });
+
+ const urlWithPath = composeLitUrl({
+ url,
+ endpoint: LIT_ENDPOINT.PKP_SIGN,
+ });
+
+ return this.generatePromise(urlWithPath, reqBody, requestId);
+ }
+ );
+
+ const res = await this._handleNodePromises(
+ nodePromises,
+ requestId,
+ this._getThreshold()
+ );
+
+ // ========== Handle Response ==========
+ if (!res.success) {
+ this._throwNodeError(res, requestId);
+ }
+
+ const responseData = (res as SuccessNodePromises)
+ .values;
+
+ this._litNodeLogger.info({
+ requestId,
+ responseData,
+ });
+
+ // clean up the response data (as there are double quotes & snake cases in the response)
+ const signedMessageShares = parsePkpSignResponse(responseData);
+
+ try {
+ const signatures = await getSignatures({
+ requestId,
+ networkPubKeySet: this.networkPubKeySet,
+ threshold: this._getThreshold(),
+ signedMessageShares: signedMessageShares,
+ });
+
+ this._litNodeLogger.info({ requestId, signatures });
+
+ return signatures;
+ } catch (e) {
+ this._litNodeLogger.error({ msg: 'Error getting signature', error: e });
+ throw e;
+ }
+ };
+
+ /**
+ * Encrypt data using the LIT network public key.
+ * See more: https://developer.litprotocol.com/sdk/access-control/encryption
+ *
+ * @param { EncryptSdkParams } params
+ * @param params.dataToEncrypt - The data to encrypt
+ * @param params.accessControlConditions - (optional) The access control conditions for the data
+ * @param params.evmContractConditions - (optional) The EVM contract conditions for the data
+ * @param params.solRpcConditions - (optional) The Solidity RPC conditions for the data
+ * @param params.unifiedAccessControlConditions - (optional) The unified access control conditions for the data
+ *
+ * @return { Promise } The encrypted ciphertext and the hash of the data
+ *
+ * @throws { Error } if the LIT node client is not ready
+ * @throws { Error } if the subnetPubKey is null
+ */
+ encrypt = async (params: EncryptSdkParams): Promise => {
+ // ========== Validate Params ==========
+ const _params = applySchemaWithValidation(
+ 'encrypt',
+ params,
+ EncryptRequestSchema
+ );
+
+ // -- validate if it's ready
+ if (!this.ready) {
+ throw new LitNodeClientNotReadyError(
+ {},
+ '6 LitNodeClient is not ready. Please call await litNodeClient.connect() first.'
+ );
+ }
+
+ // -- validate if this.subnetPubKey is null
+ if (!this.subnetPubKey) {
+ throw new LitNodeClientNotReadyError({}, 'subnetPubKey cannot be null');
+ }
+
+ // ========== Hashing Access Control Conditions =========
+ // hash the access control conditions
+ const hashOfConditions: ArrayBuffer | undefined =
+ await getHashedAccessControlConditions(_params);
+
+ if (!hashOfConditions) {
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
+ );
+ }
+
+ const hashOfConditionsStr = Buffer.from(
+ new Uint8Array(hashOfConditions)
+ ).toString('hex');
+
+ // ========== Hashing Private Data ==========
+ // hash the private data
+ const hashOfPrivateData = await crypto.subtle.digest(
+ 'SHA-256',
+ params.dataToEncrypt
+ );
+ const hashOfPrivateDataStr = Buffer.from(
+ new Uint8Array(hashOfPrivateData)
+ ).toString('hex');
+
+ // ========== Assemble identity parameter ==========
+ const identityParam = this._getIdentityParamForEncryption(
+ hashOfConditionsStr,
+ hashOfPrivateDataStr
+ );
+
+ // ========== Encrypt ==========
+ const ciphertext = await encrypt(
+ this.subnetPubKey,
+ params.dataToEncrypt,
+ Buffer.from(identityParam, 'utf8')
+ );
+
+ return { ciphertext, dataToEncryptHash: hashOfPrivateDataStr };
+ };
+
+ /**
+ *
+ * Decrypt ciphertext with the LIT network.
+ *
+ */
+ decrypt = async (params: DecryptRequest): Promise => {
+ // -- validate params
+ const { authContext, chain, ciphertext, dataToEncryptHash, userMaxPrice } =
+ applySchemaWithValidation('decrypt', params, DecryptRequestSchema);
+
+ // -- validate if it's ready
+ if (!this.ready) {
+ throw new LitNodeClientNotReadyError(
+ {},
+ '6 LitNodeClient is not ready. Please call await litNodeClient.connect() first.'
+ );
+ }
+
+ // -- validate if this.subnetPubKey is null
+ if (!this.subnetPubKey) {
+ throw new LitNodeClientNotReadyError({}, 'subnetPubKey cannot be null');
+ }
+
+ // ========== Hashing Access Control Conditions =========
+ // hash the access control conditions
+ const hashOfConditions: ArrayBuffer | undefined =
+ await getHashedAccessControlConditions(params);
+
+ if (!hashOfConditions) {
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
+ );
+ }
+
+ const hashOfConditionsStr = Buffer.from(
+ new Uint8Array(hashOfConditions)
+ ).toString('hex');
+
+ // ========== Formatting Access Control Conditions =========
+ const {
+ error,
+ formattedAccessControlConditions,
+ formattedEVMContractConditions,
+ formattedSolRpcConditions,
+ formattedUnifiedAccessControlConditions,
+ }: FormattedMultipleAccs = getFormattedAccessControlConditions(params);
+
+ if (error) {
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'You must provide either accessControlConditions or evmContractConditions or solRpcConditions or unifiedAccessControlConditions'
+ );
+ }
+
+ // ========== Assemble identity parameter ==========
+ const identityParam = this._getIdentityParamForEncryption(
+ hashOfConditionsStr,
+ dataToEncryptHash
+ );
+
+ this._litNodeLogger.info({ msg: 'identityParam', identityParam });
+
+ const userMaxPrices = await this.getMaxPricesForNodeProduct({
+ product: 'DECRYPTION',
+ userMaxPrice,
+ });
+
+ const sessionSigs = await this._getSessionSigs({
+ ...authContext,
+ userMaxPrices,
+ });
+
+ // ========== Get Network Signature ==========
+ const requestId = this._getNewRequestId();
+ const nodePromises = this._getNodePromises(
+ userMaxPrices.map(({ url }) => url),
+ (url: string) => {
+ // -- if session key is available, use it
+ const authSigToSend = sessionSigs[url];
+
+ if (!authSigToSend) {
+ throw new InvalidArgumentException(
+ {
+ info: {
+ params,
+ },
+ },
+ 'authSig is required'
+ );
+ }
+
+ const reqBody: EncryptionSignRequest = {
+ accessControlConditions: formattedAccessControlConditions,
+ evmContractConditions: formattedEVMContractConditions,
+ solRpcConditions: formattedSolRpcConditions,
+ unifiedAccessControlConditions:
+ formattedUnifiedAccessControlConditions,
+ dataToEncryptHash,
+ chain,
+ authSig: authSigToSend,
+ epoch: this.currentEpochNumber!,
+ };
+
+ const urlWithParh = composeLitUrl({
+ url,
+ endpoint: LIT_ENDPOINT.ENCRYPTION_SIGN,
+ });
+
+ return this.generatePromise(urlWithParh, reqBody, requestId);
+ }
+ );
+
+ // -- resolve promises
+ const res = await this._handleNodePromises(
+ nodePromises,
+ requestId,
+ this._getThreshold()
+ );
+
+ // -- case: promises rejected
+ if (!res.success) {
+ this._throwNodeError(res, requestId);
+ }
+
+ const signatureShares: NodeBlsSigningShare[] = (
+ res as SuccessNodePromises
+ ).values;
+
+ this._litNodeLogger.info({ requestId, signatureShares });
+
+ // ========== Result ==========
+ const decryptedData = await this._decryptWithSignatureShares(
+ this.subnetPubKey,
+ Buffer.from(identityParam, 'utf8'),
+ ciphertext,
+ signatureShares
+ );
+
+ return { decryptedData };
+ };
+
+ private _getIdentityParamForEncryption = (
+ hashOfConditionsStr: string,
+ hashOfPrivateDataStr: string
+ ): string => {
+ return new LitAccessControlConditionResource(
+ `${hashOfConditionsStr}/${hashOfPrivateDataStr}`
+ ).getResourceKey();
+ };
+
+ /** ============================== SESSION ============================== */
+
+ /**
+ * Sign a session public key using a PKP, which generates an authSig.
+ * @returns {Object} An object containing the resulting signature.
+ */
+ private _signSessionKey = async (
+ params: SignSessionKeyProp
+ ): Promise => {
+ this._litNodeLogger.info({ msg: `[signSessionKey] params:`, params });
+
+ // ========== Validate Params ==========
+ // -- validate: If it's NOT ready
+ if (!this.ready) {
+ throw new LitNodeClientNotReadyError(
+ {},
+ '[signSessionKey] ]LitNodeClient is not ready. Please call await litNodeClient.connect() first.'
+ );
+ }
+
+ // -- construct SIWE message that will be signed by node to generate an authSig.
+ const _expiration =
+ params.expiration ||
+ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
+
+ // Try to get it from local storage, if not generates one~
+ const sessionKey: SessionKeyPair =
+ params.sessionKey ?? this._getSessionKey();
+ const sessionKeyUri = this._getSessionKeyUri(sessionKey.publicKey);
+
+ this._litNodeLogger.info(
+ `[signSessionKey] sessionKeyUri is not found in params, generating a new one`,
+ sessionKeyUri
+ );
+
+ if (!sessionKeyUri) {
+ throw new InvalidParamType(
+ {
+ info: {
+ params,
+ },
+ },
+ '[signSessionKey] sessionKeyUri is not defined. Please provide a sessionKeyUri or a sessionKey.'
+ );
+ }
+
+ // Compute the address from the public key if it's provided. Otherwise, the node will compute it.
+ const pkpEthAddress = (function () {
+ // prefix '0x' if it's not already prefixed
+ params.pkpPublicKey = hexPrefixed(params.pkpPublicKey!);
+
+ if (params.pkpPublicKey) return computeAddress(params.pkpPublicKey);
+
+ // This will be populated by the node, using dummy value for now.
+ return '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
+ })();
+
+ let siwe_statement = 'Lit Protocol PKP session signature';
+ if (params.statement) {
+ siwe_statement += ' ' + params.statement;
+ this._litNodeLogger.info(
+ `[signSessionKey] statement found in params: "${params.statement}"`
+ );
+ }
+
+ let siweMessage;
+
+ const siweParams = {
+ domain: params?.domain || globalThis.location?.host || 'litprotocol.com',
+ walletAddress: pkpEthAddress,
+ statement: siwe_statement,
+ uri: sessionKeyUri,
+ version: '1',
+ chainId: params.chainId ?? 1,
+ expiration: _expiration,
+ nonce: await this.getLatestBlockhash(),
+ };
+
+ if (params.resourceAbilityRequests) {
+ siweMessage = await createSiweMessageWithRecaps({
+ ...siweParams,
+ resources: params.resourceAbilityRequests,
+ litNodeClient: this,
+ });
+ } else {
+ siweMessage = await createSiweMessage(siweParams);
+ }
+
+ // This may seem a bit weird because we usually only care about prices for sessionSigs...
+ // But this also ensures we use the cheapest nodes and takes care of getting the minNodeCount of node URLs for the operation
+ const targetNodePrices = await this.getMaxPricesForNodeProduct({
+ product: 'LIT_ACTION',
+ });
+
+ // ========== Get Node Promises ==========
+ // -- fetch shares from nodes
+ const body: JsonSignSessionKeyRequestV2 = {
+ nodeSet: this._getNodeSet(targetNodePrices.map(({ url }) => url)),
+ sessionKey: sessionKeyUri,
+ authMethods: params.authMethods,
+ ...(params?.pkpPublicKey && { pkpPublicKey: params.pkpPublicKey }),
+ siweMessage: siweMessage,
+ curveType: LIT_CURVE.BLS,
+
+ // -- custom auths
+ ...(params?.litActionIpfsId && {
+ litActionIpfsId: params.litActionIpfsId,
+ }),
+ ...(params?.litActionCode && { code: params.litActionCode }),
+ ...(params?.jsParams && { jsParams: params.jsParams }),
+ ...(this.currentEpochNumber && { epoch: this.currentEpochNumber }),
+ signingScheme: LIT_CURVE.BLS,
+ };
+
+ this._litNodeLogger.info({ msg: `[signSessionKey] body:`, body });
+
+ const requestId = this._getNewRequestId();
+ this._litNodeLogger.info({ requestId, signSessionKeyBody: body });
+
+ const targetNodeUrls = targetNodePrices.map(({ url }) => url);
+ const nodePromises = this._getNodePromises(
+ targetNodeUrls,
+ (url: string) => {
+ const reqBody: JsonSignSessionKeyRequestV1 = body;
+
+ const urlWithPath = composeLitUrl({
+ url,
+ endpoint: LIT_ENDPOINT.SIGN_SESSION_KEY,
+ });
+
+ return this.generatePromise(urlWithPath, reqBody, requestId);
+ }
+ );
+
+ // -- resolve promises
+ let res;
+ try {
+ res = await this._handleNodePromises(
+ nodePromises,
+ requestId,
+ this._getThreshold()
+ );
+ this._litNodeLogger.info({ msg: 'signSessionKey node promises', res });
+ } catch (e) {
+ throw new UnknownError(
+ {
+ info: {
+ requestId,
+ },
+ cause: e,
+ },
+ 'Error when handling node promises'
+ );
+ }
+
+ this._litNodeLogger.info({ requestId, handleNodePromisesRes: res });
+
+ // -- case: promises rejected
+ if (!res.success) {
+ this._throwNodeError(res as RejectedNodePromises, requestId);
+ return {} as SignSessionKeyResponse;
+ }
+
+ const responseData: BlsResponseData[] = res.values as BlsResponseData[];
+ this._litNodeLogger.info({
+ requestId,
+ responseData,
+ });
+
+ // ========== Extract shares from response data ==========
+ // -- 1. combine signed data as a list, and get the signatures from it
+ const curveType = responseData[0]?.curveType;
+
+ if (curveType === 'ECDSA') {
+ throw new LitNetworkError(
+ {
+ info: {
+ requestId,
+ responseData,
+ },
+ },
+ 'The ECDSA curve type is not supported in this version.'
+ );
+ }
+
+ this._litNodeLogger.info(`[signSessionKey] curveType is "${curveType}"`);
+
+ const signedDataList = responseData.map((s) => s.dataSigned);
+
+ if (signedDataList.length <= 0) {
+ const err = `[signSessionKey] signedDataList is empty.`;
+ this._litNodeLogger.info(err);
+ throw new InvalidSignatureError(
+ {
+ info: {
+ requestId,
+ responseData,
+ signedDataList,
+ },
+ },
+ err
+ );
+ }
+
+ this._litNodeLogger.info({
+ requestId,
+ signedDataList,
+ });
+
+ // -- checking if we have enough shares.
+ const validatedSignedDataList = this._validateSignSessionKeyResponseData(
+ responseData,
+ requestId,
+ this._getThreshold()
+ );
+
+ const blsSignedData: BlsResponseData[] = validatedSignedDataList;
+
+ const sigType = mostCommonValue(blsSignedData.map((s) => s.curveType));
+ this._litNodeLogger.info(`[signSessionKey] sigType:`, sigType);
+
+ const signatureShares = getBlsSignatures(blsSignedData);
+
+ this._litNodeLogger.info(
+ `[signSessionKey] signatureShares:`,
+ signatureShares
+ );
+
+ const blsCombinedSignature = await combineSignatureShares(signatureShares);
+
+ this._litNodeLogger.info(
+ `[signSessionKey] blsCombinedSignature:`,
+ blsCombinedSignature
+ );
+
+ const publicKey = removeHexPrefix(params.pkpPublicKey);
+ this._litNodeLogger.info(`[signSessionKey] publicKey:`, publicKey);
+
+ const dataSigned = mostCommonValue(blsSignedData.map((s) => s.dataSigned));
+ this._litNodeLogger.info(`[signSessionKey] dataSigned:`, dataSigned);
+
+ const mostCommonSiweMessage = mostCommonValue(
+ blsSignedData.map((s) => s.siweMessage)
+ );
+
+ this._litNodeLogger.info(
+ `[signSessionKey] mostCommonSiweMessage:`,
+ mostCommonSiweMessage
+ );
+
+ const signedMessage = normalizeAndStringify(mostCommonSiweMessage!);
+
+ this._litNodeLogger.info(`[signSessionKey] signedMessage:`, signedMessage);
+
+ const signSessionKeyRes: SignSessionKeyResponse = {
+ authSig: {
+ sig: JSON.stringify({
+ ProofOfPossession: blsCombinedSignature,
+ }),
+ algo: 'LIT_BLS',
+ derivedVia: 'lit.bls',
+ signedMessage,
+ address: computeAddress(hexPrefixed(publicKey)),
+ },
+ pkpPublicKey: publicKey,
+ };
+
+ return signSessionKeyRes;
+ };
+
+ getSignSessionKeyShares = async (
+ url: string,
+ params: {
+ body: {
+ sessionKey: string;
+ authMethods: AuthMethod[];
+ pkpPublicKey?: string;
+ authSig?: AuthSig;
+ siweMessage: string;
+ };
+ },
+ requestId: string
+ ) => {
+ this._litNodeLogger.info('getSignSessionKeyShares');
+ const urlWithPath = composeLitUrl({
+ url,
+ endpoint: LIT_ENDPOINT.SIGN_SESSION_KEY,
+ });
+ return await this._sendCommandToNode({
+ url: urlWithPath,
+ data: params.body,
+ requestId,
+ });
+ };
+
+ getMaxPricesForNodeProduct = async ({
+ userMaxPrice,
+ product,
+ }: {
+ userMaxPrice?: bigint;
+ product: keyof typeof PRODUCT_IDS;
+ }) => {
+ this._litNodeLogger.info({
+ msg: 'getMaxPricesForNodeProduct(): Product',
+ product,
+ });
+ const getUserMaxPrice = () => {
+ if (userMaxPrice) {
+ this._litNodeLogger.info({
+ msg: 'getMaxPricesForNodeProduct(): User provided maxPrice of userMaxPrice',
+ userMaxPrice,
+ });
+ return userMaxPrice;
+ }
+
+ if (this.defaultMaxPriceByProduct[product] === -1n) {
+ this._litNodeLogger.info(
+ `getMaxPricesForNodeProduct(): No user-provided maxPrice and no defaultMaxPrice set for ${product}; setting to max value`
+ );
+
+ return 340_282_366_920_938_463_463_374_607_431_768_211_455n; // Rust U128 max
+ }
+ return this.defaultMaxPriceByProduct[product];
+ };
+
+ return getMaxPricesForNodeProduct({
+ nodePrices: await this._getNodePrices(),
+ userMaxPrice: getUserMaxPrice(),
+ productId: PRODUCT_IDS[product],
+ numRequiredNodes: this._getThreshold(),
+ });
+ };
+
+ /**
+ *
+ * Retrieves or generates sessionSigs (think access token) for accessing Lit Network resources.
+ *
+ * How this function works on a high level:
+ * 1. Generate or retrieve [session keys](https://v6-api-doc-lit-js-sdk.vercel.app/interfaces/types_src.SessionKeyPair.html) (a public and private key pair)
+ * 2. Generate or retrieve the [`AuthSig`](https://v6-api-doc-lit-js-sdk.vercel.app/interfaces/types_src.AuthSig.html) that specifies the session [abilities](https://v6-api-doc-lit-js-sdk.vercel.app/enums/auth_helpers_src.LitAbility.html)
+ * 3. Sign the specific resources with the session key
+ *
+ * The process follows these steps:
+ * 1. Retrieves or generates a session key pair (Ed25519) for the user's device. The session key is either fetched from local storage or newly created if not found. The key does not expire.
+ * 2. Generates an authentication signature (`authSig`) by signing an ERC-5573 "Sign-in with Ethereum" message, which includes resource ability requests, capabilities, expiration, the user's device session public key, and a nonce. The `authSig` is retrieved from local storage, and if it has expired, the user will be prompted to re-sign.
+ * 3. Uses the session private key to sign the session public key along with the resource ability requests, capabilities, issuedAt, and expiration details. This creates a device-generated signature.
+ * 4. Constructs the session signatures (`sessionSigs`) by including the device-generated signature and the original message. The `sessionSigs` provide access to Lit Network features such as `executeJs` and `pkpSign`.
+ *
+ * See Sequence Diagram: https://www.plantuml.com/plantuml/uml/VPH1RnCn48Nl_XLFlT1Av00eGkm15QKLWY8K9K9SO-rEar4sjcLFalBl6NjJAuaMRl5utfjlPjQvJsAZx7UziQtuY5-9eWaQufQ3TOAR77cJy407Rka6zlNdHTRouUbIzSEtjiTIBUswg5v_NwMnuAVlA9KKFPN3I0x9qSSj7bqNF3iPykl9c4o9oUSJMuElv2XQ8IHAYRt3bluWM8wuVUpUJwVlFjsP8JUh5B_1DyV2AYdD6DjhLsTQTaYd3W3ad28SGWqM997fG5ZrB9DJqOaALuRwH1TMpik8tIYze-E8OrPKU5I6cMqtem2kCqOhr4vdaRAvtSjcoMkTo68scKu_Vi1EPMfrP_xVtj7sFMaHNg-6GVqk0MW0z18uKdVULTvDWtdqko28b7KktvUB2hKOBd1asU2QgDfTzrj7T4bLPdv6TR0zLwPQKkkZpIRTY4CTMbrBpg_VKuXyi49beUAHqIlirOUrL2zq9JPPdpRR5OMLVQGoGlLcjyRyQNv6MHz4W_fG42W--xWhUfNyOxiLL1USS6lRLeyAkYLNjrkVJuClm_qp5I8Lq0krUw7lwIt2DgY9oiozrjA_Yhy0
+ *
+ * Note: When generating session signatures for different PKPs or auth methods,
+ * be sure to call disconnectWeb3 to clear auth signatures stored in local storage
+ *
+ * @param { AuthenticationContext } params
+ *
+ * An example of how this function is used can be found in the Lit developer-guides-code repository [here](https://github.com/LIT-Protocol/developer-guides-code/tree/master/session-signatures/getSessionSigs).
+ *
+ */
+ private _getSessionSigs = async (
+ params: AuthenticationContext & {
+ userMaxPrices: { url: string; price: bigint }[];
+ }
+ ): Promise => {
+ // -- prepare
+ // Try to get it from local storage, if not generates one~
+ const sessionKey = params.sessionKey ?? this._getSessionKey();
+
+ const sessionKeyUri = this._getSessionKeyUri(sessionKey.publicKey);
+
+ // First get or generate the session capability object for the specified resources.
+ const sessionCapabilityObject = params.sessionCapabilityObject
+ ? params.sessionCapabilityObject
+ : await generateSessionCapabilityObjectWithWildcards(
+ params.resourceAbilityRequests.map((r) => r.resource)
+ );
+ const expiration = params.expiration || getExpiration();
+
+ // -- (TRY) to get the wallet signature
+ let authSig = await this._getWalletSig({
+ authNeededCallback: params.authNeededCallback,
+ chain: params.chain || 'ethereum',
+ sessionCapabilityObject,
+ switchChain: params.switchChain,
+ expiration: expiration,
+ sessionKey: sessionKey,
+ sessionKeyUri: sessionKeyUri,
+ nonce: await this.getLatestBlockhash(),
+
+ // -- for recap
+ resourceAbilityRequests: params.resourceAbilityRequests,
+
+ // -- optional fields
+ ...(params.litActionCode && { litActionCode: params.litActionCode }),
+ ...(params.litActionIpfsId && {
+ litActionIpfsId: params.litActionIpfsId,
+ }),
+ ...(params.jsParams && { jsParams: params.jsParams }),
+ });
+
+ const needToResignSessionKey = await this._checkNeedToResignSessionKey({
+ authSig,
+ sessionKeyUri,
+ resourceAbilityRequests: params.resourceAbilityRequests,
+ });
+
+ // -- (CHECK) if we need to resign the session key
+ if (needToResignSessionKey) {
+ this._litNodeLogger.info('need to re-sign session key. Signing...');
+ authSig = await this._authCallbackAndUpdateStorageItem({
+ authCallback: params.authNeededCallback,
+ authCallbackParams: {
+ chain: params.chain || 'ethereum',
+ statement: sessionCapabilityObject.statement,
+ resources: [sessionCapabilityObject.encodeAsSiweResource()],
+ switchChain: params.switchChain,
+ expiration,
+ sessionKey: sessionKey,
+ uri: sessionKeyUri,
+ nonce: await this.getLatestBlockhash(),
+ resourceAbilityRequests: params.resourceAbilityRequests,
+
+ // -- optional fields
+ ...(params.litActionCode && { litActionCode: params.litActionCode }),
+ ...(params.litActionIpfsId && {
+ litActionIpfsId: params.litActionIpfsId,
+ }),
+ ...(params.jsParams && { jsParams: params.jsParams }),
+ },
+ });
+ }
+
+ if (
+ authSig.address === '' ||
+ authSig.derivedVia === '' ||
+ authSig.sig === '' ||
+ authSig.signedMessage === ''
+ ) {
+ throw new WalletSignatureNotFoundError(
+ {
+ info: {
+ authSig,
+ },
+ },
+ 'No wallet signature found'
+ );
+ }
+
+ // ===== AFTER we have Valid Signed Session Key =====
+ // - Let's sign the resources with the session key
+ // - 5 minutes is the default expiration for a session signature
+ // - Because we can generate a new session sig every time the user wants to access a resource without prompting them to sign with their wallet
+ const sessionExpiration =
+ expiration ?? new Date(Date.now() + 1000 * 60 * 5).toISOString();
+
+ const capabilities = params.capabilityAuthSigs
+ ? [
+ ...(params.capabilityAuthSigs ?? []),
+ params.capabilityAuthSigs,
+ authSig,
+ ]
+ : [...(params.capabilityAuthSigs ?? []), authSig];
+
+ // This is the template that will be combined with the node address as a single object, then signed by the session key
+ // so that the node can verify the session signature
+ const sessionSigningTemplate = {
+ sessionKey: sessionKey.publicKey,
+ resourceAbilityRequests: params.resourceAbilityRequests,
+ capabilities,
+ issuedAt: new Date().toISOString(),
+ expiration: sessionExpiration,
+ };
+
+ const sessionSigs: SessionSigsMap = {};
+
+ params.userMaxPrices.forEach(({ url: nodeAddress, price }) => {
+ const toSign: SessionSigningTemplate = {
+ ...sessionSigningTemplate,
+ nodeAddress,
+ maxPrice: price.toString(),
+ };
+
+ this._litNodeLogger.info(
+ `Setting maxprice for ${nodeAddress} to `,
+ price.toString()
+ );
+
+ const signedMessage = JSON.stringify(toSign);
+
+ const uint8arrayMessage = Buffer.from(signedMessage, 'utf8');
+ const signature = ed25519.sign(uint8arrayMessage, sessionKey.secretKey);
+
+ sessionSigs[nodeAddress] = {
+ sig: Buffer.from(signature).toString('hex'),
+ derivedVia: 'litSessionSignViaNacl',
+ signedMessage: signedMessage,
+ address: sessionKey.publicKey,
+ algo: 'ed25519',
+ };
+ });
+
+ this._litNodeLogger.info({ msg: 'sessionSigs', sessionSigs });
+
+ try {
+ const formattedSessionSigs = formatSessionSigs(
+ JSON.stringify(sessionSigs)
+ );
+ this._litNodeLogger.info(formattedSessionSigs);
+ } catch (e) {
+ // swallow error
+ this._litNodeLogger.info({
+ msg: 'Error formatting session signatures',
+ e,
+ });
}
- // -- execute
- const storageConfig = JSON.parse(storageConfigOrError.result as string);
- // this.config = override(this.config, storageConfig);
- this.config = { ...this.config, ...storageConfig };
+ return sessionSigs;
+ };
+
+ /**
+ * Retrieves the PKP sessionSigs.
+ *
+ * @param params - The parameters for retrieving the PKP sessionSigs.
+ * @returns A promise that resolves to the PKP sessionSigs.
+ * @throws An error if any of the required parameters are missing or if `litActionCode` and `ipfsId` exist at the same time.
+ */
+ getPkpAuthContext = (params: AuthenticationContext) => {
+ const chain = params?.chain || 'ethereum';
+
+ return {
+ chain,
+ ...params,
+ authNeededCallback: async (props: AuthCallbackParams) => {
+ // -- validate
+ if (!props.expiration) {
+ throw new ParamsMissingError(
+ {
+ info: {
+ props,
+ },
+ },
+ '[getPkpSessionSigs/callback] expiration is required'
+ );
+ }
+
+ if (!props.resources) {
+ throw new ParamsMissingError(
+ {
+ info: {
+ props,
+ },
+ },
+ '[getPkpSessionSigs/callback]resources is required'
+ );
+ }
+
+ if (!props.resourceAbilityRequests) {
+ throw new ParamsMissingError(
+ {
+ info: {
+ props,
+ },
+ },
+ '[getPkpSessionSigs/callback]resourceAbilityRequests is required'
+ );
+ }
+
+ // lit action code and ipfs id cannot exist at the same time
+ if (props.litActionCode && props.litActionIpfsId) {
+ throw new UnsupportedMethodError(
+ {
+ info: {
+ props,
+ },
+ },
+ '[getPkpSessionSigs/callback]litActionCode and litActionIpfsId cannot exist at the same time'
+ );
+ }
+
+ // Check if IPFS options are provided and if the code should be fetched from IPFS and overwrite the current code.
+ // This will fetch the code from the specified IPFS gateway using the provided ipfsId,
+ // and update the params with the fetched code, removing the ipfsId afterward.
+ const overwriteCode =
+ params.ipfsOptions?.overwriteCode ||
+ GLOBAL_OVERWRITE_IPFS_CODE_BY_NETWORK[this.config.litNetwork];
+
+ if (overwriteCode && props.litActionIpfsId) {
+ const code = await this._getFallbackIpfsCode(
+ params.ipfsOptions?.gatewayUrl,
+ props.litActionIpfsId
+ );
+
+ props = {
+ ...props,
+ litActionCode: code,
+ litActionIpfsId: undefined,
+ };
+ }
+
+ /**
+ * We must provide an empty array for authMethods even if we are not using any auth methods.
+ * So that the nodes can serialize the request correctly.
+ */
+ const authMethods = params.authMethods || [];
+
+ const response = await this._signSessionKey({
+ sessionKey: props.sessionKey,
+ statement: props.statement || 'Some custom statement.',
+ authMethods: [...authMethods],
+ pkpPublicKey: params.pkpPublicKey,
+ expiration: props.expiration,
+ resources: props.resources,
+ chainId: 1,
+
+ // -- required fields
+ resourceAbilityRequests: props.resourceAbilityRequests,
+
+ // -- optional fields
+ ...(props.litActionCode && { litActionCode: props.litActionCode }),
+ ...(props.litActionIpfsId && {
+ litActionIpfsId: props.litActionIpfsId,
+ }),
+ ...(props.jsParams && { jsParams: props.jsParams }),
+ });
+
+ return response.authSig;
+ },
+ };
+ };
+
+ /**
+ *
+ * Get Session Key URI eg. lit:session:0x1234
+ *
+ * @param publicKey is the public key of the session key
+ * @returns { string } the session key uri
+ */
+ private _getSessionKeyUri = (publicKey: string): string => {
+ return SIWE_URI_PREFIX.SESSION_KEY + publicKey;
};
+
+ /**
+ * Authenticates an Auth Method for claiming a Programmable Key Pair (PKP).
+ * A {@link MintCallback} can be defined for custom on chain interactions
+ * by default the callback will forward to a relay server for minting on chain.
+ * @param {ClaimKeyRequest} params an Auth Method and {@link MintCallback}
+ * @returns {Promise}
+ */
+ async claimKeyId(
+ params: ClaimRequest
+ ): Promise {
+ if (!this.ready) {
+ const message =
+ 'LitNodeClient is not ready. Please call await litNodeClient.connect() first.';
+ throw new LitNodeClientNotReadyError({}, message);
+ }
+
+ if (params.authMethod.authMethodType == AUTH_METHOD_TYPE.WebAuthn) {
+ throw new LitNodeClientNotReadyError(
+ {},
+ 'Unsupported auth method type. Webauthn, and Lit Actions are not supported for claiming'
+ );
+ }
+
+ const requestId = this._getNewRequestId();
+
+ // This may seem a bit weird because we usually only care about prices for sessionSigs...
+ // But this also ensures we use the cheapest nodes and takes care of getting the minNodeCount of node URLs for the operation
+ const targetNodePrices = await this.getMaxPricesForNodeProduct({
+ product: 'LIT_ACTION',
+ });
+
+ const targetNodeUrls = targetNodePrices.map(({ url }) => url);
+
+ const nodePromises = this._getNodePromises(
+ targetNodeUrls,
+ (url: string) => {
+ if (!params.authMethod) {
+ throw new ParamsMissingError(
+ {
+ info: {
+ params,
+ },
+ },
+ 'authMethod is required'
+ );
+ }
+
+ const reqBody: JsonPKPClaimKeyRequest = {
+ authMethod: params.authMethod,
+ };
+
+ const urlWithPath = composeLitUrl({
+ url,
+ endpoint: LIT_ENDPOINT.PKP_CLAIM,
+ });
+
+ return this.generatePromise(urlWithPath, reqBody, requestId);
+ }
+ );
+
+ const responseData = await this._handleNodePromises(
+ nodePromises,
+ requestId,
+ this._getThreshold()
+ );
+
+ if (responseData.success) {
+ const nodeSignatures: Signature[] = responseData.values.map((r) => {
+ const sig = ethers.utils.splitSignature(`0x${r.signature}`);
+ return {
+ r: sig.r,
+ s: sig.s,
+ v: sig.v,
+ };
+ });
+
+ this._litNodeLogger.info({
+ requestId,
+ responseData,
+ });
+
+ const derivedKeyId = responseData.values[0].derivedKeyId;
+
+ const pubkey = await this.computeHDPubKey(derivedKeyId);
+ this._litNodeLogger.info({
+ requestId,
+ msg: `pubkey ${pubkey} derived from key id ${derivedKeyId}`,
+ });
+
+ const relayParams = params as ClaimRequest<'relay'>;
+
+ let mintTx = '';
+ if (params.mintCallback && 'signer' in params) {
+ mintTx = await params.mintCallback(
+ {
+ derivedKeyId,
+ authMethodType: params.authMethod.authMethodType,
+ signatures: nodeSignatures,
+ pubkey,
+ signer: (params as ClaimRequest<'client'>).signer,
+ ...relayParams,
+ },
+ this.config.litNetwork
+ );
+ } else {
+ mintTx = await defaultMintClaimCallback(
+ {
+ derivedKeyId,
+ authMethodType: params.authMethod.authMethodType,
+ signatures: nodeSignatures,
+ pubkey,
+ ...relayParams,
+ },
+ this.config.litNetwork
+ );
+ }
+
+ return {
+ signatures: nodeSignatures,
+ claimedKeyId: derivedKeyId,
+ pubkey,
+ mintTx,
+ };
+ } else {
+ throw new UnknownError(
+ {
+ info: {
+ requestId,
+ responseData,
+ },
+ },
+ `Claim request has failed. Request trace id: lit_%s`,
+ requestId
+ );
+ }
+ }
+
+ /**
+ * Note: ✨ This is to check data integrity of the response from the signSessionKey endpoint.
+ * As sometimes the response data structure has changed and we need to update the required fields.
+ * Validates the response data from the signSessionKey endpoint.
+ * Each response data item must have all required fields and valid ProofOfPossession.
+ *
+ * @param responseData - Array of BlsResponseData to validate
+ * @param requestId - Request ID for logging and error reporting
+ * @param threshold - Minimum number of valid responses needed
+ * @returns Filtered array of valid BlsResponseData
+ * @throws InvalidSignatureError if validation fails
+ */
+ private _validateSignSessionKeyResponseData(
+ responseData: BlsResponseData[],
+ requestId: string,
+ threshold: number
+ ): BlsResponseData[] {
+ // each of this field cannot be empty
+ const requiredFields = [
+ 'signatureShare',
+ 'curveType',
+ 'siweMessage',
+ 'dataSigned',
+ 'blsRootPubkey',
+ 'result',
+ ];
+
+ // -- checking if we have enough shares.
+ const validatedSignedDataList = responseData
+ .map((data: BlsResponseData) => {
+ // check if all required fields are present
+ for (const field of requiredFields) {
+ const key: keyof BlsResponseData = field as keyof BlsResponseData;
+
+ if (
+ data[key] === undefined ||
+ data[key] === null ||
+ data[key] === ''
+ ) {
+ this._litNodeLogger.info(
+ `Invalid signed data. "${field}" is missing. Not a problem, we only need ${threshold} nodes to sign the session key.`
+ );
+ return null;
+ }
+ }
+
+ if (!data.signatureShare.ProofOfPossession) {
+ const err = `Invalid signed data. "ProofOfPossession" is missing.`;
+ this._litNodeLogger.info(err);
+ throw new InvalidSignatureError(
+ {
+ info: {
+ requestId,
+ responseData,
+ data,
+ },
+ },
+ err
+ );
+ }
+
+ return data;
+ })
+ .filter((item) => item !== null);
+
+ this._litNodeLogger.info({
+ requestId,
+ validatedSignedDataList,
+ });
+ this._litNodeLogger.info({
+ requestId,
+ msg: 'minimum threshold',
+ threshold,
+ });
+
+ if (validatedSignedDataList.length < threshold) {
+ throw new InvalidSignatureError(
+ {
+ info: {
+ requestId,
+ responseData,
+ validatedSignedDataList,
+ threshold,
+ },
+ },
+ `not enough nodes signed the session key. Expected ${threshold}, got ${validatedSignedDataList.length}`
+ );
+ }
+
+ return validatedSignedDataList as BlsResponseData[];
+ }
}
diff --git a/packages/lit-node-client/tsconfig.json b/packages/lit-node-client/tsconfig.json
index f5b85657a8..afa40e9075 100644
--- a/packages/lit-node-client/tsconfig.json
+++ b/packages/lit-node-client/tsconfig.json
@@ -7,7 +7,8 @@
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
- "noFallthroughCasesInSwitch": true
+ "noFallthroughCasesInSwitch": true,
+ "lib": ["ES2021", "DOM"]
},
"files": [],
"include": [],
diff --git a/packages/lit-node-client/tsconfig.lib.json b/packages/lit-node-client/tsconfig.lib.json
index 21bd635299..e85ef50f65 100644
--- a/packages/lit-node-client/tsconfig.lib.json
+++ b/packages/lit-node-client/tsconfig.lib.json
@@ -5,9 +5,6 @@
"declaration": true,
"types": []
},
- "include": [
- "**/*.ts",
- "../auth-browser/src/lib/chains/lit-connect-modal.d.ts"
- ],
+ "include": ["**/*.ts"],
"exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"]
}
diff --git a/packages/lit-node-client/tsconfig.spec.json b/packages/lit-node-client/tsconfig.spec.json
index df5eec354a..a2f7dd30d7 100644
--- a/packages/lit-node-client/tsconfig.spec.json
+++ b/packages/lit-node-client/tsconfig.spec.json
@@ -2,15 +2,9 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
- "module": "ES2022",
+ "module": "commonjs",
"types": ["jest", "node"],
"allowJs": true
},
- "include": [
- "jest.config.ts",
- "**/*.test.ts",
- "**/*.spec.ts",
- "**/*.d.ts",
- "../auth-browser/src/lib/chains/lit-connect-modal.d.ts"
- ]
+ "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
}
diff --git a/packages/logger/README.md b/packages/logger/README.md
index 671f265971..e20602eadc 100644
--- a/packages/logger/README.md
+++ b/packages/logger/README.md
@@ -1,6 +1,6 @@
# logger
-This library was generated with [Nx](https://nx.dev).
+This package provides a centralized logging utility for the Lit Protocol SDK, offering structured logging capabilities across all packages. It is based in pino logger for minimal overhead and enables consistent log formatting, level-based filtering, and standardized error reporting throughout the Lit Protocol ecosystem.
## Building
diff --git a/packages/logger/src/lib/logger.spec.ts b/packages/logger/src/lib/logger.spec.ts
index a033af9426..0cd4983395 100644
--- a/packages/logger/src/lib/logger.spec.ts
+++ b/packages/logger/src/lib/logger.spec.ts
@@ -1,129 +1,68 @@
-import { LOG_LEVEL, LogLevel, LogManager } from './logger';
+import { Writable } from 'stream';
-describe('logger', () => {
- let lm: LogManager;
- beforeEach(() => {
- LogManager.clearInstance();
- lm = LogManager.Instance;
- });
-
- it('Log Manager singleton should be defined', () => {
- expect(typeof lm).toEqual('object');
- });
-
- it('should make logger with category', () => {
- const logger = lm.get('category');
- expect(logger.category).toEqual('category');
- });
-
- it('should make logger with id and category', () => {
- const logger = lm.get('category', 'foo');
- expect(logger.id).toEqual('foo');
- });
-
- it('Log Manager should pass config to loggers', () => {
- lm.withConfig({
- condenseLogs: true,
- });
- const logger = lm.get('category');
- expect(logger.Config?.['condenseLogs']).toEqual(true);
- });
-
- it('Hashing enabled should filter non unique logs', () => {
- lm.withConfig({
- condenseLogs: true,
- });
- const logger = lm.get('category', 'bar');
- logger.setLevel(LOG_LEVEL.INFO);
- expect(logger.Config?.['condenseLogs']).toEqual(true);
- logger.info('hello');
- logger.info('hello');
- const logs = lm.getLogsForId('bar');
- expect(logs.length).toEqual(1);
- });
+import { logger, setLoggerOptions, getChildLogger } from './logger';
- it('should respect info logging level', () => {
- const logger = lm.get('info-logger', 'foo');
- logger.setLevel(LOG_LEVEL.INFO);
- logger.info('logging');
- logger.debug('shouldnt log');
- const logs = lm.getLogsForId('foo');
- expect(logs.length).toEqual(1);
- });
+class TestStream extends Writable {
+ public data = '';
- it('should log error at any level', () => {
- const logger = lm.get('info-logger', 'foo2');
- logger.setLevel(LOG_LEVEL.DEBUG);
- logger.debug('logging');
- logger.error('error');
- const logs = lm.getLogsForId('foo2');
- expect(logs.length).toEqual(2);
- });
+ override _write(
+ chunk: { toString: () => string },
+ encoding: string,
+ callback: () => void
+ ) {
+ this.data += chunk.toString();
+ callback();
+ }
+}
- it('should safe serialize circular references', () => {
- const logger = lm.get('info-logger', 'foo3');
- logger.setLevel(LOG_LEVEL.DEBUG);
- const circ: any = { foo: 'bar' };
- circ.circ = circ;
- logger.debug('circular reference to serialize', circ);
- console.log(lm.getLogsForId('foo3'));
- expect(lm.getLogsForId('foo3').length).toEqual(1);
+describe('logger', () => {
+ it('should have default level "info"', () => {
+ expect(logger.level).toBe('info');
});
- it('should trace logs through multiple categories', () => {
- const logger = lm.get('info-logger', 'foo4');
- logger.setLevel(LOG_LEVEL.DEBUG);
- const logger2 = lm.get('debug-logger', 'foo4');
- logger2.setLevel(LOG_LEVEL.DEBUG);
- logger2.debug('foo');
- logger.debug('bar');
- expect(lm.getLogsForId('foo4').length).toEqual(2);
+ it('setLoggerOptions should update logger options', () => {
+ const testLogger = setLoggerOptions({ level: 'debug', name: 'TestLogger' });
+ expect(testLogger.level).toBe('debug');
});
- it('should not persist logs if level set to OFF', () => {
- const count = 1_000;
- for (let i = 0; i < count; i++) {
- const logger = lm.get('' + i, 'foo5');
- logger.setLevel(LOG_LEVEL.OFF);
- logger.debug(i + '');
- }
-
- expect(lm.getLogsForId('foo5').length).toEqual(0);
+ it('getChildLogger should create a child logger', () => {
+ const childLogger = getChildLogger({ module: 'childTest' });
+ expect(typeof childLogger.child).toBe('function');
+ expect(() => childLogger.info('Child logger test message')).not.toThrow();
});
- it('should persist logs across categories', async () => {
- const count = 10_000;
- for (let i = 0; i < count; i++) {
- const logger = lm.get('' + i, 'foo6');
- logger.setLevel(LOG_LEVEL.DEBUG);
- logger.debug(i + '');
- }
-
- expect(lm.getLogsForId('foo6').length).toEqual(count);
+ it('should log messages correctly on the parent logger', (done) => {
+ // Override the global logger with a test logger using our own destination stream:
+ const testStream = new TestStream();
+ const testLogger = setLoggerOptions(
+ { level: 'info', name: 'ParentTestLogger' },
+ testStream
+ );
+ testLogger.info('Parent message');
+
+ // Give a small amount time for the stream to process the log
+ setTimeout(() => {
+ expect(testStream.data).toMatch(/Parent message/);
+ done();
+ }, 50);
});
- it('should retain logger keys and return from LogManager', () => {
- const count = 10;
- for (let i = 0; i < count; i++) {
- const logger = lm.get('' + i, 'foo7');
- logger.setLevel(LogLevel.DEBUG);
- logger.debug(i + '');
- }
-
- expect(lm.getLogsForId('foo7').length).toEqual(count);
- expect(lm.LoggerIds.length).toEqual(10);
- });
-
- it('should order logs based on logger creation timestamp', async () => {
- const loggerA = lm.get('a', '1');
- await new Promise((res) => setTimeout(res, 100));
- const loggerB = lm.get('b', '2');
-
- const requestIds = lm.LoggerIds;
-
- expect(requestIds.length).toBe(2);
- expect(loggerA.timestamp).toBeLessThan(loggerB.timestamp);
- expect(requestIds[0]).toBe('1');
- expect(requestIds[1]).toBe('2');
+ it('should log messages on a child logger using the parent transport but adding its bindings', (done) => {
+ // Override the global logger for consistency in our test:
+ const testStream = new TestStream();
+ setLoggerOptions({ level: 'info', name: 'ParentTestLogger' }, testStream);
+ const childLogger = getChildLogger({ module: 'ChildModule' });
+ childLogger.info('Child message');
+
+ setTimeout(() => {
+ try {
+ expect(testStream.data).toMatch('"name":"ParentTestLogger"');
+ expect(testStream.data).toMatch('"msg":"Child message"');
+ expect(testStream.data).toMatch('"module":"ChildModule"');
+ done();
+ } catch (error) {
+ done(error);
+ }
+ }, 50);
});
});
diff --git a/packages/logger/src/lib/logger.ts b/packages/logger/src/lib/logger.ts
index 8af393f5e8..27021c6ea4 100644
--- a/packages/logger/src/lib/logger.ts
+++ b/packages/logger/src/lib/logger.ts
@@ -1,551 +1,32 @@
-import { version, LOG_LEVEL, LOG_LEVEL_VALUES } from '@lit-protocol/constants';
-import { hashMessage } from 'ethers/lib/utils';
-export { LOG_LEVEL };
+import { pino, Logger as Pino, LoggerOptions, DestinationStream } from 'pino';
-export enum LogLevel {
- OFF = -1,
- ERROR = 0,
- INFO = 1,
- DEBUG = 2,
- WARN = 3,
- FATAL = 4,
- TIMING_START = 5,
- TIMING_END = 6,
-}
-
-const colours = {
- reset: '\x1b[0m',
- bright: '\x1b[1m',
- dim: '\x1b[2m',
- underscore: '\x1b[4m',
- blink: '\x1b[5m',
- reverse: '\x1b[7m',
- hidden: '\x1b[8m',
-
- fg: {
- black: '\x1b[30m',
- red: '\x1b[31m',
- green: '\x1b[32m',
- yellow: '\x1b[33m',
- blue: '\x1b[34m',
- magenta: '\x1b[35m',
- cyan: '\x1b[36m',
- white: '\x1b[37m',
- gray: '\x1b[90m',
- crimson: '\x1b[38m', // Scarlet
- },
- bg: {
- black: '\x1b[40m',
- red: '\x1b[41m',
- green: '\x1b[42m',
- yellow: '\x1b[43m',
- blue: '\x1b[44m',
- magenta: '\x1b[45m',
- cyan: '\x1b[46m',
- white: '\x1b[47m',
- gray: '\x1b[100m',
- crimson: '\x1b[48m',
- },
+const DEFAULT_LOGGER_OPTIONS = {
+ name: 'LitProtocolSDK',
+ level: 'info',
};
-function _convertLoggingLevel(level: LOG_LEVEL_VALUES): string {
- switch (level) {
- case LOG_LEVEL.INFO:
- return `${colours.fg.green}[INFO]${colours.reset}`;
- case LOG_LEVEL.DEBUG:
- return `${colours.fg.cyan}[DEBUG]${colours.reset}`;
- case LOG_LEVEL.WARN:
- return `${colours.fg.yellow}[WARN]${colours.reset}`;
- case LOG_LEVEL.ERROR:
- return `${colours.fg.red}[ERROR]${colours.reset}`;
- case LOG_LEVEL.FATAL:
- return `${colours.fg.red}[FATAL]${colours.reset}`;
- case LOG_LEVEL.TIMING_START:
- return `${colours.fg.green}[TIME_START]${colours.reset}`;
- case LOG_LEVEL.TIMING_END:
- return `${colours.fg.green}[TIME_END]${colours.reset}`;
- }
-
- return '[UNKNOWN]';
-}
-
-function _resolveLoggingHandler(level: LOG_LEVEL_VALUES): any {
- switch (level) {
- case LOG_LEVEL.DEBUG:
- return console.debug;
- case LOG_LEVEL.INFO:
- return console.info;
- case LOG_LEVEL.ERROR:
- return console.error;
- case LOG_LEVEL.WARN:
- return console.warn;
- case LOG_LEVEL.FATAL:
- return console.error;
- case LOG_LEVEL.TIMING_END:
- return console.timeLog;
- case LOG_LEVEL.TIMING_START:
- return console.time;
- }
-}
-
-/**
- * Implementation of `JSON.stringify` which removes circular object references
- * @example
- * let circ = {foo: 'bar'};
- * circ.circ = circ; // creates a circular reference
- * _safeStringify(circ) -> {foo: 'bar'}
- * @param obj object to check for circular references
- * @param indent number of indents to include (spaces)
- * @returns obj param without without circular references
- */
-function _safeStringify(obj: any, indent = 2) {
- let cache: any[] | null = [];
- const retVal = JSON.stringify(
- obj,
- (_key, value) =>
- typeof value === 'object' && value !== null
- ? cache?.includes(value)
- ? undefined // Duplicate reference found, discard key
- : cache?.push(value) && value // Store value in our collection
- : value,
- indent
+type Logger = Pino;
+let logger: Logger = pino(DEFAULT_LOGGER_OPTIONS);
+
+function setLoggerOptions(
+ loggerOptions: LoggerOptions,
+ destination?: DestinationStream
+): Logger {
+ logger = pino(
+ {
+ ...DEFAULT_LOGGER_OPTIONS,
+ ...loggerOptions,
+ },
+ destination
);
- cache = null;
- return retVal;
-}
-interface ILog {
- timestamp: string;
- message: string;
- args: any[];
- id: string;
- category: string;
- level: LOG_LEVEL_VALUES;
- error?: any;
- toString(): string;
- toJSON(): Record;
+ return logger;
}
-class Log implements ILog {
- timestamp: string;
- message: string;
- args: any[];
- id: string;
- category: string;
- level: LOG_LEVEL_VALUES;
- error?: any;
-
- constructor(
- timestamp: string,
- message: string,
- args: any[],
- id: string,
- category: string,
- level: LOG_LEVEL_VALUES
- ) {
- this.timestamp = timestamp;
- this.message = message;
- this.args = args;
- this.id = id;
- this.category = category;
- this.level = level;
- }
-
- toString(): string {
- let fmtStr: string = `[Lit-JS-SDK v${version}]${_convertLoggingLevel(
- this.level
- )} [${this.category}] [id: ${this.id}] ${this.message}`;
- for (let i = 0; i < this.args.length; i++) {
- if (typeof this.args[i] === 'object') {
- fmtStr = `${fmtStr} ${_safeStringify(this.args[i])}`;
- } else {
- fmtStr = `${fmtStr} ${this.args[i]}`;
- }
- }
- return fmtStr;
- }
-
- toArray(): string[] {
- const args = [];
- args.push(`[Lit-JS-SDK v${version}]`);
- args.push(`[${this.timestamp}]`);
- args.push(_convertLoggingLevel(this.level));
- args.push(`[${this.category}]`);
-
- this.id && args.push(`${colours.fg.cyan}[id: ${this.id}]${colours.reset}`);
- this.message && args.push(this.message);
-
- for (let i = 0; i < this.args.length; i++) {
- args.push(this.args[i]);
- }
-
- return args;
- }
-
- toJSON(): Record {
- return {
- timestamp: this.timestamp,
- message: this.message,
- args: this.args,
- id: this.id,
- category: this.category,
- level: this.level,
- };
- }
+function getChildLogger(
+ ...childParams: Parameters
+): Logger {
+ return logger.child(...childParams);
}
-export type messageHandler = (log: Log) => void;
-
-export class Logger {
- private _category: string;
- private _level: LOG_LEVEL_VALUES;
- private _id: string;
- private _handler: messageHandler | undefined;
- private _consoleHandler: any;
- private _logs: Log[] = [];
- private _logHashes: Map = new Map();
- private _config: Record | undefined;
- private _isParent: boolean;
- private _children: Map;
- private _timestamp: number;
-
- public static createLogger(
- category: string,
- level: LOG_LEVEL_VALUES,
- id: string,
- isParent: boolean,
- config?: Record
- ): Logger {
- return new Logger(category, level, id, isParent, config);
- }
-
- private constructor(
- category: string,
- level: LOG_LEVEL_VALUES,
- id: string,
- isParent: boolean,
- config?: Record
- ) {
- this._category = category;
- this._level = level;
- this._id = id;
- this._consoleHandler = _resolveLoggingHandler(this._level);
- this._config = config;
- this._children = new Map();
- this._isParent = isParent;
- this._timestamp = Date.now();
- }
-
- get id(): string {
- return this._id;
- }
-
- get category(): string {
- return this._category;
- }
-
- get timestamp(): number {
- return this._timestamp;
- }
-
- get Logs(): Log[] {
- return this._logs;
- }
-
- set Config(value: Record | undefined) {
- this._config = value;
- }
-
- get Config(): Record | undefined {
- return this._config;
- }
-
- get Children(): Map {
- return this._children;
- }
-
- public setLevel(level: LOG_LEVEL_VALUES): void {
- this._level = level;
- }
-
- public setHandler(handler: messageHandler) {
- this._handler = handler;
- }
-
- public info(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.INFO, message, ...args);
- }
-
- public debug(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.DEBUG, message, ...args);
- }
-
- public warn(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.WARN, message, args);
- }
-
- public error(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.ERROR, message, ...args);
- }
-
- public fatal(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.FATAL, message, ...args);
- }
-
- public trace(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.FATAL, message, ...args);
- }
-
- public timeStart(message: string = '', ...args: any[]): void {
- this._log(LOG_LEVEL.TIMING_START, message, ...args);
- }
-
- public timeEnd(message: string = '', ...args: any[]): void {
- this._level < LOG_LEVEL.OFF &&
- this._log(LOG_LEVEL.TIMING_END, message, ...args);
- }
-
- private _log(
- level: LOG_LEVEL_VALUES,
- message: string = '',
- ...args: any[]
- ): void {
- const log = new Log(
- new Date().toISOString(),
- message,
- args,
- this._id,
- this._category,
- level
- );
-
- const arrayLog = log.toArray();
- if (this._config?.['condenseLogs'] && !this._checkHash(log)) {
- (this._level >= level || level === LogLevel.ERROR) &&
- this._consoleHandler &&
- this._consoleHandler(...arrayLog);
- (this._level >= level || level === LOG_LEVEL.ERROR) &&
- this._handler &&
- this._handler(log);
-
- (this._level >= level || level === LogLevel.ERROR) && this._addLog(log);
- } else if (!this._config?.['condenseLogs']) {
- (this._level >= level || level === LogLevel.ERROR) &&
- this._consoleHandler &&
- this._consoleHandler(...arrayLog);
- (this._level >= level || level === LOG_LEVEL.ERROR) &&
- this._handler &&
- this._handler(log);
- (this._level >= level || level === LOG_LEVEL.ERROR) && this._addLog(log);
- }
- }
-
- private _checkHash(log: Log): boolean {
- const strippedMessage = this._cleanString(log.message);
- const digest = hashMessage(strippedMessage);
- const hash = digest.toString();
- const item = this._logHashes.get(hash);
- if (item) {
- return true;
- } else {
- this._logHashes.set(hash, true);
- return false;
- }
- }
-
- private _addLog(log: Log) {
- this._logs.push(log);
- // TODO: currently we are not deleting old request id's which over time will fill local storage as the maximum storage size is 10mb
- // we should be deleting keys from the front of the collection of `Object.keys(category)` such that the first keys entered are deleted when we reach a pre defined key threshold
- // this implementation assumes that serialization / deserialization from `localStorage` keeps the same key ordering in each `category` object as we will asssume the array produced from `Object.keys` will always be the same ordering.
- // which then allows us to start at the front of the array and do `delete` operation on each key we wish to delete from the object.
- //log.id && this._addToLocalStorage(log);
- }
-
- private _addToLocalStorage(log: Log) {
- if (globalThis.localStorage) {
- let bucket: Record | string | null =
- globalThis.localStorage.getItem(log.category);
- if (bucket) {
- bucket = JSON.parse(bucket) as Record;
- if (!bucket[log.id]) {
- bucket[log.id] = [];
- }
- bucket[log.id].push(log.toString());
- globalThis.localStorage.setItem(log.category, _safeStringify(bucket));
- } else {
- const bucket: Record = {};
- bucket[log.id] = [log.toString()];
- globalThis.localStorage.setItem(log.category, _safeStringify(bucket));
- }
- }
- }
-
- /**
- *
- * @param input string which will be cleaned of non utf-8 characters
- * @returns {string} input cleaned of non utf-8 characters
- */
- private _cleanString(input: string): string {
- let output = '';
- for (let i = 0; i < input.length; i++) {
- if (input.charCodeAt(i) <= 127) {
- output += input.charAt(i);
- }
- }
- return output;
- }
-}
-
-export class LogManager {
- private static _instance: LogManager;
- private _loggers: Map;
- private _level: LOG_LEVEL_VALUES | undefined = LOG_LEVEL.DEBUG;
- private _config: Record | undefined;
-
- static get Instance(): LogManager {
- if (!LogManager._instance) {
- LogManager._instance = new LogManager();
- }
- return LogManager._instance;
- }
-
- static clearInstance() {
- (LogManager._instance as any) = undefined;
- }
-
- private constructor() {
- this._loggers = new Map();
- }
-
- public withConfig(config: Record) {
- this._config = config;
- for (const logger of this._loggers) {
- logger[1].Config = config;
- }
- }
-
- public setLevel(level: LOG_LEVEL_VALUES) {
- this._level = level;
- for (const logger of this._loggers) {
- logger[1].setLevel(level);
- }
- }
-
- public setHandler(handler: messageHandler) {
- for (const logger of this._loggers) {
- logger[1].setHandler(handler);
- }
- }
-
- get LoggerIds(): string[] {
- const keys: [string, number][] = [];
- for (const category of this._loggers.entries()) {
- for (const child of category[1].Children) {
- keys.push([child[0], child[1].timestamp]);
- }
- }
-
- return keys
- .sort((a: [string, number], b: [string, number]) => {
- return a[1] - b[1];
- })
- .map((value: [string, number]) => {
- return value[0];
- });
- }
-
- // if a logger is given an id it will persist logs under its logger instance
- public get(category: string, id?: string): Logger {
- let instance = this._loggers.get(category);
- if (!instance && !id) {
- this._loggers.set(
- category,
- Logger.createLogger(category, this._level ?? LOG_LEVEL.INFO, '', true)
- );
-
- instance = this._loggers.get(category) as Logger;
- instance.Config = this._config;
- return instance;
- }
-
- if (id) {
- if (!instance) {
- this._loggers.set(
- category,
- Logger.createLogger(category, this._level ?? LOG_LEVEL.INFO, '', true)
- );
-
- instance = this._loggers.get(category) as Logger;
- instance.Config = this._config;
- }
- const children = instance?.Children;
- let child = children?.get(id);
- if (child) {
- return child;
- }
- children?.set(
- id,
- Logger.createLogger(
- category,
- this._level ?? LOG_LEVEL.INFO,
- id ?? '',
- true
- )
- );
-
- child = children?.get(id) as Logger;
- child.Config = this._config;
- return children?.get(id) as Logger;
- // fall through condition for if there is no id for the logger and the category is not yet created.
- // ex: LogManager.Instance.get('foo');
- } else if (!instance) {
- this._loggers.set(
- category,
- Logger.createLogger(category, this._level ?? LOG_LEVEL.INFO, '', true)
- );
-
- instance = this._loggers.get(category) as Logger;
- instance.Config = this._config;
- }
-
- return instance as Logger;
- }
-
- getById(id: string): string[] {
- let logStrs: string[] = [];
- for (const category of this._loggers.entries()) {
- const logger = category[1].Children.get(id);
- if (logger) {
- const logStr = [];
- for (const log of logger.Logs) {
- logStr.push(log.toString());
- }
- logStrs = logStrs.concat(logStr);
- }
- }
-
- return logStrs;
- }
-
- public getLogsForId(id: string): string[] {
- let logsForRequest: string[] = this.getById(id);
- if (logsForRequest.length < 1 && globalThis.localStorage) {
- for (const category of this._loggers.keys()) {
- const bucketStr: string | null =
- globalThis.localStorage.getItem(category);
- const bucket: Record = JSON.parse(
- bucketStr as string
- );
- if (bucket && bucket[id]) {
- const logsForId: string[] = bucket[id].filter((log: string) =>
- log.includes(id)
- );
- logsForRequest = logsForId.concat(logsForRequest);
- }
- }
- }
-
- return logsForRequest;
- }
-}
+export { Logger, logger, setLoggerOptions, getChildLogger };
diff --git a/packages/misc-browser/src/lib/misc-browser.ts b/packages/misc-browser/src/lib/misc-browser.ts
index 9c2b0d96a5..12b060e341 100644
--- a/packages/misc-browser/src/lib/misc-browser.ts
+++ b/packages/misc-browser/src/lib/misc-browser.ts
@@ -1,46 +1,44 @@
import {
- ELeft,
- ERight,
- IEither,
- InvalidArgumentException,
LocalStorageItemNotFoundException,
LocalStorageItemNotRemovedException,
LocalStorageItemNotSetException,
} from '@lit-protocol/constants';
-import {
- uint8arrayFromString,
- uint8arrayToString,
-} from '@lit-protocol/uint8arrays';
/**
+ * Get the local storage item by key.
*
- * Get the local storage item by key
- *
- * @param { string } key
+ * @param {string} key The key to retrieve.
+ * @returns {string} The stored string.
+ * @throws Will throw an error if reading from localStorage fails or the item is not found.
*/
-export const getStorageItem = (key: string): IEither => {
- let item;
+export const getStorageItem = (key: string): string => {
+ let item: string | null;
try {
item = localStorage.getItem(key);
} catch (e) {
- // swallowing
+ throw new LocalStorageItemNotFoundException(
+ {
+ info: {
+ storageKey: key,
+ },
+ cause: e,
+ },
+ `Error reading localStorage for key "${key}"`
+ );
}
if (!item) {
- return ELeft(
- new LocalStorageItemNotFoundException(
- {
- info: {
- storageKey: key,
- },
+ throw new LocalStorageItemNotFoundException(
+ {
+ info: {
+ storageKey: key,
},
- `Failed to get %s from local storage`,
- key
- )
+ },
+ `Failed to find ${key} in local storage`
);
}
- return ERight(item);
+ return item;
};
/**
@@ -50,21 +48,20 @@ export const getStorageItem = (key: string): IEither => {
* @param { string } key is the key to set
* @param { string } value is the value to set
*/
-export const setStorageItem = (key: string, value: string): IEither => {
+export const setStorageItem = (key: string, value: string): string => {
try {
localStorage.setItem(key, value);
- return ERight(value);
+ return value;
} catch (e) {
- return ELeft(
- new LocalStorageItemNotSetException(
- {
- info: {
- storageKey: key,
- },
+ throw new LocalStorageItemNotSetException(
+ {
+ info: {
+ storageKey: key,
},
- `Failed to set %s in local storage`,
- key
- )
+ cause: e,
+ },
+ `Failed to set %s in local storage`,
+ key
);
}
};
@@ -74,176 +71,22 @@ export const setStorageItem = (key: string, value: string): IEither => {
* Remove the local storage item by key
*
* @param { string } key is the key to remove
- * @returns { IEither } Either the key or an error
+ * @returns { string } the key removed
*/
-export const removeStorageItem = (key: string): IEither => {
+export const removeStorageItem = (key: string): string => {
try {
localStorage.removeItem(key);
- return ERight(key);
+ return key;
} catch (e) {
- return ELeft(
- new LocalStorageItemNotRemovedException(
- {
- info: {
- storageKey: key,
- },
- },
- `Failed to remove %s from local storage`,
- key
- )
- );
- }
-};
-
-/**
- * Convert a Blob to a base64urlpad string. Note: This function returns a promise.
- *
- * @param { Blob | File } blob The Blob or File to turn into a base64 string
- * @returns { Promise } A promise that resolves to the base64 string
- */
-export const blobToBase64String = async (
- blob: Blob | File
-): Promise => {
- const arrayBuffer = await blob.arrayBuffer();
-
- const uint8array = new Uint8Array(arrayBuffer);
-
- return uint8arrayToString(uint8array, 'base64urlpad');
-};
-
-/**
- *
- * Convert a base64urlpad string to a Blob.
- * Note: This function DOES NOT return a promise
- *
- * @param { string } base64String The base64 string that to turn into a Blob
- * @returns { Blob } A blob that contains the decoded base64 data
- */
-export const base64StringToBlob = (base64String: string): Blob => {
- return new Blob([uint8arrayFromString(base64String, 'base64urlpad')]);
-};
-
-/**
- *
- * Convert a file to a data URL, which could then be embedded in a LIT.
- * A data URL is a string representation of a file.
- *
- * @param { File } file The file to turn into a data url
- * @returns { string } The data URL. This is a string representation that can be used anywhere the original file would be used.
- */
-export const fileToDataUrl = (
- file: File
-): Promise => {
- return new Promise((resolve) => {
- const reader = new FileReader();
- reader.onloadend = () => {
- resolve(reader.result);
- };
- reader.readAsDataURL(file);
- });
-};
-
-/**
- *
- * // TEST: downloadFile
- * Download a file in memory to the user's computer
- *
- * @param { Object } params
- * @property { string } filename The name of the file
- * @property { Uint8Array } data The actual file itself as a Uint8Array
- * @property { string } mimetype The mime type of the file
- *
- * @returns { void } The data URL. This is a string representation that can be used anywhere the original file would be used.
- *
- */
-export const downloadFile = ({
- fileName,
- data,
- mimeType,
-}: {
- fileName: string;
- data: Uint8Array;
- mimeType: string;
-}): void => {
- const element = document.createElement('a');
-
- element.setAttribute(
- 'href',
- 'data:' + mimeType + ';base64,' + uint8arrayToString(data, 'base64')
- );
- element.setAttribute('download', fileName);
-
- element.style.display = 'none';
-
- document.body.appendChild(element);
-
- element.click();
-
- document.body.removeChild(element);
-};
-
-/**
- *
- * // TEST: injectViewerIFrame
- * Inject an iFrame into the current page that will display a LIT.
- * This function safely sandboxes the content in the iFrame so that the LIT cannot see cookies or localStorage of the parent website.
- *
- * @param { Object } params
- * @property { string } destinationId The DOM ID of the element to inject the iFrame into
- * @property { string } title The title of the content being displayed
- * @property { string } fileUrl The URL of the content that will be shown in the iFrame
- * @property { string } className An optional DOM class name to add to the iFrame for styling
- *
- * @returns { void }
- */
-export const injectViewerIFrame = ({
- destinationId,
- title,
- fileUrl,
- className,
-}: {
- destinationId: string;
- title: string;
- fileUrl: string;
- className: string;
-}): void => {
- if (fileUrl.includes('data:')) {
- // data urls are not safe, refuse to do this
- throw new InvalidArgumentException(
- {
- info: {
- fileUrl,
- },
- },
- 'You can not inject an iFrame with a data url. Try a regular https URL.'
- );
- }
-
- const url = new URL(fileUrl);
- if (url.host.toLowerCase() === window.location.host.toLowerCase()) {
- throw new InvalidArgumentException(
+ throw new LocalStorageItemNotRemovedException(
{
info: {
- fileUrl,
+ storageKey: key,
},
+ cause: e,
},
- 'You cannot host a LIT on the same domain as the parent webpage. This is because iFrames with the same origin have access to localstorage and cookies in the parent webpage which is unsafe'
+ `Failed to remove %s from local storage`,
+ key
);
}
-
- const iframe = Object.assign(document.createElement('iframe'), {
- src: fileUrl,
- title: title,
- sandbox:
- 'allow-forms allow-scripts allow-popups allow-modals allow-popups-to-escape-sandbox allow-same-origin',
- loading: 'lazy',
- allow:
- 'accelerometer; ambient-light-sensor; autoplay; battery; camera; display-capture; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr; screen-wake-lock; web-share; xr-spatial-tracking',
- });
-
- if (className) {
- iframe.className = className;
- }
-
- document.getElementById(destinationId)?.appendChild(iframe);
};
diff --git a/packages/misc/.babelrc b/packages/misc/.babelrc
deleted file mode 100644
index 158083d278..0000000000
--- a/packages/misc/.babelrc
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presets": [
- [
- "@nx/web/babel",
- {
- "useBuiltIns": "usage"
- }
- ]
- ]
-}
diff --git a/packages/misc/.eslintrc.json b/packages/misc/.eslintrc.json
deleted file mode 100644
index 9d9c0db55b..0000000000
--- a/packages/misc/.eslintrc.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "extends": ["../../.eslintrc.json"],
- "ignorePatterns": ["!**/*"],
- "overrides": [
- {
- "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
- "rules": {}
- },
- {
- "files": ["*.ts", "*.tsx"],
- "rules": {}
- },
- {
- "files": ["*.js", "*.jsx"],
- "rules": {}
- }
- ]
-}
diff --git a/packages/misc/README.md b/packages/misc/README.md
deleted file mode 100644
index 381773dbee..0000000000
--- a/packages/misc/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Quick Start
-
-This submodule contains various utility functions for error handling, logging, type checking, and other operations in the JavaScript SDK for the Lit Protocol.
-
-### node.js / browser
-
-```
-yarn add @lit-protocol/misc
-```
diff --git a/packages/misc/src/index.ts b/packages/misc/src/index.ts
deleted file mode 100644
index c2ec7a0691..0000000000
--- a/packages/misc/src/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export * from './lib/addresses';
-export * from './lib/misc';
-export * from './lib/params-validators';
-export * from './lib/utils';
-export {
- validateSessionSig,
- validateSessionSigs,
-} from './lib/helper/session-sigs-validator';
-export { formatSessionSigs } from './lib/helper/session-sigs-reader';
diff --git a/packages/misc/src/lib/misc.spec.ts b/packages/misc/src/lib/misc.spec.ts
deleted file mode 100644
index f20dc60508..0000000000
--- a/packages/misc/src/lib/misc.spec.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-// @ts-nocheck
-import { TextEncoder, TextDecoder } from 'util';
-global.TextEncoder = TextEncoder;
-// @ts-ignore
-global.TextDecoder = TextDecoder;
-
-import * as utilsModule from './misc';
-
-describe('utils', () => {
- /**
- * Print Error
- */
- it('should console.log with name, message and stack', () => {
- let err: Error;
-
- try {
- throw new Error('Test Error');
- } catch (e) {
- err = e as Error;
- }
-
- console.log = jest.fn();
-
- utilsModule.printError(err);
-
- expect((console.log as any).mock.calls[0][0]).toBe('Error Stack');
- expect((console.log as any).mock.calls[1][0]).toBe('Error Name');
- expect((console.log as any).mock.calls[2][0]).toBe('Error Message');
- });
-
- it('should get the most common string in an array', () => {
- const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 8];
-
- const mostOccured = utilsModule.mostCommonString(arr);
-
- expect(mostOccured).toBe(8);
- });
-
- it('should get the last element of the array if every element only appears once', () => {
- const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
-
- const mostOccured = utilsModule.mostCommonString(arr);
-
- expect(mostOccured).toBe(0);
- });
-
- it('should get value type by a given value', () => {
- const fooString = 'fooString';
- const fooBool = true;
- const fooNumber = 6;
- const fooList: number[] = [1, 2, 3];
- const fooArray: string[] = ['a', 'b', 'c'];
- const fooTuple: [string, number] = ['hello', 10];
- const fooUint8Arr = new Uint8Array([1, 2, 3, 4, 5]);
- const fooUint16Arr = new Uint16Array([1, 2, 3, 4, 5]);
- const fooBlob = new Blob([fooUint8Arr as BlobPart], {});
- const fooFile = new File([fooUint8Arr as BlobPart], '');
-
- expect(utilsModule.getVarType(fooString)).toBe('String');
- expect(utilsModule.getVarType(fooBool)).toBe('Boolean');
- expect(utilsModule.getVarType(fooNumber)).toBe('Number');
- expect(utilsModule.getVarType(fooList)).toBe('Array');
- expect(utilsModule.getVarType(fooArray)).toBe('Array');
- expect(utilsModule.getVarType(fooTuple)).toBe('Array');
- expect(utilsModule.getVarType(fooUint8Arr)).toBe('Uint8Array');
- expect(utilsModule.getVarType(fooUint16Arr)).toBe('Uint16Array');
- expect(utilsModule.getVarType(fooBlob)).toBe('Blob');
- expect(utilsModule.getVarType(fooFile)).toBe('File');
- });
-
- it('should check type', () => {
- expect(
- utilsModule.checkType({
- value: 999,
- allowedTypes: ['Number'],
- paramName: 'paramName1',
- functionName: 'functionName1',
- })
- ).toBe(true);
-
- expect(
- utilsModule.checkType({
- value: 'foo',
- allowedTypes: ['Number', 'String'],
- paramName: 'paramName2',
- functionName: 'functionName2',
- })
- ).toBe(true);
-
- expect(
- utilsModule.checkType({
- value: [1, 2],
- allowedTypes: ['Number', 'Array'],
- paramName: 'paramName3',
- functionName: 'functionName3',
- })
- ).toBe(true);
-
- expect(
- utilsModule.checkType({
- value: new Uint8Array([1, 2, 3]),
- allowedTypes: ['String', 'Uint8Array'],
- paramName: 'paramName4',
- functionName: 'functionName4',
- })
- ).toBe(true);
- });
-
- it('should check auth type', () => {
- const authSig = {
- sig: '',
- derivedVia: 'web3.eth.personal.sign',
- signedMessage:
- 'I am creating an account to use Lit Protocol at 2022-04-12T09:23:31.290Z',
- address: '0x7e7763BE1379Bb48AFEE4F5c232Fb67D7c03947F',
- };
-
- expect(
- utilsModule.checkIfAuthSigRequiresChainParam(authSig, 'ethereum', 'fName')
- ).toBe(true);
-
- expect(
- utilsModule.checkIfAuthSigRequiresChainParam(
- {
- ethereum: 'foo',
- },
- '123',
- 'fName'
- )
- ).toBe(true);
- });
-});
-
-describe('double escaped JSON string', () => {
- test('A doubly escaped JSON string', () => {
- const doublyEscapedJson = '{\\"key\\": \\"value\\"}';
- expect(utilsModule.normalizeAndStringify(doublyEscapedJson)).toBe(
- '{"key":"value"}'
- );
- });
-
- test('A triply escaped JSON string', () => {
- const triplyEscapedJson = '{\\\\\\"key\\\\\\": \\\\\\"value\\\\\\"}';
- expect(utilsModule.normalizeAndStringify(triplyEscapedJson)).toBe(
- '{"key":"value"}'
- );
- });
-
- test('A correctly escaped JSON string (for comparison)', () => {
- const correctlyEscapedJson = '{"key":"value"}';
- expect(utilsModule.normalizeAndStringify(correctlyEscapedJson)).toBe(
- '{"key":"value"}'
- );
- });
-
- test('regular siwe message', () => {
- const regularString =
- 'litprotocol.com wants you to sign in with your Ethereum account:\\n0x3edB...';
-
- expect(utilsModule.normalizeAndStringify(regularString)).toBe(
- regularString
- );
- });
-});
-it('should remove hex prefix from a string', () => {
- const input = '0xabcdef';
- const expectedOutput = 'abcdef';
-
- const result = utilsModule.removeHexPrefix(input);
-
- expect(result).toBe(expectedOutput);
-});
-
-it('should not remove hex prefix if it is not present', () => {
- const input = 'abcdef';
- const expectedOutput = 'abcdef';
-
- const result = utilsModule.removeHexPrefix(input);
-
- expect(result).toBe(expectedOutput);
-});
-
-it('should get ip address', async () => {
- // polyfill fetch
- const fetch = require('node-fetch');
- global.fetch = fetch;
-
- const ipAddres = await utilsModule.getIpAddress('cayenne.litgateway.com');
- expect(ipAddres).toBe('207.244.70.36');
-});
diff --git a/packages/misc/src/lib/misc.ts b/packages/misc/src/lib/misc.ts
deleted file mode 100644
index 3888723540..0000000000
--- a/packages/misc/src/lib/misc.ts
+++ /dev/null
@@ -1,749 +0,0 @@
-import { Contract } from '@ethersproject/contracts';
-import { JsonRpcProvider } from '@ethersproject/providers';
-
-import {
- ABI_ERC20,
- InvalidArgumentException,
- InvalidParamType,
- LIT_AUTH_SIG_CHAIN_KEYS,
- LIT_CHAINS,
- LIT_NETWORK,
- LIT_NETWORK_VALUES,
- LOG_LEVEL,
- LOG_LEVEL_VALUES,
- LitEVMChainKeys,
- NetworkError,
- RELAYER_URL_BY_NETWORK,
- RemovedFunctionError,
- UnknownError,
- WrongNetworkException,
-} from '@lit-protocol/constants';
-import { LogManager } from '@lit-protocol/logger';
-import {
- Chain,
- AuthSig,
- NodeErrorV3,
- ClaimResult,
- LitNodeClientConfig,
- MintCallback,
- RelayClaimProcessor,
-} from '@lit-protocol/types';
-
-const logBuffer: any[][] = [];
-
-// Module scoped variable to store the LitNodeClientConfig passed to LitCore
-let litConfig: LitNodeClientConfig | undefined;
-
-export const setMiscLitConfig = (config: LitNodeClientConfig | undefined) => {
- litConfig = config;
-};
-
-/**
- *
- * Print error message based on Error interface
- *
- * @param { Error } e
- * @returns { void }
- */
-export const printError = (e: Error): void => {
- console.log('Error Stack', e.stack);
- console.log('Error Name', e.name);
- console.log('Error Message', e.message);
-};
-
-/**
- *
- * Find the element that occurs the most in an array
- *
- * @param { Array } arr
- * @returns { any } the element that appeared the most
- */
-export const mostCommonString = (arr: T[]): T | undefined => {
- return arr
- .sort(
- (a: T, b: T) =>
- arr.filter((v: T) => v === a).length -
- arr.filter((v: T) => v === b).length
- )
- .pop();
-};
-
-export const findMostCommonResponse = (responses: object[]): object => {
- const result: Record