Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
335 changes: 323 additions & 12 deletions e2e/arbitrum/lbtcUsdt0.spec.ts

Large diffs are not rendered by default.

316 changes: 173 additions & 143 deletions e2e/fixtures/ethereum.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { test as base } from "@playwright/test";
import { type Page, test as base } from "@playwright/test";
import {
type Chain,
type PublicClient,
createPublicClient,
createWalletClient,
defineChain,
Expand All @@ -20,6 +22,170 @@ type EthereumFixtures = {
injectProvider: () => Promise<void>;
};

export const injectWalletProvider = async ({
page,
publicClient,
walletClient,
chain,
}: {
page: Page;
publicClient: PublicClient;
walletClient: ReturnType<typeof createWalletClient>;
chain: Chain;
}) => {
await page.exposeFunction(
"__rpc",
async (method: string, params: unknown[]) => {
return await publicClient.request({
method,
params,
} as never);
},
);

await page.exposeFunction(
"__sendTx",
async (tx: {
to?: string;
value?: string;
data?: string;
gas?: string;
gasPrice?: string;
maxFeePerGas?: string;
maxPriorityFeePerGas?: string;
nonce?: string;
}) => {
return await walletClient.sendTransaction({
account: walletClient.account,
chain,
to: tx.to as `0x${string}` | undefined,
value: tx.value ? BigInt(tx.value) : undefined,
data: tx.data as `0x${string}` | undefined,
gas: tx.gas ? BigInt(tx.gas) : undefined,
gasPrice: tx.gasPrice ? BigInt(tx.gasPrice) : undefined,
maxFeePerGas: tx.maxFeePerGas
? BigInt(tx.maxFeePerGas)
: undefined,
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
? BigInt(tx.maxPriorityFeePerGas)
: undefined,
nonce: tx.nonce ? Number(tx.nonce) : undefined,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any);
},
);

const walletAddress = walletClient.account!.address;
const chainIdHex = "0x" + chain.id.toString(16);

await page.addInitScript(
({ addr, chainId }) => {
const listeners: Record<
string,
Array<(...args: unknown[]) => void>
> = {};

const provider = {
isMetaMask: true,
isConnected: () => true,
chainId,
selectedAddress: addr,

request: async ({
method,
params,
}: {
method: string;
params?: unknown[];
}) => {
switch (method) {
case "eth_requestAccounts":
case "eth_accounts":
return [addr];
case "eth_chainId":
return chainId;
case "net_version":
return String(parseInt(chainId, 16));
case "wallet_switchEthereumChain":
setTimeout(() => {
(listeners["chainChanged"] || []).forEach(
(cb) => cb(chainId),
);
}, 100);
return null;
case "wallet_addEthereumChain":
return null;
case "eth_sendTransaction":
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
return await (window as any).__sendTx(
(params as unknown[])[0],
);
default:
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
return await (window as any).__rpc(
method,
params || [],
);
}
},

send: (method: string, params?: unknown[]) =>
provider.request({ method, params }),

on: (event: string, callback: (...args: unknown[]) => void) => {
if (!listeners[event]) listeners[event] = [];
listeners[event].push(callback);
},
removeListener: (
event: string,
callback: (...args: unknown[]) => void,
) => {
if (listeners[event]) {
listeners[event] = listeners[event].filter(
(cb) => cb !== callback,
);
}
},
removeAllListeners: (event?: string) => {
if (event) {
delete listeners[event];
} else {
Object.keys(listeners).forEach(
(key) => delete listeners[key],
);
}
},
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).ethereum = provider;

const announceProvider = () => {
window.dispatchEvent(
new CustomEvent("eip6963:announceProvider", {
detail: Object.freeze({
info: {
uuid: "playwright-mock",
name: "MetaMask",
icon: "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'/>",
rdns: "io.metamask",
},
provider,
}),
}),
);
};

window.addEventListener(
"eip6963:requestProvider",
announceProvider,
);
announceProvider();
},
{ addr: walletAddress, chainId: chainIdHex },
);
};

export const test = base.extend<EthereumFixtures>({
// eslint-disable-next-line no-empty-pattern
walletClient: async ({}, use) => {
Expand Down Expand Up @@ -54,148 +220,12 @@ export const test = base.extend<EthereumFixtures>({
transport: http(),
});

await page.exposeFunction(
"__rpc",
async (method: string, params: unknown[]) => {
return await publicClient.request({
method,
params,
} as never);
},
);

await page.exposeFunction(
"__sendTx",
async (tx: {
to?: string;
value?: string;
data?: string;
gas?: string;
}) => {
return await walletClient.sendTransaction({
account: walletClient.account,
chain: rskRegtest,
to: tx.to as `0x${string}`,
value: tx.value ? BigInt(tx.value) : undefined,
data: tx.data as `0x${string}`,
gas: tx.gas ? BigInt(tx.gas) : undefined,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any);
},
);

const walletAddress = walletClient.account!.address;
const chainIdHex = "0x" + rskRegtest.id.toString(16);

await page.addInitScript(
({ addr, chainId }) => {
const listeners: Record<
string,
Array<(...args: unknown[]) => void>
> = {};

const provider = {
isMetaMask: true,
isConnected: () => true,
chainId,
selectedAddress: addr,

request: async ({
method,
params,
}: {
method: string;
params?: unknown[];
}) => {
switch (method) {
case "eth_requestAccounts":
case "eth_accounts":
return [addr];
case "eth_chainId":
return chainId;
case "net_version":
return String(parseInt(chainId, 16));
case "wallet_switchEthereumChain":
setTimeout(() => {
(
listeners["chainChanged"] || []
).forEach((cb) => cb(chainId));
}, 100);
return null;
case "wallet_addEthereumChain":
return null;
case "eth_sendTransaction":
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
return await (window as any).__sendTx(
(params as unknown[])[0],
);
default:
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
return await (window as any).__rpc(
method,
params || [],
);
}
},

send: (method: string, params?: unknown[]) =>
provider.request({ method, params }),

on: (
event: string,
callback: (...args: unknown[]) => void,
) => {
if (!listeners[event]) listeners[event] = [];
listeners[event].push(callback);
},
removeListener: (
event: string,
callback: (...args: unknown[]) => void,
) => {
if (listeners[event]) {
listeners[event] = listeners[event].filter(
(cb) => cb !== callback,
);
}
},
removeAllListeners: (event?: string) => {
if (event) {
delete listeners[event];
} else {
Object.keys(listeners).forEach(
(key) => delete listeners[key],
);
}
},
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).ethereum = provider;

const announceProvider = () => {
window.dispatchEvent(
new CustomEvent("eip6963:announceProvider", {
detail: Object.freeze({
info: {
uuid: "playwright-mock",
name: "MetaMask",
icon: "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'/>",
rdns: "io.metamask",
},
provider,
}),
}),
);
};

window.addEventListener(
"eip6963:requestProvider",
announceProvider,
);
announceProvider();
},
{ addr: walletAddress, chainId: chainIdHex },
);
await injectWalletProvider({
page,
publicClient,
walletClient,
chain: rskRegtest,
});
};

await use(inject);
Expand Down
7 changes: 7 additions & 0 deletions src/components/Fees.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ const Fees = () => {
}

const initiatingPair = pair();
if (initiatingPair.needsNetworkForQuote) {
setMinimum(0);
setMaximum(Number.MAX_SAFE_INTEGER);
setLimitsLoading(false);
return;
}

setLimitsLoading(true);
void Promise.all([
initiatingPair.getMinimum(),
Expand Down
6 changes: 6 additions & 0 deletions src/components/LockupEvm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ const LockupEvm = (props: {
timeoutBlockHeight: number;
hops?: EncodedHop[];
bridge?: BridgeDetail;
bridgeAmount?: bigint;
}) => {
const { slippage } = useGlobalContext();
const { getErc20Swap, signer } = useWeb3Signer();
Expand Down Expand Up @@ -623,6 +624,11 @@ const LockupEvm = (props: {
createEffect(() => {
void (async () => {
if (props.bridge !== undefined) {
if (props.bridgeAmount !== undefined) {
setBridgeValue(props.bridgeAmount);
return;
}

if (!hasHopsBefore() || props.hops === undefined) {
throw new Error(
`bridge swap ${props.swapId} is missing a lockup-side DEX hop`,
Expand Down
5 changes: 4 additions & 1 deletion src/configs/regtest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { AssetKind, Explorer, NetworkTransport } from "boltz-swaps/types";
import { type Config, baseConfig, chooseUrl } from "src/configs/base";

const mainnetPreset = buildMainnetConfig({
filterAssets: (asset) => asset === "TBTC" || asset === "USDT0",
filterAssets: (asset) =>
asset === "TBTC" || asset === "USDT0" || asset === "USDT0-ETH",
rpcUrls: {
ARB: ["http://127.0.0.1:18545"],
ETH: ["http://127.0.0.1:18546"],
},
});

Expand All @@ -18,6 +20,7 @@ const stablecoins = {
},
},
USDT0: mainnetPreset.assets.USDT0,
"USDT0-ETH": mainnetPreset.assets["USDT0-ETH"],
};

const config = {
Expand Down
Loading
Loading