移除一些静态页面

This commit is contained in:
zhl 2023-04-19 15:00:10 +08:00
parent b1e35641af
commit 60b39eb5a1
18 changed files with 32 additions and 34084 deletions

View File

@ -24,8 +24,6 @@
"@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^10.1.0",
"@fastify/jwt": "^6.7.1",
"@fastify/static": "^6.10.0",
"@fastify/view": "^7.4.1",
"@metamask/eth-sig-util": "^4.0.1",
"@typegoose/auto-increment": "^0.4.1",
"@typegoose/typegoose": "^7.4.6",
@ -34,7 +32,6 @@
"bson": "^4.0.4",
"deepmerge": "^4.2.2",
"dotenv": "^16.0.3",
"ejs": "^3.1.9",
"ethereumjs-util": "^7.1.5",
"fast-rbac": "^1.3.0",
"fast-xml-parser": "^4.1.3",

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,257 +0,0 @@
var vConsole = new window.VConsole()
window.wallet = window.wallet = {}
const DEFAULT_CHAIN_DATA = {
name: 'Matic Testnet RPC',
type: 'Testnet',
rpc: 'https://rpc-mumbai.maticvigil.com',
id: 80001,
symbol: 'MATIC',
explorerurl: 'https://mumbai.polygonscan.com/',
}
const loader = document.getElementById('loader')
const WALLET_ADDRESS = ''
function toHexChainId(chainId) {
return '0x' + chainId.toString(16)
}
// 显示加载动画
function showLoading() {
// add style display: block
loader.style.display = 'block'
}
// 隐藏加载动画
function hideLoading() {
// add style display: none
loader.style.display = 'none'
}
// 加载json
async function loadJson(url) {
return fetch(url).then(response => response.json())
}
async function initInstance(user, address, jsonUrl) {
let json = await loadJson(jsonUrl)
return new wallet.web3.eth.Contract(json.abi, address, { from: user })
}
async function initWallet() {
wallet.contract = await initInstance(wallet.account, wallet.walletAddress, '/public/abis/BEMultiSigWallet.json')
}
async function confirmTask() {
console.log('confirm task')
let ids = wallet.scheduleList
showLoading()
try {
let gas = await wallet.contract.methods.confirmTransaction(ids).estimateGas()
gas = gas | 0
await wallet.contract.methods.confirmTransaction(ids).send({ gas })
} catch (err) {
console.log('error confirm task', err)
}
hideLoading()
}
async function rejectTask() {
console.log('reject task')
let ids = wallet.scheduleList
showLoading()
try {
let gas = await wallet.contract.methods.revokeConfirmation(ids).estimateGas()
gas = gas | 0
await wallet.contract.methods.revokeConfirmation(ids).send({ gas })
} catch (err) {
console.log('error confirm task', err)
}
hideLoading()
}
function makeBatchRequest(calls, callFrom) {
let batch = new wallet.web3.BatchRequest()
let promises = calls.map(call => {
return new Promise((resolve, reject) => {
let request = call.request({ from: callFrom }, (error, data) => {
if (error) {
reject(error)
} else {
resolve(data)
}
})
batch.add(request)
})
})
batch.execute()
return Promise.all(promises)
}
/**
* 查询定时
* @param {bytes32} id beginSchedule返回的id
* @returns
*/
async function querySchedule(id) {
let instance = wallet.contract
return makeBatchRequest([
instance.methods.isOperation(id).call,
instance.methods.isOperationPending(id).call,
instance.methods.isOperationReady(id).call,
instance.methods.isOperationDone(id).call,
instance.methods.isConfirmed(id).call,
instance.methods.getTimestamp(id).call,
])
}
function initUIEvent() {
var btnConfirm = document.getElementById('btn-confirm')
btnConfirm.addEventListener('click', confirmTask, false)
var btnReject = document.getElementById('btn-reject')
btnReject.addEventListener('click', rejectTask, false)
}
async function connectMetaMask() {
let provider = null
if (typeof window.ethereum !== 'undefined') {
provider = window.ethereum
try {
await provider.request({ method: 'eth_requestAccounts' })
} catch (error) {
if (error.code === -32002) {
throw new Error('MeatMask not login, Open MeatMask and login first')
} else {
throw new Error('User Rejected')
}
}
} else if (window.web3) {
provider = window.web3.currentProvider
} else if (window.celo) {
provider = window.celo
} else {
throw new Error('No Web3 Provider found')
}
return provider
}
async function confirmNeededChain() {
const chainId = wallet.chainId
if (chainId !== DEFAULT_CHAIN_DATA.id) {
await switchEthereumChain()
}
}
async function switchEthereumChain() {
let data = DEFAULT_CHAIN_DATA
let hexChainId = toHexChainId(data.id)
try {
await wallet.provider.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: hexChainId,
chainName: data.name,
nativeCurrency: {
name: data.symbol,
symbol: data.symbol,
decimals: data.decimals || 18,
},
blockExplorerUrls: [data.explorerurl],
rpcUrls: [data.rpc],
},
],
})
console.log('add chain success')
} catch (addError) {
console.error('add chain error: ', addError)
}
// try {
// await wallet.provider.request({
// method: 'wallet_switchEthereumChain',
// params: [{ chainId: hexChainId }],
// })
// console.log('switch chain success')
// } catch (e) {
// console.log('switch chain error: ', e)
// if (e.code === 4902 || e.message.indexOf('Unrecognized chain ID') >= 0) {
// try {
// await wallet.provider.request({
// method: 'wallet_addEthereumChain',
// params: [
// {
// chainId: hexChainId,
// chainName: data.name,
// nativeCurrency: {
// name: data.symbol,
// symbol: data.symbol,
// decimals: data.decimals || 18,
// },
// blockExplorerUrls: [data.explorerurl],
// rpcUrls: [data.rpc],
// },
// ],
// })
// console.log('add chain success')
// } catch (addError) {
// console.error('add chain error: ', addError)
// }
// }
// }
}
function subscribeToEvents(provider) {
provider.on('accountsChanged', async accounts => {
if (accounts && accounts.length > 0) {
if (wallet.account !== accounts[0]) {
console.log('account change', wallet.account, accounts[0])
wallet.account = accounts
}
}
})
// Subscribe to chainId change
provider.on('chainChanged', async chainId => {
const chainIdNum = parseInt(chainId)
console.log('chainChanged', chainId, chainIdNum)
if (wallet.chainId !== chainIdNum) {
wallet.chainId = chainIdNum
await confirmNeededChain()
}
})
// Subscribe to session disconnection
provider.on('disconnect', err => {
console.log('disconnect', err)
})
}
function loadTaskData() {
wallet.walletAddress = document.getElementById('wallet-address').value
let nodes = document.getElementsByClassName('scheduleId')
wallet.scheduleList = []
for (let node of nodes) {
wallet.scheduleList.push(node.value)
}
console.log(wallet.scheduleList)
}
;(async function () {
loadTaskData()
initUIEvent()
let self = window.wallet
self.provider = await connectMetaMask()
self.web3 = new Web3(self.provider)
let accounts = await self.web3.eth.getAccounts()
if (accounts.length > 0) {
self.account = accounts[0]
}
self.chainId = await self.web3.eth.getChainId()
console.log('chainId: ', self.chainId, 'account: ', self.account)
await confirmNeededChain()
subscribeToEvents(self.provider)
await initWallet()
setTimeout(async () => {
let result = await querySchedule('0xa5c35368cd44dbe805a4595d6813ed3afefa1bf667209dc8d63f99cdec117f58')
console.log(result)
}, 5000)
})()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,115 +0,0 @@
body {
background-color: rgb(249, 249, 249);
}
p {
font-size: 0.8rem;
}
.action-bar {
display: flex;
width: 50%;
justify-content: space-around;
}
.loader {
background: #00000035;
background: radial-gradient(#222, #000);
bottom: 0;
left: 0;
display: none;
overflow: hidden;
position: fixed;
right: 0;
top: 0;
z-index: 99999;
}
.loader-inner {
bottom: 0;
height: 60px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 100px;
}
.loader-line-wrap {
animation: spin 2000ms cubic-bezier(0.175, 0.885, 0.32, 1.275) infinite;
box-sizing: border-box;
height: 50px;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
transform-origin: 50% 100%;
width: 100px;
}
.loader-line {
border: 4px solid transparent;
border-radius: 100%;
box-sizing: border-box;
height: 100px;
left: 0;
margin: 0 auto;
position: absolute;
right: 0;
top: 0;
width: 100px;
}
.loader-line-wrap:nth-child(1) {
animation-delay: -50ms;
}
.loader-line-wrap:nth-child(2) {
animation-delay: -100ms;
}
.loader-line-wrap:nth-child(3) {
animation-delay: -150ms;
}
.loader-line-wrap:nth-child(4) {
animation-delay: -200ms;
}
.loader-line-wrap:nth-child(5) {
animation-delay: -250ms;
}
.loader-line-wrap:nth-child(1) .loader-line {
border-color: hsl(0, 80%, 60%);
height: 90px;
width: 90px;
top: 7px;
}
.loader-line-wrap:nth-child(2) .loader-line {
border-color: hsl(60, 80%, 60%);
height: 76px;
width: 76px;
top: 14px;
}
.loader-line-wrap:nth-child(3) .loader-line {
border-color: hsl(120, 80%, 60%);
height: 62px;
width: 62px;
top: 21px;
}
.loader-line-wrap:nth-child(4) .loader-line {
border-color: hsl(180, 80%, 60%);
height: 48px;
width: 48px;
top: 28px;
}
.loader-line-wrap:nth-child(5) .loader-line {
border-color: hsl(240, 80%, 60%);
height: 34px;
width: 34px;
top: 35px;
}
@keyframes spin {
0%,
15% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -8,7 +8,6 @@ import { RouterMap } from 'decorators/router'
import { mongoose } from '@typegoose/typegoose'
import logger from 'logger/logger'
import BlocknumSchedule from 'schedule/blocknum.schedule'
import path from 'path'
import { RedisClient } from 'redis/RedisClient'
import WxTaskSchedule from 'schedule/wxtask.schedule'
@ -36,16 +35,6 @@ export class ApiServer {
this.server.register(zReqParserPlugin)
this.server.register(helmet, { hidePoweredBy: false })
this.server.register(zTokenParserPlugin)
this.server.register(require('@fastify/view'), {
engine: {
ejs: require('ejs'),
},
})
this.server.register(require('@fastify/static'), {
root: path.join(__dirname, '../public'),
prefix: '/public/', // optional: default '/'
constraints: {}, // optional: default {}
})
this.server.register(apiAuthPlugin, {
secret: process.env.API_TOKEN_SECRET,

View File

@ -82,9 +82,6 @@ export class BlockChain {
case TaskType.TRANSFER_NFT:
abi = await this.erc721Reactor.transfer(reqData)
break
case TaskType.MINT_PRESALE_BOX:
abi = await this.erc721Reactor.mint(reqData)
break
}
return abi
}

View File

@ -3,7 +3,7 @@ import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import { getSignature, decrypt } from '@wecom/crypto'
import { TaskQueue } from 'queue/task.queue'
import { RequestTask } from 'models/RequestTask'
import { RequestTask, TaskTypeMap } from 'models/RequestTask'
import { BlockChain } from 'chain/BlockChain'
import { ChainTask } from 'models/ChainTask'
import { isObjectId } from 'utils/string.util'
@ -47,33 +47,31 @@ class WorkFlowController extends BaseController {
}
@role(ROLE_ANON)
@router('get /workflow/confirm/:id')
async confirmPage(req, res) {
@router('get /workflow/task/:id')
async info(req, res) {
const { id } = req.params
if (!id) {
return res.view('/templates/confirm_err_page.ejs', { msg: '参数错误' })
throw new ZError(10, '参数错误')
}
if (!isObjectId(id)) {
return res.view('/templates/confirm_err_page.ejs', { msg: '参数错误' })
throw new ZError(11, '参数错误')
}
const chainTask = await ChainTask.findById(id)
if (!chainTask) {
return res.view('/templates/confirm_err_page.ejs', { msg: '任务未找到' })
throw new ZError(12, '任务未找到')
}
let requestTasks = await RequestTask.find({ chainTaskId: id })
if (requestTasks.length === 0) {
return res.view('/templates/confirm_err_page.ejs', { msg: '链请求任务未找到' })
throw new ZError(13, '链请求任务未找到')
}
let address = process.env.CHAIN_WALLET_ADDRESS
return res.view('/templates/confirm_page.ejs', { id: id, subtasks: requestTasks, mainTask: chainTask, address })
}
@role(ROLE_ANON)
@router('get /workflow/redirect/:id')
async rejectPage(req, res) {
const { id } = req.params
res.header('Content-Security-Policy', "script-src 'nonce-rAnd0m'")
return res.view('/templates/redirect_page.ejs', { id })
let types = Object.fromEntries(TaskTypeMap)
return {
chainTask,
requestTasks,
address,
types,
}
}
@role(ROLE_ANON)

View File

@ -10,9 +10,16 @@ export enum TaskType {
MINT_NFT = 2,
TRANSFER_FT = 3,
TRANSFER_NFT = 4,
MINT_PRESALE_BOX = 5,
}
export const TaskTypeMap = new Map([
[TaskType.UNKNOW, 'Unknow'],
[TaskType.MINT_FT, 'Mint Ft'],
[TaskType.MINT_NFT, 'Mint NFT'],
[TaskType.TRANSFER_FT, 'Ft转账'],
[TaskType.TRANSFER_NFT, 'NFT转账'],
])
export enum ReqTaskStatus {
NOTSTART = 0,
PEDING = 1,

View File

@ -5,7 +5,7 @@ import logger from 'logger/logger'
import { ChainTaskClass } from 'models/ChainTask'
import { MailService } from 'service/mail.service'
import { Deferred } from 'utils/promise.util'
import {CONFIRM_MAIL_HTML} from 'common/Constants'
import { CONFIRM_MAIL_HTML } from 'common/Constants'
export interface IMailData {
from?: string
@ -30,13 +30,13 @@ export class MailQueue {
public async addTaskToQueue(task: DocumentType<ChainTaskClass>) {
let html = CONFIRM_MAIL_HTML
html = html.replace("{{title}}", task.name)
html = html.replace("{{desc}}", task.desc)
let link = `${process.env.WEB_BASE_URL}/workflow/redirect/${task.id}`
html = html.replace("{{link}}", link)
let link2 = `${process.env.WEB_BASE_URL}/workflow/confirm/${task.id}`
html = html.replace("{{link2}}", link2)
let data: any = {html}
html = html.replace('{{title}}', task.name)
html = html.replace('{{desc}}', task.desc)
let link = `${process.env.WEB_BASE_URL}/pages/redirect.html?id=${task.id}`
html = html.replace('{{link}}', link)
let link2 = `${process.env.WEB_BASE_URL}/pages/confirm.html?id=${task.id}`
html = html.replace('{{link2}}', link2)
let data: any = { html }
Object(DEFAULT_MSG_DATA).zssign(data)
let deferred = new Deferred()
this.queue.push(async () => {

View File

@ -1,2 +0,0 @@
<h1>Error</h1>
<p><%= msg %></p>

View File

@ -1,105 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>任务详情</title>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="Content-Security-Policy" content="default-src * self https://cdn.jsdelivr.net/; style-src * self 'unsafe-inline'; script-src * self https://cdn.jsdelivr.net/ 'unsafe-eval'; img-src * self 'unsafe-inline' data: w3.org/svg/2000; connect-src self * 'unsafe-inline';">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, minimal-ui" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="apple-mobile-web-app-title" content="WJTX">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<link href="/public/styles/main.css" rel="stylesheet" >
</head>
<body>
<h1>确认任务 <i><%= mainTask.name %></i></h1>
<h3><%= mainTask.desc %></h3>
<input type="hidden" id="wallet-address" value="<%= address %>">
<div class="action-bar">
<button class="btn btn-primary" id="btn-confirm">通过</button>
<button class="btn btn-danger" id="btn-reject">拒绝</button>
</div>
<p>本次申请包含<b><%= subtasks.length %></b>个链操作任务</p>
<%for(var i=0;i<subtasks.length;i++){%>
<input type="hidden" class="scheduleId" value="<%=subtasks[i].scheduleId %>">
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="heading<%=subtasks[i].index %>">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapse<%=subtasks[i].index %>" aria-expanded="true" aria-controls="collapse<%=subtasks[i].index %>">
任务<%=subtasks[i].index %>: <%=subtasks[i].reqDatas.length %>个子任务
</button>
</h2>
<div id="collapse<%=subtasks[i].index %>" class="accordion-collapse collapse show" aria-labelledby="heading<%=subtasks[i].index %>" data-bs-parent="#accordionExample">
<div class="accordion-body">
<%for(var j=0;j<subtasks[i].reqDatas.length;j++){%>
<% switch (subtasks[i].reqDatas[j].type) {
case '1' : %>
<p>Mint Ft</p>
<% break;
case '2' : %>
<p>Mint NFT</p>
<% break;
case '3' : %>
<p>FT 转账</p>
<% break;
case '2' : %>
<p>NFT 转账</p>
<% break;
} %>
<p>合约地址: <%=subtasks[i].reqDatas[j].address%></p>
<p>目标钱包: <%=subtasks[i].reqDatas[j].to%></p>
<%if (subtasks[i].reqDatas[j].amount) {%> <p>数量: <%=subtasks[i].reqDatas[j].amount %></p> <%}%>
<%if (subtasks[i].reqDatas[j].tokenId) {%> <p>NFT ID: <%=subtasks[i].reqDatas[j].tokenId %></p><%}%>
<%}%>
</div>
</div>
</div>
</div>
<%}%>
<div class="loader" id="loader">
<div class="loader-inner">
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
</div>
</div>
<script src="/public/scripts/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="/public/scripts/vconsole.min.js"></script>
<script src="/public/scripts/web3.min.js"></script>
<script src="/public/scripts/main.js" async type = "module"></script>
</body>
</html>

View File

@ -1,49 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>任务详情</title>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-rAnd0m'">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, minimal-ui" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="apple-mobile-web-app-title" content="WJTX">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
</head>
<body>
<h1>请选择操作...</h1>
<p><a href="" id="href">点击跳转至操作页面</a></p>
<script nonce="rAnd0m">
(function() {
var urlBase = 'xwork.kingsome.cn/workflow/confirm/<%= id %>'
var urlMobile = `https://metamask.app.link/dapp/${urlBase}`
var url = `https://${urlBase}`
// if current devices is mobile, redirect url1, else redirect url2
if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
url = urlMobile
console.log(url)
document.getElementById('href').setAttribute('href', url)
} else {
location.href = url
}
})()
</script>
</body>
</html>

View File

@ -8,14 +8,14 @@
"module": "commonjs",
"esModuleInterop": true,
"resolveJsonModule": true,
"target": "es2018",
"target": "es2019",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./src",
"rootDir": "./src"
},
"lib": ["es2018"],
"lib": ["es2019"],
"include": [
"src/**/*.ts",
"typings/extend.d.ts"