Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 38cac1c

Browse files
committed
integrate service with coingecko
1 parent 9d0acc5 commit 38cac1c

12 files changed

+108
-31
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
node_modules
2-
dist
2+
build
33
.env

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
"start:worker:dev": "nodemon ./src/worker.ts"
2020
},
2121
"dependencies": {
22+
"axios": "^0.21.1",
2223
"body-parser": "^1.19.0",
2324
"cors": "^2.8.5",
2425
"chalk": "^4.1.0",
2526
"decimal.js": "^10.2.1",
2627
"dotenv": "^8.2.0",
2728
"express": "^4.17.1",
2829
"knex": "^0.21.1",
30+
"moment": "^2.29.1",
2931
"objection": "^2.1.3",
3032
"pg": "^8.0.3"
3133
},

src/controllers/OrganizationController.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ export default {
2626
const organization = await Organization.findByAddress(request.params.address)
2727
if (!organization) throw HttpError.NOT_FOUND('Organization not found')
2828

29+
const balances = []
2930
const orgBalances = await OrganizationBalance.findByOrganization(organization)
30-
const balances = Promise.all(orgBalances.map(async ({ assetId, price, amount, value }) => {
31+
for (const { assetId, price, amount, value } of orgBalances) {
3132
const asset = await Asset.findById(assetId)
32-
return { asset: { address: asset?.address, symbol: asset?.symbol, decimals: asset?.decimals }, price, amount, value }
33-
}));
33+
balances.push({ asset: { address: asset?.address, symbol: asset?.symbol, decimals: asset?.decimals }, price, amount, value })
34+
}
3435

3536
const { createdAt, address, executor, value, syncedAt } = organization
3637
response.status(200).send({ createdAt, address, executor, value, syncedAt, balances })

src/database/migrations/20210414202011_create_organizations_table.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export async function up(knex: Knex): Promise<void> {
77
table.string('address').notNullable()
88
table.string('executor').notNullable()
99
table.dateTime('createdAt').notNullable()
10-
table.string('value').notNullable()
10+
table.double('value', 10).notNullable()
1111
table.dateTime('syncedAt')
1212
table.unique(['address'])
1313
})

src/database/migrations/20210414202254_create_assets_table.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export async function up(knex: Knex): Promise<void> {
66
table.increments('id')
77
table.string('address').notNullable()
88
table.string('symbol').notNullable()
9-
table.string('name').notNullable()
109
table.string('decimals').notNullable()
1110
table.dateTime('createdAt').defaultTo(knex.fn.now()).notNullable()
1211
table.unique(['address'])

src/database/migrations/20210414204239_create_organization_balance_table.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ export async function up(knex: Knex): Promise<void> {
1111
table.integer('organizationId').index()
1212
table.foreign('organizationId').references(`${Organization.tableName}.id`).onDelete('CASCADE')
1313
table.string('amount').notNullable()
14-
table.string('price')
15-
table.string('value')
14+
table.double('price', 10).notNullable()
15+
table.double('value', 10).notNullable()
1616
table.dateTime('createdAt').defaultTo(knex.fn.now()).notNullable()
1717
table.unique(['assetId', 'organizationId'])
1818
})

src/helpers/numbers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
import { Decimal } from 'decimal.js'
22

33
export const decimal = (x: string | number): Decimal => new Decimal(x)
4+
5+
export const fixed = (x: Decimal): number => Number(x.toFixed(10, Decimal.ROUND_DOWN))

src/models/Coingecko.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import axios from 'axios'
2+
import moment from 'moment'
3+
import { Decimal } from 'decimal.js'
4+
5+
import { decimal } from '../helpers/numbers'
6+
7+
const BASE_URL = 'https://api.coingecko.com/api/v3'
8+
9+
type Coins = { [key: string]: Coin }
10+
11+
type Coin = {
12+
id: string
13+
name: string
14+
symbol: string
15+
address: string
16+
}
17+
18+
class Coingecko {
19+
coins?: Coins
20+
21+
async getPrice(address: string, at: string): Promise<Decimal> {
22+
const coins = await this.all()
23+
const date = moment(at).format('DD-MM-YYYY')
24+
const coinId = coins[address.toLowerCase()].id
25+
const data = await this._get(`/coins/${coinId}/history?date=${date}&localization=false`)
26+
const price = data?.market_data?.current_price?.usd || 0
27+
return decimal(price)
28+
}
29+
30+
async all(): Promise<Coins> {
31+
if (this.coins == undefined) {
32+
this.coins = {}
33+
const coinsData: any[] = await this._get('coins/list?include_platform=true')
34+
coinsData
35+
.filter((coinData: any) => coinData?.platforms?.ethereum !== undefined)
36+
.forEach(({ id, name, symbol, platforms }: any) => {
37+
let address = platforms.ethereum;
38+
this.coins![address.toLowerCase()] = ({ id, name, symbol, address: address.toLowerCase() })
39+
})
40+
}
41+
return this.coins
42+
}
43+
44+
private async _get(path: string): Promise<any> {
45+
const response = await axios.get(`${BASE_URL}/${path}`);
46+
return response.data
47+
}
48+
}
49+
50+
export default new Coingecko()

src/models/Organization.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ export default class Organization extends BaseModel {
2020
id!: number
2121
address!: string
2222
executor!: string
23-
value!: string
23+
value!: number
2424
createdAt!: string
2525
syncedAt?: string
2626

2727
static create({ address, executor, createdAt }: { address: string, executor: string, createdAt: string }): Promise<Organization> {
28-
return this.query().insert({ address, executor, createdAt, value: '0' })
28+
return this.query().insert({ address, executor, createdAt, value: 0 })
2929
}
3030

3131
static async count(): Promise<number> {
3232
return this.query().resultSize()
3333
}
3434

3535
static async totalValue(): Promise<number> {
36-
const results = await this.query().select(raw('coalesce(sum(??), 0)', 'value').as('sum'))
36+
const results = await this.query().sum('value')
3737
// @ts-ignore
3838
return results[0].sum
3939
}
@@ -46,8 +46,8 @@ export default class Organization extends BaseModel {
4646
return this.query().findOne({ address })
4747
}
4848

49-
async update({ value }: { value: string }): Promise<void> {
50-
const syncedAt = new Date().getTime().toString()
49+
async update({ value }: { value: number }): Promise<void> {
50+
const syncedAt = new Date().toISOString()
5151
await this.$query().update({ value, syncedAt })
5252
}
5353
}

src/models/OrganizationBalance.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ export default class OrganizationBalance extends BaseModel {
2828
assetId!: number
2929
organizationId!: number
3030
amount!: string
31-
price!: string
32-
value!: string
31+
price!: number
32+
value!: number
3333
createdAt!: string
3434

35-
static create({ assetId, organizationId, amount, price, value }: { assetId: number, organizationId: number, amount: string, price: string, value: string }): Promise<OrganizationBalance> {
35+
static create({ assetId, organizationId, amount, price, value }: { assetId: number, organizationId: number, amount: string, price: number, value: number }): Promise<OrganizationBalance> {
3636
return this.query().insert({ assetId, organizationId, amount, price, value })
3737
}
3838

0 commit comments

Comments
 (0)