first commit

This commit is contained in:
Samuel Andert 2023-07-18 15:36:33 +02:00
parent bb4cd43210
commit 5fdaefac93
44 changed files with 23022 additions and 41530 deletions

3
.eslintrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

20
.gitignore vendored
View File

@ -8,20 +8,28 @@
# testing # testing
/coverage /coverage
# next.js
/.next/
/out/
# production # production
/build /build
# misc # misc
.DS_Store .DS_Store
.env.local *.pem
.env.development.local
.env.test.local
.env.production.local
# debug
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
.yalc # local env files
.env*.local
.env* # vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@ -1,5 +0,0 @@
{
"tabWidth": 4,
"useTabs": true,
"trailingComma": "es5"
}

View File

@ -1,24 +1,44 @@
# Lit Protocol Oauth -> Wallet example # `signAndSaveAuthMessage` example
This project lets you start using Ethereum with just a Google Account. It's a simple example of how to use the Lit Protocol Oauth service to authenticate users and then use their Ethereum address. This is a [Next.js](https://nextjs.org/) example that demonstrates how to use the `signAndSaveAuthMessage` function from the `@lit-protocol/auth-browser` package with a **Connect Wallet** modal like [RainbowKit](https://www.rainbowkit.com/docs/introduction).
This project specifically: Note: This example uses prior versions of RainbowKit and `wagmi` that are compatible with `ethers`.
1. Uses Google Oauth to auth the user ## 💻 Getting Started
2. Mints a PKP token for the user, with their Google account as a valid auth method
3. Uses the PKP token to get an Ethereum address for the user
4. Generates a local session key for the user and stores it in LocalStorage
5. Uses the Lit Protocol's PKP Session Signing service to sign that session key with their PKP
6. Uses the local session key to sign a request to encrypt and decrypt a string that only the user can decrypt.
## How to run 1. Clone this repo and download dependencies:
First, run `yarn install`. Then run `yarn start` to run this project. You'll need a Metamask wallet set to the Chronicle network with some Lit Test tokens in it. You can learn more about Chronicle here: https://developer.litprotocol.com/intro/rollup ```bash
git clone git@github.com:LIT-Protocol/sdk-examples.git
cd connect-wallet-authsig
npm install
# or
yarn
# or
pnpm
```
Sign in with Google and wait until it says "PKP Minted". Then, click the "Encrypt then Decrypt with Lit" button. If you see the word "Success!" at the top, then it worked! Open the dev console to see how it works. 2. Add environment variables:
You also need to set 2 env vars: ```bash
NEXT_PUBLIC_ENABLE_TESTNETS='<true or false>'
NEXT_PUBLIC_WC_PROJECT_ID='<Your WalletConnect project ID>'
```
export REACT_APP_RELAY_API_URL="https://relay-server-staging.herokuapp.com" 3. Run the development server:
export REACT_APP_RPC_URL="https://chain-rpc.litprotcol.com/http" ```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
## 📚 Resources
- [Lit Protocol Developer Docs](https://developer.litprotocol.com/)
- [`@lit-protocol/auth-browser` API Docs](https://js-sdk.litprotocol.com/modules/auth_browser_src.html)

View File

@ -1,15 +0,0 @@
module.exports = {
webpack: function(config, env) {
config.module.rules = config.module.rules.map(rule => {
if (rule.oneOf instanceof Array) {
rule.oneOf[rule.oneOf.length - 1].exclude = [
/\.(js|mjs|jsx|cjs|ts|tsx)$/,
/\.html$/,
/\.json$/,
];
}
return rule;
});
return config;
},
};

7
jsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}

4
next.config.js Normal file
View File

@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = nextConfig

52589
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,66 +1,23 @@
{ {
"name": "oauth-pkp-signup", "name": "connect-wallet-authsig",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "scripts": {
"@emotion/react": "^11.10.5", "dev": "next dev",
"@emotion/styled": "^11.10.5", "build": "next build",
"@lit-protocol/access-control-conditions": "^2.2.0", "start": "next start",
"@lit-protocol/auth-helpers": "^2.2.0", "lint": "next lint"
"@lit-protocol/bls-sdk": "^2.2.0", },
"@lit-protocol/constants": "^2.2.0", "dependencies": {
"@lit-protocol/crypto": "^2.2.0", "@lit-protocol/contracts-sdk": "^2.2.41",
"@lit-protocol/lit-node-client": "^2.2.0", "@lit-protocol/lit-node-client": "^2.2.41",
"@lit-protocol/lit-node-client-nodejs": "^2.2.0", "@lit-protocol/pkp-ethers": "^2.2.41",
"@lit-protocol/types": "^2.2.0", "@rainbow-me/rainbowkit": "^0.12.17",
"@mui/material": "^5.10.16", "eslint": "8.44.0",
"@react-oauth/google": "^0.4.0", "eslint-config-next": "13.4.9",
"@simplewebauthn/browser": "^6.2.2", "next": "13.4.9",
"@testing-library/jest-dom": "^5.16.5", "react": "18.2.0",
"@testing-library/react": "^13.4.0", "react-dom": "18.2.0",
"@testing-library/user-event": "^13.5.0", "wagmi": "^0.12.19"
"@types/jest": "^29.4.0", }
"@types/node": "^18.11.19",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"base64url": "^3.0.1",
"ethers": "^5.7.2",
"js-base64": "^3.7.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"prettier": "^1.18.2",
"react-app-rewired": "^2.2.1",
"tslint": "^5.19.0",
"tslint-config-prettier": "^1.18.0",
"typescript": "3.6.2"
},
"scripts": {
"start": "react-app-rewired start",
"build": "yarn fetchContracts && react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject",
"fetchContracts": "node ./tools/getDeployedContracts.mjs"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
} }

6657
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,44 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<script src='https://unpkg.com/cbor-web'></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,38 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -1,8 +0,0 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -1,968 +0,0 @@
import * as LitJsSdk_accessControlConditions from "@lit-protocol/access-control-conditions";
import * as LitJsSdk_blsSdk from "@lit-protocol/bls-sdk";
import * as LitJsSdk_authHelpers from "@lit-protocol/auth-helpers";
import * as LitJsSdk_types from "@lit-protocol/types";
import * as LitJsSdk from "@lit-protocol/lit-node-client";
import { AccsDefaultParams, AuthSig, AuthCallback } from "@lit-protocol/types";
import { Button, ButtonGroup, TextField } from "@mui/material";
import { GoogleLogin } from "@react-oauth/google";
import {
startAuthentication,
startRegistration,
} from "@simplewebauthn/browser";
import base64url from "base64url";
import { ethers, utils } from "ethers";
import { computeAddress } from "ethers/lib/utils";
import { useState } from "react";
import "./App.css";
import { getDomainFromOrigin } from "./utils/string";
type CredentialResponse = any;
declare global {
interface Window {
cbor: any;
}
}
const RELAY_API_URL =
process.env.REACT_APP_RELAY_API_URL || "http://localhost:3001";
function App() {
const [registeredPkpEthAddress, setRegisteredPkpEthAddress] = useState<
string
>("");
const [
googleCredentialResponse,
setGoogleCredentialResponse,
] = useState<CredentialResponse | null>(null);
const [registeredPkpPublicKey, setRegisteredPkpPublicKey] = useState<
string
>("");
const [
authenticatedPkpEthAddress,
setAuthenticatedPkpEthAddress,
] = useState<string>("");
const [authenticatedPkpPublicKey, setAuthenticatedPkpPublicKey] = useState<
string
>("");
const [status, setStatus] = useState("");
const [selectedAuthMethod, setSelectedAuthMethod] = useState(6);
const [webAuthnUsername, setWebAuthnUsername] = useState<string>("");
const [authSig, setAuthSig] = useState<AuthSig | null>(null);
const [executeJsSignature, setExecuteJsSignature] = useState<string | null>(
null
);
const [encryptedSymmetricKey, setEncryptedSymmetricKey] = useState<
Uint8Array
>(new Uint8Array());
const [encryptedString, setEncryptedString] = useState<Blob | null>(null);
console.log("STATE", {
authenticatedPkpPublicKey,
authenticatedPkpEthAddress,
});
const handleLoggedInToGoogle = async (
credentialResponse: CredentialResponse
) => {
setStatus("Logged in to Google");
console.log("Got response from google sign in: ", {
credentialResponse,
});
setGoogleCredentialResponse(credentialResponse);
};
return (
<div className="App">
<div style={{ height: 80 }} />
<h1>Welcome To The PKP Demo!</h1>
<div style={{ height: 24 }} />
<h3>Choose an authentication method to begin:</h3>
<ButtonGroup variant="outlined">
<Button
variant={
selectedAuthMethod === 6 ? "contained" : "outlined"
}
onClick={() => setSelectedAuthMethod(6)}
>
Google
</Button>
<Button
variant={
selectedAuthMethod === 3 ? "contained" : "outlined"
}
onClick={() => setSelectedAuthMethod(3)}
>
WebAuthn
</Button>
</ButtonGroup>
<div style={{ height: 24 }} />
<h1>{status}</h1>
<div style={{ height: 24 }} />
{selectedAuthMethod === 6 && (
<>
<h3>Step 1: Log in with Google.</h3>
<GoogleLogin
onSuccess={handleLoggedInToGoogle}
onError={() => {
console.log("Login Failed");
}}
useOneTap
/>
{googleCredentialResponse && (
<div>
<b>Google Credential Response: </b>
{JSON.stringify(googleCredentialResponse)}
</div>
)}
<h3>Step 2: Use Google Credential to Mint PKP.</h3>
<button
onClick={() =>
handleMintPkpUsingGoogleAuth(
googleCredentialResponse,
setStatus,
({ pkpEthAddress, pkpPublicKey }) => {
setRegisteredPkpEthAddress(pkpEthAddress);
setRegisteredPkpPublicKey(pkpPublicKey);
}
)
}
>
Mint PKP
</button>
{registeredPkpEthAddress && (
<div>
Registered PKP Eth Address:{" "}
{registeredPkpEthAddress}
</div>
)}
<h3>
Step 3: Generate auth sigs from Lit Nodes, then generate
session sigs for storing an encryption condition.
</h3>
<Button
variant="contained"
onClick={async () => {
const {
encryptedString,
encryptedSymmetricKey,
} = await handleStoreEncryptionConditionNodes(
setStatus,
googleCredentialResponse,
registeredPkpPublicKey
);
setEncryptedString(encryptedString);
setEncryptedSymmetricKey(encryptedSymmetricKey);
setAuthenticatedPkpPublicKey(
registeredPkpPublicKey
);
setAuthenticatedPkpEthAddress(
publicKeyToAddress(registeredPkpPublicKey)
);
}}
>
Authenticate + Encrypt with Lit
</Button>
{authenticatedPkpEthAddress && (
<div>
Authenticated PKP Eth Address:{" "}
{authenticatedPkpEthAddress}
</div>
)}
<h3>
Step 4: Retrieve the decrypted symmetric key from Lit
Nodes.
</h3>
<Button
variant="contained"
onClick={async () => {
await handleRetrieveSymmetricKeyNodes(
setStatus,
encryptedSymmetricKey,
encryptedString!,
googleCredentialResponse,
authenticatedPkpEthAddress
);
}}
>
Decrypt
</Button>
</>
)}
{selectedAuthMethod === 3 && (
<>
<h3>Step 1: Register to mint PKP. (optional username)</h3>
<TextField
label="Username"
variant="outlined"
onChange={e => setWebAuthnUsername(e.target.value)}
/>
<Button
variant="contained"
onClick={async () => {
await handleWebAuthnRegister(
webAuthnUsername,
setStatus,
({ pkpEthAddress, pkpPublicKey }) => {
setRegisteredPkpEthAddress(pkpEthAddress);
setRegisteredPkpPublicKey(pkpPublicKey);
}
);
}}
>
Register
</Button>
{registeredPkpEthAddress && (
<div>
<b>Registered PKP Eth Address: </b>
{registeredPkpEthAddress}
</div>
)}
<h3>
Step 2: Authenticate against Lit Nodes to generate auth
sigs.
</h3>
<Button
variant="contained"
onClick={async () => {
const {
authSig,
pkpPublicKey,
} = await handleWebAuthnAuthenticate(setStatus);
setAuthSig(authSig);
// After authenticating, we can store the pkpPublicKey for executing a
// Lit Action later.
setAuthenticatedPkpPublicKey(pkpPublicKey);
setAuthenticatedPkpEthAddress(
computeAddress(`0x${pkpPublicKey}`)
);
}}
>
Authenticate
</Button>
{authenticatedPkpPublicKey && authSig && (
<>
<div>
<b>Authenticated PKP Public Key: </b>
{authenticatedPkpPublicKey}
</div>
<div>
<b>Auth Sig: </b>
{JSON.stringify(authSig)}
</div>
</>
)}
<h3>
Step 3: Generate session signatures and use them to
execute a Lit Action.
</h3>
<Button
variant="contained"
onClick={async () => {
const signature = await handleExecuteJs(
setStatus,
authSig!,
authenticatedPkpPublicKey
);
setExecuteJsSignature(signature);
}}
>
Execute Lit Action
</Button>
{executeJsSignature && (
<div>
<b>Executed Lit Action Signature: </b>
{executeJsSignature}
</div>
)}
</>
)}
</div>
);
}
export default App;
const handleMintPkpUsingGoogleAuth = async (
credentialResponse: CredentialResponse,
setStatusFn: (status: string) => void,
onSuccess: ({
pkpEthAddress,
pkpPublicKey,
}: {
pkpEthAddress: string;
pkpPublicKey: string;
}) => void
) => {
setStatusFn("Minting PKP...");
const requestId = await mintPkpUsingRelayerGoogleAuthVerificationEndpoint(
credentialResponse,
setStatusFn
);
return pollRequestUntilTerminalState(requestId, setStatusFn, onSuccess);
};
async function getLitNodeClient(): Promise<LitJsSdk.LitNodeClient> {
const litNodeClient = new LitJsSdk.LitNodeClient({
litNetwork: "serrano",
});
await litNodeClient.connect();
return litNodeClient;
}
async function handleExecuteJs(
setStatusFn: (status: string) => void,
authSig: AuthSig,
pkpPublicKey: string
): Promise<string> {
setStatusFn("Executing JS...");
const litActionCode = `
const go = async () => {
// this requests a signature share from the Lit Node
// the signature share will be automatically returned in the response from the node
// and combined into a full signature by the LitJsSdk for you to use on the client
// all the params (toSign, publicKey, sigName) are passed in from the LitJsSdk.executeJs() function
const sigShare = await LitActions.signEcdsa({ toSign, publicKey, sigName });
};
go();
`;
const litNodeClient = await getLitNodeClient();
const results = await litNodeClient.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: `0x${pkpPublicKey}`,
sigName: "sig1",
},
});
console.log("results: ", results);
return results.signatures["sig1"].signature;
}
async function mintPkpUsingRelayerGoogleAuthVerificationEndpoint(
credentialResponse: any,
setStatusFn: (status: string) => void
) {
setStatusFn("Minting PKP with relayer...");
const mintRes = await fetch(`${RELAY_API_URL}/auth/google`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"api-key": "1234567890",
},
body: JSON.stringify({
idToken: credentialResponse.credential,
}),
});
if (mintRes.status < 200 || mintRes.status >= 400) {
console.warn("Something wrong with the API call", await mintRes.json());
setStatusFn("Uh oh, something's not quite right.");
return null;
} else {
const resBody = await mintRes.json();
console.log("Response OK", { body: resBody });
setStatusFn("Successfully initiated minting PKP with relayer.");
return resBody.requestId;
}
}
async function pollRequestUntilTerminalState(
requestId: string,
setStatusFn: (status: string) => void,
onSuccess: ({
pkpEthAddress,
pkpPublicKey,
}: {
pkpEthAddress: string;
pkpPublicKey: string;
}) => void
) {
if (!requestId) {
return;
}
const maxPollCount = 20;
for (let i = 0; i < maxPollCount; i++) {
setStatusFn(`Waiting for auth completion (poll #${i + 1})`);
const getAuthStatusRes = await fetch(
`${RELAY_API_URL}/auth/status/${requestId}`,
{
headers: {
"api-key": "1234567890",
},
}
);
if (getAuthStatusRes.status < 200 || getAuthStatusRes.status >= 400) {
console.warn(
"Something wrong with the API call",
await getAuthStatusRes.json()
);
setStatusFn("Uh oh, something's not quite right.");
return;
}
const resBody = await getAuthStatusRes.json();
console.log("Response OK", { body: resBody });
if (resBody.error) {
// exit loop since error
console.warn("Something wrong with the API call", {
error: resBody.error,
});
setStatusFn("Uh oh, something's not quite right.");
return;
} else if (resBody.status === "Succeeded") {
// exit loop since success
console.info("Successfully authed", { ...resBody });
setStatusFn("Successfully authed and minted PKP!");
onSuccess({
pkpEthAddress: resBody.pkpEthAddress,
pkpPublicKey: resBody.pkpPublicKey,
});
return;
}
// otherwise, sleep then continue polling
await new Promise(r => setTimeout(r, 15000));
}
// at this point, polling ended and still no success, set failure status
setStatusFn(`Hmm this is taking longer than expected...`);
}
async function handleStoreEncryptionConditionNodes(
setStatusFn: (status: string) => void,
googleCredentialResponse: any,
requestedPkpPublicKey: string
): Promise<{
encryptedSymmetricKey: Uint8Array;
encryptedString: Blob;
}> {
setStatusFn("Storing encryption condition with the network...");
// get the user a session with it
const litNodeClient = await getLitNodeClient();
const { encryptedString, symmetricKey } = await LitJsSdk.encryptString(
"this is a secret message"
);
// key parameter - encrypt symmetric key then hash it
const encryptedSymmetricKey = LitJsSdk_blsSdk.wasmBlsSdkHelpers.encrypt(
LitJsSdk.uint8arrayFromString(litNodeClient.subnetPubKey, "base16"),
symmetricKey
);
// get the session sigs
const { sessionSigs } = await getSessionSigs(
litNodeClient,
encryptedSymmetricKey,
litNodeClient.generateAuthMethodForGoogleJWT(
googleCredentialResponse.credential
),
requestedPkpPublicKey
);
const pkpEthAddress = publicKeyToAddress(requestedPkpPublicKey);
const unifiedAccessControlConditions = getUnifiedAccessControlConditions(
pkpEthAddress
);
console.log(
"unifiedAccessControlConditions: ",
unifiedAccessControlConditions
);
// store the decryption conditions
await litNodeClient.saveEncryptionKey({
unifiedAccessControlConditions,
symmetricKey,
encryptedSymmetricKey,
sessionSigs, // Not actually needed for storing encryption condition.
chain: "ethereum",
});
console.log("encryptedSymmetricKey: ", encryptedSymmetricKey);
return {
encryptedSymmetricKey,
encryptedString,
};
}
async function getSessionSigs(
litNodeClient: LitJsSdk.LitNodeClient,
encryptedSymmetricKey: Uint8Array,
authMethod: LitJsSdk_types.AuthMethod,
requestedPkpPublicKey: string
): Promise<{
sessionSigs: LitJsSdk_types.SessionSigsMap;
}> {
// this will be fired if auth is needed. we can use this to prompt the user to sign in
const authNeededCallback: AuthCallback = async ({
resources,
expiration,
statement,
}) => {
console.log("authNeededCallback fired");
// Generate authMethod.
const authMethods = [authMethod];
// Get AuthSig
const { authSig, pkpPublicKey } = await litNodeClient.signSessionKey({
pkpPublicKey: requestedPkpPublicKey,
authMethods,
statement,
expiration:
expiration ||
new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours
resources: resources || [],
});
console.log("got session sig from node and PKP: ", {
authSig,
pkpPublicKey,
});
return authSig;
};
const hashedEncryptedSymmetricKeyStr = await hashBytes({
bytes: new Uint8Array(encryptedSymmetricKey),
});
// Construct the LitResource
const litResource = new LitJsSdk_authHelpers.LitAccessControlConditionResource(
hashedEncryptedSymmetricKeyStr
);
// Get the session sigs
const sessionSigs = await litNodeClient.getSessionSigs({
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours
chain: "ethereum",
resourceAbilityRequests: [
{
resource: litResource,
ability:
LitJsSdk_authHelpers.LitAbility
.AccessControlConditionDecryption,
},
],
switchChain: false,
authNeededCallback,
});
console.log("sessionSigs: ", sessionSigs);
return {
sessionSigs
};
}
// TODO: use when system migrates to reading from chain for access control conditions
async function handleStoreEncryptionConditionRelay(
setStatusFn: (status: string) => void,
pkpEthAddress: string
) {
setStatusFn("Storing encryption condition...");
// get the user a session with it
const litNodeClient = await getLitNodeClient();
const { encryptedZip, symmetricKey } = await LitJsSdk.zipAndEncryptString(
"this is a secret message"
);
// get the ACCs
const unifiedAccessControlConditions = getUnifiedAccessControlConditions(
pkpEthAddress
);
// value parameter - hash unified conditions
const hashedAccessControlConditions = await LitJsSdk_accessControlConditions.hashUnifiedAccessControlConditions(
unifiedAccessControlConditions
);
console.log("hashedAccessControlConditions", {
hashedAccessControlConditions,
});
const hashedAccessControlConditionsStr = LitJsSdk.uint8arrayToString(
new Uint8Array(hashedAccessControlConditions),
"base16"
);
// key parameter - encrypt symmetric key then hash it
const encryptedSymmetricKey = LitJsSdk_blsSdk.wasmBlsSdkHelpers.encrypt(
LitJsSdk.uint8arrayFromString(litNodeClient.subnetPubKey, "base16"),
symmetricKey
);
const hashedEncryptedSymmetricKeyStr = await hashBytes({
bytes: new Uint8Array(encryptedSymmetricKey),
});
// securityHash parameter - encrypt symmetric key, concat with creator address
const pkpEthAddressBytes = utils.arrayify(pkpEthAddress);
const securityHashPreimage = new Uint8Array([
...encryptedSymmetricKey,
...pkpEthAddressBytes,
]);
const securityHashStr = await hashBytes({
bytes: securityHashPreimage,
});
console.log("Storing encryption condition with relay", {
hashedEncryptedSymmetricKeyStr,
hashedAccessControlConditionsStr,
securityHashStr,
});
// call centralized conditions relayer to write encryption conditions to chain.
const storeRes = await fetch(`${RELAY_API_URL}/store-condition`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"api-key": "1234567890",
},
body: JSON.stringify({
key: hashedEncryptedSymmetricKeyStr,
value: hashedAccessControlConditionsStr,
securityHash: securityHashStr,
chainId: "1",
permanent: false,
capabilityProtocolPrefix: "litEncryptionCondition",
}),
});
if (storeRes.status < 200 || storeRes.status >= 400) {
console.warn(
"Something wrong with the API call",
await storeRes.json()
);
setStatusFn("Uh oh, something's not quite right");
} else {
setStatusFn("Successfully stored encryption condition with relayer!");
}
}
async function handleRetrieveSymmetricKeyNodes(
setStatusFn: (status: string) => void,
encryptedSymmetricKey: Uint8Array,
encryptedString: Blob,
googleCredentialResponse: any,
pkpEthAddress: string
) {
setStatusFn("Retrieving symmetric key...");
const litNodeClient = await getLitNodeClient();
// get the session sigs
const { sessionSigs } = await getSessionSigs(
litNodeClient,
encryptedSymmetricKey,
litNodeClient.generateAuthMethodForGoogleJWT(
googleCredentialResponse.credential
),
);
// get the ACC
const unifiedAccessControlConditions = getUnifiedAccessControlConditions(
pkpEthAddress
);
console.log(
"unifiedAccessControlConditions: ",
unifiedAccessControlConditions
);
const retrievedSymmKey = await litNodeClient.getEncryptionKey({
unifiedAccessControlConditions,
toDecrypt: LitJsSdk.uint8arrayToString(encryptedSymmetricKey, "base16"),
sessionSigs,
});
const decryptedString = await LitJsSdk.decryptString(
encryptedString,
retrievedSymmKey
);
console.log("decrypted string", decryptedString);
}
function publicKeyToAddress(publicKey: string) {
return utils.computeAddress(`${publicKey}`);
}
async function hashBytes({ bytes }: { bytes: Uint8Array }): Promise<string> {
const hashOfBytes = await crypto.subtle.digest("SHA-256", bytes);
const hashOfBytesStr = LitJsSdk.uint8arrayToString(
new Uint8Array(hashOfBytes),
"base16"
);
return hashOfBytesStr;
}
// 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 = await getLitNodeClient();
// 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(
username: string,
setStatusFn: (status: string) => void,
onSuccess: ({
pkpEthAddress,
pkpPublicKey,
}: {
pkpEthAddress: string;
pkpPublicKey: string;
}) => void
) {
let url = `${RELAY_API_URL}/auth/webauthn/generate-registration-options`;
// Handle optional username
if (username !== "") {
url += `?username=${encodeURIComponent(username)}`;
}
const resp = await fetch(url, { headers: { "api-key": "1234567890" } });
let attResp;
try {
const opts = await resp.json();
// Require a resident key for this demo
opts.authenticatorSelection.residentKey = "required";
opts.authenticatorSelection.requireResidentKey = true;
opts.extensions = {
credProps: true,
};
attResp = await startRegistration(opts);
} catch (error) {
// TODO: Handle error
throw error;
}
console.log("attResp", { attResp });
// Verify and mint PKP.
setStatusFn("Verifying WebAuthn registration...");
const verificationAndMintResp = await fetch(
`${RELAY_API_URL}/auth/webauthn/verify-registration`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"api-key": "1234567890",
},
body: JSON.stringify({ credential: attResp }),
}
);
if (
verificationAndMintResp.status < 200 ||
verificationAndMintResp.status >= 400
) {
console.warn(
"Something went wrong with the API call",
await verificationAndMintResp.json()
);
setStatusFn("Uh oh, something's not quite right.");
return null;
}
const resBody = await verificationAndMintResp.json();
console.log("Response OK", { body: resBody });
setStatusFn(
"Successfully registered using WebAuthn! PKP minting initiated..."
);
// Poll until success
const mintRequestId = resBody.requestId;
await pollRequestUntilTerminalState(mintRequestId, setStatusFn, onSuccess);
}
const rpcUrl = process.env.REACT_APP_RPC_URL || "http://localhost:8545";
async function handleWebAuthnAuthenticate(
setStatusFn: (status: string) => void
): Promise<{
authSig: AuthSig;
pkpPublicKey: string;
}> {
// Fetch latest blockHash
setStatusFn("Fetching latest block hash...");
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const block = await provider.getBlock("latest");
const blockHash = block.hash;
// Turn into byte array.
const blockHashBytes = ethers.utils.arrayify(blockHash);
console.log(
"blockHash",
blockHash,
blockHashBytes,
base64url(Buffer.from(blockHashBytes))
);
// Construct authentication options.
const rpId = getDomainFromOrigin(window.location.origin);
console.log("Using rpId: ", { rpId });
const authenticationOptions = {
challenge: base64url(Buffer.from(blockHashBytes)),
timeout: 60000,
userVerification: "required",
rpId,
};
// Authenticate with WebAuthn.
setStatusFn("Authenticating with WebAuthn...");
const authenticationResponse = await startAuthentication(
authenticationOptions
);
// BUG: We need to make sure userHandle is base64url encoded.
// Deep copy the authentication response.
const actualAuthenticationResponse = JSON.parse(
JSON.stringify(authenticationResponse)
);
actualAuthenticationResponse.response.userHandle = base64url.encode(
authenticationResponse.response.userHandle
);
// Call all nodes POST /web/auth/webauthn to generate authSig.
setStatusFn("Verifying WebAuthn authentication against Lit Network...");
const litNodeClient = await getLitNodeClient();
// Generate authMethod.
const authMethod = litNodeClient.generateAuthMethodForWebAuthn(
actualAuthenticationResponse
);
// Get authSig.
const { authSig, pkpPublicKey } = await litNodeClient.signSessionKey({
authMethods: [authMethod],
expiration: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
resources: [],
});
return { authSig, pkpPublicKey };
}
function getUnifiedAccessControlConditions(
pkpEthAddress?: string
): AccsDefaultParams[] {
return [
{
conditionType: "evmBasic",
contractAddress: "",
standardContractType: "",
chain: "mumbai",
method: "",
parameters: [":userAddress"],
returnValueTest: {
comparator: "=",
value:
pkpEthAddress ||
"0x3c3CA2BFFfffE532aed2923A34D6c1F9307F8076",
},
},
];
}

View File

@ -1,277 +0,0 @@
{
"address": "0xffD53EeAD24a54CA7189596eF1aa3f1369753611",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_pkpNft",
"type": "address"
},
{
"internalType": "address",
"name": "_pkpPermissions",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
},
{
"internalType": "uint256[]",
"name": "permittedAuthMethodTypes",
"type": "uint256[]"
},
{
"internalType": "bytes[]",
"name": "permittedAuthMethodIds",
"type": "bytes[]"
},
{
"internalType": "bytes[]",
"name": "permittedAuthMethodPubkeys",
"type": "bytes[]"
},
{
"internalType": "uint256[][]",
"name": "permittedAuthMethodScopes",
"type": "uint256[][]"
},
{
"internalType": "bool",
"name": "addPkpEthAddressAsPermittedAddress",
"type": "bool"
},
{
"internalType": "bool",
"name": "sendPkpToItself",
"type": "bool"
}
],
"name": "mintNextAndAddAuthMethods",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
},
{
"internalType": "bytes[]",
"name": "permittedIpfsCIDs",
"type": "bytes[]"
},
{
"internalType": "uint256[][]",
"name": "permittedIpfsCIDScopes",
"type": "uint256[][]"
},
{
"internalType": "address[]",
"name": "permittedAddresses",
"type": "address[]"
},
{
"internalType": "uint256[][]",
"name": "permittedAddressScopes",
"type": "uint256[][]"
},
{
"internalType": "uint256[]",
"name": "permittedAuthMethodTypes",
"type": "uint256[]"
},
{
"internalType": "bytes[]",
"name": "permittedAuthMethodIds",
"type": "bytes[]"
},
{
"internalType": "bytes[]",
"name": "permittedAuthMethodPubkeys",
"type": "bytes[]"
},
{
"internalType": "uint256[][]",
"name": "permittedAuthMethodScopes",
"type": "uint256[][]"
},
{
"internalType": "bool",
"name": "addPkpEthAddressAsPermittedAddress",
"type": "bool"
},
{
"internalType": "bool",
"name": "sendPkpToItself",
"type": "bool"
}
],
"name": "mintNextAndAddAuthMethodsWithTypes",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "onERC721Received",
"outputs": [
{
"internalType": "bytes4",
"name": "",
"type": "bytes4"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pkpNFT",
"outputs": [
{
"internalType": "contract PKPNFT",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pkpPermissions",
"outputs": [
{
"internalType": "contract PKPPermissions",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newPkpNftAddress",
"type": "address"
}
],
"name": "setPkpNftAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newPkpPermissionsAddress",
"type": "address"
}
],
"name": "setPkpPermissionsAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}

View File

@ -1,967 +0,0 @@
{
"address": "0x86062B7a01B8b2e22619dBE0C15cbe3F7EBd0E92",
"abi": [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "contractBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "exists",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "freeMintId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "ipfsCID",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "msgHash",
"type": "bytes32"
},
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "freeMintGrantAndBurnNext",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "freeMintId",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "msgHash",
"type": "bytes32"
},
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "freeMintNext",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "freeMintId",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "msgHash",
"type": "bytes32"
},
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "freeMintSigTest",
"outputs": [],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "freeMintSigner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getEthAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPubkey",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "getUnmintedRoutedTokenIdCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "mintCost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "ipfsCID",
"type": "bytes"
}
],
"name": "mintGrantAndBurnNext",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "ipfsCID",
"type": "bytes"
}
],
"name": "mintGrantAndBurnSpecific",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "mintNext",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "mintSpecific",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pkpNftMetadata",
"outputs": [
{
"internalType": "contract PKPNFTMetadata",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pkpPermissions",
"outputs": [
{
"internalType": "contract PKPPermissions",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "pkpRouted",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "hash",
"type": "bytes32"
}
],
"name": "prefixed",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "redeemedFreeMintIds",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "router",
"outputs": [
{
"internalType": "contract PubkeyRouter",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newFreeMintSigner",
"type": "address"
}
],
"name": "setFreeMintSigner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newMintCost",
"type": "uint256"
}
],
"name": "setMintCost",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pkpNftMetadataAddress",
"type": "address"
}
],
"name": "setPkpNftMetadataAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pkpPermissionsAddress",
"type": "address"
}
],
"name": "setPkpPermissionsAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "routerAddress",
"type": "address"
}
],
"name": "setRouterAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "tokenByIndex",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "tokenOfOwnerByIndex",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "unmintedRoutedTokenIds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}

View File

@ -1,795 +0,0 @@
{
"address": "0x274d0C69fCfC40f71E57f81E8eA5Bd786a96B832",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_pkpNft",
"type": "address"
},
{
"internalType": "address",
"name": "_router",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"indexed": false,
"internalType": "bytes",
"name": "userPubkey",
"type": "bytes"
}
],
"name": "PermittedAuthMethodAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bytes",
"name": "id",
"type": "bytes"
}
],
"name": "PermittedAuthMethodRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"indexed": false,
"internalType": "uint256",
"name": "scopeId",
"type": "uint256"
}
],
"name": "PermittedAuthMethodScopeAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"indexed": false,
"internalType": "uint256",
"name": "scopeId",
"type": "uint256"
}
],
"name": "PermittedAuthMethodScopeRemoved",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "ipfsCID",
"type": "bytes"
},
{
"internalType": "uint256[]",
"name": "scopes",
"type": "uint256[]"
}
],
"name": "addPermittedAction",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "uint256[]",
"name": "scopes",
"type": "uint256[]"
}
],
"name": "addPermittedAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "userPubkey",
"type": "bytes"
},
{
"internalType": "uint256[]",
"name": "scopes",
"type": "uint256[]"
}
],
"name": "addPermittedAuthMethod",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "scopeId",
"type": "uint256"
}
],
"name": "addPermittedAuthMethodScope",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "authMethods",
"outputs": [
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "userPubkey",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
}
],
"name": "getAuthMethodId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getEthAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPermittedActions",
"outputs": [
{
"internalType": "bytes[]",
"name": "",
"type": "bytes[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPermittedAddresses",
"outputs": [
{
"internalType": "address[]",
"name": "",
"type": "address[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "maxScopeId",
"type": "uint256"
}
],
"name": "getPermittedAuthMethodScopes",
"outputs": [
{
"internalType": "bool[]",
"name": "",
"type": "bool[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPermittedAuthMethods",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "userPubkey",
"type": "bytes"
}
],
"internalType": "struct PKPPermissions.AuthMethod[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPubkey",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
}
],
"name": "getTokenIdsForAuthMethod",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
}
],
"name": "getUserPubkeyForAuthMethod",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "ipfsCID",
"type": "bytes"
}
],
"name": "isPermittedAction",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "user",
"type": "address"
}
],
"name": "isPermittedAddress",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
}
],
"name": "isPermittedAuthMethod",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "scopeId",
"type": "uint256"
}
],
"name": "isPermittedAuthMethodScopePresent",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pkpNFT",
"outputs": [
{
"internalType": "contract PKPNFT",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "ipfsCID",
"type": "bytes"
}
],
"name": "removePermittedAction",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "user",
"type": "address"
}
],
"name": "removePermittedAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
}
],
"name": "removePermittedAuthMethod",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "authMethodType",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "id",
"type": "bytes"
},
{
"internalType": "uint256",
"name": "scopeId",
"type": "uint256"
}
],
"name": "removePermittedAuthMethodScope",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "router",
"outputs": [
{
"internalType": "contract PubkeyRouter",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newPkpNftAddress",
"type": "address"
}
],
"name": "setPkpNftAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newRouterAddress",
"type": "address"
}
],
"name": "setRouterAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}

View File

@ -1,405 +0,0 @@
{
"address": "0xEA287AF8d8835eb20175875e89576bf583539B37",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_pkpNft",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"indexed": false,
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "PubkeyRoutingDataSet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "nodeAddress",
"type": "address"
},
{
"indexed": false,
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"indexed": false,
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "PubkeyRoutingDataVote",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "ethAddressToPkpId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getEthAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getPubkey",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getRoutingData",
"outputs": [
{
"components": [
{
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"internalType": "struct PubkeyRouter.PubkeyRoutingData",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "isRouted",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pkpNFT",
"outputs": [
{
"internalType": "contract PKPNFT",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "pubkeyRegistrations",
"outputs": [
{
"components": [
{
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"internalType": "struct PubkeyRouter.PubkeyRoutingData",
"name": "routingData",
"type": "tuple"
},
{
"internalType": "uint256",
"name": "nodeVoteCount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "nodeVoteThreshold",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "pubkeys",
"outputs": [
{
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newPkpNftAddress",
"type": "address"
}
],
"name": "setPkpNftAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "setRoutingData",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "pubkey",
"type": "bytes"
},
{
"internalType": "address",
"name": "stakingContract",
"type": "address"
},
{
"internalType": "uint256",
"name": "keyType",
"type": "uint256"
}
],
"name": "voteForRoutingData",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}

View File

@ -1,842 +0,0 @@
{
"address": "0xE094c76Ec6bad7CbA6181C8b34Bc41faC7EbdF43",
"abi": [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [],
"name": "RLIHolderRateLimitWindowMilliseconds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "additionalRequestsPerMillisecondCost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "requestsPerMillisecond",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "expiresAt",
"type": "uint256"
}
],
"name": "calculateCost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "payingAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "expiresAt",
"type": "uint256"
}
],
"name": "calculateRequestsPerSecond",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "capacity",
"outputs": [
{
"internalType": "uint256",
"name": "requestsPerMillisecond",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "expiresAt",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "contractBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "defaultRateLimitWindowMilliseconds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "expiresAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requestsPerMillisecond",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "msgHash",
"type": "bytes32"
},
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "freeMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "expiresAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requestsPerMillisecond",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "msgHash",
"type": "bytes32"
},
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "freeMintSigTest",
"outputs": [],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "freeMintSigner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "freeRequestsPerRateLimitWindow",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "isExpired",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "expiresAt",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "hash",
"type": "bytes32"
}
],
"name": "prefixed",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "redeemedFreeMints",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newAdditionalRequestsPerMillisecondCost",
"type": "uint256"
}
],
"name": "setAdditionalRequestsPerSecondCost",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newFreeMintSigner",
"type": "address"
}
],
"name": "setFreeMintSigner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newFreeRequestsPerRateLimitWindow",
"type": "uint256"
}
],
"name": "setFreeRequestsPerRateLimitWindow",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newRLIHolderRateLimitWindowMilliseconds",
"type": "uint256"
}
],
"name": "setRLIHolderRateLimitWindowMilliseconds",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newRateLimitWindowMilliseconds",
"type": "uint256"
}
],
"name": "setRateLimitWindowMilliseconds",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "tokenByIndex",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tokenIdCounter",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "tokenOfOwnerByIndex",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}

View File

@ -1,18 +0,0 @@
{
"stakingContractAddress": "0x091e9b0a5A404A394377d08C0Fd8C3418075e1fe",
"multisenderContractAddress": "0x1D907ec0CE55E7E3164Da56e50D64DC2d8933142",
"litTokenContractAddress": "0x541C8a3D27643002fb8A37dCf42D22940B5b2F51",
"accessControlConditionsContractAddress": "0x6620A0e03Ca33a3818f1539DF94f9807b12B9Ec2",
"pubkeyRouterContractAddress": "0xEA287AF8d8835eb20175875e89576bf583539B37",
"pkpNftContractAddress": "0x86062B7a01B8b2e22619dBE0C15cbe3F7EBd0E92",
"rateLimitNftContractAddress": "0xE094c76Ec6bad7CbA6181C8b34Bc41faC7EbdF43",
"pkpHelperContractAddress": "0xffD53EeAD24a54CA7189596eF1aa3f1369753611",
"pkpPermissionsContractAddress": "0x274d0C69fCfC40f71E57f81E8eA5Bd786a96B832",
"pkpNftMetadataContractAddress": "0x46c568B561Cde9ded66Be7d8044C141481c74d0f",
"chainId": 80001,
"rpcUrl": "https://polygon-mumbai.g.alchemy.com/v2/onvoLvV97DDoLkAmdi0Cj7sxvfglKqDh",
"chainName": "mumbai",
"litNodeDomainName": "127.0.0.1",
"litNodePort": 7470,
"rocketPort": 7470
}

BIN
src/app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

140
src/app/globals.css Normal file
View File

@ -0,0 +1,140 @@
:root {
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
--primary-glow: conic-gradient(
from 180deg at 50% 50%,
#16abff33 0deg,
#0885ff33 55deg,
#54d6ff33 120deg,
#0071ff33 160deg,
transparent 360deg
);
--secondary-glow: radial-gradient(
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
);
--tile-start-rgb: 239, 245, 249;
--tile-end-rgb: 228, 232, 233;
--tile-border: conic-gradient(
#00000080,
#00000040,
#00000030,
#00000020,
#00000010,
#00000010,
#00000080
);
--callout-rgb: 238, 240, 241;
--callout-border-rgb: 172, 175, 176;
--card-rgb: 180, 185, 188;
--card-border-rgb: 131, 134, 135;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
--secondary-glow: linear-gradient(
to bottom right,
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0.3)
);
--tile-start-rgb: 2, 13, 46;
--tile-end-rgb: 2, 5, 19;
--tile-border: conic-gradient(
#ffffff80,
#ffffff40,
#ffffff30,
#ffffff20,
#ffffff10,
#ffffff10,
#ffffff80
);
--callout-rgb: 20, 20, 20;
--callout-border-rgb: 108, 108, 108;
--card-rgb: 100, 100, 100;
--card-border-rgb: 200, 200, 200;
}
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
a {
color: inherit;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
.main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 6rem;
min-height: 100vh;
}
.alert {
background-color: rgb(var(--callout-rgb));
border: 1px solid rgb(var(--callout-border-rgb));
border-radius: 0.5rem;
padding: 1rem 0.875rem;
margin: 1rem 0;
max-width: 32rem;
font-size: 0.875rem;
}
.alert__btn {
margin-top: 1rem;
padding: 0.375rem 0.5rem;
cursor: pointer;
}
.alert--error {
border-color: red;
}
.alert--success {
border-color: green;
}

21
src/app/layout.js Normal file
View File

@ -0,0 +1,21 @@
import './globals.css'
import { Inter } from 'next/font/google'
import { Providers } from './provider'
import '@rainbow-me/rainbowkit/styles.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<Providers>{children}</Providers>
</body>
</html>
)
}

113
src/app/page.js Normal file
View File

@ -0,0 +1,113 @@
'use client'
import { ConnectButton } from '@rainbow-me/rainbowkit'
import { useAccount, useNetwork, useSigner } from 'wagmi'
import { ethConnect, disconnectWeb3 } from '@lit-protocol/lit-node-client'
import { LOCAL_STORAGE_KEYS } from '@lit-protocol/constants'
import { useEffect, useState } from 'react'
import { PKPEthersWallet } from "@lit-protocol/pkp-ethers";
export default function Home() {
const [authSig, setAuthSig] = useState(null)
const [error, setError] = useState(null)
const { address, isConnected, isDisconnected } = useAccount()
const { data: signer } = useSigner()
const { chain } = useNetwork()
async function generateAuthSig(signer, address, chainId) {
setAuthSig(null);
setError(null);
try {
const newAuthSig = await ethConnect.signAndSaveAuthMessage({
web3: signer.provider,
account: address.toLowerCase(),
chainId: chainId,
});
setAuthSig(newAuthSig);
} catch (err) {
console.error(err);
setError(`Failed to sign auth message: ${err.message}`);
}
}
async function sendTX(){
const pkpWallet = new PKPEthersWallet({
controllerAuthSig: authSig,
pkpPubKey: "046da3ba67065fd1e2726242ca01cd4601524893f4aa4b0042578fa6cbec28fa8c9a28eb9f7893932fc09717edc9e1db57e157a21eed346247c1db5a722a01f571",
rpc: "https://rpc.gnosischain.com/",
});
await pkpWallet.init();
console.log(pkpWallet);
const from = "0x06B6BE47c86cfcDF3f77c0e17e7aD8af750782aE";
const to = "0x1A5cfC9EA11afb50011F847fb7dC07bA1e18b05A";
const value = BigInt(5000000000000000);
// @lit-protocol/pkp-ethers will automatically add missing fields (nonce, chainId, gasPrice, gasLimit)
const transactionRequest = {
from,
to,
value,
};
const signedTransactionRequest = await pkpWallet.signTransaction(
transactionRequest
);
await pkpWallet.sendTransaction(signedTransactionRequest);
}
// Fetch auth sig from local storage
useEffect(() => {
if (!authSig) {
const storedAuthSig = localStorage.getItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
if (storedAuthSig) {
const parsedAuthSig = JSON.parse(storedAuthSig);
setAuthSig(parsedAuthSig);
}
}
}, [authSig])
// Generate auth sig if not already generated and if wallet is connected
useEffect(() => {
if (!authSig && isConnected && signer) {
generateAuthSig(signer, address, chain.id);
}
}, [authSig, isConnected, signer, address, chain])
// Clear auth sig if wallet is disconnected
useEffect(() => {
if (isDisconnected) {
disconnectWeb3();
setAuthSig(null);
}
}, [isDisconnected])
return (
<main className="main">
{error &&
<div className='alert alert--error'>
<p> {error}</p>
<button className='alert__btn' onClick={() => generateAuthSig(signer, address, chain.id)}>
Try again
</button>
</div>
}
{authSig &&
<p className='alert alert--success'>🔐 Auth sig has been generated and stored in local storage under {' '}
<code>{LOCAL_STORAGE_KEYS.AUTH_SIGNATURE}</code>
!
</p>
}
<ConnectButton />
<button class="btn btn--primary" onClick={() => sendTX()}>
send
</button>
</main>
)
}

61
src/app/provider.js Normal file
View File

@ -0,0 +1,61 @@
'use client';
import * as React from 'react';
import {
RainbowKitProvider,
getDefaultWallets,
connectorsForWallets,
darkTheme,
} from '@rainbow-me/rainbowkit';
import { configureChains, createClient, WagmiConfig } from 'wagmi';
import {
mainnet,
polygon,
goerli,
polygonMumbai,
} from 'wagmi/chains';
import { publicProvider } from 'wagmi/providers/public';
const { chains, provider, webSocketProvider } = configureChains(
[
mainnet,
polygon,
...(process.env.NEXT_PUBLIC_ENABLE_TESTNETS === 'true' ? [goerli, polygonMumbai] : []),
],
[publicProvider()]
);
const projectId = process.env.NEXT_PUBLIC_WC_PROJECT_ID;
const { wallets } = getDefaultWallets({
appName: 'My RainbowKit App',
projectId,
chains,
});
const connectors = connectorsForWallets([
...wallets,
]);
const client = createClient({
autoConnect: true,
connectors,
provider,
webSocketProvider,
});
const demoAppInfo = {
appName: 'Rainbowkit Demo',
};
export function Providers({ children }) {
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
return (
<WagmiConfig client={client}>
<RainbowKitProvider chains={chains} appInfo={demoAppInfo} theme={darkTheme()}>
{mounted && children}
</RainbowKitProvider>
</WagmiConfig>
);
}

View File

@ -1,13 +0,0 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View File

@ -1,22 +0,0 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { GoogleOAuthProvider } from "@react-oauth/google";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
<GoogleOAuthProvider clientId="1071348522014-3qq1ln33ful535dnd8r4f6f9vtjrv2nu.apps.googleusercontent.com">
<App />
</GoogleOAuthProvider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

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

View File

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

View File

@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

View File

@ -1,33 +0,0 @@
// copy-🍝 from https://github.com/MasterKale/SimpleWebAuthn/blob/33528afe001d4aca62052dce204c0398c3127ffd/packages/server/src/helpers/decodeCbor.ts
export function decodeCborFirst(
cbor: any,
input:
| string
| Buffer
| ArrayBuffer
| Uint8Array
| Uint8ClampedArray
| DataView
): any {
try {
// throws if there are extra bytes
return cbor.decodeFirstSync(input);
} catch (err) {
const _err = err as CborDecoderError;
// if the error was due to extra bytes, return the unpacked value
if (_err.value) {
return _err.value;
}
throw err;
}
}
/**
* Intuited from a quick scan of `cbor.decodeFirstSync()` here:
*
* https://github.com/hildjj/node-cbor/blob/v5.1.0/lib/decoder.js#L189
*/
class CborDecoderError extends Error {
value: any;
}

View File

@ -1,39 +0,0 @@
// copy-🍝 from https://github.com/MasterKale/SimpleWebAuthn/blob/33528afe001d4aca62052dce204c0398c3127ffd/packages/server/src/helpers/decodeAttestationObject.ts#L8
/**
* Convert an AttestationObject buffer to a proper object
*
* @param base64AttestationObject Attestation Object buffer
*/
export function decodeAttestationObject(
cbor: any,
attestationObject: Buffer
): AttestationObject {
const toCBOR: AttestationObject = cbor.decodeAllSync(attestationObject)[0];
return toCBOR;
}
export type AttestationFormat =
| "fido-u2f"
| "packed"
| "android-safetynet"
| "android-key"
| "tpm"
| "apple"
| "none";
export type AttestationObject = {
fmt: AttestationFormat;
attStmt: AttestationStatement;
authData: Buffer;
};
export type AttestationStatement = {
sig?: Buffer;
x5c?: Buffer[];
response?: Buffer;
alg?: number;
ver?: string;
certInfo?: Buffer;
pubArea?: Buffer;
};

View File

@ -1,19 +0,0 @@
// copy-🍝 from https://github.com/MasterKale/SimpleWebAuthn/blob/33528afe001d4aca62052dce204c0398c3127ffd/packages/server/src/helpers/decodeAuthenticatorExtensions.ts
/**
* Convert authenticator extension data buffer to a proper object
*
* @param extensionData Authenticator Extension Data buffer
*/
export function decodeAuthenticatorExtensions(cbor, extensionData) {
let toCBOR;
try {
toCBOR = cbor.decodeAllSync(extensionData)[0];
} catch (err) {
const _err = err;
throw new Error(
`Error decoding authenticator extensions: ${_err.message}`
);
}
return toCBOR;
}

View File

@ -1,112 +0,0 @@
import { decodeCborFirst } from "./cbor";
import { decodeAuthenticatorExtensions } from "./decodeAuthenticatorExtensions";
/**
* Make sense of the authData buffer contained in an Attestation
*/
export function parseAuthenticatorData(
cbor: any,
authData: Buffer
): ParsedAuthenticatorData {
if (authData.byteLength < 37) {
throw new Error(
`Authenticator data was ${authData.byteLength} bytes, expected at least 37 bytes`
);
}
let pointer = 0;
const rpIdHash = authData.slice(pointer, (pointer += 32));
const flagsBuf = authData.slice(pointer, (pointer += 1));
const flagsInt = flagsBuf[0];
// Bit positions can be referenced here:
// https://www.w3.org/TR/webauthn-2/#flags
const flags = {
up: !!(flagsInt & (1 << 0)), // User Presence
uv: !!(flagsInt & (1 << 2)), // User Verified
be: !!(flagsInt & (1 << 3)), // Backup Eligibility
bs: !!(flagsInt & (1 << 4)), // Backup State
at: !!(flagsInt & (1 << 6)), // Attested Credential Data Present
ed: !!(flagsInt & (1 << 7)), // Extension Data Present
flagsInt,
};
const counterBuf = authData.slice(pointer, (pointer += 4));
const counter = counterBuf.readUInt32BE(0);
let aaguid: Buffer | undefined = undefined;
let credentialID: Buffer | undefined = undefined;
let credentialPublicKey: Buffer | undefined = undefined;
if (flags.at) {
aaguid = authData.slice(pointer, (pointer += 16));
const credIDLenBuf = authData.slice(pointer, (pointer += 2));
const credIDLen = credIDLenBuf.readUInt16BE(0);
credentialID = authData.slice(pointer, (pointer += credIDLen));
// Decode the next CBOR item in the buffer, then re-encode it back to a Buffer
const firstDecoded = decodeCborFirst(cbor, authData.slice(pointer));
const firstEncoded = Buffer.from(cbor.encode(firstDecoded));
credentialPublicKey = firstEncoded;
pointer += firstEncoded.byteLength;
}
let extensionsData: any | undefined = undefined;
let extensionsDataBuffer: Buffer | undefined = undefined;
if (flags.ed) {
const firstDecoded = decodeCborFirst(cbor, authData.slice(pointer));
const firstEncoded = Buffer.from(cbor.encode(firstDecoded));
extensionsDataBuffer = firstEncoded;
extensionsData = decodeAuthenticatorExtensions(
cbor,
extensionsDataBuffer
);
pointer += firstEncoded.byteLength;
}
// Pointer should be at the end of the authenticator data, otherwise too much data was sent
if (authData.byteLength > pointer) {
throw new Error(
"Leftover bytes detected while parsing authenticator data"
);
}
return {
rpIdHash,
flagsBuf,
flags,
counter,
counterBuf,
aaguid,
credentialID,
credentialPublicKey,
extensionsData,
extensionsDataBuffer,
};
}
export type ParsedAuthenticatorData = {
rpIdHash: Buffer;
flagsBuf: Buffer;
flags: {
up: boolean;
uv: boolean;
be: boolean;
bs: boolean;
at: boolean;
ed: boolean;
flagsInt: number;
};
counter: number;
counterBuf: Buffer;
aaguid?: Buffer;
credentialID?: Buffer;
credentialPublicKey?: Buffer;
extensionsData?: any;
extensionsDataBuffer?: Buffer;
};

View File

@ -1,6 +0,0 @@
export function getDomainFromOrigin(origin: string): string {
// remove protocol with regex
let newOrigin = origin.replace(/(^\w+:|^)\/\//, "");
// remove port with regex
return newOrigin.replace(/:\d+$/, "");
}

View File

@ -1,51 +0,0 @@
import { runInputOutputs } from "./util.mjs";
/** ==================== Main ==================== */
const INPUT_ROOT =
"https://raw.githubusercontent.com/LIT-Protocol/LitNodeContracts/main/";
const OUTPUT_FOLDER = "./src/abis/";
// -- explorer.litprotocol.com
const SERRANO = "deployed_contracts_serrano.json";
// -- mumbai.explorer.litprotocol.com
const COLLABLAND = "deployed_contracts_mumbai.json";
// -- CURRENT USING:
const CURRENT = SERRANO;
runInputOutputs({
IOs: [
{
input: `${INPUT_ROOT}${CURRENT}`,
output: `${OUTPUT_FOLDER}deployed-contracts.json`,
mappedKey: null,
},
{
input: `${INPUT_ROOT}deployments/mumbai_80001/PKPHelper.json`,
output: `${OUTPUT_FOLDER}PKPHelper.json`,
mappedKey: "pkpHelperContractAddress",
},
{
input: `${INPUT_ROOT}deployments/mumbai_80001/PKPNFT.json`,
output: `${OUTPUT_FOLDER}PKPNFT.json`,
mappedKey: "pkpNftContractAddress",
},
{
input: `${INPUT_ROOT}deployments/mumbai_80001/PKPPermissions.json`,
output: `${OUTPUT_FOLDER}PKPPermissions.json`,
mappedKey: "pkpPermissionsContractAddress",
},
{
input: `${INPUT_ROOT}deployments/mumbai_80001/PubkeyRouter.json`,
output: `${OUTPUT_FOLDER}PubKeyRouter.json`,
mappedKey: "pubkeyRouterContractAddress",
},
{
input: `${INPUT_ROOT}deployments/mumbai_80001/RateLimitNFT.json`,
output: `${OUTPUT_FOLDER}RateLimitNFT.json`,
mappedKey: "rateLimitNftContractAddress",
},
],
ignoreProperties: ["metadata", "bytecode", "deployedBytecode"],
});

View File

@ -1,47 +0,0 @@
import fs from "fs";
import fetch from "node-fetch";
/** ==================== Helper ==================== */
export const writeToFile = (data, filename) => {
fs.writeFile(filename, data, (err) => {
if (err) {
console.log(err);
} else {
console.log(`Wrote to ${filename}`);
}
});
};
export const asyncForEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
};
export const runInputOutputs = async ({ IOs, ignoreProperties }) => {
let deployedContracts = {};
await asyncForEach(IOs, async (item, i) => {
const { input, output, mappedKey } = item;
const data = await fetch(input).then((res) => res.text());
const json = JSON.parse(data);
if (i <= 0) {
deployedContracts = json;
}
await asyncForEach(Object.keys(json), async (key) => {
if (ignoreProperties.includes(key)) {
delete json[key];
}
});
if (mappedKey !== null) {
json.address = deployedContracts[mappedKey];
}
writeToFile(JSON.stringify(json, null, 2), output);
});
};

View File

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