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

Feat: stellar integration #1753

Merged
merged 15 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 12 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
4 changes: 4 additions & 0 deletions config/example.env
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,8 @@ ZKEVM_MAINNET_NODE_HTTP_URL=
# ZKEVM CARDONA we should fill it as Infura doesnt support polygon zkevm
ZKEVM_CARDONA_NODE_HTTP_URL=

# STELLAR
STELLAR_HORIZON_API_URL=https://horizon.stellar.org
STELLAR_SCAN_API_URL=https://stellar.expert/explorer/public

ENDAOMENT_ADMIN_WALLET_ADDRESS=0xfE3524e04E4e564F9935D34bB5e80c5CaB07F5b4
4 changes: 4 additions & 0 deletions config/test.env
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,8 @@ ZKEVM_MAINNET_NODE_HTTP_URL=https://polygon-zkevm.drpc.org
# ZKEVM CARDONA we should fill it as Infura doesnt support polygon zkevm, I found this rpc link from https://chainlist.org/chain/2442
ZKEVM_CARDONA_NODE_HTTP_URL=https://rpc.cardona.zkevm-rpc.com

# STELLAR
STELLAR_HORIZON_API_URL=https://horizon.stellar.org
STELLAR_SCAN_API_URL=https://stellar.expert/explorer/public

ENDAOMENT_ADMIN_WALLET_ADDRESS=0xfE3524e04E4e564F9935D34bB5e80c5CaB07F5b4
17 changes: 17 additions & 0 deletions migration/1722379846122-AddMemoToProjectAddressFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddMemoToProjectAddressFields1722379846122
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project_address" ADD COLUMN IF NOT EXISTS "memo" VARCHAR`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project_address" DROP COLUMN IF EXISTS "memo"`,
);
}
}
69 changes: 69 additions & 0 deletions migration/1722475689162-AddStellarTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import { Token } from '../src/entities/token';
import seedTokens from './data/seedTokens';
import { NETWORK_IDS } from '../src/provider';

export class AddStellarTokens1722475689162 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const networkId = NETWORK_IDS.STELLAR_MAINNET;

//add isQR code to token
await queryRunner.query(
`ALTER TABLE token ADD COLUMN IF NOT EXISTS "isQR" BOOLEAN DEFAULT FALSE NOT NULL`,
);

await queryRunner.manager.save(
Token,
seedTokens
.filter(token => token.networkId === networkId)
.map(token => {
const t = {
...token,
};
t.address = t.address?.toUpperCase();
return t;
}),
);
const tokens = await queryRunner.query(`
SELECT * FROM token
WHERE "networkId" = ${networkId}
`);
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) {
// Add all Stellar tokens to Giveth organization
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 networkId = NETWORK_IDS.STELLAR_MAINNET;

await queryRunner.query(`ALTER TABLE token DROP COLUMN IF EXISTS "isQR"`);

const tokens = await queryRunner.query(`
SELECT * FROM token
WHERE "networkId" = ${networkId}
`);

for (const token of tokens) {
await queryRunner.query(
`DELETE FROM organization_tokens_token WHERE "tokenId" = ${token.id}`,
);
}
await queryRunner.query(
`DELETE FROM token WHERE "networkId" = ${networkId}`,
);
}
}
39 changes: 39 additions & 0 deletions migration/1722800845343-AddDraftDonationQRFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddDraftDonationQRFields1722800845343
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE draft_donation
ADD COLUMN IF NOT EXISTS "toWalletMemo" VARCHAR NULL,
ADD COLUMN IF NOT EXISTS "qrCodeDataUrl" TEXT NULL,
ADD COLUMN IF NOT EXISTS "isQRDonation" BOOLEAN DEFAULT FALSE;
`);

// update enum draft_donation_chaintype_enum (add 'STELLAR');
await queryRunner.query(
`ALTER TYPE public.draft_donation_chaintype_enum ADD VALUE IF NOT EXISTS 'STELLAR';`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE draft_donation
DROP COLUMN IF EXISTS "toWalletMemo",
DROP COLUMN IF EXISTS "qrCodeDataUrl",
DROP COLUMN IF EXISTS "isQRDonation";
`);

// update enum draft_donation_chaintype_enum (remove 'STELLAR');
await queryRunner.query(`
DELETE FROM pg_enum
WHERE enumlabel = 'STELLAR'
AND enumtypid = (
SELECT oid
FROM pg_type
WHERE typname = 'draft_donation_chaintype_enum'
);
`);
}
}
35 changes: 35 additions & 0 deletions migration/1722860378721-UpdateDraftDonationIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class UpdateDraftDonationIndex1722860378721
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_af180374473ea402e7595196a6"`);
await queryRunner.query(`
CREATE UNIQUE INDEX IF NOT EXISTS "IDX_af180374473ea402e7595196a6"
ON public.draft_donation USING btree
("fromWalletAddress" COLLATE pg_catalog."default" ASC NULLS LAST,
"toWalletAddress" COLLATE pg_catalog."default" ASC NULLS LAST,
"networkId" ASC NULLS LAST,
amount ASC NULLS LAST,
currency COLLATE pg_catalog."default" ASC NULLS LAST)
TABLESPACE pg_default
WHERE status = 'pending'::draft_donation_status_enum AND "isQRDonation" = false;
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_af180374473ea402e7595196a6"`);
await queryRunner.query(`
CREATE UNIQUE INDEX IF NOT EXISTS "IDX_af180374473ea402e7595196a6"
ON public.draft_donation USING btree
("fromWalletAddress" COLLATE pg_catalog."default" ASC NULLS LAST,
"toWalletAddress" COLLATE pg_catalog."default" ASC NULLS LAST,
"networkId" ASC NULLS LAST,
amount ASC NULLS LAST,
currency COLLATE pg_catalog."default" ASC NULLS LAST)
TABLESPACE pg_default
WHERE status = 'pending'::draft_donation_status_enum;
`);
}
}
30 changes: 30 additions & 0 deletions migration/1722963339892-UpdateDonationIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class UpdateDonationIndex1722963339892 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
// update donation table
await queryRunner.query(`
ALTER TABLE "donation"
ADD COLUMN IF NOT EXISTS "isQRDonation" boolean DEFAULT false,
ADD COLUMN IF NOT EXISTS "toWalletMemo" text;
`);

await queryRunner.query(`DROP INDEX "idx_donation_project_user"`);
await queryRunner.query(
`CREATE INDEX IF NOT EXISTS idx_donation_project_user ON donation("projectId", "userId", "valueUsd") WHERE "status" = 'verified' AND "recurringDonationId" IS NULL AND "isQRDonation" = false AND "userId" IS NOT NULL`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "idx_donation_project_user"`);
await queryRunner.query(
`CREATE INDEX IF NOT EXISTS idx_donation_project_user ON donation("projectId", "userId", "valueUsd") WHERE "status" = 'verified' AND "recurringDonationId" IS NULL`,
);

await queryRunner.query(`
ALTER TABLE "donation"
DROP COLUMN IF EXISTS "isQRDonation",
DROP COLUMN IF EXISTS "toWalletMemo";
`);
}
}
17 changes: 17 additions & 0 deletions migration/1723025859680-AddExpirationDateToDraftDonation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddExpirationDateToDraftDonation1723025859680
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE draft_donation ADD COLUMN IF NOT EXISTS "expiresAt" TIMESTAMP`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE draft_donation DROP COLUMN IF EXISTS "expiresAt"`,
);
}
}
13 changes: 13 additions & 0 deletions migration/data/seedTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface ITokenData {
chainType?: ChainType;
coingeckoId?: string;
isStableCoin?: boolean;
isQR?: boolean;
}

const seedTokens: ITokenData[] = [
Expand Down Expand Up @@ -2076,6 +2077,18 @@ const seedTokens: ITokenData[] = [
isGivbackEligible: false,
networkId: NETWORK_IDS.ZKEVM_MAINNET,
},

// Stellar Mainnet
{
name: 'Stellar Lumens',
symbol: 'XLM',
decimals: 7,
address: 'CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA',
coingeckoId: 'stellar',
networkId: NETWORK_IDS.STELLAR_MAINNET,
chainType: ChainType.STELLAR,
isQR: true,
},
];

export default seedTokens;
Loading