Skip to content

Commit

Permalink
GQL API to query IPLDBlock by CID
Browse files Browse the repository at this point in the history
  • Loading branch information
prathamesh0 committed Oct 7, 2021
1 parent 7e63117 commit 04ed305
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 39 deletions.
26 changes: 26 additions & 0 deletions packages/codegen/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ export class Schema {
// Add a mutation for watching a contract.
this._addWatchContractMutation();

this._addIPLDType();
this._addIPLDBlockQuery();

return this._composer.buildSchema();
}

Expand Down Expand Up @@ -235,6 +238,29 @@ export class Schema {
});
}

_addIPLDType (): void {
this._composer.createObjectTC({
name: 'ResultIPLDBlock',
fields: {
block: () => this._composer.getOTC('Block').NonNull,
contractAddress: 'String!',
cid: 'String!',
data: 'String!'
}
});
}

_addIPLDBlockQuery (): void {
this._composer.Query.addFields({
ipldBlock: {
type: this._composer.getOTC('ResultIPLDBlock'),
args: {
cid: 'String!'
}
}
});
}

/**
* Adds an event subscription to the schema.
*/
Expand Down
72 changes: 36 additions & 36 deletions packages/codegen/src/templates/database-template.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ export class Database {
}

{{/each}}
async getIPLDBlock (block: BlockProgress, contractAddress: string): Promise<IPLDBlock | undefined> {
async getIPLDBlocks (where: FindConditions<IPLDBlock>): Promise<IPLDBlock[]> {
const repo = this._conn.getRepository(IPLDBlock);
return repo.findOne({ block, contractAddress });
return repo.find({ where, relations: ['block'] });
}

async saveOrUpdateIPLDBlock (ipldBlock: IPLDBlock): Promise<IPLDBlock> {
Expand All @@ -91,46 +91,47 @@ export class Database {

async getPrevIPLDBlock (queryRunner: QueryRunner, blockHash: string, contractAddress: string): Promise<IPLDBlock | undefined> {
const repo = this._conn.getRepository(IPLDBlock);

const heirerchicalQuery = `
WITH RECURSIVE cte_query AS
(
SELECT
b.block_hash,
b.block_number,
b.parent_hash,
1 as depth,
i.id
FROM
block_progress b
LEFT JOIN
ipld_block i ON i.block_id = b.id
WHERE
b.block_hash = $1
UNION ALL
WITH RECURSIVE cte_query AS
(
SELECT
b.block_hash,
b.block_number,
b.parent_hash,
c.depth + 1,
1 as depth,
i.id
FROM
block_progress b
LEFT JOIN
ipld_block i
ON i.block_id = b.id
AND i.contract_address = $2
INNER JOIN
cte_query c ON c.parent_hash = b.block_hash
WHERE
c.id IS NULL AND c.depth < $3
)
SELECT
block_number, id
FROM
cte_query
ORDER BY block_number ASC
LIMIT 1;
`;
ipld_block i ON i.block_id = b.id
WHERE
b.block_hash = $1
UNION ALL
SELECT
b.block_hash,
b.block_number,
b.parent_hash,
c.depth + 1,
i.id
FROM
block_progress b
LEFT JOIN
ipld_block i
ON i.block_id = b.id
AND i.contract_address = $2
INNER JOIN
cte_query c ON c.parent_hash = b.block_hash
WHERE
c.id IS NULL AND c.depth < $3
)
SELECT
block_number, id
FROM
cte_query
ORDER BY block_number ASC
LIMIT 1;
`;

// Fetching block and id for previous IPLDBlock in frothy region.
const [{ block_number: blockNumber, id }] = await queryRunner.query(heirerchicalQuery, [blockHash, contractAddress, MAX_REORG_DEPTH]);
Expand All @@ -142,16 +143,15 @@ export class Database {
// If IPLDBlock not found in frothy region get latest IPLDBlock in the pruned region.
// Filter out IPLDBlocks from pruned blocks.
const canonicalBlockNumber = blockNumber + 1;
const ipldBlockInPrunedRegion:any = await repo.createQueryBuilder('ipld_block')

result = await repo.createQueryBuilder('ipld_block')
.innerJoinAndSelect('block_progress', 'block', 'block.id = ipld_block.block_id')
.where('block.is_pruned = false')
.andWhere('ipld_block.contract_address = :contractAddress', { contractAddress })
.andWhere('block.block_number <= :canonicalBlockNumber', { canonicalBlockNumber })
.orderBy('block.block_number', 'DESC')
.limit(1)
.getOne();

result = ipldBlockInPrunedRegion;
}

return result;
Expand Down
4 changes: 3 additions & 1 deletion packages/codegen/src/templates/hooks-template.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ export async function handleBlock (indexer: Indexer, jobData: any): Promise<void
'/': (await indexer.getPrevIPLDBlock(blockHash, contractAddress))?.cid || null
},
ethBlock: {
cid: block.cid,
cid: {
'/': block.cid
},
num: block.blockNumber
}
};
Expand Down
48 changes: 46 additions & 2 deletions packages/codegen/src/templates/indexer-template.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,20 @@ export type ResultEvent = {
event: any;

proof: string;
}
};

export type ResultIPLDBlock = {
block: {
cid: string;
hash: string;
number: number;
timestamp: number;
parentHash: string;
};
contractAddress: string;
cid: string;
data: string;
};

export class Indexer {
_db: Database
Expand Down Expand Up @@ -118,6 +131,23 @@ export class Indexer {
};
}

getResultIPLDBlock (ipldBlock: IPLDBlock): ResultIPLDBlock {
const block = ipldBlock.block;

return {
block: {
cid: block.cid,
hash: block.blockHash,
number: block.blockNumber,
timestamp: block.blockTimestamp,
parentHash: block.parentHash
},
contractAddress: ipldBlock.contractAddress,
cid: ipldBlock.cid,
data: ipldBlock.data
};
}

{{#each queries as | query |}}
async {{query.name}} (blockHash: string, contractAddress: string
{{~#each query.params}}, {{this.name~}}: {{this.type~}} {{/each}}): Promise<ValueResult> {
Expand Down Expand Up @@ -173,7 +203,21 @@ export class Indexer {

{{/each}}
async getIPLDBlock (block: BlockProgress, contractAddress: string): Promise<IPLDBlock | undefined> {
return this._db.getIPLDBlock(block, contractAddress);
const ipldBlocks = await this._db.getIPLDBlocks({ block, contractAddress });

// There can be only one IPLDBlock for a { block, contractAddress } combination.
assert(ipldBlocks.length <= 1);

return ipldBlocks[0];
}

async getIPLDBlockByCid (cid: string): Promise<IPLDBlock | undefined> {
const ipldBlocks = await this._db.getIPLDBlocks({ cid });

// There can be only one IPLDBlock with a particular cid.
assert(ipldBlocks.length <= 1);

return ipldBlocks[0];
}

async saveOrUpdateIPLDBlock (ipldBlock: IPLDBlock): Promise<IPLDBlock> {
Expand Down
8 changes: 8 additions & 0 deletions packages/codegen/src/templates/resolvers-template.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch

const events = await indexer.getEventsInRange(fromBlockNumber, toBlockNumber);
return events.map(event => indexer.getResultEvent(event));
},

ipldBlock: async (_: any, { cid }: { cid: string }) => {
log('ipldBlock', cid);

const ipldBlock = await indexer.getIPLDBlockByCid(cid);

return ipldBlock ? indexer.getResultIPLDBlock(ipldBlock) : undefined;
}
}
};
Expand Down
1 change: 1 addition & 0 deletions packages/util/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ export class Database {
// If entity not found in frothy region get latest entity in the pruned region.
// Filter out entities from pruned blocks.
const canonicalBlockNumber = blockNumber + 1;

const entityInPrunedRegion:any = await repo.createQueryBuilder('entity')
.innerJoinAndSelect('block_progress', 'block', 'block.block_hash = entity.block_hash')
.where('block.is_pruned = false')
Expand Down

0 comments on commit 04ed305

Please sign in to comment.