Skip to content

Commit

Permalink
Merge pull request #1039 from Giveth/feature_add_optimism_goerli_network
Browse files Browse the repository at this point in the history
Feature add optimism goerli network
  • Loading branch information
mohammadranjbarz authored Jun 26, 2023
2 parents 18298ea + 70c4077 commit bf7474e
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 7 deletions.
2 changes: 1 addition & 1 deletion config/example.env
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ DONATION_VERIFICAITON_EXPIRATION_HOURS=24
# Default: unnamed
SERVICE_NAME=example
OPTIMISM_NODE_HTTP_URL=https://optimism-mainnet.public.blastapi.io/

OPTIMISM_GOERLI_NODE_HTTP_URL=

####################################### INSTANT BOOSTING #################################
# OPTIONAL - default: false
Expand Down
2 changes: 2 additions & 0 deletions config/test.env
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,7 @@ DONATION_VERIFICAITON_EXPIRATION_HOURS=24
# We need it for monoswap
POLYGON_MAINNET_NODE_HTTP_URL=https://polygon-rpc.com
OPTIMISM_NODE_HTTP_URL=https://optimism-mainnet.public.blastapi.io
OPTIMISM_GOERLI_NODE_HTTP_URL=https://optimism-goerli.public.blastapi.io


GITCOIN_ADAPTER=mock
70 changes: 70 additions & 0 deletions migration/1687383705794-AddOptimismGoerliTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { Token } from '../src/entities/token';
import seedTokens from './data/seedTokens';
import { NETWORK_IDS } from '../src/provider';
import config from '../src/config';

export class AddOptimismGoerliTokens1687383705794
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
const environment = config.get('ENVIRONMENT') as string;
if (environment === 'production') {
// We dont add optimism-goerli tokens in production ENV
return;
}

await queryRunner.manager.save(
Token,
seedTokens
.filter(token => token.networkId === NETWORK_IDS.OPTIMISM_GOERLI)
.map(t => {
t.address = t.address?.toLowerCase();
return t;
}),
);
const tokens = await queryRunner.query(`
SELECT * FROM token
WHERE "networkId" = ${NETWORK_IDS.OPTIMISM_GOERLI}
`);
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 environment = config.get('ENVIRONMENT') as string;
if (environment === 'production') {
// We dont add optimism-goerli tokens in production ENV
return;
}

const tokens = await queryRunner.query(`
SELECT * FROM token
WHERE "networkId" = ${NETWORK_IDS.OPTIMISM_GOERLI}
`);
await queryRunner.query(
`DELETE FROM organization_tokens_token WHERE "tokenId" IN (${tokens
.map(token => token.id)
.join(',')})`,
);
await queryRunner.query(
`
DELETE from token
WHERE "networkId" = ${NETWORK_IDS.OPTIMISM_GOERLI}
`,
);
}
}
30 changes: 30 additions & 0 deletions migration/data/seedTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,36 @@ const seedTokens: ITokenData[] = [
networkId: NETWORK_IDS.POLYGON,
},

// OPTIMISM Goerli tokens
{
name: 'OPTIMISM Goerli native token',
symbol: 'ETH',
address: '0x0000000000000000000000000000000000000000',
decimals: 18,
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
},
{
name: 'OPTIMISM Goerli OP token',
symbol: 'OP',
address: '0x4200000000000000000000000000000000000042',
decimals: 18,
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
},
{
name: 'Wrapped Ether',
symbol: 'WETH',
address: '0x4200000000000000000000000000000000000006',
decimals: 18,
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
},
{
name: 'Dai',
symbol: 'DAI',
address: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
decimals: 18,
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
},

// OPTIMISTIC tokens
{
name: 'OPTIMISTIC native token',
Expand Down
17 changes: 17 additions & 0 deletions src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const NETWORK_IDS = {
XDAI: 100,
POLYGON: 137,
OPTIMISTIC: 10,
OPTIMISM_GOERLI: 420,
BSC: 56,
CELO: 42220,
CELO_ALFAJORES: 44787,
Expand All @@ -27,6 +28,7 @@ export const NETWORKS_IDS_TO_NAME = {
42220: 'CELO',
44787: 'CELO_ALFAJORES',
10: 'OPTIMISTIC',
420: 'OPTIMISM_GOERLI',
};

const NETWORK_NAMES = {
Expand All @@ -37,6 +39,7 @@ const NETWORK_NAMES = {
GOERLI: 'goerli',
POLYGON: 'polygon-mainnet',
OPTIMISTIC: 'optimistic-mainnet',
OPTIMISM_GOERLI: 'optimism-goerli-testnet',
CELO: 'Celo',
CELO_ALFAJORES: 'Celo Alfajores',
};
Expand All @@ -49,6 +52,7 @@ const NETWORK_NATIVE_TOKENS = {
GOERLI: 'ETH',
POLYGON: 'MATIC',
OPTIMISTIC: 'ETH',
OPTIMISM_GOERLI: 'ETH',
CELO: 'CELO',
CELO_ALFAJORES: 'CELO',
};
Expand Down Expand Up @@ -89,6 +93,11 @@ const networkNativeTokensList = [
networkId: NETWORK_IDS.OPTIMISTIC,
nativeToken: NETWORK_NATIVE_TOKENS.OPTIMISTIC,
},
{
networkName: NETWORK_NAMES.OPTIMISM_GOERLI,
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
nativeToken: NETWORK_NATIVE_TOKENS.OPTIMISM_GOERLI,
},
{
networkName: NETWORK_NAMES.CELO,
networkId: NETWORK_IDS.CELO,
Expand Down Expand Up @@ -142,6 +151,10 @@ export function getProvider(networkId: number) {
`https://celo-alfajores.infura.io/v3/${INFURA_ID}`;
break;

case NETWORK_IDS.OPTIMISM_GOERLI:
url = `https://optimism-goerli.infura.io/v3/${INFURA_ID}`;
break;

default: {
// Use infura
const connectionInfo = ethers.providers.InfuraProvider.getUrl(
Expand Down Expand Up @@ -203,6 +216,10 @@ export function getBlockExplorerApiUrl(networkId: number): string {
apiUrl = config.get('OPTIMISTIC_SCAN_API_URL');
apiKey = config.get('OPTIMISTIC_SCAN_API_KEY');
break;
case NETWORK_IDS.OPTIMISM_GOERLI:
apiUrl = config.get('OPTIMISTIC_SCAN_API_URL');
apiKey = config.get('OPTIMISTIC_SCAN_API_KEY');
break;
default:
throw new Error(i18n.__(translationErrorMessagesKeys.INVALID_NETWORK_ID));
}
Expand Down
2 changes: 1 addition & 1 deletion src/resolvers/donationResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,7 @@ function createDonationTestCases() {
);
assert.equal(
saveDonationResponse.data.errors[0].message,
'"transactionNetworkId" must be one of [1, 3, 5, 100, 137, 10, 56, 42220, 44787]',
'"transactionNetworkId" must be one of [1, 3, 5, 100, 137, 10, 420, 56, 42220, 44787]',
);
});
it('should throw exception when currency is not valid when currency contain characters', async () => {
Expand Down
20 changes: 15 additions & 5 deletions src/resolvers/donationResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,21 @@ export class DonationResolver {
createDonationQueryValidator,
);

const priceChainId =
transactionNetworkId === NETWORK_IDS.ROPSTEN ||
transactionNetworkId === NETWORK_IDS.GOERLI
? NETWORK_IDS.MAIN_NET
: transactionNetworkId;
let priceChainId: number;
switch (transactionNetworkId) {
case NETWORK_IDS.ROPSTEN:
priceChainId = NETWORK_IDS.MAIN_NET;
break;
case NETWORK_IDS.GOERLI:
priceChainId = NETWORK_IDS.MAIN_NET;
break;
case NETWORK_IDS.OPTIMISM_GOERLI:
priceChainId = NETWORK_IDS.OPTIMISTIC;
break;
default:
priceChainId = transactionNetworkId;
break;
}

const project = await findProjectById(projectId);

Expand Down
1 change: 1 addition & 0 deletions src/server/adminJs/tabs/tokenTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export const generateTokenTab = async () => {
{ value: NETWORK_IDS.GOERLI, label: 'GOERLI' },
{ value: NETWORK_IDS.POLYGON, label: 'POLYGON' },
{ value: NETWORK_IDS.OPTIMISTIC, label: 'OPTIMISTIC' },
{ value: NETWORK_IDS.OPTIMISM_GOERLI, label: 'OPTIMISM GOERLI' },
{ value: NETWORK_IDS.CELO, label: 'CELO' },
{
value: NETWORK_IDS.CELO_ALFAJORES,
Expand Down
44 changes: 44 additions & 0 deletions src/services/donationService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,50 @@ function syncDonationStatusWithBlockchainNetworkTestCases() {
assert.isTrue(updateDonation.segmentNotified);
});

it('should verify a Optimism Goerli donation', async () => {
// https://goerli-optimism.etherscan.io/tx/0x95acfc3a5d1adbc9a4584d6bf92e9dfde48087fe54c2b750b067be718215ffc3
const amount = 0.011;

const transactionInfo = {
txHash:
'0x95acfc3a5d1adbc9a4584d6bf92e9dfde48087fe54c2b750b067be718215ffc3',
currency: 'ETH',
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
fromAddress: '0x317bbc1927be411cd05615d2ffdf8d320c6c4052',
toAddress: '0x00d18ca9782be1caef611017c2fbc1a39779a57c',
amount,
timestamp: 1679484540,
};
const user = await saveUserDirectlyToDb(transactionInfo.fromAddress);
const project = await saveProjectDirectlyToDb({
...createProjectData(),
walletAddress: transactionInfo.toAddress,
});
const donation = await saveDonationDirectlyToDb(
{
amount: transactionInfo.amount,
transactionNetworkId: transactionInfo.networkId,
transactionId: transactionInfo.txHash,
currency: transactionInfo.currency,
fromWalletAddress: transactionInfo.fromAddress,
toWalletAddress: transactionInfo.toAddress,
valueUsd: 20.73,
anonymous: false,
createdAt: new Date(transactionInfo.timestamp),
status: DONATION_STATUS.PENDING,
},
user.id,
project.id,
);
const updateDonation = await syncDonationStatusWithBlockchainNetwork({
donationId: donation.id,
});
assert.isOk(updateDonation);
assert.equal(updateDonation.id, donation.id);
assert.equal(updateDonation.status, DONATION_STATUS.VERIFIED);
assert.isTrue(updateDonation.segmentNotified);
});

it('should verify a mainnet donation', async () => {
// https://etherscan.io/tx/0x37765af1a7924fb6ee22c83668e55719c9ecb1b79928bd4b208c42dfff44da3a
const transactionInfo = {
Expand Down
19 changes: 19 additions & 0 deletions src/services/transactionService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,25 @@ function getTransactionDetailTestCases() {
assert.equal(transactionInfo.amount, amount);
});

it('should return transaction detail for normal transfer on optimism-goerli', async () => {
// https://goerli-optimism.etherscan.io/tx/0x95acfc3a5d1adbc9a4584d6bf92e9dfde48087fe54c2b750b067be718215ffc3

const amount = 0.011;
const transactionInfo = await getTransactionInfoFromNetwork({
txHash:
'0x95acfc3a5d1adbc9a4584d6bf92e9dfde48087fe54c2b750b067be718215ffc3',
symbol: 'ETH',
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
fromAddress: '0x317bbc1927be411cd05615d2ffdf8d320c6c4052',
toAddress: '0x00d18ca9782be1caef611017c2fbc1a39779a57c',
amount,
timestamp: 167740007,
});
assert.isOk(transactionInfo);
assert.equal(transactionInfo.currency, 'ETH');
assert.equal(transactionInfo.amount, amount);
});

it('should return transaction detail for normal transfer on CELO', async () => {
// https://celoscan.io/tx/0xa2a282cf6a7dec8b166aa52ac3d00fcd15a370d414615e29a168cfbb592e3637

Expand Down
1 change: 1 addition & 0 deletions src/utils/validators/graphqlQueryValidators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ const managingFundsValidator = Joi.object({
NETWORK_IDS.CELO,
NETWORK_IDS.CELO_ALFAJORES,
NETWORK_IDS.OPTIMISTIC,
NETWORK_IDS.OPTIMISM_GOERLI,
NETWORK_IDS.XDAI,
),
}),
Expand Down
11 changes: 11 additions & 0 deletions test/pre-test-scripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ async function seedTokens() {
}
await Token.create(tokenData as Token).save();
}
for (const token of SEED_DATA.TOKENS.optimism_goerli) {
const tokenData = {
...token,
networkId: NETWORK_IDS.OPTIMISM_GOERLI,
isGivbackEligible: true,
};
if (token.symbol === 'OP') {
(tokenData as any).order = 2;
}
await Token.create(tokenData as Token).save();
}
}

async function seedOrganizations() {
Expand Down
14 changes: 14 additions & 0 deletions test/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,20 @@ export const SEED_DATA = {
decimals: 18,
},
],
optimism_goerli: [
{
name: 'OPTIMISM native token',
symbol: 'ETH',
address: '0x0000000000000000000000000000000000000000',
decimals: 18,
},
{
name: 'OPTIMISM OP token',
symbol: 'OP',
address: '0x4200000000000000000000000000000000000042',
decimals: 18,
},
],
goerli: [
{
name: 'Ethereum native token',
Expand Down

0 comments on commit bf7474e

Please sign in to comment.