Skip to content

Commit

Permalink
feat: mnemonic printer xnft example
Browse files Browse the repository at this point in the history
  • Loading branch information
jeivardan committed Apr 3, 2023
1 parent 20346a7 commit feb6cc7
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 0 deletions.
27 changes: 27 additions & 0 deletions examples/xnft/mnemonic-printer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "mnemonic-printer",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "xnft legacy build",
"start": "xnft legacy start",
"dev": "xnft legacy dev"
},
"author": "",
"license": "ISC",
"dependencies": {
"@coral-xyz/xnft-cli": "0.2.0-latest.3331",
"@types/d3": "^7.4.0",
"d3-scale": "^4.0.2",
"d3-shape": "^3.1.0",
"debounce": "^1.2.1",
"micro-ed25519-hdkey": "^0.1.2",
"react": "18.2.0",
"react-xnft": "0.2.0-latest.3318",
"recoil": "^0.7.6",
"reselect": "^4.1.6",
"superstruct": "^0.16.5",
"swr": "^1.3.0"
}
}
158 changes: 158 additions & 0 deletions examples/xnft/mnemonic-printer/src/App/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import React, { useCallback, useState } from "react";
import { Button, ScrollBar, Text, TextField, View } from "react-xnft";

import type { MnemonicResponse } from "./_types/types";
import { Blockchain } from "./_types/types";
import getEthereumPublicKeys from "./_utils/getEthereumPublicKeys";
import getSolanaPublicKeys from "./_utils/getSolanaPublicKeys";

export function MnemonicPrinter() {
const [phrase, setPhrase] = useState("");
const [mnemonicResponse, setMnemonicResponse] = useState<MnemonicResponse[]>(
[]
);
const [blockChain, setBlockChain] = useState<Blockchain>(Blockchain.SOLANA);
const [message, setMessage] = useState<string>("");

const handleSubmit = useCallback(() => {
setMnemonicResponse([]);
setMessage("Loading please wait ...");
let res = getPaths(blockChain, phrase);
setMnemonicResponse(res);
setMessage("");
}, [phrase, blockChain]);

return (
<View
style={{
display: "flex",
flexDirection: "column",
height: "100%",
padding: "10px 0px",
cursor: "pointer",
paddingTop: "50px",
}}
>
<View
style={{
display: "flex",
padding: "0px 16px",
paddingBottom: "10px",
flexDirection: "column",
gap: 5,
}}
>
<TextField
placeholder="Enter secret recovery phrase"
onChange={(e) => {
setPhrase(e.target.value);
}}
value={phrase}
/>
<View
style={{
display: "flex",
gap: 5,
}}
>
<Button
style={{
border:
blockChain === Blockchain.SOLANA ? "3px solid" : "3px hidden",
flexGrow: 1,
}}
onClick={() => {
setBlockChain(Blockchain.SOLANA);
}}
>
Solana
</Button>
<Button
style={{
border:
blockChain === Blockchain.ETHEREUM ? "3px solid" : "3px hidden",
flexGrow: 1,
}}
onClick={() => {
setBlockChain(Blockchain.ETHEREUM);
}}
>
Ethereum
</Button>
</View>
<Button onClick={() => handleSubmit()}> Search </Button>
</View>
<View
style={{
display: "flex",
flexGrow: 1,
position: "relative",
}}
>
<ScrollBar>
{mnemonicResponse.length > 0 ? (
mnemonicResponse.map((res) =>
renderPublicKeys(res.derivationPath, res.publicKey)
)
) : (
<Text style={{ padding: "8px" }}>{`${message}`}</Text>
)}
</ScrollBar>
</View>
</View>
);
}

function renderPublicKeys(derivationPath: string, publicKey: string) {
return (
<View
style={{
padding: "8px 16px",
display: "flex",
position: "relative",
}}
>
<View
style={{
display: "flex",
flexGrow: 1,
flexDirection: "column",
overflow: "hidden",
}}
>
<Text
style={{
font: "Inter",
lineHeight: "24px",
fontSize: "18px",
whiteSpace: "nowrap",
fontWeight: "bold",
}}
>{`${derivationPath}`}</Text>
<Text
style={{
font: "Inter",
lineHeight: "24px",
fontSize: "16px",
wordWrap: "break-word",
whiteSpace: "initial",
}}
>{`${publicKey}`}</Text>
</View>
</View>
);
}

function getPaths(blockChain: string, phrase: string): MnemonicResponse[] {
let res: MnemonicResponse[] = [];
if (blockChain === Blockchain.SOLANA) {
setTimeout(() => {
res = getSolanaPublicKeys(phrase);
}, 25);
} else if (blockChain === Blockchain.ETHEREUM) {
setTimeout(() => {
res = getEthereumPublicKeys(phrase);
}, 25);
}
return res;
}
11 changes: 11 additions & 0 deletions examples/xnft/mnemonic-printer/src/App/_types/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export enum Blockchain {
SOLANA = "solana",
ETHEREUM = "ethereum",
}

export type MnemonicResponse = {
/** Derivation path of the public key */
derivationPath: string;
/** Public key */
publicKey: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ethers } from "ethers";

import type { MnemonicResponse } from "../_types/types";

self.onmessage = (e: MessageEvent<string>) => {
let res = getEthereumPublicKeys(e.data);
self.postMessage(res);
};

const getEthereumPublicKeys = (mnemonic: string): MnemonicResponse[] => {
let res: MnemonicResponse[] = [];
for (let i = 0; i < 10; i++) {
const path = `m/44'/60'`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/60'/${i}'`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/60'/0'/${i}`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/60'/0'/${i}'`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/60'/${i}'/0`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
for (let j = 0; j < 10; j++) {
const path = `m/44'/60'/${i}'/0'/${j}`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/60'/${i}'/0`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
for (let j = 0; j < 10; j++) {
const path = `m/44'/60'/${i}'/0/${j}`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
for (let j = 0; j < 10; j++) {
const path = `m/44'/60'/${i}'/0'/${j}`;
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
res.push({ derivationPath: path, publicKey: wallet.address });
}
}
return res;
};

export default getEthereumPublicKeys;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Keypair } from "@solana/web3.js";
import * as bip39 from "bip39";
import { HDKey } from "micro-ed25519-hdkey";

import type { MnemonicResponse } from "../_types/types";

const getSolanaPublicKeys = (mnemonic: string): MnemonicResponse[] => {
let res: MnemonicResponse[] = [];
const seed = bip39.mnemonicToSeedSync(mnemonic, "");
const hd = HDKey.fromMasterSeed(seed.toString("hex"));
for (let i = 0; i < 10; i++) {
const path = `m/44'/501'`;
const keypair = Keypair.fromSeed(hd.derive(path).privateKey);
res.push({
derivationPath: path,
publicKey: keypair.publicKey.toBase58(),
});
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/501'/${i}'`;
const keypair = Keypair.fromSeed(hd.derive(path).privateKey);
res.push({
derivationPath: path,
publicKey: keypair.publicKey.toBase58(),
});
}
for (let i = 0; i < 10; i++) {
const path = `m/44'/501'/${i}'/0'`;
const keypair = Keypair.fromSeed(hd.derive(path).privateKey);
res.push({
derivationPath: path,
publicKey: keypair.publicKey.toBase58(),
});
for (let j = 0; j < 10; j++) {
const path = `m/44'/501'/${i}'/0'/${j}'`;
const keypair = Keypair.fromSeed(hd.derive(path).privateKey);
res.push({
derivationPath: path,
publicKey: keypair.publicKey.toBase58(),
});
}
}
return res;
};

export default getSolanaPublicKeys;
10 changes: 10 additions & 0 deletions examples/xnft/mnemonic-printer/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";
import ReactXnft, { AnchorDom } from "react-xnft";

import { MnemonicPrinter } from "./App/App";

ReactXnft.render(
<AnchorDom>
<MnemonicPrinter />
</AnchorDom>
);

0 comments on commit feb6cc7

Please sign in to comment.