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

Feature add optimism goerli network #1039

Merged
merged 8 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
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
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;
}),
);
Comment on lines +17 to +25
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you need to add a condition to not add these test tokens in production env

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