backpack

backpack script

当前为 2024-03-31 提交的版本,查看 最新版本

// ==UserScript==
// @name         backpack
// @namespace    http://tampermonkey.net/
// @version      v1.6
// @description  backpack script
// @author       zhowiny
// @match        https://backpack.exchange/trade/*
// @icon         https://backpack.exchange/favicon-32x32.png
// @grant        none
// @license MIT
// ==/UserScript==

// 请使用在浏览器控制台里

const MIN_WAIT_MS = 300;
const MAX_WAIT_MS = 1000;
const MIN_SWITCH_MS = 1500;
const MAX_SWITCH_MS = 5000;

const tradingParams = {
  Buy: 2,
  Sell: 5,
}

let tradeCount = 0;
let running = false;

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) => {
  const isBuy = type === 'Buy';
  const priceCnt = getPriceCnt();
  const priceElement = priceCnt.querySelector(`& > div:${isBuy ? 'last' : 'first'}-child > div > div:nth-child(${tradingParams[type]}) button div`);
  return priceElement;
}

const setPrice = async (type) => {
  const price = getPriceElement(type);
  price.classList.add('border');
  price.click();
  await sleep(300);
}

const executeTrade = async (type) => {
  await clickElementByText(type, "p");
  await setPrice(type);
  await clickElementByText("Max", "div");
  await clickElementByText(type, "button");
};

const getRandomWait = (min, max) => Math.floor(Math.random() * max + min);

const performTradeCycle = async () => {
  try {
    tradeCount++;
    await executeTrade("Buy");
    await sleep(getRandomWait(MIN_SWITCH_MS, MAX_SWITCH_MS));
    await executeTrade("Sell");
    await sleep(getRandomWait(MIN_SWITCH_MS, MAX_SWITCH_MS));
  } catch (error) {
    console.error("发生错误:", error);
  }
};

const startTrading = async () => {
  await sleep(3000);
  await performTradeCycle();
  if (running) {
    window.requestAnimationFrame(startTrading);
  }
};

const createStartBtn = () => {
  const startBtn = document.createElement('button');
  startBtn.innerHTML= '启动脚本,开始自动交易';
  startBtn.style.cssText = 'grid-area: a';
  startBtn.classList.add('bg-greenText', 'rounded', 'p-2');
  startBtn.addEventListener('click', () => {
    const input_buy = document.querySelector('.backpack-tool input:nth-of-type(1)');
    const input_sell = document.querySelector('.backpack-tool input:nth-of-type(2)');

    running = !running;

    startBtn.innerHTML= running ? '脚本运行中,点击关闭交易' : '启动脚本,点击开始交易';
    startBtn.classList.toggle('bg-redText');
    input_buy.disabled = running;
    input_sell.disabled = running;
    input_buy.classList.toggle('bg-black/25');
    input_sell.classList.toggle('bg-black/25');

    console.log(running ? 'start' : 'stop');
    running && startTrading();

    if (!running) {
      getPriceElement('Buy').classList.remove('border');
      getPriceElement('Sell').classList.remove('border');
    }
  });
  return startBtn;
}

const createInput = (type) => {
  const input = document.createElement('input');
  input.value = tradingParams[type];
  input.type = 'number';
  input.min= 1;
  input.max = 20;
  input.step = 1;
  input.classList.add('w-12', 'h-2', 'py-2', 'text-center', 'bg-black', {Buy: 'text-greenText', Sell: 'text-redText'}[type]);
  input.addEventListener('input', e => {
    let value = parseInt(e.target.value);
    if (value > 20) value = 20;
    if (value < 1 || isNaN(value)) value = 1;
    tradingParams[type] = Math.max(1, Math.min(20, value));
    e.target.value = value;
  });
  return input;
}
const createTools = () => {
  const fragment = document.createDocumentFragment();
  const div = document.createElement('div');
  div.style.cssText = 'position: fixed;top: 10px;left:50%;transform: translateX(-50%);z-index: 1000;grid-template-areas: "a b c" "a d e"';
  div.classList.add('backpack-tool', 'grid', 'gap-2', 'text-sm', 'text-white', 'bg-base-700', 'p-2', 'rounded');
  div.appendChild(createStartBtn());
  div.appendChild(document.createTextNode('第几个买入:'));
  div.appendChild(createInput('Buy'));
  div.appendChild(document.createTextNode('第几个卖出:'));
  div.appendChild(createInput('Sell'));
  document.body.appendChild(div);
}

(function () {
  createTools()
})();

function getChineseText(text) {
  switch (text) {
    case "Market":
      return "市场";
    case "Max":
      return "最大";
    case "Buy":
      return "购买";
    case "Sell":
      return "出售";
    default:
      return text;
  }
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址