generated from MetaMask/metamask-module-template
-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(keyring-utils): add isScopeEqual + isScopeEqualToAny
- Loading branch information
Showing
2 changed files
with
108 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,58 @@ | ||
import { isScopeEqual, isScopeEqualToAny } from './scopes'; | ||
|
||
const ETH_EOA = 'eip155:0'; | ||
const ETH_MAINNET = 'eip155:1'; | ||
const ETH_TESTNET = 'eip155:11155111'; | ||
const BTC_MAINNET = 'bip122:000000000019d6689c085ae165831e93'; | ||
const BTC_TESTNET = 'bip122:000000000933ea01ad0ee984209779ba'; | ||
|
||
describe('isScopeEqual', () => { | ||
it('returns true when both scopes are equal', () => { | ||
expect(isScopeEqual(ETH_MAINNET, ETH_MAINNET)).toBe(true); | ||
expect(isScopeEqual(ETH_TESTNET, ETH_TESTNET)).toBe(true); | ||
expect(isScopeEqual(BTC_MAINNET, BTC_MAINNET)).toBe(true); | ||
expect(isScopeEqual(BTC_TESTNET, BTC_TESTNET)).toBe(true); | ||
}); | ||
|
||
it('returns false when both scopes are not equal', () => { | ||
expect(isScopeEqual(ETH_MAINNET, ETH_TESTNET)).toBe(false); | ||
expect(isScopeEqual(ETH_TESTNET, ETH_MAINNET)).toBe(false); | ||
expect(isScopeEqual(BTC_MAINNET, BTC_TESTNET)).toBe(false); | ||
expect(isScopeEqual(BTC_TESTNET, BTC_MAINNET)).toBe(false); | ||
}); | ||
|
||
it('supports EVM EOA scopes', () => { | ||
expect(isScopeEqual(ETH_MAINNET, ETH_EOA)).toBe(true); | ||
expect(isScopeEqual(ETH_TESTNET, ETH_EOA)).toBe(true); | ||
expect(isScopeEqual(ETH_EOA, ETH_MAINNET)).toBe(true); | ||
expect(isScopeEqual(ETH_EOA, ETH_TESTNET)).toBe(true); | ||
|
||
expect(isScopeEqual(ETH_EOA, BTC_MAINNET)).toBe(false); | ||
expect(isScopeEqual(BTC_MAINNET, ETH_EOA)).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('isScopeEqualToAny', () => { | ||
it('returns true when both scopes are equal', () => { | ||
expect(isScopeEqualToAny(ETH_MAINNET, [ETH_TESTNET, ETH_MAINNET])).toBe( | ||
true, | ||
); | ||
expect(isScopeEqualToAny(BTC_MAINNET, [BTC_MAINNET, BTC_TESTNET])).toBe( | ||
true, | ||
); | ||
}); | ||
|
||
it('returns false when both scopes are not equal', () => { | ||
expect(isScopeEqualToAny(ETH_MAINNET, [ETH_TESTNET])).toBe(false); | ||
expect(isScopeEqualToAny(ETH_MAINNET, [])).toBe(false); | ||
expect(isScopeEqualToAny(BTC_MAINNET, [ETH_MAINNET])).toBe(false); | ||
}); | ||
|
||
it('supports EVM EOA scopes', () => { | ||
expect(isScopeEqualToAny(ETH_EOA, [ETH_TESTNET, ETH_MAINNET])).toBe(true); | ||
expect(isScopeEqualToAny(ETH_MAINNET, [ETH_TESTNET, ETH_EOA])).toBe(true); | ||
|
||
expect(isScopeEqualToAny(BTC_MAINNET, [ETH_TESTNET, ETH_EOA])).toBe(false); | ||
expect(isScopeEqualToAny(ETH_EOA, [BTC_MAINNET, BTC_TESTNET])).toBe(false); | ||
}); | ||
}); |
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,50 @@ | ||
import type { CaipChainId } from '@metamask/utils'; | ||
import { KnownCaipNamespace } from '@metamask/utils'; | ||
|
||
// We do not uses the `EthScope` from `@metamask/keyring-api` here, to avoid pulling it | ||
// as a dependency. | ||
export const ETH_SCOPE_EOA = `${KnownCaipNamespace.Eip155}:0`; | ||
|
||
// We use a string prefix when comparing EOAs to avoid unecessary splits. | ||
const ETH_SCOPE_PREFIX = `${KnownCaipNamespace.Eip155}:`; | ||
|
||
/** | ||
* Check if scope is compatible with a list of scopes. It also supports the special | ||
* case of `eip155:0` for EVM EOA chain ID which is compatible with any EVM chain | ||
* ID (`eip155:*`). | ||
* | ||
* @param scope - The scope (CAIP-2 chain ID) to check. | ||
* @param other - Another scope to compare to. | ||
* @returns True if both scope are compatible, false otherwise. | ||
*/ | ||
export function isScopeEqual(scope: CaipChainId, other: CaipChainId): boolean { | ||
const isScopeEoa = scope === ETH_SCOPE_EOA; | ||
const isOtherEoa = other === ETH_SCOPE_EOA; | ||
|
||
// Special case for EOA scopes (we check on both sides); | ||
if (isScopeEoa) { | ||
return other.startsWith(ETH_SCOPE_PREFIX); | ||
} | ||
if (isOtherEoa) { | ||
return scope.startsWith(ETH_SCOPE_PREFIX); | ||
} | ||
|
||
// Normal case, if both scope stricly matches, then they are compatible. | ||
return scope === other; | ||
} | ||
|
||
/** | ||
* Check if scope is compatible with a list of scopes. It also supports the special | ||
* case of `eip155:0` for EVM EOA chain ID which is compatible with any EVM chain | ||
* ID (`eip155:*`). | ||
* | ||
* @param scope - The scope (CAIP-2 chain ID) to check. | ||
* @param scopes - The list of scopes to check against. | ||
* @returns True if the scope is compatible within the list of scopes. | ||
*/ | ||
export function isScopeEqualToAny( | ||
scope: CaipChainId, | ||
scopes: CaipChainId[], | ||
): boolean { | ||
return scopes.some((other) => isScopeEqual(scope, other)); | ||
} |