Skip to content

Commit c4cfd25

Browse files
feat: add solana chains
1 parent ad91f01 commit c4cfd25

File tree

9 files changed

+170
-4
lines changed

9 files changed

+170
-4
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
"types": "./dist/evm/releases/index.d.ts",
6363
"default": "./dist/evm/releases/index.js"
6464
},
65+
"./solana": {
66+
"types": "./dist/solana/index.d.ts",
67+
"default": "./dist/solana/index.js"
68+
},
6569
"./package.json": "./package.json",
6670
"./dist/*": "./dist/*"
6771
},

src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export * from "./evm";
21
export * from "./helpers";
32
export * from "./sablier";
43
export * from "./types";

src/sablier.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/**
22
* @file This file exports the Sablier object, singleton that contains the queries for the
3-
* chains, contracts, and releases.
3+
* chains, contracts, and releases for both evm and solana compatible chains.
44
*
55
* @example
66
* ```typescript
77
* import { sablier } from "sablier";
88
*
9-
* const lockupContract = sablier.contracts.get({
9+
* const lockupContract = sablier.evmContractsQueries.get({
1010
* chainId: mainnet.id,
1111
* contractName: "SablierLockup",
1212
* release: releases.lockup["v2.0"],
@@ -19,6 +19,7 @@ import _ from "lodash";
1919
import { chainsQueries as evmChainsQueries } from "./evm/chains/queries";
2020
import { contractsQueries as evmContractsQueries } from "./evm/contracts/queries";
2121
import { releasesQueries as evmReleasesQueries } from "./evm/releases/queries";
22+
import { chainsQueries as solanaChainsQueries } from "./solana/chains/queries";
2223

2324
const evmDeploymentsQueries = {
2425
/**
@@ -36,8 +37,16 @@ const evmDeploymentsQueries = {
3637
};
3738

3839
export const sablier = {
40+
/* -------------------------------------------------------------------------- */
41+
/* EVM */
42+
/* -------------------------------------------------------------------------- */
3943
evmChains: evmChainsQueries,
4044
evmContracts: evmContractsQueries,
4145
evmDeployments: evmDeploymentsQueries,
4246
evmReleases: evmReleasesQueries,
47+
48+
/* -------------------------------------------------------------------------- */
49+
/* SOLANA */
50+
/* -------------------------------------------------------------------------- */
51+
solanaChains: solanaChainsQueries,
4352
};

src/solana/chains/data.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import type { Sablier } from "@src/types";
2+
3+
const CHAIN_ID_SOLANA_MAINNET_BETA = 900000010;
4+
const CHAIN_ID_SOLANA_DEVNET = 900000020;
5+
6+
export const solana_devnet: Sablier.SOLANA.Chain = {
7+
blockExplorers: {
8+
default: { name: "Explorer", url: "https://solscan.io?cluster=devnet" },
9+
solanaFm: {
10+
name: "Solana FM",
11+
url: "https://solana.fm?cluster=devnet-alpha",
12+
},
13+
},
14+
chainlink: {
15+
feed: "99B2bTijsU6f1GCT73HmdR7HCFFjGMBcPZY6jZ96ynrR",
16+
program: "HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny",
17+
},
18+
contracts: {},
19+
definition: {
20+
chainCode: "SOLDEV",
21+
chainId: CHAIN_ID_SOLANA_DEVNET,
22+
cluster: "devnet",
23+
},
24+
id: CHAIN_ID_SOLANA_DEVNET,
25+
isSupportedByUI: true,
26+
isTestnet: true,
27+
isZK: false,
28+
name: "Devnet",
29+
nativeCurrency: {
30+
coinGeckoId: "solana",
31+
decimals: 9,
32+
name: "Solana",
33+
symbol: "SOL",
34+
},
35+
rpc: {
36+
defaults: ["https://api.devnet-beta.solana.com/"],
37+
helius: (key) => `https://devnet.helius-rpc.com/?api-key=${key}`,
38+
},
39+
rpcUrls: {
40+
default: {
41+
http: ["https://api.devnet-beta.solana.com/"],
42+
},
43+
},
44+
slug: "solana-devnet",
45+
} as const;
46+
47+
export const solana_mainnetBeta: Sablier.SOLANA.Chain = {
48+
blockExplorers: {
49+
default: { name: "Explorer", url: "https://solscan.io" },
50+
solanaFm: { name: "Solana FM", url: "https://solana.fm" },
51+
},
52+
chainlink: {
53+
feed: "99B2bTijsU6f1GCT73HmdR7HCFFjGMBcPZY6jZ96ynrR",
54+
program: "HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny",
55+
},
56+
contracts: {},
57+
definition: {
58+
chainCode: "SOL",
59+
chainId: CHAIN_ID_SOLANA_MAINNET_BETA,
60+
cluster: "mainnet-beta",
61+
},
62+
id: CHAIN_ID_SOLANA_MAINNET_BETA,
63+
isSupportedByUI: true,
64+
isTestnet: false,
65+
isZK: false,
66+
name: "Solana",
67+
nativeCurrency: {
68+
coinGeckoId: "solana",
69+
decimals: 9,
70+
name: "Solana",
71+
symbol: "SOL",
72+
},
73+
rpc: {
74+
defaults: ["https://api.mainnet-beta.solana.com/"],
75+
helius: (key) => `https://mainnet.helius-rpc.com/?api-key=${key}`,
76+
},
77+
rpcUrls: {
78+
default: {
79+
http: ["https://api.mainnet-beta.solana.com/"],
80+
},
81+
},
82+
slug: "solana-mainnet-beta",
83+
} as const;

src/solana/chains/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * as chains from "./data";
2+
export * from "./data";

src/solana/chains/queries.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { sortChains } from "@src/helpers";
2+
import type { Sablier } from "@src/types";
3+
import _ from "lodash";
4+
import * as chains from "./data";
5+
6+
export const chainsQueries = {
7+
get: (chainId: number): Sablier.SOLANA.Chain | undefined => {
8+
return _.find(chains, (c) => c.id === chainId);
9+
},
10+
getAll: (): Sablier.EVM.Chain[] => {
11+
return sortChains(_.values(chains));
12+
},
13+
getBySlug: (slug: string): Sablier.SOLANA.Chain | undefined => {
14+
return _.find(chains, (c) => c.slug === slug);
15+
},
16+
getMainnets: (): Sablier.SOLANA.Chain[] => {
17+
return sortChains(_.filter(_.values(chains), (c) => !c.isTestnet));
18+
},
19+
getOrThrow: (chainId: number): Sablier.SOLANA.Chain => {
20+
const chain = _.find(chains, (c) => c.id === chainId);
21+
if (!chain) {
22+
throw new Error(`Sablier SDK: Chain with ID ${chainId} not found`);
23+
}
24+
return chain;
25+
},
26+
getTestnets: (): Sablier.SOLANA.Chain[] => {
27+
return sortChains(_.filter(_.values(chains), (c) => c.isTestnet));
28+
},
29+
};

src/solana/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
export { chains } from "./chains";
12
export * from "./idl";

src/types.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,45 @@ export namespace Sablier {
200200
export type Version = Version.Airdrops | Version.Flow | Version.Legacy | Version.Lockup;
201201
}
202202

203+
export namespace SOLANA {
204+
export type Address = string;
205+
export type ChainCode = "SOL" | "SOLDEV" | "SOLTEST";
206+
export type Cluster = "mainnet-beta" | "devnet" | "testnet";
207+
208+
export type Chain = ViemChain & {
209+
blockExplorers: {
210+
[key: string]: ChainBlockExplorer;
211+
default: ChainBlockExplorer;
212+
};
213+
/** Whether this chain is supported by the Sablier Interface at https://app.sablier.com. */
214+
isSupportedByUI: boolean;
215+
/** Whether this is a testnet network. */
216+
isTestnet: boolean;
217+
/** Whether this is a zkEVM like zkSync. */
218+
isZK: boolean;
219+
nativeCurrency: ViemChain["nativeCurrency"] & {
220+
coinGeckoId: string;
221+
};
222+
rpc: {
223+
/** Helius RPC URL generator. */
224+
helius?: (apiKey: string) => string;
225+
/** Default RPC URL. */
226+
defaults: string[];
227+
};
228+
/** Used in deployment files to identify the chain, e.g., arbitrum-sepolia. */
229+
slug: string;
230+
chainlink: {
231+
program: Address; // Chainlink program used to retrieve on-chain price feeds
232+
feed: Address; // Account providing the SOL/USD price feed data.
233+
};
234+
definition: {
235+
chainCode: ChainCode;
236+
chainId: number;
237+
cluster: Cluster;
238+
};
239+
};
240+
}
241+
203242
export namespace Indexer {
204243
type Common = {
205244
chainId: number;

tests/helpers/missing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const MISSING_CONTRACTS: ProtocolMap = {
5353
lockup: MISSING_LOCKUP,
5454
};
5555

56-
// Chains for which we completely lack broadcasts.
56+
// chains for which we completely lack broadcasts.
5757
export const MISSING_CHAINS: number[] = [chains.iotex.id, chains.ronin.id, chains.tangle.id];
5858

5959
export function isKnownMissing(release: Sablier.EVM.Release, chain: Sablier.EVM.Chain, contractName: string): boolean {

0 commit comments

Comments
 (0)