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

Vouched projects and superfluid Base improvements #1897

Open
wants to merge 73 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
6ba562f
throw error on un-vouching the givbackseligible projects
MohammadPCh Oct 27, 2024
5565767
update message
MohammadPCh Oct 27, 2024
a744af6
optimize the approveMultipleProjects
MohammadPCh Oct 27, 2024
8d017d1
make projects verified if they become givbacksEligible
MohammadPCh Oct 27, 2024
7db802f
prevent approve or reject draft projects
MohammadPCh Oct 28, 2024
a680fa2
Merge branch 'staging' into update-verify-approve-conditions
MohammadPCh Oct 29, 2024
f33cb33
fix records
MohammadPCh Oct 29, 2024
7c23f75
fix conditions
MohammadPCh Oct 29, 2024
102ce11
use redirectUrl
MohammadPCh Oct 29, 2024
d23a58a
fix tests
MohammadPCh Oct 29, 2024
4d8b591
add unverifyProjectsTestCases
MohammadPCh Oct 29, 2024
9d99aff
add test:projectVerificationTab
MohammadPCh Oct 29, 2024
4d82302
temporary comment
MohammadPCh Oct 29, 2024
52cfb82
fix typo
MohammadPCh Nov 4, 2024
b3dfb59
send email when project verification status changed
MohammadPCh Nov 4, 2024
baa24d1
Feat/Generating public user data
kkatusic Dec 3, 2024
e5605eb
Merge branch 'staging' into feat/user_sitemap_list
kkatusic Dec 5, 2024
fd8ea0e
added tests for querying user basic data
kkatusic Dec 5, 2024
e89c1ea
add includeUnlisted to FilterProjectQueryInputParams
MohammadPCh Dec 9, 2024
92f15c9
return proper projects
MohammadPCh Dec 9, 2024
2051be0
add recipient address to streams when nonexistent (#1890)
CarlosQ96 Dec 9, 2024
d6e3888
Merge branch 'master' into staging
CarlosQ96 Dec 10, 2024
d12453d
Merge pull request #1889 from Giveth/fetch-unlisted-projects
MohammadPCh Dec 10, 2024
5cf1e60
started endaoment update feature
kkatusic Dec 11, 2024
f0c3fc8
Superfluid Base Support (#1893)
CarlosQ96 Dec 17, 2024
445fe68
Merge pull request #1866 from Giveth/update-verify-approve-conditions
divine-comedian Dec 18, 2024
82dfc17
remove project validation from anchor contract
CarlosQ96 Dec 21, 2024
b41c543
Merge pull request #1887 from Giveth/feat/user_sitemap_list
kkatusic Dec 26, 2024
ff91c4d
Add networkId logic to superfluid subgraphs (#1896)
CarlosQ96 Dec 26, 2024
b703497
fix linkedin scope
lovelgeorge99 Dec 30, 2024
b930c80
Merge pull request #1898 from Giveth/fix-linkedin-scope
lovelgeorge99 Dec 31, 2024
3e62ce6
fix user info link to user info
lovelgeorge99 Jan 2, 2025
829f973
cron job for sitemap generating
kkatusic Jan 2, 2025
c74dc3b
Merge pull request #1899 from Giveth/fix-linkedin-scope
lovelgeorge99 Jan 2, 2025
09186cd
Merge pull request #1900 from Giveth/feat/sitemap_cron_job
kkatusic Jan 3, 2025
7ebaeca
adding additional projects to Endaoment list
kkatusic Jan 3, 2025
03e134e
Merge branch 'staging' into feat/check_periodically_endaoment
kkatusic Jan 3, 2025
5a866ad
started cronjob
kkatusic Jan 3, 2025
d4cf597
finished cron job
kkatusic Jan 8, 2025
b558266
Feature cluster matching (#1862)
CarlosQ96 Jan 9, 2025
ed8e7da
Merge branch 'staging' into feat/check_periodically_endaoment
kkatusic Jan 9, 2025
b224a32
fix updateUser condition to handle email undefined case
CarlosQ96 Jan 9, 2025
60f30ad
fixed one variable; added cronjob env suggested by Carlos
kkatusic Jan 10, 2025
2d79a58
removed redundant code
kkatusic Jan 10, 2025
e8a6120
check config value
kkatusic Jan 10, 2025
baa7450
fix calling env variable
kkatusic Jan 10, 2025
448da9e
Merge pull request #1892 from Giveth/feat/check_periodically_endaoment
kkatusic Jan 10, 2025
1c37bc0
fix/removing endaomentId from update
kkatusic Jan 13, 2025
039d808
Merge pull request #1904 from Giveth/feat/check_periodically_endaoment
kkatusic Jan 13, 2025
9d61941
add qfStrategy to qfRounds (#1903)
CarlosQ96 Jan 13, 2025
acd0e5d
update bootstrap.js adding check endaoment
kkatusic Jan 13, 2025
e9ea066
adding sitemap cronjob to bootstrap
kkatusic Jan 13, 2025
e8a7de5
Merge pull request #1905 from Giveth/feat/check_periodically_endaoment
kkatusic Jan 13, 2025
9a1a8a1
additional logger data
kkatusic Jan 14, 2025
c7af69c
fine tuninnig log
kkatusic Jan 14, 2025
66e8cce
Merge pull request #1906 from Giveth/feat/check_periodically_endaoment
kkatusic Jan 14, 2025
7621d4b
improve logger
kkatusic Jan 14, 2025
1374e40
Merge pull request #1907 from Giveth/feat/check_periodically_endaoment
kkatusic Jan 14, 2025
9f5752b
fixing endaoment id
kkatusic Jan 14, 2025
2825385
Merge pull request #1908 from Giveth/feat/check_periodically_endaoment
kkatusic Jan 14, 2025
e4f6b26
Set default zero for power balance snapshot on no return from balance…
aminlatifi Jan 18, 2025
ed56a80
Fix/Sitemap env variables
kkatusic Jan 20, 2025
a80ff7c
Merge pull request #1910 from Giveth/fix/sitemap_calling
kkatusic Jan 20, 2025
b1104b9
fix missing prefix for url
kkatusic Jan 20, 2025
7bbfcdf
Merge pull request #1911 from Giveth/fix/sitemap_calling
kkatusic Jan 20, 2025
734dbab
fix matching cap calculation
CarlosQ96 Jan 22, 2025
54fa338
fix data insertion for cluster matching
CarlosQ96 Jan 22, 2025
5822180
add user passport score null case to clustermatching queries
CarlosQ96 Jan 22, 2025
9bcaded
fix error handling in cocm adapter
CarlosQ96 Jan 22, 2025
7e9c1b6
add cluster matching sync timestamp and logs (#1913)
CarlosQ96 Jan 22, 2025
0edb4e8
fix db call in worker for cluster matching
CarlosQ96 Jan 22, 2025
dc57537
add uniquness constraint to estimatedclustedMatching
CarlosQ96 Jan 22, 2025
7797caa
handle undefined case for instant power boosting services
CarlosQ96 Jan 23, 2025
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
34 changes: 34 additions & 0 deletions migration/1728554628004-AddEstimatedClusterMatching.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddEstimatedClusterMatching1728554628004
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE estimated_cluster_matching (
id SERIAL PRIMARY KEY,
"projectId" INT NOT NULL,
"qfRoundId" INT NOT NULL,
matching DOUBLE PRECISION NOT NULL
);
`);

// Create indexes on the new table
await queryRunner.query(`
CREATE INDEX estimated_cluster_matching_project_id_qfround_id
ON estimated_cluster_matching ("projectId", "qfRoundId");
`);

await queryRunner.query(`
CREATE INDEX estimated_cluster_matching_matching
ON estimated_cluster_matching (matching);
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
// Revert changes if necessary by dropping the table and restoring the view
await queryRunner.query(`
DROP TABLE IF EXISTS estimated_cluster_matching;
`);
}
}
10 changes: 10 additions & 0 deletions migration/data/seedTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,16 @@ const seedTokens: ITokenData[] = [
coingeckoId: 'degen-base',
isGivbackEligible: false,
},
// cbBTC - https://basescan.org/token/0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf
{
name: 'Coinbase Wrapped BTC',
symbol: 'cbBTC',
address: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf',
decimals: 8,
networkId: NETWORK_IDS.BASE_MAINNET,
coingeckoId: 'coinbase-wrapped-btc',
isGivbackEligible: false,
},
// Osaka Protocol - https://basescan.org/token/0xbFd5206962267c7b4b4A8B3D76AC2E1b2A5c4d5e
{
name: 'Osaka Protocol',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
"test:qfRoundService": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/services/qfRoundService.test.ts",
"test:project": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/entities/project.test.ts",
"test:projectsTab": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/server/adminJs/tabs/projectsTab.test.ts",
"test:projectVerificationTab": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/server/adminJs/tabs/projectVerificationTab.test.ts",
"test:syncUsersModelScore": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/services/cronJobs/syncUsersModelScore.test.ts",
"test:notifyDonationsWithSegment": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/services/cronJobs/notifyDonationsWithSegment.test.ts",
"test:checkProjectVerificationStatus": "NODE_ENV=test mocha ./test/pre-test-scripts.ts ./src/services/cronJobs/checkProjectVerificationStatus.test.ts",
Expand Down
17 changes: 17 additions & 0 deletions src/adapters/adaptersFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import { DonationSaveBackupMockAdapter } from './donationSaveBackup/DonationSave
import { SuperFluidAdapter } from './superFluid/superFluidAdapter';
import { SuperFluidMockAdapter } from './superFluid/superFluidMockAdapter';
import { SuperFluidAdapterInterface } from './superFluid/superFluidAdapterInterface';
import { CocmAdapter } from './cocmAdapter/cocmAdapter';
import { CocmMockAdapter } from './cocmAdapter/cocmMockAdapter';
import { CocmAdapterInterface } from './cocmAdapter/cocmAdapterInterface';

const discordAdapter = new DiscordAdapter();
const googleAdapter = new GoogleAdapter();
Expand Down Expand Up @@ -147,3 +150,17 @@ export const getSuperFluidAdapter = (): SuperFluidAdapterInterface => {
return superFluidMockAdapter;
}
};

const clusterMatchingAdapter = new CocmAdapter();
const clusterMatchingMockAdapter = new CocmMockAdapter();

export const getClusterMatchingAdapter = (): CocmAdapterInterface => {
switch (process.env.CLUSTER_MATCHING_ADAPTER) {
case 'clusterMatching':
return clusterMatchingAdapter;
case 'mock':
return clusterMatchingMockAdapter;
default:
return clusterMatchingMockAdapter;
}
};
46 changes: 46 additions & 0 deletions src/adapters/cocmAdapter/cocmAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import axios from 'axios';
import {
CocmAdapterInterface,
EstimatedMatchingInput,
ProjectsEstimatedMatchings,
} from './cocmAdapterInterface';
import { logger } from '../../utils/logger';
import { i18n, translationErrorMessagesKeys } from '../../utils/errorMessages';

export class CocmAdapter implements CocmAdapterInterface {
private ClusterMatchingURL;

constructor() {
this.ClusterMatchingURL =
process.env.CLUSTER_MATCHING_API_URL || 'localhost';
}

async fetchEstimatedClusterMatchings(
matchingDataInput: EstimatedMatchingInput,
): Promise<ProjectsEstimatedMatchings> {
try {
const result = await axios.post(
this.ClusterMatchingURL,
matchingDataInput,
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
);
if (result?.data?.error !== null) {
logger.error('clusterMatchingApi error', result.data.error);
throw new Error(
i18n.__(translationErrorMessagesKeys.CLUSTER_MATCHING_API_ERROR),
);
}
return result.data;
} catch (e) {
logger.error('clusterMatchingApi error', e);
throw new Error(
i18n.__(translationErrorMessagesKeys.CLUSTER_MATCHING_API_ERROR),
);
}
}
}
49 changes: 49 additions & 0 deletions src/adapters/cocmAdapter/cocmAdapterInterface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Example Data
// {
// "matching_data": [
// {
// "matching_amount": 83.25,
// "matching_percent": 50.0,
// "project_name": "Test1",
// "strategy": "COCM"
// },
// {
// "matching_amount": 83.25,
// "matching_percent": 50.0,
// "project_name": "Test3",
// "strategy": "COCM"
// }
// ]
// }

export interface ProjectsEstimatedMatchings {
matching_data: {
matching_amount: number;
matching_percent: number;
project_name: string;
strategy: string;
}[];
}

export interface EstimatedMatchingInput {
votes_data: [
{
voter: string;
payoutAddress: string;
amountUSD: number;
project_name: string;
score: number;
},
];
strategy: string;
min_donation_threshold_amount: number;
matching_cap_amount: number;
matching_amount: number;
passport_threshold: number;
}

export interface CocmAdapterInterface {
fetchEstimatedClusterMatchings(
matchingDataInput: EstimatedMatchingInput,
): Promise<ProjectsEstimatedMatchings>;
}
27 changes: 27 additions & 0 deletions src/adapters/cocmAdapter/cocmMockAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
CocmAdapterInterface,
ProjectsEstimatedMatchings,
} from './cocmAdapterInterface';

export class CocmMockAdapter implements CocmAdapterInterface {
async fetchEstimatedClusterMatchings(
_matchingDataInput,
): Promise<ProjectsEstimatedMatchings> {
return {
matching_data: [
{
matching_amount: 83.25,
matching_percent: 50.0,
project_name: 'Test1',
strategy: 'COCM',
},
{
matching_amount: 83.25,
matching_percent: 50.0,
project_name: 'Test3',
strategy: 'COCM',
},
],
};
}
}
60 changes: 21 additions & 39 deletions src/adapters/oauth2/linkedinAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class LinkedinAdapter implements SocialNetworkOauth2AdapterInterface {
*/

// https://docs.microsoft.com/en-us/linkedin/shared/authentication/getting-access?context=linkedin%2Fcontext#open-permissions-consumer
const scope = 'r_liteprofile';
const scope = 'openid profile email';
return `https://www.linkedin.com/oauth/v2/authorization?client_id=${clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${trackId}`;
}

Expand Down Expand Up @@ -57,50 +57,32 @@ export class LinkedinAdapter implements SocialNetworkOauth2AdapterInterface {
const accessToken = result.data.access_token;

/**
* @see {@link https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin?context=linkedin%2Fconsumer%2Fcontext#api-request}
*/
const meResult = await axios.get('https://api.linkedin.com/v2/me', {
@see {@link https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2?context=linkedin%2Fconsumer%2Fcontext#api-request-to-retreive-member-details}
*/
const meResult = await axios.get('https://api.linkedin.com/v2/userinfo', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});

/**
* sample response
{
"id":"REDACTED",
"firstName":{
"localized":{
"en_US":"Tina"
},
"preferredLocale":{
"country":"US",
"language":"en"
}
},
"lastName":{
"localized":{
"en_US":"Belcher"
},
"preferredLocale":{
"country":"US",
"language":"en"
}
},
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:B54328XZFfe2134zTyq"
}
}
* New Sample response
* {
* "sub": "782bbtaQ",
* "name": "John Doe",
* "given_name": "John",
* "family_name": "Doe",
* "picture": "https://media.licdn-ei.com/dms/image/C5F03AQHqK8v7tB1HCQ/profile-displayphoto-shrink_100_100/0/",
* "locale": "en-US",
* "email": "[email protected]",
* "email_verified": true
* }
*/
const username = meResult.data.id;
let name = username;
if (
meResult.data?.firstName?.localized?.en_US ||
meResult.data?.lastName?.localized?.en_US
) {
name = `${meResult.data?.firstName?.localized?.en_US || ''} ${
meResult.data?.lastName?.localized?.en_US || ''
}`.trim();
}
const username = meResult.data.sub;

const name =
meResult.data.name ||
`${meResult.data.given_name || ''} ${meResult.data.family_name || ''}`.trim();
return {
username,
name,
Expand Down
52 changes: 43 additions & 9 deletions src/adapters/superFluid/superFluidAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
import axios from 'axios';
import { logger } from '../../utils/logger';
import { isProduction } from '../../utils/utils';
import {
FlowUpdatedEvent,
SuperFluidAdapterInterface,
} from './superFluidAdapterInterface';
import { NETWORK_IDS } from '../../provider';

const superFluidGraphqlUrl =
const superFluidGraphqlPolygonUrl =
'https://subgraph-endpoints.superfluid.dev/optimism-mainnet/protocol-v1';
const superFluidGraphqlStagingUrl =
const superFluidGraphqlPolygonStagingUrl =
'https://optimism-sepolia.subgraph.x.superfluid.dev';
const superFluidGraphBaseUrl =
'https://subgraph-endpoints.superfluid.dev/base-mainnet/protocol-v1';

const subgraphUrl = isProduction
? superFluidGraphqlUrl
: superFluidGraphqlStagingUrl;
const subgraphUrlMap = {
[NETWORK_IDS.OPTIMISTIC]: superFluidGraphqlPolygonUrl,
[NETWORK_IDS.OPTIMISM_SEPOLIA]: superFluidGraphqlPolygonStagingUrl,
[NETWORK_IDS.BASE_MAINNET]: superFluidGraphBaseUrl,
[NETWORK_IDS.BASE_SEPOLIA]: superFluidGraphBaseUrl,
};

// Function to retrieve the subgraph URL for a given network ID
const getSubgraphUrl = (networkId: number) => {
const url = subgraphUrlMap[networkId];
if (!url) {
throw new Error(`No subgraph URL found for network ID: ${networkId}`);
}
return url;
};

// Define your GraphQL query as a string and prepare your variables
const accountQuery = `
Expand Down Expand Up @@ -169,8 +183,9 @@ export class SuperFluidAdapter implements SuperFluidAdapterInterface {
*/

// Optimism works
async accountBalance(accountId: string) {
async accountBalance(accountId: string, networkId: number) {
try {
const subgraphUrl = getSubgraphUrl(networkId);
const response = await axios.post(subgraphUrl, {
query: accountQuery,
variables: {
Expand All @@ -189,12 +204,21 @@ export class SuperFluidAdapter implements SuperFluidAdapterInterface {
sender: string;
flowRate: string;
transactionHash: string;
networkId: number;
}): Promise<FlowUpdatedEvent | undefined> {
try {
const subgraphUrl = getSubgraphUrl(params.networkId);
const whereParams = {
receiver: params.receiver,
sender: params.sender,
flowRate: params.flowRate,
transactionHash: params.transactionHash,
};

const response = await axios.post(subgraphUrl, {
query: getFlowsQuery,
variables: {
where: params,
where: whereParams,
orderBy: 'timestamp',
orderDirection: 'asc',
},
Expand All @@ -213,14 +237,24 @@ export class SuperFluidAdapter implements SuperFluidAdapterInterface {
sender: string;
flowRate: string;
timestamp_gt: number;
networkId: number;
}): Promise<FlowUpdatedEvent | undefined> {
try {
const subgraphUrl = getSubgraphUrl(params.networkId);

logger.debug('getFlowByReceiverSenderFlowRate has been called', params);

const whereParams = {
receiver: params.receiver,
sender: params.sender,
flowRate: params.flowRate,
timestamp_gt: params.timestamp_gt,
};

const response = await axios.post(subgraphUrl, {
query: getFlowsQuery,
variables: {
where: params,
where: whereParams,
orderBy: 'timestamp',
orderDirection: 'asc',
},
Expand Down
Loading
Loading