Skip to content
Merged
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
1,266 changes: 1,266 additions & 0 deletions docs/EIP7702-Implementierungsplan.md

Large diffs are not rendered by default.

676 changes: 676 additions & 0 deletions docs/gasless-token-transfer-analysis.md

Large diffs are not rendered by default.

107 changes: 107 additions & 0 deletions e2e/api/test-gasless-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Test Gasless API Response and Pimlico Paymaster
* Run: API_URL=http://localhost:3000/v1 npx tsx e2e/api/test-gasless-api.ts
*/

import { ethers } from 'ethers';
import * as dotenv from 'dotenv';
import path from 'path';

dotenv.config({ path: path.join(process.cwd(), '.env.test') });

const API_URL = process.env.API_URL || 'http://localhost:3000';
const TEST_SEED = process.env.TEST_SEED_2 || '';

async function test() {
if (!TEST_SEED) {
console.error('ERROR: TEST_SEED_2 not set in .env.test');
process.exit(1);
}

const wallet = ethers.Wallet.fromPhrase(TEST_SEED);
console.log('=== Test Gasless API Response ===');
console.log('Wallet 2:', wallet.address);
console.log('API:', API_URL);

// 1. Get auth token
const signMsgRes = await fetch(`${API_URL}/auth/signMessage?address=${wallet.address}`);
const signMsgData = await signMsgRes.json();
const signature = await wallet.signMessage(signMsgData.message);

const authRes = await fetch(`${API_URL}/auth`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ address: wallet.address, signature }),
});
const authData = await authRes.json();
console.log('\n✓ Auth token obtained');

// 2. Get sell payment info with includeTx=true
const sellRes = await fetch(`${API_URL}/sell/paymentInfos?includeTx=true`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${authData.accessToken}`,
},
body: JSON.stringify({
iban: 'CH93 0076 2011 6238 5295 7',
asset: { id: 407 }, // Sepolia USDT
amount: 0.01,
currency: { id: 2 }, // EUR
}),
});
const sellData = await sellRes.json();

console.log('\n=== API Response ===');
console.log('Status:', sellRes.status);
console.log('gaslessAvailable:', sellData.gaslessAvailable);
console.log('has depositTx:', !!sellData.depositTx);
console.log('has depositTx.eip5792:', !!sellData.depositTx?.eip5792);

if (sellData.depositTx?.eip5792) {
console.log('\n=== EIP-5792 Data ===');
console.log('paymasterUrl:', sellData.depositTx.eip5792.paymasterUrl);
console.log('chainId:', sellData.depositTx.eip5792.chainId);
console.log('calls:', JSON.stringify(sellData.depositTx.eip5792.calls, null, 2));

// 3. Test paymaster URL directly
console.log('\n=== Testing Pimlico Paymaster ===');
const paymasterUrl = sellData.depositTx.eip5792.paymasterUrl;

const testRes = await fetch(paymasterUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'pm_getPaymasterStubData',
params: [
{
sender: wallet.address,
nonce: '0x0',
callData: '0x',
callGasLimit: '0x0',
verificationGasLimit: '0x0',
preVerificationGas: '0x0',
maxFeePerGas: '0x0',
maxPriorityFeePerGas: '0x0',
},
'0x0000000071727De22E5E9d8BAf0edAc6f37da032',
'0xaa36a7',
],
}),
});
const paymasterData = await testRes.json();
console.log('Paymaster response:', JSON.stringify(paymasterData, null, 2));
}

if (sellData.error || sellData.message) {
console.log('\n❌ API Error:', sellData.message || sellData.error);
}

// Show full response for debugging
console.log('\n=== Full Response ===');
console.log(JSON.stringify(sellData, null, 2));
}

test().catch((e) => console.error('Error:', e.message));
55 changes: 55 additions & 0 deletions e2e/api/test-metamask-capabilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Test MetaMask EIP-5792 Capabilities
*
* This script injects into a browser page to check what wallet_getCapabilities returns.
* Run after MetaMask is connected.
*/

const checkCapabilities = async () => {
const ethereum = (window as any).ethereum;
if (!ethereum) {
console.error('MetaMask not installed');
return;
}

try {
const accounts = await ethereum.request({ method: 'eth_accounts' });
console.log('Connected account:', accounts[0]);

const capabilities = await ethereum.request({
method: 'wallet_getCapabilities',
params: [accounts[0]],
});

console.log('=== wallet_getCapabilities ===');
console.log(JSON.stringify(capabilities, null, 2));

// Check Sepolia (chainId 11155111 = 0xaa36a7)
const sepoliaHex = '0xaa36a7';
const sepoliaCapabilities = capabilities?.[sepoliaHex];

console.log('\n=== Sepolia Capabilities ===');
console.log('atomic:', sepoliaCapabilities?.atomic);
console.log('paymasterService:', sepoliaCapabilities?.paymasterService);

if (sepoliaCapabilities?.paymasterService?.supported) {
console.log('✓ paymasterService is SUPPORTED on Sepolia');
} else {
console.log('✗ paymasterService is NOT supported on Sepolia');
console.log('User may need to upgrade to Smart Account first');
}

if (sepoliaCapabilities?.atomic?.status === 'ready') {
console.log('→ Status "ready": MetaMask will prompt to upgrade to Smart Account');
} else if (sepoliaCapabilities?.atomic?.status === 'supported') {
console.log('→ Status "supported": Smart Account already active');
}

} catch (e: any) {
console.error('Error:', e.message || e);
}
};

// Export for use in browser console
(window as any).checkCapabilities = checkCapabilities;
console.log('Run checkCapabilities() to test');
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion e2e/synpress/sell-complete.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const CONFIG = {
USER_DATA_DIR: path.join(process.cwd(), '.cache-synpress/user-data-test'),
WALLET_PASSWORD: 'Tester@1234',
FRONTEND_URL: 'http://localhost:3001',
USDT_AMOUNT: '0.01',
USDT_AMOUNT: '10',
POPUP_TIMEOUT: 10000,
};

Expand Down
Loading
Loading