wallet-svr/src/plats/PlatExternalWallet.ts

65 lines
2.0 KiB
TypeScript

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<any> {
// 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<AccountClass>) {
await Wallet.insertOrUpdate({ account: user.id }, { address: user.openId, nweRecord: false })
}
}