Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2e test for sign-multichain #244

Merged
merged 71 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
746c125
feat: add sign transaction tests
esaminu May 21, 2024
8c56c9c
Create test assertions
benmalcom May 20, 2024
9120e91
Update page manager for SignMultiChain
benmalcom May 20, 2024
522234b
Add multichain to test app
benmalcom May 20, 2024
2f70089
Add utils for multichain
benmalcom May 20, 2024
143df68
Add multichain tools
benmalcom May 20, 2024
9b95b10
Add test cases
benmalcom May 20, 2024
60a5944
Update eslint
benmalcom May 20, 2024
eb1b7ab
Add input for address
benmalcom May 28, 2024
5a18943
Add input for address
benmalcom May 28, 2024
e768aa9
Add input for address
benmalcom May 28, 2024
ab7f864
Make modal close optional
benmalcom Jun 3, 2024
3ee8f7f
Refactor
benmalcom Jun 3, 2024
0b658ed
Refactor
benmalcom Jun 4, 2024
4f4efb6
Remove page from page manager
benmalcom Jun 4, 2024
a71b8ab
Remove await iframe
benmalcom Jun 5, 2024
055e06d
Update fastauth-wallet
benmalcom Jun 5, 2024
7d8ce36
Implement adapter to request token from faucet
benmalcom Jun 5, 2024
31be5d6
Add sign multichain ui
benmalcom Jun 5, 2024
26164c7
Implement adapter to request token from faucet
benmalcom Jun 5, 2024
b51d6b0
Implement multichain page
benmalcom Jun 5, 2024
e3774a4
Add test cases
benmalcom Jun 5, 2024
a068923
Add test cacses
benmalcom Jun 5, 2024
d46b008
Update secret variables
benmalcom Jun 5, 2024
af3a0c8
Refactor
benmalcom Jun 6, 2024
f3f373e
Refactor markup
benmalcom Jun 6, 2024
10f9536
Skip BNB transaction because of replacement fee
benmalcom Jun 12, 2024
5339536
Fix typo
benmalcom Jun 13, 2024
efdd0f9
Disable webpack iframe pointer events
benmalcom Jun 13, 2024
441d9f4
Disable pointer events on ant modal
benmalcom Jun 13, 2024
b18a670
Disable pointer events on ant modal
benmalcom Jun 14, 2024
6ea13e9
Fix faucet request error
benmalcom Jun 18, 2024
0a98ac4
Remove console logs
benmalcom Jun 18, 2024
9a93104
Make faucet request run on schedule
benmalcom Jun 18, 2024
61c26c9
Undo comment
benmalcom Jun 18, 2024
43aeaea
Trigger build: Empty commit
benmalcom Jun 18, 2024
b1a633c
Trigger build: Empty commit
benmalcom Jun 18, 2024
6ece881
Update playwright yml
benmalcom Jun 19, 2024
35938b2
Add ts comment to blocking code in sign-transaction.spec
benmalcom Jun 19, 2024
cf3ff5a
Reverse iframe detach
benmalcom Jun 19, 2024
db065ec
Move package to devDeps
benmalcom Jun 19, 2024
4c07d95
Remove duplicate mpc-service file
benmalcom Jun 19, 2024
aaaf85a
File update
benmalcom Jun 19, 2024
f90706e
Remove extra space
benmalcom Jun 20, 2024
d824b8e
Remove unnecessary await
benmalcom Jun 20, 2024
80838fa
Remove unnecessary await
benmalcom Jun 20, 2024
8690709
Replae function with utility function
benmalcom Jun 20, 2024
48ee6c9
Refactor and clean up
benmalcom Jun 20, 2024
29967e0
Remove unused vars
benmalcom Jun 20, 2024
e0addd2
Replace with utility function
benmalcom Jun 20, 2024
4875db7
empty files
benmalcom Jun 20, 2024
c96eea4
Move to typescript
benmalcom Jun 20, 2024
22515fe
Refactor form and add form validation
benmalcom Jun 20, 2024
c11bf74
Refactor type
benmalcom Jun 20, 2024
bc8c3eb
Update workflow file
benmalcom Jun 20, 2024
e393bb7
Add new module
benmalcom Jun 20, 2024
a46e8ea
Test workflow
benmalcom Jun 20, 2024
55b453c
Remove ts-ignore
benmalcom Jun 20, 2024
b0eb99a
Remove extra deps for yml
benmalcom Jun 20, 2024
6ac7662
Remove schedule test
benmalcom Jun 20, 2024
dceda20
Suppress ts check
benmalcom Jun 20, 2024
e1e583f
Add comment to file
benmalcom Jun 21, 2024
2b86323
Empty commit to trigger rebuild
benmalcom Jun 21, 2024
11af938
Empty commit to trigger rebuild
benmalcom Jun 21, 2024
643839d
Empty commit to trigger rebuild
benmalcom Jun 21, 2024
73d440e
Empty commit to trigger rebuild
benmalcom Jun 22, 2024
d89af65
Empty commit to trigger rebuild
benmalcom Jun 22, 2024
6c9d844
Send .env to playwright config
benmalcom Jun 22, 2024
df4bf9a
Refactor .env vars access
benmalcom Jun 23, 2024
73bafe2
Refactor
benmalcom Jun 23, 2024
6eea2b5
Move en vars to test step
benmalcom Jun 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,26 @@ jobs:
# - name: Print server logs
# if: failure()
# run: cat ${{ github.workspace }}/server.log

- name: Install dependencies
run: |
cd ${{ github.workspace }}/packages/near-fast-auth-signer-e2e-tests
npm install -g yarn && yarn
- name: Install Playwright Browsers
run: yarn playwright install --with-deps

- name: Run Playwright tests
env:
MAILTRAP_USER: ${{ secrets.MAILTRAP_USER }}
MAILTRAP_PASS: ${{ secrets.MAILTRAP_PASS }}
MAILTRAP_EMAIL: ${{ secrets.MAILTRAP_EMAIL }}
FIREBASE_SERVICE_ACCOUNT_TESTNET: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_TESTNET }}
MULTICHAIN_TEST_ACCOUNT_ID: ${{ secrets.MULTICHAIN_TEST_ACCOUNT_ID }}
MULTICHAIN_TEST_ACCOUNT_FAK: ${{ secrets.MULTICHAIN_TEST_ACCOUNT_FAK }}
MULTICHAIN_TEST_ACCOUNT_LAK: ${{ secrets.MULTICHAIN_TEST_ACCOUNT_LAK }}
ETH_PROVIDER_URL_TESTNET: ${{ secrets.ETH_PROVIDER_URL_TESTNET }}
BNB_PROVIDER_URL_TESTNET: ${{ secrets.BNB_PROVIDER_URL_TESTNET }}
BTC_PROVIDER_URL_TESTNET: ${{ secrets.BTC_PROVIDER_URL_TESTNET }}
run: yarn playwright test
- uses: actions/upload-artifact@v4
if: always()
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/schedule-faucet-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Request Tokens from Faucet

on:
schedule:
- cron: '0 1 * * 1' # Runs every Monday at 1am

jobs:
faucet-request:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install dependencies
run: |
cd ${{ github.workspace }}/packages/near-fast-auth-signer-e2e-tests
npm install --no-save ts-node ethers

- name: Run faucet.ts script
env:
CHAINSTACK_API_KEY: ${{ secrets.CHAINSTACK_API_KEY }}
ETH_PROVIDER_URL_TESTNET: ${{ secrets.ETH_PROVIDER_URL_TESTNET }}
BNB_PROVIDER_URL_TESTNET: ${{ secrets.BNB_PROVIDER_URL_TESTNET }}
run: yarn ts-node ${{ github.workspace }}/packages/near-fast-auth-signer-e2e-tests/scripts/faucet.ts
3 changes: 3 additions & 0 deletions packages/near-fast-auth-signer-e2e-tests/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
module.exports = {
globals: {
BigInt: true,
},
env: { browser: true, node: true },
parser: '@typescript-eslint/parser',
settings: {
Expand Down
5 changes: 4 additions & 1 deletion packages/near-fast-auth-signer-e2e-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
"@near-js/keystores": "^0.0.11",
"@near-js/transactions": "^1.2.1",
"@near-wallet-selector/core": "8.7.0",
"bitcoinjs-lib": "^6.1.5",
"borsh": "0.7.0",
"dotenv": "^16.4.5",
"canonicalize": "^2.0.0",
"firebase-admin": "^12.1.0",
"fs-extra": "^11.2.0",
"https-browserify": "^1.0.0",
"js-sha256": "^0.11.0",
"mailpop3": "^0.1.0",
"multichain-tools": "^1.0.12",
"near-api-js": "^2.1.4",
"near-fast-auth-signer": "*",
"near-fastauth-wallet": "^0.0.17",
Expand All @@ -48,6 +50,7 @@
"@types/node": "^20.9.0",
"@types/uuid": "^9.0.8",
"playwright": "^1.44.0",
"ts-node": "^10.9.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
Expand Down
91 changes: 91 additions & 0 deletions packages/near-fast-auth-signer-e2e-tests/scripts/faucet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const { ethers } = require('ethers');

interface WalletInfo {
address: string;
chain: string;
}

async function getProviderUrl(chain: string): Promise<string> {
switch (chain) {
case 'eth':
return process.env.ETH_PROVIDER_URL_TESTNET;
case 'bnb':
return process.env.BNB_PROVIDER_URL_TESTNET;
default:
throw new Error(`Unsupported chain: ${chain}`);
}
}

async function fetchEVMWalletBalance(address: string, chain: string): Promise<string> {
const providerUrl = await getProviderUrl(chain);
const provider = new ethers.JsonRpcProvider(providerUrl);
const balance = await provider.getBalance(address);
return ethers.formatEther(balance);
}

function getWalletChain(chain: string): string | null {
switch (chain) {
case 'eth':
return 'sepolia';
case 'bnb':
return 'bnb-testnet';
default:
return null;
}
}

async function fillWallet(address: string, chain: string): Promise<any> {
const walletChain = getWalletChain(chain);

if (!walletChain) {
throw new Error(`Unsupported chain: ${chain}`);
}

const apiUrl = `https://api.chainstack.com/v1/faucet/${walletChain}`;

const response = await fetch(apiUrl, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHAINSTACK_API_KEY as string}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ address }),
});

if (!response.ok) {
const text = await response.text();
throw new Error(text);
}

console.log(`Testnet token request for ${chain} address ${address} successful`);

return response.json();
}

async function requestTokensFromFaucet(wallets: WalletInfo[]): Promise<void> {
try {
const balances = await Promise.all(
wallets.map((wallet) => fetchEVMWalletBalance(wallet.address, wallet.chain))
);

const faucetRequests: Promise<any>[] = wallets.map((wallet, index) => {
if (parseFloat(balances[index]) === 0) {
return fillWallet(wallet.address, wallet.chain);
}
return Promise.resolve(null);
}).filter((request) => request !== null);

if (faucetRequests.length) {
await Promise.all(faucetRequests);
}
} catch (e) {
console.log('Error requesting token from faucet ', e.message);
}
}

const wallets: WalletInfo[] = [
{ address: '0xf64750f13f75fb9e2f4d9fd98ab72d742d1e33eb', chain: 'eth' },
{ address: '0x81d205120a9f04d3f1ce733c5ed0a0bc66714c71', chain: 'bnb' }
];

requestTokensFromFaucet(wallets);
11 changes: 11 additions & 0 deletions packages/near-fast-auth-signer-e2e-tests/test-app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { SignMessageParams } from '@near-wallet-selector/core';
import React, { useEffect, useState } from 'react';

import SignMultiChain, { TransactionFormValues } from './components/SignMultiChain';
import useWalletSelector from './hooks/useWalletSelector';
import {
getTransactionPayload,
} from '../utils/multiChain';

export default function App() {
const selectorInstance = useWalletSelector();
Expand Down Expand Up @@ -67,6 +71,12 @@ export default function App() {
}
};

const handleSubmitTransaction = async (values: TransactionFormValues) => {
const accountId = JSON.parse(window.localStorage.accountId);
const payload = await getTransactionPayload({ ...values, accountId });
await fastAuthWallet.signMultiChainTransaction(payload);
};

if (!selectorInstance || !fastAuthWallet || accounts === undefined) {
return (
<div id="loading-ws">Loading...</div>
Expand All @@ -92,6 +102,7 @@ export default function App() {
Sign In
</button>
)}
<SignMultiChain onSubmitForm={handleSubmitTransaction} />
<button
type="button"
data-testid="sign-transaction-button"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { yupResolver } from '@hookform/resolvers/yup';
import React from 'react';
import { useForm } from 'react-hook-form';
import * as yup from 'yup';

export type TransactionFormValues = {
keyType: string,
assetType: number,
amount: number,
address: string,
chainId: number,
}

type SignMultiChainProps = {
onSubmitForm: (_values: TransactionFormValues) => void
}

const schema = yup.object().shape({
keyType: yup
.string()
.required('Please select a key type'),
assetType: yup
.number()
.required('Please select an asset type'),
amount: yup
.number()
.required('Please enter amount'),
address: yup
.string()
.required('Please enter wallet address'),
chainId: yup
.number()
.required(),
});

const keyTypes = [
{ id: 'domainKey', value: 'domainKey', label: 'Domain Key' },
{ id: 'personalKey', value: 'personalKey', label: 'Personal Key' },
{ id: 'unknownKey', value: 'unknownKey', label: 'Unknown Key' },
];

const assetTypes = [
{
id: 'eth', value: 60, dataChainId: 11155111, label: 'ETH sepolia'
},
{
id: 'bnb', value: 60, dataChainId: 97, label: 'BSC testnet'
},
{
id: 'btc', value: 0, dataChainId: 0, label: 'BTC testnet'
},
];

export default function SignMultiChain(props: SignMultiChainProps) {
const { onSubmitForm } = props;

const {
handleSubmit, setValue, register,
} = useForm({
mode: 'all',
resolver: yupResolver(schema),
defaultValues: {}
});

const handleAssetTypeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setValue('chainId', parseInt(event.target.getAttribute('data-chainid'), 10));
};

const onSubmit = (values: TransactionFormValues) => onSubmitForm(values);

return (
<div
style={{
border: '1px solid #ddd', width: 'fit-content', margin: '15px 0'
}}
>
<h5>Sign MultiChain Transactions</h5>
<form
style={{
display: 'flex', flexDirection: 'column', gap: 5, margin: '5px'
}}
onSubmit={handleSubmit(onSubmit)}
>
<div
className="input-group"
style={{ display: 'flex', gap: 3, marginBottom: '5px' }}
>
{keyTypes.map((keyType) => (
<label htmlFor={keyType.id} className="radio-label" key={keyType.id}>
<input
type="radio"
id={keyType.id}
value={keyType.value}
{...register('keyType')}
/>
{keyType.label}
</label>
))}
</div>

<div
className="input-group"
style={{ display: 'flex', gap: 3, marginBottom: '5px' }}
>
{assetTypes.map((assetType) => (
<label htmlFor={assetType.id} className="radio-label" key={assetType.id}>
<input
type="radio"
id={assetType.id}
value={assetType.value}
data-chainid={assetType.dataChainId}
{...register('assetType')}
onChange={handleAssetTypeChange}
/>
{assetType.label}
</label>
))}
</div>

<div
className="input-group"
style={{ marginBottom: '10px' }}
>
<label htmlFor="amount" className="radio-label">
Amount
<input
type="text"
id="amount"
{...register('amount')}
style={{ marginLeft: '3px' }}
/>
</label>
</div>

<div
className="input-group"
style={{ marginBottom: '10px' }}
>
<label htmlFor="address" className="radio-label">
Address
<input
type="text"
id="address"
{...register('address')}
style={{ marginLeft: '3px' }}
/>
</label>
</div>
<button type="submit" style={{ width: 'fit-content', marginBottom: '15px' }}>
Submit
</button>
</form>
</div>
);
}
2 changes: 1 addition & 1 deletion packages/near-fast-auth-signer-e2e-tests/testAccounts.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"accounts": [],
"publicKeys": []
}
}
Loading
Loading