Skip to content

Commit

Permalink
refactor(multichain): add getMultichainTypeFromAddress + use it for j…
Browse files Browse the repository at this point in the history
…azzicon namespace logic
  • Loading branch information
ccharly committed Oct 9, 2024
1 parent 3fea90d commit 4622980
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 14 deletions.
39 changes: 38 additions & 1 deletion shared/lib/multichain.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { isBtcMainnetAddress, isBtcTestnetAddress } from './multichain';
import {
MultichainType,
getMultichainTypeFromAddress,
isBtcMainnetAddress,
isBtcTestnetAddress,
} from './multichain';

const BTC_MAINNET_ADDRESSES = [
// P2WPKH
Expand Down Expand Up @@ -55,4 +60,36 @@ describe('multichain', () => {
},
);
});

describe('getChainTypeFromAddress', () => {
// @ts-expect-error This is missing from the Mocha type definitions
it.each([...BTC_MAINNET_ADDRESSES, ...BTC_TESTNET_ADDRESSES])(
'returns ChainType.Bitcoin for bitcoin address: %s',
(address: string) => {
expect(getMultichainTypeFromAddress(address)).toBe(
MultichainType.Bip122,
);
},
);

// @ts-expect-error This is missing from the Mocha type definitions
it.each(ETH_ADDRESSES)(
'returns ChainType.Ethereum for ethereum address: %s',
(address: string) => {
expect(getMultichainTypeFromAddress(address)).toBe(
MultichainType.Eip155,
);
},
);

// @ts-expect-error This is missing from the Mocha type definitions
it.each(SOL_ADDRESSES)(
'returns ChainType.Ethereum for non-supported address: %s',
(address: string) => {
expect(getMultichainTypeFromAddress(address)).toBe(
MultichainType.Eip155,
);
},
);
});
});
24 changes: 24 additions & 0 deletions shared/lib/multichain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { validate, Network } from 'bitcoin-address-validation';

/**
* Multi-chain family type.
*/
export enum MultichainType {
// Bitcoin-like:
Bip122 = 'bip122',
// Ethereum:
Eip155 = 'eip155',
}

/**
* Returns whether an address is on the Bitcoin mainnet.
*
Expand All @@ -26,3 +36,17 @@ export function isBtcMainnetAddress(address: string): boolean {
export function isBtcTestnetAddress(address: string): boolean {
return validate(address, Network.testnet);
}

/**
* Returns the associated chain's type for the given address.
*
* @param address - The address to check.
* @returns The chain's type for that address.
*/
export function getMultichainTypeFromAddress(address: string): MultichainType {
if (isBtcMainnetAddress(address) || isBtcTestnetAddress(address)) {
return MultichainType.Bip122;
}
// Defaults to "Ethereum" for all other cases for now.
return MultichainType.Eip155;
}
22 changes: 9 additions & 13 deletions ui/components/component-library/avatar-account/avatar-account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { PolymorphicRef } from '../box';

import { AvatarBase, AvatarBaseProps } from '../avatar-base';
import {
isBtcMainnetAddress,
isBtcTestnetAddress,
MultichainType,
getMultichainTypeFromAddress,
} from '../../../../shared/lib/multichain';
import {
AvatarAccountDiameter,
Expand All @@ -18,19 +18,15 @@ import {
AvatarAccountProps,
} from './avatar-account.types';

// TODO: This might not scale well with our new multichain initiative since it would require
// future account's type to be added here too. The best approach might be to use
// `InternalAccount` type rather than plain addresses. This way we could use the account's
// type to "infer" the namespace.
// For now, keep keep this simple.
function getJazziconNamespace(address: string): string | undefined {
if (isBtcMainnetAddress(address) || isBtcTestnetAddress(address)) {
// TODO: Add this to @metamask/utils `KnownCaipNamespaces` and use it here:
return 'bip122';
switch (getMultichainTypeFromAddress(address)) {
case MultichainType.Bip122:
return 'bip122';
case MultichainType.Eip155:
return undefined; // Falls back to default Jazzicon behavior
default:
return undefined;
}
// We leave it `undefined` to fallback to the default jazzicon behavior (even for
// ethereum).
return undefined;
}

export const AvatarAccount: AvatarAccountComponent = React.forwardRef(
Expand Down

0 comments on commit 4622980

Please sign in to comment.