Skip to content

Commit 89f8a31

Browse files
AngelCastilloBmkazlauskas
authored andcommitted
feat(web-extension): wallet id type changed to just string
1 parent 7fe1e6d commit 89f8a31

File tree

5 files changed

+93
-34
lines changed

5 files changed

+93
-34
lines changed

packages/web-extension/src/walletManager/WalletRepository/WalletRepository.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { AddAccountProps, AddWalletProps, RemoveAccountProps, UpdateMetadataProps, WalletRepositoryApi } from './types';
22
import { AnyWallet, ScriptWallet, WalletId, WalletType } from '../types';
3-
import { Bip32PublicKey, Hash28ByteBase16 } from '@cardano-sdk/crypto';
43
import { Logger } from 'ts-log';
54
import { Observable, defer, firstValueFrom, map, shareReplay, switchMap, take } from 'rxjs';
6-
import { Serialization } from '@cardano-sdk/core';
75
import { WalletConflictError } from '../errors';
86
import { contextLogger } from '@cardano-sdk/util';
7+
import { getWalletId } from '../util';
98
import { storage } from '@cardano-sdk/wallet';
109

1110
export interface WalletRepositoryDependencies<AccountMetadata extends {}> {
@@ -58,10 +57,10 @@ export class WalletRepository<AccountMetadata extends {}> implements WalletRepos
5857

5958
async addWallet(props: AddWalletProps<AccountMetadata>): Promise<WalletId> {
6059
this.#logger.debug('addWallet', props.type);
61-
const walletId =
62-
props.type === WalletType.Script
63-
? Serialization.Script.fromCore(props.script).hash()
64-
: Hash28ByteBase16(await Bip32PublicKey.fromHex(props.extendedAccountPublicKey).hash());
60+
const walletId = await getWalletId(
61+
props.type === WalletType.Script ? props.script : props.extendedAccountPublicKey
62+
);
63+
6564
return firstValueFrom(
6665
this.#getWallets().pipe(
6766
switchMap((wallets) => {

packages/web-extension/src/walletManager/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Bip32PublicKeyHex, Hash28ByteBase16 } from '@cardano-sdk/crypto';
1+
import { Bip32PublicKeyHex } from '@cardano-sdk/crypto';
22
import { Cardano } from '@cardano-sdk/core';
33
import { HexBlob } from '@cardano-sdk/util';
44

@@ -10,7 +10,7 @@ export enum WalletType {
1010
}
1111

1212
/** For BIP-32 wallets: hash of extended account public key. For script wallets: script hash */
13-
export type WalletId = Hash28ByteBase16;
13+
export type WalletId = string;
1414

1515
export type Bip32WalletAccount<Metadata extends {}> = {
1616
accountIndex: number;
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as Crypto from '@cardano-sdk/crypto';
22
import { AsyncKeyAgent } from '@cardano-sdk/key-management';
33

4+
import { Cardano, Serialization } from '@cardano-sdk/core';
45
import { RemoteApiProperties, RemoteApiPropertyType } from '../messaging';
56
import { WalletManagerApi, WalletManagerProps } from './walletManager.types';
67

@@ -15,14 +16,51 @@ export const walletManagerProperties: RemoteApiProperties<WalletManagerApi> = {
1516
};
1617

1718
/**
18-
* Compute a unique walletId from the keyAgent chainId and the root public key hash.
19-
* `networkId-networkMagic-blake2bHashOfExtendedAccountPublicKey`
19+
* Predicate that returns true if the given object is a script.
20+
*
21+
* @param object The object to check.
2022
*/
21-
export const getWalletId = async (keyAgent: AsyncKeyAgent): Promise<string> => {
22-
const { networkId, networkMagic } = await keyAgent.getChainId();
23-
const extendedAccountPublicKey = await keyAgent.getExtendedAccountPublicKey();
24-
const pubKey = Buffer.from(extendedAccountPublicKey, 'hex');
25-
const pubKeyHash = Crypto.blake2b(Crypto.blake2b.BYTES_MIN).update(pubKey).digest('hex');
23+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
24+
const isScript = (object: any): object is Cardano.Script =>
25+
object?.__type === Cardano.ScriptType.Plutus || object?.__type === Cardano.ScriptType.Native;
2626

27-
return `${networkId}-${networkMagic}-${pubKeyHash}`;
27+
/**
28+
* Predicate that returns true if the given object is a public key.
29+
*
30+
* @param object The object to check.
31+
*/
32+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
33+
const isBip32PublicKeyHex = (object: any): object is Crypto.Bip32PublicKeyHex =>
34+
// eslint-disable-next-line wrap-regex
35+
typeof object === 'string' && object.length === 128 && /^[\da-f]+$/i.test(object);
36+
37+
/** Compute a unique walletId from the script */
38+
export const getScriptWalletId = async (script: Cardano.Script): Promise<string> =>
39+
Serialization.Script.fromCore(script).hash().slice(0, 32);
40+
41+
/**
42+
* Compute a unique walletId from the extended account public key.
43+
*
44+
* @param pubKey The extended account public key.
45+
*/
46+
export const getExtendedAccountPublicKeyWalletId = async (pubKey: Crypto.Bip32PublicKeyHex): Promise<string> =>
47+
Crypto.blake2b(Crypto.blake2b.BYTES_MIN).update(Buffer.from(pubKey, 'hex')).digest('hex');
48+
49+
/**
50+
* Compute a unique walletId from the keyAgent.
51+
*
52+
* @param keyAgent The key agent.
53+
*/
54+
export const getKeyAgentWalletId = async (keyAgent: AsyncKeyAgent): Promise<string> =>
55+
getExtendedAccountPublicKeyWalletId(await keyAgent.getExtendedAccountPublicKey());
56+
57+
/** Compute a unique walletId. */
58+
export const getWalletId = async (
59+
walletIdParam: AsyncKeyAgent | Cardano.Script | Crypto.Bip32PublicKeyHex
60+
): Promise<string> => {
61+
if (isScript(walletIdParam)) return getScriptWalletId(walletIdParam);
62+
63+
if (isBip32PublicKeyHex(walletIdParam)) return getExtendedAccountPublicKeyWalletId(walletIdParam);
64+
65+
return getKeyAgentWalletId(walletIdParam);
2866
};

packages/web-extension/test/walletManager/WalletRepository.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const storedLedgerWallet = {
2626
'ba4f80dea2632a17c99ae9d8b934abf02643db5426b889fef14709c85e294aa12ac1f1560a893ea7937c5bfbfdeab459b1a396f1174b9c5a673a640d01880c35'
2727
),
2828
type: WalletType.Ledger as const,
29-
walletId: Hash28ByteBase16('ad63f855e831d937457afc52a21a7f351137e4a9fff26c217817335a')
29+
walletId: 'bc10b0e8fdff359b389822d98d4def22'
3030
};
3131

3232
const createTrezorWalletProps = {
@@ -55,7 +55,7 @@ const createScriptWalletProps = {
5555
const storedScriptWallet = {
5656
...createScriptWalletProps,
5757
metadata: { friendlyName: 'Shared' },
58-
walletId: Serialization.Script.fromCore(createScriptWalletProps.script).hash()
58+
walletId: Serialization.Script.fromCore(createScriptWalletProps.script).hash().slice(32)
5959
};
6060

6161
describe('WalletRepository', () => {
@@ -133,11 +133,11 @@ describe('WalletRepository', () => {
133133
});
134134

135135
it('computes and returns WalletId for bip32 wallets', async () => {
136-
await expect(repository.addWallet(createTrezorWalletProps)).resolves.toHaveLength(56);
136+
await expect(repository.addWallet(createTrezorWalletProps)).resolves.toHaveLength(32);
137137
});
138138

139139
it('computes and returns WalletId for script wallets', async () => {
140-
await expect(repository.addWallet(createScriptWalletProps)).resolves.toHaveLength(56);
140+
await expect(repository.addWallet(createScriptWalletProps)).resolves.toHaveLength(32);
141141
});
142142
});
143143

Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as Crypto from '@cardano-sdk/crypto';
22
import { AsyncKeyAgent } from '@cardano-sdk/key-management';
3-
import { Cardano } from '@cardano-sdk/core';
3+
import { Cardano, Serialization } from '@cardano-sdk/core';
44

5+
import { HexBlob } from '@cardano-sdk/util';
56
import { getWalletId } from '../../src';
67

78
describe('getWalletId', () => {
@@ -22,27 +23,48 @@ describe('getWalletId', () => {
2223
);
2324
});
2425

25-
it('creates unique id for different networkId', async () => {
26+
it('can create unique id for key agents', async () => {
2627
const id1 = await getWalletId(mockKeyAgent);
27-
chainId.networkId = Cardano.NetworkId.Mainnet;
28+
pubKey = Crypto.Bip32PublicKeyHex(
29+
// eslint-disable-next-line max-len
30+
'4e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d'
31+
);
2832
const id2 = await getWalletId(mockKeyAgent);
2933
expect(id1).not.toEqual(id2);
3034
});
3135

32-
it('creates unique id for different networkMagic', async () => {
33-
const id1 = await getWalletId(mockKeyAgent);
34-
chainId.networkMagic = Cardano.NetworkMagics.Mainnet;
35-
const id2 = await getWalletId(mockKeyAgent);
36+
it('can create unique id for public keys', async () => {
37+
const id1 = await getWalletId(
38+
Crypto.Bip32PublicKeyHex(
39+
// eslint-disable-next-line max-len
40+
'3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d'
41+
)
42+
);
43+
const id2 = await getWalletId(
44+
Crypto.Bip32PublicKeyHex(
45+
// eslint-disable-next-line max-len
46+
'4e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d'
47+
)
48+
);
3649
expect(id1).not.toEqual(id2);
3750
});
3851

39-
it('create unique id for different public keys', async () => {
40-
const id1 = await getWalletId(mockKeyAgent);
41-
pubKey = Crypto.Bip32PublicKeyHex(
42-
// eslint-disable-next-line max-len
43-
'4e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d3e33018e8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d'
44-
);
45-
const id2 = await getWalletId(mockKeyAgent);
52+
it('can create unique id for scripts', async () => {
53+
const script = Serialization.Script.fromCbor(
54+
HexBlob(
55+
'82008202828200581cb275b08c999097247f7c17e77007c7010cd19f20cc086ad99d3985388201838205190bb88200581c966e394a544f242081e41d1965137b1bb412ac230d40ed5407821c378204190fa0'
56+
)
57+
).toCore();
58+
59+
const nativeScript: Cardano.Script = {
60+
__type: Cardano.ScriptType.Native,
61+
keyHash: Crypto.Ed25519KeyHashHex('b275b08c999097247f7c17e77007c7010cd19f20cc086ad99d398538'),
62+
kind: Cardano.NativeScriptKind.RequireSignature
63+
};
64+
65+
const id1 = await getWalletId(script);
66+
const id2 = await getWalletId(nativeScript);
67+
4668
expect(id1).not.toEqual(id2);
4769
});
4870
});

0 commit comments

Comments
 (0)