import { checkParamsNeeded } from 'zutils/utils/net.util' import { IPlat } from './IPlat' import { ZError } from 'zutils' import { NonceRecord } from 'modules/NonceRecord' import { SiweMessage } from 'siwe' import { DocumentType } from '@typegoose/typegoose' import { AccountClass } from 'modules/Account' import { Wallet } from 'modules/Wallet' // check if none is hex string with 24 length, or is timestamp within 5 minutes export const checkNonce = (nonce: string) => { if (!nonce) { throw new ZError(11, 'Invalid nonce') } // use regex to check if nonce is 24 length hex string if (nonce.length === 13) { const timestamp = parseInt(nonce) if (Date.now() - timestamp > 5 * 60 * 1000) { throw new ZError(13, 'nonce expired') } } else { if (!/^[0-9a-f]{24}$/.test(nonce)) { throw new ZError(11, 'Invalid nonce.') } } } export class PlatExternalWallet implements IPlat { async verifyToken(req: any): Promise { // here code is signature let { code, message } = req.params checkParamsNeeded(code, message) checkNonce(message.nonce) if (message.nonce.length === 24) { let record = await NonceRecord.findById(message.nonce) if (!record || record.status !== 0) { throw new ZError(12, 'nonce invalid') } if (record.expired < Date.now()) { throw new ZError(13, 'nonce expired') } record.status = 1 await record.save() } const msgSign = new SiweMessage(message) try { await msgSign.verify({ signature: code, nonce: message.nonce }) } catch (e) { throw new ZError(14, 'signature invalid') } const openId = message.address let data: any = {} const { api_platform } = req.headers if (api_platform) { data.platform = api_platform } return { openId, data } } async afterLogin(user: DocumentType) { await Wallet.insertOrUpdate({ account: user.id }, { address: user.openId, nweRecord: false }) } }