@avalix/chroma 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -103,35 +103,63 @@ async function getTalismanExtensionPath() {
103
103
  if (!fs.existsSync(extensionDir) || fs.readdirSync(extensionDir).length === 0) throw new Error(`Talisman extension not found at: ${extensionDir}\n\nPlease download the extension first by running:\n npx @avalix/chroma download-extensions\n`);
104
104
  return extensionDir;
105
105
  }
106
- async function importEthPrivateKey(page, { seed, name = "Test Account", password = "h3llop0lkadot!" }) {
106
+ async function findOnboardingPage(context, extensionId) {
107
+ const popupUrl = `chrome-extension://${extensionId}/dashboard.html`;
108
+ const newPage = await context.newPage();
109
+ await newPage.goto(popupUrl);
110
+ await newPage.waitForLoadState("domcontentloaded");
111
+ for (const p of context.pages()) if (p !== newPage && p.url().includes(`chrome-extension://${extensionId}/`)) await p.close();
112
+ return newPage;
113
+ }
114
+ async function completeOnboarding(extensionPage, password) {
115
+ await extensionPage.bringToFront();
116
+ await extensionPage.waitForLoadState("domcontentloaded");
117
+ if (await extensionPage.getByRole("button", { name: "Settings" }).isVisible()) {
118
+ await extensionPage.getByRole("button", { name: "Settings" }).click({ force: true });
119
+ return;
120
+ }
121
+ await extensionPage.getByTestId("onboarding-get-started-button").click();
122
+ await extensionPage.getByRole("textbox", { name: "Enter password" }).fill(password);
123
+ await extensionPage.getByRole("textbox", { name: "Confirm password" }).fill(password);
124
+ await extensionPage.getByTestId("onboarding-password-confirm-button").click();
125
+ await extensionPage.getByRole("button", { name: "No thanks" }).click();
126
+ await extensionPage.getByTestId("onboarding-enter-talisman-button").click();
127
+ const extensionId = extensionPage.url().match(/chrome-extension:\/\/([^/]+)/)?.[1];
128
+ await extensionPage.goto(`chrome-extension://${extensionId}/dashboard.html#/settings/general`);
129
+ await extensionPage.waitForLoadState("domcontentloaded");
130
+ await extensionPage.getByRole("link", { name: "Security & Privacy" }).click();
131
+ await extensionPage.getByTestId("component-toggle-button").first().click();
132
+ }
133
+ async function importPolkadotMnemonic(page, { seed, name = "Test Account", password = "h3llop0lkadot!" }) {
107
134
  const context = page.__extensionContext;
108
135
  const extensionId = page.__extensionId;
109
- const maxAttempts = 20;
110
- const retryDelay = 500;
111
- let extensionPage = null;
112
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
113
- const pages = context.pages();
114
- for (const p of pages) {
115
- const url = p.url();
116
- if (url.includes("onboarding.html") || url.includes(`chrome-extension://${extensionId}/`)) {
117
- extensionPage = p;
118
- break;
119
- }
120
- }
121
- if (extensionPage) break;
122
- if (attempt < maxAttempts - 1) await new Promise((resolve) => setTimeout(resolve, retryDelay));
136
+ const extensionPage = await findOnboardingPage(context, extensionId);
137
+ try {
138
+ await completeOnboarding(extensionPage, password);
139
+ await extensionPage.getByRole("link", { name: "Manage Accounts" }).click();
140
+ await extensionPage.getByRole("button", { name: "Get Started" }).click();
141
+ await extensionPage.getByRole("button", { name: "Add Account" }).click();
142
+ await extensionPage.getByRole("button", { name: "Import Import an existing" }).click();
143
+ await extensionPage.getByRole("button", { name: "Import via Recovery Phrase" }).click();
144
+ await extensionPage.getByRole("button", { name: "Polkadot Relay Chain, Asset" }).click();
145
+ await extensionPage.getByRole("textbox", { name: "Choose a name" }).fill(name);
146
+ await extensionPage.getByRole("textbox", { name: "Enter your 12 or 24 word" }).fill(seed);
147
+ await extensionPage.getByTestId("account-add-mnemonic-import-button").click();
148
+ await extensionPage.close();
149
+ } catch (error) {
150
+ console.error("❌ Error during Talisman Polkadot account import:", error);
151
+ throw error;
123
152
  }
124
- if (!extensionPage) throw new Error(`Talisman onboarding page not found after ${maxAttempts} attempts`);
153
+ }
154
+ async function importEthPrivateKey(page, { seed, name = "Test Account", password = "h3llop0lkadot!" }) {
155
+ const context = page.__extensionContext;
156
+ const extensionId = page.__extensionId;
157
+ const extensionPage = await findOnboardingPage(context, extensionId);
125
158
  try {
126
- await extensionPage.bringToFront();
127
- await extensionPage.waitForLoadState("domcontentloaded");
128
- await extensionPage.getByTestId("onboarding-get-started-button").click();
129
- await extensionPage.getByRole("textbox", { name: "Enter password" }).fill(password);
130
- await extensionPage.getByRole("textbox", { name: "Confirm password" }).fill(password);
131
- await extensionPage.getByTestId("onboarding-password-confirm-button").click();
132
- await extensionPage.getByRole("button", { name: "No thanks" }).click();
133
- await extensionPage.getByTestId("onboarding-enter-talisman-button").click();
134
- await extensionPage.getByRole("button", { name: "Add account Create or import" }).click();
159
+ await completeOnboarding(extensionPage, password);
160
+ await extensionPage.getByRole("link", { name: "Manage Accounts" }).click();
161
+ await extensionPage.getByRole("button", { name: "Get Started" }).click();
162
+ await extensionPage.getByRole("button", { name: "Add Account" }).click();
135
163
  await extensionPage.getByRole("button", { name: "Import Import an existing" }).click();
136
164
  await extensionPage.getByRole("button", { name: "Import via Private Key" }).click();
137
165
  await extensionPage.getByRole("button", { name: "Select account platform" }).click();
@@ -141,16 +169,20 @@ async function importEthPrivateKey(page, { seed, name = "Test Account", password
141
169
  await extensionPage.getByRole("button", { name: "Save" }).click();
142
170
  await extensionPage.close();
143
171
  } catch (error) {
144
- console.error("❌ Error during Talisman account import:", error);
172
+ console.error("❌ Error during Talisman Ethereum account import:", error);
145
173
  throw error;
146
174
  }
147
175
  }
148
176
  async function authorizeTalisman(page, options = {}) {
149
- const { accountName = "Test Account" } = options;
150
177
  const context = page.__extensionContext;
151
178
  const extensionId = page.__extensionId;
179
+ const { accountName = "Test Account" } = options;
152
180
  const extensionPopup = await findExtensionPopup(context, extensionId);
153
- await extensionPopup.getByRole("button", { name: accountName }).click();
181
+ await extensionPopup.waitForLoadState("domcontentloaded");
182
+ const accountButton = extensionPopup.getByRole("button", { name: accountName });
183
+ await accountButton.waitFor({ state: "visible" });
184
+ await accountButton.scrollIntoViewIfNeeded();
185
+ await accountButton.click({ force: true });
154
186
  await extensionPopup.getByTestId("connection-connect-button").click();
155
187
  try {
156
188
  await (await findExtensionPopup(context, extensionId)).getByRole("button", { name: "Approve" }).click();
@@ -160,23 +192,16 @@ async function approveTalismanTx(page) {
160
192
  const context = page.__extensionContext;
161
193
  const extensionId = page.__extensionId;
162
194
  const extensionPopup = await findExtensionPopup(context, extensionId);
163
- try {
164
- await extensionPopup.getByRole("button", { name: "Yes" }).click();
165
- } catch {
166
- console.log("No another popup found, skipping");
167
- }
195
+ if (await extensionPopup.getByRole("button", { name: "Yes" }).isVisible()) await extensionPopup.getByRole("button", { name: "Yes" }).click();
168
196
  await extensionPopup.getByRole("button", { name: "Approve" }).click();
169
197
  }
170
198
  async function rejectTalismanTx(page) {
171
199
  const context = page.__extensionContext;
172
200
  const extensionId = page.__extensionId;
173
- await (await findExtensionPopup(context, extensionId)).getByTestId("connection-reject-button").click();
201
+ const extensionPopup = await findExtensionPopup(context, extensionId);
202
+ await extensionPopup.getByTestId("connection-reject-button").or(extensionPopup.getByRole("button", { name: "Cancel" })).click();
174
203
  }
175
204
 
176
- //#endregion
177
- //#region src/context-playwright/types.ts
178
- const WALLET_TYPES = ["polkadot-js", "talisman"];
179
-
180
205
  //#endregion
181
206
  //#region src/context-playwright/wallet-factory.ts
182
207
  function createExtendedPage(page, context, extensionId) {
@@ -185,80 +210,58 @@ function createExtendedPage(page, context, extensionId) {
185
210
  extPage.__extensionId = extensionId;
186
211
  return extPage;
187
212
  }
188
- function createWalletInstance(walletType, extensionId, context) {
189
- let importedAccountName;
190
- const baseInstance = {
213
+ function createPolkadotJsWallet(extensionId, context) {
214
+ return {
191
215
  extensionId,
216
+ type: "polkadot-js",
192
217
  importMnemonic: async (options) => {
218
+ await importPolkadotJSAccount(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId), options);
219
+ },
220
+ authorize: async () => {
221
+ await authorizePolkadotJS(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId));
222
+ },
223
+ approveTx: async (options = {}) => {
224
+ await approvePolkadotJSTx(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId), options);
225
+ },
226
+ rejectTx: async () => {
227
+ await rejectPolkadotJSTx(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId));
228
+ }
229
+ };
230
+ }
231
+ function createTalismanWallet(extensionId, context) {
232
+ let importedAccountName;
233
+ return {
234
+ extensionId,
235
+ type: "talisman",
236
+ importPolkadotMnemonic: async (options) => {
193
237
  const extPage = createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId);
194
238
  importedAccountName = options.name || "Test Account";
195
- switch (walletType) {
196
- case "polkadot-js":
197
- await importPolkadotJSAccount(extPage, options);
198
- break;
199
- case "talisman": throw new Error("Talisman importMnemonic is not yet implemented.");
200
- default: throw new Error(`Unsupported wallet type: ${walletType}`);
201
- }
239
+ await importPolkadotMnemonic(extPage, options);
202
240
  },
203
- authorize: async (options = {}) => {
241
+ importEthPrivateKey: async (options) => {
204
242
  const extPage = createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId);
205
- const accountName = options.accountName || importedAccountName;
206
- switch (walletType) {
207
- case "polkadot-js":
208
- await authorizePolkadotJS(extPage);
209
- break;
210
- case "talisman":
211
- await authorizeTalisman(extPage, { accountName });
212
- break;
213
- default: throw new Error(`Unsupported wallet type: ${walletType}`);
214
- }
243
+ importedAccountName = options.name || "Test Account";
244
+ await importEthPrivateKey(extPage, {
245
+ seed: options.privateKey,
246
+ name: options.name,
247
+ password: options.password
248
+ });
215
249
  },
216
- approveTx: async (options = {}) => {
217
- const extPage = createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId);
218
- switch (walletType) {
219
- case "polkadot-js":
220
- await approvePolkadotJSTx(extPage, options);
221
- break;
222
- case "talisman":
223
- await approveTalismanTx(extPage);
224
- break;
225
- default: throw new Error(`Unsupported wallet type: ${walletType}`);
226
- }
250
+ authorize: async (options = {}) => {
251
+ await authorizeTalisman(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId), { accountName: options.accountName || importedAccountName });
252
+ },
253
+ approveTx: async () => {
254
+ await approveTalismanTx(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId));
227
255
  },
228
256
  rejectTx: async () => {
229
- const extPage = createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId);
230
- switch (walletType) {
231
- case "polkadot-js":
232
- await rejectPolkadotJSTx(extPage);
233
- break;
234
- case "talisman":
235
- await rejectTalismanTx(extPage);
236
- break;
237
- default: throw new Error(`Unsupported wallet type: ${walletType}`);
238
- }
257
+ await rejectTalismanTx(createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId));
239
258
  }
240
259
  };
241
- switch (walletType) {
242
- case "polkadot-js": return {
243
- ...baseInstance,
244
- type: "polkadot-js"
245
- };
246
- case "talisman": return {
247
- ...baseInstance,
248
- type: "talisman",
249
- importEthPrivateKey: async (options) => {
250
- const extPage = createExtendedPage(context.pages()[0] || await context.newPage(), context, extensionId);
251
- importedAccountName = options.name || "Test Account";
252
- await importEthPrivateKey(extPage, {
253
- seed: options.privateKey,
254
- name: options.name,
255
- password: options.password
256
- });
257
- }
258
- };
259
- default: throw new Error(`Unsupported wallet type: ${walletType}`);
260
- }
261
260
  }
261
+ const walletFactories = {
262
+ "polkadot-js": createPolkadotJsWallet,
263
+ "talisman": createTalismanWallet
264
+ };
262
265
 
263
266
  //#endregion
264
267
  //#region src/context-playwright/index.ts
@@ -306,7 +309,10 @@ function createWalletTest(options = {}) {
306
309
  },
307
310
  wallets: async ({ walletContext, walletExtensionIds }, use) => {
308
311
  const walletMap = {};
309
- for (const [walletType, extensionId] of walletExtensionIds) if (WALLET_TYPES.includes(walletType)) walletMap[walletType] = createWalletInstance(walletType, extensionId, walletContext);
312
+ for (const [walletType, extensionId] of walletExtensionIds) {
313
+ const factory = walletFactories[walletType];
314
+ if (factory) walletMap[walletType] = factory(extensionId, walletContext);
315
+ }
310
316
  await use(walletMap);
311
317
  }
312
318
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@avalix/chroma",
3
3
  "type": "module",
4
- "version": "0.0.10",
4
+ "version": "0.0.12",
5
5
  "description": "End-to-end testing library for Polkadot wallet interactions",
6
6
  "author": "Avalix Labs",
7
7
  "license": "MIT",
@@ -44,7 +44,11 @@
44
44
  "lint": "eslint --fix .",
45
45
  "prepublishOnly": "npm run build",
46
46
  "download-extensions": "rm -rf .chroma && tsx scripts/download-extensions.ts",
47
- "test": "playwright test --ui"
47
+ "test": "playwright test",
48
+ "test:ui": "playwright test --ui",
49
+ "test:unit": "vitest",
50
+ "test:unit:run": "vitest run",
51
+ "test:unit:coverage": "vitest run --coverage"
48
52
  },
49
53
  "peerDependencies": {
50
54
  "@playwright/test": "^1.57.0"
@@ -58,8 +62,9 @@
58
62
  "@types/node": "^24.10.2",
59
63
  "@types/unzipper": "^0.10.11",
60
64
  "eslint": "^9.39.1",
61
- "tsdown": "latest",
62
- "tsx": "^4.21.0"
65
+ "tsdown": "^0.20.1",
66
+ "tsx": "^4.21.0",
67
+ "vitest": "^4.0.18"
63
68
  },
64
69
  "publishConfig": {
65
70
  "access": "public"
@@ -19,15 +19,15 @@ async function clearChromaDir(): Promise<void> {
19
19
  const chromaDir = path.resolve(process.cwd(), '.chroma')
20
20
 
21
21
  if (fs.existsSync(chromaDir)) {
22
- console.log('🗑️ Clearing existing .chroma directory...')
22
+ console.log('🗑️ Clearing existing .chroma directory...')
23
23
  await fs.promises.rm(chromaDir, { recursive: true, force: true })
24
24
  }
25
25
  }
26
26
 
27
27
  async function main() {
28
28
  const version = await getVersion()
29
- console.log(`🎨 Chroma v${version}\n`)
30
- console.log('🚀 Downloading wallet extensions...\n')
29
+ console.log(`\n🎨 Chroma v${version}`)
30
+ console.log('🚀 Downloading wallet extensions...')
31
31
 
32
32
  try {
33
33
  // Clear existing .chroma directory
@@ -4,16 +4,13 @@ import type {
4
4
  ExtendedPage,
5
5
  WalletConfig,
6
6
  WalletFixtures,
7
- WalletInstance,
8
7
  Wallets,
9
- WalletType,
10
8
  WalletWorkerFixtures,
11
9
  } from './types.js'
12
10
  import { test as base, chromium } from '@playwright/test'
13
11
  import { getPolkadotJSExtensionPath } from '../wallets/polkadot-js.js'
14
12
  import { getTalismanExtensionPath } from '../wallets/talisman.js'
15
- import { WALLET_TYPES } from './types.js'
16
- import { createWalletInstance } from './wallet-factory.js'
13
+ import { walletFactories } from './wallet-factory.js'
17
14
 
18
15
  // Helper function to get extension path for a wallet config
19
16
  async function getExtensionPathForWallet(config: WalletConfig): Promise<string> {
@@ -117,17 +114,17 @@ export function createWalletTest<const T extends readonly WalletConfig[]>(
117
114
 
118
115
  // Wallet instances for each configured wallet
119
116
  wallets: async ({ walletContext, walletExtensionIds }, use) => {
120
- const walletMap: Partial<ExpectedWallets> = {}
117
+ const walletMap = {} as ExpectedWallets
121
118
 
122
119
  // Create wallet instance for each configured wallet
123
120
  for (const [walletType, extensionId] of walletExtensionIds) {
124
- if (WALLET_TYPES.includes(walletType as WalletType)) {
125
- const instance = createWalletInstance(walletType, extensionId, walletContext);
126
- (walletMap as Record<string, WalletInstance>)[walletType] = instance
121
+ const factory = walletFactories[walletType as keyof typeof walletFactories]
122
+ if (factory) {
123
+ walletMap[walletType as keyof ExpectedWallets] = factory(extensionId, walletContext) as ExpectedWallets[keyof ExpectedWallets]
127
124
  }
128
125
  }
129
126
 
130
- await use(walletMap as ExpectedWallets)
127
+ await use(walletMap)
131
128
  },
132
129
  })
133
130
  }
@@ -1,11 +1,16 @@
1
1
  import type { BrowserContext, Page } from '@playwright/test'
2
+ import type {
3
+ PolkadotJsWalletInstance,
4
+ TalismanWalletInstance,
5
+ WalletInstance,
6
+ } from './wallet-factory.js'
7
+
8
+ // Re-export wallet instance types
9
+ export type { PolkadotJsWalletInstance, TalismanWalletInstance, WalletInstance }
2
10
 
3
11
  // Wallet types - single source of truth
4
12
  export type WalletType = 'polkadot-js' | 'talisman'
5
13
 
6
- // Available wallet types as constant array
7
- export const WALLET_TYPES: readonly WalletType[] = ['polkadot-js', 'talisman'] as const
8
-
9
14
  // Wallet account configuration
10
15
  export interface WalletAccount {
11
16
  seed: string
@@ -19,29 +24,6 @@ export interface WalletConfig {
19
24
  downloadUrl?: string
20
25
  }
21
26
 
22
- // Base wallet instance - common methods for all wallets
23
- export interface BaseWalletInstance {
24
- extensionId: string
25
- importMnemonic: (options: WalletAccount) => Promise<void>
26
- authorize: (options?: { accountName?: string }) => Promise<void>
27
- approveTx: (options?: { password?: string }) => Promise<void>
28
- rejectTx: () => Promise<void>
29
- }
30
-
31
- // Polkadot-JS specific wallet instance
32
- export interface PolkadotJsWalletInstance extends BaseWalletInstance {
33
- type: 'polkadot-js'
34
- }
35
-
36
- // Talisman specific wallet instance (with additional methods)
37
- export interface TalismanWalletInstance extends BaseWalletInstance {
38
- type: 'talisman'
39
- importEthPrivateKey: (options: { privateKey: string, name?: string, password?: string }) => Promise<void>
40
- }
41
-
42
- // Union type of all wallet instances
43
- export type WalletInstance = PolkadotJsWalletInstance | TalismanWalletInstance
44
-
45
27
  // Map wallet type to its instance
46
28
  export interface WalletTypeMap {
47
29
  'polkadot-js': PolkadotJsWalletInstance
@@ -1,11 +1,5 @@
1
1
  import type { BrowserContext, Page } from '@playwright/test'
2
- import type {
3
- BaseWalletInstance,
4
- PolkadotJsWalletInstance,
5
- TalismanWalletInstance,
6
- WalletAccount,
7
- WalletInstance,
8
- } from './types.js'
2
+ import type { WalletAccount } from './types.js'
9
3
  import {
10
4
  approvePolkadotJSTx,
11
5
  authorizePolkadotJS,
@@ -16,6 +10,7 @@ import {
16
10
  approveTalismanTx,
17
11
  authorizeTalisman,
18
12
  importEthPrivateKey,
13
+ importPolkadotMnemonic,
19
14
  rejectTalismanTx,
20
15
  } from '../wallets/talisman.js'
21
16
 
@@ -27,114 +22,83 @@ function createExtendedPage(page: Page, context: BrowserContext, extensionId: st
27
22
  return extPage
28
23
  }
29
24
 
30
- // Create wallet instance helper with proper typing
31
- export function createWalletInstance(
32
- walletType: string,
33
- extensionId: string,
34
- context: BrowserContext,
35
- ): WalletInstance {
36
- // Store the imported account name for later use
37
- let importedAccountName: string | undefined
38
-
39
- // Common methods for all wallets
40
- const baseInstance: BaseWalletInstance = {
25
+ // Factory function for Polkadot-JS wallet
26
+ export function createPolkadotJsWallet(extensionId: string, context: BrowserContext) {
27
+ return {
41
28
  extensionId,
29
+ type: 'polkadot-js' as const,
42
30
  importMnemonic: async (options: WalletAccount) => {
43
31
  const page = context.pages()[0] || await context.newPage()
44
32
  const extPage = createExtendedPage(page, context, extensionId)
33
+ await importPolkadotJSAccount(extPage, options)
34
+ },
35
+ authorize: async () => {
36
+ const page = context.pages()[0] || await context.newPage()
37
+ const extPage = createExtendedPage(page, context, extensionId)
38
+ await authorizePolkadotJS(extPage)
39
+ },
40
+ approveTx: async (options: { password?: string } = {}) => {
41
+ const page = context.pages()[0] || await context.newPage()
42
+ const extPage = createExtendedPage(page, context, extensionId)
43
+ await approvePolkadotJSTx(extPage, options)
44
+ },
45
+ rejectTx: async () => {
46
+ const page = context.pages()[0] || await context.newPage()
47
+ const extPage = createExtendedPage(page, context, extensionId)
48
+ await rejectPolkadotJSTx(extPage)
49
+ },
50
+ }
51
+ }
45
52
 
46
- // Store the account name for future authorize calls
47
- importedAccountName = options.name || 'Test Account'
53
+ // Factory function for Talisman wallet
54
+ export function createTalismanWallet(extensionId: string, context: BrowserContext) {
55
+ let importedAccountName: string | undefined
48
56
 
49
- switch (walletType) {
50
- case 'polkadot-js':
51
- await importPolkadotJSAccount(extPage, options)
52
- break
53
- case 'talisman':
54
- throw new Error('Talisman importMnemonic is not yet implemented.')
55
- default:
56
- throw new Error(`Unsupported wallet type: ${walletType}`)
57
- }
57
+ return {
58
+ extensionId,
59
+ type: 'talisman' as const,
60
+ importPolkadotMnemonic: async (options: WalletAccount) => {
61
+ const page = context.pages()[0] || await context.newPage()
62
+ const extPage = createExtendedPage(page, context, extensionId)
63
+ importedAccountName = options.name || 'Test Account'
64
+ await importPolkadotMnemonic(extPage, options)
65
+ },
66
+ importEthPrivateKey: async (options: { privateKey: string, name?: string, password?: string }) => {
67
+ const page = context.pages()[0] || await context.newPage()
68
+ const extPage = createExtendedPage(page, context, extensionId)
69
+ importedAccountName = options.name || 'Test Account'
70
+ await importEthPrivateKey(extPage, {
71
+ seed: options.privateKey,
72
+ name: options.name,
73
+ password: options.password,
74
+ })
58
75
  },
59
76
  authorize: async (options: { accountName?: string } = {}) => {
60
77
  const page = context.pages()[0] || await context.newPage()
61
78
  const extPage = createExtendedPage(page, context, extensionId)
62
-
63
- // Use provided account name or fall back to the imported one
64
79
  const accountName = options.accountName || importedAccountName
65
-
66
- switch (walletType) {
67
- case 'polkadot-js':
68
- await authorizePolkadotJS(extPage)
69
- break
70
- case 'talisman':
71
- await authorizeTalisman(extPage, { accountName })
72
- break
73
- default:
74
- throw new Error(`Unsupported wallet type: ${walletType}`)
75
- }
80
+ await authorizeTalisman(extPage, { accountName })
76
81
  },
77
- approveTx: async (options: { password?: string } = {}) => {
82
+ approveTx: async () => {
78
83
  const page = context.pages()[0] || await context.newPage()
79
84
  const extPage = createExtendedPage(page, context, extensionId)
80
-
81
- switch (walletType) {
82
- case 'polkadot-js':
83
- await approvePolkadotJSTx(extPage, options)
84
- break
85
- case 'talisman':
86
- await approveTalismanTx(extPage)
87
- break
88
- default:
89
- throw new Error(`Unsupported wallet type: ${walletType}`)
90
- }
85
+ await approveTalismanTx(extPage)
91
86
  },
92
87
  rejectTx: async () => {
93
88
  const page = context.pages()[0] || await context.newPage()
94
89
  const extPage = createExtendedPage(page, context, extensionId)
95
-
96
- switch (walletType) {
97
- case 'polkadot-js':
98
- await rejectPolkadotJSTx(extPage)
99
- break
100
- case 'talisman':
101
- await rejectTalismanTx(extPage)
102
- break
103
- default:
104
- throw new Error(`Unsupported wallet type: ${walletType}`)
105
- }
90
+ await rejectTalismanTx(extPage)
106
91
  },
107
92
  }
93
+ }
108
94
 
109
- // Return wallet-specific instance with type discriminator
110
- switch (walletType) {
111
- case 'polkadot-js':
112
- return {
113
- ...baseInstance,
114
- type: 'polkadot-js',
115
- } as PolkadotJsWalletInstance
116
-
117
- case 'talisman':
118
- return {
119
- ...baseInstance,
120
- type: 'talisman',
121
- importEthPrivateKey: async (options: { privateKey: string, name?: string, password?: string }) => {
122
- const page = context.pages()[0] || await context.newPage()
123
- const extPage = createExtendedPage(page, context, extensionId)
124
-
125
- // Store the account name for future authorize calls
126
- importedAccountName = options.name || 'Test Account'
127
-
128
- // Use the seed property to pass the private key
129
- await importEthPrivateKey(extPage, {
130
- seed: options.privateKey,
131
- name: options.name,
132
- password: options.password,
133
- })
134
- },
135
- } as TalismanWalletInstance
136
-
137
- default:
138
- throw new Error(`Unsupported wallet type: ${walletType}`)
139
- }
95
+ // Wallet factories map - auto-inferred types
96
+ export const walletFactories = {
97
+ 'polkadot-js': createPolkadotJsWallet,
98
+ 'talisman': createTalismanWallet,
140
99
  }
100
+
101
+ // Auto-inferred types from factory functions
102
+ export type PolkadotJsWalletInstance = ReturnType<typeof createPolkadotJsWallet>
103
+ export type TalismanWalletInstance = ReturnType<typeof createTalismanWallet>
104
+ export type WalletInstance = PolkadotJsWalletInstance | TalismanWalletInstance