@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
JavaScript
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