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

[API] ICR API Integration #2051

Merged
merged 1 commit into from
Jan 22, 2024
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 carbonmark-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@klimadao/carbonmark-api",
"version": "5.2.1",
"version": "5.3.0",
"description": "An API for exploring Carbonmark project data, prices and activity.",
"main": "app.ts",
"scripts": {
Expand Down
1,070 changes: 1,070 additions & 0 deletions carbonmark-api/src/.generated/mocks/icr.mocks.ts

Large diffs are not rendered by default.

1,749 changes: 1,749 additions & 0 deletions carbonmark-api/src/.generated/types/icr.types.ts

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions carbonmark-api/src/app.constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { NetworkParam } from "./models/NetworkParam.model";

/** Adhere to JSONSchema spec by using a URI */
export const COMMON_SCHEMA_URI = "http://api.carbonmark.com/schemas";

Expand All @@ -14,11 +16,14 @@ const POLYGON_URLS = {
assets: `${GRAPH_API_ROOT}/cujowolf/klima-refi-current-holdings`,
tokens: `${GRAPH_API_ROOT}/klimadao/klimadao-pairs`,
digitalCarbon: `${GRAPH_API_ROOT}/klimadao/polygon-digital-carbon`,
icr: `${GRAPH_API_ROOT}/skjaldbaka17/carbon-registry-polygon`,
0xemc marked this conversation as resolved.
Show resolved Hide resolved
};

const MUMBAI_URLS = {
...POLYGON_URLS,
digitalCarbon: `${GRAPH_API_ROOT}/psparacino/digital-carbon`,
marketplace: `${GRAPH_API_ROOT_ID}/QmUUnZTeRnfsJsQaTwLeiHmAQ5xvtk2jBW7VeP3AEW5bnv`,
icr: `${GRAPH_API_ROOT}/skjaldbaka17/carbon-registry-test`,
};

/** Sanity URLS */
Expand Down Expand Up @@ -59,3 +64,51 @@ export const TOKEN_ADDRESSES = {
export const RPC_URLS = {
polygonTestnetRpc: "https://rpc-mumbai.maticvigil.com",
};

/** Definitions of available registries */
export const REGISTRIES = {
Verra: {
id: "VCS",
title: "Verra",
url: "https://registry.verra.org",
api: "https://registry.verra.org/uiapi",
},
GoldStandard: {
id: "GS",
title: "Gold Standard",
url: "https://registry.goldstandard.org",
},
ICR: {
id: "ICR",
title: "International Carbon Registry",
url: "https://www.carbonregistry.com",
},
};

export const ICR_API = (
network?: NetworkParam
): { ICR_API_URL: string; ICR_API_KEY: string } => {
const ICR_CONFIG = {
polygon: {
url: "https://api.carbonregistry.com/v0",
apiKey: process.env.ICR_MAINNET_API_KEY,
},
mumbai: {
url: "https://gaia-api-dev.mojoflower.io/v0",
apiKey: process.env.ICR_MUMBAI_API_KEY,
},
};

const VALIDATED_NETWORK: NetworkParam =
network === "polygon" || network === "mumbai" ? network : "polygon";

const API_CONFIG = ICR_CONFIG["polygon"];

if (!API_CONFIG.apiKey) {
throw new Error(
`ICR api key is undefined for network: ${VALIDATED_NETWORK}`
);
}

return { ICR_API_URL: API_CONFIG.url, ICR_API_KEY: API_CONFIG.apiKey };
};
26 changes: 26 additions & 0 deletions carbonmark-api/src/graphql/icr.fragments.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
fragment ICRProjectFragment on Project {
id
projectAddress
projectName
transactionHash
}

fragment exPostAmountsFragment on ExPostHolder {
id
amount
updatedAt
retiredAmount
exPost {
...exPostFragment
}
}

fragment exPostFragment on ExPost {
tokenId
vintage
serialization
project {
id
projectName
}
}
27 changes: 27 additions & 0 deletions carbonmark-api/src/graphql/icr.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
query getExPostInfoViaSerialization($serialization: String!) {
exPosts(where: { serialization: $serialization }) {
serialization
supply
retiredAmount
estimatedAmount
cancelledAmount
id
lastVerificationTimestamp
project {
...ICRProjectFragment
}
tokenId
verificationPeriodEnd
verificationPeriodStart
vintage
}
}

query getHoldingsByAddress($id: ID!) {
holder(id: $id) {
id
exPostAmounts {
...exPostAmountsFragment
}
}
}
1 change: 1 addition & 0 deletions carbonmark-api/src/models/Asset.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const AssetModel = Type.Object({
name: Type.String(),
symbol: Type.String(),
decimals: Type.Number(),
tokenId: Type.Optional(Type.String()),
}),
amount: Type.String(),
});
Expand Down
2 changes: 2 additions & 0 deletions carbonmark-api/src/models/Project.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export const ProjectModel = Type.Object({
)
),
hasSupply: Type.Boolean(),
tokenId: Type.Optional(Type.String()),
serialization: Type.Optional(Type.String()),
psparacino marked this conversation as resolved.
Show resolved Hide resolved
});

export type Project = Static<typeof ProjectModel>;
3 changes: 3 additions & 0 deletions carbonmark-api/src/models/Purchase.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const PurchaseModel = Type.Object({
vintage: Type.String({
examples: ["2008"],
}),
serialization: Type.Optional(
Type.String({ examples: ["ICR-ISL-354-78040-14-R-0-2021"] })
),
0xemc marked this conversation as resolved.
Show resolved Hide resolved
}),
}),
price: Type.String({
Expand Down
3 changes: 2 additions & 1 deletion carbonmark-api/src/routes/activities/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ const handler = (fastify: FastifyInstance) =>
}>,
reply: FastifyReply
): Promise<Activity[]> {
const network = request.query.network ?? "polygon";
return asResponse(
reply,
await getActivities(fastify, request.query, request.query.network)
await getActivities(fastify, request.query, network)
);
};

Expand Down
5 changes: 3 additions & 2 deletions carbonmark-api/src/routes/countries/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const handler = (
): RouteHandler<{ Querystring: Static<typeof Querystring> }> =>
async function (request, reply) {
let response;
const sdk = gql_sdk(request.query.network);
const network = request.query.network ?? "polygon";
const sdk = gql_sdk(network);
try {
response = await getAllCountries(sdk, fastify);
response = await getAllCountries(sdk, fastify, network);
psparacino marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
//Return bad gateway and pass the error
console.error(error);
Expand Down
4 changes: 3 additions & 1 deletion carbonmark-api/src/routes/projects/[id]/activity/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ const handler = (fastify: FastifyInstance) =>
reply: FastifyReply
): Promise<Activity[]> {
request.query.projectId = [request.params.id];

const network = request.query.network ?? "polygon";
return asResponse(
reply,
await getActivities(fastify, request.query, request.query.network)
await getActivities(fastify, request.query, network)
);
};

Expand Down
2 changes: 1 addition & 1 deletion carbonmark-api/src/routes/projects/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const handler = (fastify: FastifyInstance) =>
);

//Get the default args to return all results unless specified
const allOptions = await getDefaultQueryArgs(sdk, fastify);
const allOptions = await getDefaultQueryArgs(sdk, fastify, network);

const [
marketplaceProjectsData,
Expand Down
15 changes: 9 additions & 6 deletions carbonmark-api/src/routes/projects/get.utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FastifyInstance } from "fastify";
import { compact, isNil, max, maxBy } from "lodash";
import { concat, map, mapValues, min, pipe, trim, uniq } from "lodash/fp";
import { NetworkParam } from "src/models/NetworkParam.model";
import { TokenPriceT } from "src/models/TokenPrice.model";
import { Geopoint } from "../../.generated/types/cms.types";
import {
Expand Down Expand Up @@ -41,15 +42,16 @@ import { formatListings } from "../../utils/marketplace.utils";
* # this will cause a silent error. GQL Resolver needs to be updated to allow null search params
* # to return all possible values
*/

export const getDefaultQueryArgs = async (
sdk: GQL_SDK,
fastify: FastifyInstance
fastify: FastifyInstance,
network: NetworkParam
) => {
//Fetch all possible parameter values
const [category, country, vintage] = await Promise.all([
getAllCategories(sdk, fastify).then(map(extract("id"))),
getAllCountries(sdk, fastify).then(map(extract("id"))),
getAllVintages(sdk, fastify),
getAllCountries(sdk, fastify, network).then(map(extract("id"))),
getAllVintages(sdk, fastify, network),
]);

return {
Expand Down Expand Up @@ -113,7 +115,7 @@ export const buildProjectEntry = (props: {
poolProject?: GetProjectCreditsQuery["carbonProjects"][0];
cmsProject?: CarbonProject;
allPoolPrices: Record<string, PoolPrice>;
network: "polygon" | "mumbai" | undefined;
network: NetworkParam | undefined;
minSupply: number;
}): Project => {
const credits = props.poolProject?.carbonCredits;
Expand Down Expand Up @@ -219,7 +221,7 @@ export const composeProjectEntries = (
projectDataMap: ProjectDataMap,
cmsDataMap: CMSDataMap,
allPoolPrices: Record<string, PoolPrice>,
network: "polygon" | "mumbai" | undefined,
network: NetworkParam | undefined,
minSupply: number
): Project[] => {
const entries: Project[] = [];
Expand All @@ -243,5 +245,6 @@ export const composeProjectEntries = (
// TODO: Maybe this should be controlled via a query parameter
if (project.hasSupply) entries.push(project);
});

return entries;
};
6 changes: 4 additions & 2 deletions carbonmark-api/src/routes/purchases/[id]/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ const handler = async (
if (!isValidPurchaseId(request.params.id)) {
return reply.badRequest("Invalid purchase id: " + request.params.id);
}
const sdk = gql_sdk(request.query.network);
const { purchase } = await sdk.marketplace.getPurchaseById(request.params);
const network = request.query.network ?? "polygon";

const sdk = gql_sdk(network);

const { purchase } = await sdk.marketplace.getPurchaseById(request.params);
/** Handle the not found case */
if (isNil(purchase)) {
return reply.status(404).send({ error: "Purchase not found" });
Expand Down
4 changes: 3 additions & 1 deletion carbonmark-api/src/routes/purchases/get.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export const composePurchaseModel = (
const [, registryProjectId] = CreditId.splitProjectId(project.key);
return {
id: purchase.id,
amount: utils.formatUnits(purchase.amount, 18),
amount: purchase.listing.project.key.startsWith("ICR")
? purchase.amount
: utils.formatUnits(purchase.amount, 18),
price: utils.formatUnits(purchase.price, 6),
listing: {
id: purchase.listing.id,
Expand Down
13 changes: 9 additions & 4 deletions carbonmark-api/src/routes/users/[walletOrHandle]/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const handler = (fastify: FastifyInstance) =>
try {
const { query, params } = request;

const network = query.network ?? "polygon";
const walletOrHandle = params.walletOrHandle.toLowerCase();

// Fetch the firebase UserProfile first
Expand All @@ -53,12 +54,12 @@ const handler = (fastify: FastifyInstance) =>
const [user, assets] = await Promise.all([
getUserByWallet({
address: profile.address,
network: query.network,
network: network,
expiresAfter: query.expiresAfter,
}),
getHoldingsByWallet({
address: profile.address,
network: query.network,
network: network,
}),
]);

Expand All @@ -83,9 +84,13 @@ const handler = (fastify: FastifyInstance) =>
};
return {
...a,
amount: utils.formatUnits(a.amount || "0", 18),
amount: a.project.key.startsWith("ICR")
biwano marked this conversation as resolved.
Show resolved Hide resolved
? a.amount
: utils.formatUnits(a.amount || "0", 18),
price: utils.formatUnits(a.price || "0", 6),
previousAmount: utils.formatUnits(a.previousAmount || "0", 18),
previousAmount: a.project.key.startsWith("ICR")
? a.previousAmount
: utils.formatUnits(a.previousAmount || "0", 18),
biwano marked this conversation as resolved.
Show resolved Hide resolved
previousPrice: utils.formatUnits(a.previousPrice || "0", 6),
buyer: buyer || null,
seller: seller || null,
Expand Down
Loading