-
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-496]: Create trading_reward_aggregations postgres table (#825)
* [IND-496]: Create trading_reward_aggregations postgres table * rabbit recommendations * nit
- Loading branch information
1 parent
207b903
commit b5d4e8a
Showing
15 changed files
with
484 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
103 changes: 103 additions & 0 deletions
103
indexer/packages/postgres/__tests__/stores/trading-reward-aggregation-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,103 @@ | ||
import { TradingRewardAggregationFromDatabase } from '../../src/types'; | ||
import { clearData, migrate, teardown } from '../../src/helpers/db-helpers'; | ||
import { | ||
defaultSubaccountId, | ||
defaultTradingRewardAggregation, | ||
defaultTradingRewardAggregationId, | ||
defaultWallet, | ||
} from '../helpers/constants'; | ||
import * as TradingRewardAggregationTable from '../../src/stores/trading-reward-aggregation-table'; | ||
import { WalletTable } from '../../src'; | ||
import { seedData } from '../helpers/mock-generators'; | ||
|
||
describe('TradingRewardAggregation store', () => { | ||
beforeAll(async () => { | ||
await migrate(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
await seedData(); | ||
await WalletTable.create(defaultWallet); | ||
}); | ||
|
||
afterEach(async () => { | ||
await clearData(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await teardown(); | ||
}); | ||
|
||
it('Successfully creates a TradingRewardAggregation', async () => { | ||
await TradingRewardAggregationTable.create(defaultTradingRewardAggregation); | ||
}); | ||
|
||
it('Successfully finds all TradingRewardAggregations', async () => { | ||
await Promise.all([ | ||
TradingRewardAggregationTable.create(defaultTradingRewardAggregation), | ||
TradingRewardAggregationTable.create({ | ||
...defaultTradingRewardAggregation, | ||
startedAtHeight: '1', | ||
}), | ||
]); | ||
|
||
const tradingRewardAggregations: | ||
TradingRewardAggregationFromDatabase[] = await TradingRewardAggregationTable.findAll( | ||
{}, | ||
[], | ||
{ readReplica: true }, | ||
); | ||
|
||
expect(tradingRewardAggregations.length).toEqual(2); | ||
expect(tradingRewardAggregations[0]).toEqual(expect.objectContaining({ | ||
...defaultTradingRewardAggregation, | ||
startedAtHeight: '1', | ||
})); | ||
expect(tradingRewardAggregations[1]).toEqual( | ||
expect.objectContaining(defaultTradingRewardAggregation), | ||
); | ||
}); | ||
|
||
it('Successfully finds a TradingRewardAggregation', async () => { | ||
await TradingRewardAggregationTable.create(defaultTradingRewardAggregation); | ||
|
||
const tradingRewardAggregation: | ||
TradingRewardAggregationFromDatabase | undefined = await TradingRewardAggregationTable.findById( | ||
defaultTradingRewardAggregationId, | ||
); | ||
|
||
expect(tradingRewardAggregation).toEqual( | ||
expect.objectContaining(defaultTradingRewardAggregation), | ||
); | ||
}); | ||
|
||
it('Successfully returns undefined when updating a nonexistent TradingRewardAggregation', async () => { | ||
const fakeUpdate: | ||
TradingRewardAggregationFromDatabase | undefined = await TradingRewardAggregationTable.update({ | ||
id: defaultSubaccountId, | ||
}); | ||
expect(fakeUpdate).toBeUndefined(); | ||
}); | ||
|
||
it('Successfully updates an existing TradingRewardAggregation', async () => { | ||
await TradingRewardAggregationTable.create(defaultTradingRewardAggregation); | ||
|
||
const amount: string = '100000.00'; | ||
const endedAt: string = '2021-01-01T00:00:00.000Z'; | ||
const endedAtHeight: string = '1000'; | ||
const update: | ||
TradingRewardAggregationFromDatabase | undefined = await TradingRewardAggregationTable.update({ | ||
id: defaultTradingRewardAggregationId, | ||
endedAt, | ||
endedAtHeight, | ||
amount, | ||
}); | ||
expect(update).toEqual({ | ||
...defaultTradingRewardAggregation, | ||
id: defaultTradingRewardAggregationId, | ||
endedAt, | ||
endedAtHeight, | ||
amount, | ||
}); | ||
}); | ||
}); |
File renamed without changes.
35 changes: 35 additions & 0 deletions
35
.../db/migrations/migration_files/20231130153800_create_trading_reward_aggregations_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,35 @@ | ||
import * as Knex from 'knex'; | ||
|
||
export async function up(knex: Knex): Promise<void> { | ||
return knex | ||
.schema | ||
.createTable('trading_reward_aggregations', (table) => { | ||
table.uuid('id').primary(); | ||
table.string('address').notNullable(); | ||
table.timestamp('startedAt').notNullable(); | ||
table.bigInteger('startedAtHeight').notNullable(); | ||
table.timestamp('endedAt').nullable(); | ||
table.bigInteger('endedAtHeight').nullable(); | ||
table.enum( | ||
'period', | ||
[ | ||
'DAILY', | ||
'WEEKLY', | ||
'MONTHLY', | ||
], | ||
).notNullable(); | ||
table.decimal('amount').notNullable(); | ||
|
||
// Foreign | ||
table.foreign('address').references('wallets.address'); | ||
table.foreign('startedAtHeight').references('blocks.blockHeight'); | ||
|
||
// Indices | ||
table.index(['address', 'startedAtHeight']); | ||
table.index(['period', 'startedAtHeight']); | ||
}); | ||
} | ||
|
||
export async function down(knex: Knex): Promise<void> { | ||
return knex.schema.dropTableIfExists('trading_reward_aggregations'); | ||
} |
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
98 changes: 98 additions & 0 deletions
98
indexer/packages/postgres/src/models/trading-reward-aggregation-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,98 @@ | ||
import path from 'path'; | ||
|
||
import { Model } from 'objection'; | ||
|
||
import { IntegerPattern, NonNegativeNumericPattern } from '../lib/validators'; | ||
import UpsertQueryBuilder from '../query-builders/upsert'; | ||
import { IsoString } from '../types'; | ||
import { TradingRewardAggregationPeriod } from '../types/trading-reward-aggregation-types'; | ||
|
||
export default class TradingRewardAggregationModel extends Model { | ||
static get tableName() { | ||
return 'trading_reward_aggregations'; | ||
} | ||
|
||
static get idColumn() { | ||
return 'id'; | ||
} | ||
|
||
static relationMappings = { | ||
wallets: { | ||
relation: Model.BelongsToOneRelation, | ||
modelClass: path.join(__dirname, 'wallet-model'), | ||
join: { | ||
from: 'trading_reward_aggregations.address', | ||
to: 'wallets.address', | ||
}, | ||
}, | ||
blocks: { | ||
relation: Model.BelongsToOneRelation, | ||
modelClass: path.join(__dirname, 'block-model'), | ||
join: { | ||
from: 'trading_reward_aggregations.startedAtHeight', | ||
to: 'blocks.height', | ||
}, | ||
}, | ||
}; | ||
|
||
static get jsonSchema() { | ||
return { | ||
type: 'object', | ||
required: [ | ||
'id', // Generated from `address` and `startedAt` and `period` | ||
'address', | ||
'startedAt', | ||
'startedAtHeight', | ||
'period', | ||
'amount', // amount of token rewards earned by address in the period starting with startedAt | ||
], | ||
properties: { | ||
id: { type: 'string', format: 'uuid' }, | ||
address: { type: 'string' }, | ||
startedAt: { type: 'string', format: 'date-time' }, // Inclusive | ||
startedAtHeight: { type: 'string', pattern: IntegerPattern }, // Inclusive | ||
endedAt: { type: ['string', 'null'], format: 'date-time' }, // Inclusive | ||
endedAtHeight: { type: ['string', 'null'], pattern: IntegerPattern }, // Inclusive | ||
period: { type: 'string', enum: [...Object.values(TradingRewardAggregationPeriod)] }, | ||
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', | ||
startedAt: 'date-time', | ||
startedAtHeight: 'string', | ||
endedAt: 'date-time', | ||
endedAtHeight: 'string', | ||
period: 'string', | ||
amount: 'string', | ||
}; | ||
} | ||
|
||
QueryBuilderType!: UpsertQueryBuilder<this>; | ||
|
||
id!: string; | ||
|
||
address!: string; | ||
|
||
startedAt!: IsoString; | ||
|
||
startedAtHeight!: string; | ||
|
||
endedAt!: IsoString; | ||
|
||
endedAtHeight!: string; | ||
|
||
period!: TradingRewardAggregationPeriod; | ||
|
||
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
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.