Skip to content

Commit

Permalink
Merge pull request #52 from multiversx/entropy-1
Browse files Browse the repository at this point in the history
Add "mnemonicToEntropy" and "entropyToMnemonic"
  • Loading branch information
andreibancioiu authored Oct 1, 2024
2 parents 8a91245 + f2353c9 commit d6e3830
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
11 changes: 10 additions & 1 deletion src-network-wallet/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ export class ErrWrongMnemonic extends Err {
}
}

/**
* Signals a bad mnemonic entropy.
*/
export class ErrBadMnemonicEntropy extends Err {
public constructor(inner: Error) {
super("Bad mnemonic entropy", inner);
}
}

/**
* Signals a bad PEM file.
*/
Expand All @@ -49,7 +58,7 @@ export class ErrSignerCannotSign extends Err {
/**
* Signals a bad address.
*/
export class ErrBadAddress extends Err {
export class ErrBadAddress extends Err {
public constructor(value: string, inner?: Error) {
super(`Bad address: ${value}`, inner);
}
Expand Down
20 changes: 17 additions & 3 deletions src-network-wallet/mnemonic.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { generateMnemonic, mnemonicToSeedSync, validateMnemonic } from "bip39";
import { entropyToMnemonic, generateMnemonic, mnemonicToEntropy, mnemonicToSeedSync, validateMnemonic } from "bip39";
import { derivePath } from "ed25519-hd-key";
import { ErrWrongMnemonic } from "./errors";
import { ErrBadMnemonicEntropy, ErrWrongMnemonic } from "./errors";
import { UserSecretKey } from "./userKeys";

const MNEMONIC_STRENGTH = 256;
Expand All @@ -14,7 +14,7 @@ export class Mnemonic {
}

static generate(): Mnemonic {
let text = generateMnemonic(MNEMONIC_STRENGTH);
const text = generateMnemonic(MNEMONIC_STRENGTH);
return new Mnemonic(text);
}

Expand All @@ -25,6 +25,15 @@ export class Mnemonic {
return new Mnemonic(text);
}

static fromEntropy(entropy: Uint8Array): Mnemonic {
try {
const text = entropyToMnemonic(Buffer.from(entropy));
return new Mnemonic(text);
} catch (err: any) {
throw new ErrBadMnemonicEntropy(err);
}
}

public static assertTextIsValid(text: string) {
let isValid = validateMnemonic(text);

Expand All @@ -45,6 +54,11 @@ export class Mnemonic {
return this.text.split(" ");
}

getEntropy(): Uint8Array {
const entropy = mnemonicToEntropy(this.text);
return Buffer.from(entropy, "hex");
}

toString(): string {
return this.text;
}
Expand Down
39 changes: 37 additions & 2 deletions src-network-wallet/users.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { assert } from "chai";
import { Randomness } from "./crypto";
import { ErrInvariantFailed } from "./errors";
import { ErrBadMnemonicEntropy, ErrInvariantFailed } from "./errors";
import { Mnemonic } from "./mnemonic";
import { TestMessage } from "./testutils/message";
import { TestTransaction } from "./testutils/transaction";
import { DummyMnemonic, DummyMnemonicOf12Words, DummyPassword, loadTestKeystore, loadTestWallet, TestWallet } from "./testutils/wallets";
import {
DummyMnemonic,
DummyMnemonicOf12Words,
DummyPassword,
loadTestKeystore,
loadTestWallet,
TestWallet,
} from "./testutils/wallets";
import { UserSecretKey } from "./userKeys";
import { UserSigner } from "./userSigner";
import { UserVerifier } from "./userVerifier";
Expand All @@ -26,6 +33,34 @@ describe("test user wallets", () => {
assert.lengthOf(words, 24);
});

it("should convert entropy to mnemonic and back", () => {
function testConversion(text: string, entropyHex: string) {
const entropyFromMnemonic = Mnemonic.fromString(text).getEntropy();
const mnemonicFromEntropy = Mnemonic.fromEntropy(Buffer.from(entropyHex, "hex"));

assert.equal(Buffer.from(entropyFromMnemonic).toString("hex"), entropyHex);
assert.equal(mnemonicFromEntropy.toString(), text);
}

testConversion(
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
"00000000000000000000000000000000",
);

testConversion(
"moral volcano peasant pass circle pen over picture flat shop clap goat never lyrics gather prepare woman film husband gravity behind test tiger improve",
"8fbeb688d0529344e77d225898d4a73209510ad81d4ffceac9bfb30149bf387b",
);

assert.throws(
() => {
Mnemonic.fromEntropy(Buffer.from("abba", "hex"));
},
ErrBadMnemonicEntropy,
`Bad mnemonic entropy`,
);
});

it("should derive keys", async () => {
let mnemonic = Mnemonic.fromString(DummyMnemonic);

Expand Down

0 comments on commit d6e3830

Please sign in to comment.