Skip to content

Creating a web based wallet

Pre-requisites - React

Let’s try to create a web based wallet similar to https://wallet-kosh.vercel.app/

https://github.com/keshav-exe/projekt-kosh/

  • Initialize an empty React Project
npm create vite@latest
  • Install dependencies
npm install
  • Add node-pollyfills
npm install vite-plugin-node-polyfills
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { nodePolyfills } from 'vite-plugin-node-polyfills'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), nodePolyfills()],
})
  • Clean up App.jsx
import { useState } from 'react'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
</>
)
}
export default App
  • Create a mnemonics state variable
const [mnemonic, setMnemonic] = useState("");
npm install bip39
import { generateMnemonic } from "bip39";
<button onClick={async function() {
const mn = await generateMnemonic();
setMnemonic(mn)
}}>
Create Seed Phrase
</button>

Reference - https://github.com/hujiulong/web-bip39

  • Display the mnemonic in an input box
<input type="text" value={mnemonic}></input>
  • Add a SolanaWallet component

Ref - https://projects.100xdevs.com/tracks/public-private-keys/Public-Key-Cryptography-9

import { useState } from "react"
import { mnemonicToSeed } from "bip39";
import { derivePath } from "ed25519-hd-key";
import { Keypair } from "@solana/web3.js";
import nacl from "tweetnacl"
export function SolanaWallet({ mnemonic }) {
const [currentIndex, setCurrentIndex] = useState(0);
const [publicKeys, setPublicKeys] = useState([]);
return <div>
<button onClick={function() {
const seed = mnemonicToSeed(mnemonic);
const path = `m/44'/501'/${currentIndex}'/0'`;
const derivedSeed = derivePath(path, seed.toString("hex")).key;
const secret = nacl.sign.keyPair.fromSeed(derivedSeed).secretKey;
const keypair = Keypair.fromSecretKey(secret);
setCurrentIndex(currentIndex + 1);
setPublicKeys([...publicKeys, keypair.publicKey]);
}}>
Add wallet
</button>
{publicKeys.map(p => <div>
{p.toBase58()}
</div>)}
</div>
}
import { useState } from "react";
import { mnemonicToSeed } from "bip39";
import { Wallet, HDNodeWallet } from "ethers";
export const EthWallet = ({mnemonic}) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [addresses, setAddresses] = useState([]);
return (
<div>
<button onClick={async function() {
const seed = await mnemonicToSeed(mnemonic);
const derivationPath = `m/44'/60'/${currentIndex}'/0'`;
const hdNode = HDNodeWallet.fromSeed(seed);
const child = hdNode.derivePath(derivationPath);
const privateKey = child.privateKey;
const wallet = new Wallet(privateKey);
setCurrentIndex(currentIndex + 1);
setAddresses([...addresses, wallet.address]);
}}>
Add ETH wallet
</button>
{addresses.map(p => <div>
Eth - {p}
</div>)}
</div>
)
}

Screenshot 2024-08-16 at 6.57.01 PM.png

Assignment

Can you add logic to show the ETH/SOL balances for these accounts?