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