@tobelabs/chainwright 0.6.1-alpha.0 → 0.6.1-alpha.2
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/core/index.d.ts +1 -1
- package/dist/{types-dJRYhQT9.d.ts → types-COvLLLoP.d.ts} +3 -1
- package/dist/wallets/index.d.ts +20 -961
- package/dist/wallets/index.js +1 -16
- package/dist/wallets/keplr/index.d.ts +152 -0
- package/dist/wallets/keplr/index.js +3 -0
- package/dist/wallets/metamask/index.d.ts +203 -0
- package/dist/wallets/metamask/index.js +3 -0
- package/dist/wallets/meteor/index.d.ts +150 -0
- package/dist/wallets/meteor/index.js +7 -0
- package/dist/wallets/petra/index.d.ts +157 -0
- package/dist/wallets/petra/index.js +3 -0
- package/dist/wallets/phantom/index.d.ts +195 -0
- package/dist/wallets/phantom/index.js +3 -0
- package/dist/wallets/solflare/index.d.ts +142 -0
- package/dist/wallets/solflare/index.js +2 -0
- package/package.json +26 -4
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import * as _playwright_test from '@playwright/test';
|
|
2
|
+
import { Page, BrowserContext } from '@playwright/test';
|
|
3
|
+
import { Instance } from 'prool';
|
|
4
|
+
import z from 'zod';
|
|
5
|
+
import { b as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-COvLLLoP.js';
|
|
6
|
+
import { WorkerScopeFixture } from '../index.js';
|
|
7
|
+
|
|
8
|
+
type RenameAccount = {
|
|
9
|
+
page: Page;
|
|
10
|
+
currentAccountName: string;
|
|
11
|
+
newAccountName: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type SwitchAccount = {
|
|
15
|
+
page: Page;
|
|
16
|
+
accountName: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
declare class MetamaskProfile {
|
|
20
|
+
readonly name: "metamask";
|
|
21
|
+
readonly onboardingPath = "/home.html#onboarding";
|
|
22
|
+
indexUrl(): Promise<string>;
|
|
23
|
+
promptUrl(): Promise<string>;
|
|
24
|
+
extensionId(): Promise<string>;
|
|
25
|
+
promptPage(context: BrowserContext): Promise<_playwright_test.Page>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type OnboardingArgs = {
|
|
29
|
+
mode: "create";
|
|
30
|
+
mainAccountName?: string;
|
|
31
|
+
} | {
|
|
32
|
+
mode: "import";
|
|
33
|
+
mainAccountName?: string;
|
|
34
|
+
secretRecoveryPhrase: string;
|
|
35
|
+
};
|
|
36
|
+
type AddAccountArgs = {
|
|
37
|
+
privateKey: string;
|
|
38
|
+
accountName: string;
|
|
39
|
+
};
|
|
40
|
+
declare const addCustomNetworkSchema: z.ZodObject<{
|
|
41
|
+
networkName: z.ZodString;
|
|
42
|
+
rpcUrl: z.ZodURL;
|
|
43
|
+
chainId: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
|
|
44
|
+
currencySymbol: z.ZodString;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
type AddCustomNetwork = z.infer<typeof addCustomNetworkSchema>;
|
|
47
|
+
type SwitchNetwork = {
|
|
48
|
+
chainName: "Ethereum" | "Base" | "Linea";
|
|
49
|
+
networkType: "mainnet";
|
|
50
|
+
} | {
|
|
51
|
+
chainName: "Sepolia" | "Linea Sepolia" | "Mega Testnet" | "Monad Testnet" | (string & {});
|
|
52
|
+
networkType: "testnet" | "custom";
|
|
53
|
+
};
|
|
54
|
+
type GasFeeSettings = {
|
|
55
|
+
feeType: "low" | "medium" | "high";
|
|
56
|
+
} | {
|
|
57
|
+
feeType: "advanced";
|
|
58
|
+
maxBaseFee: string;
|
|
59
|
+
priorityFee: string;
|
|
60
|
+
};
|
|
61
|
+
type GetAccountAddressChains = "Ethereum" | "Tron" | "Bitcoin" | "Solana";
|
|
62
|
+
type MetamaskFixture = {
|
|
63
|
+
contextPath: string;
|
|
64
|
+
metamask: Metamask;
|
|
65
|
+
metamaskPage: Page;
|
|
66
|
+
createAnvilNode: (options?: Instance.anvil.Parameters) => Promise<{
|
|
67
|
+
rpcUrl: string;
|
|
68
|
+
anvil: Instance.anvil.Parameters;
|
|
69
|
+
chainId: number;
|
|
70
|
+
}>;
|
|
71
|
+
connectToAnvil: () => Promise<void>;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
declare class Metamask extends MetamaskProfile {
|
|
75
|
+
page: Page;
|
|
76
|
+
constructor(page: Page);
|
|
77
|
+
/**
|
|
78
|
+
* Onboards the wallet.
|
|
79
|
+
* This function onboards the wallet by entering the password and other required information.
|
|
80
|
+
* @param {OnboardingArgs} args - The arguments required for onboarding.
|
|
81
|
+
* @param args.mode - Create a new wallet or import an existing wallet.
|
|
82
|
+
* @param args.password - The password for the wallet.
|
|
83
|
+
* @param args.secretRecoveryPhrase - The secret recovery phrase for the wallet when importing a wallet.
|
|
84
|
+
* @example
|
|
85
|
+
* const metamask = new Metamask(page);
|
|
86
|
+
* await metamask.onboard({ mode: "import", password: "password", secretRecoveryPhrase: "Recovery phrase" });
|
|
87
|
+
*/
|
|
88
|
+
onboard(args: OnboardingArgs): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Unlocks the wallet.
|
|
91
|
+
* This function unlocks the wallet by entering the password.
|
|
92
|
+
* @example
|
|
93
|
+
* const metamask = new Metamask(page);
|
|
94
|
+
* await metamask.unlock()
|
|
95
|
+
*/
|
|
96
|
+
unlock(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Locks the wallet.
|
|
99
|
+
* This function opens the settings page and then locks the wallet.
|
|
100
|
+
* @example
|
|
101
|
+
* const metamask = new Metamask(page);
|
|
102
|
+
* await metamask.lock()
|
|
103
|
+
*/
|
|
104
|
+
lock(): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Renames an account.
|
|
107
|
+
* @param {Omit<RenameAccount, "page">} args - The arguments to rename the account.
|
|
108
|
+
* @param args.newAccountName - The new name of the account.
|
|
109
|
+
* @param args.currentAccountName - The current name of the account.
|
|
110
|
+
* @example
|
|
111
|
+
* const metamask = new Metamask(page);
|
|
112
|
+
* await metamask.renameAccount({ newAccountName: "New Account Name", currentAccountName: "Current Account Name" });
|
|
113
|
+
*/
|
|
114
|
+
renameAccount({ newAccountName, currentAccountName }: Omit<RenameAccount, "page">): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Adds an account to the wallet via a private key.
|
|
117
|
+
* @param {AddAccountArgs} args - The arguments to add the account.
|
|
118
|
+
* @param args.privateKey - The private key of the account to add.
|
|
119
|
+
* @param args.accountName - The name of the account to add.
|
|
120
|
+
* @example
|
|
121
|
+
* const metamask = new Metamask(page);
|
|
122
|
+
* await metamask.addAccount({ privateKey: "private key", accountName: "Account 1" });
|
|
123
|
+
*/
|
|
124
|
+
addAccount({ privateKey, accountName }: AddAccountArgs): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Switches the current account to the given account.
|
|
127
|
+
* @param {Omit<SwitchAccount, "page">} args - The arguments to switch the account.
|
|
128
|
+
* @param args.accountName - The name of the account to switch to.
|
|
129
|
+
* @example
|
|
130
|
+
* const metamask = new Metamask(page);
|
|
131
|
+
* await metamask.switchAccount({ accountName: "Account 1" });
|
|
132
|
+
*/
|
|
133
|
+
switchAccount({ accountName }: Omit<SwitchAccount, "page">): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Switches the current network to the given network.
|
|
136
|
+
* @param {SwitchNetwork} args - The arguments to switch the network.
|
|
137
|
+
* @param args.networkType - It should be "testnet", "mainnet", and "custom".
|
|
138
|
+
* @param args.chainName - (Mainnet): Ethereum, Base, Linea.
|
|
139
|
+
* @param args.chainName - (Testnet): Sepolia, Linea Sepolia, Mega Testnet, Monad Testnet.
|
|
140
|
+
* @example
|
|
141
|
+
* const metamask = new Metamask(page);
|
|
142
|
+
* await metamask.switchNetwork({chainName: "Sepolia", networkType: "testnet"});
|
|
143
|
+
*/
|
|
144
|
+
switchNetwork({ ...args }: SwitchNetwork): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Gets the current account's address.
|
|
147
|
+
* @returns The current account's address as a string.
|
|
148
|
+
* @example
|
|
149
|
+
* const metamask = new Metamask(page);
|
|
150
|
+
* await metamask.getAccountAddress()
|
|
151
|
+
*/
|
|
152
|
+
getAccountAddress(network: GetAccountAddressChains): Promise<string | null>;
|
|
153
|
+
/**
|
|
154
|
+
* Toggles the visibility of testnet networks in the wallet's network selector.
|
|
155
|
+
* To persists the change, do it at the point of onboarding.
|
|
156
|
+
* @example
|
|
157
|
+
* const metamask = new Metamask(page);
|
|
158
|
+
* await metamask.toggleShowTestnetNetwork()
|
|
159
|
+
*/
|
|
160
|
+
toggleShowTestnetNetwork(): Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* Add a custom network to the wallet. If you want to persist the added wallet, do it at
|
|
163
|
+
* the point of onboarding.
|
|
164
|
+
* @param {AddCustomNetwork} options - an object containing the parameters for adding a custom network.
|
|
165
|
+
* @param {number|string} options.chainId - the chain ID of the network.
|
|
166
|
+
* @param {string} options.currencySymbol - the currency symbol of the network.
|
|
167
|
+
* @param {string} options.networkName - the name of the network.
|
|
168
|
+
* @param {string} options.rpcUrl - the RPC URL of the network.
|
|
169
|
+
* @example
|
|
170
|
+
* const metamask = new Metamask(page);
|
|
171
|
+
* await metamask.addCustomNetwork({chainId: 100, currencySymbol: "XDAI", networkName: "Gnosis", rpcUrl: "https://gnosis.oat.farm"});
|
|
172
|
+
*/
|
|
173
|
+
addCustomNetwork({ chainId, currencySymbol, networkName, rpcUrl }: AddCustomNetwork): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Connects to an app by clicking on the "Connect to app" button.
|
|
176
|
+
* If an account is provided, it will be selected before connecting to the app.
|
|
177
|
+
* @param {string} [account] - The account to select before connecting to the app.
|
|
178
|
+
* @example
|
|
179
|
+
* const metamask = new Metamask(page);
|
|
180
|
+
* await metamask.connectToApp("Account 1");
|
|
181
|
+
*/
|
|
182
|
+
connectToApp(account?: string): Promise<void>;
|
|
183
|
+
/**
|
|
184
|
+
* Confirms a transaction in the wallet by clicking on the "Confirm" button.
|
|
185
|
+
* @example
|
|
186
|
+
* const metamask = new Metamask(page);
|
|
187
|
+
* await metamask.confirmTransaction();
|
|
188
|
+
*/
|
|
189
|
+
confirmTransaction(gasFee?: GasFeeSettings): Promise<void>;
|
|
190
|
+
/**
|
|
191
|
+
* Cancels a transaction in the wallet by clicking on the "Cancel" button.
|
|
192
|
+
* @example
|
|
193
|
+
* const metamask = new Metamask(page);
|
|
194
|
+
* await metamask.cancelTransaction();
|
|
195
|
+
*/
|
|
196
|
+
rejectTransaction(): Promise<void>;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
declare const metamaskFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MetamaskFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
200
|
+
|
|
201
|
+
declare const metamaskWorkerScopeFixture: ({ profileName, dappUrl, slowMo }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MetamaskFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Metamask>>;
|
|
202
|
+
|
|
203
|
+
export { Metamask, metamaskFixture, metamaskWorkerScopeFixture };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{expect as h}from"@playwright/test";import st from"zod";import{test as Mt}from"@playwright/test";function it(t,e){t&&(console.warn(`
|
|
2
|
+
\u26A0\uFE0F Skipping test: ${e}`),Mt.skip())}var w={buyButton:"eth-overview-buy",swapButton:"eth-overview-swap",sendButton:"eth-overview-send",receiveButton:"eth-overview-receive",openSettingsButton:"account-options-menu-button",accountMenuButton:"account-menu-icon",accountCell:"multichain-account-cell-entropy",openNetworkSelectorButton:"sort-by-networks",accountAddressesButton:"networks-subtitle-test-id",accountAddressesElements:"multichain-address-row",accountAddressQRCode:"multichain-address-row-qr-button"},F={lockButton:"global-menu-lock",networksButton:"global-menu-networks"},D={passwordInput:"unlock-password",unlockButton:"unlock-submit"},P={accountOptionsMenuButton:"multichain-account-cell-end-accessory",accountDetailsLabel:"Account details",renameAccountLabel:"Rename",addressesLabel:"Addresses",pinToTopLabel:"Pin to top",hideAccountLabel:"Hide account",backButton:"back",addMultichainAccountButton:"add-multichain-account-button",addWalletButton:"account-list-add-wallet-button",importWalletButton:"add-wallet-modal-import-wallet",importAccountButton:"add-wallet-modal-import-account"};var g={createWalletButton:"onboarding-create-wallet",importWalletButton:"onboarding-import-wallet",useSecretRecoveryPhraseButton:"onboarding-create-with-srp-button",createNewPasswordInput:"create-password-new-input",confirmNewPasswordInput:"create-password-confirm-input",confirmPasswordCheckbox:"create-password-terms",createPasswordButton:"create-password-submit",revealSecretRecoveryPhraseButton:"recovery-phrase-reveal",recoveryPhraseRemindMeLaterButton:"recovery-phrase-remind-later",metamaskMetricsIAgreeButton:"metametrics-i-agree",onboardingDoneButton:"onboarding-complete-done",importUsingSecretRecoveryPhraseButton:"onboarding-import-with-srp-button",secretRecoveryPhraseTextAreaInput:"srp-input-import__srp-note",importWalletConfirmButton:"import-srp-confirm",importAccountConfirmButton:"import-account-confirm-button",importSRPError:"bannerAlert"};async function ct({page:t,privateKey:e,accountName:o}){let a=st.string().min(1,"Account name cannot be an empty string").trim().parse(o),n=st.string().min(1,"Private key cannot be an empty string").trim().parse(e),r=t.getByTestId(w.accountMenuButton);await h(r).toBeVisible({timeout:3e4}),await r.click(),await h(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let i=t.getByTestId(P.addWalletButton),c=await i.textContent();c?.includes("Syncing")&&await h.poll(async()=>(await i.textContent())?.trim()??"",{timeout:12e4}).not.toBe(c),await h(i).toBeEnabled({timeout:6e4}),await i.click();let s=t.getByRole("dialog");await h(s).toContainText(/add wallet/i),await t.getByTestId(P.importAccountButton).click(),await t.locator("input[id='private-key-box']").fill(n);let p=t.getByTestId(g.importAccountConfirmButton);await h(p).toBeEnabled(),await p.click();let f=t.getByTestId(g.importSRPError),x=await f.isVisible().catch(()=>!1);x&&it(x,`${(await f.textContent())?.split(".")[0]}`);let S=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])"),T=(await S.textContent())?.split("$")[0];T&&await Lt({page:t,accountName:a,activeAccountLocator:S,activeAccountName:T}),await t.locator("button[aria-label='Back']").first().click()}async function Lt({page:t,accountName:e,activeAccountLocator:o,activeAccountName:a}){let n=o.locator(`div[aria-label='${a} options']`);await h(n).toBeVisible(),await n.click(),await h(t.getByRole("tooltip")).toBeVisible();let r=t.locator(`div[aria-label='${P.renameAccountLabel}']`);await h(r).toBeVisible(),await r.click();let i=t.getByRole("dialog"),c=i.getByRole("heading",{name:/rename/i});await h(c).toBeVisible();let s=i.getByRole("textbox");await h(s).toBeVisible(),await s.fill(e);let u=i.getByRole("button",{name:/confirm/i});await h(u).toBeEnabled(),await u.click(),await i.waitFor({state:"detached",timeout:2e4});let d=t.locator("div:has(> div[data-testid^='multichain-account-cell-keyring'][class*='mm-box--background-color-background-muted'])");await h(d).toContainText(e)}import{expect as V}from"@playwright/test";import N from"zod";var lt=N.object({networkName:N.string().min(1,"Network name cannot be an empty string"),rpcUrl:N.url(),chainId:N.number().or(N.string().includes("0x")),currencySymbol:N.string().toUpperCase().min(1,"Currency symbol cannot be an empty string")});import{expect as Wt}from"@playwright/test";async function K(t){let e=t.locator("div:has(> p[data-testid='notifications-tag-counter__unread-dot'])"),o=t.getByTestId(w.openSettingsButton);await e.isVisible().catch(()=>!1)?await e.click():(await Wt(o).toBeVisible(),await o.click())}async function mt({page:t,...e}){let{chainId:o,currencySymbol:a,networkName:n,rpcUrl:r}=lt.parse({...e},{reportInput:!0});await K(t),await t.getByTestId(F.networksButton).click();let c=t.locator("section[role='dialog']");await V(c).toContainText(/manage networks/i),await t.getByRole("button",{name:/add a custom network/i}).click(),await V(c).toContainText(/Add a custom network/i);let u=t.getByTestId("network-form-network-name"),d=t.getByTestId("test-add-rpc-drop-down"),p=t.getByTestId("network-form-chain-id"),f=t.getByTestId("network-form-ticker-input");await u.fill(n),await d.click(),await t.getByRole("tooltip").locator("div:has(> button:has-text('Add RPC URL'))").click(),await V(c).toContainText(/Add RPC URL/i);let T=t.getByTestId("rpc-url-input-test"),B=t.getByRole("button",{name:/Add URL/i});await T.fill(r),await B.click(),await V(c).toContainText(/Add a custom network/i);let y=t.getByTestId("network-form-chain-id-error");if(await y.isVisible().catch(()=>!1)){let C=await y.textContent();throw Error(`RPC error: ${C}`)}await p.fill(`${o}`),await f.fill(a);let I=t.getByRole("button",{name:/save/i});await V(I).toBeEnabled(),await I.click()}import{expect as dt}from"@playwright/test";function v(t){return new Promise(e=>setTimeout(e,t))}var j={confirmButton:"confirm-footer-button",cancelButton:"confirm-footer-cancel-button"};async function ut(t,e){let o=t.getByTestId(j.confirmButton);await v(2e3);let n=(await o.textContent())?.includes("Review alert"),r=await o.isDisabled().catch(()=>!1);if(n&&r){await t.getByTestId("edit-gas-fees-row").locator("> div").first().click();let d=t.getByRole("dialog");await dt(d).toBeVisible();let p=d.locator("h4",{hasText:"Insufficient funds"}),f=await d.getByTestId("alert-modal__selected-alert").textContent();if(await p.isVisible().catch(()=>!1))throw Error(`${f}`)}if(e){let s=t.getByTestId("edit-gas-fee-icon");if(await s.scrollIntoViewIfNeeded(),await s.click(),e.feeType!=="advanced"&&await t.getByTestId(`gas-option-${e.feeType}`).click(),e.feeType==="advanced"){await t.getByTestId("gas-option-advanced").click();let d=t.getByRole("textbox",{name:"Max base fee"}),p=t.getByRole("textbox",{name:"Priority fee"}),f=t.getByRole("button",{name:"Save",exact:!0});await d.fill(e.maxBaseFee),await p.fill(e.priorityFee),await f.click()}}await dt(o).toBeEnabled(),await o.click();let i=t.getByRole("dialog");await i.isVisible().catch(()=>!1)&&await i.locator("h4",{hasText:"Your assets may be at risk"}).isVisible().catch(()=>!1)&&(await i.getByTestId("alert-modal-acknowledge-checkbox").click(),await i.getByTestId("confirm-alert-modal-submit-button").click()),await t.waitForEvent("close",{timeout:15e3})}import{expect as Dt}from"@playwright/test";import{expect as Y}from"@playwright/test";async function M({page:t,accountName:e}){let o=t.getByTestId(w.accountMenuButton);if(await o.textContent()===e){console.info(`Can't switch account to "${e}", it is already selected.`);return}await Y(o).toBeVisible({timeout:15e3}),await o.click(),await Y(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let n=t.getByTestId(P.addMultichainAccountButton),r=await n.textContent();r?.includes("Syncing")&&await Y.poll(async()=>(await n.textContent())?.trim()??"",{timeout:6e4}).not.toBe(r);let i=await t.getByTestId(/^multichain-account-cell-(?:entropy|keyring):/).all(),c=null;for(let s of i)if(await s.scrollIntoViewIfNeeded(),(await s.textContent())?.includes(e)){c=s;break}if(!c)throw Error(`Account with name "${e}" not found.`);await c?.click()}async function pt(t,e){e&&await M({page:t,accountName:e});let o=t.getByRole("button",{name:"Connect",exact:!0});await o.waitFor({state:"visible",timeout:25e3}),await o.click(),await t.getByRole("heading",{name:"Connecting",exact:!0}).waitFor({state:"detached",timeout:3e4});let n;await Dt.poll(async()=>(n=await t.locator("div[class='permissions-connect']").isVisible().catch(()=>!1),n),{timeout:25e3}).toBe(!0).catch(()=>console.error("Notice dialog did not appear within the timeout period."));let r=t.getByTestId("page-container-footer-next");await r.waitFor({state:"visible",timeout:25e3}),await r.click(),await t.waitForEvent("close",{predicate:()=>!0,timeout:25e3}).catch(()=>console.error("Extension popup did not close within the timeout period when connecting to the DApp."))}async function wt(t,e){return await t.getByTestId(w.accountAddressesButton).hover(),await t.getByTestId("multichain-address-rows-list").getByRole("button",{name:/view all/i}).click(),await t.getByRole("searchbox",{name:/search networks/i}).fill(e),await t.locator(`div[data-testid='${w.accountAddressesElements}']:has-text('${e}')`).getByTestId(w.accountAddressQRCode).click(),await t.getByRole("dialog").locator("div > p[data-testid='account-address']").textContent()}import{expect as Ot}from"@playwright/test";import{errors as Vt}from"@playwright/test";async function R(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}var ft={loadingOverlay:"loading-overlay",loadingSpinner:"spinner loading-overlay__spinner"};var Ut=6e4,$t=async(t,e,o)=>{await R(e);try{await e.locator(`div[class="${t}"]`).waitFor({state:"detached",timeout:o})}catch(a){if(a instanceof Vt.TimeoutError)console.info(`Loading indicator '${t}' not found - continuing.`);else throw console.error(`Error while waiting for loading indicator '${t}' to disappear`),a}},q=async t=>{try{await $t(ft.loadingSpinner,t,Ut)}catch(e){console.warn("Warning during MetaMask load:",e)}return await v(300),t};async function gt(t){if(await t.getByTestId(D.unlockButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already locked");return}await K(t);let a=t.getByTestId(F.lockButton);await Ot(a).toBeVisible(),await a.click(),await q(t)}import{styleText as At}from"util";import{expect as W}from"@playwright/test";import Bt from"fs";import Gt from"path";import Ht from"path";var ht=".wallet-cache",xt=".wallet-context";var yt="13.22.0",U="https://github.com/amaify/chainwright/releases/download/v0.1.0/",ko=`https://github.com/MetaMask/metamask-extension/releases/download/v${yt}/metamask-chrome-${yt}.zip`,bo=`${U}solflare-wallet-extension-v2.19.1.zip`,To=`${U}petra-wallet-extension-v2.4.8.zip`,Ao=`${U}phantom-wallet-extension-v26.10.0.zip`,Co=`${U}meteor-wallet-extension-v0.7.0.zip`,Po=`${U}keplr-wallet-extension-v0.13.3.zip`;function k(t){return Ht.resolve(process.cwd(),ht,t)}async function X(t){let e=k(t),o=Gt.resolve(e,"password.txt");try{if(!Bt.existsSync(o))throw new Error("\u274C password.txt not found. Run setup script first.");return Bt.readFileSync(o,"utf-8")}catch(a){throw new Error(`\u274C Failed to get ${t} password from cache: ${a.message}`)}}import{expect as zt}from"@playwright/test";async function kt({context:t,path:e,locator:o}){let a;try{await zt.poll(async()=>(a=t.pages().filter(n=>n.url().startsWith("chrome-extension://")).find(n=>n.url().match(e)),!!a),{timeout:3e4}).toBe(!0)}catch{let n=t.pages().filter(r=>r.url().startsWith("chrome-extension://")).map(r=>r.url());throw new Error(`Popup page with path "${e}" not found in context after 30s. Pages in context: ${JSON.stringify(n)}`)}if(!a)throw new Error(`Popup page with path ${e} not found in context.`);return await Kt(a,o),await a.setViewportSize({width:360,height:592}),a}async function Kt(t,e){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(e).first().waitFor({state:"attached",timeout:4e4})}import bt from"fs";import jt from"path";async function Tt(t){let e=k(t),o=jt.resolve(e,"extension-id.txt");try{if(!bt.existsSync(o))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return bt.readFileSync(o,"utf-8")}catch(a){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${a.message}`)}}var A=class{name="metamask";onboardingPath="/home.html#onboarding";async indexUrl(){return`chrome-extension://${await this.extensionId()}/home.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/notification.html`}async extensionId(){return await Tt(this.name)}async promptPage(e){let o=await this.promptUrl();return await kt({context:e,path:o,locator:"div[data-testid='multichain-page']"})}};import{expect as Z}from"@playwright/test";async function L({page:t}){await t.locator(`div:has(> button[data-testid='${w.openSettingsButton}'])`).click(),await t.getByTestId(F.networksButton).click();let a=t.locator("section[role='dialog']");await Z(a).toBeVisible(),await Z(a).toContainText(/manage networks/i);let n="div:has(> p:has-text('Show test networks'))";await a.locator(n).scrollIntoViewIfNeeded();let r=a.locator(n);if(!await r.locator("label[class='toggle-button toggle-button--off']").isVisible().catch(()=>!1)){await a.getByRole("button",{name:/close/i}).click(),console.info("Testnet networks are already visible.");return}await r.locator("label[class='toggle-button toggle-button--off']").click(),await t.getByTestId("Sepolia").scrollIntoViewIfNeeded(),await Z(t.getByTestId("Sepolia")).toBeVisible(),await a.getByRole("button",{name:/close/i}).click()}async function tt({page:t,mainAccountName:e,...o}){console.info(At("yellowBright",`
|
|
3
|
+
\u{1F98A} MetaMask onboarding started...`,{validateStream:!1}));let a=await X("metamask"),n=new A,r=t.locator("img[class='loading-spinner']"),i=t.getByTestId(g.createWalletButton),c=t.getByTestId(g.importWalletButton),s=t.getByTestId(g.createNewPasswordInput),u=t.getByTestId(g.confirmNewPasswordInput),d=t.getByTestId(g.confirmPasswordCheckbox),p=t.getByTestId(g.createPasswordButton),f=t.getByTestId(g.metamaskMetricsIAgreeButton),x=t.getByTestId(g.onboardingDoneButton);if(await r.waitFor({state:"detached",timeout:3e4}),o.mode==="create"){let I=t.getByTestId(g.useSecretRecoveryPhraseButton);await i.click(),await I.click(),await s.fill(a),await u.fill(a),await d.click(),await p.click(),await t.getByTestId(g.revealSecretRecoveryPhraseButton).click(),await t.getByTestId(g.recoveryPhraseRemindMeLaterButton).click(),await f.click()}if(o.mode==="import"){let{secretRecoveryPhrase:I}=o,C=I.split(" "),G=t.getByTestId(g.importUsingSecretRecoveryPhraseButton);await c.click(),await G.click();let nt=t.getByTestId(g.secretRecoveryPhraseTextAreaInput);await nt.fill(C[0]),await nt.press("Space");for(let z=1;z<C.length;z++){let rt=t.getByTestId(`import-srp__srp-word-${z}`);await rt.fill(C[z]),await rt.press("Space")}await t.getByTestId(g.importWalletConfirmButton).click(),await s.fill(a),await u.fill(a),await d.click(),await p.click(),await f.click();let Nt=t.getByTestId("wallet-ready");await W(Nt).toContainText(/your wallet is ready/i)}await x.click();let T=`chrome-extension://${await n.extensionId()}/sidepanel.html`,y=await t.context().browser()?.newBrowserCDPSession(),_;await W.poll(async()=>{if(y){let{targetInfos:I}=await y.send("Target.getTargets"),C=I.find(G=>G.url===T);return _=C,!!C}},{timeout:15e3}).toBe(!0),_&&await y?.send("Target.closeTarget",{targetId:_.targetId}),await t.goto(await n.indexUrl()),await r.waitFor({state:"detached",timeout:3e4}),await W(t.getByTestId(w.buyButton)).toBeVisible(),await W(t.getByTestId(w.swapButton)).toBeVisible(),await W(t.getByTestId(w.sendButton)).toBeVisible(),await W(t.getByTestId(w.receiveButton)).toBeVisible(),await L({page:t}),e&&await M({page:t,accountName:e}),await v(5e3),console.info(At("greenBright","\u2728 MetaMask onboarding completed successfully",{validateStream:!1}))}import{expect as qt}from"@playwright/test";async function Ct(t){let e=t.getByTestId(j.cancelButton);await v(1e3),await qt(e).toBeEnabled(),await e.click()}import{expect as b}from"@playwright/test";async function Pt({page:t,currentAccountName:e,newAccountName:o}){let a=t.getByTestId(w.accountMenuButton);if(await a.textContent()===o)throw Error(`The account to be renamed "${o}" already exists.`);await b(a).toBeVisible({timeout:15e3}),await a.click(),await b(t.getByRole("heading",{name:/accounts/i})).toBeVisible();let r=t.getByTestId(P.addMultichainAccountButton),i=await r.textContent();i?.includes("Syncing")&&await b.poll(async()=>(await r.textContent())?.trim()??"",{timeout:6e4}).not.toBe(i);let c=await t.getByTestId(/^multichain-account-cell/).all(),s=null;for(let y of c)if((await y.textContent())?.includes(e)){s=y;break}if(!s)throw Error(`Account with name "${e}" not found.`);if((await s.textContent())?.split("$")[0]===o)throw Error(`The new account name "${o}" is the same as the old account name "${e}".`);let d=t.locator(`div[aria-label='${e} options']`);await b(d).toBeVisible(),await d.click(),await b(t.getByRole("tooltip")).toBeVisible();let p=t.locator(`div[aria-label='${P.renameAccountLabel}']`);await b(p).toBeVisible(),await p.click();let f=t.getByRole("dialog"),x=f.getByRole("heading",{name:/rename/i});await b(x).toBeVisible();let S=f.getByRole("textbox");await b(S).toBeVisible(),await S.fill(o);let T=f.getByRole("button",{name:/confirm/i});await b(T).toBeEnabled(),await T.click();for(let y of c)if((await y.textContent())?.includes(o)){await b(y).toBeVisible(),await b(y).toContainText(o);break}await t.locator("button[aria-label='Back']").first().click()}import{expect as et}from"@playwright/test";async function St({page:t,networkType:e,chainName:o}){let a=t.getByTestId(w.openNetworkSelectorButton);await a.click();let n=t.getByTestId("modal-header-close-button");if(e==="testnet"||e==="custom"){let s=t.getByRole("tab",{name:"Custom"});await s.click(),await t.locator("p:has-text('Testnets')").isVisible().catch(()=>!1)||(await n.click(),await L({page:t}),await a.click(),await s.click());let p=t.locator(`div div[data-testid='${o}']`),f=await p.textContent();et(f).toBe(o),await p.click();return}await t.getByRole("tab",{name:"Popular"}).click();let i=t.locator(`div div[data-testid='${o}']`),c=await i.textContent();et(c).toBe(o),await i.click(),await et(a).toContainText(o,{timeout:3e4})}import{expect as It}from"@playwright/test";async function $(t){let e=await X("metamask"),o=t.getByTestId(D.passwordInput);if(await t.getByTestId(w.openNetworkSelectorButton).isVisible().catch(()=>!1)){console.info("\u{1F4A1} Wallet is already unlocked");return}await o.fill(e);let r=t.getByTestId(D.unlockButton);await It(r).toBeVisible(),await r.click(),await q(t),await It(t.getByTestId(w.buyButton)).toBeVisible({timeout:3e4})}var E=class extends A{page;constructor(e){super(),this.page=e}async onboard(e){await tt({page:this.page,...e})}async unlock(){await $(this.page)}async lock(){await gt(this.page)}async renameAccount({newAccountName:e,currentAccountName:o}){await Pt({page:this.page,newAccountName:e,currentAccountName:o})}async addAccount({privateKey:e,accountName:o}){await ct({page:this.page,privateKey:e,accountName:o})}async switchAccount({accountName:e}){await M({page:this.page,accountName:e})}async switchNetwork({...e}){await St({page:this.page,...e})}async getAccountAddress(e){return await wt(this.page,e)}async toggleShowTestnetNetwork(){await L({page:this.page})}async addCustomNetwork({chainId:e,currencySymbol:o,networkName:a,rpcUrl:n}){await mt({page:this.page,chainId:e,currencySymbol:o,networkName:a,rpcUrl:n})}async connectToApp(e){await pt(await this.promptPage(this.page.context()),e)}async confirmTransaction(e){await ut(await this.promptPage(this.page.context()),e)}async rejectTransaction(){await Ct(await this.promptPage(this.page.context()))}};import Et from"fs";import te from"path";import{test as ee,chromium as oe}from"@playwright/test";import{Instance as ae,Pool as ne}from"prool";import Xt from"path";async function O(t){return Xt.resolve(process.cwd(),xt,t)}import{expect as Qt}from"@playwright/test";async function ot(t,e){let o=await t.newPage();return await Qt(async()=>{await o.goto(e),await R(o)}).toPass(),o}async function at(t,e){let o=await e.newPage();for(let{origin:a,localStorage:n}of t){let r=o.mainFrame();await r.goto(a),await r.evaluate(i=>{i.forEach(({name:c,value:s})=>{window.localStorage.setItem(c,s)})},n)}await o.close()}import Jt from"fs/promises";async function vt(t){await Jt.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var Yt=35e3;async function Q(t,e){try{await Promise.race([t.close(),new Promise((o,a)=>setTimeout(()=>a(new Error("Context close timed out")),Yt))])}catch(o){console.warn(`Browser context close did not complete cleanly: ${o.message}`)}try{await vt(e)}catch(o){console.error(`Failed to remove temporary context directory at ${e}. Error:`,o)}}import Rt from"fs";import Zt from"path";async function J(t){try{let e=k(t),o=Zt.resolve(e,"extension-path.txt");if(!Rt.existsSync(o))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let a=Rt.readFileSync(o,"utf-8").trim();if(!a)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return a}catch(e){throw new Error(`\u274C Failed to get ${t} extension path: ${e.message}`)}}var H,In=({slowMo:t=0,profileName:e}={})=>ee.extend({contextPath:async({browserName:o},a,n)=>{let r=await O(`${o}-${n.testId}`);await a(r)},context:async({context:o,contextPath:a},n)=>{let r=new A,i=k(r.name),c=await J(r.name),s=te.resolve(i,e??"wallet-data");if(!Et.existsSync(s))throw new Error("\u274C Cache for MetaMask wallet data not found. Create it first");Et.cpSync(s,a,{recursive:!0,force:!0});let u=[`--disable-extensions-except=${c}`,`--load-extension=${c}`];process.env.HEADLESS&&(u.push("--headless=new"),t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!"));let d=await oe.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:t}),{cookies:p,origins:f}=await o.storageState();p&&await d.addCookies(p),f&&f.length>0&&at(f,d);let x=await r.indexUrl();await d.waitForEvent("page",{predicate:B=>B.url().startsWith(x),timeout:3e4}),H=d.pages().find(B=>B.url().startsWith(x))??await ot(d,x);for(let B of d.pages())B.url().includes("about:blank")&&await B.close();await H.locator("img[class='loading-spinner']").waitFor({state:"detached"}),await $(H),await n(d),await Q(d,a)},metamaskPage:async({context:o},a)=>{await a(H)},metamask:async({context:o},a)=>{let n=new E(H);await a(n)},createAnvilNode:async({context:o},a,n)=>{let r=n.workerIndex,i;await a(async c=>{i=ne.define({instance:ae.anvil(c)});let s=await i.start(r),u=`http://${s.host}:${s.port}`,p=c?.chainId??31337;return{rpcUrl:u,anvil:s,chainId:p}}),i&&await i.stop(r)},connectToAnvil:async({context:o,metamask:a,createAnvilNode:n},r)=>{await r(async()=>{let{chainId:i,rpcUrl:c}=await n({chainId:2251});await a.addCustomNetwork({chainId:i,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:c})})}});import{test as se}from"@playwright/test";import{Instance as ce,Pool as le}from"prool";import _t from"fs";import re from"path";import{chromium as ie}from"@playwright/test";async function Ft({workerInfo:t,profileName:e,slowMo:o}){let a=new A,n=await O(t.workerIndex.toString()),r=k(a.name),i=re.resolve(r,e??"wallet-data");if(!_t.existsSync(i))throw new Error(`Cache for ${a.name} does not exist. Create it first!`);_t.cpSync(i,n,{recursive:!0,force:!0});let c=await J(a.name),s=await ie.launchPersistentContext(n,{headless:!1,args:[`--disable-extensions-except=${c}`],slowMo:process.env.HEADLESS?0:o}),u=await a.indexUrl();await s.waitForEvent("page",{predicate:p=>p.url().startsWith(u),timeout:4e4});let d=s.pages().find(p=>p.url().startsWith(u));d||(d=await s.newPage(),await d.goto(u),await R(d));for(let p of s.pages())p.url().includes("about:blank")&&await p.close();return{context:s,walletPage:d,contextPath:n}}var Kn=({profileName:t,dappUrl:e,slowMo:o}={})=>se.extend({workerScopeContents:[async({browser:a},n,r)=>{let{context:i,contextPath:c,walletPage:s}=await Ft({workerInfo:r,profileName:t,slowMo:o});await i.grantPermissions(["clipboard-read"]);let u=new E(s);await u.unlock(),await n({wallet:u,walletPage:s,context:i}),await Q(i,c)},{scope:"worker"}],dappPage:[async({workerScopeContents:a},n)=>{let{context:r}=a,i=await r.newPage();e&&await i.goto(e),await n(i)},{scope:"worker"}],metamaskPage:async({workerScopeContents:a},n)=>{await n(a.walletPage)},metamask:async({workerScopeContents:a},n)=>{let r=new E(a.walletPage);await n(r)},createAnvilNode:async({context:a},n,r)=>{let i=r.workerIndex,c;await n(async s=>{c=le.define({instance:ce.anvil(s)});let u=await c.start(i),d=`http://${u.host}:${u.port}`,f=s?.chainId??31337;return{rpcUrl:d,anvil:u,chainId:f}}),c&&await c.stop(i)},connectToAnvil:async({context:a,metamask:n,createAnvilNode:r},i)=>{await i(async()=>{let{chainId:c,rpcUrl:s}=await r({chainId:2251});await n.addCustomNetwork({chainId:c,currencySymbol:"ETH",networkName:"Anvil Localnet",rpcUrl:s})})}});export{E as Metamask,In as metamaskFixture,Kn as metamaskWorkerScopeFixture};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as _playwright_test from '@playwright/test';
|
|
2
|
+
import { BrowserContext, Page } from '@playwright/test';
|
|
3
|
+
import { b as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-COvLLLoP.js';
|
|
4
|
+
import { WorkerScopeFixture } from '../index.js';
|
|
5
|
+
|
|
6
|
+
declare class MeteorProfile {
|
|
7
|
+
readonly name: "meteor";
|
|
8
|
+
readonly onboardingPath = "ext_index_popup.html";
|
|
9
|
+
indexUrl(): Promise<string>;
|
|
10
|
+
promptUrl(): Promise<string>;
|
|
11
|
+
extensionId(): Promise<string>;
|
|
12
|
+
promptPage(context: BrowserContext): Promise<_playwright_test.Page>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type MeteorNetwork = "Mainnet" | "Testnet";
|
|
16
|
+
type OnboardingArgs = {
|
|
17
|
+
network: MeteorNetwork;
|
|
18
|
+
privateKey: string;
|
|
19
|
+
accountName: string;
|
|
20
|
+
addWallet?: Array<AddAccountArgs>;
|
|
21
|
+
};
|
|
22
|
+
type RenameAccountArgs = {
|
|
23
|
+
newAccountName: string;
|
|
24
|
+
};
|
|
25
|
+
type AddAccountArgs = {
|
|
26
|
+
privateKey: string;
|
|
27
|
+
accountName: string;
|
|
28
|
+
network: MeteorNetwork;
|
|
29
|
+
};
|
|
30
|
+
type MeteorFixture = {
|
|
31
|
+
contextPath: string;
|
|
32
|
+
meteor: Meteor;
|
|
33
|
+
meteorPage: Page;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
declare class Meteor extends MeteorProfile {
|
|
37
|
+
page: Page;
|
|
38
|
+
constructor(page: Page);
|
|
39
|
+
/**
|
|
40
|
+
* Onboards the wallet.
|
|
41
|
+
* This function onboards the wallet by entering the password and other required information.
|
|
42
|
+
* @param {OnboardingArgs} args - The arguments required for onboarding.
|
|
43
|
+
* @param args.password - The password for the wallet.
|
|
44
|
+
* @param args.secretRecoveryPhrase - The secret recovery phrase for the wallet when importing a wallet.
|
|
45
|
+
* @example
|
|
46
|
+
* const meteor = new Meteor(page);
|
|
47
|
+
* await meteor.onboard({ mode: "importPrivateKey", password: "password", privateKey: "private key" });
|
|
48
|
+
*/
|
|
49
|
+
onboard({ network, privateKey, accountName, addWallet }: OnboardingArgs): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Unlocks the wallet by entering the password.
|
|
52
|
+
* @example
|
|
53
|
+
* const meteor = new Meteor(page);
|
|
54
|
+
* await meteor.unlock();
|
|
55
|
+
*/
|
|
56
|
+
unlock(): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Locks the wallet by entering the password.
|
|
59
|
+
* This function locks the wallet by opening the settings page and then locking the wallet.
|
|
60
|
+
* @example
|
|
61
|
+
* const meteor = new Meteor(page);
|
|
62
|
+
* await meteor.lock();
|
|
63
|
+
*/
|
|
64
|
+
lock(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Renames an account in the wallet.
|
|
67
|
+
* @param {Omit<RenameAccount, "page">} args - The arguments to rename the account.
|
|
68
|
+
* @param args.newAccountName - The new name of the account.
|
|
69
|
+
* @example
|
|
70
|
+
* const meteor = new Meteor(page);
|
|
71
|
+
* await meteor.renameAccount({ newAccountName: "New Account Name" });
|
|
72
|
+
*/
|
|
73
|
+
renameAccount({ newAccountName }: RenameAccountArgs): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Switches the current network to the given network.
|
|
76
|
+
* @param {SwitchNetwork} networkName - The name of the network to switch to.
|
|
77
|
+
* @example
|
|
78
|
+
* const meteor = new Meteor(page);
|
|
79
|
+
* await meteor.switchNetwork("network name");
|
|
80
|
+
*/
|
|
81
|
+
switchNetwork(network: MeteorNetwork): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Switches the current account to the given account.
|
|
84
|
+
* @param {string} accountName - The name of the account to switch to.
|
|
85
|
+
* @example
|
|
86
|
+
* const meteor = new meteor(page);
|
|
87
|
+
* await meteor.switchAccount("Account 1");
|
|
88
|
+
*/
|
|
89
|
+
switchAccount(accountName: string): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Retrieves the current account's address.
|
|
92
|
+
* @returns A promise that resolves with the current account's address as a string.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* const meteor = new Meteor(page);
|
|
96
|
+
* const address = await meteor.getAccountAddress();
|
|
97
|
+
*/
|
|
98
|
+
getAccountAddress(): Promise<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Adds an account to the wallet via a private key or mnemonic phrase.
|
|
101
|
+
* @param {{ accountName, ...args }: AddAccount} - The arguments to add the account.
|
|
102
|
+
* @param {string} args.accountName - The name of the account to add.
|
|
103
|
+
* @param {string} args.privateKey - The private key of the account to add, if the mode is "privateKey".
|
|
104
|
+
* @param {string[]} args.mnemonicPhrase - The mnemonic phrase of the account to add, if the mode is "mnemonic".
|
|
105
|
+
* @example
|
|
106
|
+
* const meteor = new Meteor(page);
|
|
107
|
+
* await meteor.addAccount(TBD);
|
|
108
|
+
*/
|
|
109
|
+
addAccount({ accountName, network, privateKey }: AddAccountArgs): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Opens the settings page for the wallet.
|
|
112
|
+
* @example
|
|
113
|
+
* const meteor = new Meteor(page);
|
|
114
|
+
* await meteor.openSettings();
|
|
115
|
+
*/
|
|
116
|
+
openSettings(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Connects to an app by clicking on the "Connect" button.
|
|
119
|
+
* If an account is provided, it will be selected before connecting to the app.
|
|
120
|
+
* @param {string} [account] - The account to select before connecting to the app.
|
|
121
|
+
* @example
|
|
122
|
+
* const meteor = new Meteor(page);
|
|
123
|
+
* await meteor.connectToApp("Account 1");
|
|
124
|
+
*/
|
|
125
|
+
connectToApp(account?: string): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Confirms a transaction in the wallet by clicking on the "Approve" button.
|
|
128
|
+
* This function confirms a transaction in the wallet by clicking on the "Approve" button.
|
|
129
|
+
* It first opens the popup page and then clicks on the "Confirm" button.
|
|
130
|
+
* @example
|
|
131
|
+
* const meteor = new Meteor(page);
|
|
132
|
+
* await meteor.confirmTransaction();
|
|
133
|
+
*/
|
|
134
|
+
confirmTransaction(): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Cancels a transaction in the wallet by clicking on the "Cancel" button.
|
|
137
|
+
* This function cancels a transaction in the wallet by clicking on the "Cancel" button.
|
|
138
|
+
* It first opens the popup page and then clicks on the "Cancel" button.
|
|
139
|
+
* @example
|
|
140
|
+
* const meteor = new Meteor(page);
|
|
141
|
+
* await meteor.cancelTransaction();
|
|
142
|
+
*/
|
|
143
|
+
rejectTransaction(): Promise<void>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
declare const meteorFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MeteorFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
147
|
+
|
|
148
|
+
declare const meteorWorkerScopeFixture: ({ slowMo, profileName, dappUrl }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & MeteorFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Meteor>>;
|
|
149
|
+
|
|
150
|
+
export { Meteor, meteorFixture, meteorWorkerScopeFixture };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var w={openSidebarMenuButton:"button[aria-label='open sidebar']",addWalletButton:"button:has-text('Add Wallet')",settingsButton:"button:has-text('Settings')",settingsMenuBackButton:"button[aria-label='Back']"};var d={importExistingWalletButton:'button:has-text("Import an existing wallet")',switchNetworkButton:"button[id^='menu-button']",privateKeyButton:"button:has-text('Private Key')",findMyAccountButton:"button:has-text('Find my account')"};async function N(t,o,e){let r=t.locator(d.switchNetworkButton).last();await r.scrollIntoViewIfNeeded();let a=await r.textContent(),c=o.split("net")[0]?.toLowerCase()??"";if(a?.toLowerCase()===c)return console.info(`
|
|
2
|
+
Already on ${o}, no need to switch network.`),"Exit";await r.click();let u=t.locator(e).last().locator(`> button:has-text('${o}')`);await u.click(),await t.locator("div > h2:has-text('Meteor Community')").isVisible().catch(()=>!1)&&await u.click()}async function A({page:t,newAccountName:o}){await t.locator(w.openSidebarMenuButton).click(),await t.locator("div:has(> h2):has(> svg)").click();let a=t.locator("input[placeholder='Ex. My Meteor Wallet']"),c=t.locator("button[type='submit']:has-text('Update')");await a.fill(o),await c.click(),await t.locator("div[id='root'] button[aria-label='Close']").click()}async function _({page:t,privateKey:o,accountName:e,network:r}){await t.locator(w.openSidebarMenuButton).click(),await t.locator(w.addWalletButton).click(),await N(t,r,"section[role='dialog'] div[role='menu']"),await t.locator(d.importExistingWalletButton).click(),await t.locator(d.privateKeyButton).click();let l=t.locator('button:has-text("Continue")');await l.scrollIntoViewIfNeeded(),await l.click(),await t.locator("textarea:not([disabled])").fill(o),await t.locator(d.findMyAccountButton).click(),await t.locator("button[type='submit'][data-loading]").waitFor({state:"detached",timeout:25e3}),await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click(),await A({page:t,newAccountName:e})}var k={approveButton:"button:has-text('Approve')",connectButton:"button:has-text('Connect')",cancelButton:"button:has-text('Cancel')"};import Z from"fs";import ht from"path";import ft from"path";var Y=".wallet-cache",Q=".wallet-context";var J="13.22.0",v="https://github.com/amaify/chainwright/releases/download/v0.1.0/",ro=`https://github.com/MetaMask/metamask-extension/releases/download/v${J}/metamask-chrome-${J}.zip`,ao=`${v}solflare-wallet-extension-v2.19.1.zip`,no=`${v}petra-wallet-extension-v2.4.8.zip`,io=`${v}phantom-wallet-extension-v26.10.0.zip`,co=`${v}meteor-wallet-extension-v0.7.0.zip`,so=`${v}keplr-wallet-extension-v0.13.3.zip`;function f(t){return ft.resolve(process.cwd(),Y,t)}async function F(t){let o=f(t),e=ht.resolve(o,"password.txt");try{if(!Z.existsSync(e))throw new Error("\u274C password.txt not found. Run setup script first.");return Z.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} password from cache: ${r.message}`)}}async function h(t){let o=await F("meteor"),e=t.locator("input[placeholder='Enter Password']"),r=t.locator('button:has-text("Unlock")');await e.fill(o),await r.click()}async function tt(t){await h(t),await t.locator(k.approveButton).click(),await t.locator("h2:has-text('Executing Transaction')").waitFor({state:"attached"}),await t.waitForEvent("close",{timeout:15e3})}async function B(t,o){if((await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > h2").textContent())?.toLowerCase()===o.toLowerCase()){console.info(`
|
|
3
|
+
Switching to the ${o} account aborted. Account is already selected.`);return}await t.locator(w.openSidebarMenuButton).click();let l=await t.locator("div:has(div > button[type='button'][aria-label='Close'])").nth(-2).locator("div").nth(2).locator("> div").nth(1).locator("div").nth(1).locator("div > h2").all(),s=null;for(let m of l)if((await m.textContent())?.toLowerCase()===o.toLowerCase()){s=m;break}if(!s)throw new Error(`Account with name "${o}" not found.`);await s.click()}async function ot(t,o){await h(t),o&&await B(t,o);let e=t.getByRole("heading",{name:"Connect Request",exact:!0});await Promise.all([t.locator(k.connectButton).click(),e.waitFor({state:"detached",timeout:3e4})])}async function et(t){return await t.locator("div:has(button[type='button'][aria-label='open sidebar'])").nth(-2).locator("div:has(div > h2)").locator("div > svg").click(),await t.evaluate(async()=>await navigator.clipboard.readText())}async function rt(t){await t.locator(w.openSidebarMenuButton).click(),await t.locator("button:has-text('Lock Wallet')").click()}import{styleText as O}from"util";function E(t){return new Promise(o=>setTimeout(o,t))}import{expect as xt}from"@playwright/test";async function at({context:t,path:o,locator:e}){let r;try{await xt.poll(async()=>(r=t.pages().filter(a=>a.url().startsWith("chrome-extension://")).find(a=>a.url().match(o)),!!r),{timeout:3e4}).toBe(!0)}catch{let a=t.pages().filter(c=>c.url().startsWith("chrome-extension://")).map(c=>c.url());throw new Error(`Popup page with path "${o}" not found in context after 30s. Pages in context: ${JSON.stringify(a)}`)}if(!r)throw new Error(`Popup page with path ${o} not found in context.`);return await gt(r,e),await r.setViewportSize({width:360,height:592}),r}async function gt(t,o){await t.waitForLoadState("load",{timeout:4e4}),await t.waitForLoadState("domcontentloaded",{timeout:4e4}),await t.locator(o).first().waitFor({state:"attached",timeout:4e4})}import nt from"fs";import yt from"path";async function it(t){let o=f(t),e=yt.resolve(o,"extension-id.txt");try{if(!nt.existsSync(e))throw new Error("\u274C extension-id.txt not found. Run setup script first.");return nt.readFileSync(e,"utf-8")}catch(r){throw new Error(`\u274C Failed to get ${t} extension ID from cache: ${r.message}`)}}var x=class{name="meteor";onboardingPath="ext_index_popup.html";async indexUrl(){return`chrome-extension://${await this.extensionId()}/ext_index_popup.html`}async promptUrl(){return`chrome-extension://${await this.extensionId()}/ext_index.html`}async extensionId(){return await it(this.name)}async promptPage(o){let e=await this.promptUrl();return await at({context:o,path:e,locator:"div[id='root']"})}};async function C(t){await t.locator(w.openSidebarMenuButton).click(),await t.locator(w.settingsButton).click()}async function I(t,o){if(await C(t),await N(t,o,"div[role='menu']")==="Exit"){let c=t.locator(w.settingsMenuBackButton);await c.scrollIntoViewIfNeeded(),await c.click();return}let r=t.locator("p:has-text('Available Balance')");if(await E(1e3),!await r.isVisible().catch(()=>!1))throw new Error([`There is no associated account for the ${o} network in your wallet.`,`Please add an account to the ${o} network in your wallet using the "addAccount" method.`,"NOTE: For the account to be persisted across tests, do this when onboarding the wallet."].join(`
|
|
4
|
+
`))}async function R({page:t,privateKey:o,network:e,accountName:r,addWallet:a}){console.info(O("yellowBright",`
|
|
5
|
+
Meteor onboarding started...`,{validateStream:!1}));let c=await F("meteor"),u=await new x().indexUrl();await t.goto(u);let l=t.locator(d.switchNetworkButton),s=await l.textContent(),m=e.split("net")[0]?.toLowerCase()??"";s?.toLowerCase().includes(m)||(await l.click(),await t.locator("div[role='menu']").locator(`> button:has-text('${e}')`).click());let y=t.locator("input[placeholder='Enter Password']"),S=t.locator("input[placeholder='Confirm Password']"),K=t.locator("label.chakra-checkbox .chakra-checkbox__control"),g=t.locator('button:has-text("Continue")');await y.fill(c),await S.fill(c),await K.click(),await g.click(),await t.locator(d.importExistingWalletButton).click(),await t.locator(d.privateKeyButton).click(),await g.scrollIntoViewIfNeeded(),await g.click(),await t.locator("textarea:not([disabled])").fill(o);let H=t.locator(d.findMyAccountButton);await H.click();let z=t.locator("button[type='submit'][data-loading]");if(await z.waitFor({state:"detached",timeout:25e3}),await t.getByRole("status").locator("div[id='toast-1-title']:has-text('No Account Found')").isVisible().catch(()=>!1)){let b=5,M=!1;for(;b>0;){if(console.info(`
|
|
6
|
+
Retrying search for account. ${b} attempts left`),await E(15e3),await H.click(),await z.waitFor({state:"detached",timeout:2e4}),await t.locator("div:has-text('Import Your Account')").nth(-2).locator("button").isVisible().catch(()=>!1)){M=!0;break}b-=1}if(!M)throw Error(O("redBright",["No Account Found","Account associated with the private key not found. Please make sure you are trying to import an account on the correct network(Mainnet/Testnet)."].join(`
|
|
7
|
+
`),{validateStream:!1}))}await t.locator("button:not([aria-label='Back'],[id^='menu-button']):has-text('Account')").click();let j=t.locator("section[role='dialog']").locator("button:has-text('Close')").first();if(await j.isVisible().then(()=>!0).catch(()=>!1)&&await j.click(),await A({page:t,newAccountName:r}),a&&a.length>0){for(let{privateKey:q,accountName:G,network:dt}of a)await _({page:t,privateKey:q,accountName:G,network:dt});await C(t);let b=t.locator(d.switchNetworkButton).last();await b.scrollIntoViewIfNeeded();let M=await b.textContent(),X=e.split("net")[0]?.toLowerCase()??"";M?.toLowerCase()!==X&&await I(t,e),await B(t,r)}await E(3e3),console.info(O("greenBright","\u2728 Meteor onboarding completed successfully"))}async function ct(t){await h(t),await t.locator(k.cancelButton).click()}var P=class extends x{page;constructor(o){super(),this.page=o}async onboard({network:o,privateKey:e,accountName:r,addWallet:a}){await R({page:this.page,network:o,privateKey:e,accountName:r,addWallet:a})}async unlock(){await h(this.page)}async lock(){await rt(this.page)}async renameAccount({newAccountName:o}){await A({page:this.page,newAccountName:o})}async switchNetwork(o){await I(this.page,o)}async switchAccount(o){await B(this.page,o)}async getAccountAddress(){return await et(this.page)}async addAccount({accountName:o,network:e,privateKey:r}){await _({page:this.page,accountName:o,network:e,privateKey:r})}async openSettings(){await C(this.page)}async connectToApp(o){await ot(await this.promptPage(this.page.context()),o)}async confirmTransaction(){await tt(await this.promptPage(this.page.context()))}async rejectTransaction(){await ct(await this.promptPage(this.page.context()))}};import pt from"fs";import Ct from"path";import{test as St,chromium as Mt}from"@playwright/test";import bt from"path";async function T(t){return bt.resolve(process.cwd(),Q,t)}import{expect as Pt}from"@playwright/test";async function U(t){await t.waitForLoadState("load",{timeout:15e3}),await t.waitForLoadState("domcontentloaded",{timeout:15e3})}async function $(t,o){let e=await t.newPage();return await Pt(async()=>{await e.goto(o),await U(e)}).toPass(),e}async function V(t,o){let e=await o.newPage();for(let{origin:r,localStorage:a}of t){let c=e.mainFrame();await c.goto(r),await c.evaluate(p=>{p.forEach(({name:u,value:l})=>{window.localStorage.setItem(u,l)})},a)}await e.close()}import At from"fs/promises";async function st(t){await At.rm(t,{maxRetries:50,retryDelay:500,recursive:!0,force:!0})}var kt=35e3;async function L(t,o){try{await Promise.race([t.close(),new Promise((e,r)=>setTimeout(()=>r(new Error("Context close timed out")),kt))])}catch(e){console.warn(`Browser context close did not complete cleanly: ${e.message}`)}try{await st(o)}catch(e){console.error(`Failed to remove temporary context directory at ${o}. Error:`,e)}}import lt from"fs";import Bt from"path";async function D(t){try{let o=f(t),e=Bt.resolve(o,"extension-path.txt");if(!lt.existsSync(e))throw new Error("\u274C extension-path.txt not found. Run setup script first.");let r=lt.readFileSync(e,"utf-8").trim();if(!r)throw new Error("\u274C extension-path.txt is empty. Run setup script first.");return r}catch(o){throw new Error(`\u274C Failed to get ${t} extension path: ${o.message}`)}}var W,Ar=({slowMo:t=0,profileName:o}={})=>St.extend({contextPath:async({browserName:e},r,a)=>{let c=await T(`${e}-${a.testId}`);await r(c)},context:async({context:e,contextPath:r},a)=>{let c=new x,p=f(c.name),u=await D(c.name),l=Ct.resolve(p,o??"wallet-data");if(!pt.existsSync(l))throw new Error("\u274C Cache for Meteor wallet data not found. Create it first");pt.cpSync(l,r,{recursive:!0,force:!0}),process.env.HEADLESS&&t>0&&console.warn("\u26A0\uFE0F Slow motion makes no sense in headless mode. It will be ignored!");let s=await Mt.launchPersistentContext(r,{headless:!1,args:[`--disable-extensions-except=${u}`,`--load-extension=${u}`],slowMo:process.env.HEADLESS?0:t});await s.grantPermissions(["clipboard-read"]);let{cookies:m,origins:y}=await e.storageState();m&&await s.addCookies(m),y&&y.length>0&&V(y,s);let S=await c.indexUrl();W=s.pages().find(g=>g.url().startsWith(S))||await $(s,S);for(let g of s.pages())g.url().includes("about:blank")&&await g.close();await W.bringToFront(),await h(W),await a(s),await L(s,r)},meteorPage:async({context:e},r)=>{await r(W)},meteor:async({context:e},r)=>{let a=new P(W);await r(a)}});import{test as Tt}from"@playwright/test";import mt from"fs";import vt from"path";import{chromium as Et}from"@playwright/test";async function ut({wallet:t,workerInfo:o,profileName:e,slowMo:r}){let a=await T(o.workerIndex.toString()),c=f(t.name),p=vt.resolve(c,e??"wallet-data");if(!mt.existsSync(p))throw new Error(`Cache for ${t.name} does not exist. Create it first!`);mt.cpSync(p,a,{recursive:!0,force:!0});let u=await D(t.name),l=await Et.launchPersistentContext(a,{headless:!1,args:[`--disable-extensions-except=${u}`],slowMo:process.env.HEADLESS?0:r}),s=await t.indexUrl(),m=l.pages()[0];return m||(m=await l.newPage()),await m.goto(s),{context:l,walletPage:m,contextPath:a}}var Or=({slowMo:t,profileName:o,dappUrl:e}={})=>Tt.extend({workerScopeContents:[async({browser:r},a,c)=>{let{context:p,contextPath:u,walletPage:l}=await ut({workerInfo:c,profileName:o,slowMo:t,wallet:new x});await p.grantPermissions(["clipboard-read"]);for(let m of p.pages())m.url().includes("about:blank")&&await m.close();let s=new P(l);await s.unlock(),await a({wallet:s,walletPage:l,context:p}),await L(p,u)},{scope:"worker"}],dappPage:[async({workerScopeContents:r},a)=>{let{context:c}=r,p=await c.newPage();e&&await p.goto(e),await a(p)},{scope:"worker"}],meteorPage:async({workerScopeContents:r},a)=>{await a(r.walletPage)},meteor:async({workerScopeContents:r},a)=>{let c=new P(r.walletPage);await a(c)}});export{P as Meteor,Ar as meteorFixture,Or as meteorWorkerScopeFixture};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import * as _playwright_test from '@playwright/test';
|
|
2
|
+
import { Page, BrowserContext } from '@playwright/test';
|
|
3
|
+
import { b as WalletProfileFixtureArgs, c as WorkerScopeFixtureArgs } from '../../types-COvLLLoP.js';
|
|
4
|
+
import { WorkerScopeFixture } from '../index.js';
|
|
5
|
+
|
|
6
|
+
type RenameAccount = {
|
|
7
|
+
page: Page;
|
|
8
|
+
newAccountName: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
declare class PetraProfile {
|
|
12
|
+
readonly name: "petra";
|
|
13
|
+
readonly onboardingPath = "/onboarding.html";
|
|
14
|
+
indexUrl(): Promise<string>;
|
|
15
|
+
promptUrl(): Promise<string>;
|
|
16
|
+
extensionId(): Promise<string>;
|
|
17
|
+
promptPage(context: BrowserContext): Promise<_playwright_test.Page>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type OnboardingArgs = {
|
|
21
|
+
mode: "create";
|
|
22
|
+
accountName: string;
|
|
23
|
+
addWallet?: Array<AddAccount>;
|
|
24
|
+
} | {
|
|
25
|
+
mode: "importMnemonic";
|
|
26
|
+
accountName: string;
|
|
27
|
+
secretRecoveryPhrase: string;
|
|
28
|
+
addWallet?: Array<AddAccount>;
|
|
29
|
+
} | {
|
|
30
|
+
mode: "importPrivateKey";
|
|
31
|
+
accountName: string;
|
|
32
|
+
privateKey: string;
|
|
33
|
+
addWallet?: Array<AddAccount>;
|
|
34
|
+
};
|
|
35
|
+
type SwitchNetwork = "Mainnet" | "Testnet" | "Devnet" | "Shelbynet" | "Netna";
|
|
36
|
+
type AddAccount = {
|
|
37
|
+
mode: "privateKey";
|
|
38
|
+
accountName: string;
|
|
39
|
+
privateKey: string;
|
|
40
|
+
} | {
|
|
41
|
+
mode: "mnemonic";
|
|
42
|
+
accountName: string;
|
|
43
|
+
mnemonicPhrase: string;
|
|
44
|
+
};
|
|
45
|
+
type PetraFixture = {
|
|
46
|
+
contextPath: string;
|
|
47
|
+
petra: Petra;
|
|
48
|
+
petraPage: Page;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
declare class Petra extends PetraProfile {
|
|
52
|
+
page: Page;
|
|
53
|
+
constructor(page: Page);
|
|
54
|
+
/**
|
|
55
|
+
* Onboards the wallet.
|
|
56
|
+
* This function onboards the wallet by entering the password and other required information.
|
|
57
|
+
* @param {OnboardingArgs} args - The arguments required for onboarding.
|
|
58
|
+
* @param args.mode - Create a new wallet or import via private key / mnemonic.
|
|
59
|
+
* @param args.password - The password for the wallet.
|
|
60
|
+
* @param args.secretRecoveryPhrase - The secret recovery phrase for the wallet when importing a wallet.
|
|
61
|
+
* @example
|
|
62
|
+
* const petra = new Petra(page);
|
|
63
|
+
* await petra.onboard({ mode: "importPrivateKey", password: "password", privateKey: "private key" });
|
|
64
|
+
*/
|
|
65
|
+
onboard(args: OnboardingArgs): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Unlocks the wallet by entering the password.
|
|
68
|
+
* @example
|
|
69
|
+
* const petra = new Petra(page);
|
|
70
|
+
* await petra.unlock();
|
|
71
|
+
*/
|
|
72
|
+
unlock(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Locks the wallet by entering the password.
|
|
75
|
+
* This function locks the wallet by opening the settings page and then locking the wallet.
|
|
76
|
+
* @example
|
|
77
|
+
* const petra = new Petra(page);
|
|
78
|
+
* await petra.lock();
|
|
79
|
+
*/
|
|
80
|
+
lock(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Renames an account in the wallet.
|
|
83
|
+
* @param {Omit<RenameAccount, "page">} args - The arguments to rename the account.
|
|
84
|
+
* @param args.newAccountName - The new name of the account.
|
|
85
|
+
* @example
|
|
86
|
+
* const petra = new Petra(page);
|
|
87
|
+
* await petra.renameAccount({ newAccountName: "New Account Name" });
|
|
88
|
+
*/
|
|
89
|
+
renameAccount({ newAccountName }: Omit<RenameAccount, "page">): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Switches the current network to the given network.
|
|
92
|
+
* @param {SwitchNetwork} networkName - The name of the network to switch to.
|
|
93
|
+
* @example
|
|
94
|
+
* const petra = new Petra(page);
|
|
95
|
+
* await petra.switchNetwork("Testnet");
|
|
96
|
+
*/
|
|
97
|
+
switchNetwork(networkName: SwitchNetwork): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Switches the current account to the given account.
|
|
100
|
+
* @param {string} accountName - The name of the account to switch to.
|
|
101
|
+
* @example
|
|
102
|
+
* const petra = new Petra(page);
|
|
103
|
+
* await petra.switchAccount("Account 1");
|
|
104
|
+
*/
|
|
105
|
+
switchAccount(accountName: string): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Retrieves the current account's address.
|
|
108
|
+
* @returns A promise that resolves with the current account's address as a string.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* const petra = new Petra(page);
|
|
112
|
+
* const address = await petra.getAccountAddress();
|
|
113
|
+
*/
|
|
114
|
+
getAccountAddress(): Promise<string>;
|
|
115
|
+
/**
|
|
116
|
+
* Adds an account to the wallet via a private key or mnemonic phrase.
|
|
117
|
+
* @param {{ accountName, ...args }: AddAccount} - The arguments to add the account.
|
|
118
|
+
* @param {string} args.accountName - The name of the account to add.
|
|
119
|
+
* @param {string} args.privateKey - The private key of the account to add, if the mode is "privateKey".
|
|
120
|
+
* @param {string[]} args.mnemonicPhrase - The mnemonic phrase of the account to add, if the mode is "mnemonic".
|
|
121
|
+
* @example
|
|
122
|
+
* const petra = new Petra(page);
|
|
123
|
+
* await petra.addAccount({ accountName: "Account 1", privateKey: "private key", mode: "privateKey" });
|
|
124
|
+
*/
|
|
125
|
+
addAccount({ accountName, ...args }: AddAccount): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Connects to an app by clicking on the "Connect to app" button.
|
|
128
|
+
* If an account is provided, it will be selected before connecting to the app.
|
|
129
|
+
* @param {string} [account] - The account to select before connecting to the app.
|
|
130
|
+
* @example
|
|
131
|
+
* const petra = new Petra(page);
|
|
132
|
+
* await petra.connectToApp("Account 1");
|
|
133
|
+
*/
|
|
134
|
+
connectToApp(account?: string): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Confirms a transaction in the wallet by clicking on the "Approve" button.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const petra = new Petra(page);
|
|
140
|
+
* await petra.confirmTransaction();
|
|
141
|
+
*/
|
|
142
|
+
confirmTransaction(): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* Rejects a transaction in the wallet by clicking on the "Cancel" button.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* const petra = new Petra(page);
|
|
148
|
+
* await petra.rejectTransaction();
|
|
149
|
+
* */
|
|
150
|
+
rejectTransaction(): Promise<void>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
declare const petraFixture: ({ slowMo, profileName }?: WalletProfileFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PetraFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
|
|
154
|
+
|
|
155
|
+
declare const petraWorkerScopeFixture: ({ slowMo, profileName, dappUrl }?: WorkerScopeFixtureArgs) => _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & PetraFixture, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerScopeFixture<Petra>>;
|
|
156
|
+
|
|
157
|
+
export { Petra, petraFixture, petraWorkerScopeFixture };
|