-
Notifications
You must be signed in to change notification settings - Fork 0
/
mod.ts
136 lines (117 loc) · 3.65 KB
/
mod.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { Application, Session, Router, generateNonce, SiweMessage, ErrorTypes, JsonRpcProvider } from './deps.ts'
const PORT = 3000
const app = new Application()
const router = new Router<{ session: Session }>()
app.use(Session.initMiddleware())
router.get('/api/nonce', async (ctx) => {
await ctx.state.session.set('nonce', generateNonce())
ctx.response.status = 200
ctx.response.body = (await ctx.state.session.get('nonce')) as string
})
router.get('/api/me', async (ctx) => {
const session = ctx.state.session
if (!(await session.get('siwe'))) {
ctx.response.status = 401
ctx.response.headers.set('Content-Type', 'application/json')
ctx.response.body = { message: 'You have to first sign_in' }
return
}
ctx.response.status = 200
ctx.response.body = {
address: ((await session.get('siwe')) as InstanceType<typeof SiweMessage>).address,
ens: await session.get('ens')
}
})
const getInfuraUrl = (chainId: string) => {
switch (Number.parseInt(chainId)) {
case 1:
return 'https://mainnet.infura.io/v3'
case 3:
return 'https://ropsten.infura.io/v3'
case 4:
return 'https://rinkeby.infura.io/v3'
case 5:
return 'https://goerli.infura.io/v3'
case 137:
return 'https://polygon-mainnet.infura.io/v3'
}
}
router.post('/api/sign_in', async (ctx) => {
try {
const body = await ctx.request.body().value
const { ens } = body
if (!body.message) {
ctx.response.status = 422
ctx.response.body = { message: 'Expected signMessage object as body.' }
return
}
const message = new SiweMessage(body.message)
const infuraProvider = new JsonRpcProvider(
{
allowGzip: true,
url: `${getInfuraUrl(message.chainId)}/8fcacee838e04f31b6ec145eb98879c8`,
headers: {
Accept: '*/*',
Origin: `http://localhost:${PORT}`,
'Accept-Encoding': 'gzip, deflate, br',
'Content-Type': 'application/json'
}
},
Number.parseInt(message.chainId)
)
await infuraProvider.ready
const fields = await message.validate(infuraProvider)
if (fields.nonce !== (await ctx.state.session.get('nonce'))) {
ctx.response.status = 422
ctx.response.body = {
message: `Invalid nonce.`
}
return
}
await ctx.state.session.set('siwe', fields)
await ctx.state.session.set('ens', ens)
await ctx.state.session.set('nonce', null)
if (fields.expirationTime) await ctx.state.session.set('expires', new Date(fields.expirationTime))
ctx.response.status = 200
ctx.response.body = {
address: fields.address,
ens
}
} catch (e) {
await ctx.state.session.set('siwe', null)
await ctx.state.session.set('ens', null)
await ctx.state.session.set('nonce', null)
console.error(e)
switch (e) {
case ErrorTypes.EXPIRED_MESSAGE: {
ctx.response.status = 440
ctx.response.body = { message: e.message }
break
}
case ErrorTypes.INVALID_SIGNATURE: {
ctx.response.status = 422
ctx.response.body = { message: e.message }
break
}
default: {
ctx.response.status = 500
ctx.response.body = { message: e.message }
break
}
}
}
})
router.post('/api/sign_out', async (ctx) => {
const session = ctx.state.session
if (!(await session.get('siwe'))) {
ctx.response.status = 401
ctx.response.headers.set('Content-Type', 'application/json')
ctx.response.body = { message: 'You have to first sign_in' }
return
}
ctx.response.status = 205
ctx.response.body = ''
})
app.use(router.routes())
app.use(router.allowedMethods())
await app.listen(`:3000`)