Skip to content
Snippets Groups Projects
Unverified Commit b62af2e1 authored by Niklas P's avatar Niklas P Committed by GitHub
Browse files

Merge pull request #1 from Yuripetusko/main

Add polkadot api deps
parents 11c5cd26 6e41f854
No related branches found
No related tags found
No related merge requests found
......@@ -35,3 +35,4 @@ yarn-error.log*
next-env.d.ts
todo.md
.idea
# Add files here to ignore them from prettier formatting
/dist
/coverage
{
"trailingComma": "all",
"singleQuote": true,
"bracketSpacing": true,
"bracketSameLine": false,
"parser": "typescript",
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true
}
......@@ -58,7 +58,7 @@ export default function LoginButton() {
})
// take the user to the protected page if they are allowed
if(result?.url) {
if (result?.url) {
router.push("/protected");
}
......@@ -72,7 +72,7 @@ export default function LoginButton() {
}
const { data: session } = useSession()
return (
<>
{ accounts.length > 0 ?
......@@ -80,7 +80,7 @@ export default function LoginButton() {
<div className={ styles.cardWrap }>
<div className={ styles.dropDownWrap }>
{ ! session &&
<AccountSelect/>
<AccountSelect/>
}
</div>
{ session ?
......@@ -109,7 +109,7 @@ export default function LoginButton() {
</p>
</div>
</>
:
:
<div
role="button"
onClick={() => handleLogin()}
......@@ -119,7 +119,7 @@ export default function LoginButton() {
🔑 Let me in <span>-&gt;</span>
</h2>
<p className={inter.className}>
Click here to sign in with your selected account and check if
Click here to sign in with your selected account and check if
you can view the tokengated content. <br></br>
You need &gt; 1 KSM free balance.
</p>
......@@ -128,7 +128,7 @@ export default function LoginButton() {
</div>
{ isLoading ? <>Signing In ...</> : <span className={ styles.error }> { error } </span> }
</>
:
:
<div className={ styles.walletInfo }>
<p>Please <a className={ styles.colorA } href="https://polkadot.js.org/extension/">install a polkadot wallet browser extension</a> to test this dApp.</p>
<p>If you have already installed it allow this application to access it.</p>
......@@ -136,4 +136,4 @@ export default function LoginButton() {
}
</>
)
}
\ No newline at end of file
}
import '@polkadot/api-augment';
......@@ -9,6 +9,8 @@
"lint": "next lint"
},
"dependencies": {
"@polkadot/api": "^10.3.4",
"@polkadot/api-augment": "^10.3.4",
"@polkadot/extension-dapp": "^0.45.5",
"@polkadot/react-identicon": "^3.1.4",
"@talismn/connect-wallets": "^1.2.3",
......@@ -29,5 +31,8 @@
"tsparticles-engine": "^2.9.3",
"tsparticles-preset-confetti": "^2.9.3",
"typescript": "5.0.4"
},
"devDependencies": {
"prettier": "^2.8.7"
}
}
import NextAuth, { NextAuthOptions } from 'next-auth'
import CredentialsProvider from 'next-auth/providers/credentials'
import "@polkadot/api-augment"
import NextAuth, { NextAuthOptions } from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import { signatureVerify } from '@polkadot/util-crypto';
import { encodeAddress } from '@polkadot/keyring'
import { ApiPromise, WsProvider } from "@polkadot/api"
import { BN } from '@polkadot/util'
import { encodeAddress } from '@polkadot/keyring';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { BN } from '@polkadot/util';
declare module 'next-auth' {
interface Session {
address: string | undefined
ksmAddress: string
freeBalance: BN
address: string | undefined;
ksmAddress: string;
freeBalance: BN;
}
interface User {
id: string
ksmAddress: string
freeBalance: BN
id: string;
ksmAddress: string;
freeBalance: BN;
}
interface credentials {
address: string
message: string
signature: string
csrfToken: string,
address: string;
message: string;
signature: string;
csrfToken: string;
}
}
......@@ -38,76 +37,84 @@ export const authOptions: NextAuthOptions = {
placeholder: '0x0',
},
message: {
label: "Message",
type: "text",
placeholder: "0x0",
label: 'Message',
type: 'text',
placeholder: '0x0',
},
signature: {
label: "Signature",
type: "text",
placeholder: "0x0",
label: 'Signature',
type: 'text',
placeholder: '0x0',
},
csrfToken: {
label: "CSRF Token",
type: "text",
placeholder: "0x0",
label: 'CSRF Token',
type: 'text',
placeholder: '0x0',
},
name: {
label: "Name",
type: "text",
placeholder: "name",
}
label: 'Name',
type: 'text',
placeholder: 'name',
},
},
async authorize(credentials): Promise<any | null> {
if (credentials === undefined) { return null }
if (credentials === undefined) {
return null;
}
try {
const message = JSON.parse(credentials.message)
const message = JSON.parse(credentials.message);
//verify the message is from the same domain
console.log( message.uri, message.uri )
console.log( 'process.env.NEXTAUTH_URL', process.env.NEXTAUTH_URL )
if ( message.uri !== process.env.NEXTAUTH_URL ) {
return Promise.reject(new Error('🚫 You shall not pass!'))
console.log(message.uri, message.uri);
console.log('process.env.NEXTAUTH_URL', process.env.NEXTAUTH_URL);
if (message.uri !== process.env.NEXTAUTH_URL) {
return Promise.reject(new Error('🚫 You shall not pass!'));
}
// verify the message was not compromised
console.log( message.nonce, message.nonce )
console.log( 'credentials.csrfToken', credentials.csrfToken )
if (message.nonce !== credentials.csrfToken ) {
return Promise.reject(new Error('🚫 You shall not pass!'))
console.log(message.nonce, message.nonce);
console.log('credentials.csrfToken', credentials.csrfToken);
if (message.nonce !== credentials.csrfToken) {
return Promise.reject(new Error('🚫 You shall not pass!'));
}
// verify signature of the message
const { isValid } = signatureVerify(credentials.message, credentials.signature, credentials.address);
const { isValid } = signatureVerify(
credentials.message,
credentials.signature,
credentials.address,
);
if ( ! isValid ) {
return Promise.reject(new Error('🚫 Invalid Signature'))
if (!isValid) {
return Promise.reject(new Error('🚫 Invalid Signature'));
}
// verify the account has the defined token
const wsProvider = new WsProvider( process.env.RPC_ENDPOINT ?? 'wss://kusama-rpc.dwellir.com' )
const wsProvider = new WsProvider(
process.env.RPC_ENDPOINT ?? 'wss://kusama-rpc.dwellir.com',
);
const api = await ApiPromise.create({ provider: wsProvider });
if ( credentials?.address ) {
const ksmAddress = encodeAddress( credentials.address, 2 )
const accountInfo = await api.query.system.account( ksmAddress )
if ( accountInfo.data.free.gt(new BN(1_000_000_000_000)) ) {
if (credentials?.address) {
const ksmAddress = encodeAddress(credentials.address, 2);
const accountInfo = await api.query.system.account(ksmAddress);
if (accountInfo.data.free.gt(new BN(1_000_000_000_000))) {
// if the user has a free balance > 1 KSM, we let them in
return {
id: credentials.address,
name: credentials.name,
freeBalance: accountInfo.data.free,
ksmAddress,
}
};
} else {
return Promise.reject(new Error('🚫 The gate is closed for you'))
return Promise.reject(new Error('🚫 The gate is closed for you'));
}
}
return Promise.reject(new Error('🚫 API Error'))
return Promise.reject(new Error('🚫 API Error'));
} catch (e) {
return null
return null;
}
},
}),
......@@ -122,23 +129,23 @@ export const authOptions: NextAuthOptions = {
callbacks: {
async jwt({ token, user }) {
if (user) {
token.freeBalance = user.freeBalance
token.freeBalance = user.freeBalance;
}
return token
return token;
},
async session(sessionData) {
const { session, token } = sessionData
const { session, token } = sessionData;
session.address = token.sub
if ( session.address ) {
session.ksmAddress = encodeAddress( session.address, 2 )
session.address = token.sub;
if (session.address) {
session.ksmAddress = encodeAddress(session.address, 2);
}
// as we already queried it, we can add whatever token to the session,
// so pages can use it without an extra query
session.freeBalance = token.freeBalance as BN
return session
session.freeBalance = token.freeBalance as BN;
return session;
},
},
secret: process.env.NEXTAUTH_SECRET,
......@@ -148,7 +155,6 @@ export const authOptions: NextAuthOptions = {
error: '/',
newUser: '/',
},
}
};
export default NextAuth(authOptions)
export default NextAuth(authOptions);
yarn.lock 0 → 100644
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment