backpack 刷成交量脚本,支持手动开启关闭,设置买入卖出点
目前為
// ==UserScript==
// @name backpack
// @namespace http://tampermonkey.net/
// @version v0.0.3
// @description backpack 刷成交量脚本,支持手动开启关闭,设置买入卖出点
// @author zhowiny
// @match https://backpack.exchange/trade/*
// @icon https://backpack.exchange/favicon-32x32.png
// @grant none
// @license MIT
// @require https://update.greasyfork.org/scripts/491401/1352455/vue.js
// @require https://update.greasyfork.org/scripts/491414/1352613/template_vue.js
// ==/UserScript==
// 请使用在浏览器控制台里
const MIN_WAIT_MS = 300;
const MAX_WAIT_MS = 1000;
const MIN_SWITCH_MS = 1500;
const MAX_SWITCH_MS = 5000;
let tradeCount = 0;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const findElementsByText = (text, tag) => {
const elements = document.querySelectorAll(tag);
return Array.from(elements).filter((div) => div.textContent === text);
};
const getElement = (text, tag) => {
let element = findElementsByText(text, tag)[0];
if (!element) {
element = findElementsByText(getChineseText(text), tag)[0];
if (!element) return
}
return element;
}
const clickElementByText = async (text, tag) => {
const element = getElement(text, tag);
if (!element) return;
element.click();
await sleep(getRandomWait(MIN_WAIT_MS, MAX_WAIT_MS));
};
const getPriceCnt = () => {
return document.querySelector('.flex.flex-col.no-scrollbar.h-full.flex-1.snap-mandatory.overflow-y-auto.font-sans');
}
const getPriceElement = (type, num) => {
const isBuy = type === 'Buy';
const priceCnt = getPriceCnt();
const priceElement = priceCnt.querySelector(`& > div:${isBuy ? 'last' : 'first'}-child > div > div:nth-child(${num}) button div`);
return priceElement;
}
const setPrice = async (type, num) => {
const price = getPriceElement(type, num);
price.classList.add('border');
price.click();
await sleep(300);
}
const executeTrade = async (type, params) => {
await clickElementByText(type, "p");
await setPrice(type, params[type]);
await clickElementByText("Max", "div");
//await clickElementByText(type, "button");
};
const getRandomWait = (min, max) => Math.floor(Math.random() * max + min);
const performTradeCycle = async (params) => {
try {
tradeCount++;
await executeTrade("Buy", params);
await sleep(getRandomWait(MIN_SWITCH_MS, MAX_SWITCH_MS));
await executeTrade("Sell", params);
await sleep(getRandomWait(MIN_SWITCH_MS, MAX_SWITCH_MS));
} catch (error) {
console.error("发生错误:", error);
}
};
function getChineseText(text) {
switch (text) {
case "Market":
return "市场";
case "Max":
return "最大";
case "Buy":
return "购买";
case "Sell":
return "出售";
default:
return text;
}
}
const main = () => {
const {ref} = window.Vue;
window.TAMPERMONKEY_VUE_APP.template = `
<div class='backpack-tool grid gap-2 text-sm text-white bg-base-700 p-2 rounded' style='grid-template-areas: "a b c" "a d e"'>
<button
class='bg-greenText rounded p-2' style='grid-area: a;'
:class='{"bg-redText": running}'
@click='handleStart'
>
{{running ? '脚本运行中,点击关闭交易' : '启动脚本,点击开始交易'}}
</button>
<span>第几个买入:</span>
<input
class='w-12 h-2 py-2 text-center bg-black text-greenText' :class='{"bg-black/25": running}'
type='number' :min='1' :max='20' :step='1' :disabled='running'
v-model.number='tradingParams.Buy'
@input='e => handleNumberInput(e, "Buy")'
/>
<span>第几个卖出:</span>
<input
class='w-12 h-2 py-2 text-center bg-black text-redText' :class='{"bg-black/25": running}'
type='number' :min='1' :max='20' :step='1' :disabled='running'
v-model.number='tradingParams.Sell'
@input='e => handleNumberInput(e, "Sell")'
/>
</div>
`
window.TAMPERMONKEY_VUE_APP.setup = () => {
const running = ref(false);
const tradingParams = ref({
Buy: 2,
Sell: 5,
});
const handleNumberInput = (e, type) => {
let value = parseInt(e.target.value);
if (value > 20) value = 20;
if (value < 1 || isNaN(value)) value = 1;
tradingParams.value[type] = Math.max(1, Math.min(20, value));
}
const startTrading = async () => {
await sleep(3000);
await performTradeCycle(tradingParams.value);
if (running.value) {
window.requestAnimationFrame(() => startTrading());
}
};
const handleStart = () => {
running.value = !running.value;
running.value && startTrading();
console.log(running.value ? 'start' : 'stop');
!running.value && getPriceElement('Buy', tradingParams.value.Buy).classList.remove('border');
!running.value && getPriceElement('Sell', tradingParams.value.Sell).classList.remove('border');
}
return {
running,
tradingParams,
handleNumberInput,
handleStart,
}
}
}
(function() {
'use strict';
main();
})();