@kheopskit/core 4.0.0 → 5.0.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.
Files changed (54) hide show
  1. package/dist/{chunk-SIUWQBT4.js → chunk-4ENHC7G4.js} +11 -2
  2. package/dist/chunk-4ENHC7G4.js.map +1 -0
  3. package/dist/{chunk-KWFQDD7E.mjs → chunk-6XAZANB5.mjs} +58 -186
  4. package/dist/chunk-6XAZANB5.mjs.map +1 -0
  5. package/dist/{chunk-PNPPI5CH.mjs → chunk-7QSGAJ4A.mjs} +11 -2
  6. package/dist/chunk-7QSGAJ4A.mjs.map +1 -0
  7. package/dist/{chunk-TMAPQWW2.js → chunk-B4L6GAYD.js} +24 -9
  8. package/dist/chunk-B4L6GAYD.js.map +1 -0
  9. package/dist/chunk-XQWJM3KC.js +450 -0
  10. package/dist/chunk-XQWJM3KC.js.map +1 -0
  11. package/dist/{chunk-4RBYRNY3.mjs → chunk-YDLCHYHH.mjs} +22 -7
  12. package/dist/chunk-YDLCHYHH.mjs.map +1 -0
  13. package/dist/ethereum.d.mts +4 -3
  14. package/dist/ethereum.d.ts +4 -3
  15. package/dist/ethereum.js +61 -42
  16. package/dist/ethereum.js.map +1 -1
  17. package/dist/ethereum.mjs +53 -34
  18. package/dist/ethereum.mjs.map +1 -1
  19. package/dist/index.d.mts +20 -6
  20. package/dist/index.d.ts +20 -6
  21. package/dist/index.js +253 -47
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +271 -65
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/internal.d.mts +4 -4
  26. package/dist/internal.d.ts +4 -4
  27. package/dist/internal.js +3 -3
  28. package/dist/internal.mjs +2 -2
  29. package/dist/polkadot.d.mts +4 -3
  30. package/dist/polkadot.d.ts +4 -3
  31. package/dist/polkadot.js +26 -37
  32. package/dist/polkadot.js.map +1 -1
  33. package/dist/polkadot.mjs +13 -24
  34. package/dist/polkadot.mjs.map +1 -1
  35. package/dist/solana.d.mts +5 -4
  36. package/dist/solana.d.ts +5 -4
  37. package/dist/solana.js +37 -42
  38. package/dist/solana.js.map +1 -1
  39. package/dist/solana.mjs +26 -31
  40. package/dist/solana.mjs.map +1 -1
  41. package/dist/{types-BNzRUNw-.d.mts → types-C7V7DGlg.d.mts} +47 -17
  42. package/dist/{types-BNzRUNw-.d.ts → types-C7V7DGlg.d.ts} +47 -17
  43. package/package.json +42 -16
  44. package/dist/chunk-4RBYRNY3.mjs.map +0 -1
  45. package/dist/chunk-FIAL4HTE.js +0 -1
  46. package/dist/chunk-FIAL4HTE.js.map +0 -1
  47. package/dist/chunk-KWFQDD7E.mjs.map +0 -1
  48. package/dist/chunk-NU46D4MZ.js +0 -578
  49. package/dist/chunk-NU46D4MZ.js.map +0 -1
  50. package/dist/chunk-PNPPI5CH.mjs.map +0 -1
  51. package/dist/chunk-SIUWQBT4.js.map +0 -1
  52. package/dist/chunk-TMAPQWW2.js.map +0 -1
  53. package/dist/chunk-YFD3IKK5.mjs +0 -1
  54. package/dist/chunk-YFD3IKK5.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/kheopskit/kheopskit/packages/core/dist/solana.js","../src/api/solana/chains.ts","../src/api/solana/accounts.ts","../src/api/solana/signer.ts","../src/api/solana/wallets.ts","../src/api/solana/plugin.ts"],"names":[],"mappings":"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","file":"/home/runner/work/kheopskit/kheopskit/packages/core/dist/solana.js","sourcesContent":[null,"import { KheopskitError } from \"../errors\";\n\n/**\n * Wallet Standard chain identifiers for Solana clusters.\n *\n * These are the values wallets advertise in their `chains` arrays and the\n * values kheopskit accepts in `config.solanaChain`.\n *\n * @see https://github.com/anza-xyz/wallet-standard\n */\nexport type SolanaChainId =\n\t| \"solana:mainnet\"\n\t| \"solana:devnet\"\n\t| \"solana:testnet\"\n\t| \"solana:localnet\";\n\nexport const DEFAULT_SOLANA_CHAIN: SolanaChainId = \"solana:mainnet\";\n\nconst SOLANA_CHAIN_IDS = [\n\t\"solana:mainnet\",\n\t\"solana:devnet\",\n\t\"solana:testnet\",\n\t\"solana:localnet\",\n] as const satisfies SolanaChainId[];\n\nexport const isSolanaChainId = (value: unknown): value is SolanaChainId =>\n\ttypeof value === \"string\" &&\n\t(SOLANA_CHAIN_IDS as readonly string[]).includes(value);\n\n/**\n * Maps Wallet Standard chain ids to the CAIP-2 chain ids used by WalletConnect.\n *\n * CAIP-2 ids use the first 32 characters of the cluster's genesis hash as the\n * reference. The values below match `@reown/appkit/networks` (solana,\n * solanaDevnet, solanaTestnet), which is what AppKit puts in session namespaces.\n *\n * `localnet` has no canonical CAIP-2 id and cannot be used over WalletConnect.\n */\nconst SOLANA_CHAIN_TO_CAIP2 = {\n\t\"solana:mainnet\": \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n\t\"solana:devnet\": \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n\t\"solana:testnet\": \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\",\n} as const satisfies Partial<Record<SolanaChainId, string>>;\n\n/**\n * Returns the CAIP-2 chain id for a Solana chain, for use in WalletConnect\n * requests and when reading WalletConnect session namespaces.\n *\n * @throws if the chain has no canonical CAIP-2 id (e.g. localnet)\n */\nexport const getSolanaCaip2 = (chain: SolanaChainId): string => {\n\tconst caip2 = (SOLANA_CHAIN_TO_CAIP2 as Record<string, string | undefined>)[\n\t\tchain\n\t];\n\tif (!caip2)\n\t\tthrow new KheopskitError(\n\t\t\t\"UNSUPPORTED_CHAIN\",\n\t\t\t`Solana chain \"${chain}\" cannot be used over WalletConnect (no CAIP-2 id).`,\n\t\t);\n\treturn caip2;\n};\n\nconst CAIP2_TO_SOLANA_CHAIN: Record<string, SolanaChainId> = Object.fromEntries(\n\tObject.entries(SOLANA_CHAIN_TO_CAIP2).map(([chain, caip2]) => [\n\t\tcaip2,\n\t\tchain as SolanaChainId,\n\t]),\n);\n\n/**\n * Maps a CAIP-2 chain id (as found in WalletConnect session namespaces) back to\n * its {@link SolanaChainId}, or `undefined` if it isn't a recognised cluster.\n */\nexport const getSolanaChainIdFromCaip2 = (\n\tcaip2: string,\n): SolanaChainId | undefined => CAIP2_TO_SOLANA_CHAIN[caip2];\n","import type { StandardEventsFeature } from \"@wallet-standard/features\";\nimport {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tshareReplay,\n\tswitchMap,\n} from \"rxjs\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport type { SolanaAppKitWallet } from \"../types\";\nimport { getSolanaChainIdFromCaip2, type SolanaChainId } from \"./chains\";\nimport {\n\tcreateInjectedSolanaSigner,\n\tcreateWalletConnectSolanaSigner,\n} from \"./signer\";\nimport type {\n\tSolanaAccount,\n\tSolanaInjectedWallet,\n\tSolanaWallet,\n} from \"./types\";\n\ntype StandardEventsApi = StandardEventsFeature[\"standard:events\"];\n\nconst getInjectedWalletAccounts$ = (\n\twallet: SolanaInjectedWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\tconst standardWallet = wallet.wallet;\n\n\t\t\tconst buildAccounts = (): SolanaAccount[] =>\n\t\t\t\tstandardWallet.accounts.map(\n\t\t\t\t\t(account): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, account.address),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: account.address,\n\t\t\t\t\t\tchains: wallet.chains,\n\t\t\t\t\t\tsigner: createInjectedSolanaSigner(standardWallet, account, chain),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateInjectedSolanaSigner(standardWallet, account, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-emit when the wallet's authorized accounts change.\n\t\t\tconst eventsFeature = (\n\t\t\t\tstandardWallet.features as Record<string, unknown>\n\t\t\t)[\"standard:events\"] as StandardEventsApi | undefined;\n\t\t\tconst off = eventsFeature?.on(\"change\", () =>\n\t\t\t\tsubscriber.next(buildAccounts()),\n\t\t\t);\n\n\t\t\treturn () => {\n\t\t\t\toff?.();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst getAppKitAccounts$ = (\n\twallet: SolanaAppKitWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"solana\");\n\n\tif (!wallet.isConnected || !provider?.session) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\t// AppKit has no native solana adapter, so getAccount(\"solana\").allAccounts\n\t\t\t// is always empty; the WalletConnect session is the source of truth.\n\t\t\t// Accounts are CAIP-10 strings (\"solana:<chainRef>:<address>\"), one entry\n\t\t\t// per chain, so dedupe to unique addresses.\n\t\t\tconst buildAccounts = (): SolanaAccount[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\n\t\t\t\tconst solanaCaip10s = Object.values(session.namespaces)\n\t\t\t\t\t.flatMap((namespace) => namespace.accounts ?? [])\n\t\t\t\t\t.filter((account) => account.startsWith(\"solana:\"));\n\n\t\t\t\tconst addresses = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\")[2])\n\t\t\t\t\t\t\t.filter((address): address is string => !!address),\n\t\t\t\t\t),\n\t\t\t\t];\n\n\t\t\t\t// Clusters the session actually advertises (\"solana:<chainRef>\" from\n\t\t\t\t// each CAIP-10 entry), mapped back to SolanaChainId. Falls back to the\n\t\t\t\t// configured chain when none are recognised.\n\t\t\t\tconst advertisedChains = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\").slice(0, 2).join(\":\"))\n\t\t\t\t\t\t\t.map(getSolanaChainIdFromCaip2)\n\t\t\t\t\t\t\t.filter((c): c is SolanaChainId => !!c),\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t\tconst chains = advertisedChains.length ? advertisedChains : [chain];\n\n\t\t\t\treturn addresses.map(\n\t\t\t\t\t(accountAddress): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, accountAddress),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: accountAddress,\n\t\t\t\t\t\tchains,\n\t\t\t\t\t\tsigner: createWalletConnectSolanaSigner(\n\t\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t\taccountAddress,\n\t\t\t\t\t\t\tchain,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateWalletConnectSolanaSigner(provider, accountAddress, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-derive when the WalletConnect session's accounts change, mirroring\n\t\t\t// the injected wallet's standard:events \"change\" subscription.\n\t\t\tconst reemit = () => subscriber.next(buildAccounts());\n\t\t\tprovider.on(\"session_update\", reemit);\n\t\t\tprovider.on(\"accountsChanged\", reemit);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"session_update\", reemit);\n\t\t\t\tprovider.off(\"accountsChanged\", reemit);\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getSolanaAccounts$ = (\n\tsolanaWallets$: Observable<SolanaWallet[]>,\n\tsolanaChain: SolanaChainId,\n) =>\n\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\tconst sub = solanaWallets$\n\t\t\t.pipe(\n\t\t\t\tmap((wallets) => wallets.filter((w) => w.isConnected)),\n\t\t\t\tswitchMap((wallets) =>\n\t\t\t\t\twallets.length\n\t\t\t\t\t\t? combineLatest([\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter((w) => w.type === \"injected\")\n\t\t\t\t\t\t\t\t\t.map((w) => getInjectedWalletAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter((w) => w.type === \"appKit\")\n\t\t\t\t\t\t\t\t\t.map((w) => getAppKitAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t: of([]),\n\t\t\t\t),\n\t\t\t\tmap((accounts) => accounts.flat()),\n\t\t\t\tdistinctUntilChanged(isSameAccountsList),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst isSameAccountsList = (a: SolanaAccount[], b: SolanaAccount[]) => {\n\tif (a.length !== b.length) return false;\n\treturn a.every((account, i) => {\n\t\tconst other = b[i];\n\t\tif (!other || account.id !== other.id) return false;\n\t\t// Re-emit when the advertised clusters change, not just on id changes.\n\t\tif (account.chains.length !== other.chains.length) return false;\n\t\treturn account.chains.every((chain, j) => chain === other.chains[j]);\n\t});\n};\n","import {\n\taddress,\n\tgetBase58Decoder,\n\tgetBase58Encoder,\n\tgetBase64Decoder,\n\tgetBase64Encoder,\n\tgetTransactionDecoder,\n\tgetTransactionEncoder,\n\ttype SignableMessage,\n\ttype SignatureBytes,\n\ttype TransactionModifyingSigner,\n} from \"@solana/kit\";\nimport type {\n\tSolanaSignAndSendTransactionFeature,\n\tSolanaSignMessageFeature,\n\tSolanaSignTransactionFeature,\n} from \"@solana/wallet-standard-features\";\nimport type {\n\tWalletAccount,\n\tWallet as WalletStandardWallet,\n} from \"@wallet-standard/base\";\nimport { KheopskitError } from \"../errors\";\nimport type { WalletConnectProvider } from \"../types\";\nimport { getSolanaCaip2, type SolanaChainId } from \"./chains\";\nimport type { SolanaSigner } from \"./types\";\n\nconst SOLANA_SIGN_MESSAGE = \"solana:signMessage\";\nconst SOLANA_SIGN_TRANSACTION = \"solana:signTransaction\";\nconst SOLANA_SIGN_AND_SEND_TRANSACTION = \"solana:signAndSendTransaction\";\n\ntype SignMessageApi = SolanaSignMessageFeature[typeof SOLANA_SIGN_MESSAGE];\ntype SignTransactionApi =\n\tSolanaSignTransactionFeature[typeof SOLANA_SIGN_TRANSACTION];\ntype SignAndSendApi =\n\tSolanaSignAndSendTransactionFeature[typeof SOLANA_SIGN_AND_SEND_TRANSACTION];\n\n/** The branded array type expected back from a transaction-modifying signer. */\ntype SignedTransactions = Awaited<\n\tReturnType<TransactionModifyingSigner[\"modifyAndSignTransactions\"]>\n>;\n\nconst requireFeature = <T>(wallet: WalletStandardWallet, name: string): T => {\n\tconst feature = (wallet.features as Record<string, unknown>)[name];\n\tif (!feature)\n\t\tthrow new KheopskitError(\n\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t`wallet \"${wallet.name}\" does not support ${name}`,\n\t\t);\n\treturn feature as T;\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a Wallet Standard wallet's\n * `solana:*` features (injected wallets).\n *\n * Transactions are exchanged as wire bytes; messages and signatures as raw\n * bytes. Calling a method whose feature the wallet does not advertise throws.\n */\nexport const createInjectedSolanaSigner = (\n\twallet: WalletStandardWallet,\n\taccount: WalletAccount,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(account.address);\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\tconst feature = requireFeature<SignMessageApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_MESSAGE,\n\t\t\t);\n\t\t\tconst outputs = await feature.signMessage(\n\t\t\t\t...messages.map((m) => ({ account, message: m.content })),\n\t\t\t);\n\t\t\treturn messages.map((m, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output) throw new Error(\"[kheopskit] missing signMessage output\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: output.signedMessage,\n\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t[signerAddress]: output.signature as SignatureBytes,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SignableMessage;\n\t\t\t});\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignTransactionApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst outputs = await feature.signTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn transactions.map((_tx, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output)\n\t\t\t\t\tthrow new Error(\"[kheopskit] missing signTransaction output\");\n\t\t\t\treturn decoder.decode(output.signedTransaction);\n\t\t\t}) as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignAndSendApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_AND_SEND_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst outputs = await feature.signAndSendTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn outputs.map((output) => output.signature as SignatureBytes);\n\t\t},\n\t};\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a WalletConnect session, adapting the\n * `solana_*` RPC methods to the same interface as the injected signer.\n *\n * The CAIP-2 chain id is derived from {@link SolanaChainId}; transactions are\n * base64-encoded and messages/signatures base58-encoded, per the WalletConnect\n * Solana spec.\n */\nexport const createWalletConnectSolanaSigner = (\n\tprovider: WalletConnectProvider,\n\taccountAddress: string,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(accountAddress);\n\n\tconst request = <T>(method: string, params: unknown): Promise<T> => {\n\t\tif (!provider.session)\n\t\t\tthrow new KheopskitError(\"NO_SESSION\", \"No session found\");\n\t\t// Resolved lazily (not at signer construction) so building a signer for a\n\t\t// cluster without a CAIP-2 id (e.g. localnet) doesn't throw until a request\n\t\t// is actually attempted.\n\t\treturn provider.client.request<T>({\n\t\t\ttopic: provider.session.topic,\n\t\t\tchainId: getSolanaCaip2(chain),\n\t\t\trequest: { method, params },\n\t\t});\n\t};\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\t// @solana/kit naming is the inverse of the value direction here: a\n\t\t\t// Decoder turns bytes -> string (so `toBase58` produces a base58 string),\n\t\t\t// an Encoder turns string -> bytes (so `fromBase58` parses one).\n\t\t\tconst toBase58 = getBase58Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\tmessages.map(async (m) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signMessage\",\n\t\t\t\t\t\t{ pubkey: accountAddress, message: toBase58.decode(m.content) },\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: m.content,\n\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(signature) as SignatureBytes,\n\t\t\t\t\t\t},\n\t\t\t\t\t} satisfies SignableMessage;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase64 = getBase64Encoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\tconst signed = await Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst result = await request<{\n\t\t\t\t\t\ttransaction?: string;\n\t\t\t\t\t\tsignature?: string;\n\t\t\t\t\t}>(\"solana_signTransaction\", {\n\t\t\t\t\t\ttransaction: toBase64.decode(encoder.encode(tx)),\n\t\t\t\t\t});\n\t\t\t\t\t// Wallets may return either the full signed transaction (base64)\n\t\t\t\t\t// or just the signature (base58) to merge into the original.\n\t\t\t\t\tif (result.transaction)\n\t\t\t\t\t\treturn decoder.decode(fromBase64.encode(result.transaction));\n\t\t\t\t\tif (result.signature)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...tx,\n\t\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t\t...tx.signatures,\n\t\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(\n\t\t\t\t\t\t\t\t\tresult.signature,\n\t\t\t\t\t\t\t\t) as SignatureBytes,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"[kheopskit] solana_signTransaction returned no transaction or signature\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn signed as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signAndSendTransaction\",\n\t\t\t\t\t\t{ transaction: toBase64.decode(encoder.encode(tx)) },\n\t\t\t\t\t);\n\t\t\t\t\treturn fromBase58.encode(signature) as SignatureBytes;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t};\n};\n","import { getWallets } from \"@wallet-standard/app\";\nimport type { Wallet as WalletStandardWallet } from \"@wallet-standard/base\";\nimport type {\n\tStandardConnectFeature,\n\tStandardDisconnectFeature,\n} from \"@wallet-standard/features\";\nimport {\n\tBehaviorSubject,\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tshareReplay,\n} from \"rxjs\";\nimport { clearCachedObservablesByPrefix } from \"../../utils/getCachedObservable\";\nimport { getWalletId, type WalletId } from \"../../utils/WalletId\";\nimport { getAppKitWallets$ } from \"../appKit\";\nimport { KheopskitError } from \"../errors\";\nimport { store as defaultStore, type KheopskitStore } from \"../store\";\nimport type { KheopskitConfig } from \"../types\";\nimport { isSolanaChainId, type SolanaChainId } from \"./chains\";\nimport type { SolanaInjectedWallet, SolanaWallet } from \"./types\";\n\ntype ConnectApi = StandardConnectFeature[\"standard:connect\"];\ntype DisconnectApi = StandardDisconnectFeature[\"standard:disconnect\"];\n\nconst SOLANA_NAMESPACE_PREFIX = \"solana:\";\n\n/** A Wallet Standard wallet is Solana-capable if it advertises a solana chain or feature. */\nconst isSolanaWallet = (wallet: WalletStandardWallet): boolean =>\n\twallet.chains.some((chain) => chain.startsWith(SOLANA_NAMESPACE_PREFIX)) ||\n\tObject.keys(wallet.features).some((feature) =>\n\t\tfeature.startsWith(SOLANA_NAMESPACE_PREFIX),\n\t);\n\nconst getSolanaChains = (wallet: WalletStandardWallet): SolanaChainId[] =>\n\twallet.chains.filter((chain): chain is SolanaChainId =>\n\t\tisSolanaChainId(chain),\n\t);\n\n/**\n * Observable of Solana-capable Wallet Standard wallets, updated as wallets\n * register/unregister. Returns an empty array during SSR.\n */\nconst walletStandardWallets$ = new Observable<readonly WalletStandardWallet[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - the Wallet Standard registry requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst { get, on } = getWallets();\n\t\tconst emit = () => subscriber.next(get().filter(isSolanaWallet));\n\n\t\temit();\n\n\t\tconst offRegister = on(\"register\", emit);\n\t\tconst offUnregister = on(\"unregister\", emit);\n\n\t\treturn () => {\n\t\t\toffRegister();\n\t\t\toffUnregister();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst createSolanaInjectedWallets$ = (store: KheopskitStore) =>\n\tnew Observable<SolanaInjectedWallet[]>((subscriber) => {\n\t\tconst enabledWalletIds$ = new BehaviorSubject<Set<WalletId>>(new Set());\n\n\t\tconst connect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_ALREADY_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is already connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:connect\"\n\t\t\t] as ConnectApi | undefined;\n\t\t\tif (!feature)\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t\t\t`wallet ${walletId} does not support standard:connect`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tawait feature.connect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.add(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.addEnabledWalletId(walletId);\n\t\t};\n\n\t\tconst disconnect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (!enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_NOT_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is not connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\t// standard:disconnect is an optional feature. Await it when present so a\n\t\t\t// failed disconnect rejects the returned promise; if absent we still\n\t\t\t// clear local state below.\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:disconnect\"\n\t\t\t] as DisconnectApi | undefined;\n\t\t\tawait feature?.disconnect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.delete(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.removeEnabledWalletId(walletId);\n\n\t\t\t// Drop cached account observables for this wallet so a later reconnect\n\t\t\t// rebuilds them against the current wallet handle, not a stale closure.\n\t\t\tclearCachedObservablesByPrefix(`accounts:${walletId}:`);\n\t\t};\n\n\t\tconst sub = combineLatest([walletStandardWallets$, enabledWalletIds$])\n\t\t\t.pipe(\n\t\t\t\tmap(([wallets, enabledWalletIds]) =>\n\t\t\t\t\twallets.map((wallet): SolanaInjectedWallet => {\n\t\t\t\t\t\tconst walletId = getWalletId(\"solana\", wallet.name);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\t\ttype: \"injected\",\n\t\t\t\t\t\t\tid: walletId,\n\t\t\t\t\t\t\tsourceId: wallet.name,\n\t\t\t\t\t\t\twallet,\n\t\t\t\t\t\t\tchains: getSolanaChains(wallet),\n\t\t\t\t\t\t\tname: wallet.name,\n\t\t\t\t\t\t\ticon: wallet.icon,\n\t\t\t\t\t\t\tisConnected: enabledWalletIds.has(walletId),\n\t\t\t\t\t\t\tconnect: () => connect(wallet, walletId),\n\t\t\t\t\t\t\tdisconnect: () => disconnect(wallet, walletId),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tdistinctUntilChanged(walletsEqual),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nexport const getSolanaWallets$ = (\n\tconfig: KheopskitConfig,\n\tstore: KheopskitStore = defaultStore,\n) => {\n\treturn new Observable<SolanaWallet[]>((subscriber) => {\n\t\tconst subscription = combineLatest([\n\t\t\tcreateSolanaInjectedWallets$(store),\n\t\t\tgetAppKitWallets$(config).pipe(map((w) => w.solana)),\n\t\t])\n\t\t\t.pipe(\n\t\t\t\tmap(([injectedWallets, appKitWallet]) =>\n\t\t\t\t\tappKitWallet ? [...injectedWallets, appKitWallet] : injectedWallets,\n\t\t\t\t),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n};\n\n/**\n * Compare two wallet arrays by their relevant properties (not functions).\n */\nconst walletsEqual = (\n\ta: SolanaInjectedWallet[],\n\tb: SolanaInjectedWallet[],\n): boolean => {\n\tif (a.length !== b.length) return false;\n\treturn a.every(\n\t\t(w, i) =>\n\t\t\tw.id === b[i]?.id &&\n\t\t\tw.isConnected === b[i]?.isConnected &&\n\t\t\tw.name === b[i]?.name,\n\t);\n};\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getSolanaAccounts$ } from \"./accounts\";\nimport {\n\tDEFAULT_SOLANA_CHAIN,\n\tisSolanaChainId,\n\ttype SolanaChainId,\n} from \"./chains\";\nimport type { SolanaAccount, SolanaWallet } from \"./types\";\nimport { getSolanaWallets$ } from \"./wallets\";\n\nexport type SolanaPluginOptions = {\n\t/**\n\t * Solana cluster that account signers target. Each account also exposes a\n\t * `getSigner(chain)` factory for targeting another cluster.\n\t *\n\t * @default \"solana:mainnet\"\n\t */\n\tchain?: SolanaChainId;\n};\n\n/**\n * Solana platform plugin. Pass to `getKheopskit$({ platforms: [solana()] })`.\n *\n * @example\n * ```ts\n * import { solana } from \"@kheopskit/core/solana\";\n * solana({ chain: \"solana:mainnet\" });\n * ```\n */\nexport const solana = (\n\toptions: SolanaPluginOptions = {},\n): KheopskitPlatform<\"solana\", SolanaWallet, SolanaAccount> => {\n\tconst chain = options.chain ?? DEFAULT_SOLANA_CHAIN;\n\n\tif (!isSolanaChainId(chain)) {\n\t\tconsole.warn(\n\t\t\t`[kheopskit] Unknown solana chain: ${JSON.stringify(chain)}. Valid values: \"solana:mainnet\", \"solana:devnet\", \"solana:testnet\", \"solana:localnet\".`,\n\t\t);\n\t}\n\n\treturn {\n\t\tplatform: \"solana\",\n\t\tgetWallets$: (ctx: PlatformContext) =>\n\t\t\tgetSolanaWallets$(ctx.config, ctx.store),\n\t\tgetAccounts$: (wallets$) => getSolanaAccounts$(wallets$, chain),\n\t};\n};\n"]}
1
+ {"version":3,"sources":["/home/runner/work/kheopskit/kheopskit/packages/core/dist/solana.js","../src/api/solana/chains.ts","../src/api/solana/accounts.ts","../src/api/solana/signer.ts","../src/api/solana/wallets.ts","../src/api/solana/plugin.ts"],"names":[],"mappings":"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","file":"/home/runner/work/kheopskit/kheopskit/packages/core/dist/solana.js","sourcesContent":[null,"import { KheopskitError } from \"../errors\";\n\n/**\n * Wallet Standard chain identifiers for Solana clusters.\n *\n * These are the values wallets advertise in their `chains` arrays and the\n * values kheopskit accepts in `solana({ chain })`.\n *\n * @see https://github.com/anza-xyz/wallet-standard\n */\nexport type SolanaChainId =\n\t| \"solana:mainnet\"\n\t| \"solana:devnet\"\n\t| \"solana:testnet\"\n\t| \"solana:localnet\";\n\nexport const DEFAULT_SOLANA_CHAIN: SolanaChainId = \"solana:mainnet\";\n\nconst SOLANA_CHAIN_IDS = [\n\t\"solana:mainnet\",\n\t\"solana:devnet\",\n\t\"solana:testnet\",\n\t\"solana:localnet\",\n] as const satisfies SolanaChainId[];\n\nexport const isSolanaChainId = (value: unknown): value is SolanaChainId =>\n\ttypeof value === \"string\" &&\n\t(SOLANA_CHAIN_IDS as readonly string[]).includes(value);\n\n/**\n * Maps Wallet Standard chain ids to the CAIP-2 chain ids used by WalletConnect.\n *\n * CAIP-2 ids use the first 32 characters of the cluster's genesis hash as the\n * reference. The values below match `@reown/appkit/networks` (solana,\n * solanaDevnet, solanaTestnet), which is what AppKit puts in session namespaces.\n *\n * `localnet` has no canonical CAIP-2 id and cannot be used over WalletConnect.\n */\nconst SOLANA_CHAIN_TO_CAIP2 = {\n\t\"solana:mainnet\": \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n\t\"solana:devnet\": \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n\t\"solana:testnet\": \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\",\n} as const satisfies Partial<Record<SolanaChainId, string>>;\n\n/**\n * Returns the CAIP-2 chain id for a Solana chain, for use in WalletConnect\n * requests and when reading WalletConnect session namespaces.\n *\n * @throws if the chain has no canonical CAIP-2 id (e.g. localnet)\n */\nexport const getSolanaCaip2 = (chain: SolanaChainId): string => {\n\tconst caip2 = (SOLANA_CHAIN_TO_CAIP2 as Record<string, string | undefined>)[\n\t\tchain\n\t];\n\tif (!caip2)\n\t\tthrow new KheopskitError(\n\t\t\t\"UNSUPPORTED_CHAIN\",\n\t\t\t`Solana chain \"${chain}\" cannot be used over WalletConnect (no CAIP-2 id).`,\n\t\t);\n\treturn caip2;\n};\n\n/**\n * AppKit's *deprecated* CAIP-2 cluster ids (its `deprecatedCaipNetworkId`\n * values). Some wallets still place accounts in the WC session under these, so\n * map them back to a {@link SolanaChainId} instead of silently falling back to\n * the configured chain. Requests always use the current ids from\n * {@link SOLANA_CHAIN_TO_CAIP2}; testnet has no deprecated id.\n */\nconst DEPRECATED_CAIP2_TO_SOLANA_CHAIN: Record<string, SolanaChainId> = {\n\t\"solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ\": \"solana:mainnet\",\n\t\"solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K\": \"solana:devnet\",\n};\n\nconst CAIP2_TO_SOLANA_CHAIN: Record<string, SolanaChainId> = {\n\t...Object.fromEntries(\n\t\tObject.entries(SOLANA_CHAIN_TO_CAIP2).map(([chain, caip2]) => [\n\t\t\tcaip2,\n\t\t\tchain as SolanaChainId,\n\t\t]),\n\t),\n\t...DEPRECATED_CAIP2_TO_SOLANA_CHAIN,\n};\n\n/**\n * Maps a CAIP-2 chain id (as found in WalletConnect session namespaces) back to\n * its {@link SolanaChainId}, or `undefined` if it isn't a recognised cluster.\n */\nexport const getSolanaChainIdFromCaip2 = (\n\tcaip2: string,\n): SolanaChainId | undefined => CAIP2_TO_SOLANA_CHAIN[caip2];\n","import type { StandardEventsFeature } from \"@wallet-standard/features\";\nimport {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tshareReplay,\n\tswitchMap,\n} from \"rxjs\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport type { WalletConnectWallet } from \"../types\";\nimport { isWalletConnectWallet } from \"../types\";\nimport { getSolanaChainIdFromCaip2, type SolanaChainId } from \"./chains\";\nimport {\n\tcreateInjectedSolanaSigner,\n\tcreateWalletConnectSolanaSigner,\n} from \"./signer\";\nimport type {\n\tSolanaAccount,\n\tSolanaInjectedWallet,\n\tSolanaWallet,\n} from \"./types\";\n\ntype StandardEventsApi = StandardEventsFeature[\"standard:events\"];\n\nconst getInjectedWalletAccounts$ = (\n\twallet: SolanaInjectedWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\tconst standardWallet = wallet.wallet;\n\n\t\t\tconst buildAccounts = (): SolanaAccount[] =>\n\t\t\t\tstandardWallet.accounts.map(\n\t\t\t\t\t(account): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, account.address),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: account.address,\n\t\t\t\t\t\tchains: wallet.chains,\n\t\t\t\t\t\tsigner: createInjectedSolanaSigner(standardWallet, account, chain),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateInjectedSolanaSigner(standardWallet, account, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-emit when the wallet's authorized accounts change.\n\t\t\tconst eventsFeature = (\n\t\t\t\tstandardWallet.features as Record<string, unknown>\n\t\t\t)[\"standard:events\"] as StandardEventsApi | undefined;\n\t\t\tconst off = eventsFeature?.on(\"change\", () =>\n\t\t\t\tsubscriber.next(buildAccounts()),\n\t\t\t);\n\n\t\t\treturn () => {\n\t\t\t\toff?.();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst getWalletConnectAccounts$ = (\n\twallet: WalletConnectWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"solana\");\n\n\tif (!wallet.platforms.includes(\"solana\") || !provider?.session) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:solana:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\t// AppKit has no native solana adapter, so getAccount(\"solana\").allAccounts\n\t\t\t// is always empty; the WalletConnect session is the source of truth.\n\t\t\t// Accounts are CAIP-10 strings (\"solana:<chainRef>:<address>\"), one entry\n\t\t\t// per chain, so dedupe to unique addresses.\n\t\t\tconst buildAccounts = (): SolanaAccount[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\n\t\t\t\tconst solanaCaip10s = Object.values(session.namespaces)\n\t\t\t\t\t.flatMap((namespace) => namespace.accounts ?? [])\n\t\t\t\t\t.filter((account) => account.startsWith(\"solana:\"));\n\n\t\t\t\tconst addresses = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\")[2])\n\t\t\t\t\t\t\t.filter((address): address is string => !!address),\n\t\t\t\t\t),\n\t\t\t\t];\n\n\t\t\t\t// Clusters the session actually advertises (\"solana:<chainRef>\" from\n\t\t\t\t// each CAIP-10 entry), mapped back to SolanaChainId. Falls back to the\n\t\t\t\t// configured chain when none are recognised.\n\t\t\t\tconst advertisedChains = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\").slice(0, 2).join(\":\"))\n\t\t\t\t\t\t\t.map(getSolanaChainIdFromCaip2)\n\t\t\t\t\t\t\t.filter((c): c is SolanaChainId => !!c),\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t\tconst chains = advertisedChains.length ? advertisedChains : [chain];\n\n\t\t\t\treturn addresses.map(\n\t\t\t\t\t(accountAddress): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, accountAddress),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: accountAddress,\n\t\t\t\t\t\tchains,\n\t\t\t\t\t\tsigner: createWalletConnectSolanaSigner(\n\t\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t\taccountAddress,\n\t\t\t\t\t\t\tchain,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateWalletConnectSolanaSigner(provider, accountAddress, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-derive when the WalletConnect session's accounts change, mirroring\n\t\t\t// the injected wallet's standard:events \"change\" subscription.\n\t\t\tconst reemit = () => subscriber.next(buildAccounts());\n\t\t\tprovider.on(\"session_update\", reemit);\n\t\t\tprovider.on(\"accountsChanged\", reemit);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"session_update\", reemit);\n\t\t\t\tprovider.off(\"accountsChanged\", reemit);\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getSolanaAccounts$ = (\n\tsolanaWallets$: Observable<(SolanaWallet | WalletConnectWallet)[]>,\n\tsolanaChain: SolanaChainId,\n) =>\n\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\tconst sub = solanaWallets$\n\t\t\t.pipe(\n\t\t\t\tmap((wallets) => wallets.filter((w) => w.isConnected)),\n\t\t\t\tswitchMap((wallets) =>\n\t\t\t\t\twallets.length\n\t\t\t\t\t\t? combineLatest([\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter((w) => w.type === \"injected\")\n\t\t\t\t\t\t\t\t\t.map((w) => getInjectedWalletAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter(isWalletConnectWallet)\n\t\t\t\t\t\t\t\t\t.map((w) => getWalletConnectAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t: of([]),\n\t\t\t\t),\n\t\t\t\tmap((accounts) => accounts.flat()),\n\t\t\t\tdistinctUntilChanged(isSameAccountsList),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst isSameAccountsList = (a: SolanaAccount[], b: SolanaAccount[]) => {\n\tif (a.length !== b.length) return false;\n\treturn a.every((account, i) => {\n\t\tconst other = b[i];\n\t\tif (!other || account.id !== other.id) return false;\n\t\t// Re-emit when the advertised clusters change, not just on id changes.\n\t\tif (account.chains.length !== other.chains.length) return false;\n\t\treturn account.chains.every((chain, j) => chain === other.chains[j]);\n\t});\n};\n","import {\n\taddress,\n\tgetBase58Decoder,\n\tgetBase58Encoder,\n\tgetBase64Decoder,\n\tgetBase64Encoder,\n\tgetTransactionDecoder,\n\tgetTransactionEncoder,\n\ttype SignableMessage,\n\ttype SignatureBytes,\n\ttype TransactionModifyingSigner,\n} from \"@solana/kit\";\nimport type {\n\tSolanaSignAndSendTransactionFeature,\n\tSolanaSignMessageFeature,\n\tSolanaSignTransactionFeature,\n} from \"@solana/wallet-standard-features\";\nimport type {\n\tWalletAccount,\n\tWallet as WalletStandardWallet,\n} from \"@wallet-standard/base\";\nimport { KheopskitError } from \"../errors\";\nimport type { WalletConnectProvider } from \"../types\";\nimport { getSolanaCaip2, type SolanaChainId } from \"./chains\";\nimport type { SolanaSigner } from \"./types\";\n\nconst SOLANA_SIGN_MESSAGE = \"solana:signMessage\";\nconst SOLANA_SIGN_TRANSACTION = \"solana:signTransaction\";\nconst SOLANA_SIGN_AND_SEND_TRANSACTION = \"solana:signAndSendTransaction\";\n\ntype SignMessageApi = SolanaSignMessageFeature[typeof SOLANA_SIGN_MESSAGE];\ntype SignTransactionApi =\n\tSolanaSignTransactionFeature[typeof SOLANA_SIGN_TRANSACTION];\ntype SignAndSendApi =\n\tSolanaSignAndSendTransactionFeature[typeof SOLANA_SIGN_AND_SEND_TRANSACTION];\n\n/** The branded array type expected back from a transaction-modifying signer. */\ntype SignedTransactions = Awaited<\n\tReturnType<TransactionModifyingSigner[\"modifyAndSignTransactions\"]>\n>;\n\nconst requireFeature = <T>(wallet: WalletStandardWallet, name: string): T => {\n\tconst feature = (wallet.features as Record<string, unknown>)[name];\n\tif (!feature)\n\t\tthrow new KheopskitError(\n\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t`wallet \"${wallet.name}\" does not support ${name}`,\n\t\t);\n\treturn feature as T;\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a Wallet Standard wallet's\n * `solana:*` features (injected wallets).\n *\n * Transactions are exchanged as wire bytes; messages and signatures as raw\n * bytes. Calling a method whose feature the wallet does not advertise throws.\n */\nexport const createInjectedSolanaSigner = (\n\twallet: WalletStandardWallet,\n\taccount: WalletAccount,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(account.address);\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\tconst feature = requireFeature<SignMessageApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_MESSAGE,\n\t\t\t);\n\t\t\tconst outputs = await feature.signMessage(\n\t\t\t\t...messages.map((m) => ({ account, message: m.content })),\n\t\t\t);\n\t\t\treturn messages.map((m, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output) throw new Error(\"[kheopskit] missing signMessage output\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: output.signedMessage,\n\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t[signerAddress]: output.signature as SignatureBytes,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SignableMessage;\n\t\t\t});\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignTransactionApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst outputs = await feature.signTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn transactions.map((_tx, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output)\n\t\t\t\t\tthrow new Error(\"[kheopskit] missing signTransaction output\");\n\t\t\t\treturn decoder.decode(output.signedTransaction);\n\t\t\t}) as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignAndSendApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_AND_SEND_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst outputs = await feature.signAndSendTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn outputs.map((output) => output.signature as SignatureBytes);\n\t\t},\n\t};\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a WalletConnect session, adapting the\n * `solana_*` RPC methods to the same interface as the injected signer.\n *\n * The CAIP-2 chain id is derived from {@link SolanaChainId}; transactions are\n * base64-encoded and messages/signatures base58-encoded, per the WalletConnect\n * Solana spec.\n */\nexport const createWalletConnectSolanaSigner = (\n\tprovider: WalletConnectProvider,\n\taccountAddress: string,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(accountAddress);\n\n\tconst request = <T>(method: string, params: unknown): Promise<T> => {\n\t\tif (!provider.session)\n\t\t\tthrow new KheopskitError(\"NO_SESSION\", \"No session found\");\n\t\t// Resolved lazily (not at signer construction) so building a signer for a\n\t\t// cluster without a CAIP-2 id (e.g. localnet) doesn't throw until a request\n\t\t// is actually attempted.\n\t\treturn provider.client.request<T>({\n\t\t\ttopic: provider.session.topic,\n\t\t\tchainId: getSolanaCaip2(chain),\n\t\t\trequest: { method, params },\n\t\t});\n\t};\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\t// @solana/kit naming is the inverse of the value direction here: a\n\t\t\t// Decoder turns bytes -> string (so `toBase58` produces a base58 string),\n\t\t\t// an Encoder turns string -> bytes (so `fromBase58` parses one).\n\t\t\tconst toBase58 = getBase58Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\tmessages.map(async (m) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signMessage\",\n\t\t\t\t\t\t{ pubkey: accountAddress, message: toBase58.decode(m.content) },\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: m.content,\n\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(signature) as SignatureBytes,\n\t\t\t\t\t\t},\n\t\t\t\t\t} satisfies SignableMessage;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase64 = getBase64Encoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\tconst signed = await Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst result = await request<{\n\t\t\t\t\t\ttransaction?: string;\n\t\t\t\t\t\tsignature?: string;\n\t\t\t\t\t}>(\"solana_signTransaction\", {\n\t\t\t\t\t\ttransaction: toBase64.decode(encoder.encode(tx)),\n\t\t\t\t\t});\n\t\t\t\t\t// Wallets may return either the full signed transaction (base64)\n\t\t\t\t\t// or just the signature (base58) to merge into the original.\n\t\t\t\t\tif (result.transaction)\n\t\t\t\t\t\treturn decoder.decode(fromBase64.encode(result.transaction));\n\t\t\t\t\tif (result.signature)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...tx,\n\t\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t\t...tx.signatures,\n\t\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(\n\t\t\t\t\t\t\t\t\tresult.signature,\n\t\t\t\t\t\t\t\t) as SignatureBytes,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"[kheopskit] solana_signTransaction returned no transaction or signature\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn signed as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signAndSendTransaction\",\n\t\t\t\t\t\t{ transaction: toBase64.decode(encoder.encode(tx)) },\n\t\t\t\t\t);\n\t\t\t\t\treturn fromBase58.encode(signature) as SignatureBytes;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t};\n};\n","import { getWallets } from \"@wallet-standard/app\";\nimport type { Wallet as WalletStandardWallet } from \"@wallet-standard/base\";\nimport type {\n\tStandardConnectFeature,\n\tStandardDisconnectFeature,\n} from \"@wallet-standard/features\";\nimport {\n\tBehaviorSubject,\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tshareReplay,\n} from \"rxjs\";\nimport { clearCachedObservablesByPrefix } from \"../../utils/getCachedObservable\";\nimport { getWalletId, type WalletId } from \"../../utils/WalletId\";\nimport { KheopskitError } from \"../errors\";\nimport { store as defaultStore, type KheopskitStore } from \"../store\";\nimport { isSolanaChainId, type SolanaChainId } from \"./chains\";\nimport type { SolanaInjectedWallet } from \"./types\";\n\ntype ConnectApi = StandardConnectFeature[\"standard:connect\"];\ntype DisconnectApi = StandardDisconnectFeature[\"standard:disconnect\"];\n\nconst SOLANA_NAMESPACE_PREFIX = \"solana:\";\n\n/** A Wallet Standard wallet is Solana-capable if it advertises a solana chain or feature. */\nconst isSolanaWallet = (wallet: WalletStandardWallet): boolean =>\n\twallet.chains.some((chain) => chain.startsWith(SOLANA_NAMESPACE_PREFIX)) ||\n\tObject.keys(wallet.features).some((feature) =>\n\t\tfeature.startsWith(SOLANA_NAMESPACE_PREFIX),\n\t);\n\nconst getSolanaChains = (wallet: WalletStandardWallet): SolanaChainId[] =>\n\twallet.chains.filter((chain): chain is SolanaChainId =>\n\t\tisSolanaChainId(chain),\n\t);\n\n/**\n * Observable of Solana-capable Wallet Standard wallets, updated as wallets\n * register/unregister. Returns an empty array during SSR.\n */\nconst walletStandardWallets$ = new Observable<readonly WalletStandardWallet[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - the Wallet Standard registry requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst { get, on } = getWallets();\n\t\tconst emit = () => subscriber.next(get().filter(isSolanaWallet));\n\n\t\temit();\n\n\t\tconst offRegister = on(\"register\", emit);\n\t\tconst offUnregister = on(\"unregister\", emit);\n\n\t\treturn () => {\n\t\t\toffRegister();\n\t\t\toffUnregister();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst createSolanaInjectedWallets$ = (store: KheopskitStore) =>\n\tnew Observable<SolanaInjectedWallet[]>((subscriber) => {\n\t\tconst enabledWalletIds$ = new BehaviorSubject<Set<WalletId>>(new Set());\n\n\t\tconst connect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_ALREADY_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is already connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:connect\"\n\t\t\t] as ConnectApi | undefined;\n\t\t\tif (!feature)\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t\t\t`wallet ${walletId} does not support standard:connect`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tawait feature.connect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.add(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.addEnabledWalletId(walletId);\n\t\t};\n\n\t\tconst disconnect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (!enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_NOT_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is not connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\t// standard:disconnect is an optional feature. Await it when present so a\n\t\t\t// failed disconnect rejects the returned promise; if absent we still\n\t\t\t// clear local state below.\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:disconnect\"\n\t\t\t] as DisconnectApi | undefined;\n\t\t\tawait feature?.disconnect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.delete(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.removeEnabledWalletId(walletId);\n\n\t\t\t// Drop cached account observables for this wallet so a later reconnect\n\t\t\t// rebuilds them against the current wallet handle, not a stale closure.\n\t\t\tclearCachedObservablesByPrefix(`accounts:${walletId}:`);\n\t\t};\n\n\t\tconst sub = combineLatest([walletStandardWallets$, enabledWalletIds$])\n\t\t\t.pipe(\n\t\t\t\tmap(([wallets, enabledWalletIds]) =>\n\t\t\t\t\twallets.map((wallet): SolanaInjectedWallet => {\n\t\t\t\t\t\tconst walletId = getWalletId(\"solana\", wallet.name);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\t\ttype: \"injected\",\n\t\t\t\t\t\t\tid: walletId,\n\t\t\t\t\t\t\tsourceId: wallet.name,\n\t\t\t\t\t\t\twallet,\n\t\t\t\t\t\t\tchains: getSolanaChains(wallet),\n\t\t\t\t\t\t\tname: wallet.name,\n\t\t\t\t\t\t\ticon: wallet.icon,\n\t\t\t\t\t\t\tisConnected: enabledWalletIds.has(walletId),\n\t\t\t\t\t\t\tconnect: () => connect(wallet, walletId),\n\t\t\t\t\t\t\tdisconnect: () => disconnect(wallet, walletId),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tdistinctUntilChanged(walletsEqual),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\n// The shared WalletConnect connector is emitted once by core (see\n// `getWallets$`), not per platform — so this returns only injected wallets.\nexport const getSolanaWallets$ = (store: KheopskitStore = defaultStore) =>\n\tcreateSolanaInjectedWallets$(store);\n\n/**\n * Compare two wallet arrays by their relevant properties (not functions).\n */\nconst walletsEqual = (\n\ta: SolanaInjectedWallet[],\n\tb: SolanaInjectedWallet[],\n): boolean => {\n\tif (a.length !== b.length) return false;\n\treturn a.every(\n\t\t(w, i) =>\n\t\t\tw.id === b[i]?.id &&\n\t\t\tw.isConnected === b[i]?.isConnected &&\n\t\t\tw.name === b[i]?.name,\n\t);\n};\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getSolanaAccounts$ } from \"./accounts\";\nimport {\n\tDEFAULT_SOLANA_CHAIN,\n\tisSolanaChainId,\n\ttype SolanaChainId,\n} from \"./chains\";\nimport type { SolanaAccount, SolanaWallet } from \"./types\";\nimport { getSolanaWallets$ } from \"./wallets\";\n\nexport type SolanaPluginOptions = {\n\t/**\n\t * Solana cluster that account signers target. Each account also exposes a\n\t * `getSigner(chain)` factory for targeting another cluster.\n\t *\n\t * @default \"solana:mainnet\"\n\t */\n\tchain?: SolanaChainId;\n};\n\n/**\n * Solana platform plugin. Pass to `getKheopskit$({ platforms: [solana()] })`.\n *\n * @example\n * ```ts\n * import { solana } from \"@kheopskit/core/solana\";\n * solana({ chain: \"solana:mainnet\" });\n * ```\n */\nexport const solana = (\n\toptions: SolanaPluginOptions = {},\n): KheopskitPlatform<\"solana\", SolanaWallet, SolanaAccount> => {\n\tconst chain = options.chain ?? DEFAULT_SOLANA_CHAIN;\n\n\tif (!isSolanaChainId(chain)) {\n\t\tconsole.warn(\n\t\t\t`[kheopskit] Unknown solana chain: ${JSON.stringify(chain)}. Valid values: \"solana:mainnet\", \"solana:devnet\", \"solana:testnet\", \"solana:localnet\".`,\n\t\t);\n\t}\n\n\treturn {\n\t\tplatform: \"solana\",\n\t\tgetWallets$: (ctx: PlatformContext) => getSolanaWallets$(ctx.store),\n\t\tgetAccounts$: (wallets$) => getSolanaAccounts$(wallets$, chain),\n\t};\n};\n"]}
package/dist/solana.mjs CHANGED
@@ -1,16 +1,16 @@
1
- import "./chunk-YFD3IKK5.mjs";
2
1
  import {
3
2
  KheopskitError,
4
- getAppKitWallets$,
5
3
  getWalletAccountId,
6
4
  isSolanaAddress,
7
5
  store
8
- } from "./chunk-KWFQDD7E.mjs";
6
+ } from "./chunk-6XAZANB5.mjs";
9
7
  import {
10
8
  clearCachedObservablesByPrefix,
11
9
  getCachedObservable$,
12
- getWalletId
13
- } from "./chunk-PNPPI5CH.mjs";
10
+ getWalletId,
11
+ isInjectedWallet,
12
+ isWalletConnectWallet
13
+ } from "./chunk-7QSGAJ4A.mjs";
14
14
 
15
15
  // src/api/solana/chains.ts
16
16
  var DEFAULT_SOLANA_CHAIN = "solana:mainnet";
@@ -35,12 +35,19 @@ var getSolanaCaip2 = (chain) => {
35
35
  );
36
36
  return caip2;
37
37
  };
38
- var CAIP2_TO_SOLANA_CHAIN = Object.fromEntries(
39
- Object.entries(SOLANA_CHAIN_TO_CAIP2).map(([chain, caip2]) => [
40
- caip2,
41
- chain
42
- ])
43
- );
38
+ var DEPRECATED_CAIP2_TO_SOLANA_CHAIN = {
39
+ "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ": "solana:mainnet",
40
+ "solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K": "solana:devnet"
41
+ };
42
+ var CAIP2_TO_SOLANA_CHAIN = {
43
+ ...Object.fromEntries(
44
+ Object.entries(SOLANA_CHAIN_TO_CAIP2).map(([chain, caip2]) => [
45
+ caip2,
46
+ chain
47
+ ])
48
+ ),
49
+ ...DEPRECATED_CAIP2_TO_SOLANA_CHAIN
50
+ };
44
51
  var getSolanaChainIdFromCaip2 = (caip2) => CAIP2_TO_SOLANA_CHAIN[caip2];
45
52
 
46
53
  // src/api/solana/accounts.ts
@@ -248,11 +255,11 @@ var getInjectedWalletAccounts$ = (wallet, chain) => {
248
255
  }).pipe(shareReplay({ refCount: true, bufferSize: 1 }))
249
256
  );
250
257
  };
251
- var getAppKitAccounts$ = (wallet, chain) => {
258
+ var getWalletConnectAccounts$ = (wallet, chain) => {
252
259
  const provider = wallet.appKit.getProvider("solana");
253
- if (!wallet.isConnected || !provider?.session) return of([]);
260
+ if (!wallet.platforms.includes("solana") || !provider?.session) return of([]);
254
261
  return getCachedObservable$(
255
- `accounts:${wallet.id}:${chain}`,
262
+ `accounts:${wallet.id}:solana:${chain}`,
256
263
  () => new Observable((subscriber) => {
257
264
  const buildAccounts = () => {
258
265
  const session = provider.session;
@@ -303,7 +310,7 @@ var getSolanaAccounts$ = (solanaWallets$, solanaChain) => new Observable((subscr
303
310
  switchMap(
304
311
  (wallets) => wallets.length ? combineLatest([
305
312
  ...wallets.filter((w) => w.type === "injected").map((w) => getInjectedWalletAccounts$(w, solanaChain)),
306
- ...wallets.filter((w) => w.type === "appKit").map((w) => getAppKitAccounts$(w, solanaChain))
313
+ ...wallets.filter(isWalletConnectWallet).map((w) => getWalletConnectAccounts$(w, solanaChain))
307
314
  ]) : of([])
308
315
  ),
309
316
  map((accounts) => accounts.flat()),
@@ -420,21 +427,7 @@ var createSolanaInjectedWallets$ = (store2) => new Observable2((subscriber) => {
420
427
  sub.unsubscribe();
421
428
  };
422
429
  }).pipe(shareReplay2({ refCount: true, bufferSize: 1 }));
423
- var getSolanaWallets$ = (config, store2 = store) => {
424
- return new Observable2((subscriber) => {
425
- const subscription = combineLatest2([
426
- createSolanaInjectedWallets$(store2),
427
- getAppKitWallets$(config).pipe(map2((w) => w.solana))
428
- ]).pipe(
429
- map2(
430
- ([injectedWallets, appKitWallet]) => appKitWallet ? [...injectedWallets, appKitWallet] : injectedWallets
431
- )
432
- ).subscribe(subscriber);
433
- return () => {
434
- subscription.unsubscribe();
435
- };
436
- }).pipe(shareReplay2({ refCount: true, bufferSize: 1 }));
437
- };
430
+ var getSolanaWallets$ = (store2 = store) => createSolanaInjectedWallets$(store2);
438
431
  var walletsEqual = (a, b) => {
439
432
  if (a.length !== b.length) return false;
440
433
  return a.every(
@@ -452,15 +445,17 @@ var solana = (options = {}) => {
452
445
  }
453
446
  return {
454
447
  platform: "solana",
455
- getWallets$: (ctx) => getSolanaWallets$(ctx.config, ctx.store),
448
+ getWallets$: (ctx) => getSolanaWallets$(ctx.store),
456
449
  getAccounts$: (wallets$) => getSolanaAccounts$(wallets$, chain)
457
450
  };
458
451
  };
459
452
  export {
460
453
  DEFAULT_SOLANA_CHAIN,
461
454
  getSolanaCaip2,
455
+ isInjectedWallet,
462
456
  isSolanaAddress,
463
457
  isSolanaChainId,
458
+ isWalletConnectWallet,
464
459
  solana
465
460
  };
466
461
  //# sourceMappingURL=solana.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/solana/chains.ts","../src/api/solana/accounts.ts","../src/api/solana/signer.ts","../src/api/solana/wallets.ts","../src/api/solana/plugin.ts"],"sourcesContent":["import { KheopskitError } from \"../errors\";\n\n/**\n * Wallet Standard chain identifiers for Solana clusters.\n *\n * These are the values wallets advertise in their `chains` arrays and the\n * values kheopskit accepts in `config.solanaChain`.\n *\n * @see https://github.com/anza-xyz/wallet-standard\n */\nexport type SolanaChainId =\n\t| \"solana:mainnet\"\n\t| \"solana:devnet\"\n\t| \"solana:testnet\"\n\t| \"solana:localnet\";\n\nexport const DEFAULT_SOLANA_CHAIN: SolanaChainId = \"solana:mainnet\";\n\nconst SOLANA_CHAIN_IDS = [\n\t\"solana:mainnet\",\n\t\"solana:devnet\",\n\t\"solana:testnet\",\n\t\"solana:localnet\",\n] as const satisfies SolanaChainId[];\n\nexport const isSolanaChainId = (value: unknown): value is SolanaChainId =>\n\ttypeof value === \"string\" &&\n\t(SOLANA_CHAIN_IDS as readonly string[]).includes(value);\n\n/**\n * Maps Wallet Standard chain ids to the CAIP-2 chain ids used by WalletConnect.\n *\n * CAIP-2 ids use the first 32 characters of the cluster's genesis hash as the\n * reference. The values below match `@reown/appkit/networks` (solana,\n * solanaDevnet, solanaTestnet), which is what AppKit puts in session namespaces.\n *\n * `localnet` has no canonical CAIP-2 id and cannot be used over WalletConnect.\n */\nconst SOLANA_CHAIN_TO_CAIP2 = {\n\t\"solana:mainnet\": \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n\t\"solana:devnet\": \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n\t\"solana:testnet\": \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\",\n} as const satisfies Partial<Record<SolanaChainId, string>>;\n\n/**\n * Returns the CAIP-2 chain id for a Solana chain, for use in WalletConnect\n * requests and when reading WalletConnect session namespaces.\n *\n * @throws if the chain has no canonical CAIP-2 id (e.g. localnet)\n */\nexport const getSolanaCaip2 = (chain: SolanaChainId): string => {\n\tconst caip2 = (SOLANA_CHAIN_TO_CAIP2 as Record<string, string | undefined>)[\n\t\tchain\n\t];\n\tif (!caip2)\n\t\tthrow new KheopskitError(\n\t\t\t\"UNSUPPORTED_CHAIN\",\n\t\t\t`Solana chain \"${chain}\" cannot be used over WalletConnect (no CAIP-2 id).`,\n\t\t);\n\treturn caip2;\n};\n\nconst CAIP2_TO_SOLANA_CHAIN: Record<string, SolanaChainId> = Object.fromEntries(\n\tObject.entries(SOLANA_CHAIN_TO_CAIP2).map(([chain, caip2]) => [\n\t\tcaip2,\n\t\tchain as SolanaChainId,\n\t]),\n);\n\n/**\n * Maps a CAIP-2 chain id (as found in WalletConnect session namespaces) back to\n * its {@link SolanaChainId}, or `undefined` if it isn't a recognised cluster.\n */\nexport const getSolanaChainIdFromCaip2 = (\n\tcaip2: string,\n): SolanaChainId | undefined => CAIP2_TO_SOLANA_CHAIN[caip2];\n","import type { StandardEventsFeature } from \"@wallet-standard/features\";\nimport {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tshareReplay,\n\tswitchMap,\n} from \"rxjs\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport type { SolanaAppKitWallet } from \"../types\";\nimport { getSolanaChainIdFromCaip2, type SolanaChainId } from \"./chains\";\nimport {\n\tcreateInjectedSolanaSigner,\n\tcreateWalletConnectSolanaSigner,\n} from \"./signer\";\nimport type {\n\tSolanaAccount,\n\tSolanaInjectedWallet,\n\tSolanaWallet,\n} from \"./types\";\n\ntype StandardEventsApi = StandardEventsFeature[\"standard:events\"];\n\nconst getInjectedWalletAccounts$ = (\n\twallet: SolanaInjectedWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\tconst standardWallet = wallet.wallet;\n\n\t\t\tconst buildAccounts = (): SolanaAccount[] =>\n\t\t\t\tstandardWallet.accounts.map(\n\t\t\t\t\t(account): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, account.address),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: account.address,\n\t\t\t\t\t\tchains: wallet.chains,\n\t\t\t\t\t\tsigner: createInjectedSolanaSigner(standardWallet, account, chain),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateInjectedSolanaSigner(standardWallet, account, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-emit when the wallet's authorized accounts change.\n\t\t\tconst eventsFeature = (\n\t\t\t\tstandardWallet.features as Record<string, unknown>\n\t\t\t)[\"standard:events\"] as StandardEventsApi | undefined;\n\t\t\tconst off = eventsFeature?.on(\"change\", () =>\n\t\t\t\tsubscriber.next(buildAccounts()),\n\t\t\t);\n\n\t\t\treturn () => {\n\t\t\t\toff?.();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst getAppKitAccounts$ = (\n\twallet: SolanaAppKitWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"solana\");\n\n\tif (!wallet.isConnected || !provider?.session) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\t// AppKit has no native solana adapter, so getAccount(\"solana\").allAccounts\n\t\t\t// is always empty; the WalletConnect session is the source of truth.\n\t\t\t// Accounts are CAIP-10 strings (\"solana:<chainRef>:<address>\"), one entry\n\t\t\t// per chain, so dedupe to unique addresses.\n\t\t\tconst buildAccounts = (): SolanaAccount[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\n\t\t\t\tconst solanaCaip10s = Object.values(session.namespaces)\n\t\t\t\t\t.flatMap((namespace) => namespace.accounts ?? [])\n\t\t\t\t\t.filter((account) => account.startsWith(\"solana:\"));\n\n\t\t\t\tconst addresses = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\")[2])\n\t\t\t\t\t\t\t.filter((address): address is string => !!address),\n\t\t\t\t\t),\n\t\t\t\t];\n\n\t\t\t\t// Clusters the session actually advertises (\"solana:<chainRef>\" from\n\t\t\t\t// each CAIP-10 entry), mapped back to SolanaChainId. Falls back to the\n\t\t\t\t// configured chain when none are recognised.\n\t\t\t\tconst advertisedChains = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\").slice(0, 2).join(\":\"))\n\t\t\t\t\t\t\t.map(getSolanaChainIdFromCaip2)\n\t\t\t\t\t\t\t.filter((c): c is SolanaChainId => !!c),\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t\tconst chains = advertisedChains.length ? advertisedChains : [chain];\n\n\t\t\t\treturn addresses.map(\n\t\t\t\t\t(accountAddress): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, accountAddress),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: accountAddress,\n\t\t\t\t\t\tchains,\n\t\t\t\t\t\tsigner: createWalletConnectSolanaSigner(\n\t\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t\taccountAddress,\n\t\t\t\t\t\t\tchain,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateWalletConnectSolanaSigner(provider, accountAddress, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-derive when the WalletConnect session's accounts change, mirroring\n\t\t\t// the injected wallet's standard:events \"change\" subscription.\n\t\t\tconst reemit = () => subscriber.next(buildAccounts());\n\t\t\tprovider.on(\"session_update\", reemit);\n\t\t\tprovider.on(\"accountsChanged\", reemit);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"session_update\", reemit);\n\t\t\t\tprovider.off(\"accountsChanged\", reemit);\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getSolanaAccounts$ = (\n\tsolanaWallets$: Observable<SolanaWallet[]>,\n\tsolanaChain: SolanaChainId,\n) =>\n\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\tconst sub = solanaWallets$\n\t\t\t.pipe(\n\t\t\t\tmap((wallets) => wallets.filter((w) => w.isConnected)),\n\t\t\t\tswitchMap((wallets) =>\n\t\t\t\t\twallets.length\n\t\t\t\t\t\t? combineLatest([\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter((w) => w.type === \"injected\")\n\t\t\t\t\t\t\t\t\t.map((w) => getInjectedWalletAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter((w) => w.type === \"appKit\")\n\t\t\t\t\t\t\t\t\t.map((w) => getAppKitAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t: of([]),\n\t\t\t\t),\n\t\t\t\tmap((accounts) => accounts.flat()),\n\t\t\t\tdistinctUntilChanged(isSameAccountsList),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst isSameAccountsList = (a: SolanaAccount[], b: SolanaAccount[]) => {\n\tif (a.length !== b.length) return false;\n\treturn a.every((account, i) => {\n\t\tconst other = b[i];\n\t\tif (!other || account.id !== other.id) return false;\n\t\t// Re-emit when the advertised clusters change, not just on id changes.\n\t\tif (account.chains.length !== other.chains.length) return false;\n\t\treturn account.chains.every((chain, j) => chain === other.chains[j]);\n\t});\n};\n","import {\n\taddress,\n\tgetBase58Decoder,\n\tgetBase58Encoder,\n\tgetBase64Decoder,\n\tgetBase64Encoder,\n\tgetTransactionDecoder,\n\tgetTransactionEncoder,\n\ttype SignableMessage,\n\ttype SignatureBytes,\n\ttype TransactionModifyingSigner,\n} from \"@solana/kit\";\nimport type {\n\tSolanaSignAndSendTransactionFeature,\n\tSolanaSignMessageFeature,\n\tSolanaSignTransactionFeature,\n} from \"@solana/wallet-standard-features\";\nimport type {\n\tWalletAccount,\n\tWallet as WalletStandardWallet,\n} from \"@wallet-standard/base\";\nimport { KheopskitError } from \"../errors\";\nimport type { WalletConnectProvider } from \"../types\";\nimport { getSolanaCaip2, type SolanaChainId } from \"./chains\";\nimport type { SolanaSigner } from \"./types\";\n\nconst SOLANA_SIGN_MESSAGE = \"solana:signMessage\";\nconst SOLANA_SIGN_TRANSACTION = \"solana:signTransaction\";\nconst SOLANA_SIGN_AND_SEND_TRANSACTION = \"solana:signAndSendTransaction\";\n\ntype SignMessageApi = SolanaSignMessageFeature[typeof SOLANA_SIGN_MESSAGE];\ntype SignTransactionApi =\n\tSolanaSignTransactionFeature[typeof SOLANA_SIGN_TRANSACTION];\ntype SignAndSendApi =\n\tSolanaSignAndSendTransactionFeature[typeof SOLANA_SIGN_AND_SEND_TRANSACTION];\n\n/** The branded array type expected back from a transaction-modifying signer. */\ntype SignedTransactions = Awaited<\n\tReturnType<TransactionModifyingSigner[\"modifyAndSignTransactions\"]>\n>;\n\nconst requireFeature = <T>(wallet: WalletStandardWallet, name: string): T => {\n\tconst feature = (wallet.features as Record<string, unknown>)[name];\n\tif (!feature)\n\t\tthrow new KheopskitError(\n\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t`wallet \"${wallet.name}\" does not support ${name}`,\n\t\t);\n\treturn feature as T;\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a Wallet Standard wallet's\n * `solana:*` features (injected wallets).\n *\n * Transactions are exchanged as wire bytes; messages and signatures as raw\n * bytes. Calling a method whose feature the wallet does not advertise throws.\n */\nexport const createInjectedSolanaSigner = (\n\twallet: WalletStandardWallet,\n\taccount: WalletAccount,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(account.address);\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\tconst feature = requireFeature<SignMessageApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_MESSAGE,\n\t\t\t);\n\t\t\tconst outputs = await feature.signMessage(\n\t\t\t\t...messages.map((m) => ({ account, message: m.content })),\n\t\t\t);\n\t\t\treturn messages.map((m, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output) throw new Error(\"[kheopskit] missing signMessage output\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: output.signedMessage,\n\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t[signerAddress]: output.signature as SignatureBytes,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SignableMessage;\n\t\t\t});\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignTransactionApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst outputs = await feature.signTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn transactions.map((_tx, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output)\n\t\t\t\t\tthrow new Error(\"[kheopskit] missing signTransaction output\");\n\t\t\t\treturn decoder.decode(output.signedTransaction);\n\t\t\t}) as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignAndSendApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_AND_SEND_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst outputs = await feature.signAndSendTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn outputs.map((output) => output.signature as SignatureBytes);\n\t\t},\n\t};\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a WalletConnect session, adapting the\n * `solana_*` RPC methods to the same interface as the injected signer.\n *\n * The CAIP-2 chain id is derived from {@link SolanaChainId}; transactions are\n * base64-encoded and messages/signatures base58-encoded, per the WalletConnect\n * Solana spec.\n */\nexport const createWalletConnectSolanaSigner = (\n\tprovider: WalletConnectProvider,\n\taccountAddress: string,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(accountAddress);\n\n\tconst request = <T>(method: string, params: unknown): Promise<T> => {\n\t\tif (!provider.session)\n\t\t\tthrow new KheopskitError(\"NO_SESSION\", \"No session found\");\n\t\t// Resolved lazily (not at signer construction) so building a signer for a\n\t\t// cluster without a CAIP-2 id (e.g. localnet) doesn't throw until a request\n\t\t// is actually attempted.\n\t\treturn provider.client.request<T>({\n\t\t\ttopic: provider.session.topic,\n\t\t\tchainId: getSolanaCaip2(chain),\n\t\t\trequest: { method, params },\n\t\t});\n\t};\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\t// @solana/kit naming is the inverse of the value direction here: a\n\t\t\t// Decoder turns bytes -> string (so `toBase58` produces a base58 string),\n\t\t\t// an Encoder turns string -> bytes (so `fromBase58` parses one).\n\t\t\tconst toBase58 = getBase58Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\tmessages.map(async (m) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signMessage\",\n\t\t\t\t\t\t{ pubkey: accountAddress, message: toBase58.decode(m.content) },\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: m.content,\n\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(signature) as SignatureBytes,\n\t\t\t\t\t\t},\n\t\t\t\t\t} satisfies SignableMessage;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase64 = getBase64Encoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\tconst signed = await Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst result = await request<{\n\t\t\t\t\t\ttransaction?: string;\n\t\t\t\t\t\tsignature?: string;\n\t\t\t\t\t}>(\"solana_signTransaction\", {\n\t\t\t\t\t\ttransaction: toBase64.decode(encoder.encode(tx)),\n\t\t\t\t\t});\n\t\t\t\t\t// Wallets may return either the full signed transaction (base64)\n\t\t\t\t\t// or just the signature (base58) to merge into the original.\n\t\t\t\t\tif (result.transaction)\n\t\t\t\t\t\treturn decoder.decode(fromBase64.encode(result.transaction));\n\t\t\t\t\tif (result.signature)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...tx,\n\t\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t\t...tx.signatures,\n\t\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(\n\t\t\t\t\t\t\t\t\tresult.signature,\n\t\t\t\t\t\t\t\t) as SignatureBytes,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"[kheopskit] solana_signTransaction returned no transaction or signature\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn signed as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signAndSendTransaction\",\n\t\t\t\t\t\t{ transaction: toBase64.decode(encoder.encode(tx)) },\n\t\t\t\t\t);\n\t\t\t\t\treturn fromBase58.encode(signature) as SignatureBytes;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t};\n};\n","import { getWallets } from \"@wallet-standard/app\";\nimport type { Wallet as WalletStandardWallet } from \"@wallet-standard/base\";\nimport type {\n\tStandardConnectFeature,\n\tStandardDisconnectFeature,\n} from \"@wallet-standard/features\";\nimport {\n\tBehaviorSubject,\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tshareReplay,\n} from \"rxjs\";\nimport { clearCachedObservablesByPrefix } from \"../../utils/getCachedObservable\";\nimport { getWalletId, type WalletId } from \"../../utils/WalletId\";\nimport { getAppKitWallets$ } from \"../appKit\";\nimport { KheopskitError } from \"../errors\";\nimport { store as defaultStore, type KheopskitStore } from \"../store\";\nimport type { KheopskitConfig } from \"../types\";\nimport { isSolanaChainId, type SolanaChainId } from \"./chains\";\nimport type { SolanaInjectedWallet, SolanaWallet } from \"./types\";\n\ntype ConnectApi = StandardConnectFeature[\"standard:connect\"];\ntype DisconnectApi = StandardDisconnectFeature[\"standard:disconnect\"];\n\nconst SOLANA_NAMESPACE_PREFIX = \"solana:\";\n\n/** A Wallet Standard wallet is Solana-capable if it advertises a solana chain or feature. */\nconst isSolanaWallet = (wallet: WalletStandardWallet): boolean =>\n\twallet.chains.some((chain) => chain.startsWith(SOLANA_NAMESPACE_PREFIX)) ||\n\tObject.keys(wallet.features).some((feature) =>\n\t\tfeature.startsWith(SOLANA_NAMESPACE_PREFIX),\n\t);\n\nconst getSolanaChains = (wallet: WalletStandardWallet): SolanaChainId[] =>\n\twallet.chains.filter((chain): chain is SolanaChainId =>\n\t\tisSolanaChainId(chain),\n\t);\n\n/**\n * Observable of Solana-capable Wallet Standard wallets, updated as wallets\n * register/unregister. Returns an empty array during SSR.\n */\nconst walletStandardWallets$ = new Observable<readonly WalletStandardWallet[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - the Wallet Standard registry requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst { get, on } = getWallets();\n\t\tconst emit = () => subscriber.next(get().filter(isSolanaWallet));\n\n\t\temit();\n\n\t\tconst offRegister = on(\"register\", emit);\n\t\tconst offUnregister = on(\"unregister\", emit);\n\n\t\treturn () => {\n\t\t\toffRegister();\n\t\t\toffUnregister();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst createSolanaInjectedWallets$ = (store: KheopskitStore) =>\n\tnew Observable<SolanaInjectedWallet[]>((subscriber) => {\n\t\tconst enabledWalletIds$ = new BehaviorSubject<Set<WalletId>>(new Set());\n\n\t\tconst connect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_ALREADY_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is already connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:connect\"\n\t\t\t] as ConnectApi | undefined;\n\t\t\tif (!feature)\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t\t\t`wallet ${walletId} does not support standard:connect`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tawait feature.connect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.add(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.addEnabledWalletId(walletId);\n\t\t};\n\n\t\tconst disconnect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (!enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_NOT_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is not connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\t// standard:disconnect is an optional feature. Await it when present so a\n\t\t\t// failed disconnect rejects the returned promise; if absent we still\n\t\t\t// clear local state below.\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:disconnect\"\n\t\t\t] as DisconnectApi | undefined;\n\t\t\tawait feature?.disconnect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.delete(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.removeEnabledWalletId(walletId);\n\n\t\t\t// Drop cached account observables for this wallet so a later reconnect\n\t\t\t// rebuilds them against the current wallet handle, not a stale closure.\n\t\t\tclearCachedObservablesByPrefix(`accounts:${walletId}:`);\n\t\t};\n\n\t\tconst sub = combineLatest([walletStandardWallets$, enabledWalletIds$])\n\t\t\t.pipe(\n\t\t\t\tmap(([wallets, enabledWalletIds]) =>\n\t\t\t\t\twallets.map((wallet): SolanaInjectedWallet => {\n\t\t\t\t\t\tconst walletId = getWalletId(\"solana\", wallet.name);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\t\ttype: \"injected\",\n\t\t\t\t\t\t\tid: walletId,\n\t\t\t\t\t\t\tsourceId: wallet.name,\n\t\t\t\t\t\t\twallet,\n\t\t\t\t\t\t\tchains: getSolanaChains(wallet),\n\t\t\t\t\t\t\tname: wallet.name,\n\t\t\t\t\t\t\ticon: wallet.icon,\n\t\t\t\t\t\t\tisConnected: enabledWalletIds.has(walletId),\n\t\t\t\t\t\t\tconnect: () => connect(wallet, walletId),\n\t\t\t\t\t\t\tdisconnect: () => disconnect(wallet, walletId),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tdistinctUntilChanged(walletsEqual),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nexport const getSolanaWallets$ = (\n\tconfig: KheopskitConfig,\n\tstore: KheopskitStore = defaultStore,\n) => {\n\treturn new Observable<SolanaWallet[]>((subscriber) => {\n\t\tconst subscription = combineLatest([\n\t\t\tcreateSolanaInjectedWallets$(store),\n\t\t\tgetAppKitWallets$(config).pipe(map((w) => w.solana)),\n\t\t])\n\t\t\t.pipe(\n\t\t\t\tmap(([injectedWallets, appKitWallet]) =>\n\t\t\t\t\tappKitWallet ? [...injectedWallets, appKitWallet] : injectedWallets,\n\t\t\t\t),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsubscription.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n};\n\n/**\n * Compare two wallet arrays by their relevant properties (not functions).\n */\nconst walletsEqual = (\n\ta: SolanaInjectedWallet[],\n\tb: SolanaInjectedWallet[],\n): boolean => {\n\tif (a.length !== b.length) return false;\n\treturn a.every(\n\t\t(w, i) =>\n\t\t\tw.id === b[i]?.id &&\n\t\t\tw.isConnected === b[i]?.isConnected &&\n\t\t\tw.name === b[i]?.name,\n\t);\n};\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getSolanaAccounts$ } from \"./accounts\";\nimport {\n\tDEFAULT_SOLANA_CHAIN,\n\tisSolanaChainId,\n\ttype SolanaChainId,\n} from \"./chains\";\nimport type { SolanaAccount, SolanaWallet } from \"./types\";\nimport { getSolanaWallets$ } from \"./wallets\";\n\nexport type SolanaPluginOptions = {\n\t/**\n\t * Solana cluster that account signers target. Each account also exposes a\n\t * `getSigner(chain)` factory for targeting another cluster.\n\t *\n\t * @default \"solana:mainnet\"\n\t */\n\tchain?: SolanaChainId;\n};\n\n/**\n * Solana platform plugin. Pass to `getKheopskit$({ platforms: [solana()] })`.\n *\n * @example\n * ```ts\n * import { solana } from \"@kheopskit/core/solana\";\n * solana({ chain: \"solana:mainnet\" });\n * ```\n */\nexport const solana = (\n\toptions: SolanaPluginOptions = {},\n): KheopskitPlatform<\"solana\", SolanaWallet, SolanaAccount> => {\n\tconst chain = options.chain ?? DEFAULT_SOLANA_CHAIN;\n\n\tif (!isSolanaChainId(chain)) {\n\t\tconsole.warn(\n\t\t\t`[kheopskit] Unknown solana chain: ${JSON.stringify(chain)}. Valid values: \"solana:mainnet\", \"solana:devnet\", \"solana:testnet\", \"solana:localnet\".`,\n\t\t);\n\t}\n\n\treturn {\n\t\tplatform: \"solana\",\n\t\tgetWallets$: (ctx: PlatformContext) =>\n\t\t\tgetSolanaWallets$(ctx.config, ctx.store),\n\t\tgetAccounts$: (wallets$) => getSolanaAccounts$(wallets$, chain),\n\t};\n};\n"],"mappings":"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","names":["address","combineLatest","distinctUntilChanged","map","Observable","shareReplay","Observable","shareReplay","store","combineLatest","map","distinctUntilChanged"]}
1
+ {"version":3,"sources":["../src/api/solana/chains.ts","../src/api/solana/accounts.ts","../src/api/solana/signer.ts","../src/api/solana/wallets.ts","../src/api/solana/plugin.ts"],"sourcesContent":["import { KheopskitError } from \"../errors\";\n\n/**\n * Wallet Standard chain identifiers for Solana clusters.\n *\n * These are the values wallets advertise in their `chains` arrays and the\n * values kheopskit accepts in `solana({ chain })`.\n *\n * @see https://github.com/anza-xyz/wallet-standard\n */\nexport type SolanaChainId =\n\t| \"solana:mainnet\"\n\t| \"solana:devnet\"\n\t| \"solana:testnet\"\n\t| \"solana:localnet\";\n\nexport const DEFAULT_SOLANA_CHAIN: SolanaChainId = \"solana:mainnet\";\n\nconst SOLANA_CHAIN_IDS = [\n\t\"solana:mainnet\",\n\t\"solana:devnet\",\n\t\"solana:testnet\",\n\t\"solana:localnet\",\n] as const satisfies SolanaChainId[];\n\nexport const isSolanaChainId = (value: unknown): value is SolanaChainId =>\n\ttypeof value === \"string\" &&\n\t(SOLANA_CHAIN_IDS as readonly string[]).includes(value);\n\n/**\n * Maps Wallet Standard chain ids to the CAIP-2 chain ids used by WalletConnect.\n *\n * CAIP-2 ids use the first 32 characters of the cluster's genesis hash as the\n * reference. The values below match `@reown/appkit/networks` (solana,\n * solanaDevnet, solanaTestnet), which is what AppKit puts in session namespaces.\n *\n * `localnet` has no canonical CAIP-2 id and cannot be used over WalletConnect.\n */\nconst SOLANA_CHAIN_TO_CAIP2 = {\n\t\"solana:mainnet\": \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n\t\"solana:devnet\": \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n\t\"solana:testnet\": \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\",\n} as const satisfies Partial<Record<SolanaChainId, string>>;\n\n/**\n * Returns the CAIP-2 chain id for a Solana chain, for use in WalletConnect\n * requests and when reading WalletConnect session namespaces.\n *\n * @throws if the chain has no canonical CAIP-2 id (e.g. localnet)\n */\nexport const getSolanaCaip2 = (chain: SolanaChainId): string => {\n\tconst caip2 = (SOLANA_CHAIN_TO_CAIP2 as Record<string, string | undefined>)[\n\t\tchain\n\t];\n\tif (!caip2)\n\t\tthrow new KheopskitError(\n\t\t\t\"UNSUPPORTED_CHAIN\",\n\t\t\t`Solana chain \"${chain}\" cannot be used over WalletConnect (no CAIP-2 id).`,\n\t\t);\n\treturn caip2;\n};\n\n/**\n * AppKit's *deprecated* CAIP-2 cluster ids (its `deprecatedCaipNetworkId`\n * values). Some wallets still place accounts in the WC session under these, so\n * map them back to a {@link SolanaChainId} instead of silently falling back to\n * the configured chain. Requests always use the current ids from\n * {@link SOLANA_CHAIN_TO_CAIP2}; testnet has no deprecated id.\n */\nconst DEPRECATED_CAIP2_TO_SOLANA_CHAIN: Record<string, SolanaChainId> = {\n\t\"solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ\": \"solana:mainnet\",\n\t\"solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K\": \"solana:devnet\",\n};\n\nconst CAIP2_TO_SOLANA_CHAIN: Record<string, SolanaChainId> = {\n\t...Object.fromEntries(\n\t\tObject.entries(SOLANA_CHAIN_TO_CAIP2).map(([chain, caip2]) => [\n\t\t\tcaip2,\n\t\t\tchain as SolanaChainId,\n\t\t]),\n\t),\n\t...DEPRECATED_CAIP2_TO_SOLANA_CHAIN,\n};\n\n/**\n * Maps a CAIP-2 chain id (as found in WalletConnect session namespaces) back to\n * its {@link SolanaChainId}, or `undefined` if it isn't a recognised cluster.\n */\nexport const getSolanaChainIdFromCaip2 = (\n\tcaip2: string,\n): SolanaChainId | undefined => CAIP2_TO_SOLANA_CHAIN[caip2];\n","import type { StandardEventsFeature } from \"@wallet-standard/features\";\nimport {\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tof,\n\tshareReplay,\n\tswitchMap,\n} from \"rxjs\";\nimport { getWalletAccountId } from \"../../utils\";\nimport { getCachedObservable$ } from \"../../utils/getCachedObservable\";\nimport type { WalletConnectWallet } from \"../types\";\nimport { isWalletConnectWallet } from \"../types\";\nimport { getSolanaChainIdFromCaip2, type SolanaChainId } from \"./chains\";\nimport {\n\tcreateInjectedSolanaSigner,\n\tcreateWalletConnectSolanaSigner,\n} from \"./signer\";\nimport type {\n\tSolanaAccount,\n\tSolanaInjectedWallet,\n\tSolanaWallet,\n} from \"./types\";\n\ntype StandardEventsApi = StandardEventsFeature[\"standard:events\"];\n\nconst getInjectedWalletAccounts$ = (\n\twallet: SolanaInjectedWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tif (!wallet.isConnected) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\tconst standardWallet = wallet.wallet;\n\n\t\t\tconst buildAccounts = (): SolanaAccount[] =>\n\t\t\t\tstandardWallet.accounts.map(\n\t\t\t\t\t(account): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, account.address),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: account.address,\n\t\t\t\t\t\tchains: wallet.chains,\n\t\t\t\t\t\tsigner: createInjectedSolanaSigner(standardWallet, account, chain),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateInjectedSolanaSigner(standardWallet, account, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-emit when the wallet's authorized accounts change.\n\t\t\tconst eventsFeature = (\n\t\t\t\tstandardWallet.features as Record<string, unknown>\n\t\t\t)[\"standard:events\"] as StandardEventsApi | undefined;\n\t\t\tconst off = eventsFeature?.on(\"change\", () =>\n\t\t\t\tsubscriber.next(buildAccounts()),\n\t\t\t);\n\n\t\t\treturn () => {\n\t\t\t\toff?.();\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nconst getWalletConnectAccounts$ = (\n\twallet: WalletConnectWallet,\n\tchain: SolanaChainId,\n): Observable<SolanaAccount[]> => {\n\tconst provider = wallet.appKit.getProvider(\"solana\");\n\n\tif (!wallet.platforms.includes(\"solana\") || !provider?.session) return of([]);\n\n\treturn getCachedObservable$(`accounts:${wallet.id}:solana:${chain}`, () =>\n\t\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\t\t// AppKit has no native solana adapter, so getAccount(\"solana\").allAccounts\n\t\t\t// is always empty; the WalletConnect session is the source of truth.\n\t\t\t// Accounts are CAIP-10 strings (\"solana:<chainRef>:<address>\"), one entry\n\t\t\t// per chain, so dedupe to unique addresses.\n\t\t\tconst buildAccounts = (): SolanaAccount[] => {\n\t\t\t\tconst session = provider.session;\n\t\t\t\tif (!session) return [];\n\n\t\t\t\tconst solanaCaip10s = Object.values(session.namespaces)\n\t\t\t\t\t.flatMap((namespace) => namespace.accounts ?? [])\n\t\t\t\t\t.filter((account) => account.startsWith(\"solana:\"));\n\n\t\t\t\tconst addresses = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\")[2])\n\t\t\t\t\t\t\t.filter((address): address is string => !!address),\n\t\t\t\t\t),\n\t\t\t\t];\n\n\t\t\t\t// Clusters the session actually advertises (\"solana:<chainRef>\" from\n\t\t\t\t// each CAIP-10 entry), mapped back to SolanaChainId. Falls back to the\n\t\t\t\t// configured chain when none are recognised.\n\t\t\t\tconst advertisedChains = [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tsolanaCaip10s\n\t\t\t\t\t\t\t.map((account) => account.split(\":\").slice(0, 2).join(\":\"))\n\t\t\t\t\t\t\t.map(getSolanaChainIdFromCaip2)\n\t\t\t\t\t\t\t.filter((c): c is SolanaChainId => !!c),\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t\tconst chains = advertisedChains.length ? advertisedChains : [chain];\n\n\t\t\t\treturn addresses.map(\n\t\t\t\t\t(accountAddress): SolanaAccount => ({\n\t\t\t\t\t\tid: getWalletAccountId(wallet.id, accountAddress),\n\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\taddress: accountAddress,\n\t\t\t\t\t\tchains,\n\t\t\t\t\t\tsigner: createWalletConnectSolanaSigner(\n\t\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t\taccountAddress,\n\t\t\t\t\t\t\tchain,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tgetSigner: (c) =>\n\t\t\t\t\t\t\tcreateWalletConnectSolanaSigner(provider, accountAddress, c),\n\t\t\t\t\t\twalletName: wallet.name,\n\t\t\t\t\t\twalletId: wallet.id,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tsubscriber.next(buildAccounts());\n\n\t\t\t// Re-derive when the WalletConnect session's accounts change, mirroring\n\t\t\t// the injected wallet's standard:events \"change\" subscription.\n\t\t\tconst reemit = () => subscriber.next(buildAccounts());\n\t\t\tprovider.on(\"session_update\", reemit);\n\t\t\tprovider.on(\"accountsChanged\", reemit);\n\n\t\t\treturn () => {\n\t\t\t\tprovider.off(\"session_update\", reemit);\n\t\t\t\tprovider.off(\"accountsChanged\", reemit);\n\t\t\t};\n\t\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 })),\n\t);\n};\n\nexport const getSolanaAccounts$ = (\n\tsolanaWallets$: Observable<(SolanaWallet | WalletConnectWallet)[]>,\n\tsolanaChain: SolanaChainId,\n) =>\n\tnew Observable<SolanaAccount[]>((subscriber) => {\n\t\tconst sub = solanaWallets$\n\t\t\t.pipe(\n\t\t\t\tmap((wallets) => wallets.filter((w) => w.isConnected)),\n\t\t\t\tswitchMap((wallets) =>\n\t\t\t\t\twallets.length\n\t\t\t\t\t\t? combineLatest([\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter((w) => w.type === \"injected\")\n\t\t\t\t\t\t\t\t\t.map((w) => getInjectedWalletAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t\t...wallets\n\t\t\t\t\t\t\t\t\t.filter(isWalletConnectWallet)\n\t\t\t\t\t\t\t\t\t.map((w) => getWalletConnectAccounts$(w, solanaChain)),\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t: of([]),\n\t\t\t\t),\n\t\t\t\tmap((accounts) => accounts.flat()),\n\t\t\t\tdistinctUntilChanged(isSameAccountsList),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst isSameAccountsList = (a: SolanaAccount[], b: SolanaAccount[]) => {\n\tif (a.length !== b.length) return false;\n\treturn a.every((account, i) => {\n\t\tconst other = b[i];\n\t\tif (!other || account.id !== other.id) return false;\n\t\t// Re-emit when the advertised clusters change, not just on id changes.\n\t\tif (account.chains.length !== other.chains.length) return false;\n\t\treturn account.chains.every((chain, j) => chain === other.chains[j]);\n\t});\n};\n","import {\n\taddress,\n\tgetBase58Decoder,\n\tgetBase58Encoder,\n\tgetBase64Decoder,\n\tgetBase64Encoder,\n\tgetTransactionDecoder,\n\tgetTransactionEncoder,\n\ttype SignableMessage,\n\ttype SignatureBytes,\n\ttype TransactionModifyingSigner,\n} from \"@solana/kit\";\nimport type {\n\tSolanaSignAndSendTransactionFeature,\n\tSolanaSignMessageFeature,\n\tSolanaSignTransactionFeature,\n} from \"@solana/wallet-standard-features\";\nimport type {\n\tWalletAccount,\n\tWallet as WalletStandardWallet,\n} from \"@wallet-standard/base\";\nimport { KheopskitError } from \"../errors\";\nimport type { WalletConnectProvider } from \"../types\";\nimport { getSolanaCaip2, type SolanaChainId } from \"./chains\";\nimport type { SolanaSigner } from \"./types\";\n\nconst SOLANA_SIGN_MESSAGE = \"solana:signMessage\";\nconst SOLANA_SIGN_TRANSACTION = \"solana:signTransaction\";\nconst SOLANA_SIGN_AND_SEND_TRANSACTION = \"solana:signAndSendTransaction\";\n\ntype SignMessageApi = SolanaSignMessageFeature[typeof SOLANA_SIGN_MESSAGE];\ntype SignTransactionApi =\n\tSolanaSignTransactionFeature[typeof SOLANA_SIGN_TRANSACTION];\ntype SignAndSendApi =\n\tSolanaSignAndSendTransactionFeature[typeof SOLANA_SIGN_AND_SEND_TRANSACTION];\n\n/** The branded array type expected back from a transaction-modifying signer. */\ntype SignedTransactions = Awaited<\n\tReturnType<TransactionModifyingSigner[\"modifyAndSignTransactions\"]>\n>;\n\nconst requireFeature = <T>(wallet: WalletStandardWallet, name: string): T => {\n\tconst feature = (wallet.features as Record<string, unknown>)[name];\n\tif (!feature)\n\t\tthrow new KheopskitError(\n\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t`wallet \"${wallet.name}\" does not support ${name}`,\n\t\t);\n\treturn feature as T;\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a Wallet Standard wallet's\n * `solana:*` features (injected wallets).\n *\n * Transactions are exchanged as wire bytes; messages and signatures as raw\n * bytes. Calling a method whose feature the wallet does not advertise throws.\n */\nexport const createInjectedSolanaSigner = (\n\twallet: WalletStandardWallet,\n\taccount: WalletAccount,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(account.address);\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\tconst feature = requireFeature<SignMessageApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_MESSAGE,\n\t\t\t);\n\t\t\tconst outputs = await feature.signMessage(\n\t\t\t\t...messages.map((m) => ({ account, message: m.content })),\n\t\t\t);\n\t\t\treturn messages.map((m, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output) throw new Error(\"[kheopskit] missing signMessage output\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: output.signedMessage,\n\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t[signerAddress]: output.signature as SignatureBytes,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SignableMessage;\n\t\t\t});\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignTransactionApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst outputs = await feature.signTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn transactions.map((_tx, i) => {\n\t\t\t\tconst output = outputs[i];\n\t\t\t\tif (!output)\n\t\t\t\t\tthrow new Error(\"[kheopskit] missing signTransaction output\");\n\t\t\t\treturn decoder.decode(output.signedTransaction);\n\t\t\t}) as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst feature = requireFeature<SignAndSendApi>(\n\t\t\t\twallet,\n\t\t\t\tSOLANA_SIGN_AND_SEND_TRANSACTION,\n\t\t\t);\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst outputs = await feature.signAndSendTransaction(\n\t\t\t\t...transactions.map((tx) => ({\n\t\t\t\t\taccount,\n\t\t\t\t\ttransaction: new Uint8Array(encoder.encode(tx)),\n\t\t\t\t\tchain,\n\t\t\t\t})),\n\t\t\t);\n\t\t\treturn outputs.map((output) => output.signature as SignatureBytes);\n\t\t},\n\t};\n};\n\n/**\n * Builds a {@link SolanaSigner} backed by a WalletConnect session, adapting the\n * `solana_*` RPC methods to the same interface as the injected signer.\n *\n * The CAIP-2 chain id is derived from {@link SolanaChainId}; transactions are\n * base64-encoded and messages/signatures base58-encoded, per the WalletConnect\n * Solana spec.\n */\nexport const createWalletConnectSolanaSigner = (\n\tprovider: WalletConnectProvider,\n\taccountAddress: string,\n\tchain: SolanaChainId,\n): SolanaSigner => {\n\tconst signerAddress = address(accountAddress);\n\n\tconst request = <T>(method: string, params: unknown): Promise<T> => {\n\t\tif (!provider.session)\n\t\t\tthrow new KheopskitError(\"NO_SESSION\", \"No session found\");\n\t\t// Resolved lazily (not at signer construction) so building a signer for a\n\t\t// cluster without a CAIP-2 id (e.g. localnet) doesn't throw until a request\n\t\t// is actually attempted.\n\t\treturn provider.client.request<T>({\n\t\t\ttopic: provider.session.topic,\n\t\t\tchainId: getSolanaCaip2(chain),\n\t\t\trequest: { method, params },\n\t\t});\n\t};\n\n\treturn {\n\t\taddress: signerAddress,\n\t\tmodifyAndSignMessages: async (messages) => {\n\t\t\t// @solana/kit naming is the inverse of the value direction here: a\n\t\t\t// Decoder turns bytes -> string (so `toBase58` produces a base58 string),\n\t\t\t// an Encoder turns string -> bytes (so `fromBase58` parses one).\n\t\t\tconst toBase58 = getBase58Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\tmessages.map(async (m) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signMessage\",\n\t\t\t\t\t\t{ pubkey: accountAddress, message: toBase58.decode(m.content) },\n\t\t\t\t\t);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: m.content,\n\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t...m.signatures,\n\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(signature) as SignatureBytes,\n\t\t\t\t\t\t},\n\t\t\t\t\t} satisfies SignableMessage;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\tmodifyAndSignTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst decoder = getTransactionDecoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase64 = getBase64Encoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\tconst signed = await Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst result = await request<{\n\t\t\t\t\t\ttransaction?: string;\n\t\t\t\t\t\tsignature?: string;\n\t\t\t\t\t}>(\"solana_signTransaction\", {\n\t\t\t\t\t\ttransaction: toBase64.decode(encoder.encode(tx)),\n\t\t\t\t\t});\n\t\t\t\t\t// Wallets may return either the full signed transaction (base64)\n\t\t\t\t\t// or just the signature (base58) to merge into the original.\n\t\t\t\t\tif (result.transaction)\n\t\t\t\t\t\treturn decoder.decode(fromBase64.encode(result.transaction));\n\t\t\t\t\tif (result.signature)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...tx,\n\t\t\t\t\t\t\tsignatures: {\n\t\t\t\t\t\t\t\t...tx.signatures,\n\t\t\t\t\t\t\t\t[signerAddress]: fromBase58.encode(\n\t\t\t\t\t\t\t\t\tresult.signature,\n\t\t\t\t\t\t\t\t) as SignatureBytes,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"[kheopskit] solana_signTransaction returned no transaction or signature\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn signed as unknown as SignedTransactions;\n\t\t},\n\t\tsignAndSendTransactions: async (transactions) => {\n\t\t\tconst encoder = getTransactionEncoder();\n\t\t\tconst toBase64 = getBase64Decoder();\n\t\t\tconst fromBase58 = getBase58Encoder();\n\t\t\treturn Promise.all(\n\t\t\t\ttransactions.map(async (tx) => {\n\t\t\t\t\tconst { signature } = await request<{ signature: string }>(\n\t\t\t\t\t\t\"solana_signAndSendTransaction\",\n\t\t\t\t\t\t{ transaction: toBase64.decode(encoder.encode(tx)) },\n\t\t\t\t\t);\n\t\t\t\t\treturn fromBase58.encode(signature) as SignatureBytes;\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t};\n};\n","import { getWallets } from \"@wallet-standard/app\";\nimport type { Wallet as WalletStandardWallet } from \"@wallet-standard/base\";\nimport type {\n\tStandardConnectFeature,\n\tStandardDisconnectFeature,\n} from \"@wallet-standard/features\";\nimport {\n\tBehaviorSubject,\n\tcombineLatest,\n\tdistinctUntilChanged,\n\tmap,\n\tObservable,\n\tshareReplay,\n} from \"rxjs\";\nimport { clearCachedObservablesByPrefix } from \"../../utils/getCachedObservable\";\nimport { getWalletId, type WalletId } from \"../../utils/WalletId\";\nimport { KheopskitError } from \"../errors\";\nimport { store as defaultStore, type KheopskitStore } from \"../store\";\nimport { isSolanaChainId, type SolanaChainId } from \"./chains\";\nimport type { SolanaInjectedWallet } from \"./types\";\n\ntype ConnectApi = StandardConnectFeature[\"standard:connect\"];\ntype DisconnectApi = StandardDisconnectFeature[\"standard:disconnect\"];\n\nconst SOLANA_NAMESPACE_PREFIX = \"solana:\";\n\n/** A Wallet Standard wallet is Solana-capable if it advertises a solana chain or feature. */\nconst isSolanaWallet = (wallet: WalletStandardWallet): boolean =>\n\twallet.chains.some((chain) => chain.startsWith(SOLANA_NAMESPACE_PREFIX)) ||\n\tObject.keys(wallet.features).some((feature) =>\n\t\tfeature.startsWith(SOLANA_NAMESPACE_PREFIX),\n\t);\n\nconst getSolanaChains = (wallet: WalletStandardWallet): SolanaChainId[] =>\n\twallet.chains.filter((chain): chain is SolanaChainId =>\n\t\tisSolanaChainId(chain),\n\t);\n\n/**\n * Observable of Solana-capable Wallet Standard wallets, updated as wallets\n * register/unregister. Returns an empty array during SSR.\n */\nconst walletStandardWallets$ = new Observable<readonly WalletStandardWallet[]>(\n\t(subscriber) => {\n\t\t// Guard against SSR - the Wallet Standard registry requires browser APIs\n\t\tif (typeof window === \"undefined\") {\n\t\t\tsubscriber.next([]);\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst { get, on } = getWallets();\n\t\tconst emit = () => subscriber.next(get().filter(isSolanaWallet));\n\n\t\temit();\n\n\t\tconst offRegister = on(\"register\", emit);\n\t\tconst offUnregister = on(\"unregister\", emit);\n\n\t\treturn () => {\n\t\t\toffRegister();\n\t\t\toffUnregister();\n\t\t};\n\t},\n).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\nconst createSolanaInjectedWallets$ = (store: KheopskitStore) =>\n\tnew Observable<SolanaInjectedWallet[]>((subscriber) => {\n\t\tconst enabledWalletIds$ = new BehaviorSubject<Set<WalletId>>(new Set());\n\n\t\tconst connect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_ALREADY_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is already connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:connect\"\n\t\t\t] as ConnectApi | undefined;\n\t\t\tif (!feature)\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"FEATURE_NOT_SUPPORTED\",\n\t\t\t\t\t`wallet ${walletId} does not support standard:connect`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\tawait feature.connect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.add(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.addEnabledWalletId(walletId);\n\t\t};\n\n\t\tconst disconnect = async (\n\t\t\twallet: WalletStandardWallet,\n\t\t\twalletId: WalletId,\n\t\t) => {\n\t\t\tif (!enabledWalletIds$.value.has(walletId))\n\t\t\t\tthrow new KheopskitError(\n\t\t\t\t\t\"WALLET_NOT_CONNECTED\",\n\t\t\t\t\t`wallet ${walletId} is not connected`,\n\t\t\t\t\t{ walletId },\n\t\t\t\t);\n\n\t\t\t// standard:disconnect is an optional feature. Await it when present so a\n\t\t\t// failed disconnect rejects the returned promise; if absent we still\n\t\t\t// clear local state below.\n\t\t\tconst feature = (wallet.features as Record<string, unknown>)[\n\t\t\t\t\"standard:disconnect\"\n\t\t\t] as DisconnectApi | undefined;\n\t\t\tawait feature?.disconnect();\n\n\t\t\tconst newSet = new Set(enabledWalletIds$.value);\n\t\t\tnewSet.delete(walletId);\n\t\t\tenabledWalletIds$.next(newSet);\n\n\t\t\tstore.removeEnabledWalletId(walletId);\n\n\t\t\t// Drop cached account observables for this wallet so a later reconnect\n\t\t\t// rebuilds them against the current wallet handle, not a stale closure.\n\t\t\tclearCachedObservablesByPrefix(`accounts:${walletId}:`);\n\t\t};\n\n\t\tconst sub = combineLatest([walletStandardWallets$, enabledWalletIds$])\n\t\t\t.pipe(\n\t\t\t\tmap(([wallets, enabledWalletIds]) =>\n\t\t\t\t\twallets.map((wallet): SolanaInjectedWallet => {\n\t\t\t\t\t\tconst walletId = getWalletId(\"solana\", wallet.name);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tplatform: \"solana\",\n\t\t\t\t\t\t\ttype: \"injected\",\n\t\t\t\t\t\t\tid: walletId,\n\t\t\t\t\t\t\tsourceId: wallet.name,\n\t\t\t\t\t\t\twallet,\n\t\t\t\t\t\t\tchains: getSolanaChains(wallet),\n\t\t\t\t\t\t\tname: wallet.name,\n\t\t\t\t\t\t\ticon: wallet.icon,\n\t\t\t\t\t\t\tisConnected: enabledWalletIds.has(walletId),\n\t\t\t\t\t\t\tconnect: () => connect(wallet, walletId),\n\t\t\t\t\t\t\tdisconnect: () => disconnect(wallet, walletId),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tdistinctUntilChanged(walletsEqual),\n\t\t\t)\n\t\t\t.subscribe(subscriber);\n\n\t\treturn () => {\n\t\t\tsub.unsubscribe();\n\t\t};\n\t}).pipe(shareReplay({ refCount: true, bufferSize: 1 }));\n\n// The shared WalletConnect connector is emitted once by core (see\n// `getWallets$`), not per platform — so this returns only injected wallets.\nexport const getSolanaWallets$ = (store: KheopskitStore = defaultStore) =>\n\tcreateSolanaInjectedWallets$(store);\n\n/**\n * Compare two wallet arrays by their relevant properties (not functions).\n */\nconst walletsEqual = (\n\ta: SolanaInjectedWallet[],\n\tb: SolanaInjectedWallet[],\n): boolean => {\n\tif (a.length !== b.length) return false;\n\treturn a.every(\n\t\t(w, i) =>\n\t\t\tw.id === b[i]?.id &&\n\t\t\tw.isConnected === b[i]?.isConnected &&\n\t\t\tw.name === b[i]?.name,\n\t);\n};\n","import type { KheopskitPlatform, PlatformContext } from \"../types\";\nimport { getSolanaAccounts$ } from \"./accounts\";\nimport {\n\tDEFAULT_SOLANA_CHAIN,\n\tisSolanaChainId,\n\ttype SolanaChainId,\n} from \"./chains\";\nimport type { SolanaAccount, SolanaWallet } from \"./types\";\nimport { getSolanaWallets$ } from \"./wallets\";\n\nexport type SolanaPluginOptions = {\n\t/**\n\t * Solana cluster that account signers target. Each account also exposes a\n\t * `getSigner(chain)` factory for targeting another cluster.\n\t *\n\t * @default \"solana:mainnet\"\n\t */\n\tchain?: SolanaChainId;\n};\n\n/**\n * Solana platform plugin. Pass to `getKheopskit$({ platforms: [solana()] })`.\n *\n * @example\n * ```ts\n * import { solana } from \"@kheopskit/core/solana\";\n * solana({ chain: \"solana:mainnet\" });\n * ```\n */\nexport const solana = (\n\toptions: SolanaPluginOptions = {},\n): KheopskitPlatform<\"solana\", SolanaWallet, SolanaAccount> => {\n\tconst chain = options.chain ?? DEFAULT_SOLANA_CHAIN;\n\n\tif (!isSolanaChainId(chain)) {\n\t\tconsole.warn(\n\t\t\t`[kheopskit] Unknown solana chain: ${JSON.stringify(chain)}. Valid values: \"solana:mainnet\", \"solana:devnet\", \"solana:testnet\", \"solana:localnet\".`,\n\t\t);\n\t}\n\n\treturn {\n\t\tplatform: \"solana\",\n\t\tgetWallets$: (ctx: PlatformContext) => getSolanaWallets$(ctx.store),\n\t\tgetAccounts$: (wallets$) => getSolanaAccounts$(wallets$, chain),\n\t};\n};\n"],"mappings":"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","names":["address","combineLatest","distinctUntilChanged","map","Observable","shareReplay","Observable","shareReplay","store","combineLatest","map","distinctUntilChanged"]}
@@ -3,6 +3,10 @@ import { Observable } from 'rxjs';
3
3
 
4
4
  type WalletAccountId = string;
5
5
  declare const getWalletAccountId: (walletId: string, address: string) => WalletAccountId;
6
+ declare const parseWalletAccountId: (accountId: string) => {
7
+ walletId: string;
8
+ address: string;
9
+ };
6
10
 
7
11
  type WalletId = string;
8
12
  declare const getWalletId: (platform: WalletPlatform, identifier: string) => WalletId;
@@ -10,6 +14,11 @@ declare const parseWalletId: (walletId: string) => {
10
14
  platform: WalletPlatform;
11
15
  identifier: string;
12
16
  };
17
+ /**
18
+ * Non-throwing variant of {@link parseWalletId}. Use when validating untrusted
19
+ * input (e.g. cached state persisted by an older version) before parsing.
20
+ */
21
+ declare const isValidWalletId: (walletId: unknown) => walletId is WalletId;
13
22
 
14
23
  type KheopskitStoreData = {
15
24
  autoReconnect?: WalletId[];
@@ -103,7 +112,7 @@ type AppKitInstance = {
103
112
  caipNetworkId?: string;
104
113
  }[];
105
114
  };
106
- type WalletType = "injected" | "appKit";
115
+ type WalletType = "injected" | "walletconnect";
107
116
  type PolkadotAccountType = "sr25519" | "ed25519" | "ecdsa" | "ethereum";
108
117
  /**
109
118
  * SDK-free fields common to every wallet, regardless of platform. Platform
@@ -139,21 +148,27 @@ type BaseWalletAccount = {
139
148
  walletId: WalletId;
140
149
  };
141
150
  /**
142
- * AppKit (WalletConnect) wallet handle for a given platform. References only
143
- * `@reown/appkit` (a hard dependency) — no optional platform SDK — so it lives
144
- * in core and is shared by every platform's wallet union.
151
+ * The single WalletConnect connector, shared across every platform.
145
152
  *
146
- * The per-platform aliases below (`PolkadotAppKitWallet`, ) are kept so each
147
- * platform entry point can re-export a concrete name.
153
+ * Unlike injected wallets, it is **not tied to a platform**: one WalletConnect
154
+ * session spans whichever namespaces the remote wallet approves in a single
155
+ * pairing (a namespace can't be added to a live session afterwards). So there is
156
+ * exactly one of these in `wallets`, discriminated by `type: "walletconnect"`.
157
+ * Its accounts appear in `accounts`, each carrying its own `platform`.
148
158
  */
149
- type AppKitWallet<P extends WalletPlatform = WalletPlatform> = {
159
+ type WalletConnectWallet = {
150
160
  id: WalletId;
151
- platform: P;
152
- type: "appKit";
161
+ type: "walletconnect";
162
+ /**
163
+ * Platforms (namespaces) the live session currently carries. Empty until
164
+ * connected; populated with whatever the wallet approved (e.g. just
165
+ * `["ethereum"]`, or `["polkadot", "ethereum"]`).
166
+ */
167
+ platforms: WalletPlatform[];
153
168
  /**
154
169
  * Raw Reown AppKit instance, exposed as an escape hatch for advanced use
155
170
  * (custom modal control, reading providers directly). Most consumers should
156
- * use the wallet's `connect`/`disconnect` and the derived accounts instead.
171
+ * use `connect`/`disconnect` and the derived accounts instead.
157
172
  */
158
173
  appKit: AppKitInstance;
159
174
  name: string;
@@ -162,9 +177,23 @@ type AppKitWallet<P extends WalletPlatform = WalletPlatform> = {
162
177
  connect: () => Promise<void>;
163
178
  disconnect: () => Promise<void>;
164
179
  };
165
- type PolkadotAppKitWallet = AppKitWallet<"polkadot">;
166
- type EthereumAppKitWallet = AppKitWallet<"ethereum">;
167
- type SolanaAppKitWallet = AppKitWallet<"solana">;
180
+ /** Narrows a wallet to the platform-less {@link WalletConnectWallet}. */
181
+ declare const isWalletConnectWallet: (wallet: BaseWallet | WalletConnectWallet) => wallet is WalletConnectWallet;
182
+ /**
183
+ * Narrows a wallet to an injected (browser-extension / Wallet Standard) wallet —
184
+ * the complement of {@link isWalletConnectWallet}. `state.wallets` is
185
+ * `(InjectedWallet | WalletConnectWallet)[]`, so use this to recover the
186
+ * injected-only fields when iterating: `platform`, `sourceId`, and the SDK
187
+ * handle (`provider` on Ethereum, `extension` on Polkadot, `wallet` on Solana).
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * for (const wallet of wallets.filter(isInjectedWallet)) {
192
+ * console.log(wallet.platform, wallet.sourceId); // typed, no WC widening
193
+ * }
194
+ * ```
195
+ */
196
+ declare const isInjectedWallet: <W extends BaseWallet | WalletConnectWallet>(wallet: W) => wallet is Exclude<W, WalletConnectWallet>;
168
197
  /**
169
198
  * Dapp metadata shown in the WalletConnect modal. Mirrors WalletConnect's
170
199
  * `Metadata`, declared locally so core doesn't depend on
@@ -212,7 +241,7 @@ type PlatformContext = {
212
241
  type KheopskitPlatform<TPlatform extends WalletPlatform = WalletPlatform, TWallet extends BaseWallet = BaseWallet, TAccount extends BaseWalletAccount = BaseWalletAccount> = {
213
242
  readonly platform: TPlatform;
214
243
  getWallets$(ctx: PlatformContext): Observable<TWallet[]>;
215
- getAccounts$(wallets$: Observable<TWallet[]>): Observable<TAccount[]>;
244
+ getAccounts$(wallets$: Observable<(TWallet | WalletConnectWallet)[]>): Observable<TAccount[]>;
216
245
  /**
217
246
  * Optional hydration filter. Cached accounts for which this returns false are
218
247
  * dropped during SSR hydration (Polkadot uses it to honour `accountTypes`).
@@ -274,7 +303,7 @@ type KheopskitConfig<P extends readonly KheopskitPlatform[] = readonly Kheopskit
274
303
  * so it remains absent until the live account loads.
275
304
  */
276
305
  type KheopskitState<P extends readonly KheopskitPlatform[] = readonly KheopskitPlatform[]> = {
277
- wallets: WalletOf<P[number]>[];
306
+ wallets: (WalletOf<P[number]> | WalletConnectWallet)[];
278
307
  accounts: AccountOf<P[number]>[];
279
308
  config: KheopskitConfig<P>;
280
309
  /**
@@ -294,7 +323,8 @@ type KheopskitState<P extends readonly KheopskitPlatform[] = readonly KheopskitP
294
323
  */
295
324
  type CachedWallet = {
296
325
  id: WalletId;
297
- platform: WalletPlatform;
326
+ /** Absent for the platform-less WalletConnect connector. */
327
+ platform?: WalletPlatform;
298
328
  type: WalletType;
299
329
  name: string;
300
330
  isConnected: boolean;
@@ -316,4 +346,4 @@ type CachedAccount = {
316
346
  walletName: string;
317
347
  };
318
348
 
319
- export { type AccountOf as A, type BaseWallet as B, type CachedAccount as C, type EthereumAppKitWallet as E, type KheopskitPlatform as K, type PlatformContext as P, type SolanaAppKitWallet as S, type WalletAccountId as W, type WalletId as a, type KheopskitConfig as b, createKheopskitStore as c, type KheopskitState as d, type AppKitInstance as e, type AppKitWallet as f, type BaseWalletAccount as g, type CachedWallet as h, type PolkadotAccountType as i, type PolkadotAppKitWallet as j, type WalletConnectConfig as k, type WalletConnectMetadata as l, type WalletConnectProvider as m, type WalletOf as n, type WalletPlatform as o, type WalletType as p, getDefaultStore as q, getWalletAccountId as r, getWalletId as s, parseWalletId as t };
349
+ export { type AccountOf as A, type BaseWallet as B, type CachedAccount as C, type KheopskitPlatform as K, type PlatformContext as P, type WalletAccountId as W, type WalletId as a, type WalletConnectWallet as b, isWalletConnectWallet as c, type KheopskitConfig as d, createKheopskitStore as e, type KheopskitState as f, type AppKitInstance as g, type BaseWalletAccount as h, isInjectedWallet as i, type CachedWallet as j, type PolkadotAccountType as k, type WalletConnectConfig as l, type WalletConnectMetadata as m, type WalletConnectProvider as n, type WalletOf as o, type WalletPlatform as p, type WalletType as q, getDefaultStore as r, getWalletAccountId as s, getWalletId as t, isValidWalletId as u, parseWalletAccountId as v, parseWalletId as w };