-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Show current price in user assets (#526)
* show current price in user assets * fix condition --------- Co-authored-by: Adrian Adamiak <[email protected]>
- Loading branch information
1 parent
32dee7b
commit 4e67d8c
Showing
5 changed files
with
190 additions
and
15 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
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
76 changes: 76 additions & 0 deletions
76
packages/backend/src/peripherals/database/PricesRepository.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,76 @@ | ||
import { AssetId, Hash256, PedersenHash, Timestamp } from '@explorer/types' | ||
import { Logger } from '@l2beat/backend-tools' | ||
import { expect } from 'earl' | ||
import { it } from 'mocha' | ||
|
||
import { setupDatabaseTestSuite } from '../../test/database' | ||
import { PricesRepository } from './PricesRepository' | ||
import { StateUpdateRepository } from './StateUpdateRepository' | ||
|
||
describe(PricesRepository.name, () => { | ||
const { database } = setupDatabaseTestSuite() | ||
const stateUpdateRepository = new StateUpdateRepository( | ||
database, | ||
Logger.SILENT | ||
) | ||
const repository = new PricesRepository(database, Logger.SILENT) | ||
|
||
afterEach(() => repository.deleteAll()) | ||
|
||
describe(PricesRepository.prototype.getAllLatest.name, () => { | ||
it('returns prices for all assets for the latest state update', async () => { | ||
await stateUpdateRepository.add(mockStateUpdate(1)) | ||
await stateUpdateRepository.add(mockStateUpdate(199)) | ||
await stateUpdateRepository.add(mockStateUpdate(200)) | ||
|
||
await repository.add({ | ||
stateUpdateId: 200, | ||
assetId: AssetId('MATIC-6'), | ||
price: 100n, | ||
}) | ||
await repository.add({ | ||
stateUpdateId: 200, | ||
assetId: AssetId('LTC-8'), | ||
price: 100n, | ||
}) | ||
await repository.add({ | ||
stateUpdateId: 200, | ||
assetId: AssetId('ETH-9'), | ||
price: 100n, | ||
}) | ||
await repository.add({ | ||
stateUpdateId: 199, | ||
assetId: AssetId('USDC-6'), | ||
price: 100n, | ||
}) | ||
await repository.add({ | ||
stateUpdateId: 1, | ||
assetId: AssetId('ETH-9'), | ||
price: 100n, | ||
}) | ||
|
||
const results = await repository.getAllLatest() | ||
expect(results).toEqualUnsorted([ | ||
{ stateUpdateId: 200, assetId: AssetId('MATIC-6'), price: 100n }, | ||
{ stateUpdateId: 200, assetId: AssetId('LTC-8'), price: 100n }, | ||
{ stateUpdateId: 200, assetId: AssetId('ETH-9'), price: 100n }, | ||
]) | ||
}) | ||
}) | ||
}) | ||
|
||
function mockStateUpdate(id: number) { | ||
return { | ||
stateUpdate: { | ||
id, | ||
batchId: id - 1, | ||
blockNumber: id, | ||
rootHash: PedersenHash.fake(), | ||
stateTransitionHash: Hash256.fake(), | ||
timestamp: Timestamp(0), | ||
}, | ||
positions: [], | ||
prices: [], | ||
transactionHashes: [], | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
packages/backend/src/peripherals/database/PricesRepository.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 { AssetId } from '@explorer/types' | ||
import { Logger } from '@l2beat/backend-tools' | ||
import { PriceRow } from 'knex/types/tables' | ||
|
||
import { BaseRepository } from './shared/BaseRepository' | ||
import { Database } from './shared/Database' | ||
|
||
export interface PricesRecord { | ||
stateUpdateId: number | ||
assetId: AssetId | ||
price: bigint | ||
} | ||
|
||
export class PricesRepository extends BaseRepository { | ||
constructor(database: Database, logger: Logger) { | ||
super(database, logger) | ||
|
||
/* eslint-disable @typescript-eslint/unbound-method */ | ||
this.add = this.wrapAdd(this.add) | ||
this.getAllLatest = this.wrapGet(this.getAllLatest) | ||
this.deleteAll = this.wrapDelete(this.deleteAll) | ||
/* eslint-enable @typescript-eslint/unbound-method */ | ||
} | ||
|
||
async add(record: PricesRecord): Promise<number> { | ||
const knex = await this.knex() | ||
const results = await knex('prices') | ||
.insert(toPriceRow(record)) | ||
.returning('state_update_id') | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return results[0]!.state_update_id | ||
} | ||
|
||
async getAllLatest() { | ||
const knex = await this.knex() | ||
|
||
const rows = await knex('prices') | ||
.select('*') | ||
.innerJoin( | ||
knex('prices') | ||
.max('state_update_id as max_state_update_id') | ||
.as('latest_prices'), | ||
(join) => { | ||
join.on( | ||
'prices.state_update_id', | ||
'=', | ||
'latest_prices.max_state_update_id' | ||
) | ||
} | ||
) | ||
|
||
return rows.map(toPricesRecord) | ||
} | ||
|
||
async deleteAll() { | ||
const knex = await this.knex() | ||
return await knex('prices').delete() | ||
} | ||
} | ||
|
||
function toPricesRecord(row: PriceRow): PricesRecord { | ||
return { | ||
stateUpdateId: row.state_update_id, | ||
assetId: AssetId(row.asset_id), | ||
price: BigInt(row.price), | ||
} | ||
} | ||
|
||
function toPriceRow(record: PricesRecord): PriceRow { | ||
return { | ||
state_update_id: record.stateUpdateId, | ||
asset_id: record.assetId.toString(), | ||
price: record.price, | ||
} | ||
} |
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