forked from coral-xyz/backpack
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Started with a basic implementation Fixes coral-xyz#3542
- Loading branch information
Showing
3 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
import React, { useEffect, useState } from "react"; | ||
import { Button, ScrollBar, Text, TextField, View } from "react-xnft"; | ||
import { Keypair } from "@solana/web3.js"; | ||
import * as bip39 from "bip39"; | ||
import { ethers } from "ethers"; | ||
import { HDKey } from "micro-ed25519-hdkey"; | ||
|
||
export enum Blockchain { | ||
SOLANA = "solana", | ||
ETHEREUM = "ethereum", | ||
} | ||
|
||
export type MnemonicResponse = { | ||
/** Derivation path of the public key */ | ||
derivationPath: string; | ||
/** Public key */ | ||
publicKey: string; | ||
}; | ||
|
||
export function MnemonicPrinter() { | ||
const [mnemonic, setMnemonic] = useState<string>(""); | ||
const [mnemonicResponse, setMnemonicResponse] = useState<MnemonicResponse[]>( | ||
[] | ||
); | ||
const [blockChain, setBlockChain] = useState<Blockchain>(Blockchain.SOLANA); | ||
|
||
const handleSubmit = () => { | ||
setMnemonicResponse([]); | ||
if (blockChain === Blockchain.SOLANA) { | ||
let res = getSolanaPublicKeys(mnemonic); | ||
setMnemonicResponse(res); | ||
} else if (blockChain === Blockchain.ETHEREUM) { | ||
let res = getEthereumPublicKeys(mnemonic); | ||
setMnemonicResponse(res); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
console.log(mnemonicResponse); | ||
}, [mnemonicResponse]); | ||
|
||
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; | ||
}; | ||
|
||
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; | ||
}; | ||
|
||
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) => { | ||
setMnemonic(e.target.value); | ||
}} | ||
value={mnemonic} | ||
/> | ||
<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 | ||
? mnemonicResponse.map((res) => | ||
renderPublicKeys(res.derivationPath, res.publicKey) | ||
) | ||
: null} | ||
</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> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); |