Skip to content

Commit

Permalink
Release mpeth token (#1305)
Browse files Browse the repository at this point in the history
* add mpeth prices fetch and token

* add env var to tests

* add tests for fetching price method (check status)
  • Loading branch information
CarlosQ96 authored Feb 6, 2024
1 parent ee10acf commit bdcfff4
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/develop-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
SOLANA_TEST_NODE_RPC_URL: ${{ secrets.SOLANA_TEST_NODE_RPC_URL }}
SOLANA_DEVNET_NODE_RPC_URL: ${{ secrets.SOLANA_DEVNET_NODE_RPC_URL }}
SOLANA_MAINNET_NODE_RPC_URL: ${{ secrets.SOLANA_MAINNET_NODE_RPC_URL }}
MPETH_GRAPHQL_PRICES_URL: ${{ secrets.MPETH_GRAPHQL_PRICES_URL }}

publish:
needs: test
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/master-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
SOLANA_TEST_NODE_RPC_URL: ${{ secrets.SOLANA_TEST_NODE_RPC_URL }}
SOLANA_DEVNET_NODE_RPC_URL: ${{ secrets.SOLANA_DEVNET_NODE_RPC_URL }}
SOLANA_MAINNET_NODE_RPC_URL: ${{ secrets.SOLANA_MAINNET_NODE_RPC_URL }}
MPETH_GRAPHQL_PRICES_URL: ${{ secrets.MPETH_GRAPHQL_PRICES_URL }}

publish:
needs: test
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/run-tests-on-pr.yml.bck
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ jobs:
OPTIMISTIC_SCAN_API_KEY: ${{ secrets.OPTIMISTIC_SCAN_API_KEY }}
CELO_SCAN_API_KEY: ${{ secrets.CELO_SCAN_API_KEY }}
CELO_ALFAJORES_SCAN_API_KEY: ${{ secrets.CELO_ALFAJORES_SCAN_API_KEY }}
MPETH_GRAPHQL_PRICES_URL: ${{ secrets.MPETH_GRAPHQL_PRICES_URL }}
1 change: 1 addition & 0 deletions .github/workflows/staging-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ jobs:
SOLANA_TEST_NODE_RPC_URL: ${{ secrets.SOLANA_TEST_NODE_RPC_URL }}
SOLANA_DEVNET_NODE_RPC_URL: ${{ secrets.SOLANA_DEVNET_NODE_RPC_URL }}
SOLANA_MAINNET_NODE_RPC_URL: ${{ secrets.SOLANA_MAINNET_NODE_RPC_URL }}
MPETH_GRAPHQL_PRICES_URL: ${{ secrets.MPETH_GRAPHQL_PRICES_URL }}

publish:
needs: test
Expand Down
10 changes: 10 additions & 0 deletions config/example.env
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,13 @@ DONATION_SAVE_BACKUP_DATABASE=

# Default value is saveBackup
DONATION_SAVE_BACKUP_ADAPTER=saveBackup

ENABLE_UPDATE_RECURRING_DONATION_STREAM=true

# Default value is 1
NUMBER_OF_UPDATE_RECURRING_DONATION_CONCURRENT_JOB=1

# Default value is 0 0 * * * that means one day at 00:00
UPDATE_RECURRING_DONATIONS_STREAM=0 0 * * *

MPETH_GRAPHQL_PRICES_URL=
77 changes: 77 additions & 0 deletions migration/1706820821887-addmpEthToDatabaseTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { NETWORK_IDS } from '../src/provider';
import { ChainType } from '../src/types/network';
import { Token } from '../src/entities/token';

const mpEthTokens = [
{
name: 'mpETH',
symbol: 'mpETH',
address: '0x48afbbd342f64ef8a9ab1c143719b63c2ad81710',
decimals: 18,
isGivbackEligible: true,
networkId: NETWORK_IDS.MAIN_NET,
chainType: ChainType.EVM,
},
{
name: 'mpETH',
symbol: 'mpETH',
address: '0x819845b60a192167ed1139040b4f8eca31834f27',
mainnetAddress: '0x48afbbd342f64ef8a9ab1c143719b63c2ad81710',
decimals: 18,
isGivbackEligible: true,
networkId: NETWORK_IDS.OPTIMISTIC,
chainType: ChainType.EVM,
},
];

export class addmpEthToDatabaseTokens1706820821887
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.manager.save(Token, mpEthTokens);

const tokens = await queryRunner.query(`
SELECT * FROM token
WHERE
("address" = '0x48afbbd342f64ef8a9ab1c143719b63c2ad81710' AND "networkId" = ${NETWORK_IDS.MAIN_NET}) OR
("address" = '0x819845b60a192167ed1139040b4f8eca31834f27' AND "networkId" = ${NETWORK_IDS.OPTIMISTIC})
`);
const givethOrganization = (
await queryRunner.query(`SELECT * FROM organization
WHERE label='giveth'`)
)[0];

const traceOrganization = (
await queryRunner.query(`SELECT * FROM organization
WHERE label='trace'`)
)[0];

for (const token of tokens) {
await queryRunner.query(`INSERT INTO organization_tokens_token ("tokenId","organizationId") VALUES
(${token.id}, ${givethOrganization.id}),
(${token.id}, ${traceOrganization.id})
;`);
}
}

public async down(queryRunner: QueryRunner): Promise<void> {
const tokens = await queryRunner.query(`
SELECT * FROM token
WHERE
("address" = '0x48afbbd342f64ef8a9ab1c143719b63c2ad81710' AND "networkId" = ${NETWORK_IDS.MAIN_NET}) OR
("address" = '0x819845b60a192167ed1139040b4f8eca31834f27' AND "networkId" = ${NETWORK_IDS.OPTIMISTIC})
`);
await queryRunner.query(
`DELETE FROM organization_tokens_token WHERE "tokenId" IN (${tokens
.map(token => token.id)
.join(',')})`,
);

await queryRunner.query(
`DELETE FROM token WHERE "id" IN (${tokens
.map(token => token.id)
.join(',')})`,
);
}
}
64 changes: 64 additions & 0 deletions src/services/donationService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,70 @@ function fillOldStableCoinDonationsPriceTestCases() {
expect(donation.valueUsd).to.gt(0);
});

it('should fill price for mpETH donation on the MAINNET network', async () => {
const token = 'mpETH';
const amount = 2;
let donation = await saveDonationDirectlyToDb(
{
...createDonationData(),
currency: token,
valueUsd: undefined,
valueEth: undefined,
amount,
},
SEED_DATA.FIRST_USER.id,
SEED_DATA.FIRST_PROJECT.id,
);

const project = (await Project.findOne({
where: { id: SEED_DATA.FIRST_PROJECT.id },
})) as Project;

await updateDonationPricesAndValues(
donation,
project,
null,
token,
CHAIN_ID.MAINNET,
amount,
);
donation = (await findDonationById(donation.id))!;
expect(donation.valueUsd).to.gt(0);
expect(donation.priceUsd).to.below(donation.valueUsd);
});

it('should fill price for mpETH donation on the OPTIMISM network', async () => {
const token = 'mpETH';
const amount = 2;
let donation = await saveDonationDirectlyToDb(
{
...createDonationData(),
currency: token,
valueUsd: undefined,
valueEth: undefined,
amount,
},
SEED_DATA.FIRST_USER.id,
SEED_DATA.FIRST_PROJECT.id,
);

const project = (await Project.findOne({
where: { id: SEED_DATA.FIRST_PROJECT.id },
})) as Project;

await updateDonationPricesAndValues(
donation,
project,
null,
token,
CHAIN_ID.OPTIMISM,
amount,
);
donation = (await findDonationById(donation.id))!;
expect(donation.valueUsd).to.gt(0);
expect(donation.priceUsd).to.below(donation.valueUsd);
});

it('should fill price for Celo donation on the CELO Alfajores network', async () => {
const token = 'CELO';
const amount = 100;
Expand Down
5 changes: 5 additions & 0 deletions src/services/donationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { fetchSafeTransactionHash } from './safeServices';
import { ChainType } from '../types/network';
import { NETWORK_IDS } from '../provider';
import { getTransactionInfoFromNetwork } from './chains';
import { fetchMpEthPrice } from './mpEthPriceService';

export const TRANSAK_COMPLETED_STATUS = 'COMPLETED';

Expand All @@ -65,6 +66,10 @@ export const updateDonationPricesAndValues = async (
if (token?.isStableCoin) {
donation.priceUsd = 1;
donation.valueUsd = Number(amount);
} else if (currency === 'mpETH') {
const mpEthPriceInUsd = await fetchMpEthPrice();
donation.priceUsd = toFixNumber(mpEthPriceInUsd, 4);
donation.valueUsd = toFixNumber(donation.amount * mpEthPriceInUsd, 4);
} else if (currency === 'GIV') {
const { givPriceInUsd } = await fetchGivPrice();
donation.priceUsd = toFixNumber(givPriceInUsd, 4);
Expand Down
12 changes: 12 additions & 0 deletions src/services/mpEthPriceService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { assert, expect } from 'chai';
import { fetchMpEthPrice } from './mpEthPriceService';

describe('fetchMpEthPrice test cases', fetchMpEthPriceTestCases);

function fetchMpEthPriceTestCases() {
it('should fetch the price from velodrome subgraph for mpeth', async () => {
const mpEthPrice = await fetchMpEthPrice();
assert.isOk(mpEthPrice);
expect(mpEthPrice).to.gt(0);
});
}
37 changes: 37 additions & 0 deletions src/services/mpEthPriceService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { logger } from '../utils/logger';
import Axios, { AxiosResponse } from 'axios';
import axiosRetry from 'axios-retry';

const mpEthSubgraphUrl = process.env.MPETH_GRAPHQL_PRICES_URL as string;

// Maximum timeout of axios.
const axiosTimeout = 20000;

const query = {
query: `
{
tokens(where:{id:"0x819845b60a192167ed1139040b4f8eca31834f27"}) {
id
name
symbol
decimals
lastPriceUSD
}
}
`,
};

export const fetchMpEthPrice = async () => {
try {
const result = await Axios.post(mpEthSubgraphUrl, query, {
headers: {
'Content-Type': 'application/json',
},
timeout: axiosTimeout,
});
return Number(result.data.data.tokens[0].lastPriceUSD);
} catch (e) {
logger.error('fetching Giv Price fetchGivPrice() err', e);
throw e;
}
};
14 changes: 14 additions & 0 deletions test/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,13 @@ export const SEED_DATA = {
decimals: 18,
isStableCoin: true,
},
{
name: 'mpETH',
symbol: 'mpETH',
address: '0x48afbbd342f64ef8a9ab1c143719b63c2ad81710',
decimals: 18,
isStableCoin: true,
},
],
ropsten: [
{
Expand Down Expand Up @@ -1329,6 +1336,13 @@ export const SEED_DATA = {
decimals: 18,
isStableCoin: true,
},
{
name: 'mpETH',
symbol: 'mpETH',
address: '0x819845b60a192167ed1139040b4f8eca31834f27',
decimals: 18,
isStableCoin: true,
},
],
etc: [
{
Expand Down

0 comments on commit bdcfff4

Please sign in to comment.