-
Notifications
You must be signed in to change notification settings - Fork 117
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
- Loading branch information
1 parent
b274f0a
commit d41d94a
Showing
11 changed files
with
335 additions
and
3 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
55 changes: 55 additions & 0 deletions
55
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,55 @@ | ||
import { TradingRewardFromDatabase } from '../../src/types'; | ||
import { clearData, migrate, teardown } from '../../src/helpers/db-helpers'; | ||
import { defaultTradingReward } from '../helpers/constants'; | ||
import * as TradingRewardTable from '../../src/stores/trading-reward-table'; | ||
|
||
describe('TradingReward store', () => { | ||
beforeAll(async () => { | ||
await migrate(); | ||
}); | ||
|
||
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)); | ||
expect(tradingRewards[1]).toEqual(expect.objectContaining({ | ||
...defaultTradingReward, | ||
blockHeight: '20', | ||
})); | ||
}); | ||
|
||
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('wallet.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
105 changes: 105 additions & 0 deletions
105
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,105 @@ | ||
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.ASC, | ||
); | ||
} | ||
|
||
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
Oops, something went wrong.