Skip to content

Commit

Permalink
feature: Asset.tokenMints and Asset.tokenMints_aggregate
Browse files Browse the repository at this point in the history
- Renames the Mint SQL VIEW to TokenMint
- Renames the Token SQL VIEW to TokenInOutput,
however there are no changes to the exposed GraphQL model,
with TransactionOutput.tokens.
- Uses the ma_tx_mint rather than ma_tx_out table for building
the Asset table on startup
- Also adds missing field params to Transaction.mint
Closes #456
  • Loading branch information
rhyslbw committed Mar 23, 2021
1 parent 4bf4866 commit 687abcd
Show file tree
Hide file tree
Showing 25 changed files with 276 additions and 198 deletions.
89 changes: 50 additions & 39 deletions packages/api-cardano-db-hasura/hasura/project/metadata/tables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
select: assets
update: update_assets
custom_column_names: {}
array_relationships:
- name: tokenMints
using:
manual_configuration:
remote_table:
schema: public
name: TokenMint
column_mapping:
assetId: assetId
insert_permissions:
- role: cardano-graphql
permission:
Expand Down Expand Up @@ -284,35 +293,6 @@
filter: {}
limit: 2500
allow_aggregations: true
- table:
schema: public
name: Mint
object_relationships:
- name: asset
using:
manual_configuration:
remote_table:
schema: public
name: Asset
column_mapping:
assetId: assetId
- name: transaction
using:
manual_configuration:
remote_table:
schema: public
name: Transaction
column_mapping:
tx_id: id
select_permissions:
- role: cardano-graphql
permission:
columns:
- assetId
- quantity
filter: {}
limit: 2500
allow_aggregations: true
- table:
schema: public
name: Reward
Expand Down Expand Up @@ -571,12 +551,7 @@
allow_aggregations: true
- table:
schema: public
name: Token
configuration:
custom_root_fields:
select_aggregate: tokens_aggregate
select: tokens
custom_column_names: {}
name: TokenInOutput
object_relationships:
- name: asset
using:
Expand Down Expand Up @@ -605,6 +580,42 @@
filter: {}
limit: 2500
allow_aggregations: true
- table:
schema: public
name: TokenMint
configuration:
custom_root_fields:
select_aggregate: tokenMints_aggregate
select: tokenMints
custom_column_names: {}
object_relationships:
- name: asset
using:
manual_configuration:
remote_table:
schema: public
name: Asset
column_mapping:
assetId: assetId
- name: transaction
using:
manual_configuration:
remote_table:
schema: public
name: Transaction
column_mapping:
tx_id: id
select_permissions:
- role: cardano-graphql
permission:
columns:
- assetId
- assetName
- policyId
- quantity
filter: {}
limit: 2500
allow_aggregations: true
- table:
schema: public
name: Transaction
Expand Down Expand Up @@ -644,7 +655,7 @@
manual_configuration:
remote_table:
schema: public
name: Mint
name: TokenMint
column_mapping:
id: tx_id
- name: outputs
Expand Down Expand Up @@ -706,7 +717,7 @@
manual_configuration:
remote_table:
schema: public
name: Token
name: TokenInOutput
column_mapping:
source_tx_out_id: tx_out_id
select_permissions:
Expand Down Expand Up @@ -739,7 +750,7 @@
manual_configuration:
remote_table:
schema: public
name: Token
name: TokenInOutput
column_mapping:
id: tx_out_id
select_permissions:
Expand Down Expand Up @@ -776,7 +787,7 @@
manual_configuration:
remote_table:
schema: public
name: Token
name: TokenInOutput
column_mapping:
id: tx_out_id
select_permissions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ DROP VIEW IF EXISTS
"Cardano",
"Delegation",
"Epoch",
"Mint",
"ShelleyEpochProtocolParams",
"Reward",
"SlotLeader",
"StakeDeregistration",
"StakePool",
"StakeRegistration",
"StakePoolRetirement",
"Token",
"TokenMint",
"TokenInOutput",
"Transaction",
"TransactionInput",
"TransactionOutput",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS "Asset"
policy as "policyId",
CAST(NULL AS TEXT) AS "ticker",
CAST(NULL AS TEXT) AS "url"
FROM ma_tx_out;
FROM ma_tx_mint;

ALTER TABLE "Asset" ADD PRIMARY KEY ("assetId");

Expand Down Expand Up @@ -49,7 +49,7 @@ CREATE OR REPLACE VIEW "Cardano" AS
WHERE (block.block_no IS NOT NULL)
ORDER BY block.block_no DESC
LIMIT 1;

CREATE VIEW "Delegation" AS
SELECT
delegation.id AS "id",
Expand Down Expand Up @@ -193,18 +193,20 @@ FROM epoch_stake
JOIN pool_hash
ON pool_hash.id = epoch_stake.pool_id;

CREATE VIEW "Mint" AS
CREATE VIEW "TokenMint" AS
SELECT
CONCAT(RIGHT(CONCAT(E'\\', policy), -3), RIGHT(CONCAT(E'\\', name), -3)) as "assetId",
RIGHT(CONCAT(E'\\', name), -3) AS "assetName",
policy AS "policyId",
quantity,
tx_id
FROM ma_tx_mint;

CREATE VIEW "Token" AS
CREATE VIEW "TokenInOutput" AS
SELECT
CONCAT(RIGHT(CONCAT(E'\\',policy), -3), RIGHT(CONCAT(E'\\',name), -3)) as "assetId",
RIGHT(CONCAT(E'\\', name), -3) as "assetName",
policy as "policyId",
policy AS "policyId",
quantity,
tx_out_id
FROM ma_tx_out;
Expand Down
69 changes: 68 additions & 1 deletion packages/api-cardano-db-hasura/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,18 @@ type Asset {
fingerprint: AssetFingerprint
logo: String
metadataHash: String
tokenMints (
limit: Int
order_by: [TokenMint_order_by!]
offset: Int
where: TokenMint_bool_exp
): [TokenMint]!
tokenMints_aggregate (
limit: Int
order_by: [TokenMint_order_by!]
offset: Int
where: TokenMint_bool_exp
): TokenMint_aggregate!
name: String
policyId: Hash28Hex!
ticker: String
Expand Down Expand Up @@ -815,6 +827,56 @@ type Token_sum_fields {
quantity: String
}

type TokenMint {
asset: Asset!
quantity: String!
transaction: Transaction!
}

input TokenMint_order_by {
asset: Asset_order_by
quantity: order_by
transaction: Transaction_order_by
}

input TokenMint_bool_exp {
_and: [TokenMint_bool_exp]
_not: TokenMint_bool_exp
_or: [TokenMint_bool_exp]
asset: Asset_bool_exp
quantity: text_comparison_exp
transaction: Transaction_bool_exp
}

type TokenMint_aggregate {
aggregate: TokenMint_aggregate_fields
nodes: [TokenMint!]!
}

type TokenMint_aggregate_fields {
avg: TokenMint_avg_fields!
count: String!
max: TokenMint_max_fields!
min: TokenMint_min_fields!
sum: TokenMint_sum_fields!
}

type TokenMint_avg_fields {
quantity: String
}

type TokenMint_max_fields {
quantity: String
}

type TokenMint_min_fields {
quantity: String
}

type TokenMint_sum_fields {
quantity: String
}

type Transaction {
block: Block
blockIndex: Int!
Expand All @@ -836,7 +898,12 @@ type Transaction {
invalidBefore: String
invalidHereafter: String
metadata: [TransactionMetadata]
mint: [Token!]!
mint(
limit: Int
order_by: [Token_order_by]
offset: Int
where: Token_bool_exp
): [Token!]!
mint_aggregate(
limit: Int
order_by: [Token_order_by]
Expand Down
18 changes: 9 additions & 9 deletions packages/api-cardano-db-hasura/src/DataSyncController.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import axios, { AxiosInstance } from 'axios'
import { chunkArray, DataFetcher } from '@cardano-graphql/util'
import AssetFingerprint from '@emurgo/cip14-js'
import { Asset } from './graphql_types'
import { HostDoesNotExist } from './errors'
import hash from 'object-hash'
import { dummyLogger, Logger } from 'ts-log'
import { Db } from './Db'
import { HasuraClient } from './HasuraClient'
import { AssetWithoutTokens } from './typeAliases'

export interface Signature {
signature: string
publicKey: string
}

export const assetFingerprint = (asset: Pick<Asset, 'assetName' | 'policyId'>) =>
export const assetFingerprint = (asset: Pick<AssetWithoutTokens, 'assetName' | 'policyId'>) =>
new AssetFingerprint(
Buffer.from(asset.policyId, 'hex'),
asset.assetName !== '' ? Buffer.from(asset.assetName, 'hex') : undefined)
Expand Down Expand Up @@ -130,7 +130,7 @@ export class DataSyncController {
const batchSize = 500
const distinctAssetsInTokensCount = await this.hasuraClient.distinctAssetsInTokensCount()
this.logger.debug(
'distinct assets in tokens count',
'Distinct assets in tokens count',
{ module: 'DataSyncController', value: distinctAssetsInTokensCount }
)
const batchQty = Math.ceil(distinctAssetsInTokensCount / batchSize)
Expand All @@ -142,7 +142,7 @@ export class DataSyncController {
const assetsAlreadyInDb =
await this.hasuraClient.getAssetsById(assetsInBatch.map(asset => asset.assetId))
this.logger.debug(
'asset IDs from tokens',
'Assets from tokens',
{
module: 'DataSyncController',
value: { batch: i, qty: assetsInBatch.length, existing: assetsAlreadyInDb.length }
Expand Down Expand Up @@ -170,13 +170,13 @@ export class DataSyncController {
}
return totalCount
},
60 * 1000,
120 * 1000,
this.logger
)
}

private async fetchAndApplyMetadata (assets: Asset[]) {
const assetBatches = chunkArray<Asset>(assets, 250)
private async fetchAndApplyMetadata (assets: AssetWithoutTokens[]) {
const assetBatches = chunkArray<AssetWithoutTokens>(assets, 250)
for (const batch of assetBatches) {
const newMetadata = await this.getAssetMetadata(batch)
const assetsWithMetadata = newMetadata
Expand Down Expand Up @@ -208,7 +208,7 @@ export class DataSyncController {
}
}

private async getAssetMetadata (assets: Asset[]): Promise<AssetMetadata[]> {
private async getAssetMetadata (assets: AssetWithoutTokens[]): Promise<AssetMetadata[]> {
try {
const response = await this.axiosClient.post('metadata/query', {
subjects: assets.map(asset => asset.assetId),
Expand All @@ -231,7 +231,7 @@ export class DataSyncController {
}

private async ensureAssetFingerprints (): Promise<void> {
const runBatch = async (assets: Pick<Asset, 'assetId' | 'assetName' | 'policyId'>[]) => {
const runBatch = async (assets: Pick<AssetWithoutTokens, 'assetId' | 'assetName' | 'policyId'>[]) => {
await this.hasuraClient.addAssetFingerprints(
assets.map((asset) => ({ assetId: asset.assetId, fingerprint: assetFingerprint(asset) }))
)
Expand Down
Loading

0 comments on commit 687abcd

Please sign in to comment.