Handle bigint and decimal types for entities in watchers (#295)

* Add a GraphDecimal class to replace Decimal with

* Replace Decimal in uni-info-watcher with GraphDecimal

* Add definition for custom scalar BigDecimal in uni-info-watcher

* Use pg-type numeric and transformer for bigint columns in typeorm entities
This commit is contained in:
prathamesh0 2021-12-02 13:22:29 +05:30 committed by GitHub
parent 9d95e49ec9
commit 08c712d766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 573 additions and 340 deletions

View File

@ -3,6 +3,7 @@
//
import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm';
import { bigintTransformer } from '@vulcanize/util';
@Entity()
@Index(['blockHash', 'blockNumber', 'token', 'owner', 'spender'], { unique: true })
@ -25,7 +26,7 @@ export class Allowance {
@Column('varchar', { length: 42 })
spender!: string;
@Column('numeric')
@Column('numeric', { transformer: bigintTransformer })
value!: bigint;
@Column('text', { nullable: true })

View File

@ -3,6 +3,7 @@
//
import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm';
import { bigintTransformer } from '@vulcanize/util';
@Entity()
@Index(['blockHash', 'blockNumber', 'token', 'owner'], { unique: true })
@ -22,7 +23,7 @@ export class Balance {
@Column('varchar', { length: 42 })
owner!: string;
@Column('numeric')
@Column('numeric', { transformer: bigintTransformer })
value!: bigint;
@Column('text', { nullable: true })

View File

@ -14,8 +14,8 @@
"apollo-server-express": "^2.25.0",
"apollo-type-bigint": "^0.1.3",
"debug": "^4.3.1",
"decimal.js": "^10.3.1",
"express": "^4.17.1",
"graphql": "^15.5.0",
"graphql-import-node": "^0.0.4",
"graphql-request": "^3.4.0",
"json-bigint": "^1.0.0",

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal } from '@vulcanize/util';
@Entity()
export class Bundle {
@ -18,6 +17,6 @@ export class Bundle {
@Column('integer')
blockNumber!: number;
@Column('numeric', { default: 0, transformer: decimalTransformer })
ethPriceUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
ethPriceUSD!: GraphDecimal
}

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { bigintTransformer, graphDecimalTransformer, GraphDecimal } from '@vulcanize/util';
import { Transaction } from './Transaction';
import { Pool } from './Pool';
@ -25,8 +24,8 @@ export class Burn {
@ManyToOne(() => Transaction, transaction => transaction.burns, { onDelete: 'CASCADE' })
transaction!: Transaction
@Column('bigint')
timestamp!: BigInt;
@Column('numeric', { transformer: bigintTransformer })
timestamp!: bigint;
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool
@ -43,21 +42,21 @@ export class Burn {
@Column('varchar', { length: 42 })
origin!: string
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
amount!: bigint
@Column('numeric', { transformer: decimalTransformer })
amount0!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amount0!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
amount1!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amount1!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
amountUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amountUSD!: GraphDecimal
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
tickLower!: bigint
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
tickUpper!: bigint
}

View File

@ -2,9 +2,8 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { Entity, Column, PrimaryColumn } from 'typeorm';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
@Entity()
export class Factory {
@ -18,32 +17,32 @@ export class Factory {
@Column('integer')
blockNumber!: number;
@Column('bigint', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
poolCount!: bigint;
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedETH!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedETH!: GraphDecimal;
@Column('bigint', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
txCount!: bigint;
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedUSD!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedUSD!: GraphDecimal;
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalVolumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalVolumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalVolumeETH!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalVolumeETH!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalFeesUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalFeesUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalFeesETH!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalFeesETH!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
untrackedVolumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
untrackedVolumeUSD!: GraphDecimal
// TODO: Add remaining fields when they are used.
}

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Transaction } from './Transaction';
import { Pool } from './Pool';
@ -25,8 +24,8 @@ export class Mint {
@ManyToOne(() => Transaction, transaction => transaction.mints, { onDelete: 'CASCADE' })
transaction!: Transaction
@Column('bigint')
timestamp!: BigInt;
@Column('numeric', { transformer: bigintTransformer })
timestamp!: bigint;
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool
@ -46,21 +45,21 @@ export class Mint {
@Column('varchar', { length: 42 })
origin!: string
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
amount!: bigint
@Column('numeric', { transformer: decimalTransformer })
amount0!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amount0!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
amount1!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amount1!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
amountUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amountUSD!: GraphDecimal
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
tickLower!: bigint
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
tickUpper!: bigint
}

View File

@ -2,9 +2,8 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Token } from './Token';
@ -26,59 +25,59 @@ export class Pool {
@ManyToOne(() => Token, { onDelete: 'CASCADE' })
token1!: Token;
@Column('numeric', { default: 0, transformer: decimalTransformer })
token0Price!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
token0Price!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
token1Price!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
token1Price!: GraphDecimal
@Column('numeric')
@Column('numeric', { transformer: bigintTransformer })
feeTier!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
sqrtPrice!: bigint
@Column('bigint', { nullable: true })
@Column('numeric', { nullable: true, transformer: bigintTransformer })
tick!: bigint | null
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
liquidity!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
feeGrowthGlobal0X128!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
feeGrowthGlobal1X128!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedToken1!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedETH!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedETH!: GraphDecimal
@Column('bigint', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
txCount!: bigint;
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeToken1!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
untrackedVolumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
untrackedVolumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
feesUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
feesUSD!: GraphDecimal
// TODO: Add remaining fields when they are used.
}

View File

@ -2,9 +2,8 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Pool } from './Pool';
@ -26,56 +25,56 @@ export class PoolDayData {
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool;
@Column('numeric', { transformer: decimalTransformer })
high!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
high!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
low!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
low!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
open!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
open!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
close!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
close!: GraphDecimal;
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
sqrtPrice!: bigint
@Column('bigint', { nullable: true })
@Column('numeric', { nullable: true, transformer: bigintTransformer })
tick!: bigint | null
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
liquidity!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
feeGrowthGlobal0X128!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
feeGrowthGlobal1X128!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
token0Price!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
token0Price!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
token1Price!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
token1Price!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
tvlUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
tvlUSD!: GraphDecimal
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
txCount!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeToken1!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
feesUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
feesUSD!: GraphDecimal
// TODO: Add remaining fields when they are used.
}

View File

@ -2,9 +2,8 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Pool } from './Pool';
@ -26,56 +25,56 @@ export class PoolHourData {
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool;
@Column('numeric', { transformer: decimalTransformer })
high!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
high!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
low!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
low!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
open!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
open!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
close!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
close!: GraphDecimal;
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
sqrtPrice!: bigint
@Column('bigint', { nullable: true })
@Column('numeric', { nullable: true, transformer: bigintTransformer })
tick!: bigint | null
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
liquidity!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
feeGrowthGlobal0X128!: bigint
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
feeGrowthGlobal1X128!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
token0Price!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
token0Price!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
token1Price!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
token1Price!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
tvlUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
tvlUSD!: GraphDecimal
@Column('numeric', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
txCount!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeToken1!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
feesUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
feesUSD!: GraphDecimal
// TODO: Add remaining fields when they are used.
}

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Pool } from './Pool';
import { Token } from './Token';
@ -24,35 +23,35 @@ export class Position {
@Column('integer')
blockNumber!: number;
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
feeGrowthInside0LastX128!: bigint
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
feeGrowthInside1LastX128!: bigint
@Column('bigint', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
liquidity!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
depositedToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
depositedToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
depositedToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
depositedToken1!: GraphDecimal
@Column('varchar', { length: 42, default: ADDRESS_ZERO })
owner!: string
@Column('numeric', { default: 0, transformer: decimalTransformer })
withdrawnToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
withdrawnToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
withdrawnToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
withdrawnToken1!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
collectedFeesToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
collectedFeesToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
collectedFeesToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
collectedFeesToken1!: GraphDecimal
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Pool } from './Pool';
import { Transaction } from './Transaction';
@ -23,38 +22,38 @@ export class PositionSnapshot {
@Column('integer')
blockNumber!: number;
@Column('bigint')
timestamp!: BigInt;
@Column('numeric', { transformer: bigintTransformer })
timestamp!: bigint;
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
feeGrowthInside0LastX128!: bigint
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
feeGrowthInside1LastX128!: bigint
@Column('bigint', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
liquidity!: bigint
@Column('numeric', { default: 0, transformer: decimalTransformer })
depositedToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
depositedToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
depositedToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
depositedToken1!: GraphDecimal
@Column('varchar', { length: 42, default: ADDRESS_ZERO })
owner!: string
@Column('numeric', { default: 0, transformer: decimalTransformer })
withdrawnToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
withdrawnToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
withdrawnToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
withdrawnToken1!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
collectedFeesToken0!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
collectedFeesToken0!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
collectedFeesToken1!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
collectedFeesToken1!: GraphDecimal
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Transaction } from './Transaction';
import { Pool } from './Pool';
@ -25,8 +24,8 @@ export class Swap {
@ManyToOne(() => Transaction, transaction => transaction.swaps, { onDelete: 'CASCADE' })
transaction!: Transaction
@Column('bigint')
timestamp!: BigInt;
@Column('numeric', { transformer: bigintTransformer })
timestamp!: bigint;
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool
@ -46,18 +45,18 @@ export class Swap {
@Column('varchar', { length: 42 })
recipient!: string
@Column('numeric', { transformer: decimalTransformer })
amount0!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amount0!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
amount1!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amount1!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
amountUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
amountUSD!: GraphDecimal
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
tick!: bigint
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
sqrtPriceX96!: bigint
}

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Pool } from './Pool';
@ -20,8 +19,8 @@ export class Tick {
@Column('integer')
blockNumber!: number;
@Column('bigint')
tickIdx!: BigInt;
@Column('numeric', { transformer: bigintTransformer })
tickIdx!: bigint;
@ManyToOne(() => Pool, { onDelete: 'CASCADE' })
pool!: Pool
@ -29,15 +28,15 @@ export class Tick {
@Column('varchar', { length: 42 })
poolAddress!: string
@Column('numeric', { transformer: decimalTransformer })
price0!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
price0!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
price1!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
price1!: GraphDecimal
@Column('bigint', { default: 0 })
@Column('numeric', { default: 0, transformer: bigintTransformer })
liquidityGross!: bigint
@Column('bigint', { default: 0 })
@Column('numeric', { default: 0, transformer: bigintTransformer })
liquidityNet!: bigint
}

View File

@ -2,9 +2,8 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { Entity, PrimaryColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Pool } from './Pool';
@ -26,35 +25,35 @@ export class Token {
@Column('varchar')
name!: string;
@Column('numeric', { transformer: decimalTransformer })
totalSupply!: Decimal;
@Column('numeric', { transformer: bigintTransformer })
totalSupply!: bigint;
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
decimals!: bigint;
@Column('numeric', { default: 0, transformer: decimalTransformer })
derivedETH!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
derivedETH!: GraphDecimal;
@Column('bigint', { default: BigInt(0) })
@Column('numeric', { default: BigInt(0), transformer: bigintTransformer })
txCount!: bigint;
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLocked!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLocked!: GraphDecimal;
@Column('numeric', { default: 0, transformer: decimalTransformer })
totalValueLockedUSD!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
totalValueLockedUSD!: GraphDecimal;
@Column('numeric', { default: 0, transformer: decimalTransformer })
volume!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volume!: GraphDecimal;
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal;
@Column('numeric', { default: 0, transformer: decimalTransformer })
untrackedVolumeUSD!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
untrackedVolumeUSD!: GraphDecimal;
@Column('numeric', { default: 0, transformer: decimalTransformer })
feesUSD!: Decimal;
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
feesUSD!: GraphDecimal;
@ManyToMany(() => Pool)
@JoinTable()

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal } from '@vulcanize/util';
import { Token } from './Token';
@ -26,36 +25,36 @@ export class TokenDayData {
@ManyToOne(() => Token, { onDelete: 'CASCADE' })
token!: Token
@Column('numeric', { transformer: decimalTransformer })
high!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
high!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
low!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
low!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
open!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
open!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
close!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
close!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
priceUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
priceUSD!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
totalValueLocked!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
totalValueLocked!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
totalValueLockedUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
totalValueLockedUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volume!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volume!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
untrackedVolumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
untrackedVolumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
feesUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
feesUSD!: GraphDecimal
}

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal } from '@vulcanize/util';
import { Token } from './Token';
@ -26,36 +25,36 @@ export class TokenHourData {
@ManyToOne(() => Token, { onDelete: 'CASCADE' })
token!: Token
@Column('numeric', { transformer: decimalTransformer })
high!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
high!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
low!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
low!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
open!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
open!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
close!: Decimal;
@Column('numeric', { transformer: graphDecimalTransformer })
close!: GraphDecimal;
@Column('numeric', { transformer: decimalTransformer })
priceUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
priceUSD!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
totalValueLocked!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
totalValueLocked!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer })
totalValueLockedUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
totalValueLockedUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volume!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volume!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
untrackedVolumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
untrackedVolumeUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
feesUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
feesUSD!: GraphDecimal
}

View File

@ -2,9 +2,8 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { Entity, PrimaryColumn, Column, OneToMany } from 'typeorm';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
import { Mint } from './Mint';
import { Burn } from './Burn';
@ -22,11 +21,11 @@ export class Transaction {
@Column('integer')
blockNumber!: number;
@Column('numeric', { default: 0, transformer: decimalTransformer })
ethPriceUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
ethPriceUSD!: GraphDecimal
@Column('bigint')
timestamp!: BigInt;
@Column('numeric', { transformer: bigintTransformer })
timestamp!: bigint;
@OneToMany(() => Mint, mint => mint.transaction)
mints!: Mint[];

View File

@ -3,8 +3,7 @@
//
import { Entity, PrimaryColumn, Column } from 'typeorm';
import Decimal from 'decimal.js';
import { decimalTransformer } from '@vulcanize/util';
import { graphDecimalTransformer, GraphDecimal, bigintTransformer } from '@vulcanize/util';
@Entity()
export class UniswapDayData {
@ -21,18 +20,18 @@ export class UniswapDayData {
@Column('integer')
date!: number
@Column('numeric', { transformer: decimalTransformer })
tvlUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer })
tvlUSD!: GraphDecimal
@Column('numeric', { default: 0, transformer: decimalTransformer })
volumeUSD!: Decimal
@Column('numeric', { default: 0, transformer: graphDecimalTransformer })
volumeUSD!: GraphDecimal
@Column('bigint')
@Column('numeric', { transformer: bigintTransformer })
txCount!: bigint;
@Column('numeric', { transformer: decimalTransformer, default: 0 })
volumeETH!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer, default: 0 })
volumeETH!: GraphDecimal
@Column('numeric', { transformer: decimalTransformer, default: 0 })
feesUSD!: Decimal
@Column('numeric', { transformer: graphDecimalTransformer, default: 0 })
feesUSD!: GraphDecimal
}

View File

@ -11,14 +11,13 @@ import { providers, utils } from 'ethers';
import { Client as UniClient } from '@vulcanize/uni-watcher';
import { Client as ERC20Client } from '@vulcanize/erc20-watcher';
import { EthClient } from '@vulcanize/ipld-eth-client';
import { IndexerInterface, Indexer as BaseIndexer, QueryOptions, OrderDirection, BlockHeight, Relation } from '@vulcanize/util';
import { IndexerInterface, Indexer as BaseIndexer, QueryOptions, OrderDirection, BlockHeight, Relation, GraphDecimal } from '@vulcanize/util';
import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices, WHITELIST_TOKENS } from './utils/pricing';
import { updatePoolDayData, updatePoolHourData, updateTokenDayData, updateTokenHourData, updateUniswapDayData } from './utils/interval-updates';
import { Token } from './entity/Token';
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
import { createTick } from './utils/tick';
import Decimal from 'decimal.js';
import { Position } from './entity/Position';
import { Database } from './database';
import { Event } from './entity/Event';
@ -874,12 +873,12 @@ export class Indexer implements IndexerInterface {
let amount0Abs = amount0;
let amount1Abs = amount1;
if (amount0.lt(new Decimal(0))) {
amount0Abs = amount0.times(new Decimal('-1'));
if (amount0.lt(new GraphDecimal(0))) {
amount0Abs = amount0.times(new GraphDecimal('-1'));
}
if (amount1.lt(new Decimal(0))) {
amount1Abs = amount1.times(new Decimal('-1'));
if (amount1.lt(new GraphDecimal(0))) {
amount1Abs = amount1.times(new GraphDecimal('-1'));
}
const amount0ETH = amount0Abs.times(token0.derivedETH);
@ -889,12 +888,12 @@ export class Indexer implements IndexerInterface {
// Get amount that should be tracked only - div 2 because cant count both input and output as volume.
const trackedAmountUSD = await getTrackedAmountUSD(this._db, dbTx, amount0Abs, token0, amount1Abs, token1, this._isDemo);
const amountTotalUSDTracked = trackedAmountUSD.div(new Decimal('2'));
const amountTotalUSDTracked = trackedAmountUSD.div(new GraphDecimal('2'));
const amountTotalETHTracked = safeDiv(amountTotalUSDTracked, bundle.ethPriceUSD);
const amountTotalUSDUntracked = amount0USD.plus(amount1USD).div(new Decimal('2'));
const amountTotalUSDUntracked = amount0USD.plus(amount1USD).div(new GraphDecimal('2'));
const feesETH = amountTotalETHTracked.times(pool.feeTier.toString()).div(new Decimal('1000000'));
const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toString()).div(new Decimal('1000000'));
const feesETH = amountTotalETHTracked.times(pool.feeTier.toString()).div(new GraphDecimal('1000000'));
const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toString()).div(new GraphDecimal('1000000'));
// Global updates.
factory.txCount = BigInt(factory.txCount) + BigInt(1);

View File

@ -5,8 +5,9 @@
import assert from 'assert';
import BigInt from 'apollo-type-bigint';
import debug from 'debug';
import { GraphQLScalarType } from 'graphql';
import { BlockHeight, OrderDirection } from '@vulcanize/util';
import { BlockHeight, GraphDecimal, OrderDirection } from '@vulcanize/util';
import { Indexer } from './indexer';
import { Burn } from './entity/Burn';
@ -35,6 +36,19 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
return {
BigInt: new BigInt('bigInt'),
BigDecimal: new GraphQLScalarType({
name: 'BigDecimal',
description: 'BigDecimal custom scalar type',
parseValue (value) {
// value from the client
return new GraphDecimal(value);
},
serialize (value: GraphDecimal) {
// value sent to the client
return value.toFixed();
}
}),
ChainIndexingStatus: {
__resolveType: () => {
return 'EthereumIndexingStatus';

View File

@ -2,16 +2,17 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { BigNumber } from 'ethers';
import { QueryRunner } from 'typeorm';
import { GraphDecimal } from '@vulcanize/util';
import { Transaction as TransactionEntity } from '../entity/Transaction';
import { Database } from '../database';
import { Block, Transaction } from '../events';
export const exponentToBigDecimal = (decimals: bigint): Decimal => {
let bd = new Decimal(1);
export const exponentToBigDecimal = (decimals: bigint): GraphDecimal => {
let bd = new GraphDecimal(1);
for (let i = 0; BigNumber.from(decimals).gte(i); i++) {
bd = bd.times(10);
@ -20,12 +21,12 @@ export const exponentToBigDecimal = (decimals: bigint): Decimal => {
return bd;
};
export const convertTokenToDecimal = (tokenAmount: bigint, exchangeDecimals: bigint): Decimal => {
export const convertTokenToDecimal = (tokenAmount: bigint, exchangeDecimals: bigint): GraphDecimal => {
if (exchangeDecimals === BigInt(0)) {
return new Decimal(tokenAmount.toString());
return new GraphDecimal(tokenAmount.toString());
}
return (new Decimal(tokenAmount.toString())).div(exponentToBigDecimal(exchangeDecimals));
return (new GraphDecimal(tokenAmount.toString())).div(exponentToBigDecimal(exchangeDecimals));
};
export const loadTransaction = async (db: Database, dbTx: QueryRunner, event: { block: Block, tx: Transaction }): Promise<TransactionEntity> => {
@ -44,21 +45,21 @@ export const loadTransaction = async (db: Database, dbTx: QueryRunner, event: {
};
// Return 0 if denominator is 0 in division.
export const safeDiv = (amount0: Decimal, amount1: Decimal): Decimal => {
export const safeDiv = (amount0: GraphDecimal, amount1: GraphDecimal): GraphDecimal => {
if (amount1.isZero()) {
return new Decimal(0);
return new GraphDecimal(0);
} else {
return amount0.div(amount1);
}
};
export const bigDecimalExponated = (value: Decimal, power: bigint): Decimal => {
export const bigDecimalExponated = (value: GraphDecimal, power: bigint): GraphDecimal => {
if (power === BigInt(0)) {
return new Decimal(1);
return new GraphDecimal(1);
}
const negativePower = power > BigInt(0);
let result = (new Decimal(0)).plus(value);
let result = (new GraphDecimal(0)).plus(value);
const powerAbs = BigNumber.from(power).abs();
for (let i = BigNumber.from(1); i.lt(powerAbs); i = i.add(1)) {
@ -66,7 +67,7 @@ export const bigDecimalExponated = (value: Decimal, power: bigint): Decimal => {
}
if (negativePower) {
result = safeDiv(new Decimal(1), result);
result = safeDiv(new GraphDecimal(1), result);
}
return result;

View File

@ -3,10 +3,11 @@
//
import assert from 'assert';
import Decimal from 'decimal.js';
import { BigNumber } from 'ethers';
import { QueryRunner } from 'typeorm';
import { GraphDecimal } from '@vulcanize/util';
import { exponentToBigDecimal, safeDiv } from '.';
import { Database } from '../database';
import { Token } from '../entity/Token';
@ -43,30 +44,30 @@ export const WHITELIST_TOKENS: string[] = [
'0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9' // AAVE
];
const MINIMUM_ETH_LOCKED = new Decimal(52);
const MINIMUM_ETH_LOCKED = new GraphDecimal(52);
const Q192 = 2 ** 192;
// Constants used in demo.
const ETH_PRICE_IN_USD = '3200.00';
export const sqrtPriceX96ToTokenPrices = (sqrtPriceX96: bigint, token0: Token, token1: Token): Decimal[] => {
const num = new Decimal((sqrtPriceX96 * sqrtPriceX96).toString());
const denom = new Decimal(Q192.toString());
export const sqrtPriceX96ToTokenPrices = (sqrtPriceX96: bigint, token0: Token, token1: Token): GraphDecimal[] => {
const num = new GraphDecimal((sqrtPriceX96 * sqrtPriceX96).toString());
const denom = new GraphDecimal(Q192.toString());
const price1 = num
.div(denom)
.times(exponentToBigDecimal(token0.decimals))
.div(exponentToBigDecimal(token1.decimals));
const price0 = safeDiv(new Decimal('1'), price1);
const price0 = safeDiv(new GraphDecimal('1'), price1);
return [price0, price1];
};
export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: Block, isDemo: boolean): Promise<Decimal> => {
export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: Block, isDemo: boolean): Promise<GraphDecimal> => {
if (isDemo) {
// For demo purpose in local development.
const ethPriceInUSD = new Decimal(ETH_PRICE_IN_USD);
const ethPriceInUSD = new GraphDecimal(ETH_PRICE_IN_USD);
return ethPriceInUSD;
}
@ -76,7 +77,7 @@ export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: B
if (usdcPool) {
return usdcPool.token0Price;
} else {
return new Decimal(0);
return new GraphDecimal(0);
}
};
@ -84,16 +85,16 @@ export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: B
* Search through graph to find derived Eth per token.
* @todo update to be derived ETH (add stablecoin estimates)
**/
export const findEthPerToken = async (db: Database, dbTx: QueryRunner, token: Token, isDemo: boolean): Promise<Decimal> => {
export const findEthPerToken = async (db: Database, dbTx: QueryRunner, token: Token, isDemo: boolean): Promise<GraphDecimal> => {
if (token.id === WETH_ADDRESS || isDemo) {
return new Decimal(1);
return new GraphDecimal(1);
}
const whiteList = token.whitelistPools;
// For now just take USD from pool with greatest TVL.
// Need to update this to actually detect best rate based on liquidity distribution.
let largestLiquidityETH = new Decimal(0);
let priceSoFar = new Decimal(0);
let largestLiquidityETH = new GraphDecimal(0);
let priceSoFar = new GraphDecimal(0);
for (let i = 0; i < whiteList.length; ++i) {
const poolAddress = whiteList[i].id;
@ -139,12 +140,12 @@ export const findEthPerToken = async (db: Database, dbTx: QueryRunner, token: To
export const getTrackedAmountUSD = async (
db: Database,
dbTx: QueryRunner,
tokenAmount0: Decimal,
tokenAmount0: GraphDecimal,
token0: Token,
tokenAmount1: Decimal,
tokenAmount1: GraphDecimal,
token1: Token,
isDemo: boolean
): Promise<Decimal> => {
): Promise<GraphDecimal> => {
const bundle = await db.getBundle(dbTx, { id: '1' });
assert(bundle);
const price0USD = token0.derivedETH.times(bundle.ethPriceUSD);
@ -158,14 +159,14 @@ export const getTrackedAmountUSD = async (
// Take double value of the whitelisted token amount.
if (WHITELIST_TOKENS.includes(token0.id) && !WHITELIST_TOKENS.includes(token1.id)) {
return tokenAmount0.times(price0USD).times(new Decimal('2'));
return tokenAmount0.times(price0USD).times(new GraphDecimal('2'));
}
// Take double value of the whitelisted token amount.
if (!WHITELIST_TOKENS.includes(token0.id) && WHITELIST_TOKENS.includes(token1.id)) {
return tokenAmount1.times(price1USD).times(new Decimal('2'));
return tokenAmount1.times(price1USD).times(new GraphDecimal('2'));
}
// Neither token is on white list, tracked amount is 0.
return new Decimal(0);
return new GraphDecimal(0);
};

View File

@ -2,9 +2,10 @@
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
import { QueryRunner } from 'typeorm';
import { GraphDecimal } from '@vulcanize/util';
import { Pool } from '../entity/Pool';
import { Database } from '../database';
import { bigDecimalExponated, safeDiv } from '.';
@ -19,10 +20,10 @@ export const createTick = async (db: Database, dbTx: QueryRunner, tickId: string
tick.poolAddress = pool.id;
// 1.0001^tick is token1/token0.
const price0 = bigDecimalExponated(new Decimal('1.0001'), tickIdx);
const price0 = bigDecimalExponated(new GraphDecimal('1.0001'), tickIdx);
tick.price0 = price0;
tick.price1 = safeDiv(new Decimal(1), price0);
tick.price1 = safeDiv(new GraphDecimal(1), price0);
return db.saveTick(dbTx, tick, block);
};

View File

@ -4,10 +4,9 @@
import { expect } from 'chai';
import { ethers } from 'ethers';
import Decimal from 'decimal.js';
import _ from 'lodash';
import { OrderDirection } from '@vulcanize/util';
import { OrderDirection, GraphDecimal } from '@vulcanize/util';
import { insertNDummyBlocks } from '@vulcanize/util/test';
import { Database } from '../src/database';
@ -102,7 +101,7 @@ export const checkTokenHourData = async (client: Client, tokenAddress: string):
const hourStartUnix = hourIndex * 3600;
const tokenData = await client.getToken(tokenAddress);
const bundles = await client.getBundles(1);
const tokenPrice = new Decimal(tokenData.token.derivedETH).times(bundles[0].ethPriceUSD);
const tokenPrice = new GraphDecimal(tokenData.token.derivedETH).times(bundles[0].ethPriceUSD);
expect(tokenID).to.be.equal(tokenAddress);
expect(periodStartUnix).to.be.equal(hourStartUnix);
@ -203,7 +202,7 @@ export const insertDummyToken = async (db: Database, block: Block, token?: Token
token.symbol = 'TEST';
token.name = 'TestToken';
token.id = tokenAddress;
token.totalSupply = new Decimal(0);
token.totalSupply = BigInt(0);
token.decimals = BigInt(0);
}

View File

@ -12,3 +12,4 @@ export * from './src/events';
export * from './src/types';
export * from './src/indexer';
export * from './src/job-runner';
export * from './src/graph-decimal';

View File

@ -6,6 +6,7 @@
"dependencies": {
"@vulcanize/solidity-mapper": "^0.1.0",
"debug": "^4.3.1",
"decimal.js": "^10.3.1",
"ethers": "^5.2.0",
"fs-extra": "^10.0.0",
"pg-boss": "^6.1.0",
@ -15,9 +16,10 @@
"@types/fs-extra": "^9.0.11",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"@uniswap/v3-periphery": "1.0.0",
"@vulcanize/cache": "^0.1.0",
"@vulcanize/ipld-eth-client": "^0.1.0",
"@uniswap/v3-periphery": "1.0.0",
"apollo-server-express": "^2.25.0",
"eslint": "^7.27.0",
"eslint-config-semistandard": "^15.0.1",
"eslint-config-standard": "^16.0.3",
@ -26,11 +28,9 @@
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0",
"hardhat": "^2.3.0",
"typeorm": "^0.2.32",
"typeorm-naming-strategies": "^2.0.0",
"lodash": "^4.17.21",
"apollo-server-express": "^2.25.0",
"decimal.js": "^10.3.1"
"typeorm": "^0.2.32",
"typeorm-naming-strategies": "^2.0.0"
},
"scripts": {
"lint": "eslint .",

View File

@ -0,0 +1,210 @@
//
// Copyright 2021 Vulcanize, Inc.
//
import Decimal from 'decimal.js';
// Constant used in function digitsToString.
const LOG_BASE = 7;
// Customize Decimal according the limits of IEEE-754 decimal128.
// Reference: https://github.com/graphprotocol/graph-node/blob/v0.24.2/graph/src/data/store/scalar.rs#L42
const MIN_EXP = -6143;
const MAX_EXP = 6144;
const PRECISION = 34;
const _GraphDecimal = Decimal.clone({ precision: PRECISION });
// Wrapper class around Decimal.
export class GraphDecimal {
value: Decimal;
constructor (n: Decimal.Value) {
// Apply precision to the input value using toSignificantDigits().
this.value = new _GraphDecimal(n).toSignificantDigits();
}
toString (): string {
this._checkOutOfRange(this);
return this.value.toString();
}
toFixed (): string {
this._checkOutOfRange(this);
return this.value.toFixed();
}
plus (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.plus(param));
}
add (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.add(param));
}
minus (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.minus(param));
}
sub (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.sub(param));
}
times (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.times(param));
}
mul (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.mul(param));
}
dividedBy (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.dividedBy(param));
}
div (n: Decimal.Value | GraphDecimal): GraphDecimal {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return new GraphDecimal(this.value.div(param));
}
isZero (): boolean {
this._checkOutOfRange(this);
return this.value.isZero();
}
lessThan (n: Decimal.Value | GraphDecimal): boolean {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return this.value.lessThan(param);
}
lt (n: Decimal.Value | GraphDecimal): boolean {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return this.value.lt(param);
}
greaterThan (n: Decimal.Value | GraphDecimal): boolean {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return this.value.lessThan(param);
}
gt (n: Decimal.Value | GraphDecimal): boolean {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return this.value.lessThan(param);
}
comparedTo (n: Decimal.Value | GraphDecimal): number {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return this.value.comparedTo(param);
}
cmp (n: Decimal.Value | GraphDecimal): number {
this._checkOutOfRange(this);
const param = this._checkOutOfRange(n);
return this.value.cmp(param);
}
/**
* Function to check and throw an error if a given value has exponent out of the specified range (MIN_EXP to MAX_EXP).
* @param n A Decimal value to check the range for.
* @returns A Decimal.Value instance.
*/
private _checkOutOfRange (n: Decimal.Value | GraphDecimal): Decimal.Value {
let exp;
// Return n.value if n is an instance of GraphDecimal.
if (n instanceof GraphDecimal) {
n = n.value;
exp = _getGraphExp(n.d, n.e);
} else {
const decimal = new Decimal(n);
exp = _getGraphExp(decimal.d, decimal.e);
}
if (exp < MIN_EXP || exp > MAX_EXP) {
throw new Error(`Big decimal exponent '${exp}' is outside the '${MIN_EXP}' to '${MAX_EXP}' range`);
}
return n;
}
}
// Get exponent from Decimal d and e according to format in graph-node.
function _getGraphExp (d: any, e: number): number {
const digits = _digitsToString(d);
const exp = e - digits.length + 1;
return exp;
}
// Get digits in a string from an array of digit numbers (Decimal().d)
// https://github.com/MikeMcl/decimal.js/blob/master/decimal.mjs#L2516
function _digitsToString (d: any) {
let i, k, ws;
const indexOfLastWord = d.length - 1;
let str = '';
let w = d[0];
if (indexOfLastWord > 0) {
str += w;
for (i = 1; i < indexOfLastWord; i++) {
ws = d[i] + '';
k = LOG_BASE - ws.length;
if (k) str += _getZeroString(k);
str += ws;
}
w = d[i];
ws = w + '';
k = LOG_BASE - ws.length;
if (k) str += _getZeroString(k);
} else if (w === 0) {
return '0';
}
// Remove trailing zeros of last w.
for (; w % 10 === 0;) w /= 10;
return str + w;
}
function _getZeroString (k: any) {
let zs = '';
for (; k--;) zs += '0';
return zs;
}

View File

@ -3,15 +3,16 @@
//
import assert from 'assert';
import Decimal from 'decimal.js';
import { ValueTransformer } from 'typeorm';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { utils, getDefaultProvider, providers } from 'ethers';
import Decimal from 'decimal.js';
import { DEFAULT_CONFIG_PATH } from './constants';
import { Config } from './config';
import { JobQueue } from './job-queue';
import { GraphDecimal } from './graph-decimal';
/**
* Method to wait for specified time.
@ -19,6 +20,26 @@ import { JobQueue } from './job-queue';
*/
export const wait = async (time: number): Promise<void> => new Promise(resolve => setTimeout(resolve, time));
/**
* Transformer used by typeorm entity for GraphDecimal type fields.
*/
export const graphDecimalTransformer: ValueTransformer = {
to: (value?: GraphDecimal) => {
if (value) {
return value.toFixed();
}
return value;
},
from: (value?: string) => {
if (value) {
return new GraphDecimal(value);
}
return value;
}
};
/**
* Transformer used by typeorm entity for Decimal type fields.
*/