Skip to content

Instantly share code, notes, and snippets.

@occluder
Last active December 12, 2025 08:35
Show Gist options
  • Select an option

  • Save occluder/61d8bba347b61092d7c21d2739f23761 to your computer and use it in GitHub Desktop.

Select an option

Save occluder/61d8bba347b61092d7c21d2739f23761 to your computer and use it in GitHub Desktop.
Warframe.Market Order Bump Script
// ==UserScript==
// @name Warframe.Market Order Bump
// @namespace http://tampermonkey.net/
// @version 1.7
// @description Bump all your warframe.market orders with a button. As of 10-12-2025 this no longer works
// @author occluder
// @match https://warframe.market/profile/*
// @connect api.warframe.market
// @connect warframe.market
// @grant GM.xmlHttpRequest
// @grant GM_log
// ==/UserScript==
(function () {
'use strict';
// SET USERNAME FOR SCRIPT TO WORK
const USERNAME = null;
const ORDER_API_BASE = 'https://api.warframe.market/v1/profile/';
const CSRF_META_SELECTOR = 'meta[name="csrf-token"]';
if (!USERNAME) {
alert('[WFM Order Bump] Please set your username in the script.');
return;
}
// Track if button has been added to avoid duplicates
let buttonAdded = false;
function log(...args) {
console.log('[WFM Order Bump]', ...args);
if (typeof GM_log !== 'undefined') GM_log(args.join(' '));
}
function isUserProfile() {
return USERNAME === window.location.pathname.split('/').pop();
}
function getCSRFToken() {
const meta = document.querySelector(CSRF_META_SELECTOR);
if (meta && meta.content) {
log('Found CSRF token');
return meta.content;
}
log('CSRF token not found in meta tag');
return null;
}
function fetchWithGM(url, method, headers, body) {
return new Promise((resolve) => {
GM.xmlHttpRequest({
method: method,
url: url,
headers: headers,
data: body,
credentials: true,
onload: function (response) {
resolve({
status: response.status,
responseText: response.responseText,
ok: response.status >= 200 && response.status < 300
});
},
onerror: function (response) {
resolve({
status: response.status,
responseText: response.responseText || 'Network error',
ok: false
});
}
});
});
}
async function fetchOrders() {
const url = ORDER_API_BASE + USERNAME + '/orders';
log('Fetching orders from API');
const response = await fetchWithGM(url, 'GET', {
'Referer': 'https://warframe.market/',
'Origin': 'https://warframe.market'
}, null);
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
const data = JSON.parse(response.responseText);
const sellOrders = data?.payload?.sell_orders || [];
const buyOrders = data?.payload?.buy_orders || [];
log(`Found ${sellOrders.length} sell orders and ${buyOrders.length} buy orders from API`);
return [...sellOrders, ...buyOrders];
}
function extractOrders(apiData) {
const orders = [];
apiData.forEach(order => {
if (order.id && order.platinum !== undefined && order.quantity !== undefined && order.visible !== undefined) {
orders.push({
id: order.id,
platinum: order.platinum,
quantity: order.quantity,
visible: order.visible
});
}
});
log(`Extracted ${orders.length} valid orders`);
return orders;
}
function createButton() {
const button = document.createElement('button');
button.className = 'btn btn__primary--L8HyD';
button.type = 'button';
button.tabIndex = 0;
button.setAttribute('data-order-bump', 'true'); // Mark our button
const innerDiv = document.createElement('div');
const svg = `
<svg class="wfm-icon" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor" d="M17 3a2.8 2.8 0 0 1 4 4L8 20l-5 2 2-5Z"></path>
</svg>`;
innerDiv.innerHTML = `${svg}<span>Bump Orders</span>`;
button.appendChild(innerDiv);
return button;
}
async function updateOrder(order, csrfToken) {
const url = 'https://api.warframe.market/v2/order/' + encodeURIComponent(order.id);
const body = JSON.stringify({
platinum: order.platinum,
quantity: order.quantity,
visible: order.visible
});
const headers = {
'Content-Type': 'application/json',
'Referer': 'https://warframe.market/',
'Origin': 'https://warframe.market',
'X-CSRF-Token': csrfToken
};
const response = await fetchWithGM(url, 'PATCH', headers, body);
if (response.ok) {
return { success: true, id: order.id };
} else {
const error = `HTTP ${response.status}: ${response.responseText.substring(0, 100)}`;
return { success: false, id: order.id, error };
}
}
async function handleButtonClick(event) {
log('Starting bump process');
const csrfToken = getCSRFToken();
if (!csrfToken) {
alert('CSRF token not found. Are you logged in?');
return;
}
let ordersData;
try {
ordersData = await fetchOrders();
} catch (error) {
alert('Failed to fetch orders from API: ' + error.message);
return;
}
const orders = extractOrders(ordersData);
if (orders.length === 0) {
alert('No valid orders found to bump');
return;
}
const button = event.target.closest('button[data-order-bump]');
const originalText = button.textContent;
button.disabled = true;
button.textContent = 'Bumping orders...';
const failed = [];
for (const order of orders) {
const result = await updateOrder(order, csrfToken);
if (!result.success) {
failed.push(result);
}
await new Promise(resolve => setTimeout(resolve, 750));
}
button.disabled = false;
button.textContent = originalText;
if (failed.length > 0) {
const errorMsg = failed.map(f => `Order ${f.id}: ${f.error}`).join('\n');
alert(`Some orders failed to update:\n\n${errorMsg}`);
} else {
alert(`Successfully bumped ${orders.length} orders`);
}
}
function addButton() {
if (!isUserProfile()) {
return; // Not on the correct profile page
}
if (document.querySelector('button[data-order-bump]')) {
return;
}
const targetContainer = document.querySelector('.description__buttons');
if (!targetContainer) {
log('Could not find button container');
return;
}
const button = createButton();
button.addEventListener('click', handleButtonClick);
targetContainer.appendChild(button);
buttonAdded = true;
log('Button added to UI');
}
function setupNavigationObserver() {
let currentUrl = window.location.href;
const observer = new MutationObserver(() => {
if (window.location.href !== currentUrl) {
currentUrl = window.location.href;
log('URL changed to:', currentUrl);
if (!isUserProfile()) {
buttonAdded = false;
}
setTimeout(addButton, 500);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
window.addEventListener('popstate', () => {
setTimeout(addButton, 500);
});
}
function setupDOMObserver() {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
// Check if the added node contains our target container
if (node.nodeType === 1) { // Element node
if (node.querySelector && node.querySelector('.description__buttons')) {
addButton();
} else if (node.classList && node.classList.contains('description__buttons')) {
addButton();
}
}
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
function main() {
if (!isUserProfile()) {
log('Not on user profile page, skipping');
return;
}
log('Script initialized for user:', USERNAME);
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
addButton();
setupNavigationObserver();
setupDOMObserver();
});
} else {
addButton();
setupNavigationObserver();
setupDOMObserver();
}
}
main();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment