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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,14 +11,13 @@ import { providers, utils } from 'ethers';
import { Client as UniClient } from '@vulcanize/uni-watcher'; import { Client as UniClient } from '@vulcanize/uni-watcher';
import { Client as ERC20Client } from '@vulcanize/erc20-watcher'; import { Client as ERC20Client } from '@vulcanize/erc20-watcher';
import { EthClient } from '@vulcanize/ipld-eth-client'; 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 { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices, WHITELIST_TOKENS } from './utils/pricing';
import { updatePoolDayData, updatePoolHourData, updateTokenDayData, updateTokenHourData, updateUniswapDayData } from './utils/interval-updates'; import { updatePoolDayData, updatePoolHourData, updateTokenDayData, updateTokenHourData, updateUniswapDayData } from './utils/interval-updates';
import { Token } from './entity/Token'; import { Token } from './entity/Token';
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils'; import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
import { createTick } from './utils/tick'; import { createTick } from './utils/tick';
import Decimal from 'decimal.js';
import { Position } from './entity/Position'; import { Position } from './entity/Position';
import { Database } from './database'; import { Database } from './database';
import { Event } from './entity/Event'; import { Event } from './entity/Event';
@ -874,12 +873,12 @@ export class Indexer implements IndexerInterface {
let amount0Abs = amount0; let amount0Abs = amount0;
let amount1Abs = amount1; let amount1Abs = amount1;
if (amount0.lt(new Decimal(0))) { if (amount0.lt(new GraphDecimal(0))) {
amount0Abs = amount0.times(new Decimal('-1')); amount0Abs = amount0.times(new GraphDecimal('-1'));
} }
if (amount1.lt(new Decimal(0))) { if (amount1.lt(new GraphDecimal(0))) {
amount1Abs = amount1.times(new Decimal('-1')); amount1Abs = amount1.times(new GraphDecimal('-1'));
} }
const amount0ETH = amount0Abs.times(token0.derivedETH); 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. // 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 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 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 feesETH = amountTotalETHTracked.times(pool.feeTier.toString()).div(new GraphDecimal('1000000'));
const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toString()).div(new Decimal('1000000')); const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toString()).div(new GraphDecimal('1000000'));
// Global updates. // Global updates.
factory.txCount = BigInt(factory.txCount) + BigInt(1); factory.txCount = BigInt(factory.txCount) + BigInt(1);

View File

@ -5,8 +5,9 @@
import assert from 'assert'; import assert from 'assert';
import BigInt from 'apollo-type-bigint'; import BigInt from 'apollo-type-bigint';
import debug from 'debug'; 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 { Indexer } from './indexer';
import { Burn } from './entity/Burn'; import { Burn } from './entity/Burn';
@ -35,6 +36,19 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
return { return {
BigInt: new BigInt('bigInt'), 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: { ChainIndexingStatus: {
__resolveType: () => { __resolveType: () => {
return 'EthereumIndexingStatus'; return 'EthereumIndexingStatus';

View File

@ -2,16 +2,17 @@
// Copyright 2021 Vulcanize, Inc. // Copyright 2021 Vulcanize, Inc.
// //
import Decimal from 'decimal.js';
import { BigNumber } from 'ethers'; import { BigNumber } from 'ethers';
import { QueryRunner } from 'typeorm'; import { QueryRunner } from 'typeorm';
import { GraphDecimal } from '@vulcanize/util';
import { Transaction as TransactionEntity } from '../entity/Transaction'; import { Transaction as TransactionEntity } from '../entity/Transaction';
import { Database } from '../database'; import { Database } from '../database';
import { Block, Transaction } from '../events'; import { Block, Transaction } from '../events';
export const exponentToBigDecimal = (decimals: bigint): Decimal => { export const exponentToBigDecimal = (decimals: bigint): GraphDecimal => {
let bd = new Decimal(1); let bd = new GraphDecimal(1);
for (let i = 0; BigNumber.from(decimals).gte(i); i++) { for (let i = 0; BigNumber.from(decimals).gte(i); i++) {
bd = bd.times(10); bd = bd.times(10);
@ -20,12 +21,12 @@ export const exponentToBigDecimal = (decimals: bigint): Decimal => {
return bd; return bd;
}; };
export const convertTokenToDecimal = (tokenAmount: bigint, exchangeDecimals: bigint): Decimal => { export const convertTokenToDecimal = (tokenAmount: bigint, exchangeDecimals: bigint): GraphDecimal => {
if (exchangeDecimals === BigInt(0)) { 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> => { 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. // 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()) { if (amount1.isZero()) {
return new Decimal(0); return new GraphDecimal(0);
} else { } else {
return amount0.div(amount1); return amount0.div(amount1);
} }
}; };
export const bigDecimalExponated = (value: Decimal, power: bigint): Decimal => { export const bigDecimalExponated = (value: GraphDecimal, power: bigint): GraphDecimal => {
if (power === BigInt(0)) { if (power === BigInt(0)) {
return new Decimal(1); return new GraphDecimal(1);
} }
const negativePower = power > BigInt(0); 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(); const powerAbs = BigNumber.from(power).abs();
for (let i = BigNumber.from(1); i.lt(powerAbs); i = i.add(1)) { 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) { if (negativePower) {
result = safeDiv(new Decimal(1), result); result = safeDiv(new GraphDecimal(1), result);
} }
return result; return result;

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"@vulcanize/solidity-mapper": "^0.1.0", "@vulcanize/solidity-mapper": "^0.1.0",
"debug": "^4.3.1", "debug": "^4.3.1",
"decimal.js": "^10.3.1",
"ethers": "^5.2.0", "ethers": "^5.2.0",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"pg-boss": "^6.1.0", "pg-boss": "^6.1.0",
@ -15,9 +16,10 @@
"@types/fs-extra": "^9.0.11", "@types/fs-extra": "^9.0.11",
"@typescript-eslint/eslint-plugin": "^4.25.0", "@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0", "@typescript-eslint/parser": "^4.25.0",
"@uniswap/v3-periphery": "1.0.0",
"@vulcanize/cache": "^0.1.0", "@vulcanize/cache": "^0.1.0",
"@vulcanize/ipld-eth-client": "^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": "^7.27.0",
"eslint-config-semistandard": "^15.0.1", "eslint-config-semistandard": "^15.0.1",
"eslint-config-standard": "^16.0.3", "eslint-config-standard": "^16.0.3",
@ -26,11 +28,9 @@
"eslint-plugin-promise": "^5.1.0", "eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0", "eslint-plugin-standard": "^5.0.0",
"hardhat": "^2.3.0", "hardhat": "^2.3.0",
"typeorm": "^0.2.32",
"typeorm-naming-strategies": "^2.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"apollo-server-express": "^2.25.0", "typeorm": "^0.2.32",
"decimal.js": "^10.3.1" "typeorm-naming-strategies": "^2.0.0"
}, },
"scripts": { "scripts": {
"lint": "eslint .", "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 assert from 'assert';
import Decimal from 'decimal.js';
import { ValueTransformer } from 'typeorm'; import { ValueTransformer } from 'typeorm';
import yargs from 'yargs'; import yargs from 'yargs';
import { hideBin } from 'yargs/helpers'; import { hideBin } from 'yargs/helpers';
import { utils, getDefaultProvider, providers } from 'ethers'; import { utils, getDefaultProvider, providers } from 'ethers';
import Decimal from 'decimal.js';
import { DEFAULT_CONFIG_PATH } from './constants'; import { DEFAULT_CONFIG_PATH } from './constants';
import { Config } from './config'; import { Config } from './config';
import { JobQueue } from './job-queue'; import { JobQueue } from './job-queue';
import { GraphDecimal } from './graph-decimal';
/** /**
* Method to wait for specified time. * 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)); 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. * Transformer used by typeorm entity for Decimal type fields.
*/ */