Skip to content

Commit

Permalink
Add user actions table (#6)
Browse files Browse the repository at this point in the history
* feat: add deposit events

* feat: add withdraw events

* feat: add repay event

* feat: add deposits, withdraws, and repay on pToken table

* feat: add borrow event

* feat: add script to test transfer

* feat: add transfer event

* refactor: use validate env helper on deposit and transfer script

* feat: add borrowIndex data and accrue interest event

* chore: add log pToken data for testing

* feat: add reserve changes events

* refactor: rename onBehalfOf to user
  • Loading branch information
yvesfracari authored Jan 14, 2025
1 parent cbab5da commit 33b21f3
Show file tree
Hide file tree
Showing 12 changed files with 720 additions and 69 deletions.
157 changes: 155 additions & 2 deletions ponder.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const pToken = onchainTable('PToken', t => ({
exchangeRateCurrent: t.bigint().notNull(),
borrowRatePerSecond: t.bigint().notNull(),
supplyRatePerSecond: t.bigint().notNull(),
borrowIndex: t.bigint().notNull().default(0n),
cash: t.bigint().notNull().default(0n),
totalSupply: t.bigint().notNull().default(0n),
totalReserves: t.bigint().notNull().default(0n),
Expand Down Expand Up @@ -92,6 +93,63 @@ export const marketExited = onchainTable('MarketExited', t => ({
userId: t.text().notNull(),
}));

export const deposit = onchainTable('Deposit', t => ({
id: t.text().primaryKey(),
transactionId: t.text().notNull(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
minter: t.hex().notNull(),
userId: t.text().notNull(),
assets: t.bigint().notNull(),
shares: t.bigint().notNull(),
}));

export const withdraw = onchainTable('Withdraw', t => ({
id: t.text().primaryKey(),
transactionId: t.text().notNull(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
sender: t.hex().notNull(),
receiver: t.hex().notNull(),
userId: t.text().notNull(),
assets: t.bigint().notNull(),
shares: t.bigint().notNull(),
}));

export const repayBorrow = onchainTable('Repay', t => ({
id: t.text().primaryKey(),
transactionId: t.text().notNull(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
payer: t.hex().notNull(),
userId: t.text().notNull(),
repayAssets: t.bigint().notNull(),
accountBorrows: t.bigint().notNull(),
totalBorrows: t.bigint().notNull(),
}));

export const borrow = onchainTable('Borrow', t => ({
id: t.text().primaryKey(),
transactionId: t.text().notNull(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
borrower: t.hex().notNull(),
userId: t.text().notNull(),
borrowAssets: t.bigint().notNull(),
accountBorrows: t.bigint().notNull(),
totalBorrows: t.bigint().notNull(),
}));

export const transfer = onchainTable('Transfers', t => ({
id: t.text().primaryKey(),
transactionId: t.text().notNull(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
fromId: t.text().notNull(),
toId: t.text().notNull(),
shares: t.bigint().notNull(),
}));

export const underlyingToken = onchainTable('UnderlyingToken', t => ({
id: t.text().primaryKey(),
symbol: t.text().notNull(),
Expand Down Expand Up @@ -151,6 +209,11 @@ export const pTokenRelations = relations(pToken, ({ one, many }) => ({
}),
marketsEntered: many(marketEntered),
marketsExited: many(marketExited),
deposits: many(deposit),
withdraws: many(withdraw),
repayBorrows: many(repayBorrow),
borrows: many(borrow),
transfers: many(transfer),
}));

export const marketEnteredRelations = relations(marketEntered, ({ one }) => ({
Expand Down Expand Up @@ -191,8 +254,14 @@ export const underlyingTokenRelations = relations(
);

export const userRelations = relations(user, ({ many }) => ({
marketEntered: many(marketEntered),
marketExited: many(marketExited),
marketsEntered: many(marketEntered),
marketsExited: many(marketExited),
deposits: many(deposit),
withdraws: many(withdraw),
repayBorrows: many(repayBorrow),
borrows: many(borrow),
transfersSent: many(transfer, { relationName: 'fromId' }),
transfersReceived: many(transfer, { relationName: 'toId' }),
}));

export const transactionRelations = relations(transaction, ({ many }) => ({
Expand All @@ -201,4 +270,88 @@ export const transactionRelations = relations(transaction, ({ many }) => ({
actionsPaused: many(actionPaused),
protocolsCreation: many(protocol),
pTokensCreation: many(pToken),
deposits: many(deposit),
withdraws: many(withdraw),
repayBorrows: many(repayBorrow),
borrows: many(borrow),
transfers: many(transfer),
}));

export const depositRelations = relations(deposit, ({ one }) => ({
transaction: one(transaction, {
fields: [deposit.transactionId],
references: [transaction.id],
}),
pToken: one(pToken, {
fields: [deposit.pTokenId],
references: [pToken.id],
}),
user: one(user, {
fields: [deposit.userId],
references: [user.id],
}),
}));

export const withdrawRelations = relations(withdraw, ({ one }) => ({
transaction: one(transaction, {
fields: [withdraw.transactionId],
references: [transaction.id],
}),
pToken: one(pToken, {
fields: [withdraw.pTokenId],
references: [pToken.id],
}),
user: one(user, {
fields: [withdraw.userId],
references: [user.id],
}),
}));

export const repayRelations = relations(repayBorrow, ({ one }) => ({
transaction: one(transaction, {
fields: [repayBorrow.transactionId],
references: [transaction.id],
}),
pToken: one(pToken, {
fields: [repayBorrow.pTokenId],
references: [pToken.id],
}),
user: one(user, {
fields: [repayBorrow.userId],
references: [user.id],
}),
}));

export const borrowRelations = relations(borrow, ({ one }) => ({
transaction: one(transaction, {
fields: [borrow.transactionId],
references: [transaction.id],
}),
pToken: one(pToken, {
fields: [borrow.pTokenId],
references: [pToken.id],
}),
user: one(user, {
fields: [borrow.userId],
references: [user.id],
}),
}));

export const transferRelations = relations(transfer, ({ one }) => ({
transaction: one(transaction, {
fields: [transfer.transactionId],
references: [transaction.id],
}),
pToken: one(pToken, {
fields: [transfer.pTokenId],
references: [pToken.id],
}),
from: one(user, {
fields: [transfer.fromId],
references: [user.id],
}),
to: one(user, {
fields: [transfer.toId],
references: [user.id],
}),
}));
49 changes: 14 additions & 35 deletions scripts/createRandomPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,52 +17,31 @@ import { RiskEngineAbi } from '../abis/RiskEngineAbi';
import { PTokenAbi } from '../abis/PTokenAbi';
import { resolve } from 'path';
import { min, MathSol } from '../src/utils/math';
import {
Action,
TokenConfig,
TokenInfo,
TokenPositions,
UserPosition,
} from './types';
import { validateEnvKeys } from './validateEnvKeys';

// Load environment variables from .env.local if it exists
dotenv.config({ path: resolve(process.cwd(), '.env.local') });

// Environment validation
const requiredEnvVars = [
validateEnvKeys([
'FUNDING_PRIVATE_KEY',
'RISK_ENGINE_ADDRESS',
'STETH_ADDRESS',
'USDC_ADDRESS',
'WETH_ADDRESS',
'PSTETH_ADDRESS',
'PUSDC_ADDRESS',
'PWETH_ADDRESS',
'STETH_PRICE',
'USDC_ADDRESS',
'PUSDC_ADDRESS',
'USDC_PRICE',
'WETH_ADDRESS',
'PWETH_ADDRESS',
'WETH_PRICE',
] as const;

for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`);
}
}

interface TokenInfo {
address: Address;
pTokenAddress: Address;
price: bigint;
decimals: bigint;
}

interface UserPosition {
deposited: bigint;
borrowed: bigint;
inMarket: boolean;
underlyingBalance: bigint;
}

type TokenPositions = Record<Address, UserPosition>;

type TokenKey = 'steth' | 'usdc' | 'weth';

type Action = 'borrow' | 'withdraw' | 'deposit' | 'repay';

interface TokenConfig extends Record<TokenKey, TokenInfo> {}
]);

// Configuration
const config = {
Expand Down
Loading

0 comments on commit 33b21f3

Please sign in to comment.