-
Notifications
You must be signed in to change notification settings - Fork 124
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IND-494]: Create trading_rewards postgres table (#822)
* [IND-494]: Create trading_rewards postgres table * nit * fix tests * fix tests and linter * fix tests * fix foreign key * lint
- Loading branch information
1 parent
7d78a89
commit 66073c1
Showing
11 changed files
with
313 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
indexer/packages/postgres/__tests__/stores/trading-rewards-table.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { TradingRewardFromDatabase } from '../../src/types'; | ||
import { clearData, migrate, teardown } from '../../src/helpers/db-helpers'; | ||
import { defaultTradingReward, defaultWallet } from '../helpers/constants'; | ||
import * as TradingRewardTable from '../../src/stores/trading-reward-table'; | ||
import { WalletTable } from '../../src'; | ||
|
||
describe('TradingReward store', () => { | ||
beforeAll(async () => { | ||
await migrate(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
await WalletTable.create(defaultWallet); | ||
}); | ||
|
||
afterEach(async () => { | ||
await clearData(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await teardown(); | ||
}); | ||
|
||
it('Successfully creates a TradingReward', async () => { | ||
await TradingRewardTable.create(defaultTradingReward); | ||
}); | ||
|
||
it('Successfully finds all TradingRewards', async () => { | ||
await Promise.all([ | ||
TradingRewardTable.create(defaultTradingReward), | ||
TradingRewardTable.create({ | ||
...defaultTradingReward, | ||
blockHeight: '20', | ||
}), | ||
]); | ||
|
||
const tradingRewards: TradingRewardFromDatabase[] = await TradingRewardTable.findAll( | ||
{}, | ||
[], | ||
{ readReplica: true }, | ||
); | ||
|
||
expect(tradingRewards.length).toEqual(2); | ||
expect(tradingRewards[0]).toEqual(expect.objectContaining({ | ||
...defaultTradingReward, | ||
blockHeight: '20', | ||
})); | ||
expect(tradingRewards[1]).toEqual(expect.objectContaining(defaultTradingReward)); | ||
}); | ||
|
||
it('Successfully finds a TradingReward', async () => { | ||
await TradingRewardTable.create(defaultTradingReward); | ||
|
||
const tradingReward: TradingRewardFromDatabase | undefined = await TradingRewardTable.findById( | ||
TradingRewardTable.uuid(defaultTradingReward.address, defaultTradingReward.blockHeight), | ||
); | ||
|
||
expect(tradingReward).toEqual(expect.objectContaining(defaultTradingReward)); | ||
}); | ||
}); |
25 changes: 25 additions & 0 deletions
25
...postgres/src/db/migrations/migration_files/20231129153017_create_trading_rewards_table.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as Knex from 'knex'; | ||
|
||
export async function up(knex: Knex): Promise<void> { | ||
return knex | ||
.schema | ||
.createTable('trading_rewards', (table) => { | ||
table.uuid('id').primary(); | ||
table.string('address').notNullable(); | ||
table.timestamp('blockTime').notNullable(); | ||
table.bigInteger('blockHeight').notNullable(); | ||
table.decimal('amount').notNullable(); | ||
|
||
// Foreign | ||
table.foreign('address').references('wallets.address'); | ||
|
||
// Indices | ||
table.index(['address']); | ||
table.index(['blockTime']); | ||
table.index(['blockHeight']); | ||
}); | ||
} | ||
|
||
export async function down(knex: Knex): Promise<void> { | ||
return knex.schema.dropTableIfExists('trading_rewards'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ const layer1Tables = [ | |
'liquidity_tiers', | ||
'wallets', | ||
'compliance_data', | ||
'trading_rewards', | ||
]; | ||
|
||
/** | ||
|
75 changes: 75 additions & 0 deletions
75
indexer/packages/postgres/src/models/trading-reward-model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import path from 'path'; | ||
|
||
import { Model } from 'objection'; | ||
|
||
import { IntegerPattern, NonNegativeNumericPattern } from '../lib/validators'; | ||
import UpsertQueryBuilder from '../query-builders/upsert'; | ||
|
||
export default class TradingRewardModel extends Model { | ||
static get tableName() { | ||
return 'trading_rewards'; | ||
} | ||
|
||
static get idColumn() { | ||
return 'id'; | ||
} | ||
|
||
static relationMappings = { | ||
wallet: { | ||
relation: Model.BelongsToOneRelation, | ||
modelClass: path.join(__dirname, 'wallet-model'), | ||
join: { | ||
from: 'trading_rewards.address', | ||
to: 'wallets.address', | ||
}, | ||
}, | ||
}; | ||
|
||
static get jsonSchema() { | ||
return { | ||
type: 'object', | ||
required: [ | ||
'id', | ||
'address', | ||
'blockTime', | ||
'blockHeight', | ||
'amount', | ||
], | ||
properties: { | ||
id: { type: 'string', format: 'uuid' }, | ||
address: { type: 'string' }, | ||
blockTime: { type: 'string', format: 'date-time' }, | ||
blockHeight: { type: 'string', pattern: IntegerPattern }, | ||
amount: { type: 'string', pattern: NonNegativeNumericPattern }, | ||
}, | ||
}; | ||
} | ||
|
||
/** | ||
* A mapping from column name to JSON conversion expected. | ||
* See getSqlConversionForDydxModelTypes for valid conversions. | ||
* | ||
* TODO(IND-239): Ensure that jsonSchema() / sqlToJsonConversions() / model fields match. | ||
*/ | ||
static get sqlToJsonConversions() { | ||
return { | ||
id: 'string', | ||
address: 'string', | ||
blockTime: 'date-time', | ||
blockHeight: 'string', | ||
amount: 'string', | ||
}; | ||
} | ||
|
||
QueryBuilderType!: UpsertQueryBuilder<this>; | ||
|
||
id!: string; | ||
|
||
address!: string; | ||
|
||
blockTime!: string; | ||
|
||
blockHeight!: string; | ||
|
||
amount!: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
indexer/packages/postgres/src/stores/trading-reward-table.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { QueryBuilder } from 'objection'; | ||
|
||
import { BUFFER_ENCODING_UTF_8, DEFAULT_POSTGRES_OPTIONS } from '../constants'; | ||
import { setupBaseQuery, verifyAllRequiredFields } from '../helpers/stores-helpers'; | ||
import Transaction from '../helpers/transaction'; | ||
import { getUuid } from '../helpers/uuid'; | ||
import TradingRewardModel from '../models/trading-reward-model'; | ||
import { | ||
Options, | ||
Ordering, | ||
QueryableField, | ||
QueryConfig, | ||
TradingRewardColumns, | ||
TradingRewardCreateObject, | ||
TradingRewardFromDatabase, | ||
TradingRewardQueryConfig, | ||
} from '../types'; | ||
|
||
export function uuid(address: string, blockHeight: string): string { | ||
// TODO(IND-483): Fix all uuid string substitutions to use Array.join. | ||
return getUuid(Buffer.from(`${address}-${blockHeight}`, BUFFER_ENCODING_UTF_8)); | ||
} | ||
|
||
export async function findAll( | ||
{ | ||
address, | ||
blockHeight, | ||
blockTimeBeforeOrAt, | ||
limit, | ||
}: TradingRewardQueryConfig, | ||
requiredFields: QueryableField[], | ||
options: Options = DEFAULT_POSTGRES_OPTIONS, | ||
): Promise<TradingRewardFromDatabase[]> { | ||
verifyAllRequiredFields( | ||
{ | ||
address, | ||
blockHeight, | ||
blockTimeBeforeOrAt, | ||
limit, | ||
} as QueryConfig, | ||
requiredFields, | ||
); | ||
|
||
let baseQuery: QueryBuilder<TradingRewardModel> = setupBaseQuery<TradingRewardModel>( | ||
TradingRewardModel, | ||
options, | ||
); | ||
|
||
if (address) { | ||
baseQuery = baseQuery.where(TradingRewardColumns.address, address); | ||
} | ||
|
||
if (blockHeight) { | ||
baseQuery = baseQuery.where(TradingRewardColumns.blockHeight, blockHeight); | ||
} | ||
|
||
if (blockTimeBeforeOrAt) { | ||
baseQuery = baseQuery.where(TradingRewardColumns.blockTime, '<=', blockTimeBeforeOrAt); | ||
} | ||
|
||
if (options.orderBy !== undefined) { | ||
for (const [column, order] of options.orderBy) { | ||
baseQuery = baseQuery.orderBy( | ||
column, | ||
order, | ||
); | ||
} | ||
} else { | ||
baseQuery = baseQuery.orderBy( | ||
TradingRewardColumns.blockHeight, | ||
Ordering.DESC, | ||
).orderBy( | ||
TradingRewardColumns.address, | ||
Ordering.DESC, | ||
); | ||
} | ||
|
||
if (limit) { | ||
baseQuery = baseQuery.limit(limit); | ||
} | ||
|
||
return baseQuery.returning('*'); | ||
} | ||
|
||
export async function create( | ||
tradingRewardToCreate: TradingRewardCreateObject, | ||
options: Options = { txId: undefined }, | ||
): Promise<TradingRewardFromDatabase> { | ||
return TradingRewardModel.query( | ||
Transaction.get(options.txId), | ||
).insert({ | ||
id: uuid(tradingRewardToCreate.address, tradingRewardToCreate.blockHeight), | ||
...tradingRewardToCreate, | ||
}).returning('*'); | ||
} | ||
|
||
export async function findById( | ||
address: string, | ||
options: Options = DEFAULT_POSTGRES_OPTIONS, | ||
): Promise<TradingRewardFromDatabase | undefined> { | ||
const baseQuery: QueryBuilder<TradingRewardModel> = setupBaseQuery<TradingRewardModel>( | ||
TradingRewardModel, | ||
options, | ||
); | ||
return baseQuery | ||
.findById(address) | ||
.returning('*'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
indexer/packages/postgres/src/types/trading-reward-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { IsoString } from './utility-types'; | ||
|
||
export interface TradingRewardCreateObject { | ||
address: string; | ||
blockTime: IsoString; | ||
blockHeight: string; | ||
amount: string; | ||
} | ||
|
||
export enum TradingRewardColumns { | ||
id = 'id', | ||
address = 'address', | ||
blockTime = 'blockTime', | ||
blockHeight = 'blockHeight', | ||
amount = 'amount', | ||
} |