Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate findAccountsByPublicKey endpoint to QueryAPI #685

Merged
merged 3 commits into from
Apr 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 44 additions & 9 deletions src/middleware/indexer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const { Pool } = require('pg');
const Cache = require('node-cache');
const bunyan = require('bunyan');
const fetch = require('node-fetch');

const {
BRIDGE_TOKEN_FACTORY_ACCOUNT_ID = 'factory.bridge.near',
GRAPHQL_URL = 'https://near-queryapi.api.pagoda.co/v1/graphql',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this handle testnet queries as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that's a good point, it does not. We may need to parameterise this in ECS, and use ExplorerDB in testnet, QueryAPI doesn't support testnet yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the heads up, I changed to have a fallback for non-mainnet environments or if no results from graphql

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you actually want a fallback for mainnet queries that return no results from graphql? If the DBs are actually going to be unavailable after April 30th then I imagine you'd want to know sooner than later that there's a disparity in what QueryAPI is returning. Also saves you the effort of needing to come back in < 2 weeks to remove the fallback 🙂

Are the testnet indexer DBs also going to be unavailable after April 30th? It's sounding like there will be an indeterminate gap in coverage for testnet. I don't know how severe the real impact of this would be, it's probably safe to assume there isn't a lot of account recovery, staking, etc. coming from testnet environments. It would almost certainly break parity for wallets supporting testnet but it might not be a dealbreaker in the short term.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good questions, yes we want to keep the fallback, April 30th is the desired deadline, but there are other endpoints that needs to be migrated before we turn off the DB instance.

Testnet indexer DBs will stay, there is no deadline or workstream yet to deprecate them.

NEAR_WALLET_ENV,
// INDEXER_DB_CONNECTION,
INDEXER_DB_REPLICAS,
Expand Down Expand Up @@ -119,15 +121,48 @@ const findAccountActivity = async (ctx) => {
const findAccountsByPublicKey = async (ctx) => {
try {
const { publicKey } = ctx.params;
const { rows } = await pool.query(`
SELECT DISTINCT account_id
FROM access_keys
JOIN accounts USING (account_id)
WHERE public_key = $1
AND accounts.deleted_by_receipt_id IS NULL
AND access_keys.deleted_by_receipt_id IS NULL
`, [publicKey]);
ctx.body = rows.map(({ account_id }) => account_id);
let accounts = [];

if (NEAR_WALLET_ENV.startsWith('mainnet')) {
const response = await fetch(GRAPHQL_URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-hasura-role': 'dataplatform_near'
},
body: JSON.stringify({
query: `
query access_keys_v1_by_public_key {
dataplatform_near_access_keys_v1_access_keys_v1(
where: {public_key: {_eq: "${publicKey}"}}
) {
account_id
}
}
`,
operationName: 'access_keys_v1_by_public_key'
}),
});

const respJson = await response.json();
const access_keys = respJson.data.dataplatform_near_access_keys_v1_access_keys_v1;
accounts = access_keys.map(item => item.account_id);
}

// fallback to indexer db for non-mainnet environments or if no results from graphql
if (accounts.length === 0) {
const { rows } = await pool.query(`
SELECT DISTINCT account_id
FROM access_keys
JOIN accounts USING (account_id)
WHERE public_key = $1
AND accounts.deleted_by_receipt_id IS NULL
AND access_keys.deleted_by_receipt_id IS NULL
`, [publicKey]);
accounts = rows.map(({ account_id }) => account_id);
}

ctx.body = accounts;
} catch (e) {
if (ctx.log && typeof ctx.log.error === 'function') {
ctx.log.error(e);
Expand Down
Loading