Prerequisites
Before running the script, ensure you have the following installed: Python:- Python 3.10
- Web3 (
pip install web3
) - Requests (
pip install requests
)
- Node.js 18+
- TypeScript (
npm install -g typescript
) - Web3 (
npm install web3
) - Axios (
npm install axios
)
- Node.js 18+
- Web3 (
npm install web3
) - Axios (
npm install axios
)
Setup and Configuration
Copy
from web3 import Web3
import requests
import json
import time
# Configuration
API_KEY = "your_api_key"
UNIQUE_PID = "your_unique_pid"
QUOTE_ENDPOINT = "https://router.gluex.xyz/v1/quote"
RPC_URL = "https://mainnet.gateway.tenderly.co/your_rpc_url"
PRIVATE_KEY = "your_private_key"
# Token Addresses
USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" # USDC on Ethereum
ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" # ETH on Ethereum
INPUT_AMOUNT = 1000000 # 1 USDC (6 decimals)
# Initialize Web3
web3 = Web3(Web3.HTTPProvider(RPC_URL))
account = web3.eth.account.from_key(PRIVATE_KEY)
COMPUTATION_UNITS = 1000000
COMPUTATION_COST = web3.eth.gas_price
Fetching a Swap Quote
Before executing the transaction, fetch a quote from the GlueX RouterCopy
def fetch_quote():
"""Fetch a quote from the GlueX Router for $USDC to $ETH swap"""
headers = {"x-api-key": API_KEY}
body = {
"chainID": "1", # Ethereum Mainnet
"userAddress": account.address,
"outputReceiver": account.address,
"uniquePID": UNIQUE_PID,
"inputToken": USDC_ADDRESS,
"outputToken": ETH_ADDRESS,
"inputAmount": INPUT_AMOUNT,
"isPermit2": False
}
response = requests.post(QUOTE_ENDPOINT, json=body, headers=headers)
return response.json()
Approving the Router Contract
Before executing the swap, the router contract needs permission to spend the user’s USDC tokensCopy
def approve_spender(spender, amount, token_address):
"""Approve the router contract to spend $USDC"""
signature = "0x095ea7b3"
padded_spender = Web3.to_checksum_address(spender)[2:].zfill(64)
calldata = f"{signature}{padded_spender}{int(amount):064x}"
txn = {
"from": account.address,
"to": Web3.to_checksum_address(token_address),
"data": calldata,
"gas": COMPUTATION_UNITS,
"gasPrice": web3.eth.gas_price,
"nonce": web3.eth.get_transaction_count(account.address),
"chainId": 1, # Ethereum mainnet
}
signed_txn = web3.eth.account.sign_transaction(txn, account.key)
txn_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Approval Transaction Hash: {web3.to_hex(txn_hash)}")
return txn_hash
Executing the Transaction
After approval, we execute the transaction using the calldata from the quoteCopy
def execute_transaction(calldata, router_address):
"""Execute the swap transaction on GlueX Router"""
txn = {
"from": account.address,
"to": Web3.to_checksum_address(router_address),
"data": calldata,
"gas": COMPUTATION_UNITS,
"gasPrice": web3.eth.gas_price,
"nonce": web3.eth.get_transaction_count(account.address),
"chainId": 1, # Ethereum mainnet
}
signed_txn = web3.eth.account.sign_transaction(txn, account.key)
try:
txn_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
except Web3RPCError as err:
time.sleep(5)
txn["nonce"] = web3.eth.get_transaction_count(account.address)
signed_txn = web3.eth.account.sign_transaction(txn, account.key)
txn_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction Hash: {web3.to_hex(txn_hash)}")
return txn_hash
Putting Everything Together
Copy
def main():
# Fetch the quote
quote_data = fetch_quote()
if quote_data.get('statusCode') != 200:
print("Error fetching quote:", quote_data)
return
print("Quote received successfully:", quote_data)
router_address = quote_data["result"]["router"]
calldata = quote_data["result"]["calldata"]
# Approve the router contract
print("Approving router contract to spend USDC...")
txn_hash = approve_spender(router_address, INPUT_AMOUNT, USDC_ADDRESS)
print("Waiting for approval transaction confirmation...")
approval_receipt = web3.eth.wait_for_transaction_receipt(txn_hash)
if approval_receipt.status != 1:
print("Approval failed. Aborting.")
return
# Execute the transaction
print("Executing transaction...")
execute_txn = execute_transaction(calldata, router_address)
receipt = web3.eth.wait_for_transaction_receipt(execute_txn)
print("Transaction confirmed. Receipt:")
print(receipt)
if __name__ == "__main__":
main()
Complete Code Implementation
Complete Python Implementation
Complete Python Implementation
Copy
from web3 import Web3
from web3.exceptions import Web3RPCError
import requests
import json
import time
# Configuration
API_KEY = "your_api_key"
UNIQUE_PID = "your_unique_pid"
QUOTE_ENDPOINT = "https://router.gluex.xyz/v1/quote"
RPC_URL = "https://mainnet.gateway.tenderly.co/your_rpc_url"
PRIVATE_KEY = "your_private_key"
# Token Addresses
USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" # USDC on Ethereum
ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" # ETH on Ethereum
INPUT_AMOUNT = 1000000 # 1 USDC (6 decimals)
# Initialize Web3
web3 = Web3(Web3.HTTPProvider(RPC_URL))
account = web3.eth.account.from_key(PRIVATE_KEY)
COMPUTATION_UNITS = 1000000
COMPUTATION_COST = web3.eth.gas_price
def fetch_quote():
"""Fetch a quote from the GlueX Router for $USDC to $ETH swap"""
headers = {"x-api-key": API_KEY}
body = {
"chainID": "1", # Ethereum Mainnet
"userAddress": account.address,
"outputReceiver": account.address,
"uniquePID": UNIQUE_PID,
"inputToken": USDC_ADDRESS,
"outputToken": ETH_ADDRESS,
"inputAmount": INPUT_AMOUNT,
"isPermit2": False
}
response = requests.post(QUOTE_ENDPOINT, json=body, headers=headers)
return response.json()
def approve_spender(spender, amount, token_address):
"""Approve the router contract to spend $USDC"""
signature = "0x095ea7b3"
padded_spender = Web3.to_checksum_address(spender)[2:].zfill(64)
calldata = f"{signature}{padded_spender}{int(amount):064x}"
txn = {
"from": account.address,
"to": Web3.to_checksum_address(token_address),
"data": calldata,
"gas": COMPUTATION_UNITS,
"gasPrice": web3.eth.gas_price,
"nonce": web3.eth.get_transaction_count(account.address),
"chainId": 1, # Ethereum mainnet
}
signed_txn = web3.eth.account.sign_transaction(txn, account.key)
txn_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Approval Transaction Hash: {web3.to_hex(txn_hash)}")
return txn_hash
def execute_transaction(calldata, router_address):
"""Execute the swap transaction on GlueX Router"""
txn = {
"from": account.address,
"to": Web3.to_checksum_address(router_address),
"data": calldata,
"gas": COMPUTATION_UNITS,
"gasPrice": web3.eth.gas_price,
"nonce": web3.eth.get_transaction_count(account.address),
"chainId": 1, # Ethereum mainnet
}
signed_txn = web3.eth.account.sign_transaction(txn, account.key)
try:
txn_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
except Web3RPCError as err:
time.sleep(5)
txn["nonce"] = web3.eth.get_transaction_count(account.address)
signed_txn = web3.eth.account.sign_transaction(txn, account.key)
txn_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction Hash: {web3.to_hex(txn_hash)}")
return txn_hash
def main():
# Fetch the quote
quote_data = fetch_quote()
if quote_data.get('statusCode') != 200:
print("Error fetching quote:", quote_data)
return
print("Quote received successfully:", quote_data)
router_address = quote_data["result"]["router"]
calldata = quote_data["result"]["calldata"]
# Approve the router contract
print("Approving router contract to spend USDC...")
txn_hash = approve_spender(router_address, INPUT_AMOUNT, USDC_ADDRESS)
print("Waiting for approval transaction confirmation...")
approval_receipt = web3.eth.wait_for_transaction_receipt(txn_hash)
if approval_receipt.status != 1:
print("Approval failed. Aborting.")
return
# Execute the transaction
print("Executing transaction...")
execute_txn = execute_transaction(calldata, router_address)
receipt = web3.eth.wait_for_transaction_receipt(execute_txn)
print("Transaction confirmed. Receipt:")
print(receipt)
if __name__ == "__main__":
main()
Complete TypeScript Implementation
Complete TypeScript Implementation
Copy
import { Web3 } from 'web3';
import axios from 'axios';
// Configuration
const API_KEY = "your_api_key";
const UNIQUE_PID = "your_unique_pid";
const QUOTE_ENDPOINT = "https://router.gluex.xyz/v1/quote";
const RPC_URL = "https://mainnet.gateway.tenderly.co/your_rpc_url";
const PRIVATE_KEY = "your_private_key";
// Token Addresses
const USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; // USDC on Ethereum
const ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; // ETH on Ethereum
const INPUT_AMOUNT = BigInt("1000000"); // 1 USDC (6 decimals)
// Initialize Web3
const web3 = new Web3(RPC_URL);
const account = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
const COMPUTATION_UNITS = 1000000;
// Types
interface QuoteBody {
chainID: string;
userAddress: string;
outputReceiver: string;
uniquePID: string;
inputToken: string;
outputToken: string;
inputAmount: bigint;
isPermit2: boolean;
}
interface QuoteRequestBody {
chainID: string;
userAddress: string;
outputReceiver: string;
uniquePID: string;
inputToken: string;
outputToken: string;
inputAmount: string;
isPermit2: boolean;
}
interface QuoteResponse {
statusCode: number;
result?: {
router: string;
calldata: string;
};
}
const fetchQuote = async (body: QuoteRequestBody, headers: { [key: string]: string }): Promise<QuoteResponse> => {
console.log("Fetch a quote from the GlueX Router for $USDC to $ETH swap");
const response = await axios.post(QUOTE_ENDPOINT, body, { headers });
return response.data;
};
const approveSpender = async (
spender: string,
amount: bigint,
tokenAddress: string
): Promise<string> => {
const signature = "0x095ea7b3";
const paddedSpender = web3.utils.toChecksumAddress(spender).slice(2).padStart(64, '0');
const calldata = `${signature}${paddedSpender}${amount.toString(16).padStart(64, '0')}`;
const txn = {
from: account.address,
to: web3.utils.toChecksumAddress(tokenAddress),
data: calldata,
gas: COMPUTATION_UNITS,
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(account.address),
chainId: 1, // Ethereum mainnet
};
const signedTxn = await account.signTransaction(txn);
const receipt = await web3.eth.sendSignedTransaction(signedTxn.rawTransaction);
const txHash = web3.utils.toHex(receipt.transactionHash);
console.log(`Approval Transaction Hash: ${txHash}`);
return txHash;
};
const executeTransaction = async (
calldata: string,
routerAddress: string
): Promise<string> => {
const txn = {
from: account.address,
to: web3.utils.toChecksumAddress(routerAddress),
data: calldata,
gas: COMPUTATION_UNITS,
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(account.address),
chainId: 1, // Ethereum mainnet
};
try {
const signedTxn = await account.signTransaction(txn);
const receipt = await web3.eth.sendSignedTransaction(signedTxn.rawTransaction);
const txHash = web3.utils.toHex(receipt.transactionHash);
console.log(`Transaction Hash: ${txHash}`);
return txHash;
} catch (err) {
await new Promise(resolve => setTimeout(resolve, 5000));
txn.nonce = await web3.eth.getTransactionCount(account.address);
const signedTxn = await account.signTransaction(txn);
const receipt = await web3.eth.sendSignedTransaction(signedTxn.rawTransaction);
const txHash = web3.utils.toHex(receipt.transactionHash);
console.log(`Transaction Hash: ${txHash}`);
return txHash;
}
};
const main = async (): Promise<void> => {
const headers = { "x-api-key": API_KEY };
const body: QuoteBody = {
chainID: "1", // Ethereum Mainnet
userAddress: account.address,
outputReceiver: account.address,
uniquePID: UNIQUE_PID,
inputToken: USDC_ADDRESS,
outputToken: ETH_ADDRESS,
inputAmount: INPUT_AMOUNT,
isPermit2: false
};
// Convert BigInt to string for axios serialization
const requestBody = {
...body,
inputAmount: body.inputAmount.toString()
};
console.log("Fetching swap quote...");
const quoteData = await fetchQuote(requestBody, headers);
if (quoteData.statusCode !== 200) {
console.log("Error fetching quote:", quoteData);
return;
}
console.log("Quote received successfully:", quoteData);
const routerAddress = quoteData.result!.router;
const calldata = quoteData.result!.calldata;
// Approve the router contract
console.log("Approving router contract to spend USDC...");
const txnHash = await approveSpender(routerAddress, INPUT_AMOUNT, USDC_ADDRESS);
console.log("Waiting for approval transaction confirmation...");
const approvalReceipt = await web3.eth.getTransactionReceipt(txnHash);
if (!approvalReceipt || !approvalReceipt.status) {
console.log("Approval failed. Aborting.");
return;
}
// Execute the transaction
console.log("Executing transaction...");
const executeTxn = await executeTransaction(calldata, routerAddress);
const receipt = await web3.eth.getTransactionReceipt(executeTxn);
console.log("Transaction confirmed. Receipt:");
console.log(receipt);
};
// Run the main function
main().catch(console.error);
Complete JavaScript Implementation
Complete JavaScript Implementation
Copy
import { Web3 } from 'web3';
import axios from 'axios';
// Configuration
const API_KEY = "your_api_key";
const UNIQUE_PID = "your_unique_pid";
const QUOTE_ENDPOINT = "https://router.gluex.xyz/v1/quote";
const RPC_URL = "https://mainnet.gateway.tenderly.co/your_rpc_url";
const PRIVATE_KEY = "your_private_key";
// Token Addresses
const USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; // USDC on Ethereum
const ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; // ETH on Ethereum
const INPUT_AMOUNT = BigInt("1000000"); // 1 USDC (6 decimals)
// Initialize Web3
const web3 = new Web3(RPC_URL);
const account = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
const COMPUTATION_UNITS = 1000000;
const fetchQuote = async (body, headers) => {
console.log("Fetch a quote from the GlueX Router for $USDC to $ETH swap");
const response = await axios.post(QUOTE_ENDPOINT, body, { headers });
return response.data;
};
const approveSpender = async (spender, amount, tokenAddress) => {
const signature = "0x095ea7b3";
const paddedSpender = web3.utils.toChecksumAddress(spender).slice(2).padStart(64, '0');
const calldata = `${signature}${paddedSpender}${amount.toString(16).padStart(64, '0')}`;
const txn = {
from: account.address,
to: web3.utils.toChecksumAddress(tokenAddress),
data: calldata,
gas: COMPUTATION_UNITS,
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(account.address),
chainId: 1, // Ethereum mainnet
};
const signedTxn = await account.signTransaction(txn);
const receipt = await web3.eth.sendSignedTransaction(signedTxn.rawTransaction);
const txHash = web3.utils.toHex(receipt.transactionHash);
console.log(`Approval Transaction Hash: ${txHash}`);
return txHash;
};
const executeTransaction = async (calldata, routerAddress) => {
const txn = {
from: account.address,
to: web3.utils.toChecksumAddress(routerAddress),
data: calldata,
gas: COMPUTATION_UNITS,
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(account.address),
chainId: 1, // Ethereum mainnet
};
try {
const signedTxn = await account.signTransaction(txn);
const receipt = await web3.eth.sendSignedTransaction(signedTxn.rawTransaction);
const txHash = web3.utils.toHex(receipt.transactionHash);
console.log(`Transaction Hash: ${txHash}`);
return txHash;
} catch (err) {
await new Promise(resolve => setTimeout(resolve, 5000));
txn.nonce = await web3.eth.getTransactionCount(account.address);
const signedTxn = await account.signTransaction(txn);
const receipt = await web3.eth.sendSignedTransaction(signedTxn.rawTransaction);
const txHash = web3.utils.toHex(receipt.transactionHash);
console.log(`Transaction Hash: ${txHash}`);
return txHash;
}
};
const main = async () => {
const headers = { "x-api-key": API_KEY };
const body = {
chainID: "1", // Ethereum Mainnet
userAddress: account.address,
outputReceiver: account.address,
uniquePID: UNIQUE_PID,
inputToken: USDC_ADDRESS,
outputToken: ETH_ADDRESS,
inputAmount: INPUT_AMOUNT,
isPermit2: false
};
// Convert BigInt to string for axios serialization
const requestBody = {
...body,
inputAmount: body.inputAmount.toString()
};
console.log("Fetching swap quote...");
const quoteData = await fetchQuote(requestBody, headers);
if (quoteData.statusCode !== 200) {
console.log("Error fetching quote:", quoteData);
return;
}
console.log("Quote received successfully:", quoteData);
const routerAddress = quoteData.result.router;
const calldata = quoteData.result.calldata;
// Approve the router contract
console.log("Approving router contract to spend USDC...");
const txnHash = await approveSpender(routerAddress, INPUT_AMOUNT, USDC_ADDRESS);
console.log("Waiting for approval transaction confirmation...");
const approvalReceipt = await web3.eth.getTransactionReceipt(txnHash);
if (!approvalReceipt || !approvalReceipt.status) {
console.log("Approval failed. Aborting.");
return;
}
// Execute the transaction
console.log("Executing transaction...");
const executeTxn = await executeTransaction(calldata, routerAddress);
const receipt = await web3.eth.getTransactionReceipt(executeTxn);
console.log("Transaction confirmed. Receipt:");
console.log(receipt);
};
// Run the main function
main().catch(console.error);
Running the Script
To execute the swap, run the script as follows:Copy
python dex-transaction.py