@levrbet/shared 0.5.75 → 0.5.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/core/types/orderbook/index.d.ts +1 -0
- package/dist/core/types/orderbook/index.js +1 -0
- package/dist/core/types/orderbook/index.js.map +1 -1
- package/dist/core/types/orderbook/mm-decision.types.d.ts +63 -0
- package/dist/core/types/orderbook/mm-decision.types.js +10 -0
- package/dist/core/types/orderbook/mm-decision.types.js.map +1 -0
- package/package.json +2 -2
- package/prisma/auth.prisma +53 -0
- package/prisma/campaigns.prisma +31 -0
- package/prisma/markets.prisma +74 -0
- package/prisma/notifications.prisma +35 -0
- package/prisma/orderbook.prisma +123 -0
- package/prisma/referrals.prisma +123 -0
- package/prisma/schema.prisma +0 -652
- package/prisma/sports.prisma +209 -0
- package/prisma/users.prisma +71 -0
- package/scripts/postinstall.js +4 -4
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ The Prisma schema is bundled in this package and the client is auto-generated on
|
|
|
52
52
|
```bash
|
|
53
53
|
npx levrbet-prisma-setup
|
|
54
54
|
# Or directly:
|
|
55
|
-
npx prisma generate --schema=node_modules/@levrbet/shared/prisma
|
|
55
|
+
npx prisma generate --schema=node_modules/@levrbet/shared/prisma
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
## Development
|
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./depth.types"), exports);
|
|
18
|
+
__exportStar(require("./mm-decision.types"), exports);
|
|
18
19
|
__exportStar(require("./order.types"), exports);
|
|
19
20
|
__exportStar(require("./preview.types"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/types/orderbook/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B;AAC7B,gDAA6B;AAC7B,kDAA+B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/types/orderbook/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B;AAC7B,sDAAmC;AACnC,gDAA6B;AAC7B,kDAA+B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { MarketType, MMDecisionOutcome, MMDecisionReason, MMDecisionTrigger, OrderDirection } from "@prisma/client";
|
|
2
|
+
import type { Side } from "../blockchain/contract.types";
|
|
3
|
+
export declare enum MMDecisionOp {
|
|
4
|
+
PLACE = "PLACE",
|
|
5
|
+
EDIT = "EDIT",
|
|
6
|
+
CANCEL = "CANCEL"
|
|
7
|
+
}
|
|
8
|
+
export interface MMDecisionLevel {
|
|
9
|
+
price: number;
|
|
10
|
+
size: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MMDecisionOperation {
|
|
13
|
+
op: MMDecisionOp;
|
|
14
|
+
direction: OrderDirection;
|
|
15
|
+
orderId?: string;
|
|
16
|
+
price: number;
|
|
17
|
+
size: string;
|
|
18
|
+
success: boolean;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MarketMakerDecisionDto {
|
|
22
|
+
id: string;
|
|
23
|
+
chainId: number;
|
|
24
|
+
gameId: number;
|
|
25
|
+
gameMarketId: string;
|
|
26
|
+
side: Side;
|
|
27
|
+
marketType: MarketType;
|
|
28
|
+
outcome: MMDecisionOutcome;
|
|
29
|
+
reason?: MMDecisionReason;
|
|
30
|
+
trigger: MMDecisionTrigger;
|
|
31
|
+
refPrice?: number;
|
|
32
|
+
gameProgressBps?: number;
|
|
33
|
+
onChainBalance?: string;
|
|
34
|
+
totalBidBudget?: string;
|
|
35
|
+
marketBidBudget?: string;
|
|
36
|
+
cumulativeBidSpend?: string;
|
|
37
|
+
numActiveMarkets?: number;
|
|
38
|
+
numActiveSides?: number;
|
|
39
|
+
askAvailable?: string;
|
|
40
|
+
positionId?: string;
|
|
41
|
+
bidLevels: MMDecisionLevel[];
|
|
42
|
+
askLevels: MMDecisionLevel[];
|
|
43
|
+
bidEdits: number;
|
|
44
|
+
bidsPlaced: number;
|
|
45
|
+
bidsCancelled: number;
|
|
46
|
+
askEdits: number;
|
|
47
|
+
asksPlaced: number;
|
|
48
|
+
asksCancelled: number;
|
|
49
|
+
activeOrderCount?: number;
|
|
50
|
+
expectedOrderCount?: number;
|
|
51
|
+
operations: MMDecisionOperation[];
|
|
52
|
+
createdAt: string;
|
|
53
|
+
}
|
|
54
|
+
export interface MarketMakerDecisionFilters {
|
|
55
|
+
gameId: number;
|
|
56
|
+
chainId?: number;
|
|
57
|
+
gameMarketId?: string;
|
|
58
|
+
side?: Side;
|
|
59
|
+
from?: string;
|
|
60
|
+
to?: string;
|
|
61
|
+
outcome?: MMDecisionOutcome;
|
|
62
|
+
limit?: number;
|
|
63
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MMDecisionOp = void 0;
|
|
4
|
+
var MMDecisionOp;
|
|
5
|
+
(function (MMDecisionOp) {
|
|
6
|
+
MMDecisionOp["PLACE"] = "PLACE";
|
|
7
|
+
MMDecisionOp["EDIT"] = "EDIT";
|
|
8
|
+
MMDecisionOp["CANCEL"] = "CANCEL";
|
|
9
|
+
})(MMDecisionOp || (exports.MMDecisionOp = MMDecisionOp = {}));
|
|
10
|
+
//# sourceMappingURL=mm-decision.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mm-decision.types.js","sourceRoot":"","sources":["../../../../src/core/types/orderbook/mm-decision.types.ts"],"names":[],"mappings":";;;AAGA,IAAY,YAIX;AAJD,WAAY,YAAY;IACpB,+BAAe,CAAA;IACf,6BAAa,CAAA;IACb,iCAAiB,CAAA;AACrB,CAAC,EAJW,YAAY,aAAZ,YAAY,GAAZ,YAAY,QAIvB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@levrbet/shared",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.77",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
-
"prisma
|
|
30
|
+
"prisma",
|
|
31
31
|
"scripts"
|
|
32
32
|
],
|
|
33
33
|
"bin": {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
enum LevrService {
|
|
2
|
+
Auth
|
|
3
|
+
Orderbook
|
|
4
|
+
OracleCore
|
|
5
|
+
OraclePeriphery
|
|
6
|
+
OracleProcessor
|
|
7
|
+
Leaderboard
|
|
8
|
+
Lab
|
|
9
|
+
LiquidationEngine
|
|
10
|
+
LambdaFunctions
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
enum ApiKeyScope {
|
|
14
|
+
Read
|
|
15
|
+
Write
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
model ApiKey {
|
|
19
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
20
|
+
apiKeyId String @unique
|
|
21
|
+
userId String
|
|
22
|
+
ethAddress String?
|
|
23
|
+
name String
|
|
24
|
+
ciphertext String
|
|
25
|
+
kmsKeyId String
|
|
26
|
+
service LevrService? // Optional: restrict key to a specific service
|
|
27
|
+
scopes ApiKeyScope[]
|
|
28
|
+
isActive Boolean @default(true)
|
|
29
|
+
expiresAt DateTime?
|
|
30
|
+
lastUsedAt DateTime?
|
|
31
|
+
usageCount Int @default(0)
|
|
32
|
+
createdAt DateTime @default(now())
|
|
33
|
+
updatedAt DateTime @updatedAt
|
|
34
|
+
|
|
35
|
+
@@index([userId, isActive])
|
|
36
|
+
@@index([service, isActive])
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
model AuditLog {
|
|
40
|
+
objectId String @id @default(cuid()) @map("_id")
|
|
41
|
+
action String // e.g., "api_key.created", "application.created", "token.validated"
|
|
42
|
+
resourceId String? // ID of the resource being acted upon
|
|
43
|
+
metadata Json @default("{}")
|
|
44
|
+
ipAddress String?
|
|
45
|
+
userAgent String?
|
|
46
|
+
timestamp DateTime @default(now())
|
|
47
|
+
// Relations
|
|
48
|
+
userId String
|
|
49
|
+
|
|
50
|
+
@@index([action])
|
|
51
|
+
@@index([timestamp])
|
|
52
|
+
@@index([userId])
|
|
53
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
model FreeBetCampaign {
|
|
2
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
3
|
+
merkleRoot String @unique
|
|
4
|
+
campaignId Int
|
|
5
|
+
chainId Int
|
|
6
|
+
name String
|
|
7
|
+
description String
|
|
8
|
+
txHash String?
|
|
9
|
+
|
|
10
|
+
entries FreeBetCampaignEntry[]
|
|
11
|
+
|
|
12
|
+
createdAt DateTime @default(now())
|
|
13
|
+
|
|
14
|
+
@@unique([chainId, campaignId])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
model FreeBetCampaignEntry {
|
|
18
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
19
|
+
merkleRoot String
|
|
20
|
+
ethAddress String
|
|
21
|
+
proof Json?
|
|
22
|
+
amount BigInt @default(0)
|
|
23
|
+
nonce Int @default(0)
|
|
24
|
+
spent Boolean @default(false)
|
|
25
|
+
paused Boolean @default(false)
|
|
26
|
+
|
|
27
|
+
campaign FreeBetCampaign @relation(fields: [merkleRoot], references: [merkleRoot])
|
|
28
|
+
|
|
29
|
+
@@unique([merkleRoot, ethAddress, nonce])
|
|
30
|
+
@@index([ethAddress])
|
|
31
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
enum Sides {
|
|
2
|
+
A
|
|
3
|
+
B
|
|
4
|
+
C
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
enum MarketType {
|
|
8
|
+
FullTimeWinner
|
|
9
|
+
OverUnder
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
enum MarketStatus {
|
|
13
|
+
Open
|
|
14
|
+
Closed
|
|
15
|
+
Settled
|
|
16
|
+
Refunded
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
model Odds {
|
|
20
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
21
|
+
txHash String
|
|
22
|
+
odds Json // define for the specific market type
|
|
23
|
+
prices Json
|
|
24
|
+
timestamp DateTime
|
|
25
|
+
marketType MarketType
|
|
26
|
+
details Json? // the unique details for the odds
|
|
27
|
+
gamePhase GamePhase
|
|
28
|
+
gamePeriod Int
|
|
29
|
+
gameClock Int
|
|
30
|
+
gameProgressBps Int?
|
|
31
|
+
chainId Int
|
|
32
|
+
marketPhase MarketStatus
|
|
33
|
+
provider String? // optional for now to avoid breaking staging
|
|
34
|
+
opticOddsOddsId String? // optional for now to avoid breaking staging
|
|
35
|
+
lsportsOddsId String? // optional for now to avoid breaking staging
|
|
36
|
+
|
|
37
|
+
levrGameObjectId String @db.ObjectId
|
|
38
|
+
marketObjectId String @db.ObjectId
|
|
39
|
+
gameMarketId String
|
|
40
|
+
market Market @relation(fields: [marketObjectId], references: [objectId])
|
|
41
|
+
|
|
42
|
+
createdAt DateTime @default(now())
|
|
43
|
+
updatedAt DateTime @updatedAt
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
model Market {
|
|
47
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
48
|
+
chainId Int
|
|
49
|
+
gameId Int
|
|
50
|
+
levrMarketId String
|
|
51
|
+
levrMarketContract String
|
|
52
|
+
gameMarketId String @unique
|
|
53
|
+
txHash String
|
|
54
|
+
maturedAt DateTime?
|
|
55
|
+
leveraged Boolean @default(false)
|
|
56
|
+
isMatured Boolean @default(false)
|
|
57
|
+
normalizationFactor Float
|
|
58
|
+
marketDetails Json
|
|
59
|
+
marketRiskAllocation Json
|
|
60
|
+
providers Json
|
|
61
|
+
activeProvider Json
|
|
62
|
+
marketType MarketType
|
|
63
|
+
status MarketStatus
|
|
64
|
+
winner Sides?
|
|
65
|
+
targetLine Float? // for over under markets
|
|
66
|
+
|
|
67
|
+
levrGameObjectId String @db.ObjectId // new unique identifier
|
|
68
|
+
levrGame LevrGame @relation(fields: [levrGameObjectId], references: [objectId])
|
|
69
|
+
|
|
70
|
+
odds Odds[]
|
|
71
|
+
|
|
72
|
+
createdAt DateTime @default(now())
|
|
73
|
+
updatedAt DateTime @updatedAt
|
|
74
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
enum NotificationType {
|
|
2
|
+
BetPlaced
|
|
3
|
+
BetSettled
|
|
4
|
+
BetCredit
|
|
5
|
+
Deposit
|
|
6
|
+
Withdrawal
|
|
7
|
+
ReferralSignup
|
|
8
|
+
ReferralRewardEarned
|
|
9
|
+
ReferralPayoutPublished
|
|
10
|
+
MarketSettled
|
|
11
|
+
GameLive
|
|
12
|
+
ApiKeyCreated
|
|
13
|
+
SecurityAlert
|
|
14
|
+
GreylistFlagged
|
|
15
|
+
Promo
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
model Notification {
|
|
19
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
20
|
+
userId String @db.ObjectId
|
|
21
|
+
user User @relation("UserNotifications", fields: [userId], references: [objectId])
|
|
22
|
+
type NotificationType
|
|
23
|
+
title String
|
|
24
|
+
message String
|
|
25
|
+
metadata Json @default("{}") // arbitrary event payload (e.g. amount, txHash, gameMarketId)
|
|
26
|
+
actionUrl String? // optional deep link for the client to route to on click
|
|
27
|
+
readAt DateTime?
|
|
28
|
+
|
|
29
|
+
createdAt DateTime @default(now())
|
|
30
|
+
updatedAt DateTime @updatedAt
|
|
31
|
+
|
|
32
|
+
@@index([userId])
|
|
33
|
+
@@index([userId, readAt])
|
|
34
|
+
@@index([type])
|
|
35
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
enum MMDecisionOutcome {
|
|
2
|
+
QUOTED
|
|
3
|
+
SKIPPED
|
|
4
|
+
CANCELLED_ALL
|
|
5
|
+
ABORTED
|
|
6
|
+
ERROR
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
enum MMDecisionReason {
|
|
10
|
+
NO_REF_PRICE
|
|
11
|
+
OUTSIDE_WINDOW
|
|
12
|
+
PAST_STOP
|
|
13
|
+
BUDGET_EXHAUSTED
|
|
14
|
+
MARKET_CLOSED
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enum MMDecisionTrigger {
|
|
18
|
+
ODDS_MOVEMENT
|
|
19
|
+
HEARTBEAT
|
|
20
|
+
STATUS_CHANGE
|
|
21
|
+
INITIAL
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
enum OrderDirection {
|
|
25
|
+
BID
|
|
26
|
+
ASK
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
enum TerminalOrderStatus {
|
|
30
|
+
FILLED
|
|
31
|
+
CANCELLED
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
model ClosedOrder {
|
|
35
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
36
|
+
orderId String @unique
|
|
37
|
+
chainId Int
|
|
38
|
+
gameId Int
|
|
39
|
+
gameMarketId String
|
|
40
|
+
levrMarketId String
|
|
41
|
+
side Int
|
|
42
|
+
direction OrderDirection
|
|
43
|
+
type String
|
|
44
|
+
status TerminalOrderStatus
|
|
45
|
+
price Int
|
|
46
|
+
ethAddress String
|
|
47
|
+
cancelReason String?
|
|
48
|
+
cancelDetails String?
|
|
49
|
+
transactionHash String?
|
|
50
|
+
|
|
51
|
+
// BID-specific
|
|
52
|
+
budget String?
|
|
53
|
+
filledBudget String?
|
|
54
|
+
leverage Float?
|
|
55
|
+
|
|
56
|
+
// ASK-specific
|
|
57
|
+
volume String?
|
|
58
|
+
filledVolume String?
|
|
59
|
+
positionId String?
|
|
60
|
+
|
|
61
|
+
placedAt DateTime
|
|
62
|
+
resolvedAt DateTime @default(now())
|
|
63
|
+
createdAt DateTime @default(now())
|
|
64
|
+
updatedAt DateTime @updatedAt
|
|
65
|
+
|
|
66
|
+
@@index([ethAddress])
|
|
67
|
+
@@index([ethAddress, status])
|
|
68
|
+
@@index([ethAddress, resolvedAt(sort: Desc)])
|
|
69
|
+
@@index([chainId, gameMarketId])
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
model MarketMakerDecision {
|
|
73
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
74
|
+
|
|
75
|
+
// Identity / routing
|
|
76
|
+
chainId Int
|
|
77
|
+
gameId Int
|
|
78
|
+
gameMarketId String
|
|
79
|
+
side Int // Side enum (numeric, matches ClosedOrder)
|
|
80
|
+
marketType MarketType
|
|
81
|
+
|
|
82
|
+
// Outcome
|
|
83
|
+
outcome MMDecisionOutcome
|
|
84
|
+
reason MMDecisionReason?
|
|
85
|
+
trigger MMDecisionTrigger
|
|
86
|
+
|
|
87
|
+
// Inputs snapshot
|
|
88
|
+
refPrice Int? // 3dp
|
|
89
|
+
gameProgressBps Int?
|
|
90
|
+
|
|
91
|
+
// Budget snapshot (e6 values as strings)
|
|
92
|
+
onChainBalance String?
|
|
93
|
+
totalBidBudget String?
|
|
94
|
+
marketBidBudget String?
|
|
95
|
+
cumulativeBidSpend String?
|
|
96
|
+
numActiveMarkets Int?
|
|
97
|
+
numActiveSides Int?
|
|
98
|
+
askAvailable String?
|
|
99
|
+
positionId String?
|
|
100
|
+
|
|
101
|
+
// Computed ladders (price 3dp, size e6 as string)
|
|
102
|
+
bidLevels Json // [{ price, size }]
|
|
103
|
+
askLevels Json // [{ price, size }]
|
|
104
|
+
|
|
105
|
+
// Action summary
|
|
106
|
+
bidEdits Int @default(0)
|
|
107
|
+
bidsPlaced Int @default(0)
|
|
108
|
+
bidsCancelled Int @default(0)
|
|
109
|
+
askEdits Int @default(0)
|
|
110
|
+
asksPlaced Int @default(0)
|
|
111
|
+
asksCancelled Int @default(0)
|
|
112
|
+
activeOrderCount Int?
|
|
113
|
+
expectedOrderCount Int?
|
|
114
|
+
|
|
115
|
+
// Concrete order operations issued this cycle
|
|
116
|
+
operations Json // [{ op, direction, orderId?, price, size, success, error? }]
|
|
117
|
+
|
|
118
|
+
createdAt DateTime @default(now())
|
|
119
|
+
|
|
120
|
+
@@index([gameId, createdAt(sort: Desc)])
|
|
121
|
+
@@index([gameMarketId, side, createdAt(sort: Desc)])
|
|
122
|
+
@@index([createdAt])
|
|
123
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
enum ReferralStatus {
|
|
2
|
+
Pending
|
|
3
|
+
Active
|
|
4
|
+
Suspended
|
|
5
|
+
Completed
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
enum GreylistStatus {
|
|
9
|
+
None // Not flagged — included in Merkle
|
|
10
|
+
Flagged // Active greylist — excluded from Merkle
|
|
11
|
+
Cleared // Admin-cleared — re-included in future epochs
|
|
12
|
+
Confirmed // Admin-confirmed fraud — permanently excluded
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
enum EpochStatus {
|
|
16
|
+
Active
|
|
17
|
+
Processing
|
|
18
|
+
Completed
|
|
19
|
+
Failed
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
enum ReferralTier {
|
|
23
|
+
T1
|
|
24
|
+
T2
|
|
25
|
+
T3
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
model Referral {
|
|
29
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
30
|
+
referrerId String @db.ObjectId
|
|
31
|
+
referredId String @db.ObjectId
|
|
32
|
+
referralCode String
|
|
33
|
+
referralSource String? // e.g. campaign or link source
|
|
34
|
+
status ReferralStatus @default(Active)
|
|
35
|
+
greylistStatus GreylistStatus @default(None) // Denormalized flag for fast filtering in fee computation
|
|
36
|
+
|
|
37
|
+
// Relations
|
|
38
|
+
referrer User @relation("ReferrerRelations", fields: [referrerId], references: [objectId])
|
|
39
|
+
referred User @relation("ReferredRelations", fields: [referredId], references: [objectId])
|
|
40
|
+
|
|
41
|
+
createdAt DateTime @default(now())
|
|
42
|
+
updatedAt DateTime @updatedAt
|
|
43
|
+
|
|
44
|
+
@@index([referrerId])
|
|
45
|
+
@@index([referredId])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
model ReferralEpoch {
|
|
49
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
50
|
+
periodId String @unique
|
|
51
|
+
periodStart DateTime
|
|
52
|
+
periodEnd DateTime
|
|
53
|
+
timezone String @default("America/Mexico_City")
|
|
54
|
+
status EpochStatus @default(Active)
|
|
55
|
+
|
|
56
|
+
// On-chain reward info (one root per epoch)
|
|
57
|
+
totalFeesUsd Float?
|
|
58
|
+
rewardPoolUsd Float?
|
|
59
|
+
merkleRoot String?
|
|
60
|
+
merkleTxHash String?
|
|
61
|
+
rootPublishedAt DateTime?
|
|
62
|
+
notes String?
|
|
63
|
+
|
|
64
|
+
ReferralRewards ReferralReward[]
|
|
65
|
+
|
|
66
|
+
createdAt DateTime @default(now())
|
|
67
|
+
updatedAt DateTime @updatedAt
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
model ReferralReward {
|
|
71
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
72
|
+
userId String @db.ObjectId
|
|
73
|
+
epochId String @db.ObjectId
|
|
74
|
+
periodId String // denormalized for readability (e.g. "2025W45")
|
|
75
|
+
|
|
76
|
+
// --- Aggregates ---
|
|
77
|
+
referredBetVolumeUsd Float @default(0.0)
|
|
78
|
+
referredFeeUsd Float @default(0.0)
|
|
79
|
+
tier ReferralTier @default(T1)
|
|
80
|
+
tierPercentage Float @default(0.025)
|
|
81
|
+
|
|
82
|
+
// --- Payouts ---
|
|
83
|
+
payoutBeforeScaleUsd Float @default(0.0)
|
|
84
|
+
payoutScaledUsd Float @default(0.0)
|
|
85
|
+
payoutTokenUnits String? // token base units (string for precision)
|
|
86
|
+
scaleFactor Float?
|
|
87
|
+
|
|
88
|
+
// --- Claim sync info ---
|
|
89
|
+
isClaimedOnChain Boolean @default(false)
|
|
90
|
+
claimedTxHash String?
|
|
91
|
+
lastSyncedFromChainAt DateTime?
|
|
92
|
+
|
|
93
|
+
createdAt DateTime @default(now())
|
|
94
|
+
updatedAt DateTime @updatedAt
|
|
95
|
+
|
|
96
|
+
// --- Relations ---
|
|
97
|
+
user User @relation("UserRewards", fields: [userId], references: [objectId])
|
|
98
|
+
epoch ReferralEpoch @relation(fields: [epochId], references: [objectId])
|
|
99
|
+
|
|
100
|
+
@@unique([userId, periodId])
|
|
101
|
+
@@index([epochId])
|
|
102
|
+
@@index([userId])
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
model GreylistEntry {
|
|
106
|
+
objectId String @id @default(auto()) @map("_id") @db.ObjectId
|
|
107
|
+
walletAddress String // The greylisted wallet (referrer OR referee)
|
|
108
|
+
status GreylistStatus @default(None)
|
|
109
|
+
reason String // Why flagged (e.g. "velocity anomaly", "wallet clustering", "manual flag")
|
|
110
|
+
source String // What triggered it: "admin", "system:velocity", "system:clustering"
|
|
111
|
+
flaggedBy String? // Admin userId who flagged (null if system-flagged)
|
|
112
|
+
reviewedBy String? // Admin userId who reviewed (cleared/confirmed)
|
|
113
|
+
reviewedAt DateTime? // When reviewed
|
|
114
|
+
reviewNotes String? // Admin notes on review decision
|
|
115
|
+
metadata Json? // Arbitrary data: IP patterns, cluster info, etc.
|
|
116
|
+
|
|
117
|
+
createdAt DateTime @default(now())
|
|
118
|
+
updatedAt DateTime @updatedAt
|
|
119
|
+
|
|
120
|
+
@@index([walletAddress])
|
|
121
|
+
@@index([status])
|
|
122
|
+
@@index([walletAddress, status])
|
|
123
|
+
}
|