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

V2 API (Sepolia) #717

Merged
merged 4 commits into from
Oct 20, 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
3 changes: 0 additions & 3 deletions .dockerignore

This file was deleted.

4 changes: 3 additions & 1 deletion .github/workflows/generate-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ jobs:
steps:
- name: Checkout source
uses: actions/checkout@v2
with:
submodules: true

- name: Setup Node.js & Yarn
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
cache: yarn
env:
# Workaround for https://github.com/actions/setup-node/issues/317
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "bold"]
path = bold
url = [email protected]:liquity/bold.git
24 changes: 0 additions & 24 deletions Dockerfile

This file was deleted.

1 change: 1 addition & 0 deletions bold
Submodule bold added at cd6030
11 changes: 0 additions & 11 deletions docker-compose.yml

This file was deleted.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"private": true,
"type": "module",
"scripts": {
"start": "ts-node-esm src/index.ts",
"once": "ts-node-esm src/once.ts",
"start": "tsx src/index.ts",
"once": "tsx src/once.ts",
"build": "tsc --project tsconfig.json"
},
"dependencies": {
Expand All @@ -24,7 +24,8 @@
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"eslint": "8.57.1",
"ts-node": "10.9.2",
"tsx": "^4.19.1",
"typescript": "5.6.3"
}
},
"packageManager": "[email protected]+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
}
111 changes: 111 additions & 0 deletions src/AlchemyProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Network, Networkish } from "@ethersproject/networks";
import { defineReadOnly } from "@ethersproject/properties";
import { ConnectionInfo } from "@ethersproject/web";

import {
CommunityResourcable,
showThrottleMessage,
WebSocketProvider,
UrlJsonRpcProvider
} from "@ethersproject/providers";

import { Logger } from "@ethersproject/logger";
const logger = new Logger("providers/5.8.0-custom");

// This key was provided to ethers.js by Alchemy to be used by the
// default provider, but it is recommended that for your own
// production environments, that you acquire your own API key at:
// https://dashboard.alchemyapi.io

const defaultApiKey = "_gg7wSSi0KMBsdKnGVfHDueq6xMB9EkC";

export class AlchemyWebSocketProvider extends WebSocketProvider implements CommunityResourcable {
readonly apiKey!: string;

constructor(network?: Networkish, apiKey?: any) {
const provider = new AlchemyProvider(network, apiKey);

const url = provider.connection.url
.replace(/^http/i, "ws")
.replace(".alchemyapi.", ".ws.alchemyapi.");

super(url, provider.network);
defineReadOnly(this, "apiKey", provider.apiKey);
}

isCommunityResource(): boolean {
return this.apiKey === defaultApiKey;
}
}

export class AlchemyProvider extends UrlJsonRpcProvider {
static getWebSocketProvider(network?: Networkish, apiKey?: any): AlchemyWebSocketProvider {
return new AlchemyWebSocketProvider(network, apiKey);
}

static getApiKey(apiKey: any): any {
if (apiKey == null) {
return defaultApiKey;
}
if (apiKey && typeof apiKey !== "string") {
logger.throwArgumentError("invalid apiKey", "apiKey", apiKey);
}
return apiKey;
}

static getUrl(network: Network, apiKey: string): ConnectionInfo {
let host = null;
switch (network.name) {
case "homestead":
host = "eth-mainnet.alchemyapi.io/v2/";
break;
case "goerli":
host = "eth-goerli.g.alchemy.com/v2/";
break;
case "sepolia":
host = "eth-sepolia.g.alchemy.com/v2/";
break;
case "matic":
host = "polygon-mainnet.g.alchemy.com/v2/";
break;
case "maticmum":
host = "polygon-mumbai.g.alchemy.com/v2/";
break;
case "arbitrum":
host = "arb-mainnet.g.alchemy.com/v2/";
break;
case "arbitrum-goerli":
host = "arb-goerli.g.alchemy.com/v2/";
break;
case "arbitrum-sepolia":
host = "arb-sepolia.g.alchemy.com/v2/";
break;
case "optimism":
host = "opt-mainnet.g.alchemy.com/v2/";
break;
case "optimism-goerli":
host = "opt-goerli.g.alchemy.com/v2/";
break;
case "optimism-sepolia":
host = "opt-sepolia.g.alchemy.com/v2/";
break;
default:
logger.throwArgumentError("unsupported network", "network", arguments[0]);
}

return {
allowGzip: true,
url: "https:/" + "/" + host + apiKey,
throttleCallback: (attempt: number, url: string) => {
if (apiKey === defaultApiKey) {
showThrottleMessage();
}
return Promise.resolve(true);
}
};
}

isCommunityResource(): boolean {
return this.apiKey === defaultApiKey;
}
}
12 changes: 6 additions & 6 deletions src/connection.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { AlchemyProvider } from "@ethersproject/providers";
import type { Provider } from "@ethersproject/abstract-provider";
import { Networkish, getNetwork } from "@ethersproject/networks";
import { EthersLiquity } from "@liquity/lib-ethers";
import { Batched, WebSocketAugmented } from "@liquity/providers";

import { AlchemyProvider } from "./AlchemyProvider.js";

const BatchedWebSocketAugmentedAlchemyProvider = Batched(WebSocketAugmented(AlchemyProvider));

export interface LiquityConnectionOptions {
alchemyApiKey?: string;
useWebSocket?: boolean;
}

export const connectToLiquity = (
export const getProvider = (
networkish: Networkish,
options?: LiquityConnectionOptions
): Promise<EthersLiquity> => {
): Provider => {
const network = getNetwork(networkish);
const provider = new BatchedWebSocketAugmentedAlchemyProvider(network, options?.alchemyApiKey);
const liquity = EthersLiquity.connect(provider);

provider.chainId = network.chainId;

Expand All @@ -27,5 +27,5 @@ export const connectToLiquity = (
);
}

return liquity;
return provider;
};
8 changes: 4 additions & 4 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import path from "path";
import { Decimal } from "@liquity/lib-base";

export const DEFAULT_SERVER_PORT = 8080;
export const DEFAULT_NETWORK = "mainnet";

export const DEFAULT_OUTPUT_DIR = "docs/v1";
export const OUTPUT_DIR = "docs";
export const OUTPUT_DIR_V1 = path.join(OUTPUT_DIR, "v1");
export const OUTPUT_DIR_V2 = path.join(OUTPUT_DIR, "v2");
export const LQTY_CIRCULATING_SUPPLY_FILE = "lqty_circulating_supply.txt";
export const LUSD_TOTAL_SUPPLY_FILE = "lusd_total_supply.txt";
export const LUSD_CB_BAMM_STATS_FILE = "lusd_cb_bamm_stats.json";
Expand Down
25 changes: 0 additions & 25 deletions src/index.ts

This file was deleted.

72 changes: 61 additions & 11 deletions src/once.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import fs from "fs";
import path from "path";
import util from "util";
import { EthersLiquity } from "@liquity/lib-ethers";

import { connectToLiquity } from "./connection.js";
import { getProvider } from "./connection.js";
import { fetchLQTYCirculatingSupply } from "./fetchLQTYCirculatingSupply.js";
import { fetchLUSDTotalSupply } from "./fetchLUSDTotalSupply.js";
import { fetchLUSDCBBAMMStats } from "./fetchLUSDCBBAMMStats.js";
import { fetchV2Stats } from "./v2/fetchV2Stats.js";
// import v2MainnetAddresses from "../bold/contracts/addresses/1.json";
import v2SepoliaAddresses from "../bold/contracts/addresses/11155111.json";

import {
DEFAULT_NETWORK,
DEFAULT_OUTPUT_DIR,
OUTPUT_DIR_V1,
OUTPUT_DIR_V2,
LQTY_CIRCULATING_SUPPLY_FILE,
LUSD_CB_BAMM_STATS_FILE,
LUSD_TOTAL_SUPPLY_FILE
Expand All @@ -21,27 +26,72 @@ const panic = <T>(message: string): T => {
const alchemyApiKey = process.env.ALCHEMY_API_KEY || undefined; // filter out empty string
const transposeApiKey: string = process.env.TRANSPOSE_API_KEY || panic("missing TRANSPOSE_API_KEY");

const outputDir = DEFAULT_OUTPUT_DIR;
const lqtyCirculatingSupplyFile = path.join(outputDir, LQTY_CIRCULATING_SUPPLY_FILE);
const lusdTotalSupplyFile = path.join(outputDir, LUSD_TOTAL_SUPPLY_FILE);
const lusdCBBAMMStatsFile = path.join(outputDir, LUSD_CB_BAMM_STATS_FILE);
const lqtyCirculatingSupplyFile = path.join(OUTPUT_DIR_V1, LQTY_CIRCULATING_SUPPLY_FILE);
const lusdTotalSupplyFile = path.join(OUTPUT_DIR_V1, LUSD_TOTAL_SUPPLY_FILE);
const lusdCBBAMMStatsFile = path.join(OUTPUT_DIR_V1, LUSD_CB_BAMM_STATS_FILE);

connectToLiquity(DEFAULT_NETWORK, { alchemyApiKey })
const mainnetProvider = getProvider("mainnet", { alchemyApiKey });
const sepoliaProvider = getProvider("sepolia", { alchemyApiKey });

interface Tree extends Record<string, string | Tree> {}

const writeTree = (parentDir: string, tree: Tree) => {
if (!fs.existsSync(parentDir)) fs.mkdirSync(parentDir);

for (const [k, v] of Object.entries(tree)) {
const prefix = path.join(parentDir, k);

if (typeof v === "string") {
fs.writeFileSync(`${prefix}.txt`, v);
} else {
writeTree(prefix, v);
}
}
};

EthersLiquity.connect(mainnetProvider)
.then(async liquity => {
const [lqtyCirculatingSupply, lusdTotalSupply, lusdCBBAMMStats] = await Promise.all([
const [
lqtyCirculatingSupply,
lusdTotalSupply,
lusdCBBAMMStats,
// v2MainnetStats,
v2SepoliaStats
] = await Promise.all([
fetchLQTYCirculatingSupply(liquity),
fetchLUSDTotalSupply(liquity),
fetchLUSDCBBAMMStats(transposeApiKey)
fetchLUSDCBBAMMStats(transposeApiKey),
// fetchV2Stats(mainnetProvider, v2MainnetAddresses),
fetchV2Stats(sepoliaProvider, v2SepoliaAddresses)
]);

fs.mkdirSync(outputDir, { recursive: true });
const v2Stats = {
// ...v2MainnetStats,
testnet: {
sepolia: v2SepoliaStats
}
};

fs.mkdirSync(OUTPUT_DIR_V1, { recursive: true });
fs.writeFileSync(lqtyCirculatingSupplyFile, `${lqtyCirculatingSupply}`);
fs.writeFileSync(lusdTotalSupplyFile, `${lusdTotalSupply}`);
fs.writeFileSync(lusdCBBAMMStatsFile, JSON.stringify(lusdCBBAMMStats));

writeTree(OUTPUT_DIR_V2, v2Stats);
// fs.writeFileSync(
// path.join(OUTPUT_DIR_V2, "mainnet.json"),
// JSON.stringify(v2MainnetStats, null, 2)
// );
fs.writeFileSync(
path.join(OUTPUT_DIR_V2, "testnet", "sepolia.json"),
JSON.stringify(v2SepoliaStats, null, 2)
);

console.log(`LQTY circulating supply: ${lqtyCirculatingSupply}`);
console.log(`LUSD total supply: ${lusdTotalSupply}`);
console.log("LUSD CB BAMM stats:", lusdCBBAMMStats);
console.log();
console.log("v2 stats:", util.inspect(v2Stats, { colors: true, depth: null }));
})
.catch(error => {
console.error(error);
Expand Down
Loading
Loading