UNPKG

@keyban/sdk-base

Version:

Keyban Javascript SDK provides core functionalities for the MPC wallet solution, supporting web and Node.js apps with TypeScript, custom storage, and Ethereum blockchain integration.

332 lines (328 loc) 10.7 kB
import { ApiClient } from './chunk-5DFR5Z62.js'; import { Network } from '@keyban/types'; export * from '@keyban/types'; export { ApplicationFeature, ApplicationThemeMode, Currency, DppProductStatus, Network } from '@keyban/types'; import { InMemoryCache } from '@apollo/client/cache'; import { ApolloLink, ApolloClient } from '@apollo/client/core'; import { SetContextLink } from '@apollo/client/link/context'; import { HttpLink } from '@apollo/client/link/http'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { getMainDefinition, relayStylePagination } from '@apollo/client/utilities'; import { createClient } from 'graphql-ws'; import { formatUnits } from 'viem'; // src/account.ts var KeybanAccount = class { api; /** * Internal constructor used by chain-specific clients. * @param api - Keyban API facade for remote operations. * @internal */ constructor(api) { this.api = api; } }; function createApolloClient(apiUrl, accessTokenProvider) { const authLink = new SetContextLink(async ({ headers }) => { const token = await accessTokenProvider?.(); return { headers: { ...headers, authorization: token ? `Bearer ${token}` : "" } }; }); const httpLink = new HttpLink({ uri: apiUrl.toString() }); const wsUrl = new URL(apiUrl); wsUrl.protocol = "wss"; const wsLink = new GraphQLWsLink(createClient({ url: wsUrl.toString() })); const transportLink = ApolloLink.split( ({ query }) => { const definition = getMainDefinition(query); return definition.kind === "OperationDefinition" && definition.operation === "subscription"; }, wsLink, httpLink ); const dateFieldPolicy = { read: (value) => value && value + "Z" }; return new ApolloClient({ devtools: { enabled: true }, defaultOptions: { query: { fetchPolicy: "network-only" }, watchQuery: { fetchPolicy: "cache-and-network" } }, cache: new InMemoryCache({ typePolicies: { Query: { fields: { tokenBalances: relayStylePagination(["filter"]), nftBalances: relayStylePagination(["filter"]), assetTransfers: relayStylePagination(["filter"]), orders: relayStylePagination(["filter"]) } }, Transaction: { fields: { date: dateFieldPolicy } }, Order: { fields: { createdAt: dateFieldPolicy } } } }), link: ApolloLink.from([authLink, transportLink]) }); } // src/clientShareProvider.ts var KeybanClientShareProvider = class { #api; constructor(client) { this.#api = client.api; } async get(key) { return this.#api.clientShareStorage.get(key); } async set(key, clientShare) { return this.#api.clientShareStorage.set(key, clientShare); } }; // src/client.ts var KeybanClientBase = class { /** * The Keyban API URL, defaulting to "https://api.prod.keyban.io". */ apiUrl; /** * The application ID used for authentication with the Keyban API. */ appId; /** * The blockchain used by Keyban. */ network; /** * The Apollo GraphQL client used for making API requests. */ apolloClient; clientShareProvider; metadataConfig; constructor(config, metadataConfig) { this.apiUrl = new URL(config.apiUrl ?? "https://api.prod.keyban.io"); this.appId = config.appId; this.network = config.network; this.clientShareProvider = config.clientShareProvider ?? new KeybanClientShareProvider(this); const indexerPrefix = { [Network.EthereumAnvil]: "subql-ethereum-anvil.", [Network.PolygonAmoy]: "subql-polygon-amoy.", [Network.StarknetDevnet]: "subql-starknet-devnet.", [Network.StarknetSepolia]: "subql-starknet-sepolia.", [Network.StarknetMainnet]: "subql-starknet-mainnet.", [Network.StellarQuickstart]: "subql-stellar-quickstart.", [Network.StellarTestnet]: "subql-stellar-testnet.", [Network.StellarMainnet]: "subql-stellar-mainnet." }[this.network]; this.apolloClient = createApolloClient( new URL(this.apiUrl.origin.replace("api.", indexerPrefix)) ); const metadataUrl = new URL(`/v1/metadata`, this.apiUrl); metadataUrl.searchParams.set("network", this.network); this.metadataConfig = metadataConfig ?? fetch(metadataUrl).then((res) => res.json()); } get api() { return ApiClient.getInstance(this).api; } /** * Retrieves the native currency details associated with the current network. * * Returns an object that includes the native currency's name, symbol, and decimal precision * for the active {@link KeybanClientBase.network}. * @returns The native currency information for the current network. */ get nativeCurrency() { return { [Network.EthereumAnvil]: { decimals: 18, name: "Ether", symbol: "ETH" }, [Network.PolygonAmoy]: { name: "POL", symbol: "POL", decimals: 18 }, [Network.StarknetDevnet]: { name: "Starknet Token", symbol: "STRK", decimals: 18 }, [Network.StarknetSepolia]: { name: "StarkNet Token", symbol: "STRK", decimals: 18 }, [Network.StarknetMainnet]: { name: "StarkNet Token", symbol: "STRK", decimals: 18 }, [Network.StellarQuickstart]: { name: "Lumen", symbol: "XLM", decimals: 7 }, [Network.StellarTestnet]: { name: "Lumen", symbol: "XLM", decimals: 7 }, [Network.StellarMainnet]: { name: "Lumen", symbol: "XLM", decimals: 7 } }[this.network]; } /** * Retrieves the fee unit configuration based on the current network. * * Maps supported networks to their fee unit details, including symbol and number of decimals. * Supported configurations include: * - EthereumAnvil & PolygonAmoy: symbol "gwei", decimals 9 * - StarknetDevnet, StarknetSepolia & StarknetMainnet: symbol "FRI", decimals 18 * - StellarQuickstart, StellarTestnet & StellarMainnet: symbol "stroop", decimals 7 * @returns The fee unit configuration for the active network. */ get feesUnit() { return { [Network.EthereumAnvil]: { symbol: "gwei", decimals: 9 }, [Network.PolygonAmoy]: { symbol: "gwei", decimals: 9 }, [Network.StarknetDevnet]: { symbol: "FRI", decimals: 18 }, [Network.StarknetSepolia]: { symbol: "FRI", decimals: 18 }, [Network.StarknetMainnet]: { symbol: "FRI", decimals: 18 }, [Network.StellarQuickstart]: { symbol: "stroop", decimals: 7 }, [Network.StellarTestnet]: { symbol: "stroop", decimals: 7 }, [Network.StellarMainnet]: { symbol: "stroop", decimals: 7 } }[this.network]; } /** * Performs a health check on the Keyban API to determine its operational status. * @returns - A promise resolving to the API status, either `"operational"` or `"down"`. * @example * ```typescript * const status = await client.apiStatus(); * console.log(`API Status: ${status}`); * ``` * @throws {Error} Throws an error if the health check request fails. * @see {@link KeybanApiStatus} */ async apiStatus() { return fetch(new URL("/health/ready", this.apiUrl)).then((res) => res.ok ? "operational" : "down").catch((err) => { console.error("Failed to perform health check", err); return "down"; }); } }; var KeybanClient = class extends KeybanClientBase { #client; #pendingAccounts = /* @__PURE__ */ new Map(); /** * Creates a new instance of `KeybanClient`. * @param config - The configuration object to initialize the client. * @throws {SdkError} If the configuration is invalid. * @example * ```typescript * const client = new KeybanClient({ * apiUrl: "https://api.prod.keyban.io", * appId: "your-app-id", * network: Network.EthereumAnvil, * }); * ``` */ constructor(config) { super(config); this.#client = { [Network.EthereumAnvil]: () => import('./evm-OGWCUTTG.js').then( ({ KeybanEvmClient }) => new KeybanEvmClient(config, this.metadataConfig) ), [Network.PolygonAmoy]: () => import('./evm-OGWCUTTG.js').then( ({ KeybanEvmClient }) => new KeybanEvmClient(config, this.metadataConfig) ), [Network.StarknetDevnet]: () => import('./starknet-6BK2DQFX.js').then( ({ StarknetClient }) => new StarknetClient(config, this.metadataConfig) ), [Network.StarknetSepolia]: () => import('./starknet-6BK2DQFX.js').then( ({ StarknetClient }) => new StarknetClient(config, this.metadataConfig) ), [Network.StarknetMainnet]: () => import('./starknet-6BK2DQFX.js').then( ({ StarknetClient }) => new StarknetClient(config, this.metadataConfig) ), [Network.StellarQuickstart]: () => import('./stellar-PFZVBOIH.js').then( ({ StellarClient }) => new StellarClient(config, this.metadataConfig) ), [Network.StellarTestnet]: () => import('./stellar-PFZVBOIH.js').then( ({ StellarClient }) => new StellarClient(config, this.metadataConfig) ), [Network.StellarMainnet]: () => import('./stellar-PFZVBOIH.js').then( ({ StellarClient }) => new StellarClient(config, this.metadataConfig) ) }[this.network](); } async initialize() { const key = "WHATEVER"; const pending = this.#pendingAccounts.get(key); if (pending) return pending; const promise = this.#client.then((client) => client.initialize()); this.#pendingAccounts.set(key, promise); promise.catch(() => { }).finally(() => this.#pendingAccounts.delete(key)); return promise; } }; function formatBalance(client, balance, token) { let decimals = balance.decimals; let symbol = balance.symbol; if (balance.isFees) { decimals = client.feesUnit.decimals; symbol = client.feesUnit.symbol; } else if (balance.isNative) { decimals = client.nativeCurrency.decimals; symbol = client.nativeCurrency.symbol; } else if (token) { decimals = token.decimals ?? void 0; symbol = token.symbol ?? void 0; } decimals = decimals ?? 0; const fmt = formatUnits( typeof balance.raw === "bigint" ? balance.raw : BigInt(balance.raw), decimals ); return symbol ? `${fmt} ${symbol}` : fmt; } export { KeybanAccount, KeybanClient, KeybanClientBase, formatBalance }; //# sourceMappingURL=chunk-XOGOIR6D.js.map //# sourceMappingURL=chunk-XOGOIR6D.js.map