Skip to content

Commit

Permalink
replace the node's graphql api with direct db queries
Browse files Browse the repository at this point in the history
  • Loading branch information
ecioppettini committed Apr 13, 2024
1 parent 4904081 commit 934bf03
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 73 deletions.
15 changes: 14 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/engine/paima-funnel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"dependencies": {
"assert-never": "^1.2.1",
"@dcspark/carp-client": "^3.1.0",
"@dcspark/cardano-multiplatform-lib-nodejs": "5.2.0"
"@dcspark/cardano-multiplatform-lib-nodejs": "5.2.0",
"postgres": "^3.3.5"
}
}
9 changes: 8 additions & 1 deletion packages/engine/paima-funnel/src/funnels/FunnelCache.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ChainData } from '@paima/sm';
import postgres from 'postgres';

export interface FunnelCacheEntry {
/**
Expand Down Expand Up @@ -184,6 +185,7 @@ export type MinaFunnelCacheEntryState = {
startingSlotTimestamp: number;
lastPoint: { timestamp: number } | undefined;
genesisTime: number;
pg: postgres.Sql;
cursors:
| {
[cdeId: number]: { cursor: string; finished: boolean };
Expand All @@ -195,12 +197,17 @@ export class MinaFunnelCacheEntry implements FunnelCacheEntry {
private state: MinaFunnelCacheEntryState | null = null;
public static readonly SYMBOL = Symbol('MinaFunnelStartingSlot');

public updateStartingSlot(startingSlotTimestamp: number, genesisTime: number): void {
public updateStartingSlot(
startingSlotTimestamp: number,
genesisTime: number,
pg: postgres.Sql
): void {
this.state = {
startingSlotTimestamp,
genesisTime,
lastPoint: this.state?.lastPoint,
cursors: this.state?.cursors,
pg,
};
}

Expand Down
85 changes: 16 additions & 69 deletions packages/engine/paima-funnel/src/funnels/mina/funnel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,19 @@ import { getPaginationCursors } from '@paima/db';
import { getActionCdeData, getEventCdeData } from '../../cde/minaGeneric.js';
import type { MinaConfig } from '@paima/utils';
import { MinaFunnelCacheEntry } from '../FunnelCache.js';
import postgres from 'postgres';

async function getGenesisTime(graphql: string): Promise<number> {
const genesisTime = (await fetch(graphql, {
method: 'POST',

headers: {
'Content-Type': 'application/json',
},

body: JSON.stringify({
query: `
{
genesisBlock {
protocolState {
blockchainState {
utcDate
}
}
}
}
`,
}),
})
.then(res => res.json())
.then(res => res.data.genesisBlock.protocolState.blockchainState.utcDate)) as string;
async function getGenesisTime(pg: postgres.Sql): Promise<number> {
const row = await pg`select timestamp from blocks where height = 1;`;

return Number.parseInt(genesisTime, 10);
return Number.parseInt(row[0]['timestamp'], 10);
}

async function findMinaConfirmedSlot(pg: postgres.Sql): Promise<number> {
const row =
await pg`select global_slot_since_genesis from blocks where chain_status = 'canonical' order by height desc limit 1;`;

return Number.parseInt(row[0]['global_slot_since_genesis'], 10);
}

function slotToMinaTimestamp(slot: number, genesisTime: number, slotDuration: number): number {
Expand All @@ -60,44 +46,6 @@ function baseChainTimestampToMina(
return Math.max(baseChainTimestamp * 1000 - slotDuration * 1000 * confirmationDepth, 0);
}

// TODO: maybe using the node's rpc here it's not really safe? if it's out of
// sync with the archive db we could end up skipping events
// it would be better to have an endpoint for this on the archive api
// either that, or the archive node api should take a block hash, and if it's
// not there it should return an error.
async function findMinaConfirmedSlot(graphql: string, confirmationDepth: number): Promise<number> {
const body = JSON.stringify({
query: `
{
bestChain(maxLength: ${confirmationDepth}) {
stateHash
protocolState {
consensusState {
blockHeight
slotSinceGenesis
}
previousStateHash
}
}
}
`,
});

const confirmedSlot = await fetch(graphql, {
method: 'POST',

headers: {
'Content-Type': 'application/json',
},

body,
})
.then(res => res.json())
.then(res => res.data.bestChain[0].protocolState.consensusState.slotSinceGenesis);

return Number.parseInt(confirmedSlot, 10);
}

export class MinaFunnel extends BaseFunnel implements ChainFunnel {
config: MinaConfig;
chainName: string;
Expand Down Expand Up @@ -127,10 +75,7 @@ export class MinaFunnel extends BaseFunnel implements ChainFunnel {

let cachedState = this.cache.getState();

const confirmedSlot = await findMinaConfirmedSlot(
this.config.graphql,
this.config.confirmationDepth
);
const confirmedSlot = await findMinaConfirmedSlot(cachedState.pg);

const confirmedTimestamp = slotToMinaTimestamp(
confirmedSlot,
Expand Down Expand Up @@ -391,7 +336,9 @@ export class MinaFunnel extends BaseFunnel implements ChainFunnel {
const newEntry = new MinaFunnelCacheEntry();
sharedData.cacheManager.cacheEntries[MinaFunnelCacheEntry.SYMBOL] = newEntry;

const genesisTime = await getGenesisTime(config.graphql);
const pg = postgres(config.archiveConnectionString);

const genesisTime = await getGenesisTime(pg);

const startingBlockTimestamp = (await sharedData.web3.eth.getBlock(startingBlockHeight))
.timestamp as number;
Expand All @@ -408,7 +355,7 @@ export class MinaFunnel extends BaseFunnel implements ChainFunnel {

const slotAsMinaTimestamp = slotToMinaTimestamp(slot, genesisTime, config.slotDuration);

newEntry.updateStartingSlot(slotAsMinaTimestamp, genesisTime);
newEntry.updateStartingSlot(slotAsMinaTimestamp, genesisTime, pg);

const cursors = await getPaginationCursors.run(undefined, dbTx);

Expand Down
2 changes: 1 addition & 1 deletion packages/paima-sdk/paima-utils/src/config/loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export const CardanoConfigSchema = Type.Object({
export type CardanoConfig = Static<typeof CardanoConfigSchema>;

export const MinaConfigSchema = Type.Object({
archiveConnectionString: Type.String(),
archive: Type.String(),
graphql: Type.String(),
// k
confirmationDepth: Type.Number(),
paginationLimit: Type.Number({ default: 50 }),
Expand Down

0 comments on commit 934bf03

Please sign in to comment.