import type { SolanaRpcApi, SolanaRpcApiDevnet, SolanaRpcApiMainnet, SolanaRpcApiTestnet } from '@solana/rpc-api'; import type { Rpc, RpcTransport } from '@solana/rpc-spec'; import { type ClusterUrl, type DevnetUrl, type MainnetUrl, type TestnetUrl } from '@solana/rpc-types'; /** * A {@link RpcTransport} that communicates with the devnet cluster. * * Such transports are understood to communicate with a RPC server that services devnet, and as such * might only be accepted for use as the transport of a {@link RpcDevnet}. * * This is useful in cases where you need to make assertions about what capabilities a RPC offers. * For example, RPC methods like {@link requestAirdrop} are not available on mainnet. You can use * the ability to assert on the type of RPC transport at compile time to prevent calling * unimplemented methods or presuming the existence of unavailable capabilities. */ export type RpcTransportDevnet = RpcTransport & { '~cluster': 'devnet' }; /** * A {@link RpcTransport} that communicates with the testnet cluster. * * Such transports are understood to communicate with a RPC server that services testnet, and as * such might only be accepted for use as the transport of a {@link RpcTestnet}. * * This is useful in cases where you need to make assertions about what capabilities a RPC offers. * For example, RPC methods like {@link requestAirdrop} are not available on mainnet. You can use * the ability to assert on the type of RPC transport at compile time to prevent calling * unimplemented methods or presuming the existence of unavailable capabilities. */ export type RpcTransportTestnet = RpcTransport & { '~cluster': 'testnet' }; /** * A {@link RpcTransport} that communicates with the mainnet cluster. * * Such transports are understood to communicate with a RPC server that services mainnet, and as * such might only be accepted for use as the transport of a {@link RpcMainnet}. * * This is useful in cases where you need to make assertions about what capabilities a RPC offers. * For example, RPC methods like {@link requestAirdrop} are not available on mainnet. You can use * the ability to assert on the type of RPC transport at compile time to prevent calling * unimplemented methods or presuming the existence of unavailable capabilities. */ export type RpcTransportMainnet = RpcTransport & { '~cluster': 'mainnet' }; /** * Given a {@link ClusterUrl}, this utility type will resolve to as specific a {@link RpcTransport} * as possible. * * @example * ```ts * function createCustomTransport( * clusterUrl: TClusterUrl, * ): RpcTransportFromClusterUrl { * /* ... *\/ * } * * const transport = createCustomTransport(testnet('http://api.testnet.solana.com')); * transport satisfies RpcTransportTestnet; // OK * ``` */ export type RpcTransportFromClusterUrl = TClusterUrl extends DevnetUrl ? RpcTransportDevnet : TClusterUrl extends TestnetUrl ? RpcTransportTestnet : TClusterUrl extends MainnetUrl ? RpcTransportMainnet : RpcTransport; /** * A {@link Rpc} that supports the RPC methods available on the devnet cluster. * * This is useful in cases where you need to make assertions about the suitability of a RPC for a * given purpose. For example, you might like to make it a type error to combine certain types with * RPCs belonging to certain clusters, at compile time. * * @example * ```ts * async function getSpecialAccountInfo( * address: Address<'ReAL1111111111111111111111111111'>, * rpc: RpcMainnet, * ): Promise; * async function getSpecialAccountInfo( * address: Address<'TeST1111111111111111111111111111'>, * rpc: RpcDevnet | RpcTestnet, * ): Promise; * async function getSpecialAccountInfo(address: Address, rpc: Rpc): Promise { * /* ... *\/ * } * const rpc = createSolanaRpc(devnet('https://api.devnet.solana.com')); * await getSpecialAccountInfo(address('ReAL1111111111111111111111111111'), rpc); // ERROR * ``` */ export type RpcDevnet = Rpc & { '~cluster': 'devnet' }; /** * A {@link Rpc} that supports the RPC methods available on the testnet cluster. * * This is useful in cases where you need to make assertions about the suitability of a RPC for a * given purpose. For example, you might like to make it a type error to combine certain types with * RPCs belonging to certain clusters, at compile time. * * @example * ```ts * async function getSpecialAccountInfo( * address: Address<'ReAL1111111111111111111111111111'>, * rpc: RpcMainnet, * ): Promise; * async function getSpecialAccountInfo( * address: Address<'TeST1111111111111111111111111111'>, * rpc: RpcDevnet | RpcTestnet, * ): Promise; * async function getSpecialAccountInfo(address: Address, rpc: Rpc): Promise { * /* ... *\/ * } * const rpc = createSolanaRpc(devnet('https://api.devnet.solana.com')); * await getSpecialAccountInfo(address('ReAL1111111111111111111111111111'), rpc); // ERROR * ``` */ export type RpcTestnet = Rpc & { '~cluster': 'testnet' }; /** * A {@link Rpc} that supports the RPC methods available on the mainnet cluster. * * This is useful in cases where you need to make assertions about the suitability of a RPC for a * given purpose. For example, you might like to make it a type error to combine certain types with * RPCs belonging to certain clusters, at compile time. * * @example * ```ts * async function getSpecialAccountInfo( * address: Address<'ReAL1111111111111111111111111111'>, * rpc: RpcMainnet, * ): Promise; * async function getSpecialAccountInfo( * address: Address<'TeST1111111111111111111111111111'>, * rpc: RpcDevnet | RpcTestnet, * ): Promise; * async function getSpecialAccountInfo(address: Address, rpc: Rpc): Promise { * /* ... *\/ * } * const rpc = createSolanaRpc(devnet('https://api.devnet.solana.com')); * await getSpecialAccountInfo(address('ReAL1111111111111111111111111111'), rpc); // ERROR * ``` */ export type RpcMainnet = Rpc & { '~cluster': 'mainnet' }; /** * Given a {@link RpcTransport} and a set of RPC methods denoted by `TRpcMethods`, this utility type * will resolve to a {@link Rpc} that supports those methods on as specific a cluster as possible. * * @example * ```ts * function createCustomRpc( * transport: TRpcTransport, * ): RpcFromTransport { * /* ... *\/ * } * const transport = createDefaultRpcTransport({ url: mainnet('http://rpc.company') }); * transport satisfies RpcTransportMainnet; // OK * const rpc = createCustomRpc(transport); * rpc satisfies RpcMainnet; // OK * ``` */ export type RpcFromTransport = TRpcTransport extends RpcTransportDevnet ? RpcDevnet : TRpcTransport extends RpcTransportTestnet ? RpcTestnet : TRpcTransport extends RpcTransportMainnet ? RpcMainnet : Rpc; /** * Given a {@link RpcTransport} this utility type will resolve to a union of all the methods of the * Solana RPC API supported by the transport's cluster. * * @example * ```ts * function createSolanaRpcFromTransport( * transport: TTransport, * ): RpcFromTransport, TTransport> { * /* ... *\/ * } * const transport = createDefaultRpcTransport({ url: mainnet('http://rpc.company') }); * transport satisfies RpcTransportMainnet; // OK * const rpc = createSolanaRpcFromTransport(transport); * rpc satisfies RpcMainnet; // OK * ``` */ export type SolanaRpcApiFromTransport = TTransport extends RpcTransportDevnet ? SolanaRpcApiDevnet : TTransport extends RpcTransportTestnet ? SolanaRpcApiTestnet : TTransport extends RpcTransportMainnet ? SolanaRpcApiMainnet : SolanaRpcApi; /** * Given a {@link ClusterUrl} this utility type will resolve to a union of all the methods of the * Solana RPC API supported by the URL's cluster. * * @example * ```ts * function createSolanaRpcFromClusterUrl( * clusterUrl: TClusterUrl, * ): Rpc, RpcTransportFromClusterUrl> { * /* ... *\/ * } * const rpc = createSolanaRpcFromClusterUrl(mainnet('http://rpc.company')); * rpc satisfies Rpc; // OK * ``` */ export type SolanaRpcApiFromClusterUrl = SolanaRpcApiFromTransport< RpcTransportFromClusterUrl >;