Skip to content

Commit cbd7f54

Browse files
committed
feat: legacy deployments
build: fix "include" paths in tsconfig.json build: update tsconfig ci: cron job for JSON-RPC tests feat: add Ronin chain feat: functions to retrieve all contracts fix: latest version for Flow refactor: move indexers logic refactor: split helpers into separate getters refactor: import from specific subfolders refactor: use @internal to skip some logic from the dist bundle test: run chains tests only when env var is set
1 parent 1db36c6 commit cbd7f54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+536
-311
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: "Cron: Test Chains"
2+
3+
on:
4+
schedule:
5+
# Runs at 02:00 UTC every day
6+
- cron: "0 2 * * *"
7+
workflow_dispatch:
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: "Check out the repo"
14+
uses: "actions/checkout@v4"
15+
16+
- name: "Install Bun"
17+
uses: "oven-sh/setup-bun@v2"
18+
with:
19+
bun-version: "latest"
20+
21+
- name: "Install the Node.js dependencies"
22+
run: "bun install --frozen-lockfile"
23+
24+
- name: "Check the code"
25+
run: "bun run check"
26+
27+
- name: "Run the tests"
28+
env:
29+
TEST_JSON_RPC: true
30+
run: "bun run test --retry 5 --testTimeout 60000" # run tests with 5 retries and 60 seconds of timeout
31+
32+
- name: "Add summary"
33+
run: | # shell
34+
echo "## Test Chains result" >> $GITHUB_STEP_SUMMARY
35+
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@sablier/deployments",
33
"description": "Keeping track of Sablier deployments",
4-
"version": "1.0.0-alpha.15",
4+
"version": "1.0.0-alpha.16",
55
"author": {
66
"name": "Sablier Labs Ltd",
77
"url": "https://sablier.com"
@@ -62,7 +62,7 @@
6262
"test:ui": "vitest --silent --ui",
6363
"test:watch": "vitest --silent",
6464
"tsc:build": "tsc -p tsconfig.build.json && bun tsc-alias -p tsconfig.build.json",
65-
"tsc:check": "tsc -p tsconfig.build.json --noEmit"
65+
"tsc:check": "tsc -p tsconfig.json --noEmit"
6666
},
6767
"types": "./dist/index.d.ts"
6868
}

scripts/print-aliases.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { releases } from "@src/releases";
2-
import { isLockupV1Release } from "@src/types";
32
import _ from "lodash";
43
import logger from "./logger";
54

@@ -21,7 +20,7 @@ async function main() {
2120
let contractName: string;
2221

2322
// Lockup v1.x has core/periphery structure, others are flat
24-
if (isLockupV1Release(release)) {
23+
if (release.kind === "lockupV1") {
2524
// Type cast the manifest to ManifestLockupV1
2625
const manifest = release.manifest;
2726
contractName = _.get(manifest.core, key) || _.get(manifest.periphery, key) || key;

scripts/print-missing-broadcasts.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
* bun run scripts/missing-broadcasts.ts flow
99
* bun run scripts/missing-broadcasts.ts lockup
1010
*/
11-
import { getChain, releasesByProtocol } from "@src";
11+
import { getChain } from "@src/chains";
12+
import { releasesByProtocol } from "@src/releases";
1213
import type { Sablier } from "@src/types";
13-
import { isLockupV1Release } from "@src/types";
1414
import _ from "lodash";
1515
import { checkBroadcast, checkZKBroadcast } from "./check-broadcast";
1616
import logger from "./logger";
@@ -30,9 +30,9 @@ type BroadcastType = Sablier.Protocol;
3030

3131
function parseArgs(): BroadcastType {
3232
const protocol = process.argv[2] as BroadcastType;
33-
const validProtocols: BroadcastType[] = ["flow", "airdrops", "lockup"];
33+
const validProtocols: BroadcastType[] = ["airdrops", "flow", "legacy", "lockup"];
3434
if (!protocol || !validProtocols.includes(protocol)) {
35-
logger.error("Error: Please provide one of these protocols: flow, airdrops, or lockup");
35+
logger.error("Error: Please provide one of these protocols: airdrops, flow, legacy, lockup");
3636
process.exit(1);
3737
}
3838

@@ -65,20 +65,28 @@ async function checkMissingBroadcasts(): Promise<void> {
6565
for (const deployment of release.deployments) {
6666
const chain = getChain(deployment.chainId);
6767

68-
// TODO
69-
if (isLockupV1Release(release)) {
68+
let hasValidBroadcasts = false;
69+
70+
if (release.kind === "lockupV1") {
71+
const components = ["core", "periphery"];
72+
hasValidBroadcasts = await Promise.all(
73+
components.map((component) =>
74+
chain.isZK ? checkZKBroadcast(release, chain, component) : checkBroadcast(release, chain, component),
75+
),
76+
).then((results) => results.every(Boolean));
7077
} else {
7178
const paths = chain.isZK
7279
? await checkZKBroadcast(release, chain, "")
7380
: await checkBroadcast(release, chain, "");
81+
hasValidBroadcasts = !!paths;
82+
}
7483

75-
// Note: for LockupV1, we expect both core and periphery paths to exist.
76-
if (!paths) {
77-
if (!missing[release.version]) {
78-
missing[release.version] = [];
79-
}
80-
missing[release.version].push(chain);
84+
// Add to missing list if broadcasts aren't valid
85+
if (!hasValidBroadcasts) {
86+
if (!missing[release.version]) {
87+
missing[release.version] = [];
8188
}
89+
missing[release.version].push(chain);
8290
}
8391
}
8492
}

src/chains/ids.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const ChainId = {
2020
MORPH: 2818,
2121
OP_MAINNET: 10,
2222
POLYGON: 137,
23+
RONIN: 2020,
2324
SCROLL: 534352,
2425
SEI: 1329,
2526
SUPERSEED: 5330,

src/chains/index.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,21 @@ import { mainnets, mainnetsById } from "./mainnets";
1414
import { testnets, testnetsById } from "./testnets";
1515

1616
export { mainnets, mainnetsById, testnets, testnetsById };
17-
export const all: Sablier.Chain[] = [...mainnets, ...testnets];
18-
export const allById: Record<number, Sablier.Chain> = { ...mainnetsById, ...testnetsById };
17+
export const chains: Sablier.Chain[] = [...mainnets, ...testnets];
18+
export const chainsById: Record<number, Sablier.Chain> = { ...mainnetsById, ...testnetsById };
19+
20+
export function getChain(chainId: number | string): Sablier.Chain {
21+
const chain = chainsById[Number(chainId)];
22+
if (!chain) {
23+
throw new Error(`Chain with ID ${chainId} not found`);
24+
}
25+
return chain;
26+
}
27+
28+
export function getChainName(chainId: number | string): string {
29+
const chainName = chainsById[Number(chainId)].name;
30+
if (!chainName) {
31+
throw new Error(`Chain with ID ${chainId} not found`);
32+
}
33+
return chainName;
34+
}

src/chains/mainnets.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,19 @@ export const mainnetsById: Record<number, Sablier.Chain> = {
281281
public: "https://polygon-bor.publicnode.com",
282282
},
283283
},
284+
[ChainId.RONIN]: {
285+
explorerURL: "https://app.roninchain.com/",
286+
id: ChainId.RONIN,
287+
isSupportedByUI: false,
288+
isTestnet: false,
289+
isZK: false,
290+
key: "ronin",
291+
name: "Ronin",
292+
nativeToken: ETH,
293+
rpc: {
294+
public: "https://api.roninchain.com/rpc",
295+
},
296+
},
284297
[ChainId.SCROLL]: {
285298
explorerURL: "https://scrollscan.com",
286299
id: ChainId.SCROLL,

src/chains/testnets.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const testnetsById: Record<number, Sablier.Chain> = {
4242
name: "Blast Sepolia",
4343
nativeToken: ETH,
4444
rpc: {
45-
public: "https://sepolia.blast.io",
45+
public: "https://rpc.ankr.com/blast_testnet_sepolia",
4646
},
4747
},
4848
[ChainId.ETHEREUM_SEPOLIA]: {

src/constants.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/helpers.ts

Lines changed: 8 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,8 @@
1-
import _ from "lodash";
2-
import { allById } from "./chains";
3-
import { BaseURL, THEGRAPH_ORG_ID } from "./constants";
4-
import { envio, subgraphs } from "./indexers";
5-
import type { Sablier } from "./types";
1+
import { getChain } from "@src/chains";
62
import versions from "./versions";
73

8-
export function getChain(chainId: number | string): Sablier.Chain {
9-
const chain = allById[Number(chainId)];
10-
if (!chain) {
11-
throw new Error(`Chain with ID ${chainId} not found`);
12-
}
13-
return chain;
14-
}
15-
16-
export function getChainName(chainId: number | string): string {
17-
const chainName = allById[Number(chainId)].name;
18-
if (!chainName) {
19-
throw new Error(`Chain with ID ${chainId} not found`);
20-
}
21-
return chainName;
22-
}
4+
import _ from "lodash";
5+
import type { Sablier } from "./types";
236

247
/**
258
* Get the explorer URL for a contract. Compatible with Etherscan, Blockscout, etc.
@@ -31,70 +14,18 @@ export function getContractExplorerURL(explorerURL: string, contractAddress: Sab
3114
return `${explorerURL}/address/${contractAddress}`;
3215
}
3316

34-
export function getDeployment(
35-
protocol: Sablier.Protocol,
36-
chainId: number,
37-
contractMap: Sablier.ContractMap,
38-
aliases: Sablier.AliasMap,
39-
): Sablier.Deployment {
40-
const chain = getChain(chainId);
41-
const contracts: Sablier.Contract[] = [];
42-
for (const [contractName, address] of _.entries(contractMap)) {
43-
const alias = aliases[contractName];
44-
const explorerURL = getContractExplorerURL(chain.explorerURL, address);
45-
contracts.push({ address, alias, explorerURL, name: contractName });
46-
}
47-
48-
const envioEndpoint = getEnvioEndpoint(protocol, chainId);
49-
const thegraph = getTheGraph(protocol, chainId);
50-
51-
return {
52-
chainId,
53-
contracts,
54-
indexers: {
55-
envio: envioEndpoint,
56-
thegraph,
57-
},
58-
};
59-
}
60-
61-
export function getDeploymentLockupV1(
62-
chainId: number,
63-
contractMap: {
64-
core: Sablier.ContractMap;
65-
periphery: Sablier.ContractMap;
66-
},
67-
aliases: Sablier.AliasMap,
68-
): Sablier.DeploymentLockupV1 {
69-
const mergedContracts = { ...contractMap.core, ...contractMap.periphery };
70-
const deployment = getDeployment("lockup", chainId, mergedContracts, aliases) as Sablier.DeploymentLockupV1;
71-
deployment.core = _.entries(contractMap.core).map(([name, address]) => ({ name, address }));
72-
deployment.periphery = _.entries(contractMap.periphery).map(([name, address]) => ({ name, address }));
73-
return deployment;
74-
}
75-
7617
/**
7718
* Extract all string values from a nested object
7819
* @param obj The object to extract string values from
7920
* @returns Array of all string values from the object
8021
*/
81-
export const getNestedValues = <T extends Record<string, unknown>>(obj: T): string[] => {
22+
export function getNestedValues<T extends Record<string, unknown>>(obj: T): string[] {
8223
return _.flatMap(obj, (value) => {
8324
if (_.isObject(value) && !_.isArray(value)) {
8425
return getNestedValues(value as Record<string, unknown>);
8526
}
8627
return _.isString(value) ? value : [];
8728
});
88-
};
89-
90-
/** Type guard to check if a manifest is a Lockup v1.x manifest. */
91-
export function isLockupV1Manifest(manifest: Sablier.Manifest): manifest is Sablier.ManifestLockupV1 {
92-
return "core" in manifest && "periphery" in manifest;
93-
}
94-
95-
/** Type guard to check if a release is a Lockup v1.x release. */
96-
export function isLockupV1Release(release: Sablier.Release): release is Sablier.ReleaseLockupV1 {
97-
return release.protocol === "lockup" && release.version.startsWith("v1.");
9829
}
9930

10031
export function isValidAirdropsVersion(version: Sablier.Version): boolean {
@@ -105,6 +36,10 @@ export function isValidFlowVersion(version: Sablier.Version): boolean {
10536
return version === versions.flow.v1_0 || version === versions.flow.v1_1;
10637
}
10738

39+
export function isValidLegacyVersion(version: Sablier.Version): boolean {
40+
return version === versions.legacy.v1_0 || version === versions.legacy.v1_1;
41+
}
42+
10843
export function isValidLockupVersion(version: Sablier.Version): boolean {
10944
return (
11045
version === versions.lockup.v1_0 ||
@@ -125,30 +60,3 @@ export function sortDeployments<T extends { chainId: number }>(deployments: T[])
12560
return aChain.name.localeCompare(bChain.name);
12661
});
12762
}
128-
129-
/*//////////////////////////////////////////////////////////////////////////
130-
PRIVATE FUNCTIONS
131-
//////////////////////////////////////////////////////////////////////////*/
132-
133-
function getEnvioEndpoint(protocol: Sablier.Protocol, chainId: number): string | undefined {
134-
if (chainId in envio.unsupportedChains) {
135-
return undefined;
136-
}
137-
return envio.endpoints[protocol];
138-
}
139-
140-
function getTheGraph(protocol: Sablier.Protocol, chainId: number): Sablier.TheGraph | undefined {
141-
const subgraph = subgraphs[protocol][chainId];
142-
if (!subgraph) {
143-
return undefined;
144-
}
145-
146-
return {
147-
explorer: `${BaseURL.TheGraph.EXPLORER}/${subgraph.id}`,
148-
studio: `${BaseURL.TheGraph.STUDIO}/${THEGRAPH_ORG_ID}/${subgraph.name}/version/latest`,
149-
subgraph: {
150-
id: subgraph.id,
151-
url: (apiKey: string) => `${BaseURL.TheGraph.GATEWAY}/${apiKey}/subgraphs/id/${subgraph.id}`,
152-
},
153-
};
154-
}

0 commit comments

Comments
 (0)