removed nextjs example implementation
This commit is contained in:
3
src/app.css
Normal file
3
src/app.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
12
src/app.d.ts
vendored
Normal file
12
src/app.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
16
src/app.html
Normal file
16
src/app.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<script>
|
||||
// Fix `global is not defined` error
|
||||
global = window
|
||||
</script>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
@ -1,140 +0,0 @@
|
||||
: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;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
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>
|
||||
)
|
||||
}
|
150
src/app/page.js
150
src/app/page.js
@ -1,150 +0,0 @@
|
||||
'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 {
|
||||
console.log("LOG " + (useSigner.data))
|
||||
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 sendTXethereum(){
|
||||
|
||||
const pkpWallet = new PKPEthersWallet({
|
||||
controllerAuthSig: authSig,
|
||||
pkpPubKey: "046da3ba67065fd1e2726242ca01cd4601524893f4aa4b0042578fa6cbec28fa8c9a28eb9f7893932fc09717edc9e1db57e157a21eed346247c1db5a722a01f571",
|
||||
rpc: "https://rpc.eth.gateway.fm",
|
||||
});
|
||||
await pkpWallet.init();
|
||||
console.log(pkpWallet);
|
||||
|
||||
const from = "0x06B6BE47c86cfcDF3f77c0e17e7aD8af750782aE";
|
||||
const to = "0x1A5cfC9EA11afb50011F847fb7dC07bA1e18b05A";
|
||||
const value = BigInt(1000000000000000);
|
||||
const chainId = 1;
|
||||
const gasLimit = 21000;
|
||||
|
||||
// @lit-protocol/pkp-ethers will automatically add missing fields (nonce, chainId, gasPrice, gasLimit)
|
||||
const transactionRequest = {
|
||||
from,
|
||||
to,
|
||||
value,
|
||||
chainId,
|
||||
gasLimit,
|
||||
};
|
||||
|
||||
const signedTransactionRequest = await pkpWallet.signTransaction(
|
||||
transactionRequest
|
||||
);
|
||||
|
||||
await pkpWallet.sendTransaction(signedTransactionRequest);
|
||||
}
|
||||
|
||||
async function sendTXgnosis(){
|
||||
|
||||
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(1000000000000000);
|
||||
|
||||
// @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 style={{marginTop: "2rem", padding: "1rem"}} onClick={() => sendTXgnosis()}>
|
||||
send 0.001 xdai
|
||||
</button>
|
||||
|
||||
<button style={{marginTop: "2rem", padding: "1rem"}} onClick={() => sendTXethereum()}>
|
||||
send 0.001 eth
|
||||
</button>
|
||||
</main>
|
||||
)
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
'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>
|
||||
);
|
||||
}
|
7
src/index.test.ts
Normal file
7
src/index.test.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('sum test', () => {
|
||||
it('adds 1 + 2 to equal 3', () => {
|
||||
expect(1 + 2).toBe(3);
|
||||
});
|
||||
});
|
56
src/lib/AuthSig.svelte
Normal file
56
src/lib/AuthSig.svelte
Normal file
@ -0,0 +1,56 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { checkAndSignAuthMessage } from '@lit-protocol/lit-node-client';
|
||||
import { LOCAL_STORAGE_KEYS } from '@lit-protocol/constants';
|
||||
|
||||
let authSig = null;
|
||||
let error = null;
|
||||
|
||||
async function generateAuthSig() {
|
||||
authSig = null;
|
||||
error = null;
|
||||
try {
|
||||
authSig = await checkAndSignAuthMessage({
|
||||
chain: 'xdai'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
error = `Failed to sign auth message: ${err.message}`;
|
||||
}
|
||||
}
|
||||
onMount(() => {
|
||||
const storedAuthSig = localStorage.getItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
|
||||
if (storedAuthSig) {
|
||||
authSig = JSON.parse(storedAuthSig);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- AuthSig Address Displayed -->
|
||||
{#if authSig}
|
||||
<div class="bg-gray-100 p-4 rounded-lg shadow-md mb-4 flex items-center">
|
||||
<p class="text-gray-700 font-medium">
|
||||
AuthSig Address: <span class="text-orange-500">{authSig.address}</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- Error Message -->
|
||||
{:else if error}
|
||||
<div class="bg-red-100 p-4 rounded-lg shadow-md mb-4 flex items-center">
|
||||
<p class="text-red-700 font-medium">{error}</p>
|
||||
</div>
|
||||
<!-- Login Button -->
|
||||
{:else}
|
||||
<div class="flex justify-center">
|
||||
<button
|
||||
class="bg-orange-500 hover:bg-orange-600 text-white font-bold py-2 px-4 rounded-lg shadow-lg flex items-center m-2"
|
||||
on:click={generateAuthSig}
|
||||
>
|
||||
<img
|
||||
src="https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Fox.svg"
|
||||
alt="MetaMask"
|
||||
class="w-6 h-6 mr-2"
|
||||
/>
|
||||
<span class="text-lg">Login</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
40
src/lib/LitStatus.svelte
Normal file
40
src/lib/LitStatus.svelte
Normal file
@ -0,0 +1,40 @@
|
||||
<!-- src/routes/LitStatus.svelte -->
|
||||
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import Lit from '../lib/lit';
|
||||
|
||||
let networkStatus = 'Disconnected';
|
||||
let isNetworkLoading = true;
|
||||
|
||||
// Connect to the LIT network on component mount
|
||||
onMount(() => {
|
||||
Lit.connect();
|
||||
|
||||
// Define the event handler
|
||||
const handleLitReady = () => {
|
||||
networkStatus = 'Connected';
|
||||
isNetworkLoading = false;
|
||||
};
|
||||
|
||||
// Listen for the lit-ready event
|
||||
document.addEventListener('lit-ready', handleLitReady, false);
|
||||
|
||||
// Cleanup the event listener on component destroy
|
||||
return () => {
|
||||
document.removeEventListener('lit-ready', handleLitReady);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="bg-gray-100 p-4 rounded-lg shadow-md mb-4">
|
||||
{#if isNetworkLoading}
|
||||
<p class="text-gray-700 font-medium">
|
||||
LIT Network Status: <span class="text-blue-500">Loading ...</span>
|
||||
</p>
|
||||
{:else}
|
||||
<p class="text-gray-700 font-medium">
|
||||
LIT Network Status: <span class="text-green-600">{networkStatus}</span>
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
67
src/lib/Send.svelte
Normal file
67
src/lib/Send.svelte
Normal file
@ -0,0 +1,67 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import { PKPEthersWallet } from '@lit-protocol/pkp-ethers';
|
||||
import { LOCAL_STORAGE_KEYS } from '@lit-protocol/constants';
|
||||
|
||||
let pkpWallet;
|
||||
let authSig = null;
|
||||
|
||||
// Load wallet on component mount
|
||||
onMount(async () => {
|
||||
const storedAuthSig = localStorage.getItem(LOCAL_STORAGE_KEYS.AUTH_SIGNATURE);
|
||||
|
||||
if (storedAuthSig) {
|
||||
authSig = JSON.parse(storedAuthSig);
|
||||
pkpWallet = new PKPEthersWallet({
|
||||
controllerAuthSig: authSig,
|
||||
pkpPubKey:
|
||||
'046da3ba67065fd1e2726242ca01cd4601524893f4aa4b0042578fa6cbec28fa8c9a28eb9f7893932fc09717edc9e1db57e157a21eed346247c1db5a722a01f571',
|
||||
rpc: 'https://rpc.gnosischain.com/'
|
||||
});
|
||||
await pkpWallet.init();
|
||||
console.log(pkpWallet);
|
||||
} else {
|
||||
alert('no authsig');
|
||||
}
|
||||
});
|
||||
|
||||
const sendTransaction = async () => {
|
||||
if (!authSig) {
|
||||
alert('no authsig');
|
||||
} else {
|
||||
console.log('transaction initiated');
|
||||
const from = pkpWallet.address;
|
||||
const to = '0x1A5cfC9EA11afb50011F847fb7dC07bA1e18b05A';
|
||||
const value = BigInt(10000000000000000);
|
||||
const gasLimit = 21000;
|
||||
|
||||
// @lit-protocol/pkp-ethers will automatically add missing fields (nonce, chainId, gasPrice, gasLimit)
|
||||
const transactionRequest = {
|
||||
from,
|
||||
to,
|
||||
value,
|
||||
gasLimit
|
||||
};
|
||||
console.log('transaction request created');
|
||||
|
||||
const signedTransactionRequest = await pkpWallet.signTransaction(transactionRequest);
|
||||
await pkpWallet.sendTransaction(signedTransactionRequest);
|
||||
console.log('transaction sent');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="p-4 bg-gray-200 flex justify-center items-center flex-col">
|
||||
{#if pkpWallet}
|
||||
<div class="mb-4 text-lg font-medium">
|
||||
PKP Wallet: <span class="text-blue-600">{pkpWallet.address}</span>
|
||||
</div>
|
||||
{/if}
|
||||
<button
|
||||
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full shadow-lg focus:outline-none focus:shadow-outline-blue active:bg-blue-800 transition duration-150 ease-in-out"
|
||||
on:click={sendTransaction}
|
||||
>
|
||||
send 0.01 xdai
|
||||
</button>
|
||||
</div>
|
15
src/lib/lit.js
Normal file
15
src/lib/lit.js
Normal file
@ -0,0 +1,15 @@
|
||||
// src/lib/lit.js
|
||||
|
||||
import * as Lit from "@lit-protocol/lit-node-client";
|
||||
|
||||
const client = new Lit.LitNodeClient();
|
||||
|
||||
class LitConnector {
|
||||
litNodeClient;
|
||||
async connect() {
|
||||
await client.connect();
|
||||
this.litNodeClient = client;
|
||||
}
|
||||
}
|
||||
|
||||
export default new LitConnector();
|
5
src/routes/+layout.svelte
Normal file
5
src/routes/+layout.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
import '../app.css';
|
||||
</script>
|
||||
|
||||
<slot />
|
9
src/routes/+page.svelte
Normal file
9
src/routes/+page.svelte
Normal file
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import LitStatus from '$lib/LitStatus.svelte';
|
||||
import AuthSign from '$lib/AuthSig.svelte';
|
||||
import Send from '$lib/Send.svelte';
|
||||
</script>
|
||||
|
||||
<LitStatus />
|
||||
<AuthSign />
|
||||
<Send />
|
Reference in New Issue
Block a user