Skip to main content
Glama

create_gas_station

Create a new Aptos gas station project for fee sponsorship by specifying a project name to enable transaction cost coverage on the blockchain.

Instructions

Creates a new Aptos gas station (fee sponsorship) project.

Args:
    project_name: Name of the gas station project

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_nameYes

Implementation Reference

  • The main handler function for the 'create_gas_station' MCP tool. It creates a complete Aptos gas station project structure including server and client TypeScript code, package.json, tsconfig.json, .env, and README.md files by calling helper functions to generate the code templates.
    @mcp.tool()
    async def create_gas_station(project_name: str) -> str:
        """
        Creates a new Aptos gas station (fee sponsorship) project.
        
        Args:
            project_name: Name of the gas station project
        """
        project_name = project_name.strip().replace(" ", "-").lower()
        
        try:
            # Create project directory
            project_dir = os.path.join(os.getcwd(), project_name)
            if os.path.exists(project_dir):
                return f"Directory {project_dir} already exists. Please choose a different name."
            
            os.makedirs(project_dir)
            
            # Create server directory
            server_dir = os.path.join(project_dir, "server")
            os.makedirs(server_dir, exist_ok=True)
            
            # Create client directory
            client_dir = os.path.join(project_dir, "client")
            os.makedirs(client_dir, exist_ok=True)
            
            # Generate server files
            server_ts_path = os.path.join(server_dir, "server.ts")
            with open(server_ts_path, "w") as f:
                f.write(generate_gas_station_server())
            
            # Generate client files
            client_ts_path = os.path.join(client_dir, "client.ts")
            with open(client_ts_path, "w") as f:
                f.write(generate_gas_station_client())
            
            # Create package.json for server
            server_package_json = {
                "name": f"{project_name}-server",
                "version": "1.0.0",
                "description": "Aptos Gas Station Server for fee sponsorship",
                "main": "server.ts",
                "scripts": {
                    "build": "tsc",
                    "start": "ts-node server.ts"
                },
                "dependencies": {
                    "@aptos-labs/ts-sdk": "^1.2.0",
                    "express": "^4.18.2",
                    "dotenv": "^16.3.1"
                },
                "devDependencies": {
                    "@types/express": "^4.17.17",
                    "ts-node": "^10.9.1",
                    "typescript": "^5.1.6"
                }
            }
            
            with open(os.path.join(server_dir, "package.json"), "w") as f:
                json.dump(server_package_json, f, indent=2)
            
            # Create package.json for client
            client_package_json = {
                "name": f"{project_name}-client",
                "version": "1.0.0",
                "description": "Aptos Gas Station Client Example",
                "main": "client.ts",
                "scripts": {
                    "build": "tsc",
                    "start": "ts-node client.ts"
                },
                "dependencies": {
                    "@aptos-labs/ts-sdk": "^1.2.0",
                    "axios": "^1.4.0"
                },
                "devDependencies": {
                    "ts-node": "^10.9.1",
                    "typescript": "^5.1.6"
                }
            }
            
            with open(os.path.join(client_dir, "package.json"), "w") as f:
                json.dump(client_package_json, f, indent=2)
            
            # Create tsconfig.json files
            tsconfig = {
                "compilerOptions": {
                    "target": "es2020",
                    "module": "commonjs",
                    "esModuleInterop": True,
                    "forceConsistentCasingInFileNames": True,
                    "strict": True,
                    "skipLibCheck": True,
                    "outDir": "dist"
                }
            }
            
            with open(os.path.join(server_dir, "tsconfig.json"), "w") as f:
                json.dump(tsconfig, f, indent=2)
            
            with open(os.path.join(client_dir, "tsconfig.json"), "w") as f:
                json.dump(tsconfig, f, indent=2)
            
            # Create .env file for server
            env_content = """# Aptos Network: DEVNET, TESTNET, MAINNET
    APTOS_NETWORK=DEVNET
    
    # Port for the server
    PORT=3000
    
    # Optional: Fund gas account on start (true/false)
    AUTO_FUND_ACCOUNT=true
    """
            
            with open(os.path.join(server_dir, ".env"), "w") as f:
                f.write(env_content)
            
            # Create README.md
            readme_content = f"""# {project_name} - Aptos Gas Station
    
    A gas station implementation for Aptos that allows fee sponsorship (fee payer) for transactions.
    
    ## Structure
    
    - `server/`: Gas station server that acts as a fee payer
    - `client/`: Example client that uses the gas station
    
    ## Server Setup
    
    1. Navigate to the server directory:
       ```
       cd server
       ```
    
    2. Install dependencies:
       ```
       npm install
       ```
    
    3. Configure your environment:
       Edit the `.env` file to customize your setup.
    
    4. Start the server:
       ```
       npm start
       ```
    
    ## Client Example
    
    The client directory contains an example of how to use the gas station to submit transactions without paying gas fees.
    
    1. Navigate to the client directory:
       ```
       cd client
       ```
    
    2. Install dependencies:
       ```
       npm install
       ```
    
    3. Run the example:
       ```
       npm start
       ```
    
    ## How It Works
    
    1. Client builds a transaction and signs it
    2. Client sends the transaction to the gas station
    3. Gas station signs the transaction as a fee payer
    4. Gas station submits the transaction to the blockchain
    5. Original transaction executes with fees paid by the gas station
    
    ## Security Considerations
    
    - Implement proper authentication for production
    - Add rate limiting to prevent abuse
    - Monitor gas usage to control costs
    """
            
            with open(os.path.join(project_dir, "README.md"), "w") as f:
                f.write(readme_content)
            
            return f"""
    Successfully created Aptos Gas Station project at {project_dir}!
    
    The project includes:
    - Server implementation (Express.js)
    - Client example code
    - Configuration files
    
    Next steps:
    1. Navigate to the server directory: `cd {project_name}/server`
    2. Install dependencies: `npm install`
    3. Configure your environment in .env
    4. Start the server: `npm start`
    
    To try the client example:
    1. Navigate to the client directory: `cd {project_name}/client`
    2. Install dependencies: `npm install`
    3. Run the example: `npm start`
    
    See the README.md file for more information.
    """
        
        except Exception as e:
            return f"Error creating gas station project: {str(e)}"
  • The @mcp.tool() decorator registers the create_gas_station function as an MCP tool.
    @mcp.tool()
  • Helper function that generates the complete TypeScript code for the gas station Express server, including endpoints for signing and submitting sponsored transactions.
    def generate_gas_station_server() -> str:
        """Generate the server code for a gas station"""
        return """import express, { Request, Response } from 'express';
    import {
        Account, AccountAuthenticator,
        Aptos,
        AptosConfig,
        Deserializer,
        Network,
        NetworkToNetworkName,
        SimpleTransaction,
    } from '@aptos-labs/ts-sdk';
    import dotenv from 'dotenv';
    
    dotenv.config();
    
    const app = express();
    app.use(express.json());
    
    const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000;
    
    const APTOS_NETWORK = NetworkToNetworkName[process.env.APTOS_NETWORK || ''] || Network.DEVNET;
    
    const config = new AptosConfig({network: APTOS_NETWORK});
    const aptos = new Aptos(config);
    
    const feePayerAccount = Account.generate();
    console.log(`Gas Station Account Address: ${feePayerAccount.accountAddress.toString()}`);
    
    // Fund the feePayerAccount account
    const fundFeePayerAccount = async () => {
        console.log('=== Funding Gas Station Account ===');
        try {
            await aptos.fundAccount({
                accountAddress: feePayerAccount.accountAddress,
                amount: 100_000_000,
            });
            console.log('Gas Station Account funded successfully.');
        } catch (error) {
            console.error('Error funding Gas Station Account:', error);
            console.log('Note: Automatic funding only works on DEVNET. On other networks, manually fund this address.');
        }
    };
    
    app.post('/signAndSubmit', async (req: Request, res: Response) => {
        try {
            const {transactionBytes, senderAuthenticator} = req.body;
    
            if (!transactionBytes) {
                return res.status(400).json({error: 'transactionBytes is required'});
            }
            if (!senderAuthenticator) {
                return res.status(400).json({error: 'senderAuthenticator is required'});
            }
    
            console.log('=== Received Transaction Request ===');
    
            // Deserialize the raw transaction
            const deserializer = new Deserializer(Uint8Array.from(transactionBytes));
            const transaction = SimpleTransaction.deserialize(deserializer);
    
            console.log('=== Signing Transaction as Fee Payer ===');
    
            // Gas station signs the transaction as fee payer
            const feePayerAuthenticator = aptos.transaction.signAsFeePayer({
                signer: feePayerAccount,
                transaction,
            });
    
            const deserializedSenderAuth = AccountAuthenticator.deserialize(new Deserializer(Uint8Array.from(senderAuthenticator)));
    
            console.log('=== Submitting Sponsored Transaction ===');
            const signedTxnInput = {
                transaction,
                senderAuthenticator: deserializedSenderAuth,
                feePayerAuthenticator,
            };
            let response = await aptos.transaction.submit.simple(signedTxnInput);
            
            console.log(`Transaction submitted. Hash: ${response.hash}`);
            await aptos.waitForTransaction({transactionHash: response.hash});
            console.log('Transaction executed successfully!');
    
            return res.status(200).json({
                transactionHash: response.hash,
                message: 'Transaction sponsored and executed successfully',
                feePayerAddress: feePayerAccount.accountAddress.toString()
            });
        } catch (error) {
            console.error('Error processing transaction:', error);
            return res.status(500).json({error: String(error)});
        }
    });
    
    // Health check endpoint
    app.get('/health', (req: Request, res: Response) => {
        return res.status(200).json({
            status: 'healthy',
            network: APTOS_NETWORK,
            feePayerAddress: feePayerAccount.accountAddress.toString()
        });
    });
    
    app.listen(PORT, async () => {
        console.log(`Gas Station Server running on http://localhost:${PORT}`);
        if (process.env.AUTO_FUND_ACCOUNT === 'true') {
            await fundFeePayerAccount();
        }
    });
    """
  • Helper function that generates the TypeScript client example code demonstrating how to build, sign, and submit a transaction via the gas station for fee sponsorship.
    def generate_gas_station_client() -> str:
        """Generate the client code for a gas station"""
        return """import axios from 'axios';
    import { Account, Aptos, AptosConfig, Network, } from '@aptos-labs/ts-sdk';
    
    const GAS_STATION_URL = "http://localhost:3000";
    
    const main = async () => {
        const config = new AptosConfig({ network: Network.DEVNET });
        const aptos = new Aptos(config);
    
        console.log("=== Aptos Gas Station Client Demo ===");
        
        // Create sender and recipient accounts
        const alice = Account.generate();
        const bob = Account.generate();
    
        console.log("Alice's address:", alice.accountAddress.toString());
        console.log("Bob's address:", bob.accountAddress.toString());
    
        // Fund Alice's account (the transaction sender, but not fee payer)
        console.log("\\n=== Funding Alice's account ===");
        await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: 100_000_000 });
        console.log("Alice's account funded");
    
        // Build a transaction (Alice sending APT to Bob)
        console.log("\\n=== Building transaction ===");
        const transaction = await aptos.transaction.build.simple({
            sender: alice.accountAddress,
            withFeePayer: true,  // Important: Mark that this transaction will have a fee payer
            data: {
                function: "0x1::aptos_account::transfer",
                functionArguments: [bob.accountAddress, 100],  // Sending 100 octas to Bob
            },
        });
        
        console.log("Transaction built successfully");
    
        // Alice signs the transaction (but doesn't pay for gas)
        console.log("\\n=== Alice signing transaction ===");
        const senderAuthenticator = aptos.transaction.sign({ signer: alice, transaction });
        console.log("Transaction signed by Alice");
    
        // Send the transaction to the gas station for fee sponsorship
        console.log("\\n=== Sending to Gas Station for sponsorship ===");
        try {
            const response = await axios.post(
                `${GAS_STATION_URL}/signAndSubmit`,
                {
                    transactionBytes: Array.from(transaction.bcsToBytes()),
                    senderAuthenticator: Array.from(senderAuthenticator.bcsToBytes()),
                },
                {
                    headers: {
                        "Content-Type": "application/json",
                    },
                }
            );
    
            const { transactionHash, feePayerAddress } = response.data;
    
            console.log("Transaction sponsored by:", feePayerAddress);
            console.log("Transaction submitted. Hash:", transactionHash);
            
            // Wait for transaction to be executed
            console.log("\\n=== Waiting for transaction execution ===");
            const executedTx = await aptos.waitForTransaction({ transactionHash });
            console.log("Transaction executed successfully!");
            
            // Verify Bob received the funds
            console.log("\\n=== Checking Bob's balance ===");
            const bobBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress });
            console.log("Bob's balance:", bobBalance, "octas");
            
        } catch (error) {
            console.error("Error:", error.response?.data || error.message);
        }
    };
    
    main();
    """

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tlazypanda/aptos-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server