-
Notifications
You must be signed in to change notification settings - Fork 0
/
v1_contract.ts
124 lines (102 loc) · 3.2 KB
/
v1_contract.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
// Find all our documentation at https://docs.near.org
import { assert, NearBindgen, UnorderedMap, call, near, view } from 'near-sdk-js'
type Pool = {
id: string
yieldSourceContract: string
currentSessionId: string
sessions: UnorderedMap<Session>
}
type Player = {
tickets: bigint
amount: bigint
}
type Session = {
id: string
totalTickets: bigint
players: {
// Addres => Player (in native currency)
[key: string]: Player
}
duration: bigint
start: bigint
end: bigint
countOfWinNumbers: number
}
@NearBindgen({})
class FunStake {
pools = new UnorderedMap<Pool>('pools')
day = BigInt(86400)
admin = ''
constructor() {
this.admin = near.predecessorAccountId()
}
@view({})
private isAdmin(): void {
assert(near.predecessorAccountId() === this.admin, 'Only admin can call this method')
}
// Only admin
@call({})
public createPool({ yieldSourceContract }: { yieldSourceContract: string }): void {
this.isAdmin()
const newId = String(this.pools.length)
const pool: Pool = {
id: newId,
yieldSourceContract,
currentSessionId: '0',
sessions: new UnorderedMap<Session>('sessions'),
}
this.pools.set(newId, pool)
}
@call({})
public stake({ poolId }: { poolId: string }): void {
const pool = this.pools.get(poolId)
const session = pool.sessions.get(pool.currentSessionId)
const sender = near.predecessorAccountId()
const value = near.attachedDeposit()
if (!session.players[sender]) {
session.players[sender].amount = value
} else {
session.players[sender].amount += value
}
const pastTime = near.blockTimestamp() - session.start
const userTickets = session.players[sender].tickets
// Do we need to caluclate based on day or just seconds
const remainingTime = session.end - near.blockTimestamp()
// const remainingDays = session.duration / this.day - pastTime / this.day
const newTotalUsertickets = userTickets + remainingTime * value
session.players[sender].tickets = newTotalUsertickets
session.totalTickets += newTotalUsertickets
}
// Only Admin
public startSession({
poolId,
duration,
countOfWinNumbers,
}: { poolId: string; duration: bigint; countOfWinNumbers: number }): void {
const pool = this.pools.get(poolId)
const newSessionId = String(pool.sessions.length)
const session: Session = {
id: newSessionId,
players: {},
duration,
start: near.blockTimestamp(),
end: near.blockTimestamp() + duration,
totalTickets: BigInt(0),
countOfWinNumbers,
}
pool.sessions.set(newSessionId, session)
pool.currentSessionId = newSessionId
}
public finalizeSession({ poolId }: { poolId: string }): void {
const pool = this.pools.get(poolId)
const session = pool.sessions.get(pool.currentSessionId)
assert(near.blockTimestamp() > session.end, 'Session is not ended yet')
const winingNumbers = []
for (let i = 0; i < session.countOfWinNumbers; i++) {
const randomString = near.randomSeed()
const firstChar = randomString.toString().charCodeAt(0)
winingNumbers.push(BigInt(firstChar) % session.totalTickets)
}
// TODO: Transfer the yield to the winner
}
}