Skip to content

Commit d134dd8

Browse files
authored
feat: add cip142 support to dapp-connector (#1607)
1 parent d15a044 commit d134dd8

File tree

7 files changed

+77
-14
lines changed

7 files changed

+77
-14
lines changed

packages/dapp-connector/src/WalletApi/Cip30Wallet.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { APIErrorCode, ApiError } from '../errors';
22
import {
33
Bytes,
44
Cbor,
5+
Cip142WalletApi,
56
Cip30WalletApiWithPossibleExtensions,
7+
Cip95WalletApi,
68
CipExtensionApis,
79
Paginate,
810
WalletApi,
@@ -28,7 +30,8 @@ export const CipMethodsMapping: Record<number, WalletMethod[]> = {
2830
'signData',
2931
'submitTx'
3032
],
31-
95: ['getRegisteredPubStakeKeys', 'getUnregisteredPubStakeKeys', 'getPubDRepKey', 'signData']
33+
95: ['getRegisteredPubStakeKeys', 'getUnregisteredPubStakeKeys', 'getPubDRepKey', 'signData'],
34+
142: ['getNetworkMagic']
3235
};
3336
export const WalletApiMethodNames: WalletMethod[] = Object.values(CipMethodsMapping).flat();
3437

@@ -79,7 +82,7 @@ export class Cip30Wallet {
7982
readonly name: WalletName;
8083
readonly icon: WalletIcon;
8184
/** Support the full api by default */
82-
readonly supportedExtensions: WalletApiExtension[] = [{ cip: 95 }];
85+
readonly supportedExtensions: WalletApiExtension[] = [{ cip: 95 }, { cip: 142 }];
8386

8487
readonly #logger: Logger;
8588
readonly #api: WalletApi;
@@ -195,14 +198,17 @@ export class Cip30Wallet {
195198
getUnregisteredPubStakeKeys: () => walletApi.getUnregisteredPubStakeKeys(),
196199
signData: (addr: Cardano.PaymentAddress | Cardano.RewardAccount | Bytes, payload: Bytes) =>
197200
walletApi.signData(addr, payload)
201+
},
202+
cip142: {
203+
getNetworkMagic: () => walletApi.getNetworkMagic()
198204
}
199205
};
200206

201207
if (enabledExtensions) {
202208
for (const extension of enabledExtensions) {
203209
const cipName = `cip${extension.cip}` as keyof CipExtensionApis;
204210
if (additionalCipApis[cipName]) {
205-
baseApi[cipName] = additionalCipApis[cipName];
211+
baseApi[cipName] = additionalCipApis[cipName] as Cip95WalletApi & Cip142WalletApi;
206212
}
207213
}
208214
}

packages/dapp-connector/src/WalletApi/types.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,16 @@ export interface Cip95WalletApi {
206206
signData: SignData;
207207
}
208208

209-
export type WalletApi = Cip30WalletApi & Cip95WalletApi;
209+
export interface Cip142WalletApi {
210+
getNetworkMagic: () => Promise<Cardano.NetworkMagics>;
211+
}
212+
213+
export type WalletApi = Cip30WalletApi & Cip95WalletApi & Cip142WalletApi;
210214
export type WalletMethod = keyof WalletApi;
211215

212216
export interface CipExtensionApis {
213217
cip95: Cip95WalletApi;
218+
cip142: Cip142WalletApi;
214219
}
215220

216221
export type Cip30WalletApiWithPossibleExtensions = Cip30WalletApi & Partial<CipExtensionApis>;

packages/dapp-connector/test/WalletApi/Cip30Wallet.test.ts

+32-6
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('Wallet', () => {
5353
expect(wallet.apiVersion).toBe('0.1.0');
5454
expect(typeof wallet.name).toBe('string');
5555
expect(wallet.name).toBe(testWallet.properties.walletName);
56-
expect(wallet.supportedExtensions).toEqual<WalletApiExtension[]>([{ cip: 95 }]);
56+
expect(wallet.supportedExtensions).toEqual<WalletApiExtension[]>([{ cip: 95 }, { cip: 142 }]);
5757
expect(typeof wallet.isEnabled).toBe('function');
5858
const isEnabled = await wallet.isEnabled();
5959
expect(typeof isEnabled).toBe('boolean');
@@ -98,6 +98,30 @@ describe('Wallet', () => {
9898
expect(await api.getExtensions()).toEqual([{ cip: 95 }]);
9999
});
100100

101+
test('with cip142 extension', async () => {
102+
const api = await wallet.enable({ extensions: [{ cip: 142 }] });
103+
expect(typeof api).toBe('object');
104+
const methods = new Set(Object.keys(api));
105+
expect(methods).toEqual(new Set([...CipMethodsMapping[30], 'cip142', 'experimental']));
106+
const cip142Methods = new Set(Object.keys(api.cip142!));
107+
expect(cip142Methods).toEqual(new Set(CipMethodsMapping[142]));
108+
expect(await wallet.isEnabled()).toBe(true);
109+
expect(await api.getExtensions()).toEqual([{ cip: 142 }]);
110+
});
111+
112+
test('with cip95 and cip142 extensions', async () => {
113+
const api = await wallet.enable({ extensions: [{ cip: 95 }, { cip: 142 }] });
114+
expect(typeof api).toBe('object');
115+
const methods = new Set(Object.keys(api));
116+
expect(methods).toEqual(new Set([...CipMethodsMapping[30], 'cip95', 'cip142', 'experimental']));
117+
const cip95Methods = new Set(Object.keys(api.cip95!));
118+
expect(cip95Methods).toEqual(new Set(CipMethodsMapping[95]));
119+
const cip142Methods = new Set(Object.keys(api.cip142!));
120+
expect(cip142Methods).toEqual(new Set(CipMethodsMapping[142]));
121+
expect(await wallet.isEnabled()).toBe(true);
122+
expect(await api.getExtensions()).toEqual([{ cip: 95 }, { cip: 142 }]);
123+
});
124+
101125
test('no extensions wallet cannot enable cip95 extension', async () => {
102126
const api = await walletNoExtensions.enable({ extensions: [{ cip: 95 }] });
103127
expect(await walletNoExtensions.isEnabled()).toBe(true);
@@ -112,13 +136,15 @@ describe('Wallet', () => {
112136
expect(await wallet.isEnabled()).toBe(true);
113137
expect(await cip30api.getExtensions()).toEqual([]);
114138

115-
const cip95api = await wallet.enable({ extensions: [{ cip: 95 }] });
116-
const cip95methods = new Set(Object.keys(cip95api));
117-
expect(cip95methods).toEqual(new Set([...CipMethodsMapping[30], 'cip95', 'experimental']));
118-
const cip95InnerMethods = new Set(Object.keys(cip95api.cip95!));
139+
const apiWithExtension = await wallet.enable({ extensions: [{ cip: 95 }, { cip: 142 }] });
140+
const cip95methods = new Set(Object.keys(apiWithExtension));
141+
expect(cip95methods).toEqual(new Set([...CipMethodsMapping[30], 'cip95', 'cip142', 'experimental']));
142+
const cip95InnerMethods = new Set(Object.keys(apiWithExtension.cip95!));
119143
expect(cip95InnerMethods).toEqual(new Set(CipMethodsMapping[95]));
144+
const cip142Methods = new Set(Object.keys(apiWithExtension.cip142!));
145+
expect(cip142Methods).toEqual(new Set(CipMethodsMapping[142]));
120146
expect(await wallet.isEnabled()).toBe(true);
121-
expect(await cip95api.getExtensions()).toEqual([{ cip: 95 }]);
147+
expect(await apiWithExtension.getExtensions()).toEqual([{ cip: 95 }, { cip: 142 }]);
122148
});
123149

124150
test('unsupported extensions does not reject and returns cip30 methods', async () => {

packages/dapp-connector/test/testWallet.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { Cardano, Serialization } from '@cardano-sdk/core';
2-
import { Cip30DataSignature, WalletApi, WalletProperties } from '../src/WalletApi';
2+
import { Cip30DataSignature, RemoteAuthenticator, WalletApi, WalletProperties } from '../src';
33
import { Ed25519PublicKeyHex } from '@cardano-sdk/crypto';
4-
import { RemoteAuthenticator } from '../src';
54

65
export const api = <WalletApi>{
76
getBalance: async () => '100',
87
getChangeAddress: async () => 'change-address',
98
getCollateral: async () => null,
109
getExtensions: async () => [{ cip: 95 }],
1110
getNetworkId: async () => 0,
11+
getNetworkMagic: async () => Cardano.NetworkMagics.Preprod,
1212
getPubDRepKey: async () => 'getPubDRepKey' as Ed25519PublicKeyHex,
1313
getRegisteredPubStakeKeys: async () =>
1414
['registeredPubStakeKey-1', 'registeredPubStakeKey-2'] as Ed25519PublicKeyHex[],

packages/e2e/test/web-extension/extension/stubWalletApi.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ export const stubWalletApi: WalletApi = {
2626
}
2727
]
2828
]),
29-
getExtensions: async () => [{ cip: 95 }],
29+
getExtensions: async () => [{ cip: 95 }, { cip: 142 }],
3030
getNetworkId: async () => 0,
31+
getNetworkMagic: async () => Cardano.NetworkMagics.Mainnet,
3132
getPubDRepKey: async () => Ed25519PublicKeyHex('deeb8f82f2af5836ebbc1b450b6dbf0b03c93afe5696f10d49e8a8304ebfac01'),
3233
getRegisteredPubStakeKeys: async () => [
3334
Ed25519PublicKeyHex('deeb8f82f2af5836ebbc1b450b6dbf0b03c93afe5696f10d49e8a8304ebfac01')

packages/wallet/src/cip30.ts

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
ApiError,
44
Bytes,
55
Cbor,
6+
Cip142WalletApi,
67
Cip30DataSignature,
78
Cip95WalletApi,
89
DataSignError,
@@ -573,11 +574,28 @@ const extendedCip95WalletApi = (
573574
}
574575
});
575576

577+
const extendedCip142WalletApi = (
578+
wallet$: Observable<ObservableWallet>,
579+
{ logger }: Cip30WalletDependencies
580+
): Cip142WalletApi => ({
581+
getNetworkMagic: async () => {
582+
try {
583+
const wallet = await firstValueFrom(wallet$);
584+
const genesisParameters = await firstValueFrom(wallet.genesisParameters$);
585+
return genesisParameters.networkMagic;
586+
} catch (error) {
587+
logger.error(error);
588+
throw new ApiError(APIErrorCode.InternalError, formatUnknownError(error));
589+
}
590+
}
591+
});
592+
576593
export const createWalletApi = (
577594
wallet$: Observable<ObservableWallet>,
578595
confirmationCallback: CallbackConfirmation,
579596
{ logger }: Cip30WalletDependencies
580597
): WithSenderContext<WalletApi> => ({
581598
...baseCip30WalletApi(wallet$, confirmationCallback, { logger }),
582-
...extendedCip95WalletApi(wallet$, { logger })
599+
...extendedCip95WalletApi(wallet$, { logger }),
600+
...extendedCip142WalletApi(wallet$, { logger })
583601
});

packages/wallet/test/integration/cip30mapping.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,13 @@ describe('cip30', () => {
753753
const extensions = await api.getExtensions(context);
754754
expect(extensions).toEqual([{ cip: 95 }]);
755755
});
756+
757+
describe('api.getNetworkMagic', () => {
758+
it('returns the network magic', async () => {
759+
const networkMagic = await api.getNetworkMagic(context);
760+
expect(networkMagic).toEqual(Cardano.NetworkMagics.Mainnet);
761+
});
762+
});
756763
});
757764

758765
describe('confirmation callbacks', () => {

0 commit comments

Comments
 (0)