From 1ad8753fa988e3fae87769b16e34d377d459fb2a Mon Sep 17 00:00:00 2001 From: Josh Long Date: Wed, 13 Sep 2023 17:05:38 -0400 Subject: [PATCH 01/10] updates for claim key comments and abstractions --- packages/core/src/lib/lit-core.ts | 39 ++++++++++++------- .../src/lib/providers/BaseProvider.ts | 23 +++++++++++ .../src/lib/lit-node-client-nodejs.ts | 5 ++- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/packages/core/src/lib/lit-core.ts b/packages/core/src/lib/lit-core.ts index 5af1ec4e83..54407371dd 100644 --- a/packages/core/src/lib/lit-core.ts +++ b/packages/core/src/lib/lit-core.ts @@ -1,4 +1,6 @@ import { computeHDPubKey } from '@lit-protocol/crypto'; +import { keccak256 } from '@ethersproject/keccak256'; +import { toUtf8Bytes } from '@ethersproject/strings'; import { canonicalAccessControlConditionFormatter, canonicalEVMContractConditionFormatter, @@ -46,6 +48,7 @@ import { SuccessNodePromises, SupportedJsonRequests, } from '@lit-protocol/types'; +import { ethers } from 'ethers'; export class LitCore { config: LitNodeClientConfig; @@ -590,7 +593,10 @@ export class LitCore { * @param sigType * @returns {string} public key */ - computeHDPubKey = (keyId: string, sigType: SIGTYPE = SIGTYPE.EcdsaCaitSith) => { + computeHDPubKey = ( + keyId: string, + sigType: SIGTYPE = SIGTYPE.EcdsaCaitSith + ) => { if (!this.hdRootPubkeys) { throwError({ message: `root public keys not found, have you connected to the nodes?`, @@ -601,20 +607,23 @@ export class LitCore { return computeHDPubKey(this.hdRootPubkeys as string[], keyId, sigType); }; - /** - * Telem collector for function invokation counts - * @param date - * @param functionName - * @param executionTime + * Calculates a Key Id for claiming a pkp based on a user identifier and an app identifier. + * The key Identifier is an Auth Method Id which scopes the key uniquely to a specific application context. + * These identifiers are specific to each auth method and will derive the public key protion of a pkp which will be persited + * when a key is claimed. + * | Auth Method | User ID | App ID | + * |:------------|:-------|:-------| + * | Google OAuth | token `sub` | token `aud` | + * | Discord OAuth | user id | client app identifier | + * | Stytch OTP |token `sub` | token `aud`| + * @param userId {string} user identifier for the Key Identifier + * @param appId {string} app identifier for the Key Identifier + * @returns {String} public key of pkp when claimed */ - collectData = (date: string, functionName: string, executionTime: number) => { - fetch(TELEM_API_URL + '/collect', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ date, functionName, executionTime }), - }); - }; + computeHDKeyId(userId: string, appId: string): String { + return ethers.utils.keccak256( + ethers.utils.toUtf8Bytes(`${userId}:${appId}`) + ); + } } diff --git a/packages/lit-auth-client/src/lib/providers/BaseProvider.ts b/packages/lit-auth-client/src/lib/providers/BaseProvider.ts index 113a62c439..745f5cca95 100644 --- a/packages/lit-auth-client/src/lib/providers/BaseProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/BaseProvider.ts @@ -200,6 +200,29 @@ export abstract class BaseProvider { const res = await this.litNodeClient.claimKeyId(claimRequest); return res; } + /** + * Calculates a public key for a given `key identifier` which is an `Auth Method Identifier` + * the Auth Method Identifier is a hash of a user identifier and app idendtifer. + * These identifiers are specific to each auth method and will derive the public key protion of a pkp which will be persited + * when a key is claimed. + * | Auth Method | User ID | App ID | + * |:------------|:-------|:-------| + * | Google OAuth | token `sub` | token `aud` | + * | Discord OAuth | user id | client app identifier | + * | Stytch OTP |token `sub` | token `aud`| + * @param userId + * @param appId + * @returns + */ + computPublicKeyFromAuthMethod = async ( + authMethod: AuthMethod + ): Promise => { + const authMethodId = await this.getAuthMethodId(authMethod); + if (!this.litNodeClient) { + throw new Error('Lit Node Client is configured'); + } + return this.litNodeClient.computeHDPubKey(authMethodId); + }; /** * Generate request data for minting and fetching PKPs via relay server 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 index 5154161d4e..1170af6e66 100644 --- 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 @@ -2101,8 +2101,8 @@ export class LitNodeClientNodeJs extends LitCore { errorCode: LIT_ERROR.LIT_NODE_CLIENT_NOT_READY_ERROR.name, }); } + const requestId = this.getRequestId(); const nodePromises = await this.getNodePromises((url: string) => { - const requestId = this.getRequestId(); const nodeRequestParams = { authMethod: params.authMethod, }; @@ -2163,8 +2163,9 @@ export class LitNodeClientNodeJs extends LitCore { mintTx, }; } else { + return throwError({ - message: 'claim request has failed', + message: `Claim request has failed. Request trace id: lit_${requestId} `, errorKind: LIT_ERROR.UNKNOWN_ERROR.kind, errorCode: LIT_ERROR.UNKNOWN_ERROR.code, }); From 805d41dd04791fd9a7538698a4e14ec0e7ef4aab Mon Sep 17 00:00:00 2001 From: Chris Cassano <1285652+glitch003@users.noreply.github.com> Date: Thu, 14 Sep 2023 01:08:09 -0700 Subject: [PATCH 02/10] Feature/easier local node testing (#215) * fix typescript errors with nodejs app * config and docs for testing against a local node * local testing works * restore cayenne contracts * add env var docs * cleanup --- README.md | 100 +++-- apps/html/index.html | 4 +- apps/nodejs/manual-test.ts | 370 +++++++++++++----- apps/react/src/app/app.tsx | 2 +- packages/contracts-sdk/fetch-contracts.mjs | 51 ++- .../contracts-sdk/lit-contracts.config.json | 7 +- .../contracts-sdk/src/abis/Allowlist.data.ts | 2 +- .../src/abis/ContractResolver.data.ts | 2 +- .../src/abis/Multisender.data.ts | 2 +- .../contracts-sdk/src/abis/PKPHelper.data.ts | 2 +- .../contracts-sdk/src/abis/PKPNFT.data.ts | 2 +- .../src/abis/PKPNFTMetadata.data.ts | 2 +- .../src/abis/PKPPermissions.data.ts | 2 +- .../src/abis/PubkeyRouter.data.ts | 2 +- .../src/abis/RateLimitNFT.data.ts | 2 +- .../contracts-sdk/src/abis/Staking.data.ts | 9 +- packages/contracts-sdk/src/abis/Staking.json | 7 - packages/contracts-sdk/src/abis/Staking.ts | 10 - .../src/abis/StakingBalances.data.ts | 2 +- .../contracts-sdk/src/deployed-contracts.json | 46 +-- .../src/lib/providers/BaseProvider.ts | 6 +- .../src/lib/lit-node-client-nodejs.ts | 92 +++-- tsconfig.base.json | 2 +- 23 files changed, 459 insertions(+), 267 deletions(-) diff --git a/README.md b/README.md index a01b3f8fc1..dcd2b144cb 100644 --- a/README.md +++ b/README.md @@ -67,39 +67,37 @@ For usage directly in the browser with a script tag -Package | Category | Version | Download ---- | --- | --- | --- -| [@lit-protocol/lit-node-client-nodejs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client-nodejs) | ![lit-node-client-nodejs](https://img.shields.io/badge/-nodejs-2E8B57 "lit-node-client-nodejs") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/lit-node-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client) | ![lit-node-client](https://img.shields.io/badge/-universal-8A6496 "lit-node-client") | 3.0.0 | npm
Vanilla JS (UMD) - +| Package | Category | Version | Download | +| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [@lit-protocol/lit-node-client-nodejs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client-nodejs) | ![lit-node-client-nodejs](https://img.shields.io/badge/-nodejs-2E8B57 'lit-node-client-nodejs') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/lit-node-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client) | ![lit-node-client](https://img.shields.io/badge/-universal-8A6496 'lit-node-client') | 3.0.0 | npm
Vanilla JS (UMD) | 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 | Version | Download ---- | --- | --- | --- -| [@lit-protocol/access-control-conditions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions) | ![access-control-conditions](https://img.shields.io/badge/-universal-8A6496 "access-control-conditions") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/auth-helpers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-helpers) | ![auth-helpers](https://img.shields.io/badge/-universal-8A6496 "auth-helpers") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/bls-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/bls-sdk) | ![bls-sdk](https://img.shields.io/badge/-universal-8A6496 "bls-sdk") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/constants](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/constants) | ![constants](https://img.shields.io/badge/-universal-8A6496 "constants") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/contracts-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/contracts-sdk) | ![contracts-sdk](https://img.shields.io/badge/-universal-8A6496 "contracts-sdk") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/core](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/core) | ![core](https://img.shields.io/badge/-universal-8A6496 "core") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/crypto](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/crypto) | ![crypto](https://img.shields.io/badge/-universal-8A6496 "crypto") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/ecdsa-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/ecdsa-sdk) | ![ecdsa-sdk](https://img.shields.io/badge/-universal-8A6496 "ecdsa-sdk") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/encryption](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/encryption) | ![encryption](https://img.shields.io/badge/-universal-8A6496 "encryption") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/lit-third-party-libs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-third-party-libs) | ![lit-third-party-libs](https://img.shields.io/badge/-universal-8A6496 "lit-third-party-libs") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/misc](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc) | ![misc](https://img.shields.io/badge/-universal-8A6496 "misc") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/nacl](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/nacl) | ![nacl](https://img.shields.io/badge/-universal-8A6496 "nacl") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/pkp-base](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-base) | ![pkp-base](https://img.shields.io/badge/-universal-8A6496 "pkp-base") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/pkp-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-client) | ![pkp-client](https://img.shields.io/badge/-universal-8A6496 "pkp-client") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/pkp-cosmos](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-cosmos) | ![pkp-cosmos](https://img.shields.io/badge/-universal-8A6496 "pkp-cosmos") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/pkp-ethers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-ethers) | ![pkp-ethers](https://img.shields.io/badge/-universal-8A6496 "pkp-ethers") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/pkp-sui](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-sui) | ![pkp-sui](https://img.shields.io/badge/-universal-8A6496 "pkp-sui") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/pkp-walletconnect](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-walletconnect) | ![pkp-walletconnect](https://img.shields.io/badge/-universal-8A6496 "pkp-walletconnect") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/types](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/types) | ![types](https://img.shields.io/badge/-universal-8A6496 "types") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/uint8arrays](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/uint8arrays) | ![uint8arrays](https://img.shields.io/badge/-universal-8A6496 "uint8arrays") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/auth-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-browser) | ![auth-browser](https://img.shields.io/badge/-browser-E98869 "auth-browser") | 3.0.0 | npm
Vanilla JS (UMD) -| [@lit-protocol/misc-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc-browser) | ![misc-browser](https://img.shields.io/badge/-browser-E98869 "misc-browser") | 3.0.0 | npm
Vanilla JS (UMD) +| Package | Category | Version | Download | +| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [@lit-protocol/access-control-conditions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions) | ![access-control-conditions](https://img.shields.io/badge/-universal-8A6496 'access-control-conditions') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/auth-helpers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-helpers) | ![auth-helpers](https://img.shields.io/badge/-universal-8A6496 'auth-helpers') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/bls-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/bls-sdk) | ![bls-sdk](https://img.shields.io/badge/-universal-8A6496 'bls-sdk') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/constants](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/constants) | ![constants](https://img.shields.io/badge/-universal-8A6496 'constants') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/contracts-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/contracts-sdk) | ![contracts-sdk](https://img.shields.io/badge/-universal-8A6496 'contracts-sdk') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/core](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/core) | ![core](https://img.shields.io/badge/-universal-8A6496 'core') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/crypto](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/crypto) | ![crypto](https://img.shields.io/badge/-universal-8A6496 'crypto') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/ecdsa-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/ecdsa-sdk) | ![ecdsa-sdk](https://img.shields.io/badge/-universal-8A6496 'ecdsa-sdk') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/encryption](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/encryption) | ![encryption](https://img.shields.io/badge/-universal-8A6496 'encryption') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/lit-third-party-libs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-third-party-libs) | ![lit-third-party-libs](https://img.shields.io/badge/-universal-8A6496 'lit-third-party-libs') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/misc](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc) | ![misc](https://img.shields.io/badge/-universal-8A6496 'misc') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/nacl](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/nacl) | ![nacl](https://img.shields.io/badge/-universal-8A6496 'nacl') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/pkp-base](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-base) | ![pkp-base](https://img.shields.io/badge/-universal-8A6496 'pkp-base') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/pkp-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-client) | ![pkp-client](https://img.shields.io/badge/-universal-8A6496 'pkp-client') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/pkp-cosmos](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-cosmos) | ![pkp-cosmos](https://img.shields.io/badge/-universal-8A6496 'pkp-cosmos') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/pkp-ethers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-ethers) | ![pkp-ethers](https://img.shields.io/badge/-universal-8A6496 'pkp-ethers') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/pkp-sui](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-sui) | ![pkp-sui](https://img.shields.io/badge/-universal-8A6496 'pkp-sui') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/pkp-walletconnect](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-walletconnect) | ![pkp-walletconnect](https://img.shields.io/badge/-universal-8A6496 'pkp-walletconnect') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/types](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/types) | ![types](https://img.shields.io/badge/-universal-8A6496 'types') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/uint8arrays](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/uint8arrays) | ![uint8arrays](https://img.shields.io/badge/-universal-8A6496 'uint8arrays') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/auth-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-browser) | ![auth-browser](https://img.shields.io/badge/-browser-E98869 'auth-browser') | 3.0.0 | npm
Vanilla JS (UMD) | +| [@lit-protocol/misc-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc-browser) | ![misc-browser](https://img.shields.io/badge/-browser-E98869 'misc-browser') | 3.0.0 | npm
Vanilla JS (UMD) | @@ -130,7 +128,7 @@ http://docs.lit-js-sdk-v2.litprotocol.com/
- NX Console: https://nx.dev/core-features/integrate-with-editors -# Quick Start +# Quick Start The following commands will help you start developing with this repository. @@ -212,7 +210,6 @@ yarn delete:app yarn delete:package ``` - ## Building ```jsx @@ -247,13 +244,13 @@ Run `yarn bump` to bump the version. You must have at least nodejs v18 to do thi ### to npm -``` +```sh yarn publish:packages ``` ### clone & publish to npm -```jsx +```sh yarn tools --clone <(?) --publish> <(?) --remove-after> // eg @@ -262,7 +259,7 @@ yarn tools --clone lit-node-client @litprotocol/dev --publish --remove-after ## bump, build, test, gen docs, publish, git push -``` +```sh yarn bump yarn build yarn test:unit @@ -280,7 +277,7 @@ git push The following will serve the react testing app and launch the cypress e2e testing after -``` +```sh yarn test:e2e ``` @@ -318,6 +315,37 @@ yarn tools --test --e2e html yarn tools --test --e2e react ``` +## Testing with a Local Lit Node + +First, deploy your Lit Node Contracts, since the correct addresses will be pulled from the `../lit-assets/blockchain/contracts/deployed-lit-node-contracts-temp.json` file. + +Set these two env vars: + +```sh +export LIT_JS_SDK_LOCAL_NODE_DEV="true" +export LIT_JS_SDK_FUNDED_WALLET_PRIVATE_KEY="putAFundedPrivateKeyOnChronicleHere" +``` + +Run: + +```sh +yarn update:contracts-sdk --fetch +yarn update:contracts-sdk --gen +yarn build:packages +``` + +To run manual tests: + +```sh + yarn nx run nodejs:serve +``` + +## ENV Vars + +- LIT_JS_SDK_GITHUB_ACCESS_TOKEN - a github access token to get the contract ABIs from a private repo +- LIT_JS_SDK_LOCAL_NODE_DEV - set to true to use a local node +- LIT_JS_SDK_FUNDED_WALLET_PRIVATE_KEY - set to a funded wallet on Chronicle Testnet + ## Other Commands ### Interactive graph dependencies using NX diff --git a/apps/html/index.html b/apps/html/index.html index b99eea0d55..fd358c8e9d 100644 --- a/apps/html/index.html +++ b/apps/html/index.html @@ -1,4 +1,4 @@ - + @@ -62,7 +62,7 @@ - (HTML) THIS FILE IS AUTOMATICALLY GENERATED FROM tools/scripts/gen-html.mjs Wed, 13 Sep 2023 15:40:07 GMT + (HTML) THIS FILE IS AUTOMATICALLY GENERATED FROM tools/scripts/gen-html.mjs Thu, 14 Sep 2023 05:53:44 GMT diff --git a/apps/nodejs/manual-test.ts b/apps/nodejs/manual-test.ts index a6c1082cc7..6db6365b30 100644 --- a/apps/nodejs/manual-test.ts +++ b/apps/nodejs/manual-test.ts @@ -1,96 +1,98 @@ -import * as litNodeClient from '@lit-protocol/lit-node-client'; +import { LitContracts } from '@lit-protocol/contracts-sdk'; +import * as LitJsSdk from '@lit-protocol/lit-node-client'; // import { LitContracts } from '@lit-protocol/contracts-sdk'; -// import { ethers } from 'ethers'; - -// // *********************************************** -// // Configuration for this test -// // *********************************************** -// const TEST_FUNDED_PRIVATE_KEY = -// '3dfb4f70b15b6fccc786347aaea445f439a7f10fd10c55dd50cafc3d5a0abac1'; -// const PKP_PUBKEY = -// '0x0447972cdf33b1b0329c3ddeea661c023e6b251d8b1aeaa92da881cc6d0d1eff22c2cbd6a5fead8ba860064881cdaabd7176ca2cade0d50829460d729bd13514f3'; -// const CONTROLLER_AUTHSIG = { -// sig: '0x694a3ff6e16ab7d7189b7507df9b73ec118d1966abad7f0e3984df19991ddc2d558abca2fcc5b4acfb710d455c63ca2ad538f4d603d64bd93a1f124b119eac031b', -// derivedVia: 'web3.eth.personal.sign', -// signedMessage: -// 'demo-encrypt-decrypt-react.vercel.app wants you to sign in with your Ethereum account:\n0x1cD4147AF045AdCADe6eAC4883b9310FD286d95a\n\n\nURI: https://demo-encrypt-decrypt-react.vercel.app/\nVersion: 1\nChain ID: 1\nNonce: MrgYgnIW5yHCTKetV\nIssued At: 2022-12-14T02:29:48.420Z\nExpiration Time: 2022-12-21T02:29:48.401Z', -// address: '0x1cd4147af045adcade6eac4883b9310fd286d95a', -// }; - -// console.log( -// '------------------------------ litNodeClientTest ------------------------------' -// ); -// // globalThis.crypto = require('crypto').webcrypto; -// // globalThis.Blob = require('node:buffer').Blob; - -// // ================================== -// // Business Logic -// // ================================== -// const runLogic = async (contract: LitContracts) => { -// let mintCost; -// let tx; - -// await contract.connect(); - -// // ------------------------------------------------------ -// // only run this if it's a pkp wallet -// // ------------------------------------------------------ -// if ('rpcProvider' in contract.signer) { -// console.log("It's a PKP Wallet"); -// const pkpWallet = await setupPKP(); - -// mintCost = await contract.pkpNftContract.read.mintCost(); -// console.log('mintCost:', mintCost.toString()); - -// tx = await contract.pkpNftContract.write.populateTransaction.mintNext(2, { -// value: mintCost, -// }); -// console.log('tx:', tx); - -// const signedTx = await pkpWallet.signTransaction(tx); -// console.log('signedTx:', signedTx); - -// const sentTx = await pkpWallet.sendTransaction(signedTx as any); -// console.log('sentTx:', sentTx); - -// const res = await sentTx.wait(); -// console.log('res:', res); -// return; -// } - -// // ------------------------------------------- -// // regular minting process -// // ------------------------------------------- -// try { -// mintCost = await contract.pkpNftContract.read.mintCost(); -// console.log('mintCost:', mintCost.toString()); -// } catch (e) { -// console.error('Failed to get mint cost'); -// console.log(e); -// } -// try { -// tx = await contract.pkpNftContract.write.mintNext(2, { -// value: mintCost, -// }); -// console.log('tx:', tx); - -// const res = await tx.wait(); -// console.log('res:', res); -// } catch (e: any) { -// console.error('Failed to mintNext:', e.message); -// } -// // wait 1 second -// await new Promise((resolve) => setTimeout(resolve, 1000)); -// }; +import { ethers } from 'ethers'; +import { PKPEthersWallet } from '@lit-protocol/pkp-ethers'; +import { SiweMessage } from 'lit-siwe'; +import { LIT_EVM_CHAINS } from '@lit-protocol/constants'; + + + +// *********************************************** +// Configuration for this test +// *********************************************** +const TEST_FUNDED_PRIVATE_KEY = + process.env.LIT_JS_SDK_FUNDED_WALLET_PRIVATE_KEY; + +console.log( + '------------------------------ litNodeClientTest ------------------------------' +); +// globalThis.crypto = require('crypto').webcrypto; +// globalThis.Blob = require('node:buffer').Blob; + +// ================================== +// Business Logic +// ================================== +const runLogic = async (contract: LitContracts) => { + let mintCost; + let tx; + + await contract.connect(); + + // ------------------------------------------------------ + // only run this if it's a pkp wallet + // ------------------------------------------------------ + // if ('rpcProvider' in contract.signer) { + // console.log("It's a PKP Wallet"); + // const pkpWallet = await setupPKP(); + + // mintCost = await contract.pkpNftContract.read.mintCost(); + // console.log('mintCost:', mintCost.toString()); + + // tx = await contract.pkpNftContract.write.mintNext(2, { + // value: mintCost, + // }); + // console.log('tx:', tx); + + // const signedTx = await pkpWallet.signTransaction(tx); + // console.log('signedTx:', signedTx); + + // const sentTx = await pkpWallet.sendTransaction(signedTx as any); + // console.log('sentTx:', sentTx); + + // const res = await sentTx.wait(); + // console.log('res:', res); + // return; + // } + + // ------------------------------------------- + // regular minting process + // ------------------------------------------- + try { + mintCost = await contract.pkpNftContract.read.mintCost(); + console.log('mintCost:', mintCost.toString()); + } catch (e) { + console.error('Failed to get mint cost'); + console.log(e); + } + + let pkpPubkey; + try { + tx = await contract.pkpNftContract.write.mintNext(2, { + value: mintCost, + }); + console.log('tx:', tx); + + const res = await tx.wait(); + console.log('res:', res); + let pkpMintedEvent = res.events.find(event => event.event === "PKPMinted"); + console.log('pkpMintedEvent:', pkpMintedEvent); + pkpPubkey = pkpMintedEvent.args.pubkey; + } catch (e: any) { + console.error('Failed to mintNext:', e.message); + } + // wait 1 second + await new Promise((resolve) => setTimeout(resolve, 1000)); + return pkpPubkey; +}; -// // ============================= -// // PKP Setup -// // ============================= +// ============================= +// PKP Setup +// ============================= // const setupPKP = async () => { -// const pkpWallet = new PKPWallet({ +// const pkpWallet = new PKPEthersWallet({ // pkpPubKey: PKP_PUBKEY, // controllerAuthSig: CONTROLLER_AUTHSIG, -// provider: 'https://rpc-mumbai.maticvigil.com', // }); // await pkpWallet.init(); @@ -101,9 +103,9 @@ import * as litNodeClient from '@lit-protocol/lit-node-client'; // return pkpSigner; // }; -// // =========================================== -// // random private key test -// // =========================================== +// =========================================== +// random private key test +// =========================================== // const useRandomPrivateKey = async () => { // console.warn('\n\n1. Testing random private key\n\n\n'); // const litContracts = new LitContracts({ randomPrivatekey: true }); @@ -195,7 +197,7 @@ import * as litNodeClient from '@lit-protocol/lit-node-client'; // const privateKey = TEST_FUNDED_PRIVATE_KEY; // const provider = new ethers.providers.JsonRpcProvider( -// 'https://matic-mumbai.chainstacklabs.com' +// LIT_EVM_CHAINS['chronicleTestnet'].rpcUrls[0] // ); // const signer = new ethers.Wallet(privateKey, provider); @@ -203,27 +205,175 @@ import * as litNodeClient from '@lit-protocol/lit-node-client'; // await runLogic(litContracts); // }; -// // ========================================================================= -// // Enable/Disable the function you want to test manually -// // ========================================================================= -export const manualTest = async () => { - console.log('Manual Test Here!'); - const client = new litNodeClient.LitNodeClient({ +const pkpSign = async (client, pkpPubkey, authSig) => { + // try and sign something + let sig = await client.pkpSign({ + toSign: [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], // hello world in Uint8Array + pubKey: pkpPubkey, + authSig, + }); + + // console.log("sig: ", sig); + + const recoveredPk = ethers.utils.recoverPublicKey("0x" + sig.dataSigned, sig.signature); + const addr = ethers.utils.computeAddress('0x' + sig.publicKey); + const recoveredAddr = ethers.utils.computeAddress(recoveredPk); + const claimedAddr = ethers.utils.computeAddress(pkpPubkey); + + const allGood = addr === recoveredAddr && addr === claimedAddr; + + console.log('all addresses match: ', allGood); + return allGood; +} + +const litActionSign = async(client, pkpPubkey, authSig) => { + console.log('testing sig with lit actions...'); + // this code will be run on the node + const litActionCode = ` + const go = async () => { + // this requests a signature share from the Lit Node + // the signature share will be automatically returned in the HTTP response from the node + // all the params (toSign, publicKey, sigName) are passed in from the LitJsSdk.executeJs() function + await Lit.Actions.signEcdsa({ toSign, publicKey , sigName }); + await Lit.Actions.signEcdsa({ toSign, publicKey , sigName: 'sig2' }); + }; + + go(); + `; + + const signatures = await client.executeJs({ + code: litActionCode, + authSig, + // all jsParams can be used anywhere in your litActionCode + jsParams: { + // this is the string "Hello World" for testing + toSign: [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], + publicKey: pkpPubkey, + sigName: "sig1", + }, + }); + // console.log("signatures: ", signatures); + const { sig1, sig2 } = signatures.signatures + const sigKeys = { + sig1: { + recovered: ethers.utils.computeAddress(ethers.utils.recoverPublicKey("0x" + sig1.dataSigned, sig1.signature)), + reported: ethers.utils.computeAddress('0x' + sig1.publicKey) + }, + sig2: { + recovered: ethers.utils.computeAddress(ethers.utils.recoverPublicKey("0x" + sig2.dataSigned, sig2.signature)), + reported: ethers.utils.computeAddress('0x' + sig2.publicKey) + }, + } + + // console.log(`sigKeys: ${JSON.stringify(sigKeys, null, 2)}`) + + const pkpAddr = ethers.utils.computeAddress(pkpPubkey); + // console.log('pkpAddr:', pkpAddr) + + + let allGood = sigKeys.sig1.recovered == sigKeys.sig1.reported && sigKeys.sig2.recovered == sigKeys.sig2.reported && sigKeys.sig1.recovered == sigKeys.sig2.recovered && sigKeys.sig1.recovered == pkpAddr; + console.log('all addresses match: ', allGood); + return allGood; + } + +const mintPkpAndSign = async () => { + let client; + if (process.env.LIT_JS_SDK_LOCAL_NODE_DEV === "true") { + // use local node + client = new LitJsSdk.LitNodeClient({ + litNetwork: 'custom', + "minNodeCount": 2, + "bootstrapUrls": [ + "http://localhost:7470", + "http://localhost:7471", + "http://localhost:7472", + ], + debug: false + }); + } else { + // use cayenne + client = new LitJsSdk.LitNodeClient({ + litNetwork: 'cayenne', + debug: false + }); + } + + await client.connect(); + + const litContracts = new LitContracts({ + privateKey: TEST_FUNDED_PRIVATE_KEY, + }); + const pkpPubkey = await runLogic(litContracts); + console.log('pkpPubkey:', pkpPubkey); + + const privateKey = TEST_FUNDED_PRIVATE_KEY; + const provider = new ethers.providers.JsonRpcProvider( + LIT_EVM_CHAINS['chronicleTestnet'].rpcUrls[0] + ); + const wallet = new ethers.Wallet(privateKey, provider); + const authSig = await getAuthSig(wallet); + + let startTime = Date.now(); + let allGood = true; + const testCount = 100; + for(let i = 0; i < testCount; i++){ + console.log(`testing ${i + 1} of ${testCount}`); + let result = await pkpSign(client, pkpPubkey, authSig); + if (!result) { + allGood = false; + } + } + console.log(`it took ${(Date.now() - startTime) / 1000}s to run ${testCount} tests`) + console.log('all tests were good', allGood); + // await litActionSign(client, pkpPubkey, authSig); +} + +const getAuthSig = async (wallet) => { + const address = wallet.address; + + // Craft the SIWE message + const domain = 'localhost'; + const origin = 'https://localhost/login'; + const statement = + 'This is a test statement. You can put anything you want here.'; + const siweMessage = new SiweMessage({ + domain, + address, + statement, + uri: origin, + version: '1', + chainId: 1, + }); + const messageToSign = siweMessage.prepareMessage(); + + // Sign the message and format the authSig + const signature = await wallet.signMessage(messageToSign); + + const authSig = { + sig: signature, + derivedVia: 'web3.eth.personal.sign', + signedMessage: messageToSign, + address: address, + }; + return authSig +} + +const testLitActionJsExecution = async () => { + const client = new LitJsSdk.LitNodeClient({ litNetwork: 'cayenne', }); await client.connect(); + // generate a random wallet using ethers + let wallet = ethers.Wallet.createRandom(); + console.log('Wallet Address:', wallet.address); + const address = wallet.address; + const authSig = await getAuthSig(wallet); + const res = await client.executeJs({ targetNodeRange: 1, - authSig: { - sig: '0x721a354498677a1024fb48a78e56c68fd11ad705565933dd9ac770501cecad8811e8591453e21ab50d2579c3d2fe7b0dcbcb1b6436c67e9c6263169c182f50bd1b', - derivedVia: 'web3.eth.personal.sign', - signedMessage: - 'demo-encrypt-decrypt-react.vercel.app wants you to sign in with your Ethereum account:\n0xEDA4f4A8AbCecB28bf1663df9257Ec6F188B8107\n\n\nURI: https://demo-encrypt-decrypt-react.vercel.app/\nVersion: 1\nChain ID: 1\nNonce: hwrDnUCFsiR10S2lX\nIssued At: 2023-01-25T14:26:44.497Z\nExpiration Time: 2023-02-01T14:26:44.480Z', - address: '0xeda4f4a8abcecb28bf1663df9257ec6f188b8107', - }, - + authSig, jsParams: {}, code: `(async() => { console.log("RUN TEST BABY!"); @@ -232,4 +382,12 @@ export const manualTest = async () => { }); console.log('res:', res); +} + +// // ========================================================================= +// // Enable/Disable the function you want to test manually +// // ========================================================================= +export const manualTest = async () => { + console.log('Manual Test Here!'); + await mintPkpAndSign(); }; diff --git a/apps/react/src/app/app.tsx b/apps/react/src/app/app.tsx index 031fb3118e..3d93b90320 100644 --- a/apps/react/src/app/app.tsx +++ b/apps/react/src/app/app.tsx @@ -1802,7 +1802,7 @@ pre { `, }} /> - (REACT) THIS FILE IS AUTOMATICALLY GENERATED FROM tools/scripts/gen-react.mjs Wed, 13 Sep 2023 15:40:07 GMT + (REACT) THIS FILE IS AUTOMATICALLY GENERATED FROM tools/scripts/gen-react.mjs Thu, 14 Sep 2023 05:53:45 GMT
diff --git a/packages/contracts-sdk/fetch-contracts.mjs b/packages/contracts-sdk/fetch-contracts.mjs index f0ff452390..63ecf5463e 100644 --- a/packages/contracts-sdk/fetch-contracts.mjs +++ b/packages/contracts-sdk/fetch-contracts.mjs @@ -103,15 +103,16 @@ export const asyncForEach = async (array, callback) => { */ export const getContractAddresses = async (LitConfig) => { // get deployed contract addresses - const contractAddresses = JSON.parse( - await fetch(LitConfig.contracts, { - headers: LitConfig.abis.isPrivate - ? { - Authorization: `token ${LitConfig.abis.token}`, - } - : {}, - }).then((res) => res.text()) - ); + let contractAddresses; + if (process.env.LIT_JS_SDK_LOCAL_NODE_DEV === 'true') { + // get contracts from local filesystem + contractAddresses = await readJsonFile(LitConfig.contractsLocal); + } else { + // get contracts from remote + contractAddresses = JSON.parse( + await fetch(LitConfig.contracts).then((res) => res.text()) + ); + } Object.entries(contractAddresses).forEach(([key, value]) => { if (key.includes('ContractAddress')) return; @@ -133,7 +134,8 @@ export const getContractAddresses = async (LitConfig) => { correctedName = correctedName.replace('Nft', 'NFT'); correctedName = correctedName.replace('Lit', 'LIT'); correctedName = correctedName.replace('Resolver', 'ContractResolver'); - if (correctedName == "HdKeyDeriver"){ // dont process the contract with name as it is internally used wihtin `PubkeyRouter` + if (correctedName == 'HdKeyDeriver') { + // dont process the contract with name as it is internally used wihtin `PubkeyRouter` return; } if (correctedName === 'ContractResolver') { @@ -142,7 +144,12 @@ export const getContractAddresses = async (LitConfig) => { // append .json // correctedName = correctedName - let abiPath = LitConfig.root + LitConfig.abis.dir + correctedName + '.json'; + let abiPath; + if (process.env.LIT_JS_SDK_LOCAL_NODE_DEV === 'true') { + abiPath = LitConfig.abis.dirLocal + correctedName + '.json'; + } else { + abiPath = LitConfig.root + LitConfig.abis.dir + correctedName + '.json'; + } contracts.push({ name: item[0], @@ -169,14 +176,20 @@ await asyncForEach(deployedContracts, async (contract) => { let json; try { - json = await fetch(contract.abiPath, { - headers: LitConfig.abis.isPrivate - ? { - Authorization: `token ${LitConfig.abis.token}`, - } - : {}, - }).then((res) => res.text()); - json = JSON.parse(json); + if (process.env.LIT_JS_SDK_LOCAL_NODE_DEV === 'true') { + // get from local filesystem + json = await readJsonFile(contract.abiPath); + } else { + // get from remote + json = await fetch(contract.abiPath, { + headers: LitConfig.abis.isPrivate + ? { + Authorization: `token ${process.env.LIT_JS_SDK_GITHUB_ACCESS_TOKEN}`, + } + : {}, + }).then((res) => res.text()); + json = JSON.parse(json); + } } catch (e) { redLog(`Failed to fetch ${contract.abiPath}`); } diff --git a/packages/contracts-sdk/lit-contracts.config.json b/packages/contracts-sdk/lit-contracts.config.json index fc3b7f86bb..d402e1b8bb 100644 --- a/packages/contracts-sdk/lit-contracts.config.json +++ b/packages/contracts-sdk/lit-contracts.config.json @@ -4,7 +4,8 @@ "abis": { "dir": "abis/", "ignoreProperties": ["metadata", "bytecode", "deployedBytecode"], - "token": "", - "isPrivate": true - } + "isPrivate": true, + "dirLocal": "../lit-assets/rust/lit-core/lit-blockchain/abis/" + }, + "contractsLocal": "../lit-assets/blockchain/contracts/deployed-lit-node-contracts-temp.json" } diff --git a/packages/contracts-sdk/src/abis/Allowlist.data.ts b/packages/contracts-sdk/src/abis/Allowlist.data.ts index ca6c61ca4f..1bfa7bf746 100644 --- a/packages/contracts-sdk/src/abis/Allowlist.data.ts +++ b/packages/contracts-sdk/src/abis/Allowlist.data.ts @@ -1,5 +1,5 @@ export const allowlist = { - "address": "0x01385531dF2397425acb2Dffd3fA5Fd76729504a", + "address": "0x9fb501502402Fe4A8CE44c8C39a5d63787ED653c", "abi": [ { "inputs": [], diff --git a/packages/contracts-sdk/src/abis/ContractResolver.data.ts b/packages/contracts-sdk/src/abis/ContractResolver.data.ts index bb34896e4a..4a4b1e3755 100644 --- a/packages/contracts-sdk/src/abis/ContractResolver.data.ts +++ b/packages/contracts-sdk/src/abis/ContractResolver.data.ts @@ -1,5 +1,5 @@ export const contractResolver = { - "address": "0x0bca885Cf322D0E478DC48Fb84b4f522144db9D7", + "address": "0x53Df74f2Ca020ab439002158e6De0A32b1AA66D1", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/abis/Multisender.data.ts b/packages/contracts-sdk/src/abis/Multisender.data.ts index b1fc7b216a..fb4f0d4602 100644 --- a/packages/contracts-sdk/src/abis/Multisender.data.ts +++ b/packages/contracts-sdk/src/abis/Multisender.data.ts @@ -1,5 +1,5 @@ export const multisender = { - "address": "0x373195723448308d43a43989790C0b768Ef14853", + "address": "0xacAe3822240234d8Ebbb591787a2E2b6247Ce63e", "abi": [ { "anonymous": false, diff --git a/packages/contracts-sdk/src/abis/PKPHelper.data.ts b/packages/contracts-sdk/src/abis/PKPHelper.data.ts index 840a094d6a..38a296906c 100644 --- a/packages/contracts-sdk/src/abis/PKPHelper.data.ts +++ b/packages/contracts-sdk/src/abis/PKPHelper.data.ts @@ -1,5 +1,5 @@ export const pkpHelper = { - "address": "0xA8C519a051b85A2010C498145C698074782AB6DF", + "address": "0x0600cBB5dc983A970b165390Da00e699E5baeDD1", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/abis/PKPNFT.data.ts b/packages/contracts-sdk/src/abis/PKPNFT.data.ts index 6cda8932e1..484a2c089e 100644 --- a/packages/contracts-sdk/src/abis/PKPNFT.data.ts +++ b/packages/contracts-sdk/src/abis/PKPNFT.data.ts @@ -1,5 +1,5 @@ export const pkpNft = { - "address": "0xBBaa35e9b4a38c8f639d25f49c529967Ffeb0C06", + "address": "0x0122829576DDd317c44364238f5DDe205d6da25F", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/abis/PKPNFTMetadata.data.ts b/packages/contracts-sdk/src/abis/PKPNFTMetadata.data.ts index 834096c8cb..9479797b8b 100644 --- a/packages/contracts-sdk/src/abis/PKPNFTMetadata.data.ts +++ b/packages/contracts-sdk/src/abis/PKPNFTMetadata.data.ts @@ -1,5 +1,5 @@ export const pkpNftMetadata = { - "address": "0xa7F9bDf4fF1aEb9C1AB41E965610Df5699b09D68", + "address": "0xFB7eeE9859eA34D06962f4362FA7B4E294039B05", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/abis/PKPPermissions.data.ts b/packages/contracts-sdk/src/abis/PKPPermissions.data.ts index 8344792ad5..cb8614285d 100644 --- a/packages/contracts-sdk/src/abis/PKPPermissions.data.ts +++ b/packages/contracts-sdk/src/abis/PKPPermissions.data.ts @@ -1,5 +1,5 @@ export const pkpPermissions = { - "address": "0x61Dc305F03cFF5Ba8f39D5F8F9BE2D3298e8aE38", + "address": "0x05A6d463c73adA7A0D3Af317Cd68271e5E34bCd4", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/abis/PubkeyRouter.data.ts b/packages/contracts-sdk/src/abis/PubkeyRouter.data.ts index 83821d12ec..2a1972cf76 100644 --- a/packages/contracts-sdk/src/abis/PubkeyRouter.data.ts +++ b/packages/contracts-sdk/src/abis/PubkeyRouter.data.ts @@ -1,5 +1,5 @@ export const pubkeyRouter = { - "address": "0xb26b4DC365843cDaE996F526913D3D4F45343aE8", + "address": "0x9da98532bd3b7cDDA18ae34DFeCdeBBb75AC3F7D", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/abis/RateLimitNFT.data.ts b/packages/contracts-sdk/src/abis/RateLimitNFT.data.ts index b4698b29a0..77e7d91070 100644 --- a/packages/contracts-sdk/src/abis/RateLimitNFT.data.ts +++ b/packages/contracts-sdk/src/abis/RateLimitNFT.data.ts @@ -1,5 +1,5 @@ export const rateLimitNft = { - "address": "0x8624EE1100B45DD3e55B7399446CbF01ab5Db333", + "address": "0x4B15DAC8f60fC2B5A691A13bD5eC26aaa0f50a0b", "abi": [ { "inputs": [], diff --git a/packages/contracts-sdk/src/abis/Staking.data.ts b/packages/contracts-sdk/src/abis/Staking.data.ts index 558f72ce28..084b7b1dd5 100644 --- a/packages/contracts-sdk/src/abis/Staking.data.ts +++ b/packages/contracts-sdk/src/abis/Staking.data.ts @@ -1,5 +1,5 @@ export const staking = { - "address": "0x07A5bE9e0Aa724563e904B5e7AF37921e193f801", + "address": "0x187e8770A9ad58a83b3A619ba9bb3629dA6E25B1", "abi": [ { "inputs": [ @@ -1195,13 +1195,6 @@ export const staking = { "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "pauseEpoch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/packages/contracts-sdk/src/abis/Staking.json b/packages/contracts-sdk/src/abis/Staking.json index b9e185facf..eeb99b6152 100644 --- a/packages/contracts-sdk/src/abis/Staking.json +++ b/packages/contracts-sdk/src/abis/Staking.json @@ -1193,13 +1193,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "pauseEpoch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/packages/contracts-sdk/src/abis/Staking.ts b/packages/contracts-sdk/src/abis/Staking.ts index 5443260f8e..2406bf4677 100755 --- a/packages/contracts-sdk/src/abis/Staking.ts +++ b/packages/contracts-sdk/src/abis/Staking.ts @@ -135,7 +135,6 @@ export type StakingMethodNames = | 'nextValidatorCountForConsensus' | 'nodeAddressToStakerAddress' | 'owner' - | 'pauseEpoch' | 'readyForNextEpoch' | 'renounceOwnership' | 'requestToJoin' @@ -608,15 +607,6 @@ export interface Staking { * Type: function */ owner(overrides?: ContractCallOverrides): Promise; - /** - * Payable: false - * Constant: false - * StateMutability: nonpayable - * Type: function - */ - pauseEpoch( - overrides?: ContractTransactionOverrides - ): Promise; /** * Payable: false * Constant: true diff --git a/packages/contracts-sdk/src/abis/StakingBalances.data.ts b/packages/contracts-sdk/src/abis/StakingBalances.data.ts index 5c93b5d5e3..6f6355dc70 100644 --- a/packages/contracts-sdk/src/abis/StakingBalances.data.ts +++ b/packages/contracts-sdk/src/abis/StakingBalances.data.ts @@ -1,5 +1,5 @@ export const stakingBalances = { - "address": "0xAB783F4B8ceD3f98Adc169d50F1063dD0517EEA8", + "address": "0x23Ab8F5cD37be7B6036a17fD75A842533d2D39d0", "abi": [ { "inputs": [ diff --git a/packages/contracts-sdk/src/deployed-contracts.json b/packages/contracts-sdk/src/deployed-contracts.json index 9ac2458a7b..bba63de850 100644 --- a/packages/contracts-sdk/src/deployed-contracts.json +++ b/packages/contracts-sdk/src/deployed-contracts.json @@ -3,84 +3,84 @@ "name": "stakingBalancesContractAddress", "correctedName": "StakingBalances", "exportName": "stakingBalances", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/StakingBalances.json", - "address": "0xAB783F4B8ceD3f98Adc169d50F1063dD0517EEA8" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/StakingBalances.json", + "address": "0x23Ab8F5cD37be7B6036a17fD75A842533d2D39d0" }, { "name": "stakingContractAddress", "correctedName": "Staking", "exportName": "staking", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/Staking.json", - "address": "0x07A5bE9e0Aa724563e904B5e7AF37921e193f801" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/Staking.json", + "address": "0x187e8770A9ad58a83b3A619ba9bb3629dA6E25B1" }, { "name": "multisenderContractAddress", "correctedName": "Multisender", "exportName": "multisender", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/Multisender.json", - "address": "0x373195723448308d43a43989790C0b768Ef14853" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/Multisender.json", + "address": "0xacAe3822240234d8Ebbb591787a2E2b6247Ce63e" }, { "name": "litTokenContractAddress", "correctedName": "LITToken", "exportName": "litToken", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/LITToken.json", + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/LITToken.json", "address": "0x53695556f8a1a064EdFf91767f15652BbfaFaD04" }, { "name": "pubkeyRouterContractAddress", "correctedName": "PubkeyRouter", "exportName": "pubkeyRouter", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/PubkeyRouter.json", - "address": "0xb26b4DC365843cDaE996F526913D3D4F45343aE8" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/PubkeyRouter.json", + "address": "0x9da98532bd3b7cDDA18ae34DFeCdeBBb75AC3F7D" }, { "name": "pkpNftContractAddress", "correctedName": "PKPNFT", "exportName": "pkpNft", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/PKPNFT.json", - "address": "0xBBaa35e9b4a38c8f639d25f49c529967Ffeb0C06" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/PKPNFT.json", + "address": "0x0122829576DDd317c44364238f5DDe205d6da25F" }, { "name": "rateLimitNftContractAddress", "correctedName": "RateLimitNFT", "exportName": "rateLimitNft", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/RateLimitNFT.json", - "address": "0x8624EE1100B45DD3e55B7399446CbF01ab5Db333" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/RateLimitNFT.json", + "address": "0x4B15DAC8f60fC2B5A691A13bD5eC26aaa0f50a0b" }, { "name": "pkpHelperContractAddress", "correctedName": "PKPHelper", "exportName": "pkpHelper", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/PKPHelper.json", - "address": "0xA8C519a051b85A2010C498145C698074782AB6DF" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/PKPHelper.json", + "address": "0x0600cBB5dc983A970b165390Da00e699E5baeDD1" }, { "name": "pkpPermissionsContractAddress", "correctedName": "PKPPermissions", "exportName": "pkpPermissions", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/PKPPermissions.json", - "address": "0x61Dc305F03cFF5Ba8f39D5F8F9BE2D3298e8aE38" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/PKPPermissions.json", + "address": "0x05A6d463c73adA7A0D3Af317Cd68271e5E34bCd4" }, { "name": "pkpNftMetadataContractAddress", "correctedName": "PKPNFTMetadata", "exportName": "pkpNftMetadata", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/PKPNFTMetadata.json", - "address": "0xa7F9bDf4fF1aEb9C1AB41E965610Df5699b09D68" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/PKPNFTMetadata.json", + "address": "0xFB7eeE9859eA34D06962f4362FA7B4E294039B05" }, { "name": "allowlistContractAddress", "correctedName": "Allowlist", "exportName": "allowlist", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/Allowlist.json", - "address": "0x01385531dF2397425acb2Dffd3fA5Fd76729504a" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/Allowlist.json", + "address": "0x9fb501502402Fe4A8CE44c8C39a5d63787ED653c" }, { "name": "resolverContractAddress", "correctedName": "ContractResolver", "exportName": "contractResolver", - "abiPath": "https://raw.githubusercontent.com/LIT-Protocol/lit-assets/develop/rust/lit-core/lit-blockchain/abis/ContractResolver.json", - "address": "0x0bca885Cf322D0E478DC48Fb84b4f522144db9D7" + "abiPath": "../lit-assets/rust/lit-core/lit-blockchain/abis/ContractResolver.json", + "address": "0x53Df74f2Ca020ab439002158e6De0A32b1AA66D1" } ] \ No newline at end of file diff --git a/packages/lit-auth-client/src/lib/providers/BaseProvider.ts b/packages/lit-auth-client/src/lib/providers/BaseProvider.ts index 113a62c439..6cf450875e 100644 --- a/packages/lit-auth-client/src/lib/providers/BaseProvider.ts +++ b/packages/lit-auth-client/src/lib/providers/BaseProvider.ts @@ -188,8 +188,8 @@ export abstract class BaseProvider { * @param claimRequest * @returns {Promise} - Response from the network for the claim */ - public async claimKeyId( - claimRequest: ClaimRequest + public async claimKeyId( + claimRequest: ClaimRequest ): Promise { if (!this.litNodeClient.ready) { await this.litNodeClient.connect().catch((err) => { @@ -197,7 +197,7 @@ export abstract class BaseProvider { }); } - const res = await this.litNodeClient.claimKeyId(claimRequest); + const res = await this.litNodeClient.claimKeyId(claimRequest); return res; } 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 index 5154161d4e..d0161f73e8 100644 --- 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 @@ -798,7 +798,7 @@ export class LitNodeClientNodeJs extends LitCore { this.getLitActionRequestBody(params); // -- choose the right signature - let sigToPassToNode = this.getAuthSigOrSessionAuthSig({ + const sigToPassToNode = this.getAuthSigOrSessionAuthSig({ authSig, sessionSigs, url, @@ -807,7 +807,7 @@ export class LitNodeClientNodeJs extends LitCore { reqBody.authSig = sigToPassToNode; // this return { url: string, data: JsonRequest } - let singleNodePromise = this.getJsExecutionShares( + const singleNodePromise = this.getJsExecutionShares( url, reqBody, requestId @@ -816,10 +816,10 @@ export class LitNodeClientNodeJs extends LitCore { nodePromises.push(singleNodePromise); } - const handledPromise = await this.handleNodePromises( + const handledPromise = (await this.handleNodePromises( nodePromises, targetNodeRange - ); + )) as SuccessNodePromises | RejectedNodePromises; // -- handle response return handledPromise; @@ -827,28 +827,45 @@ export class LitNodeClientNodeJs extends LitCore { // ========== Shares Resolvers ========== _getFlattenShare = (share: any): SigShare => { - // flatten the signature object so that the properties of the signature are top level const flattenObj = Object.entries(share).map(([key, item]) => { - if (item === null || item === undefined) { return null; } const typedItem = item as SigShare; - const requiredShareProps = ['sigType', 'dataSigned', 'signatureShare', 'shareIndex', 'bigR', 'publicKey'] - - const requiredSessionSigsShareProps = [...requiredShareProps, 'siweMessage'] as const; - - const requiredSignatureShareProps = [...requiredShareProps, 'sigName'] as const; + const requiredShareProps = [ + 'sigType', + 'dataSigned', + 'signatureShare', + 'shareIndex', + 'bigR', + 'publicKey', + ]; + + const requiredSessionSigsShareProps = [ + ...requiredShareProps, + 'siweMessage', + ] as const; + + const requiredSignatureShareProps = [ + ...requiredShareProps, + 'sigName', + ] as const; const hasProps = (props: any) => { - return [...props].every(prop => typedItem[prop as keyof SigShare] !== undefined && typedItem[prop as keyof SigShare] !== null) - } - - if (hasProps(requiredSessionSigsShareProps) || hasProps(requiredSignatureShareProps)) { + return [...props].every( + (prop) => + typedItem[prop as keyof SigShare] !== undefined && + typedItem[prop as keyof SigShare] !== null + ); + }; + if ( + hasProps(requiredSessionSigsShareProps) || + hasProps(requiredSignatureShareProps) + ) { typedItem.signatureShare = typedItem.signatureShare.replaceAll('"', ''); typedItem.bigR = typedItem.bigR.replaceAll('"', ''); typedItem.publicKey = typedItem.publicKey.replaceAll('"', ''); @@ -861,14 +878,15 @@ export class LitNodeClientNodeJs extends LitCore { }); // removed all null values and should only have one item - const flattenShare = (flattenObj.filter(item => item !== null))[0] as SigShare; - + const flattenShare = flattenObj.filter( + (item) => item !== null + )[0] as SigShare; if (flattenShare === null || flattenShare === undefined) { - return share + return share; } return flattenShare; - } + }; /** * @@ -893,9 +911,8 @@ export class LitNodeClientNodeJs extends LitCore { shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex); const sigShares: Array = shares.map((s: any) => { - const share = this._getFlattenShare(s); - console.log("XX share", share) + console.log('XX share', share); return { sigType: share.sigType, @@ -905,7 +922,7 @@ export class LitNodeClientNodeJs extends LitCore { publicKey: share.publicKey, dataSigned: share.dataSigned, siweMessage: share.siweMessage, - } + }; }); log('getSessionSignatures - sigShares', sigShares); @@ -940,10 +957,10 @@ export class LitNodeClientNodeJs extends LitCore { throwError({ message: 'siganture could not be combined', errorKind: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.kind, - errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name + errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name, }); } - + const encodedSig = joinSignature({ r: '0x' + signature.r, s: '0x' + signature.s, @@ -986,11 +1003,9 @@ export class LitNodeClientNodeJs extends LitCore { shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex); const sigShares: Array = shares.map((s: any) => { - const share = this._getFlattenShare(s); - console.log("YY share", share) - return ({ + return { sigType: share.sigType, signatureShare: share.signatureShare, shareIndex: share.shareIndex, @@ -998,7 +1013,7 @@ export class LitNodeClientNodeJs extends LitCore { publicKey: share.publicKey, dataSigned: share.dataSigned, sigName: share.sigName ? share.sigName : 'sig', - }) + }; }); log('getSignatures - sigShares', sigShares); @@ -1033,7 +1048,7 @@ export class LitNodeClientNodeJs extends LitCore { throwError({ message: 'siganture could not be combined', errorKind: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.kind, - errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name + errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name, }); } @@ -1965,8 +1980,8 @@ export class LitNodeClientNodeJs extends LitCore { const sessionCapabilityObject = params.sessionCapabilityObject ? params.sessionCapabilityObject : this.generateSessionCapabilityObjectWithWildcards( - params.resourceAbilityRequests.map((r) => r.resource) - ); + params.resourceAbilityRequests.map((r) => r.resource) + ); let expiration = params.expiration || this.getExpiration(); // -- (TRY) to get the wallet signature @@ -2080,8 +2095,8 @@ export class LitNodeClientNodeJs extends LitCore { * @param {ClaimKeyRequest} params an Auth Method and {@link MintCallback} * @returns {Promise} */ - async claimKeyId( - params: ClaimRequest + async claimKeyId( + params: ClaimRequest ): Promise { if (!this.ready) { const message = @@ -2134,16 +2149,18 @@ export class LitNodeClientNodeJs extends LitCore { const pubkey: string = this.computeHDPubKey(derivedKeyId); log(`pubkey ${pubkey} derived from key id ${derivedKeyId}`); + const relayParams: ClaimRequest<'relay'> = + params as ClaimRequest<'relay'>; + let mintTx = ''; - if (params.mintCallback) { + if (params.mintCallback && 'signer' in params) { mintTx = await params.mintCallback({ derivedKeyId, authMethodType: params.authMethod.authMethodType, signatures: nodeSignatures, pubkey, signer: (params as ClaimRequest<'client'>).signer, - relayUrl: (params as ClaimRequest<'relay'>).relayUrl, - relayApiKey: (params as ClaimRequest<'relay'>).relayApiKey, + ...relayParams, }); } else { mintTx = await defaultMintClaimCallback({ @@ -2151,8 +2168,7 @@ export class LitNodeClientNodeJs extends LitCore { authMethodType: params.authMethod.authMethodType, signatures: nodeSignatures, pubkey, - relayUrl: (params as ClaimRequest<'relay'>).relayUrl, - relayApiKey: (params as ClaimRequest<'relay'>).relayApiKey, + ...relayParams, }); } diff --git a/tsconfig.base.json b/tsconfig.base.json index e9cc3cb256..d79d1c4238 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -10,7 +10,7 @@ "importHelpers": true, "target": "ES2020", "module": "ES2020", - "lib": ["ES2020", "dom"], + "lib": ["ES2020", "dom", "ES2021.String"], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", From c898b8d8dedd69fbfa882aeccfb861a19453efa8 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 14 Sep 2023 09:18:06 +0100 Subject: [PATCH 03/10] feat: script to enable/disable nx build cache --- package.json | 6 ++++-- tools/scripts/endisable-cache.mjs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tools/scripts/endisable-cache.mjs diff --git a/package.json b/package.json index 7e40f6dd61..e98bb68fd6 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,9 @@ "txServer": "node tx-handler-server.mjs", "prettier": "nx format:write --all", "delete:merged-branches": "git branch --merged | egrep -v '(^\\*|master|main|develop)' | xargs git branch -d", - "delete:no-merged-branches": "git branch --no-merged | egrep -v '(^\\*|master|main|develop)' | xargs git branch -d" + "delete:no-merged-branches": "git branch --no-merged | egrep -v '(^\\*|master|main|develop)' | xargs git branch -d", + "cache:enable": "node ./tools/scripts/endisable-cache.mjs --enable=true", + "cache:disable": "node ./tools/scripts/endisable-cache.mjs --enable=false" }, "private": true, "dependencies": { @@ -190,4 +192,4 @@ "workspaces": [ "packages/*" ] -} +} \ No newline at end of file diff --git a/tools/scripts/endisable-cache.mjs b/tools/scripts/endisable-cache.mjs new file mode 100644 index 0000000000..460c772e03 --- /dev/null +++ b/tools/scripts/endisable-cache.mjs @@ -0,0 +1,31 @@ +import fs from 'fs'; +import path from 'path'; + +/** + * This script enables or disables the cache in the nx.json file. + * Usage: node endisable-cache.mjs --enable=true + * --enable: Set to true to enable the cache, false to disable it. + */ + +const args = process.argv.slice(2); +const enableCache = + args.find((arg) => arg.startsWith('--enable'))?.split('=')[1] === 'true'; + +const nxConfigPath = path.join(process.cwd(), 'nx.json'); +const nxConfig = JSON.parse(fs.readFileSync(nxConfigPath, 'utf-8')); + +if (enableCache) { + nxConfig.tasksRunnerOptions.default.options = { + cacheableOperations: ['build'], + cacheableDirectories: ['node_modules'], + }; +} else { + delete nxConfig.tasksRunnerOptions.default.options; +} + +fs.writeFileSync(nxConfigPath, JSON.stringify(nxConfig, null, 2)); + +console.log('\nšŸ“ Available commands:'); +console.log('--enable=true: Enable the cache'); +console.log('--enable=false: Disable the cache'); +console.log('\n'); From e2f2649e43666a2b7f92ef8fb9912ab389c6d078 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 14 Sep 2023 09:21:58 +0100 Subject: [PATCH 04/10] chore: update text --- tools/scripts/endisable-cache.mjs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/scripts/endisable-cache.mjs b/tools/scripts/endisable-cache.mjs index 460c772e03..a826f46619 100644 --- a/tools/scripts/endisable-cache.mjs +++ b/tools/scripts/endisable-cache.mjs @@ -1,5 +1,6 @@ import fs from 'fs'; import path from 'path'; +import { greenLog } from './utils.mjs'; /** * This script enables or disables the cache in the nx.json file. @@ -17,7 +18,7 @@ const nxConfig = JSON.parse(fs.readFileSync(nxConfigPath, 'utf-8')); if (enableCache) { nxConfig.tasksRunnerOptions.default.options = { cacheableOperations: ['build'], - cacheableDirectories: ['node_modules'], + // cacheableDirectories: ['node_modules'], }; } else { delete nxConfig.tasksRunnerOptions.default.options; @@ -25,7 +26,7 @@ if (enableCache) { fs.writeFileSync(nxConfigPath, JSON.stringify(nxConfig, null, 2)); -console.log('\nšŸ“ Available commands:'); -console.log('--enable=true: Enable the cache'); -console.log('--enable=false: Disable the cache'); -console.log('\n'); +greenLog('\nšŸ“ This script enables or disables the cache in the nx.json file.\n', true); +greenLog('--enable=true: Enable the cache', true); +greenLog('--enable=false: Disable the cache', true); + From fc18bacafc9a4587c37ad7ab6d34d14e09487549 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 14 Sep 2023 10:44:08 +0100 Subject: [PATCH 05/10] feat: add bun test script --- package.json | 1 + tools/scripts/test-script.mjs | 82 +++++++++++++++++++++++++++++++++++ tools/scripts/utils.mjs | 11 +++++ 3 files changed, 94 insertions(+) create mode 100644 tools/scripts/test-script.mjs diff --git a/package.json b/package.json index e98bb68fd6..9a1872ec32 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "test:e2e": "yarn tools --test --e2e run-react-and-test", "test:unit": "yarn test:packages", "test:custom": "yarn tools --test --custom", + "test:file": "bun ./tools/scripts/test-script.mjs", "publish:packages": "yarn node ./tools/scripts/pub.mjs --prod", "publish:dev": "yarn node ./tools/scripts/pub.mjs --tag dev", "publish:test": "yarn node ./tools/scripts/pub.mjs --tag test", diff --git a/tools/scripts/test-script.mjs b/tools/scripts/test-script.mjs new file mode 100644 index 0000000000..d0b8f53c70 --- /dev/null +++ b/tools/scripts/test-script.mjs @@ -0,0 +1,82 @@ +import fs from 'fs'; +import path from 'path'; + +import { bunSpawn, greenLog, redLog } from './utils.mjs'; + +/** + * This script recursively looks for files in the directory ./packages that ends with .spec.ts or .test.ts. + * When run with node ./tools/scripts/test-scripts.mjs , it runs the script with command 'bun test ' + * + * Arguments can be provided in the format "--=" + * + * Example: node ./tools/scripts/test-scripts.mjs --dir=./packages --ext=.spec.ts,.test.ts + */ + +const args = process.argv.slice(2); +const TEST_DIR = + args.find((arg) => arg.startsWith('--dir'))?.split('=')[1] || './packages'; +const TEST_FILE_EXTENSIONS = args + .find((arg) => arg.startsWith('--ext')) + ?.split('=')[1] + ?.split(',') || ['.spec.ts', '.test.ts']; + +/** + * Recursively find test files in the given directory + * @param {string} dir - The directory to search in + * @param {string[]} exts - The file extensions to look for + * @returns {string[]} - The paths of the found test files + */ +function findTestFiles(dir, exts) { + let testFiles = []; + const files = fs.readdirSync(dir); + + for (const file of files) { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + // Extract the extension from the file name considering the possibility of multiple dots in the file name + const fileExtension = '.' + file.split('.').slice(1).join('.'); + + if (stat.isDirectory()) { + testFiles = testFiles.concat(findTestFiles(filePath, exts)); + } else if (exts.includes(fileExtension)) { + testFiles.push(filePath); + } + } + + return testFiles; +} + +/** + * Run the test command for the given test file + * @param {string} testFile - The path of the test file + */ +function runTest(testFile) { + const command = `bun test ${testFile}`; + console.log('Running command: ', command); + bunSpawn(command, { stdout: 'inherit' }); +} + +const testFiles = findTestFiles(TEST_DIR, TEST_FILE_EXTENSIONS); + +greenLog(`${testFiles.length} test files found!`, true); + +const testName = process.argv[2]; + +if (testName) { + const matchingTestFiles = testFiles.filter((file) => { + return file.includes(testName); + }); + + if (!matchingTestFiles.length) { + console.error(`No test files matching "${testName}" found.`); + process.exit(1); + } + + for (const filePath of matchingTestFiles) { + runTest(filePath); + } +} else { + redLog('Please provide a test name. eg. bun test:file lit-node-client'); + process.exit(1); +} diff --git a/tools/scripts/utils.mjs b/tools/scripts/utils.mjs index 2263a90e49..72052a716a 100644 --- a/tools/scripts/utils.mjs +++ b/tools/scripts/utils.mjs @@ -162,6 +162,17 @@ export const spawnCommand = ( }); }; +export const bunSpawn = (commands, options = {}) => { + const defaultOptions = { stdout: 'inherit' }; + + let _commands = commands.split(' '); + + Bun.spawn(_commands, { + ...defaultOptions, + ...options, + }); +}; + export const spawnListener = (commands, callback, prefix = '', color = 31) => { let _commands = commands.split(' '); // let eventName = _commands.join('-'); From 1369be5cc37a9c5278c1ba1ac125cf3192c46b2e Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 14 Sep 2023 10:47:58 +0100 Subject: [PATCH 06/10] chore: make test exit --- tools/scripts/endisable-cache.mjs | 2 +- tools/scripts/test-script.mjs | 8 +++++--- tools/scripts/utils.mjs | 6 ++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/scripts/endisable-cache.mjs b/tools/scripts/endisable-cache.mjs index a826f46619..d0d304f6f4 100644 --- a/tools/scripts/endisable-cache.mjs +++ b/tools/scripts/endisable-cache.mjs @@ -29,4 +29,4 @@ fs.writeFileSync(nxConfigPath, JSON.stringify(nxConfig, null, 2)); greenLog('\nšŸ“ This script enables or disables the cache in the nx.json file.\n', true); greenLog('--enable=true: Enable the cache', true); greenLog('--enable=false: Disable the cache', true); - +process.exit(); \ No newline at end of file diff --git a/tools/scripts/test-script.mjs b/tools/scripts/test-script.mjs index d0b8f53c70..3b730222c7 100644 --- a/tools/scripts/test-script.mjs +++ b/tools/scripts/test-script.mjs @@ -51,10 +51,10 @@ function findTestFiles(dir, exts) { * Run the test command for the given test file * @param {string} testFile - The path of the test file */ -function runTest(testFile) { +async function runTest(testFile) { const command = `bun test ${testFile}`; console.log('Running command: ', command); - bunSpawn(command, { stdout: 'inherit' }); + await bunSpawn(command, { stdout: 'inherit' }); } const testFiles = findTestFiles(TEST_DIR, TEST_FILE_EXTENSIONS); @@ -74,9 +74,11 @@ if (testName) { } for (const filePath of matchingTestFiles) { - runTest(filePath); + await runTest(filePath); } } else { redLog('Please provide a test name. eg. bun test:file lit-node-client'); process.exit(1); } + +process.exit(0); \ No newline at end of file diff --git a/tools/scripts/utils.mjs b/tools/scripts/utils.mjs index 72052a716a..069f490600 100644 --- a/tools/scripts/utils.mjs +++ b/tools/scripts/utils.mjs @@ -162,15 +162,17 @@ export const spawnCommand = ( }); }; -export const bunSpawn = (commands, options = {}) => { +export const bunSpawn = async (commands, options = {}) => { const defaultOptions = { stdout: 'inherit' }; let _commands = commands.split(' '); - Bun.spawn(_commands, { + const proc = Bun.spawn(_commands, { ...defaultOptions, ...options, }); + + await proc.exited; }; export const spawnListener = (commands, callback, prefix = '', color = 31) => { From b83f15d03c05ad0479e1e63f31b775b0cdda56e5 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 14 Sep 2023 10:48:21 +0100 Subject: [PATCH 07/10] chore: bun test lit node client --- .../src/lib/lit-node-client2.spec.ts | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 packages/lit-node-client/src/lib/lit-node-client2.spec.ts diff --git a/packages/lit-node-client/src/lib/lit-node-client2.spec.ts b/packages/lit-node-client/src/lib/lit-node-client2.spec.ts new file mode 100644 index 0000000000..1d29d120a3 --- /dev/null +++ b/packages/lit-node-client/src/lib/lit-node-client2.spec.ts @@ -0,0 +1,70 @@ +import { LitNodeClient } from './lit-node-client'; +import * as LITCONFIG from 'lit.config.json'; + +let client: LitNodeClient; + +describe('Lit Actions', async () => { + client = new LitNodeClient({ + litNetwork: 'cayenne', + debug: true + }); + + await client.connect(); + + test('should be connected', async () => { + expect(client.ready).toBe(true); + }); + + test('lit action log should return hello world', async () => { + + const res = await client.executeJs({ + authSig: LITCONFIG.CONTROLLER_AUTHSIG, + code: `(async () => { + console.log('hello world') + })();`, + jsParams: { + publicKey: LITCONFIG.PKP_PUBKEY, + }, + }) + + expect(res.logs).toContain('hello world'); + }); + + it('lit action response should return json {hello: "world"}', async () => { + const res = await client.executeJs({ + authSig: LITCONFIG.CONTROLLER_AUTHSIG, + code: `(async () => { + LitActions.setResponse({ + response: JSON.stringify({hello: 'world'}) + }); + })();`, + jsParams: { + publicKey: LITCONFIG.PKP_PUBKEY, + }, + }) + expect(res.response).toEqual(JSON.stringify({ hello: 'world' })); + }); + + it('lit action should sign a message', async () => { + + const res = await client.executeJs({ + authSig: LITCONFIG.CONTROLLER_AUTHSIG, + code: `(async () => { + const sigShare = await LitActions.signEcdsa({ + toSign, + publicKey, + sigName + }); + })();`, + jsParams: { + // hello world in Uint8Array + toSign: [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], + publicKey: LITCONFIG.PKP_PUBKEY, + sigName: 'hello-world-sig', + }, + }); + + expect(res).toBe(1); + + }); +}); From 2799773f5f0026bb59298be3a1bc6a9d0f0e821c Mon Sep 17 00:00:00 2001 From: Josh Long Date: Thu, 14 Sep 2023 18:59:18 -0400 Subject: [PATCH 08/10] Update executeJs for claim processing from execution response --- .../src/lib/lit-node-client-nodejs.ts | 116 +++++++++++++----- packages/types/src/lib/interfaces.ts | 3 + 2 files changed, 90 insertions(+), 29 deletions(-) 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 index 1170af6e66..b730078007 100644 --- 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 @@ -827,28 +827,45 @@ export class LitNodeClientNodeJs extends LitCore { // ========== Shares Resolvers ========== _getFlattenShare = (share: any): SigShare => { - // flatten the signature object so that the properties of the signature are top level const flattenObj = Object.entries(share).map(([key, item]) => { - if (item === null || item === undefined) { return null; } const typedItem = item as SigShare; - const requiredShareProps = ['sigType', 'dataSigned', 'signatureShare', 'shareIndex', 'bigR', 'publicKey'] - - const requiredSessionSigsShareProps = [...requiredShareProps, 'siweMessage'] as const; - - const requiredSignatureShareProps = [...requiredShareProps, 'sigName'] as const; + const requiredShareProps = [ + 'sigType', + 'dataSigned', + 'signatureShare', + 'shareIndex', + 'bigR', + 'publicKey', + ]; + + const requiredSessionSigsShareProps = [ + ...requiredShareProps, + 'siweMessage', + ] as const; + + const requiredSignatureShareProps = [ + ...requiredShareProps, + 'sigName', + ] as const; const hasProps = (props: any) => { - return [...props].every(prop => typedItem[prop as keyof SigShare] !== undefined && typedItem[prop as keyof SigShare] !== null) - } - - if (hasProps(requiredSessionSigsShareProps) || hasProps(requiredSignatureShareProps)) { + return [...props].every( + (prop) => + typedItem[prop as keyof SigShare] !== undefined && + typedItem[prop as keyof SigShare] !== null + ); + }; + if ( + hasProps(requiredSessionSigsShareProps) || + hasProps(requiredSignatureShareProps) + ) { typedItem.signatureShare = typedItem.signatureShare.replaceAll('"', ''); typedItem.bigR = typedItem.bigR.replaceAll('"', ''); typedItem.publicKey = typedItem.publicKey.replaceAll('"', ''); @@ -861,14 +878,15 @@ export class LitNodeClientNodeJs extends LitCore { }); // removed all null values and should only have one item - const flattenShare = (flattenObj.filter(item => item !== null))[0] as SigShare; - + const flattenShare = flattenObj.filter( + (item) => item !== null + )[0] as SigShare; if (flattenShare === null || flattenShare === undefined) { - return share + return share; } return flattenShare; - } + }; /** * @@ -893,9 +911,8 @@ export class LitNodeClientNodeJs extends LitCore { shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex); const sigShares: Array = shares.map((s: any) => { - const share = this._getFlattenShare(s); - console.log("XX share", share) + console.log('XX share', share); return { sigType: share.sigType, @@ -905,7 +922,7 @@ export class LitNodeClientNodeJs extends LitCore { publicKey: share.publicKey, dataSigned: share.dataSigned, siweMessage: share.siweMessage, - } + }; }); log('getSessionSignatures - sigShares', sigShares); @@ -940,10 +957,10 @@ export class LitNodeClientNodeJs extends LitCore { throwError({ message: 'siganture could not be combined', errorKind: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.kind, - errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name + errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name, }); } - + const encodedSig = joinSignature({ r: '0x' + signature.r, s: '0x' + signature.s, @@ -986,11 +1003,10 @@ export class LitNodeClientNodeJs extends LitCore { shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex); const sigShares: Array = shares.map((s: any) => { - const share = this._getFlattenShare(s); - console.log("YY share", share) + console.log('YY share', share); - return ({ + return { sigType: share.sigType, signatureShare: share.signatureShare, shareIndex: share.shareIndex, @@ -998,7 +1014,7 @@ export class LitNodeClientNodeJs extends LitCore { publicKey: share.publicKey, dataSigned: share.dataSigned, sigName: share.sigName ? share.sigName : 'sig', - }) + }; }); log('getSignatures - sigShares', sigShares); @@ -1033,7 +1049,7 @@ export class LitNodeClientNodeJs extends LitCore { throwError({ message: 'siganture could not be combined', errorKind: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.kind, - errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name + errorCode: LIT_ERROR.UNKNOWN_SIGNATURE_ERROR.name, }); } @@ -1054,6 +1070,31 @@ export class LitNodeClientNodeJs extends LitCore { return signatures; }; + getClaims = (claims: any[]): Record => { + let keys: string[] = Object.keys(claims[0]); + let signatures: Record = {}; + let claimRes: Record = {}; + for (let i = 0; i < keys.length; i++) { + let claimSet: {signature: string, keyId: string}[] = claims.map(c => c[keys[i]]); + signatures[keys[i]] = []; + for (let j = 0; i < claimSet.length; i++) { + let sig = ethers.utils.splitSignature(`0x${claimSet[j].signature}`); + let convertedSig = { + r: sig.r, + s: sig.s, + v: sig.v, + }; + signatures[keys[i]].push(convertedSig); + } + claimRes[keys[i]] = { + signatures: signatures[keys[i]], + keyId: claimSet[0].keyId + }; + } + + return claimRes; + } + /** * * Get a single signature @@ -1168,8 +1209,12 @@ export class LitNodeClientNodeJs extends LitCore { log('responseData', JSON.stringify(responseData, null, 2)); // -- in the case where we are not signing anything on Lit action and using it as purely serverless function - if (Object.keys(responseData[0].signedData).length <= 0) { + if ( + Object.keys(responseData[0].signedData).length <= 0 && + Object.keys(responseData[0].claimData).length <= 0 + ) { return { + claims: {}, signatures: null, decryptions: [], response: responseData[0].response, @@ -1210,8 +1255,22 @@ export class LitNodeClientNodeJs extends LitCore { responseData.map((r: NodeLog) => r.logs) ); + // -- 4. combine claims + const claimsList = responseData.map((r) => { + const { claimData } = r; + for (const key of Object.keys(claimData)) { + for (const subkey of Object.keys(claimData[key])) { + if (typeof claimData[key][subkey] == 'string') { + claimData[key][subkey] = claimData[key][subkey].replaceAll('"', ''); + } + + } + } + }); + const claims = this.getClaims(claimsList); // ========== Result ========== let returnVal: ExecuteJsResponse = { + claims, signatures, decryptions: [], // FIXME: Fix if and when we enable decryptions from within a Lit Action. response, @@ -1965,8 +2024,8 @@ export class LitNodeClientNodeJs extends LitCore { const sessionCapabilityObject = params.sessionCapabilityObject ? params.sessionCapabilityObject : this.generateSessionCapabilityObjectWithWildcards( - params.resourceAbilityRequests.map((r) => r.resource) - ); + params.resourceAbilityRequests.map((r) => r.resource) + ); let expiration = params.expiration || this.getExpiration(); // -- (TRY) to get the wallet signature @@ -2163,7 +2222,6 @@ export class LitNodeClientNodeJs extends LitCore { mintTx, }; } else { - return throwError({ message: `Claim request has failed. Request trace id: lit_${requestId} `, errorKind: LIT_ERROR.UNKNOWN_ERROR.kind, diff --git a/packages/types/src/lib/interfaces.ts b/packages/types/src/lib/interfaces.ts index 467ed3bce4..108bb1881b 100644 --- a/packages/types/src/lib/interfaces.ts +++ b/packages/types/src/lib/interfaces.ts @@ -5,6 +5,7 @@ import { AccessControlConditions, Chain, ClaimProcessor, + ClaimResult, ConditionType, EncryptedSymmetricKey, EvmContractConditions, @@ -555,6 +556,7 @@ export interface ExecuteJsResponse { decryptions: any[]; response: string; logs: string; + claims: Record; debug?: { allNodeResponses: NodeResponse[]; allNodeLogs: NodeLog[]; @@ -571,6 +573,7 @@ export interface SendNodeCommand { } export interface NodeShare { + claimData: any; shareIndex: any; unsignedJwt: any; signedData: any; From 13796728d38deb1019ad50419d405d85fe4f5a5f Mon Sep 17 00:00:00 2001 From: Josh Long Date: Thu, 14 Sep 2023 19:01:42 -0400 Subject: [PATCH 09/10] chage claim test --- .../src/lib/lit-node-client.spec.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/lit-node-client/src/lib/lit-node-client.spec.ts b/packages/lit-node-client/src/lib/lit-node-client.spec.ts index c473e932bb..eb92026fd0 100644 --- a/packages/lit-node-client/src/lib/lit-node-client.spec.ts +++ b/packages/lit-node-client/src/lib/lit-node-client.spec.ts @@ -108,14 +108,14 @@ describe('Lit Actions', () => { it('should claim key id from auth method', async () => { - + const authMethod = { + authMethodType: 4, + accessToken: LITCONFIG.AUTH_METHOD_ACCESS_TOKEN + }; let res = await client.claimKeyId({ - authMethod: { - authMethodType: 4, - accessToken: "RTPcbUUguY7YtOjZhKeXtEPTYkXfgX" - } + authMethod }); - + const data = { // hello world in Uint8Array toSign: [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100], @@ -123,14 +123,10 @@ describe('Lit Actions', () => { sigName: 'hello-world-sig', }; - let authMethod = { - authMethodType: 4, - accessToken: "RTPcbUUguY7YtOjZhKeXtEPTYkXfgX" - } let sig = await client.pkpSign({ toSign: data.toSign, - pubKey: "0x044ec325db817193c3a01088d082ded81dc0a29ad615a67b87b9e295d9a1c91d955f8aeeec551d5d4930795f5c390e369f745e36e97893ead710354ee882ed60c0", + pubKey: res.pubkey, authMethods: [authMethod], authSig: LITCONFIG.CONTROLLER_AUTHSIG, }); From 39c5474c282b2a271309b37a5074e2b65b806966 Mon Sep 17 00:00:00 2001 From: Josh Long Date: Thu, 14 Sep 2023 19:02:22 -0400 Subject: [PATCH 10/10] add new error type --- packages/constants/src/lib/errors.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/constants/src/lib/errors.ts b/packages/constants/src/lib/errors.ts index d65903167c..e5c4db8e10 100644 --- a/packages/constants/src/lib/errors.ts +++ b/packages/constants/src/lib/errors.ts @@ -106,6 +106,11 @@ export const LIT_ERROR = { code: 'unknown_signature_type', kind: LitErrorKind.Validation, }, + UNKNOWN_SIGNATURE_ERROR: { + name: "UnknownSignatureError", + code: 'unknown_signature_error', + kind: LitErrorKind.Unknown, + }, PARAM_NULL_ERROR: { name: 'ParamNullError', code: 'param_null_error',