Skip to content

Commit 74d7ec9

Browse files
feat: add solana chains
1 parent e31ad15 commit 74d7ec9

File tree

9 files changed

+167
-16
lines changed

9 files changed

+167
-16
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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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
@@ -27,6 +27,7 @@ import _ from "lodash";
2727
import { chainsQueries as evmChainsQueries } from "./evm/chains/queries";
2828
import { contractsQueries as evmContractsQueries } from "./evm/contracts/queries";
2929
import { releasesQueries as evmReleasesQueries } from "./evm/releases/queries";
30+
import { chainsQueries as solanaChainsQueries } from "./solana/chains/queries";
3031

3132
const evmDeploymentsQueries = {
3233
/**
@@ -50,11 +51,16 @@ const evm = {
5051
releases: evmReleasesQueries,
5152
};
5253

54+
const solana = {
55+
chains: solanaChainsQueries,
56+
};
57+
5358
export const sablier = {
5459
// Kept like this for backwards compatibility
5560
chains: evm.chains,
5661
contract: evm.contracts,
5762
deployments: evm.deployments,
5863
evm,
5964
releases: evm.releases,
65+
solana
6066
};

src/solana/chains/data.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
name: "Devnet",
28+
nativeCurrency: {
29+
coinGeckoId: "solana",
30+
decimals: 9,
31+
name: "Solana",
32+
symbol: "SOL",
33+
},
34+
rpc: {
35+
defaults: ["https://api.devnet-beta.solana.com/"],
36+
helius: (key) => `https://devnet.helius-rpc.com/?api-key=${key}`,
37+
},
38+
rpcUrls: {
39+
default: {
40+
http: ["https://api.devnet-beta.solana.com/"],
41+
},
42+
},
43+
slug: "solana-devnet",
44+
} as const;
45+
46+
export const solana_mainnetBeta: Sablier.Solana.Chain = {
47+
blockExplorers: {
48+
default: { name: "Explorer", url: "https://solscan.io" },
49+
solanaFm: { name: "Solana FM", url: "https://solana.fm" },
50+
},
51+
chainlink: {
52+
feed: "99B2bTijsU6f1GCT73HmdR7HCFFjGMBcPZY6jZ96ynrR",
53+
program: "HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny",
54+
},
55+
contracts: {},
56+
definition: {
57+
chainCode: "SOL",
58+
chainId: CHAIN_ID_SOLANA_MAINNET_BETA,
59+
cluster: "mainnet-beta",
60+
},
61+
id: CHAIN_ID_SOLANA_MAINNET_BETA,
62+
isSupportedByUI: true,
63+
isTestnet: false,
64+
name: "Solana",
65+
nativeCurrency: {
66+
coinGeckoId: "solana",
67+
decimals: 9,
68+
name: "Solana",
69+
symbol: "SOL",
70+
},
71+
rpc: {
72+
defaults: ["https://api.mainnet-beta.solana.com/"],
73+
helius: (key) => `https://mainnet.helius-rpc.com/?api-key=${key}`,
74+
},
75+
rpcUrls: {
76+
default: {
77+
http: ["https://api.mainnet-beta.solana.com/"],
78+
},
79+
},
80+
slug: "solana-mainnet-beta",
81+
} 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.Solana.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: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@ export namespace Sablier {
66
/* TYPES */
77
/* -------------------------------------------------------------------------- */
88

9+
type BaseChain = ViemChain & {
10+
blockExplorers: {
11+
[key: string]: ChainBlockExplorer;
12+
default: ChainBlockExplorer;
13+
};
14+
/** Whether this chain is supported by the Sablier Interface at https://app.sablier.com. */
15+
isSupportedByUI: boolean;
16+
/** Whether this is a testnet network. */
17+
isTestnet: boolean;
18+
/** Whether this is a zkEVM like zkSync. */
19+
nativeCurrency: ViemChain["nativeCurrency"] & {
20+
coinGeckoId: string;
21+
};
22+
slug: string;
23+
};
24+
925
/**
1026
* @see https://github.com/wevm/viem/discussions/3678
1127
*/
@@ -30,20 +46,8 @@ export namespace Sablier {
3046
export type Address = `0x${string}`;
3147

3248
export type AbiMap = { [contractName: string]: readonly object[] };
33-
export type Chain = ViemChain & {
34-
blockExplorers: {
35-
[key: string]: ChainBlockExplorer;
36-
default: ChainBlockExplorer;
37-
};
38-
/** Whether this chain is supported by the Sablier Interface at https://app.sablier.com. */
39-
isSupportedByUI: boolean;
40-
/** Whether this is a testnet network. */
41-
isTestnet: boolean;
42-
/** Whether this is a zkEVM like zkSync. */
49+
export type Chain = BaseChain & {
4350
isZK: boolean;
44-
nativeCurrency: ViemChain["nativeCurrency"] & {
45-
coinGeckoId: string;
46-
};
4751
rpc: {
4852
/** Alchemy RPC URL generator. */
4953
alchemy?: (apiKey: string) => string;
@@ -246,6 +250,31 @@ export namespace Sablier {
246250
}
247251
}
248252

253+
export namespace Solana {
254+
export type Address = string;
255+
export type ChainCode = "SOL" | "SOLDEV" | "SOLTEST";
256+
export type Cluster = "mainnet-beta" | "devnet" | "testnet";
257+
258+
export type Chain = BaseChain & {
259+
rpc: {
260+
/** Helius RPC URL generator. */
261+
helius?: (apiKey: string) => string;
262+
/** Default RPC URL. */
263+
defaults: string[];
264+
};
265+
/** Used in deployment files to identify the chain, e.g., arbitrum-sepolia. */
266+
chainlink: {
267+
program: Address; // Chainlink program used to retrieve on-chain price feeds
268+
feed: Address; // Account providing the SOL/USD price feed data.
269+
};
270+
definition: {
271+
chainCode: ChainCode;
272+
chainId: number;
273+
cluster: Cluster;
274+
};
275+
};
276+
}
277+
249278
/* --------------------------------------------------------------------------------------------------- */
250279
/* RE-EXPORTS (FOR BACKWARD COMPATIBILITY) */
251280
/* --------------------------------------------------------------------------------------------------- */

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)