Skip to content
Snippets Groups Projects
Unverified Commit cb0763e6 authored by ArmchairAncap's avatar ArmchairAncap
Browse files

Correct xx wallet balance lookup

parent 7530878c
No related branches found
No related tags found
No related merge requests found
# Polkadot Tokengated Tutorial with next-auth
This is a the demo repo for a tokengated website with polkadot js API and next.js. It allows you to connect your wallet and sign a message. Then the server will check the via the polkadot js api if the signing wallet passes an arbitrary token check.
A tutorial that explains how it works will be published soon on [polkadot.study](https://polkadot.study)
## Run the Project Locally
First copy the .env.local.example to .env.local
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
## More
- The project was funded by the Kusama Treasury in Referendum 102 (within polkadot.study proposal)
- This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
\ No newline at end of file
# Polkadot Tokengated Tutorial with next-auth
## README for xx Network
This is a the demo repo for a tokengated website with polkadot js API and next.js. It allows you to connect your wallet and sign a message. Then the server will check the via the polkadot js api if the signing wallet passes an arbitrary token check.
(See [KSM_README.md](./KSM_README.md) for upstream README document.)
A tutorial that explains how it works will be published soon on [polkadot.study](https://polkadot.study)
Thank you to [the original author](https://polkadot.study/tutorials/tokengated-polkadot-next-js/intro) and the guy who [forked it](https://github.com/yk909/polkadot-js-tokengated-website/) to apply some fixes (verify/compare if you plan to use in production, of course).
## Run the Project Locally
This sort of works now and I'm sharing in the hope someone will use it for xx Network or other Substrate projects/chains for which the upstream forks don't provide instructions.
First copy the .env.local.example to .env.local
## How to run
First, run the development server:
Install Polkadot{.js} extension, create xx Network wallet, fund it with some amount of xx coins (1.01, for example) and set it to work on `xx Network`.
```bash
Download this repo, create `.env.local` in root directory, and run:
```sh
cp .env.local.example .env.local
vim .env.local
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
My .env.local for non-production use:
```raw
NEXTAUTH_SECRET=123123123
NEXTAUTH_URL=http://localhost:3000
RPC_ENDPOINT=ws://192.168.1.30:63007
```
Go to http://localhost:3000 in the browser in which you installed Polkadot{.js} and connect the extension to http://localhost:3000 (see [xx_polkadot_extension.png](./xx_polkadot_extension.png)), generate an address and make it restricted for use on xx Network (I hoped this would ensure balance will be looked up correctly, but it was not).
With that, I can login (see [xx_screenshot.png](./xx_screenshot.png) and balance of xx coins is correctly shown. We could probably check tokens (issued on xx Network), but I haven't looked into that yet.
(Note that, if you go to https://wallet.xx.network, Polkadot{.js} can let you add the wallet from the browser extension and show it in xx Network Wallet. Neat!)
`npm run build` builds okay, but has warnings about multiple versions of some package, etc. I don't know JS well enough to fix this quickly.
## What modified and why
`.env.local` and `pages/api/auth/[...nextauth].js` line 92 there's a fall back to public RPC endpoint, but I modified that one to local as well.
In `components/login.tsx` I added some functions for debugging, and logging to console.
In `pages/protected-api.tsx` and `pages/protected.tsx` ("static" protected page), changed KSM to XX and changed the number of decimals to 9 from 12:
```sh
const ksmBalance = formatBalance( session.freeBalance, { decimals: 9, withSi: true, withUnit: 'XX' } )
```
All modified pages from yk909's fork (you can see in Commits):
```sh
modified: components/account-select.tsx
modified: components/login.tsx
modified: package-lock.json
modified: package.json
modified: pages/api/auth/[...nextauth].ts
modified: pages/protected-api.tsx
modified: pages/protected.tsx
```
## Known issues
Internally, the xx wallet address is shown in generic Polkadot format, which is fine - the same private key could be used with a number of Substrate chain addresses.
```raw
token {
name: '123123123',
sub: '5GxeeFALkRvjnNgkiMjiP6q2GGnZ1ZmFyjCusHG4VoezqZSN',
freeBalance: '0x000000000000000000000000b14a8cbc',
iat: 1729956938,
exp: 1732548938,
jti: '3252212b-0fb2-4a82-88d0-3ceaf5886aa1'
}
```
## More
The FAQs say [it's normal to see another address](https://polkadot.js.org/docs/keyring/FAQ#my-pair-address-does-not-match-with-my-chain).
- The project was funded by the Kusama Treasury in Referendum 102 (within polkadot.study proposal)
- This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
\ No newline at end of file
......@@ -63,6 +63,8 @@ export const authOptions: NextAuthOptions = {
}
try {
const message = JSON.parse(credentials.message);
// AA: specify xx Network
const keyring = new Keyring({ type: 'sr25519', ss58Format: 55 });
//verify the message is from the same uri
if (message.uri !== process.env.NEXTAUTH_URL) {
......@@ -87,27 +89,36 @@ export const authOptions: NextAuthOptions = {
return Promise.reject(new Error('🚫 Invalid Signature'));
}
// AA: specify xx Network
const keyring = new Keyring({ type: 'sr25519', ss58Format: 55 });
// verify the account has the defined token
const wsProvider = new WsProvider(
process.env.RPC_ENDPOINT ?? 'ws://192.168.1.3:63007',
);
// verify the account has the defined token
const wsProvider = new WsProvider(process.env.RPC_ENDPOINT ?? 'ws://192.168.1.3:63007');
const api = await ApiPromise.create({ provider: wsProvider });
await api.isReady;
if (credentials?.address) {
// AA: encode wallet address for ss58Format 55
const ksmAddress = encodeAddress(credentials.address, 55);
const accountInfo = await api.query.system.account(ksmAddress);
const balance = accountInfo.data.free.add(accountInfo.data.reserved);
// AA: write ksmAddress for xx Network to console
console.log('wallet address on xx Network: ', ksmAddress);
console.log('wallet balance on xx Network: ', balance.toString());
if (accountInfo.data.free.gt(new BN(1_000_000_000))) {
// if the user has a free balance > 1 XX, 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'));
}
// highlight-end
};
return Promise.reject(new Error('🚫 API Error'));
return {
id: credentials.address,
name: credentials.name,
freeBalance: api.createType('Balance', 0),
ksmAddress: ksmAddress,
};
} catch (e) {
return null;
......
......@@ -45,10 +45,9 @@ export default function ProtectedPage() {
}
// format the big number to a human readable format
// const ksmBalance = formatBalance( freeBalance, { decimals: 12, withSi: true, withUnit: 'KSM' } )
// AA: hard-coded 2.00 xx
const freeBalance = new BN(2000000000);
const ksmBalance = formatBalance(freeBalance, {
// const ksmBalance = formatBalance( session.freeBalance, { decimals: 12, withSi: true, withUnit: 'KSM' } )
// AA: xx uses 9 decimals
const ksmBalance = formatBalance(session.freeBalance, {
decimals: 9,
withSi: true,
withUnit: 'XX',
......
......@@ -31,7 +31,7 @@ export default function Admin({ freeBalance }: { freeBalance: BN }): JSX.Element
// format the big number to a human readable format
// const ksmBalance = formatBalance( freeBalance, { decimals: 12, withSi: true, withUnit: 'KSM' } )
// AA: freeBalance obtained in L11
// AA: freeBalance on XX Network has 9 decimals
const ksmBalance = formatBalance(freeBalance, {
decimals: 9,
withSi: true,
......
## README for xx Network
Thank you to [the original author](https://polkadot.study/tutorials/tokengated-polkadot-next-js/intro) and the guy who [forked it](https://github.com/yk909/polkadot-js-tokengated-website/) to apply some fixes (verify/compare if you plan to use in production, of course).
This is partially working, but I'm sharing in the hope someone will use it for xx Network or other Substrate projects/chains for which the upstream forks don't provide instructions.
## How to run
Install Polkadot{.js} extension, create xx Network wallet, fund it with some amount of xx coins (1.01, for example) and set it to work on `xx Network`.
Download this repo, create `.env.local` and run:
```sh
npm run dev
```
Go to http://localhost:3000 in the browser where you installed Polkadot{.js}, and connect the extension to http://localhost:3000 (see xx_polkadot_extension.png), generate an address and make it restricted for use on xx Network (I hoped this would ensure balance will be looked up correctly, but it was not).
With that, I can login but (see xx_screenshot.png) my balance is not correctly shown.
It's interesting that if you go to wallet.xx.network, Polkadot{.js} will add the wallet from the extension and show it in xx Wallet. Neat!
`npm run build` builds okay, but has warnings about multiple versions of some package, etc. I don't know JS well enough to fix this quickly.
## What modified and why
`.env.local` and `pages/api/auth/[...nextauth].js` line 92 there's a fall back to public RPC endpoint, but I modified that one to local as well. In the latter file there's also balance lookup which seems to be malfunctioning somehow.
In `components/login.tsx` I added some functions for debugging, and logging to console.
In `pages/protected-api.tsx` and `pages/protected.tsx` ("static" protected page), changed KSM to XX:
```sh
const ksmBalance = formatBalance( session.freeBalance, { decimals: 9, withSi: true, withUnit: 'XX' } )
```
All modified pages from yk909's fork (you can see in Commits):
```sh
modified: components/account-select.tsx
modified: components/login.tsx
modified: package-lock.json
modified: package.json
modified: pages/api/auth/[...nextauth].ts
modified: pages/protected-api.tsx
modified: pages/protected.tsx
```
## Known issues
Upon login, incorrect wallet balance is not displayed (0 is shown) which means either it's failing to look it up or I messed the logic up while trying random things.
It seems it's looking up the balance of the Kusama address instead of 6xxx on xx Network. This is what's output to console.
```raw
token {
name: '123123123',
sub: '5GxeeFALkRvjnNgkiMjiP6q2GGnZ1ZmFyjCusHG4VoezqZSN',
freeBalance: '0x00000000000000000000000000000000',
iat: 1729089706,
exp: 1731681706,
jti: '79ce6529-185f-4a3e-b68a-75d75a712438'
}
JSON Web Token {
"name": "123123123",
"sub": "5GxeeFALkRvjnNgkiMjiP6q2GGnZ1ZmFyjCusHG4VoezqZSN",
"freeBalance": "0x00000000000000000000000000000000",
"iat": 1729089706,
"exp": 1731681706,
"jti": "79ce6529-185f-4a3e-b68a-75d75a712438"
}
```
The FAQs say [it's normal to see another address](https://polkadot.js.org/docs/keyring/FAQ#my-pair-address-does-not-match-with-my-chain), but balance look up should work and it doesn't because my wallet balance is > 0 XX.
`encodeAddress(session.address, 55)` is one correction that needed to be made, and the proper encoding used to get the correct wallet address from xx Network printed out in console log. But its balance is still wrong (i.e. not queried). For demo purposes I hard-coded it into JS on one of the protected pages.
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