@kheopskit/core 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -48,6 +48,13 @@ type WalletId = string;
48
48
  type KheopskitConfig = {
49
49
  autoReconnect: boolean;
50
50
  platforms: WalletPlatform[];
51
+ /**
52
+ * Allowed Polkadot account key types.
53
+ * Accounts with other key types are filtered out from kheopskit state.
54
+ *
55
+ * @default ["sr25519", "ed25519", "ecdsa"]
56
+ */
57
+ polkadotAccountTypes: PolkadotAccountType[];
51
58
  walletConnect?: {
52
59
  projectId: string;
53
60
  metadata: Metadata;
@@ -137,7 +144,9 @@ type EthereumAppKitWallet = {
137
144
  type EthereumWallet = EthereumInjectedWallet | EthereumAppKitWallet;
138
145
  type Wallet = PolkadotWallet | EthereumWallet;
139
146
  type WalletPlatform = Wallet["platform"];
140
- type PolkadotAccount = InjectedPolkadotAccount & {
147
+ type PolkadotAccountType = "sr25519" | "ed25519" | "ecdsa" | "ethereum";
148
+ type PolkadotAccount = Omit<InjectedPolkadotAccount, "type"> & {
149
+ type: PolkadotAccountType;
141
150
  id: WalletAccountId;
142
151
  platform: "polkadot";
143
152
  walletName: string;
@@ -148,6 +157,8 @@ type EthereumAccount = {
148
157
  platform: "ethereum";
149
158
  client: WalletClient<CustomTransport, undefined, Account, undefined>;
150
159
  address: `0x${string}`;
160
+ /** Current chain ID the wallet is connected to. `undefined` while loading or after provider disconnect. */
161
+ chainId: number | undefined;
151
162
  walletName: string;
152
163
  walletId: string;
153
164
  isWalletDefault: boolean;
@@ -174,6 +185,10 @@ type CachedAccount = {
174
185
  platform: WalletPlatform;
175
186
  address: string;
176
187
  name?: string;
188
+ /** Cached chain ID for Ethereum accounts. */
189
+ chainId?: number;
190
+ /** Cached key type for Polkadot accounts. */
191
+ polkadotAccountType?: PolkadotAccountType;
177
192
  walletId: WalletId;
178
193
  walletName: string;
179
194
  };
@@ -275,4 +290,4 @@ type KheopskitState = {
275
290
  };
276
291
  declare const getKheopskit$: (config?: Partial<KheopskitConfig>, ssrCookies?: string, existingStore?: ReturnType<typeof createKheopskitStore>) => Observable<KheopskitState>;
277
292
 
278
- export { type CachedAccount, type CachedWallet, DEFAULT_STORAGE_KEY, type EthereumAccount, type EthereumAppKitWallet, type EthereumInjectedWallet, type EthereumWallet, type KheopskitConfig, type KheopskitState, type PolkadotAccount, type PolkadotAppKitWallet, type PolkadotInjectedWallet, type PolkadotWallet, type Wallet, type WalletAccount, type WalletPlatform, clearAllCachedObservables, clearCachedObservable, createKheopskitStore, getCachedIcon, getDefaultStore, getKheopskit$, getSafeLocalStorage, hydrateAccount, hydrateWallet, resetAppKitCache, resolveConfig };
293
+ export { type CachedAccount, type CachedWallet, DEFAULT_STORAGE_KEY, type EthereumAccount, type EthereumAppKitWallet, type EthereumInjectedWallet, type EthereumWallet, type KheopskitConfig, type KheopskitState, type PolkadotAccount, type PolkadotAccountType, type PolkadotAppKitWallet, type PolkadotInjectedWallet, type PolkadotWallet, type Wallet, type WalletAccount, type WalletPlatform, clearAllCachedObservables, clearCachedObservable, createKheopskitStore, getCachedIcon, getDefaultStore, getKheopskit$, getSafeLocalStorage, hydrateAccount, hydrateWallet, resetAppKitCache, resolveConfig };
package/dist/index.d.ts CHANGED
@@ -48,6 +48,13 @@ type WalletId = string;
48
48
  type KheopskitConfig = {
49
49
  autoReconnect: boolean;
50
50
  platforms: WalletPlatform[];
51
+ /**
52
+ * Allowed Polkadot account key types.
53
+ * Accounts with other key types are filtered out from kheopskit state.
54
+ *
55
+ * @default ["sr25519", "ed25519", "ecdsa"]
56
+ */
57
+ polkadotAccountTypes: PolkadotAccountType[];
51
58
  walletConnect?: {
52
59
  projectId: string;
53
60
  metadata: Metadata;
@@ -137,7 +144,9 @@ type EthereumAppKitWallet = {
137
144
  type EthereumWallet = EthereumInjectedWallet | EthereumAppKitWallet;
138
145
  type Wallet = PolkadotWallet | EthereumWallet;
139
146
  type WalletPlatform = Wallet["platform"];
140
- type PolkadotAccount = InjectedPolkadotAccount & {
147
+ type PolkadotAccountType = "sr25519" | "ed25519" | "ecdsa" | "ethereum";
148
+ type PolkadotAccount = Omit<InjectedPolkadotAccount, "type"> & {
149
+ type: PolkadotAccountType;
141
150
  id: WalletAccountId;
142
151
  platform: "polkadot";
143
152
  walletName: string;
@@ -148,6 +157,8 @@ type EthereumAccount = {
148
157
  platform: "ethereum";
149
158
  client: WalletClient<CustomTransport, undefined, Account, undefined>;
150
159
  address: `0x${string}`;
160
+ /** Current chain ID the wallet is connected to. `undefined` while loading or after provider disconnect. */
161
+ chainId: number | undefined;
151
162
  walletName: string;
152
163
  walletId: string;
153
164
  isWalletDefault: boolean;
@@ -174,6 +185,10 @@ type CachedAccount = {
174
185
  platform: WalletPlatform;
175
186
  address: string;
176
187
  name?: string;
188
+ /** Cached chain ID for Ethereum accounts. */
189
+ chainId?: number;
190
+ /** Cached key type for Polkadot accounts. */
191
+ polkadotAccountType?: PolkadotAccountType;
177
192
  walletId: WalletId;
178
193
  walletName: string;
179
194
  };
@@ -275,4 +290,4 @@ type KheopskitState = {
275
290
  };
276
291
  declare const getKheopskit$: (config?: Partial<KheopskitConfig>, ssrCookies?: string, existingStore?: ReturnType<typeof createKheopskitStore>) => Observable<KheopskitState>;
277
292
 
278
- export { type CachedAccount, type CachedWallet, DEFAULT_STORAGE_KEY, type EthereumAccount, type EthereumAppKitWallet, type EthereumInjectedWallet, type EthereumWallet, type KheopskitConfig, type KheopskitState, type PolkadotAccount, type PolkadotAppKitWallet, type PolkadotInjectedWallet, type PolkadotWallet, type Wallet, type WalletAccount, type WalletPlatform, clearAllCachedObservables, clearCachedObservable, createKheopskitStore, getCachedIcon, getDefaultStore, getKheopskit$, getSafeLocalStorage, hydrateAccount, hydrateWallet, resetAppKitCache, resolveConfig };
293
+ export { type CachedAccount, type CachedWallet, DEFAULT_STORAGE_KEY, type EthereumAccount, type EthereumAppKitWallet, type EthereumInjectedWallet, type EthereumWallet, type KheopskitConfig, type KheopskitState, type PolkadotAccount, type PolkadotAccountType, type PolkadotAppKitWallet, type PolkadotInjectedWallet, type PolkadotWallet, type Wallet, type WalletAccount, type WalletPlatform, clearAllCachedObservables, clearCachedObservable, createKheopskitStore, getCachedIcon, getDefaultStore, getKheopskit$, getSafeLocalStorage, hydrateAccount, hydrateWallet, resetAppKitCache, resolveConfig };
package/dist/index.js CHANGED
@@ -152,6 +152,7 @@ var hydrateAccount = (cached) => {
152
152
  return {
153
153
  id: cached.id,
154
154
  platform: "polkadot",
155
+ type: cached.polkadotAccountType ?? "sr25519",
155
156
  address: cached.address,
156
157
  name: cached.name,
157
158
  walletId: cached.walletId,
@@ -166,6 +167,7 @@ var hydrateAccount = (cached) => {
166
167
  id: cached.id,
167
168
  platform: "ethereum",
168
169
  address: cached.address,
170
+ chainId: cached.chainId,
169
171
  walletId: cached.walletId,
170
172
  walletName: cached.walletName,
171
173
  isWalletDefault: false,
@@ -188,6 +190,8 @@ var serializeAccount = (account) => ({
188
190
  platform: account.platform,
189
191
  address: account.address,
190
192
  name: "name" in account ? account.name : void 0,
193
+ chainId: account.platform === "ethereum" ? account.chainId : void 0,
194
+ polkadotAccountType: account.platform === "polkadot" ? account.type : void 0,
191
195
  walletId: account.walletId,
192
196
  walletName: account.walletName
193
197
  });
@@ -467,12 +471,28 @@ var DEFAULT_STORAGE_KEY = "kheopskit";
467
471
  var DEFAULT_CONFIG = {
468
472
  autoReconnect: true,
469
473
  platforms: ["polkadot"],
474
+ polkadotAccountTypes: ["sr25519", "ed25519", "ecdsa"],
470
475
  debug: false,
471
476
  storageKey: DEFAULT_STORAGE_KEY,
472
477
  hydrationGracePeriod: 500
473
478
  };
479
+ var VALID_POLKADOT_ACCOUNT_TYPES = /* @__PURE__ */ new Set([
480
+ "sr25519",
481
+ "ed25519",
482
+ "ecdsa",
483
+ "ethereum"
484
+ ]);
474
485
  var resolveConfig = (config) => {
475
- return Object.assign({}, DEFAULT_CONFIG, config);
486
+ const resolved = Object.assign({}, DEFAULT_CONFIG, config);
487
+ const invalid = resolved.polkadotAccountTypes.filter(
488
+ (t) => !VALID_POLKADOT_ACCOUNT_TYPES.has(t)
489
+ );
490
+ if (invalid.length > 0) {
491
+ console.warn(
492
+ `[kheopskit] Unknown polkadotAccountTypes: ${JSON.stringify(invalid)}. Valid values: "sr25519", "ed25519", "ecdsa", "ethereum".`
493
+ );
494
+ }
495
+ return resolved;
476
496
  };
477
497
 
478
498
  // src/api/kheopskit.ts
@@ -697,12 +717,37 @@ var getWalletAccountId = (walletId, address) => {
697
717
  };
698
718
 
699
719
  // src/api/ethereum/accounts.ts
720
+ var normalizeEvmChainId = (value) => {
721
+ let raw = value;
722
+ if (typeof raw === "string" && raw.startsWith("eip155:")) {
723
+ raw = raw.slice("eip155:".length);
724
+ }
725
+ if (typeof raw === "bigint") {
726
+ return raw >= 0n ? Number(raw) : void 0;
727
+ }
728
+ if (typeof raw === "number") {
729
+ return Number.isInteger(raw) && raw >= 0 ? raw : void 0;
730
+ }
731
+ if (typeof raw === "string") {
732
+ const normalized = raw.trim().toLowerCase();
733
+ if (!normalized) return void 0;
734
+ const parsed = normalized.startsWith("0x") ? Number.parseInt(normalized, 16) : Number.parseInt(normalized, 10);
735
+ return Number.isNaN(parsed) ? void 0 : parsed;
736
+ }
737
+ return void 0;
738
+ };
739
+ var toCaipNetworkId = (value) => {
740
+ const chainId = normalizeEvmChainId(value);
741
+ return chainId === void 0 ? void 0 : `eip155:${chainId}`;
742
+ };
700
743
  var getInjectedWalletAccounts$ = (wallet) => {
701
744
  if (!wallet.isConnected) return (0, import_rxjs5.of)([]);
702
745
  return getCachedObservable$(
703
746
  `accounts:${wallet.id}`,
704
747
  () => new import_rxjs5.Observable((subscriber) => {
705
- const getAccount = (address, i) => {
748
+ const addresses$ = new import_rxjs5.ReplaySubject(1);
749
+ const chainId$ = new import_rxjs5.ReplaySubject(1);
750
+ const getAccount = (address, i, chainId) => {
706
751
  const client = (0, import_viem2.createWalletClient)({
707
752
  account: address,
708
753
  transport: (0, import_viem2.custom)(wallet.provider)
@@ -712,26 +757,42 @@ var getInjectedWalletAccounts$ = (wallet) => {
712
757
  platform: "ethereum",
713
758
  client,
714
759
  address: (0, import_viem2.getAddress)(address),
760
+ chainId,
715
761
  walletName: wallet.name,
716
762
  walletId: wallet.id,
717
763
  isWalletDefault: i === 0
718
764
  };
719
765
  };
720
- const handleAccountsChanged = (addresses) => {
721
- subscriber.next(addresses.map(getAccount));
766
+ const handleAccountsChanged = (addrs) => {
767
+ addresses$.next(addrs);
768
+ };
769
+ const handleChainChanged = (chainIdHex) => {
770
+ chainId$.next(normalizeEvmChainId(chainIdHex));
771
+ };
772
+ const handleDisconnect = () => {
773
+ chainId$.next(void 0);
722
774
  };
723
775
  wallet.provider.on("accountsChanged", handleAccountsChanged);
724
- wallet.provider.request({ method: "eth_accounts" }).then((addresses) => {
725
- subscriber.next(addresses.map(getAccount));
726
- }).catch((err) => {
776
+ wallet.provider.on("chainChanged", handleChainChanged);
777
+ wallet.provider.on("disconnect", handleDisconnect);
778
+ wallet.provider.request({ method: "eth_accounts" }).then((addrs) => addresses$.next(addrs)).catch((err) => {
727
779
  console.error("Failed to get accounts", err);
728
- subscriber.next([]);
780
+ addresses$.next([]);
729
781
  });
782
+ wallet.provider.request({ method: "eth_chainId" }).then(handleChainChanged).catch(() => chainId$.next(void 0));
783
+ const sub = (0, import_rxjs5.combineLatest)([addresses$, chainId$]).pipe(
784
+ (0, import_rxjs5.map)(
785
+ ([addresses, chainId]) => addresses.map((addr, i) => getAccount(addr, i, chainId))
786
+ )
787
+ ).subscribe(subscriber);
730
788
  return () => {
731
789
  wallet.provider.removeListener(
732
790
  "accountsChanged",
733
791
  handleAccountsChanged
734
792
  );
793
+ wallet.provider.removeListener("chainChanged", handleChainChanged);
794
+ wallet.provider.removeListener("disconnect", handleDisconnect);
795
+ sub.unsubscribe();
735
796
  };
736
797
  }).pipe((0, import_rxjs5.shareReplay)({ refCount: true, bufferSize: 1 }))
737
798
  );
@@ -760,24 +821,29 @@ var getAppKitAccounts$ = (wallet) => {
760
821
  () => new import_rxjs5.Observable((subscriber) => {
761
822
  const caipNetworkId$ = new import_rxjs5.ReplaySubject(1);
762
823
  const handleChainChanged = (chainId) => {
763
- caipNetworkId$.next(`eip155:${chainId}`);
824
+ const caipNetworkId = toCaipNetworkId(chainId);
825
+ if (caipNetworkId) {
826
+ caipNetworkId$.next(caipNetworkId);
827
+ }
764
828
  };
765
829
  provider.on("chainChanged", handleChainChanged);
766
830
  provider.request({ method: "eth_chainId" }).then(handleChainChanged);
767
831
  const sub = caipNetworkId$.pipe(
768
832
  (0, import_rxjs5.distinctUntilChanged)(),
769
- (0, import_rxjs5.map)(
770
- (caipNetworkId) => (0, import_viem2.custom)(
833
+ (0, import_rxjs5.map)((caipNetworkId) => {
834
+ const chainId = normalizeEvmChainId(caipNetworkId);
835
+ const transport = (0, import_viem2.custom)(
771
836
  wrapWalletConnectProvider(
772
837
  provider,
773
838
  // biome-ignore lint/style/noNonNullAssertion: legacy
774
839
  provider.session.topic,
775
840
  caipNetworkId
776
841
  )
777
- )
778
- ),
842
+ );
843
+ return { transport, chainId };
844
+ }),
779
845
  (0, import_rxjs5.map)(
780
- (transport) => account.allAccounts.map((acc, i) => {
846
+ ({ transport, chainId }) => account.allAccounts.map((acc, i) => {
781
847
  const client = (0, import_viem2.createWalletClient)({
782
848
  account: acc.address,
783
849
  transport
@@ -789,6 +855,7 @@ var getAppKitAccounts$ = (wallet) => {
789
855
  walletId: wallet.id,
790
856
  address: acc.address,
791
857
  client,
858
+ chainId,
792
859
  isWalletDefault: i === 0
793
860
  };
794
861
  })
@@ -823,7 +890,9 @@ var getEthereumAccounts$ = (ethereumWallets) => new import_rxjs5.Observable((sub
823
890
  );
824
891
  var isSameAccountsList = (a, b) => {
825
892
  if (a.length !== b.length) return false;
826
- return a.every((account, i) => account.id === b[i]?.id);
893
+ return a.every(
894
+ (account, i) => account.id === b[i]?.id && account.chainId === b[i]?.chainId
895
+ );
827
896
  };
828
897
 
829
898
  // src/api/polkadot/accounts.ts
@@ -835,6 +904,7 @@ var getInjectedWalletAccounts$2 = (wallet) => {
835
904
  const getAccount = (account) => ({
836
905
  id: getWalletAccountId(wallet.id, account.address),
837
906
  ...account,
907
+ type: account.type ?? "sr25519",
838
908
  platform: "polkadot",
839
909
  walletName: wallet.name,
840
910
  walletId: wallet.id
@@ -904,12 +974,19 @@ var getAppKitAccounts$2 = (wallet) => {
904
974
  polkadotSigner: getAppKitPolkadotSigner(wallet.appKit, acc.address),
905
975
  genesisHash: null,
906
976
  name: `${wallet.name} Polkadot`,
977
+ // WalletConnect (Reown AppKit) doesn't expose account key type;
978
+ // default to sr25519, which is the most common Polkadot key type.
907
979
  type: "sr25519"
908
980
  })
909
981
  )
910
982
  );
911
983
  };
912
- var getPolkadotAccounts$ = (polkadotWallets$) => new import_rxjs6.Observable((subscriber) => {
984
+ var getPolkadotAccounts$ = (polkadotWallets$, polkadotAccountTypes) => new import_rxjs6.Observable((subscriber) => {
985
+ if (polkadotAccountTypes.length === 0) {
986
+ console.warn(
987
+ "[kheopskit] config.polkadotAccountTypes is empty; all Polkadot accounts will be filtered out."
988
+ );
989
+ }
913
990
  const sub = polkadotWallets$.pipe(
914
991
  (0, import_rxjs6.map)((wallets) => wallets.filter((w) => w.isConnected)),
915
992
  (0, import_rxjs6.switchMap)(
@@ -918,7 +995,9 @@ var getPolkadotAccounts$ = (polkadotWallets$) => new import_rxjs6.Observable((su
918
995
  ...wallets.filter((w) => w.type === "appKit").map(getAppKitAccounts$2)
919
996
  ]) : (0, import_rxjs6.of)([])
920
997
  ),
921
- (0, import_rxjs6.map)((accounts) => accounts.flat()),
998
+ (0, import_rxjs6.map)(
999
+ (accounts) => accounts.flat().filter((account) => polkadotAccountTypes.includes(account.type))
1000
+ ),
922
1001
  (0, import_rxjs6.distinctUntilChanged)(isSameAccountsList2)
923
1002
  ).subscribe(subscriber);
924
1003
  return () => {
@@ -940,7 +1019,8 @@ var getAccounts$ = (config, wallets) => {
940
1019
  return getPolkadotAccounts$(
941
1020
  wallets.pipe(
942
1021
  (0, import_rxjs7.map)((w) => w.filter((w2) => w2.platform === "polkadot"))
943
- )
1022
+ ),
1023
+ config.polkadotAccountTypes
944
1024
  );
945
1025
  case "ethereum":
946
1026
  return getEthereumAccounts$(
@@ -964,6 +1044,34 @@ var getAccounts$ = (config, wallets) => {
964
1044
  // src/api/store.ts
965
1045
  var import_lodash_es = require("lodash-es");
966
1046
  var DEFAULT_SETTINGS = {};
1047
+ var toCompactPolkadotAccountType = (type) => {
1048
+ switch (type) {
1049
+ case "sr25519":
1050
+ return 0;
1051
+ case "ed25519":
1052
+ return 1;
1053
+ case "ecdsa":
1054
+ return 2;
1055
+ case "ethereum":
1056
+ return 3;
1057
+ default:
1058
+ return null;
1059
+ }
1060
+ };
1061
+ var fromCompactPolkadotAccountType = (type) => {
1062
+ switch (type) {
1063
+ case 0:
1064
+ return "sr25519";
1065
+ case 1:
1066
+ return "ed25519";
1067
+ case 2:
1068
+ return "ecdsa";
1069
+ case 3:
1070
+ return "ethereum";
1071
+ default:
1072
+ return void 0;
1073
+ }
1074
+ };
967
1075
  var createKheopskitStore = (options = {}) => {
968
1076
  const { ssrCookies, storageKey = DEFAULT_STORAGE_KEY } = options;
969
1077
  const storage = ssrCookies !== void 0 ? createCompactCookieStorage(ssrCookies) : safeLocalStorage;
@@ -1039,7 +1147,9 @@ var toCompactStore = (data) => {
1039
1147
  (account) => [
1040
1148
  account.walletId,
1041
1149
  account.address,
1042
- account.name ?? null
1150
+ account.name ?? null,
1151
+ account.chainId ?? null,
1152
+ toCompactPolkadotAccountType(account.polkadotAccountType)
1043
1153
  ]
1044
1154
  );
1045
1155
  return {
@@ -1064,13 +1174,15 @@ var fromCompactStore = (data) => {
1064
1174
  };
1065
1175
  });
1066
1176
  const accounts = (data.a ?? []).map((item) => {
1067
- const [walletId, address, name] = item;
1177
+ const [walletId, address, name, chainId, polkadotAccountType] = item;
1068
1178
  const { platform } = parseWalletId(walletId);
1069
1179
  return {
1070
1180
  id: getWalletAccountId(walletId, address),
1071
1181
  platform,
1072
1182
  address,
1073
1183
  name: name ?? void 0,
1184
+ chainId: chainId ?? void 0,
1185
+ polkadotAccountType: platform === "polkadot" ? fromCompactPolkadotAccountType(polkadotAccountType) : void 0,
1074
1186
  walletId,
1075
1187
  walletName: walletNameMap.get(walletId) ?? walletId
1076
1188
  };
@@ -1400,7 +1512,9 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1400
1512
  }
1401
1513
  return wallet;
1402
1514
  });
1403
- const cachedAccounts = cachedState.accounts.map(hydrateAccount);
1515
+ const cachedAccounts = cachedState.accounts.map(hydrateAccount).filter(
1516
+ (account) => account.platform !== "polkadot" || kc.polkadotAccountTypes.includes(account.type)
1517
+ );
1404
1518
  if (kc.debug && cachedWallets.length > 0) {
1405
1519
  console.debug("[kheopskit] hydrating from cache:", {
1406
1520
  wallets: cachedWallets.length,
@@ -1532,7 +1646,9 @@ var getKheopskit$ = (config, ssrCookies, existingStore) => {
1532
1646
  var arraysEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
1533
1647
  var statesEqual = (a, b) => a.isHydrating === b.isHydrating && a.wallets.length === b.wallets.length && a.accounts.length === b.accounts.length && a.wallets.every(
1534
1648
  (w, i) => w.id === b.wallets[i]?.id && w.isConnected === b.wallets[i]?.isConnected
1535
- ) && a.accounts.every((acc, i) => acc.id === b.accounts[i]?.id);
1649
+ ) && a.accounts.every(
1650
+ (acc, i) => acc.id === b.accounts[i]?.id && (acc.platform !== "ethereum" || acc.chainId === b.accounts[i]?.chainId)
1651
+ );
1536
1652
  // Annotate the CommonJS export names for ESM import in node:
1537
1653
  0 && (module.exports = {
1538
1654
  DEFAULT_STORAGE_KEY,