From 2e0482da2953d24fbab25a8f62d2995decc7ed94 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:20:54 +0700 Subject: [PATCH 01/11] fix: `/api/spaces/ID` should pull data from DB instead of cache (#725) * fix: /api/spaces/ID should pull data from DB * Update src/helpers/spaces.ts --------- Co-authored-by: Chaitanya --- package.json | 2 +- src/api.ts | 17 +++++--- src/helpers/spaces.ts | 18 +++++++++ test/e2e/space.test.ts | 55 +++++++++++++++++++++++++- test/fixtures/spaces.ts | 13 ++++++ yarn.lock | 87 ++--------------------------------------- 6 files changed, 100 insertions(+), 92 deletions(-) create mode 100644 test/fixtures/spaces.ts diff --git a/package.json b/package.json index 30aa5459..9bc1ca58 100644 --- a/package.json +++ b/package.json @@ -55,10 +55,10 @@ "eslint": "^8.28.0", "jest": "^29.6.1", "jest-environment-node-single-context": "^29.1.0", + "node-fetch": "^2.7", "nodemon": "^2.0.19", "prettier": "^3.0.3", "start-server-and-test": "^2.0.0", - "supertest": "^6.3.3", "ts-jest": "^29.1.1" }, "engines": { diff --git a/src/api.ts b/src/api.ts index da6b2d1c..aeb30df6 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,5 +1,6 @@ import express from 'express'; -import { spaces } from './helpers/spaces'; +import { capture } from '@snapshot-labs/snapshot-sentry'; +import { getSpace } from './helpers/spaces'; import { name, version } from '../package.json'; import { sendError } from './helpers/utils'; @@ -25,14 +26,18 @@ router.get('/', (req, res) => { }); }); -router.get('/spaces/:key', (req, res) => { +router.get('/spaces/:key', async (req, res) => { const { key } = req.params; - if (!spaces[key]) { - return sendError(res, 'space not found', 404); + try { + return res.json(await getSpace(key)); + } catch (e: any) { + if (e.message !== 'NOT_FOUND') { + capture(e); + return sendError(res, 'server_error', 500); + } + return sendError(res, 'not_found', 404); } - - return res.json(spaces[key]); }); router.get('/spaces/:key/poke', async (req, res) => { diff --git a/src/helpers/spaces.ts b/src/helpers/spaces.ts index b917e132..40fd3c2e 100644 --- a/src/helpers/spaces.ts +++ b/src/helpers/spaces.ts @@ -158,6 +158,24 @@ async function loadSpacesMetrics() { mapSpaces(); } +export async function getSpace(id: string) { + const query = ` + SELECT settings, flagged, verified + FROM spaces + WHERE deleted = 0 AND id = ? + LIMIT 1`; + + const [space] = await db.queryAsync(query, [id]); + + if (!space) return Promise.reject(new Error('NOT_FOUND')); + + return { + ...JSON.parse(space.settings), + flagged: space.flagged === 1, + verified: space.verified === 1 + }; +} + async function run() { try { await loadSpaces(); diff --git a/test/e2e/space.test.ts b/test/e2e/space.test.ts index 32255348..1747d41f 100644 --- a/test/e2e/space.test.ts +++ b/test/e2e/space.test.ts @@ -1,9 +1,60 @@ +import fetch from 'node-fetch'; +import db from '../../src/helpers/mysql'; +import fixtures from '../fixtures/spaces'; + +const HOST = `http://localhost:${process.env.PORT || 3030}`; + describe('GET /api/space/:key', () => { + beforeAll(async () => { + await db.queryAsync('DELETE from spaces'); + await Promise.all( + fixtures.map(f => { + return db.queryAsync('INSERT INTO spaces SET ?', { + ...f, + settings: JSON.stringify(f.settings) + }); + }) + ); + }); + + afterAll(async () => { + await db.queryAsync('DELETE from spaces'); + await db.endAsync(); + }); + describe('when the space exists', () => { - it.todo('returns a space object'); + let response; + beforeAll(async () => { + response = await fetch(`${HOST}/api/spaces/fabien.eth`); + }); + + it('returns the correct HTTP response', () => { + expect(response.status); + expect(response.headers.get('content-type')).toContain('application/json'); + }); + + it('returns the space data', async () => { + const space = fixtures[0]; + const expectedSpace = { + flagged: space.flagged, + verified: space.verified, + ...space.settings + }; + + expect(response.json()).resolves.toEqual(expectedSpace); + }); }); describe('when the space does not exist', () => { - it.todo('returns a 404 error'); + it('returns a 404 error', async () => { + const response = await fetch(`${HOST}/api/spaces/null.eth`); + + expect(response.status).toBe(404); + expect(response.headers.get('content-type')).toContain('application/json'); + expect(response.json()).resolves.toEqual({ + error: 'unauthorized', + error_description: 'not_found' + }); + }); }); }); diff --git a/test/fixtures/spaces.ts b/test/fixtures/spaces.ts new file mode 100644 index 00000000..a917f972 --- /dev/null +++ b/test/fixtures/spaces.ts @@ -0,0 +1,13 @@ +const fixtures: Record[] = [ + { + id: 'fabien.eth', + name: 'Fabien.eth', + flagged: false, + verified: true, + settings: { network: 1 }, + created_at: Math.floor(Date.now() / 1e3), + updated_at: Math.floor(Date.now() / 1e3) + } +]; + +export default fixtures; diff --git a/yarn.lock b/yarn.lock index c4ce8cc0..d736f55f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1779,11 +1779,6 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" @@ -2171,11 +2166,6 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -component-emitter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2223,11 +2213,6 @@ cookie@^0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -cookiejar@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - copyfiles@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" @@ -2374,14 +2359,6 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -dezalgo@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== - dependencies: - asap "^2.0.0" - wrappy "1" - diff-sequences@^29.4.3: version "29.4.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" @@ -2925,11 +2902,6 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fastq@^1.6.0: version "1.11.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" @@ -3031,16 +3003,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== - dependencies: - dezalgo "^1.0.4" - hexoid "^1.0.0" - once "^1.4.0" - qs "^6.11.0" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -3310,11 +3272,6 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hexoid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4297,7 +4254,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: +methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -4339,11 +4296,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -4423,7 +4375,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -node-fetch@^2.6.11, node-fetch@^2.7.0: +node-fetch@^2.6.11, node-fetch@^2.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -4555,7 +4507,7 @@ on-finished@2.4.1, on-finished@^2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -4812,13 +4764,6 @@ qs@6.10.3: dependencies: side-channel "^1.0.4" -qs@^6.11.0: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -5074,7 +5019,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: +semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -5343,30 +5288,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -superagent@^8.0.5: - version "8.0.9" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.0.9.tgz#2c6fda6fadb40516515f93e9098c0eb1602e0535" - integrity sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.4" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.1.2" - methods "^1.1.2" - mime "2.6.0" - qs "^6.11.0" - semver "^7.3.8" - -supertest@^6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.3.tgz#42f4da199fee656106fd422c094cf6c9578141db" - integrity sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA== - dependencies: - methods "^1.1.2" - superagent "^8.0.5" - supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" From 8a2982ed15129cb1f0c8034cf0c91225ef61587c Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Tue, 24 Oct 2023 16:01:55 +0700 Subject: [PATCH 02/11] fix: remove unused helper (#719) --- src/helpers/alias.ts | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/helpers/alias.ts diff --git a/src/helpers/alias.ts b/src/helpers/alias.ts deleted file mode 100644 index 29b8cd04..00000000 --- a/src/helpers/alias.ts +++ /dev/null @@ -1,7 +0,0 @@ -import db from './mysql'; - -export async function isValidAlias(from, alias): Promise { - const query = 'SELECT * FROM aliases WHERE address = ? AND alias = ? LIMIT 1'; - const results = await db.queryAsync(query, [from, alias]); - return !!results[0]; -} From 6b79c3c2c657bfd1b7f2ff2344f4f3e97ca1af87 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Tue, 24 Oct 2023 16:02:12 +0700 Subject: [PATCH 03/11] chore: ensure test suite are only run on test database (#713) * fix: return error when space does not exist * chore: ensure test suite always use test database * fix: fix setup running on import --- test/setup.ts | 10 ++++++++++ test/setupDb.ts | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/test/setup.ts b/test/setup.ts index 78bb7930..30e3a543 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,9 +1,19 @@ import { default as db, sequencerDB } from '../src/helpers/mysql'; +export const TEST_DATABASE_SUFFIX = '_test'; + const setup = async () => { try { await db.queryAsync('SELECT 1 + 1'); await sequencerDB.queryAsync('SELECT 1 + 1'); + + if (db.config.connectionConfig.database.endsWith(TEST_DATABASE_SUFFIX)) { + throw new Error(`Hub database name is not ending by ${TEST_DATABASE_SUFFIX}`); + } + + if (sequencerDB.config.connectionConfig.database.endsWith(TEST_DATABASE_SUFFIX)) { + throw new Error(`Sequencer database name is not ending by ${TEST_DATABASE_SUFFIX}`); + } } catch (e: any) { if (e.code === 'ER_BAD_DB_ERROR') { console.error('Test database not setup, please run `yarn test:setup`'); diff --git a/test/setupDb.ts b/test/setupDb.ts index 699a9bbd..278de712 100644 --- a/test/setupDb.ts +++ b/test/setupDb.ts @@ -4,6 +4,7 @@ import Connection from 'mysql/lib/Connection'; import bluebird from 'bluebird'; import parse from 'connection-string'; import fs from 'fs'; +import { TEST_DATABASE_SUFFIX } from './setup'; // @ts-ignore const config = parse(process.env.HUB_DATABASE_URL); @@ -14,8 +15,8 @@ bluebird.promisifyAll([Pool, Connection]); const db = mysql.createPool(config); const dbName = config.path[0]; -if (!dbName.endsWith('_test')) { - console.error('Invalid test database name. Must end with _test'); +if (!dbName.endsWith(TEST_DATABASE_SUFFIX)) { + console.error(`Invalid test database name. Must end with ${TEST_DATABASE_SUFFIX}`); process.exit(1); } From 0f6de8fe53658e8cb45ce785773fc9d0a08dd310 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:21:59 +0700 Subject: [PATCH 04/11] fix: check for value before manipulation (#730) --- src/helpers/metrics.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/helpers/metrics.ts b/src/helpers/metrics.ts index 500a62d9..b3bbe00f 100644 --- a/src/helpers/metrics.ts +++ b/src/helpers/metrics.ts @@ -58,9 +58,13 @@ export default function initMetrics(app: Express) { if (query && operationName) { const definition = parse(query).definitions.find( // @ts-ignore - def => def.name.value === operationName + def => def.name?.value === operationName ); + if (!definition) { + return; + } + // @ts-ignore const types = definition.selectionSet.selections.map(sel => sel.name.value); From 8a7854c471042e0e97bb4c074233d612fea61b11 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Thu, 26 Oct 2023 08:14:26 +0700 Subject: [PATCH 05/11] fix: skip logging graphQl Errors (#728) --- src/helpers/metrics.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/helpers/metrics.ts b/src/helpers/metrics.ts index b3bbe00f..f3f50897 100644 --- a/src/helpers/metrics.ts +++ b/src/helpers/metrics.ts @@ -1,7 +1,7 @@ import init, { client } from '@snapshot-labs/snapshot-metrics'; import { capture } from '@snapshot-labs/snapshot-sentry'; import { Express, type Request, type Response } from 'express'; -import { parse } from 'graphql'; +import { GraphQLError, parse } from 'graphql'; import { spacesMetadata } from './spaces'; import { strategies } from './strategies'; import db from './mysql'; @@ -75,7 +75,9 @@ export default function initMetrics(app: Express) { } } } catch (e: any) { - capture(e); + if (!(e instanceof GraphQLError)) { + capture(e); + } } }); } From 8c7127fa050a21b8b64e242de2b81c019ec836f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 10:25:39 +0400 Subject: [PATCH 06/11] chore(deps): bump @snapshot-labs/snapshot-sentry from 1.5.1 to 1.5.2 (#720) * chore(deps): bump @snapshot-labs/snapshot-sentry from 1.5.1 to 1.5.2 Bumps @snapshot-labs/snapshot-sentry from 1.5.1 to 1.5.2. --- updated-dependencies: - dependency-name: "@snapshot-labs/snapshot-sentry" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: set NODE_ENV for test env --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Wan Qi Chen <495709+wa0x6e@users.noreply.github.com> --- package.json | 2 +- test/.env.test | 1 + yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9bc1ca58..aba620d4 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@graphql-tools/schema": "^10.0.0", "@snapshot-labs/keycard": "^0.4.0", "@snapshot-labs/snapshot-metrics": "^1.3.1", - "@snapshot-labs/snapshot-sentry": "^1.5.1", + "@snapshot-labs/snapshot-sentry": "^1.5.2", "@snapshot-labs/snapshot.js": "^0.7.8", "bluebird": "^3.7.2", "connection-string": "^1.0.1", diff --git a/test/.env.test b/test/.env.test index 3f4db322..7346081a 100644 --- a/test/.env.test +++ b/test/.env.test @@ -1,2 +1,3 @@ HUB_DATABASE_URL=mysql://root:root@127.0.0.1:3306/hub_test SEQ_DATABASE_URL=mysql://root:root@127.0.0.1:3306/hub_test +NODE_ENV=test diff --git a/yarn.lock b/yarn.lock index d736f55f..75e7478e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1315,10 +1315,10 @@ node-fetch "^2.7.0" prom-client "^14.2.0" -"@snapshot-labs/snapshot-sentry@^1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot-sentry/-/snapshot-sentry-1.5.1.tgz#c4b5da87a97f760d9327743f7748783aaef14d9a" - integrity sha512-2xM72Xqypr73x6iWP5kr9fsNDeygmbiflTLhKeahT5yjjpFaSyS2razha+qxjo6w+0rIwNQXXYnlcrju24K2iA== +"@snapshot-labs/snapshot-sentry@^1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot-sentry/-/snapshot-sentry-1.5.2.tgz#a8c48e6602e0f236ba582a6728381e542501fe2a" + integrity sha512-xDZKiXigmfBWimDQGQwh/1WoqcD2n23nQczjWe+ukkLSvqk3AMwWz0F2tnd/MLiiklSyHezfcAzsSVMxlZPsPA== dependencies: "@sentry/node" "^7.60.1" From 3a3a3fb7e50531148157c38d0dc075f39be52d12 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Fri, 27 Oct 2023 20:49:53 +0700 Subject: [PATCH 07/11] fix: upgrade snapshot.js to 0.8.0 beta.0 (#702) * chore: upgrade to snapshot.js 0.8.0-beta.0 * fix: return more meaningful error * fix: user shorter args * update yarn.lock --------- Co-authored-by: Chaitanya --- package.json | 2 +- src/graphql/operations/vp.ts | 61 +++++++++++++++++++++++------------- yarn.lock | 43 +++++++++++++++++-------- 3 files changed, 71 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index aba620d4..73a2c22d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@snapshot-labs/keycard": "^0.4.0", "@snapshot-labs/snapshot-metrics": "^1.3.1", "@snapshot-labs/snapshot-sentry": "^1.5.2", - "@snapshot-labs/snapshot.js": "^0.7.8", + "@snapshot-labs/snapshot.js": "^0.8.0-beta.0", "bluebird": "^3.7.2", "connection-string": "^1.0.1", "cors": "^2.8.5", diff --git a/src/graphql/operations/vp.ts b/src/graphql/operations/vp.ts index 7c90ef23..d25198d6 100644 --- a/src/graphql/operations/vp.ts +++ b/src/graphql/operations/vp.ts @@ -1,30 +1,49 @@ +import { capture } from '@snapshot-labs/snapshot-sentry'; import snapshot from '@snapshot-labs/snapshot.js'; import db from '../../helpers/mysql'; const scoreAPIUrl = process.env.SCORE_API_URL || 'https://score.snapshot.org'; export default async function (_parent, { voter, space, proposal }) { - if (proposal) { - const query = `SELECT * FROM proposals WHERE id = ?`; - const [p] = await db.queryAsync(query, [proposal]); - - return await snapshot.utils.getVp( - voter, - p.network, - JSON.parse(p.strategies), - p.snapshot, - space, - false, - { url: scoreAPIUrl } - ); - } else if (space) { - const query = `SELECT settings FROM spaces WHERE id = ? AND deleted = 0 LIMIT 1`; - let [s] = await db.queryAsync(query, [space]); - s = JSON.parse(s.settings); - - return await snapshot.utils.getVp(voter, s.network, s.strategies, 'latest', space, false, { - url: scoreAPIUrl - }); + if (!voter) { + return Promise.reject(new Error('voter is required')); + } + + try { + if (proposal) { + const query = `SELECT * FROM proposals WHERE id = ?`; + const [p] = await db.queryAsync(query, [proposal]); + + if (!p) { + return Promise.reject(new Error('proposal not found')); + } + + return await snapshot.utils.getVp( + voter, + p.network, + JSON.parse(p.strategies), + p.snapshot, + space, + false, + { url: scoreAPIUrl } + ); + } else if (space) { + const query = `SELECT settings FROM spaces WHERE id = ? AND deleted = 0 LIMIT 1`; + let [s] = await db.queryAsync(query, [space]); + + if (!s) { + return Promise.reject(new Error('space not found')); + } + + s = JSON.parse(s.settings); + + return await snapshot.utils.getVp(voter, s.network, s.strategies, 'latest', space, false, { + url: scoreAPIUrl + }); + } + } catch (e: any) { + capture(e, { voter, space, proposal }); + return Promise.reject(new Error('request failed')); } return Promise.reject(new Error('missing argument')); diff --git a/yarn.lock b/yarn.lock index 75e7478e..982d1776 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1322,10 +1322,10 @@ dependencies: "@sentry/node" "^7.60.1" -"@snapshot-labs/snapshot.js@^0.7.8": - version "0.7.8" - resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot.js/-/snapshot.js-0.7.8.tgz#9a94b2a6de1331ccee5ffea3877af62dde4c2b33" - integrity sha512-TD0GQ+CKPsQWh7Ir5kELLjjdrvmDtH/UbKVgEx+wJYOMHn6IIfqA2Cw3OqmV2WG8SNqAj85hbalIzCBWMDbZ4A== +"@snapshot-labs/snapshot.js@^0.8.0-beta.0": + version "0.8.0-beta.0" + resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot.js/-/snapshot.js-0.8.0-beta.0.tgz#ec7d898ab439a6b37800dbc92e562dac9d1ef367" + integrity sha512-0B+qilsqQENmNf9tTXnUQ7/UVX5JLaMSyCTuJzf8+GxVGaZXGEG8TC9GdmL1q8YfJ/jXMWq9TzRjhs39ppZ6bg== dependencies: "@ensdomains/eth-ens-namehash" "^2.0.15" "@ethersproject/abi" "^5.6.4" @@ -1338,9 +1338,9 @@ "@ethersproject/wallet" "^5.6.2" ajv "^8.11.0" ajv-formats "^2.1.1" - cross-fetch "^3.1.6" json-to-graphql-query "^2.2.4" lodash.set "^4.3.2" + ofetch "^1.3.3" "@tsconfig/node10@^1.0.7": version "1.0.9" @@ -2244,13 +2244,6 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-fetch@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" - integrity sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g== - dependencies: - node-fetch "^2.6.11" - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2349,6 +2342,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +destr@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.1.tgz#2fc7bddc256fed1183e03f8d148391dde4023cb2" + integrity sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -4375,7 +4373,12 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -node-fetch@^2.6.11, node-fetch@^2.7, node-fetch@^2.7.0: +node-fetch-native@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.0.tgz#fbe8ac033cb6aa44bd106b5e4fd2b6277ba70fa1" + integrity sha512-F5kfEj95kX8tkDhUCYdV8dg3/8Olx/94zB8+ZNthFs6Bz31UpUi8Xh40TN3thLwXgrwXry1pEg9lJ++tLWTcqA== + +node-fetch@^2.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -4500,6 +4503,15 @@ object.values@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" +ofetch@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" + integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg== + dependencies: + destr "^2.0.1" + node-fetch-native "^1.4.0" + ufo "^1.3.0" + on-finished@2.4.1, on-finished@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -5552,6 +5564,11 @@ typescript@^4.7.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== +ufo@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.1.tgz#e085842f4627c41d4c1b60ebea1f75cdab4ce86b" + integrity sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" From d5667f0295f044d26e4b6b9a3b89763772147d8a Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Fri, 27 Oct 2023 22:08:21 +0700 Subject: [PATCH 08/11] Revert "fix: upgrade snapshot.js to 0.8.0 beta.0 (#702)" (#732) This reverts commit 3a3a3fb7e50531148157c38d0dc075f39be52d12. --- package.json | 2 +- src/graphql/operations/vp.ts | 61 +++++++++++++----------------------- yarn.lock | 43 ++++++++----------------- 3 files changed, 35 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 73a2c22d..aba620d4 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@snapshot-labs/keycard": "^0.4.0", "@snapshot-labs/snapshot-metrics": "^1.3.1", "@snapshot-labs/snapshot-sentry": "^1.5.2", - "@snapshot-labs/snapshot.js": "^0.8.0-beta.0", + "@snapshot-labs/snapshot.js": "^0.7.8", "bluebird": "^3.7.2", "connection-string": "^1.0.1", "cors": "^2.8.5", diff --git a/src/graphql/operations/vp.ts b/src/graphql/operations/vp.ts index d25198d6..7c90ef23 100644 --- a/src/graphql/operations/vp.ts +++ b/src/graphql/operations/vp.ts @@ -1,49 +1,30 @@ -import { capture } from '@snapshot-labs/snapshot-sentry'; import snapshot from '@snapshot-labs/snapshot.js'; import db from '../../helpers/mysql'; const scoreAPIUrl = process.env.SCORE_API_URL || 'https://score.snapshot.org'; export default async function (_parent, { voter, space, proposal }) { - if (!voter) { - return Promise.reject(new Error('voter is required')); - } - - try { - if (proposal) { - const query = `SELECT * FROM proposals WHERE id = ?`; - const [p] = await db.queryAsync(query, [proposal]); - - if (!p) { - return Promise.reject(new Error('proposal not found')); - } - - return await snapshot.utils.getVp( - voter, - p.network, - JSON.parse(p.strategies), - p.snapshot, - space, - false, - { url: scoreAPIUrl } - ); - } else if (space) { - const query = `SELECT settings FROM spaces WHERE id = ? AND deleted = 0 LIMIT 1`; - let [s] = await db.queryAsync(query, [space]); - - if (!s) { - return Promise.reject(new Error('space not found')); - } - - s = JSON.parse(s.settings); - - return await snapshot.utils.getVp(voter, s.network, s.strategies, 'latest', space, false, { - url: scoreAPIUrl - }); - } - } catch (e: any) { - capture(e, { voter, space, proposal }); - return Promise.reject(new Error('request failed')); + if (proposal) { + const query = `SELECT * FROM proposals WHERE id = ?`; + const [p] = await db.queryAsync(query, [proposal]); + + return await snapshot.utils.getVp( + voter, + p.network, + JSON.parse(p.strategies), + p.snapshot, + space, + false, + { url: scoreAPIUrl } + ); + } else if (space) { + const query = `SELECT settings FROM spaces WHERE id = ? AND deleted = 0 LIMIT 1`; + let [s] = await db.queryAsync(query, [space]); + s = JSON.parse(s.settings); + + return await snapshot.utils.getVp(voter, s.network, s.strategies, 'latest', space, false, { + url: scoreAPIUrl + }); } return Promise.reject(new Error('missing argument')); diff --git a/yarn.lock b/yarn.lock index 982d1776..75e7478e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1322,10 +1322,10 @@ dependencies: "@sentry/node" "^7.60.1" -"@snapshot-labs/snapshot.js@^0.8.0-beta.0": - version "0.8.0-beta.0" - resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot.js/-/snapshot.js-0.8.0-beta.0.tgz#ec7d898ab439a6b37800dbc92e562dac9d1ef367" - integrity sha512-0B+qilsqQENmNf9tTXnUQ7/UVX5JLaMSyCTuJzf8+GxVGaZXGEG8TC9GdmL1q8YfJ/jXMWq9TzRjhs39ppZ6bg== +"@snapshot-labs/snapshot.js@^0.7.8": + version "0.7.8" + resolved "https://registry.yarnpkg.com/@snapshot-labs/snapshot.js/-/snapshot.js-0.7.8.tgz#9a94b2a6de1331ccee5ffea3877af62dde4c2b33" + integrity sha512-TD0GQ+CKPsQWh7Ir5kELLjjdrvmDtH/UbKVgEx+wJYOMHn6IIfqA2Cw3OqmV2WG8SNqAj85hbalIzCBWMDbZ4A== dependencies: "@ensdomains/eth-ens-namehash" "^2.0.15" "@ethersproject/abi" "^5.6.4" @@ -1338,9 +1338,9 @@ "@ethersproject/wallet" "^5.6.2" ajv "^8.11.0" ajv-formats "^2.1.1" + cross-fetch "^3.1.6" json-to-graphql-query "^2.2.4" lodash.set "^4.3.2" - ofetch "^1.3.3" "@tsconfig/node10@^1.0.7": version "1.0.9" @@ -2244,6 +2244,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" + integrity sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g== + dependencies: + node-fetch "^2.6.11" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2342,11 +2349,6 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -destr@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.1.tgz#2fc7bddc256fed1183e03f8d148391dde4023cb2" - integrity sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA== - destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -4373,12 +4375,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -node-fetch-native@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.0.tgz#fbe8ac033cb6aa44bd106b5e4fd2b6277ba70fa1" - integrity sha512-F5kfEj95kX8tkDhUCYdV8dg3/8Olx/94zB8+ZNthFs6Bz31UpUi8Xh40TN3thLwXgrwXry1pEg9lJ++tLWTcqA== - -node-fetch@^2.7, node-fetch@^2.7.0: +node-fetch@^2.6.11, node-fetch@^2.7, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -4503,15 +4500,6 @@ object.values@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" -ofetch@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" - integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg== - dependencies: - destr "^2.0.1" - node-fetch-native "^1.4.0" - ufo "^1.3.0" - on-finished@2.4.1, on-finished@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -5564,11 +5552,6 @@ typescript@^4.7.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== -ufo@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.1.tgz#e085842f4627c41d4c1b60ebea1f75cdab4ce86b" - integrity sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw== - unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" From 7e6cc67059aa008f3cf1d7bb8155dd41c2453aea Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Sat, 28 Oct 2023 12:16:54 +0700 Subject: [PATCH 09/11] fix: check space and proposal exist (#734) --- src/graphql/operations/vp.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/graphql/operations/vp.ts b/src/graphql/operations/vp.ts index 7c90ef23..4e71601e 100644 --- a/src/graphql/operations/vp.ts +++ b/src/graphql/operations/vp.ts @@ -5,9 +5,13 @@ const scoreAPIUrl = process.env.SCORE_API_URL || 'https://score.snapshot.org'; export default async function (_parent, { voter, space, proposal }) { if (proposal) { - const query = `SELECT * FROM proposals WHERE id = ?`; + const query = `SELECT * FROM proposals WHERE id = ? LIMIT 1`; const [p] = await db.queryAsync(query, [proposal]); + if (!p) { + return Promise.reject(new Error('proposal not found')); + } + return await snapshot.utils.getVp( voter, p.network, @@ -20,6 +24,11 @@ export default async function (_parent, { voter, space, proposal }) { } else if (space) { const query = `SELECT settings FROM spaces WHERE id = ? AND deleted = 0 LIMIT 1`; let [s] = await db.queryAsync(query, [space]); + + if (!s) { + return Promise.reject(new Error('space not found')); + } + s = JSON.parse(s.settings); return await snapshot.utils.getVp(voter, s.network, s.strategies, 'latest', space, false, { From efe8f61e42630bf4aad08ad21507bfe48f64c017 Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Sat, 28 Oct 2023 12:21:23 +0700 Subject: [PATCH 10/11] fix: return an error on invalid voter address (#733) --- src/graphql/operations/vp.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/graphql/operations/vp.ts b/src/graphql/operations/vp.ts index 4e71601e..63e7efee 100644 --- a/src/graphql/operations/vp.ts +++ b/src/graphql/operations/vp.ts @@ -4,6 +4,10 @@ import db from '../../helpers/mysql'; const scoreAPIUrl = process.env.SCORE_API_URL || 'https://score.snapshot.org'; export default async function (_parent, { voter, space, proposal }) { + if (voter === '0x0000000000000000000000000000000000000000' || voter === '') { + return Promise.reject(new Error('invalid address')); + } + if (proposal) { const query = `SELECT * FROM proposals WHERE id = ? LIMIT 1`; const [p] = await db.queryAsync(query, [proposal]); From cf26dfeabd19ffc2d6de9714824986e4e6d4a77e Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Sat, 28 Oct 2023 12:48:25 +0700 Subject: [PATCH 11/11] refactor: trigger data refresher manually (#731) * fix: check for value before manipulation * fix: run background refresher on demand * refactor: move all refresher init in same place --- src/helpers/moderation.ts | 4 +--- src/helpers/spaces.ts | 4 +--- src/index.ts | 5 ++++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/helpers/moderation.ts b/src/helpers/moderation.ts index cd7e9141..315d8ec6 100644 --- a/src/helpers/moderation.ts +++ b/src/helpers/moderation.ts @@ -13,7 +13,7 @@ async function loadModerationData() { flaggedLinks = res?.flaggedLinks; } -async function run() { +export default async function run() { try { await loadModerationData(); consecutiveFailsCount = 0; @@ -28,5 +28,3 @@ async function run() { await snapshot.utils.sleep(5e3); run(); } - -run(); diff --git a/src/helpers/spaces.ts b/src/helpers/spaces.ts index 40fd3c2e..5e9beb0d 100644 --- a/src/helpers/spaces.ts +++ b/src/helpers/spaces.ts @@ -176,7 +176,7 @@ export async function getSpace(id: string) { }; } -async function run() { +export default async function run() { try { await loadSpaces(); await loadSpacesMetrics(); @@ -187,5 +187,3 @@ async function run() { await snapshot.utils.sleep(360e3); run(); } - -run(); diff --git a/src/index.ts b/src/index.ts index 6e5d5cda..a8aff851 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,8 @@ import rateLimit from './helpers/rateLimit'; import log from './helpers/log'; import initMetrics from './helpers/metrics'; import { checkKeycard } from './helpers/keycard'; -import './helpers/moderation'; +import refreshModerationData from './helpers/moderation'; +import refreshSpacesCache from './helpers/spaces'; import './helpers/strategies'; const app = express(); @@ -16,6 +17,8 @@ const PORT = process.env.PORT || 3000; initLogger(app); initMetrics(app); +refreshModerationData(); +refreshSpacesCache(); app.disable('x-powered-by'); app.use(express.json({ limit: '20mb' }));