Skip to content

Commit

Permalink
feat/438 - Update to shortened addresses (anoma#439)
Browse files Browse the repository at this point in the history
* Update private key derivation to slip10_ed25519

* Updated shared to use new addresses, fix shared tests

* Remove atest address from balance query - these are invalid

* Updated tokens to remove ERC20 for now, updated slip44 lib to get NAM

* Update commit, fix helper

* Remove Address->secret, add Address->hash

* Update to v0.26.0

* Updating for Ledger app (anoma#448)
  • Loading branch information
jurevans authored Nov 15, 2023
1 parent 04acabe commit e0df6a2
Show file tree
Hide file tree
Showing 29 changed files with 533 additions and 886 deletions.
2 changes: 1 addition & 1 deletion apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"dependencies": {
"@cosmjs/encoding": "^0.29.0",
"@dao-xyz/borsh": "^5.1.5",
"@ledgerhq/hw-transport": "^6.28.3",
"@ledgerhq/hw-transport": "^6.28.2",
"@ledgerhq/hw-transport-webhid": "^6.27.14",
"@ledgerhq/hw-transport-webusb": "^6.27.14",
"@namada/chains": "0.1.0",
Expand Down
9 changes: 4 additions & 5 deletions apps/extension/src/App/Accounts/AccountListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const isChild = (type: AccountType, path: Bip44Path): boolean => {
// with a path that isn't the default path (/0'/0/0). This is for display
// purposes only. If the sum of the path components is greater than
// zero, it is a child.
const { account, change, index = 0 } = path;
const { account, change, index } = path;
return account + change + index > 0;
}

Expand All @@ -49,13 +49,12 @@ const isChild = (type: AccountType, path: Bip44Path): boolean => {

const formatDerivationPath = (
isChildAccount: boolean,
{ account, change, index = 0 }: Bip44Path,
{ account, change, index }: Bip44Path,
type: AccountType
): string =>
isChildAccount
? `/${account}'/${
type !== AccountType.Mnemonic ? `${change}/` : ""
}${index}`
? `/${account}'/${type !== AccountType.Mnemonic ? `${change}/` : ""
}${index}`
: "";

const AccountListing = ({ account, parentAlias }: Props): JSX.Element => {
Expand Down
7 changes: 3 additions & 4 deletions apps/extension/src/App/Accounts/AddAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const findNextIndex = (
accounts
.filter((account) => account.type === accountType)
.forEach((account) => {
const { index = 0 } = account.path;
const { index } = account.path;
maxIndex = index + 1;
});

Expand Down Expand Up @@ -402,9 +402,8 @@ const AddAccount: React.FC<Props> = ({

<Bip44Path>
Derivation path:{" "}
<span>{`${parentDerivationPath}${
isTransparent ? `${change}/` : ""
}${index}`}</span>
<span>{`${parentDerivationPath}${isTransparent ? `${change}/` : ""
}${index}`}</span>
</Bip44Path>
<FormValidationMsg>{validation}</FormValidationMsg>
</AddAccountForm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ export const LedgerConnect: React.FC = () => {
}

const { address, publicKey } = await ledger.getAddressAndPublicKey();

navigate(
formatRouterPath([TopLevelRoute.Ledger, LedgerConnectRoute.Import]),
{ state: { address, publicKey } }
{
state: {
address,
publicKey,
},
}
);
} catch (e) {
handleError(e);
Expand Down
116 changes: 59 additions & 57 deletions apps/extension/src/background/keyring/keyring.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import BigNumber from "bignumber.js";

import { deserialize } from "@dao-xyz/borsh";

import { chains } from "@namada/chains";
Expand Down Expand Up @@ -180,7 +178,11 @@ export class KeyRing {
const mnemonic = Mnemonic.from_phrase(phrase);
const seed = mnemonic.to_seed();
const { coinType } = chains[this.chainId].bip44;
const path = { account: 0, change: 0, index: 0 };
const path = {
account: 0,
change: 0,
index: 0,
};
const bip44Path = makeBip44PathArray(coinType, path);
const hdWallet = new HDWallet(seed);
const key = hdWallet.derive(new Uint32Array(bip44Path));
Expand Down Expand Up @@ -251,7 +253,7 @@ export class KeyRing {
const text = readStringPointer(privateKey, this.cryptoMemory);
const address = new Address(text).implicit();

const { account, change, index = 0 } = path;
const { account, change, index } = path;
const id = generateId(
UUID_NAMESPACE,
"account",
Expand All @@ -278,7 +280,7 @@ export class KeyRing {
path: Bip44Path,
parentId: string
): DerivedAccountInfo {
const { index = 0 } = path;
const { index } = path;
const id = generateId(UUID_NAMESPACE, "shielded-account", parentId, index);
const zip32 = new ShieldedHDWallet(seed);
const account = zip32.derive_to_serialized_keys(index);
Expand Down Expand Up @@ -308,58 +310,58 @@ export class KeyRing {
};
}

private async *getAddressWithBalance(
seed: VecU8Pointer,
parentId: string,
type: AccountType
): AsyncGenerator<
{
path: Bip44Path;
info: DerivedAccountInfo;
},
void,
void
> {
let index = 0;
let emptyBalanceCount = 0;
const deriveFn = (
type === AccountType.PrivateKey
? this.deriveTransparentAccount
: this.deriveShieldedAccount
).bind(this);

const get = async (
index: number
): Promise<{
path: Bip44Path;
info: DerivedAccountInfo;
balances: [string, string][];
}> => {
// Cloning the seed, otherwise it gets zeroized in deriveTransparentAccount
const seedClone = seed.clone();
const path = { account: 0, change: 0, index };
const accountInfo = deriveFn(seedClone, path, parentId);
const balances: [string, string][] = await this.query.query_balance(
accountInfo.owner
);

return { path, info: accountInfo, balances };
};

while (index < 999999999 && emptyBalanceCount < 20) {
const { path, info, balances } = await get(index++);
const hasBalance = balances.some(([, value]) => {
return !new BigNumber(value).isZero();
});

if (hasBalance) {
emptyBalanceCount = 0;
yield { path, info };
} else {
emptyBalanceCount++;
}
}
}
// private async *getAddressWithBalance(
// seed: VecU8Pointer,
// parentId: string,
// type: AccountType
// ): AsyncGenerator<
// {
// path: Bip44Path;
// info: DerivedAccountInfo;
// },
// void,
// void
// > {
// let index = 0;
// let emptyBalanceCount = 0;
// const deriveFn = (
// type === AccountType.PrivateKey
// ? this.deriveTransparentAccount
// : this.deriveShieldedAccount
// ).bind(this);
//
// const get = async (
// index: number
// ): Promise<{
// path: Bip44Path;
// info: DerivedAccountInfo;
// balances: [string, string][];
// }> => {
// // Cloning the seed, otherwise it gets zeroized in deriveTransparentAccount
// const seedClone = seed.clone();
// const path = { account: 0, change: 0, index };
// const accountInfo = deriveFn(seedClone, path, parentId);
// const balances: [string, string][] = await this.query.query_balance(
// accountInfo.owner
// );
//
// return { path, info: accountInfo, balances };
// };
//
// while (index < 999999999 && emptyBalanceCount < 20) {
// const { path, info, balances } = await get(index++);
// const hasBalance = balances.some(([, value]) => {
// return !new BigNumber(value).isZero();
// });
//
// if (hasBalance) {
// emptyBalanceCount = 0;
// yield { path, info };
// } else {
// emptyBalanceCount++;
// }
// }
// }

public async scanAddresses(): Promise<void> {
// if (!this._password) {
Expand Down
8 changes: 5 additions & 3 deletions apps/extension/src/background/keyring/service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fromBase64 } from "@cosmjs/encoding";
import { fromBase64, fromHex } from "@cosmjs/encoding";

import { PhraseSize } from "@namada/crypto";
import { Query, Sdk, TxType } from "@namada/shared";
import { public_key_to_bech32, Query, Sdk, TxType } from "@namada/shared";
import { IndexedDBKVStore, KVStore } from "@namada/storage";
import { AccountType, Bip44Path, DerivedAccount } from "@namada/types";
import { Result } from "@namada/utils";
Expand Down Expand Up @@ -107,10 +107,12 @@ export class KeyRingService {
bip44Path: Bip44Path,
parentId?: string
): Promise<AccountStore | false> {
const publicKeyBytes = fromHex(publicKey);
const bech32PublicKey = public_key_to_bech32(publicKeyBytes);
return await this._keyRing.storeLedger(
alias,
address,
publicKey,
bech32PublicKey,
bip44Path,
parentId
);
Expand Down
5 changes: 3 additions & 2 deletions apps/extension/src/background/ledger/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "@namada/ledger-namada";
import { defaultChainId, chains } from "@namada/chains";
import { makeBip44Path } from "@namada/utils";
import { toHex } from "@cosmjs/encoding";

const namadaChain = chains[defaultChainId];
const { coinType } = namadaChain.bip44;
Expand All @@ -30,7 +31,7 @@ export const DEFAULT_LEDGER_BIP44_PATH = makeBip44Path(coinType, {
});

export class Ledger {
constructor(public readonly namadaApp: NamadaApp | undefined = undefined) {}
constructor(public readonly namadaApp: NamadaApp | undefined = undefined) { }

/**
* Returns an initialized Ledger class instance with initialized Transport
Expand Down Expand Up @@ -85,7 +86,7 @@ export class Ledger {
// Return address as bech32-encoded string
address: address.toString(),
// Return public key as hex-encoded string
publicKey: publicKey.toString("hex").substring(2),
publicKey: toHex(publicKey),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,6 @@ const assetIconByToken: Record<TokenType, { light: string; dark: string }> = {
light: AssetEthereumEther,
dark: AssetEthereumEther,
},
["TESTERC20"]: {
light: AssetEthereumEther,
dark: AssetEthereumEther,
},
["NUTTESTERC20"]: {
light: AssetEthereumEther,
dark: AssetEthereumEther,
},
["ATOM"]: {
light: AssetCosmosAtom,
dark: AssetCosmosAtom,
Expand Down Expand Up @@ -204,7 +196,8 @@ const DerivedAccounts = ({ setTotal }: Props): JSX.Element => {
<TokenIcon
src={getAssetIconByTheme(token as TokenType)}
/>
{amount.toString()} {Tokens[token as TokenType].symbol}
{amount.toString()}{" "}
{Tokens[token as TokenType].symbol}
</TokenBalance>
);
})}
Expand Down
18 changes: 9 additions & 9 deletions apps/namada-interface/src/App/Token/TokenSend/TokenSend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const TokenSend = (): JSX.Element => {
let defaultTab = 0;

// Load the correct form if coming from URL in QR code:
if (target && target.startsWith("atest")) {
if (target && target.startsWith("tnam")) {
defaultTab = 1;
}

Expand All @@ -112,13 +112,13 @@ const TokenSend = (): JSX.Element => {

const handleTokenChange =
(selectAccountFn: (accId: string) => void) =>
(e: React.ChangeEvent<HTMLSelectElement>): void => {
const { value } = e.target;
const [accountId, tokenSymbol] = value.split("|");
(e: React.ChangeEvent<HTMLSelectElement>): void => {
const { value } = e.target;
const [accountId, tokenSymbol] = value.split("|");

selectAccountFn(accountId);
setToken(tokenSymbol as TokenType);
};
selectAccountFn(accountId);
setToken(tokenSymbol as TokenType);
};

return (
<TokenSendContainer>
Expand Down Expand Up @@ -153,7 +153,7 @@ const TokenSend = (): JSX.Element => {
address={selectedShieldedAccountAddress}
tokenType={token}
defaultTarget={
target?.startsWith("patest") ? target : undefined
target?.startsWith("znam") ? target : undefined
}
/>
)}
Expand Down Expand Up @@ -181,7 +181,7 @@ const TokenSend = (): JSX.Element => {
address={selectedTransparentAccountAddress}
tokenType={token}
defaultTarget={
target?.startsWith("atest") ? target : undefined
target?.startsWith("tnam") ? target : undefined
}
/>
)}
Expand Down
6 changes: 3 additions & 3 deletions apps/namada-interface/src/App/Token/TokenSend/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const PAYMENT_ADDRESS_PREFIX = "patest1";
export const PAYMENT_ADDRESS_PREFIX = "znam1";
export const PAYMENT_ADDRESS_LENGTH = 82;
export const ESTABLISHED_ADDRESS_PREFIX = "atest1";
export const ESTABLISHED_ADDRESS_LENGTH = 84;
export const ESTABLISHED_ADDRESS_PREFIX = "tnam1";
export const ESTABLISHED_ADDRESS_LENGTH = 45;
31 changes: 14 additions & 17 deletions apps/namada-interface/src/store/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,27 @@ export const mockAppState: RootState = {
accounts: {
derived: {
"namada-masp-1.5.32ccad5356012a7": {
atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp:
{
details: {
chainId: "namada-masp-1.5.32ccad5356012a7",
alias: "Namada",
address:
"atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp",
isShielded: false,
type: AccountType.PrivateKey,
},
balance: {
NAM: new BigNumber(1000),
ATOM: new BigNumber(1000),
ETH: new BigNumber(1000),
},
tnam1q8gpzlamqksqjagt2xs3p6tnfcldy0fcd53fs4jh: {
details: {
chainId: "namada-masp-1.5.32ccad5356012a7",
alias: "Namada",
address: "tnam1q8gpzlamqksqjagt2xs3p6tnfcldy0fcd53fs4jh",
isShielded: false,
type: AccountType.PrivateKey,
},
balance: {
NAM: new BigNumber(1000),
ATOM: new BigNumber(1000),
ETH: new BigNumber(1000),
},
},
},
"namada-test.1e670ba91369ec891fc": {
"39UL18": {
details: {
chainId: "namada-test.1e670ba91369ec891fc",
alias: "Namada",
address:
"atest1v4ehgw36xqcyz3zrxsenzd3kxsunsvzzxymyywpkg4zrjv2pxepyyd3cgse5gwzxgsm5x3zrkf2pwp",
address: "tnam1qz4sdx5jlh909j44uz46pf29ty0ztftfzc98s8dx",
type: AccountType.PrivateKey,
isShielded: false,
},
Expand Down
Loading

0 comments on commit e0df6a2

Please sign in to comment.