Transform more files to TS, replace lit-js-sdk with js-sdk (#4)

This commit is contained in:
Howard 2023-02-23 16:39:50 -08:00 committed by GitHub
parent 339986b666
commit efb3eab092
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 2846 additions and 1840 deletions

View File

@ -5,21 +5,24 @@
"dependencies": { "dependencies": {
"@emotion/react": "^11.10.5", "@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5", "@emotion/styled": "^11.10.5",
"@lit-protocol/access-control-conditions": "2.1.17",
"@lit-protocol/bls-sdk": "2.1.17",
"@lit-protocol/constants": "2.1.17",
"@lit-protocol/crypto": "2.1.17",
"@lit-protocol/lit-node-client": "2.1.17",
"@mui/material": "^5.10.16", "@mui/material": "^5.10.16",
"@react-oauth/google": "^0.4.0", "@react-oauth/google": "^0.4.0",
"@simplewebauthn/browser": "^6.2.2", "@simplewebauthn/browser": "^6.2.2",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"@types/jest": "24.0.17", "@types/jest": "^29.4.0",
"@types/node": "12.6.9", "@types/node": "^18.11.19",
"@types/react": "16.8.24", "@types/react": "^18.0.27",
"@types/react-dom": "16.8.5", "@types/react-dom": "^18.0.10",
"@types/react-router-dom": "^4.3.4",
"base64url": "^3.0.1", "base64url": "^3.0.1",
"ethers": "^5.7.2", "ethers": "^5.7.2",
"js-base64": "^3.7.2", "js-base64": "^3.7.2",
"lit-js-sdk": "^1.2.37",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",

View File

@ -1,40 +1,53 @@
import * as LitJsSdk_accessControlConditions from "@lit-protocol/access-control-conditions";
import * as LitJsSdk_blsSdk from "@lit-protocol/bls-sdk";
import { AccsDefaultParams } from "@lit-protocol/constants";
import * as LitJsSdk from "@lit-protocol/lit-node-client";
import { Button, ButtonGroup } from "@mui/material";
import { GoogleLogin } from "@react-oauth/google"; import { GoogleLogin } from "@react-oauth/google";
import { ethers, utils } from "ethers"; import {
import LitJsSdk from "lit-js-sdk"; startAuthentication,
startRegistration,
} from "@simplewebauthn/browser";
import base64url from "base64url";
import { utils } from "ethers";
import { hexlify } from "ethers/lib/utils";
import { useState } from "react"; import { useState } from "react";
import "./App.css"; import "./App.css";
import { ButtonGroup, Button } from "@mui/material";
import base64url from "base64url";
import {
startRegistration,
startAuthentication,
} from "@simplewebauthn/browser";
import { parseAuthenticatorData } from "./utils/parseAuthenticatorData";
import { decodeAttestationObject } from "./utils/decodeAttestationObject"; import { decodeAttestationObject } from "./utils/decodeAttestationObject";
import { hexlify } from "ethers/lib/utils"; import { parseAuthenticatorData } from "./utils/parseAuthenticatorData";
window.LitJsSdk = LitJsSdk; type CredentialResponse = any;
window.ethers = ethers;
declare global {
interface Window {
cbor: any;
}
}
const RELAY_API_URL = const RELAY_API_URL =
process.env.REACT_APP_RELAY_API_URL || "http://localhost:3001"; process.env.REACT_APP_RELAY_API_URL || "http://localhost:3001";
function App() { function App() {
const [pkpEthAddress, setPkpEthAddress] = useState(null); const [pkpEthAddress, setPkpEthAddress] = useState<string>("");
const [googleCredentialResponse, setGoogleCredentialResponse] = useState( const [
null googleCredentialResponse,
); setGoogleCredentialResponse,
const [pkpPublicKey, setPkpPublicKey] = useState(null); ] = useState<CredentialResponse | null>(null);
const [pkpPublicKey, setPkpPublicKey] = useState<string>("");
const [status, setStatus] = useState(""); const [status, setStatus] = useState("");
const [selectedAuthMethod, setSelectedAuthMethod] = useState(6); const [selectedAuthMethod, setSelectedAuthMethod] = useState(6);
const [ const [
webAuthnCredentialPublicKey, webAuthnCredentialPublicKey,
setWebAuthnCredentialPublicKey, setWebAuthnCredentialPublicKey,
] = useState(); ] = useState<string>("");
const [webAuthnSignature, setWebAuthnSignature] = useState(); const [webAuthnSignature, setWebAuthnSignature] = useState<string>("");
const [webAuthnSignatureBase, setWebAuthnSignatureBase] = useState(); const [webAuthnSignatureBase, setWebAuthnSignatureBase] = useState<string>(
""
);
const handleLoggedInToGoogle = async credentialResponse => { const handleLoggedInToGoogle = async (
credentialResponse: CredentialResponse
) => {
setStatus("Logged in to Google"); setStatus("Logged in to Google");
console.log("Got response from google sign in: ", { console.log("Got response from google sign in: ", {
credentialResponse, credentialResponse,
@ -98,8 +111,11 @@ function App() {
<div>PKP Eth Address: {pkpEthAddress}</div> <div>PKP Eth Address: {pkpEthAddress}</div>
)} )}
<h3> <h3>
Step 2: Use Lit Network to obtain a session sig and then <s>
store an encryption condition. Step 2: Use Lit Network to obtain a session sig and
then store an encryption condition.
</s>
(Session Sigs do not work currently.)
</h3> </h3>
<button <button
onClick={() => onClick={() =>
@ -107,7 +123,11 @@ function App() {
setStatus, setStatus,
selectedAuthMethod, selectedAuthMethod,
googleCredentialResponse, googleCredentialResponse,
{}, {
signature: "dummy",
signatureBase: "dummy",
credentialPublicKey: "dummy",
},
pkpEthAddress, pkpEthAddress,
pkpPublicKey pkpPublicKey
) )
@ -153,7 +173,7 @@ function App() {
// set in local state // set in local state
setWebAuthnCredentialPublicKey( setWebAuthnCredentialPublicKey(
hexlify( hexlify(
parsedAuthData.credentialPublicKey parsedAuthData.credentialPublicKey!
) )
); );
} }
@ -181,8 +201,11 @@ function App() {
Authenticate Authenticate
</Button> </Button>
<h3> <h3>
Step 3: Use Lit Network to obtain a session sig and then <s>
store an encryption condition. Step 3: Use Lit Network to obtain a session sig and
then store an encryption condition.
</s>
(Session Sigs do not work currently.)
</h3> </h3>
<Button <Button
variant="contained" variant="contained"
@ -212,8 +235,8 @@ function App() {
export default App; export default App;
async function mintPkpUsingRelayerGoogleAuthVerificationEndpoint( async function mintPkpUsingRelayerGoogleAuthVerificationEndpoint(
credentialResponse, credentialResponse: any,
setStatusFn setStatusFn: (status: string) => void
) { ) {
setStatusFn("Minting PKP with relayer..."); setStatusFn("Minting PKP with relayer...");
@ -240,10 +263,10 @@ async function mintPkpUsingRelayerGoogleAuthVerificationEndpoint(
} }
async function mintPkpUsingRelayerWebAuthnVerificationEndpoint( async function mintPkpUsingRelayerWebAuthnVerificationEndpoint(
signature, signature: string,
signatureBase, signatureBase: string,
credentialPublicKey, credentialPublicKey: string,
setStatusFn setStatusFn: (status: string) => void
) { ) {
setStatusFn("Minting PKP with relayer..."); setStatusFn("Minting PKP with relayer...");
@ -272,9 +295,15 @@ async function mintPkpUsingRelayerWebAuthnVerificationEndpoint(
} }
async function pollRequestUntilTerminalState( async function pollRequestUntilTerminalState(
requestId, requestId: string,
setStatusFn, setStatusFn: (status: string) => void,
onSuccess onSuccess: ({
pkpEthAddress,
pkpPublicKey,
}: {
pkpEthAddress: string;
pkpPublicKey: string;
}) => void
) { ) {
if (!requestId) { if (!requestId) {
return; return;
@ -326,15 +355,19 @@ async function pollRequestUntilTerminalState(
} }
async function handleStoreEncryptionCondition( async function handleStoreEncryptionCondition(
setStatusFn, setStatusFn: (status: string) => void,
selectedAuthMethod, selectedAuthMethod: number,
googleCredentialResponse, googleCredentialResponse: any,
webAuthnVerificationMaterial, webAuthnVerificationMaterial: {
pkpEthAddress, signature: string;
pkpPublicKey signatureBase: string;
credentialPublicKey: string;
},
pkpEthAddress: string,
pkpPublicKey: string
) { ) {
setStatusFn("Storing encryption condition..."); setStatusFn("Storing encryption condition...");
var unifiedAccessControlConditions = [ var unifiedAccessControlConditions: AccsDefaultParams[] = [
{ {
conditionType: "evmBasic", conditionType: "evmBasic",
contractAddress: "", contractAddress: "",
@ -356,7 +389,7 @@ async function handleStoreEncryptionCondition(
expiration, expiration,
uri, uri,
litNodeClient, litNodeClient,
}) => { }: any) => {
console.log("authNeededCallback fired"); console.log("authNeededCallback fired");
const authMethods = const authMethods =
selectedAuthMethod === 6 selectedAuthMethod === 6
@ -396,9 +429,6 @@ async function handleStoreEncryptionCondition(
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours
chain: "ethereum", chain: "ethereum",
resources: [`litEncryptionCondition://*`], resources: [`litEncryptionCondition://*`],
sessionCapabilityObject: {
def: ["litEncryptionCondition"],
},
switchChain: false, switchChain: false,
authNeededCallback, authNeededCallback,
}); });
@ -409,7 +439,7 @@ async function handleStoreEncryptionCondition(
); );
// value parameter - hash unified conditions // value parameter - hash unified conditions
const hashedAccessControlConditions = await LitJsSdk.hashUnifiedAccessControlConditions( const hashedAccessControlConditions = await LitJsSdk_accessControlConditions.hashUnifiedAccessControlConditions(
unifiedAccessControlConditions unifiedAccessControlConditions
); );
console.log("hashedAccessControlConditions", { console.log("hashedAccessControlConditions", {
@ -421,12 +451,12 @@ async function handleStoreEncryptionCondition(
); );
// key parameter - encrypt symmetric key then hash it // key parameter - encrypt symmetric key then hash it
const encryptedSymmetricKey = LitJsSdk.encryptWithBlsPubkey({ const encryptedSymmetricKey = LitJsSdk_blsSdk.wasmBlsSdkHelpers.encrypt(
pubkey: litNodeClient.networkPubKey, LitJsSdk.uint8arrayFromString(litNodeClient.subnetPubKey, "base16"),
data: symmetricKey, symmetricKey
}); );
const hashedEncryptedSymmetricKeyStr = await LitJsSdk.hashEncryptionKey({ const hashedEncryptedSymmetricKeyStr = await hashBytes({
encryptedSymmetricKey, bytes: new Uint8Array(encryptedSymmetricKey),
}); });
// securityHash parameter - encrypt symmetric key, concat with creator address // securityHash parameter - encrypt symmetric key, concat with creator address
@ -435,9 +465,9 @@ async function handleStoreEncryptionCondition(
...encryptedSymmetricKey, ...encryptedSymmetricKey,
...pkpEthAddressBytes, ...pkpEthAddressBytes,
]); ]);
// TODO: LitJsSdk.hashEncryptionKey ought to be renamed to just .hashBytes
const securityHashStr = await LitJsSdk.hashEncryptionKey({ const securityHashStr = await hashBytes({
encryptedSymmetricKey: securityHashPreimage, bytes: securityHashPreimage,
}); });
console.log("Storing encryption condition with relay", { console.log("Storing encryption condition with relay", {
@ -476,102 +506,114 @@ async function handleStoreEncryptionCondition(
} }
} }
async function handleEncryptThenDecrypt( async function hashBytes({ bytes }: { bytes: Uint8Array }): Promise<string> {
setStatusFn, const hashOfBytes = await crypto.subtle.digest("SHA-256", bytes);
googleCredentialResponse, const hashOfBytesStr = LitJsSdk.uint8arrayToString(
pkpEthAddress, new Uint8Array(hashOfBytes),
pkpPublicKey "base16"
) {
setStatusFn("Encrypting then decrypting...");
var unifiedAccessControlConditions = [
{
conditionType: "evmBasic",
contractAddress: "",
standardContractType: "",
chain: "mumbai",
method: "",
parameters: [":userAddress"],
returnValueTest: {
comparator: "=",
value: pkpEthAddress,
},
},
];
// this will be fired if auth is needed. we can use this to prompt the user to sign in
const authNeededCallback = async ({
chain,
resources,
expiration,
uri,
litNodeClient,
}) => {
console.log("authNeededCallback fired");
const sessionSig = await litNodeClient.signSessionKey({
sessionKey: uri,
authMethods: [
{
authMethodType: 6,
accessToken: googleCredentialResponse.credential,
},
],
pkpPublicKey,
expiration,
resources,
chain,
});
console.log("got session sig from node and PKP: ", sessionSig);
return sessionSig;
};
// get the user a session with it
const litNodeClient = new LitJsSdk.LitNodeClient({
litNetwork: "serrano",
});
await litNodeClient.connect();
const sessionSigs = await litNodeClient.getSessionSigs({
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours
chain: "ethereum",
resources: [`litEncryptionCondition://*`],
switchChain: false,
authNeededCallback,
});
console.log("sessionSigs before saving encryption key: ", sessionSigs);
const { encryptedZip, symmetricKey } = await LitJsSdk.zipAndEncryptString(
"this is a secret message"
); );
return hashOfBytesStr;
const encryptedSymmetricKey = await litNodeClient.saveEncryptionKey({
unifiedAccessControlConditions,
symmetricKey,
sessionSigs,
});
const hashOfKey = await LitJsSdk.hashEncryptionKey({
encryptedSymmetricKey,
});
console.log("encrypted symmetric key", encryptedSymmetricKey);
const retrievedSymmKey = await litNodeClient.getEncryptionKey({
unifiedAccessControlConditions,
toDecrypt: LitJsSdk.uint8arrayToString(encryptedSymmetricKey, "base16"),
sessionSigs,
});
const decryptedFiles = await LitJsSdk.decryptZip(
encryptedZip,
retrievedSymmKey
);
const decryptedString = await decryptedFiles["string.txt"].async("text");
console.log("decrypted string", decryptedString);
setStatusFn("Success!");
} }
async function handleWebAuthnRegister(setStatusFn, onSuccess) { // async function handleEncryptThenDecrypt(
// setStatusFn,
// googleCredentialResponse,
// pkpEthAddress,
// pkpPublicKey
// ) {
// setStatusFn("Encrypting then decrypting...");
// var unifiedAccessControlConditions = [
// {
// conditionType: "evmBasic",
// contractAddress: "",
// standardContractType: "",
// chain: "mumbai",
// method: "",
// parameters: [":userAddress"],
// returnValueTest: {
// comparator: "=",
// value: pkpEthAddress,
// },
// },
// ];
// // this will be fired if auth is needed. we can use this to prompt the user to sign in
// const authNeededCallback = async ({
// chain,
// resources,
// expiration,
// uri,
// litNodeClient,
// }) => {
// console.log("authNeededCallback fired");
// const sessionSig = await litNodeClient.signSessionKey({
// sessionKey: uri,
// authMethods: [
// {
// authMethodType: 6,
// accessToken: googleCredentialResponse.credential,
// },
// ],
// pkpPublicKey,
// expiration,
// resources,
// chain,
// });
// console.log("got session sig from node and PKP: ", sessionSig);
// return sessionSig;
// };
// // get the user a session with it
// const litNodeClient = new LitJsSdk.LitNodeClient({
// litNetwork: "serrano",
// });
// await litNodeClient.connect();
// const sessionSigs = await litNodeClient.getSessionSigs({
// expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours
// chain: "ethereum",
// resources: [`litEncryptionCondition://*`],
// switchChain: false,
// authNeededCallback,
// });
// console.log("sessionSigs before saving encryption key: ", sessionSigs);
// const { encryptedZip, symmetricKey } = await LitJsSdk.zipAndEncryptString(
// "this is a secret message"
// );
// const encryptedSymmetricKey = await litNodeClient.saveEncryptionKey({
// unifiedAccessControlConditions,
// symmetricKey,
// sessionSigs,
// });
// const hashOfKey = await LitJsSdk.hashEncryptionKey({
// encryptedSymmetricKey,
// });
// console.log("encrypted symmetric key", encryptedSymmetricKey);
// const retrievedSymmKey = await litNodeClient.getEncryptionKey({
// unifiedAccessControlConditions,
// toDecrypt: LitJsSdk.uint8arrayToString(encryptedSymmetricKey, "base16"),
// sessionSigs,
// });
// const decryptedFiles = await LitJsSdk.decryptZip(
// encryptedZip,
// retrievedSymmKey
// );
// const decryptedString = await decryptedFiles["string.txt"].async("text");
// console.log("decrypted string", decryptedString);
// setStatusFn("Success!");
// }
async function handleWebAuthnRegister(
setStatusFn: (status: string) => void,
onSuccess: ({ attResp }: { attResp: any }) => void
) {
const resp = await fetch(`${RELAY_API_URL}/generate-registration-options`); const resp = await fetch(`${RELAY_API_URL}/generate-registration-options`);
let attResp; let attResp;
@ -620,11 +662,11 @@ async function handleWebAuthnRegister(setStatusFn, onSuccess) {
} }
async function handleWebAuthnAuthenticate( async function handleWebAuthnAuthenticate(
setStatusFn, setStatusFn: (status: string) => void,
webAuthnCredentialPublicKey, webAuthnCredentialPublicKey: string,
onSuccess, onSuccess: (resp: any) => void,
setWebAuthnSignatureFn, setWebAuthnSignatureFn: (signature: string) => void,
setWebAuthnSignatureBaseFn setWebAuthnSignatureBaseFn: (signatureBase: string) => void
) { ) {
const resp = await fetch( const resp = await fetch(
`${RELAY_API_URL}/generate-authentication-options` `${RELAY_API_URL}/generate-authentication-options`

View File

@ -5,7 +5,9 @@ import App from "./App";
import reportWebVitals from "./reportWebVitals"; import reportWebVitals from "./reportWebVitals";
import { GoogleOAuthProvider } from "@react-oauth/google"; import { GoogleOAuthProvider } from "@react-oauth/google";
const root = ReactDOM.createRoot(document.getElementById("root")); const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<GoogleOAuthProvider clientId="1071348522014-3qq1ln33ful535dnd8r4f6f9vtjrv2nu.apps.googleusercontent.com"> <GoogleOAuthProvider clientId="1071348522014-3qq1ln33ful535dnd8r4f6f9vtjrv2nu.apps.googleusercontent.com">

1
src/react-app-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="react-scripts" />

View File

@ -1,6 +1,8 @@
const reportWebVitals = onPerfEntry => { import { ReportHandler } from "web-vitals";
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) { if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry); getCLS(onPerfEntry);
getFID(onPerfEntry); getFID(onPerfEntry);
getFCP(onPerfEntry); getFCP(onPerfEntry);

View File

@ -1,25 +1,26 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es6",
"lib": [ "lib": [
"dom", "dom",
"dom.iterable", "dom.iterable",
"esnext" "esnext"
], ],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strict": true, "strict": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"module": "esnext", "noFallthroughCasesInSwitch": true,
"moduleResolution": "node", "module": "esnext",
"resolveJsonModule": true, "moduleResolution": "node",
"isolatedModules": true, "resolveJsonModule": true,
"noEmit": true, "isolatedModules": true,
"jsx": "preserve" "noEmit": true,
"jsx": "react-jsx"
}, },
"include": [ "include": [
"src" "src"
] ]
} }

4275
yarn.lock

File diff suppressed because it is too large Load Diff