├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── jsconfig.json ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── components │ ├── LogText.vue │ └── TopMenu.vue ├── main.js ├── request │ ├── okReq.js │ └── request.js ├── router │ └── router.js ├── utils │ ├── DateUtils.js │ └── NumberUtils.js └── view │ ├── Home.vue │ ├── OKXContainer.vue │ └── exchange │ └── OKXWithdraw.vue └── vue.config.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'plugin:vue/vue3-recommended', 4 | 'airbnb-base', 5 | ], 6 | plugins: [ 7 | 'vue', 8 | ], 9 | rules: { 10 | 'no-console': 'off', // 如果你不想限制console输出,可以把这个规则关闭 11 | 'vue/max-attributes-per-line': ['error', { 12 | singleline: 5, // 在单行上最多允许5个属性 13 | multiline: { 14 | max: 1, // 在多行上允许一个属性 15 | allowFirstLine: false // 不允许属性和开始标签放在同一行 16 | } 17 | }], 18 | // 在vue模板文件中强制使用4个空格缩进 19 | 'vue/html-indent': ['error', 2] 20 | }, 21 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fast-exchange 2 | 3 | 本项目为交易所账户与链上地址之间的交互提供了极大便利性。本项目为纯前端项目,直接连接区块链网络或者其他第三方网络进行交互。至于老生常谈的安全问题,有条件的可以`review代码`,无法review代码的小伙伴就跟着`感觉`走吧。 4 | 5 | Owner承诺github上的源码**不存在**恶意代码,其他基于此项目二次开发的代码,Owner无法保证其安全性,所以请尽量**从github下载发行版**。 6 | 7 | ## 开发者使用说明 8 | 9 | 欢迎有想法有时间的开发小伙伴提pr,review之后会尽快approve。 10 | 11 | 另外Owner更擅长后端,欢迎前端伙伴提一些界面优化类的PR。 12 | 13 | ### 技术栈 14 | 15 | VUE3 + axios + vue-router + element-plus + starkjs 16 | 17 | ### 安装依赖 18 | 19 | ``` 20 | npm install 21 | ``` 22 | 23 | ### 启动项目 24 | 25 | ``` 26 | npm run serve 27 | ``` 28 | 29 | ### 构建项目 30 | ``` 31 | npm run build 32 | ``` 33 | 34 | ## 普通用户使用说明 35 | 36 | 1. OKX配置白名单, 不会的可以搜一下 37 | 2. OKX生成API KEY, 生成之后请妥善保管, 避免丢失. 38 | 3. 点击**release**获取开箱即用的发行版软件,如下图。 39 | 40 | ![1693679293231](https://github.com/AceSen/picture/blob/main/fast-airdrop/release.png) 41 | 42 | ​ 4.下载ZIP包 43 | 44 | ![1693679353548](https://github.com/AceSen/picture/blob/main/fast-airdrop/releasezip.png) 45 | 46 | ​ 5.解压,打开dist文件夹, 打开index.html即可使用,界面如下 47 | 48 | ![1693678010502](https://github.com/AceSen/picture/blob/main/fast-airdrop/okxpage.png) 49 | 50 | 51 | 52 | ## 联系我们 53 | 54 | twitter:https://twitter.com/senokel 55 | 56 | 57 | 58 | ## 打赏/捐赠 59 | 60 | **新需求:** 61 | 62 | 有新需求的小伙伴,可以提起issue,会根据issue规划下一步功能开发。 63 | 64 | **捐赠:** 65 | 66 | 请向starknet地址捐赠 : 0x0219e47CD3Ab97C7602233c283811b731b75f7A5a2D26294de8ad0754e5fe7C4 67 | 68 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "baseUrl": "./", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@/*": [ 9 | "src/*" 10 | ] 11 | }, 12 | "lib": [ 13 | "esnext", 14 | "dom", 15 | "dom.iterable", 16 | "scripthost" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fast-airdrop", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^1.5.0", 12 | "core-js": "^3.8.3", 13 | "crypto-js": "^4.1.1", 14 | "element-plus": "^2.3.12", 15 | "vue": "^3.2.13", 16 | "vue-router": "^4.2.4" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.12.16", 20 | "@babel/eslint-parser": "^7.12.16", 21 | "@vue/cli-plugin-babel": "~5.0.0", 22 | "@vue/cli-plugin-eslint": "~5.0.0", 23 | "@vue/cli-service": "~5.0.0", 24 | "eslint": "^7.32.0", 25 | "eslint-plugin-vue": "^8.0.3" 26 | }, 27 | "eslintConfig": { 28 | "root": true, 29 | "env": { 30 | "node": true 31 | }, 32 | "extends": [ 33 | "plugin:vue/vue3-essential", 34 | "eslint:recommended" 35 | ], 36 | "parserOptions": { 37 | "parser": "@babel/eslint-parser" 38 | }, 39 | "rules": {} 40 | }, 41 | "browserslist": [ 42 | "> 1%", 43 | "last 2 versions", 44 | "not dead", 45 | "not ie 11" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AceSen/fast-exchange/002ebb8a911c8cda70cd79873766d26b2f893e9a/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 22 | 23 | 32 | -------------------------------------------------------------------------------- /src/components/LogText.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 29 | 30 | -------------------------------------------------------------------------------- /src/components/TopMenu.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 37 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import ElementPlus from 'element-plus' 4 | import 'element-plus/dist/index.css' 5 | import router from './router/router' 6 | 7 | createApp(App).use(ElementPlus).use(router).mount('#app') 8 | -------------------------------------------------------------------------------- /src/request/okReq.js: -------------------------------------------------------------------------------- 1 | import { request } from './request'; 2 | import CryptoJS from "crypto-js"; 3 | 4 | const config = { 5 | baseURL: "https://www.okx.com" 6 | }; 7 | 8 | /** 9 | * 签名 10 | * @param {*String} method 请求方式 11 | * @param {*String} url 路径 12 | */ 13 | function getOkSign(method, url, timestamp, secret, body) { 14 | if (!method || !url || !timestamp || !secret) { 15 | return null; 16 | } 17 | 18 | return CryptoJS.enc.Base64.stringify( 19 | CryptoJS.HmacSHA256(timestamp + method.toUpperCase() + url + body, secret) 20 | ); 21 | } 22 | 23 | /** 24 | * 25 | * @param {*} param 26 | * @param {*} headers 27 | * @param {*} secret 28 | * @returns 29 | */ 30 | function getBalance(param, headers, secret) { 31 | config.method = 'get'; 32 | config.url = '/api/v5/asset/balances'; 33 | const timestamp = new Date().toISOString(); 34 | const sign = getOkSign(config.method, config.url, timestamp, secret, ''); 35 | config.headers = { 36 | "OK-ACCESS-SIGN": sign, 37 | "OK-ACCESS-TIMESTAMP": timestamp, 38 | ...headers, 39 | } 40 | 41 | return request(config); 42 | } 43 | 44 | function getCcyList(param, headers, secret) { 45 | config.method = 'get'; 46 | config.url = '/api/v5/asset/currencies'; 47 | const timestamp = new Date().toISOString(); 48 | const sign = getOkSign(config.method, config.url, timestamp, secret, ''); 49 | config.headers = { 50 | "OK-ACCESS-SIGN": sign, 51 | "OK-ACCESS-TIMESTAMP": timestamp, 52 | ...headers, 53 | } 54 | 55 | return request(config); 56 | } 57 | 58 | function withdrawal(param, headers, secret) { 59 | config.method = 'post'; 60 | config.url = '/api/v5/asset/withdrawal'; 61 | const timestamp = new Date().toISOString(); 62 | const sign = getOkSign(config.method, config.url, timestamp, secret, JSON.stringify(param)); 63 | console.log(JSON.stringify(param)) 64 | config.headers = { 65 | "OK-ACCESS-SIGN": sign, 66 | "OK-ACCESS-TIMESTAMP": timestamp, 67 | ...headers, 68 | }; 69 | config.data = param; 70 | 71 | return request(config); 72 | } 73 | 74 | /** 75 | * 查询充币历史记录 76 | * @param {*} param 77 | * @param {*} headers 78 | * @param {*} secret 79 | * @returns 80 | */ 81 | function getDepositHis(param, headers, secret) { 82 | config.method = 'get'; 83 | config.url = '/api/v5/asset/deposit-history'; 84 | const timestamp = new Date().toISOString(); 85 | const sign = getOkSign(config.method, config.url, timestamp, secret, ''); 86 | config.headers = { 87 | "OK-ACCESS-SIGN": sign, 88 | "OK-ACCESS-TIMESTAMP": timestamp, 89 | ...headers, 90 | }; 91 | return request(config) 92 | } 93 | 94 | /** 95 | * 获取充值地址 96 | * @param {*} param 97 | * @param {*} headers 98 | * @param {*} secret 99 | * @returns 100 | */ 101 | function getDepositAddr(param, headers, secret) { 102 | config.method = 'get'; 103 | config.url = '/api/v5/asset/deposit-address?ccy=' + param; 104 | const timestamp = new Date().toISOString(); 105 | const sign = getOkSign(config.method, config.url, timestamp, secret, ''); 106 | config.headers = { 107 | "OK-ACCESS-SIGN": sign, 108 | "OK-ACCESS-TIMESTAMP": timestamp, 109 | ...headers, 110 | }; 111 | return request(config) 112 | } 113 | 114 | 115 | export default { 116 | getBalance, 117 | getCcyList, 118 | withdrawal, 119 | getDepositHis, 120 | getDepositAddr, 121 | } 122 | 123 | -------------------------------------------------------------------------------- /src/request/request.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | export function request(config) { 4 | const service = axios.create({ 5 | timeout: 5000, 6 | }) 7 | 8 | service.interceptors.request.use(config => { 9 | return config; 10 | }, 11 | err => { 12 | console.log(err); 13 | return Promise.reject(); 14 | }) 15 | 16 | service.interceptors.response.use(res => { 17 | return res.data; 18 | }, 19 | err => { 20 | console.log(err); 21 | return Promise.reject(); 22 | }) 23 | 24 | return service(config); 25 | } -------------------------------------------------------------------------------- /src/router/router.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHashHistory } from "vue-router"; 2 | import OKXContainer from "@/view/OKXContainer.vue"; 3 | import Home from "@/view/Home.vue"; 4 | 5 | const routes = [ 6 | { 7 | path: "/", 8 | component: Home, 9 | name: "Home", 10 | children: [ 11 | { 12 | path: "/exchange/okx", 13 | name: "OKXContainer", 14 | component: OKXContainer, 15 | 16 | }, 17 | ] 18 | }, 19 | 20 | ]; 21 | 22 | const router = createRouter({ 23 | history: createWebHashHistory(), 24 | routes, 25 | }); 26 | 27 | export default router; 28 | -------------------------------------------------------------------------------- /src/utils/DateUtils.js: -------------------------------------------------------------------------------- 1 | export default { 2 | /** 3 | * 暂停运行 4 | * @param {*number} ms 5 | * @returns 6 | */ 7 | sleep(ms) { 8 | return new Promise(resolve => setTimeout(resolve, ms)); 9 | }, 10 | 11 | /** 12 | * 格式化时间 13 | * @param {*Date} dateTime 14 | * @returns 15 | */ 16 | formatDateTime(dateTime) { 17 | let Y = dateTime.getFullYear(); 18 | let M = (dateTime.getMonth() + 1 < 10 ? '0' + (dateTime.getMonth() + 1) : dateTime.getMonth() + 1); 19 | let D = (dateTime.getDate() < 10 ? '0' + dateTime.getDate() : dateTime.getDate()); 20 | let h = (dateTime.getHours() < 10 ? '0' + dateTime.getHours() : dateTime.getHours()); 21 | let m = (dateTime.getMinutes() < 10 ? '0' + dateTime.getMinutes() : dateTime.getMinutes()); 22 | let s = (dateTime.getSeconds() < 10 ? '0' + dateTime.getSeconds() : dateTime.getSeconds()); 23 | let ms = dateTime.getMilliseconds(); 24 | let strDate = `${Y}/${M}/${D} ${h}:${m}:${s}:${ms}`; 25 | return strDate; 26 | }, 27 | } -------------------------------------------------------------------------------- /src/utils/NumberUtils.js: -------------------------------------------------------------------------------- 1 | export default { 2 | floatRate10: function() { 3 | return (1 + (Math.random() / 10)).toFixed(2); 4 | }, 5 | 6 | floatRate: function(num) { 7 | return (1 + (Math.random() * num)).toFixed(2); 8 | }, 9 | 10 | getRandomNum12: function() { 11 | const timestamp = Date.now().toString().slice(-8); // 获取后8位时间戳 12 | const randomPart = Math.floor(Math.random() * 10000).toString().padStart(4, '0'); // 生成4位随机数 13 | 14 | return timestamp + randomPart; 15 | }, 16 | } -------------------------------------------------------------------------------- /src/view/Home.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 34 | 35 | -------------------------------------------------------------------------------- /src/view/OKXContainer.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | 35 | -------------------------------------------------------------------------------- /src/view/exchange/OKXWithdraw.vue: -------------------------------------------------------------------------------- 1 | 64 | 65 | 362 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('@vue/cli-service') 2 | module.exports = defineConfig({ 3 | transpileDependencies: true, 4 | publicPath: './', 5 | outputDir: 'dist', 6 | indexPath: 'index.html', 7 | lintOnSave: false, 8 | }) 9 | --------------------------------------------------------------------------------