Skip to content

Commit 4eca7d1

Browse files
committed
feat: add cip142 support to dapp-connector
1 parent 62010d2 commit 4eca7d1

File tree

8 files changed

+80
-15
lines changed

8 files changed

+80
-15
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', () => {

yarn-project.nix

+3-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ cacheEntries = {
441441
"@emurgo/cip14-js@npm:3.0.1" = { filename = "@emurgo-cip14-js-npm-3.0.1-6011030ea2-9eaf312410.zip"; sha512 = "9eaf3124108e8c252a745de9ef1f334ab26a32271077b00fe0ea2a06e40838dd435165dac523ebd4d851ae7a94d8c56766dabc372aabffedd36551c798c607c5"; };
442442
"@endemolshinegroup/cosmiconfig-typescript-loader@npm:3.0.2" = { filename = "@endemolshinegroup-cosmiconfig-typescript-loader-npm-3.0.2-97436e68fc-7fe0198622.zip"; sha512 = "7fe0198622b1063c40572034df7e8ba867865a1b4815afe230795929abcf785758b34d7806a8e2100ba8ab4e92c5a1c3e11a980c466c4406df6e7ec6e50df8b6"; };
443443
"@es-joy/jsdoccomment@npm:0.10.8" = { filename = "@es-joy-jsdoccomment-npm-0.10.8-d03c65b162-3e144ef393.zip"; sha512 = "3e144ef393459a541b64f6c9c8e62fb6d9b47e1a2c626410487ede12c472064f6ce6e0911df60b42ccf126d5a66102707eef59ca14767cb7aeb5e608b227558d"; };
444-
"@esbuild/linux-x64@npm:0.21.5" = { filename = "@esbuild-linux-x64-npm-0.21.5-88079726c4-8.zip"; sha512 = "91c202dca064909b2c56522f98e3a3b24bc5d43405506b4e67923ecb5d0cc2b78dcee8d815f705d71395402f8532670a391777a3cf6a08894049e453becf07a0"; };
444+
"@esbuild/darwin-arm64@npm:0.21.5" = { filename = "@esbuild-darwin-arm64-npm-0.21.5-62349c1520-8.zip"; sha512 = "50d5d633be3d0fe0fce54c4740171ae6d2e8f5220280a6f6996f234c718de25535e50a31cee1745b5b80f2cc9e336c42c7fc2b49f3ea38b5f3ff5d8c97ef4123"; };
445445
"@eslint/eslintrc@npm:0.4.3" = { filename = "@eslint-eslintrc-npm-0.4.3-ee1bbcab87-03a7704150.zip"; sha512 = "03a7704150b868c318aab6a94d87a33d30dc2ec579d27374575014f06237ba1370ae11178db772f985ef680d469dc237e7b16a1c5d8edaaeb8c3733e7a95a6d3"; };
446446
"@ethereumjs/common@npm:4.4.0" = { filename = "@ethereumjs-common-npm-4.4.0-ee991f5124-6b8cbfcfb5.zip"; sha512 = "6b8cbfcfb5bdde839545c89dce3665706733260e26455d0eb3bcbc3c09e371ae629d51032b95d86f2aeeb15325244a6622171f9005165266fefd923eaa99f1c5"; };
447447
"@ethereumjs/rlp@npm:5.0.2" = { filename = "@ethereumjs-rlp-npm-5.0.2-72fb389b37-b569061ddb.zip"; sha512 = "b569061ddb1f4cf56a82f7a677c735ba37f9e94e2bbaf567404beb9e2da7aa1f595e72fc12a17c61f7aec67fd5448443efe542967c685a2fe0ffc435793dcbab"; };
@@ -1461,6 +1461,8 @@ cacheEntries = {
14611461
"fs.realpath@npm:1.0.0" = { filename = "fs.realpath-npm-1.0.0-c8f05d8126-99ddea01a7.zip"; sha512 = "99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0"; };
14621462
"fsevents@npm:2.3.2" = { filename = "fsevents-npm-2.3.2-a881d6ac9f-97ade64e75.zip"; sha512 = "97ade64e75091afee5265e6956cb72ba34db7819b4c3e94c431d4be2b19b8bb7a2d4116da417950c3425f17c8fe693d25e20212cac583ac1521ad066b77ae31f"; };
14631463
"fsevents@npm:2.3.3" = { filename = "fsevents-npm-2.3.3-ce9fb0ffae-11e6ea6fea.zip"; sha512 = "11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317"; };
1464+
"fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::version=2.3.2&hash=18f3a7" = { filename = "fsevents-patch-3340e2eb10-8.zip"; sha512 = "edbd0fd80be379c14409605f77e52fdc78a119e17f875e8b90a220c3e5b29e54a1477c21d91fd30b957ea4866406dc3ff87b61432d2840ff8866b309e5866140"; };
1465+
"fsevents@patch:fsevents@npm%3A2.3.3#~builtin<compat/fsevents>::version=2.3.3&hash=18f3a7" = { filename = "fsevents-patch-7934e3c202-8.zip"; sha512 = "4639e24e2774cbd3669bd08521e0eeeb9d05bbabffdfdee418cc75a237660bc2fb30520a266ad5379199e2d657f430dd4236ad3642674ef32f20cc7258506725"; };
14641466
"ftp@npm:0.3.10" = { filename = "ftp-npm-0.3.10-348fb9ac23-ddd313c1d4.zip"; sha512 = "ddd313c1d44eb7429f3a7d77a0155dc8fe86a4c64dca58f395632333ce4b4e74c61413c6e0ef66ea3f3d32d905952fbb6d028c7117d522f793eb1fa282e17357"; };
14651467
"function-bind@npm:1.1.1" = { filename = "function-bind-npm-1.1.1-b56b322ae9-b32fbaebb3.zip"; sha512 = "b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a"; };
14661468
"function.prototype.name@npm:1.1.5" = { filename = "function.prototype.name-npm-1.1.5-e776a642bb-acd21d733a.zip"; sha512 = "acd21d733a9b649c2c442f067567743214af5fa248dbeee69d8278ce7df3329ea5abac572be9f7470b4ec1cd4d8f1040e3c5caccf98ebf2bf861a0deab735c27"; };

0 commit comments

Comments
 (0)