@multiplatform.one/web3 7.18.0 → 7.19.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 (246) hide show
  1. package/README.md +60 -0
  2. package/dist/cjs/clients/adapter.cjs +33 -0
  3. package/dist/cjs/clients/adapter.native.js +36 -0
  4. package/dist/cjs/clients/adapter.native.js.map +1 -0
  5. package/dist/cjs/clients/bitcoin.cjs +46 -0
  6. package/dist/cjs/clients/bitcoin.native.js +51 -0
  7. package/dist/cjs/clients/bitcoin.native.js.map +1 -0
  8. package/dist/cjs/clients/connector.cjs +45 -0
  9. package/dist/cjs/clients/connector.native.js +49 -0
  10. package/dist/cjs/clients/connector.native.js.map +1 -0
  11. package/dist/cjs/clients/evm.cjs +171 -0
  12. package/dist/cjs/clients/evm.native.js +198 -0
  13. package/dist/cjs/clients/evm.native.js.map +1 -0
  14. package/dist/cjs/clients/gpg.cjs +31 -0
  15. package/dist/cjs/clients/gpg.native.js +34 -0
  16. package/dist/cjs/clients/gpg.native.js.map +1 -0
  17. package/dist/cjs/clients/hooks.cjs +78 -0
  18. package/dist/cjs/clients/hooks.native.js +85 -0
  19. package/dist/cjs/clients/hooks.native.js.map +1 -0
  20. package/dist/cjs/clients/index.cjs +49 -0
  21. package/dist/cjs/clients/index.native.js +52 -0
  22. package/dist/cjs/clients/index.native.js.map +1 -0
  23. package/dist/cjs/clients/solana.cjs +322 -0
  24. package/dist/cjs/clients/solana.native.js +511 -0
  25. package/dist/cjs/clients/solana.native.js.map +1 -0
  26. package/dist/cjs/clients/solanaMessage.cjs +38 -0
  27. package/dist/cjs/clients/solanaMessage.native.js +44 -0
  28. package/dist/cjs/clients/solanaMessage.native.js.map +1 -0
  29. package/dist/cjs/clients/sui.cjs +46 -0
  30. package/dist/cjs/clients/sui.native.js +51 -0
  31. package/dist/cjs/clients/sui.native.js.map +1 -0
  32. package/dist/cjs/clients/types.cjs +37 -0
  33. package/dist/cjs/clients/types.native.js +160 -0
  34. package/dist/cjs/clients/types.native.js.map +1 -0
  35. package/dist/cjs/clients/useSolanaClient.cjs +50 -0
  36. package/dist/cjs/clients/useSolanaClient.native.js +57 -0
  37. package/dist/cjs/clients/useSolanaClient.native.js.map +1 -0
  38. package/dist/cjs/clients/walletStandard.cjs +63 -0
  39. package/dist/cjs/clients/walletStandard.native.js +71 -0
  40. package/dist/cjs/clients/walletStandard.native.js.map +1 -0
  41. package/dist/cjs/connectkit/connectors/walletAdapterConnector.cjs +2 -0
  42. package/dist/cjs/connectkit/connectors/walletAdapterConnector.native.js +2 -0
  43. package/dist/cjs/connectkit/connectors/walletAdapterConnector.native.js.map +1 -1
  44. package/dist/cjs/connectkit/siwe/SIWEProvider.cjs +4 -5
  45. package/dist/cjs/connectkit/siwe/SIWEProvider.native.js +4 -5
  46. package/dist/cjs/connectkit/siwe/SIWEProvider.native.js.map +1 -1
  47. package/dist/cjs/index.cjs +2 -1
  48. package/dist/cjs/index.native.js +1 -0
  49. package/dist/cjs/index.native.js.map +1 -1
  50. package/dist/cjs/solana.cjs +41 -0
  51. package/dist/cjs/solana.native.js +44 -0
  52. package/dist/cjs/solana.native.js.map +1 -0
  53. package/dist/esm/clients/adapter.mjs +8 -0
  54. package/dist/esm/clients/adapter.mjs.map +1 -0
  55. package/dist/esm/clients/adapter.native.js +8 -0
  56. package/dist/esm/clients/adapter.native.js.map +1 -0
  57. package/dist/esm/clients/bitcoin.mjs +21 -0
  58. package/dist/esm/clients/bitcoin.mjs.map +1 -0
  59. package/dist/esm/clients/bitcoin.native.js +23 -0
  60. package/dist/esm/clients/bitcoin.native.js.map +1 -0
  61. package/dist/esm/clients/connector.mjs +20 -0
  62. package/dist/esm/clients/connector.mjs.map +1 -0
  63. package/dist/esm/clients/connector.native.js +21 -0
  64. package/dist/esm/clients/connector.native.js.map +1 -0
  65. package/dist/esm/clients/evm.mjs +146 -0
  66. package/dist/esm/clients/evm.mjs.map +1 -0
  67. package/dist/esm/clients/evm.native.js +170 -0
  68. package/dist/esm/clients/evm.native.js.map +1 -0
  69. package/dist/esm/clients/gpg.mjs +3 -0
  70. package/dist/esm/clients/gpg.mjs.map +1 -0
  71. package/dist/esm/clients/gpg.native.js +3 -0
  72. package/dist/esm/clients/gpg.native.js.map +1 -0
  73. package/dist/esm/clients/hooks.mjs +51 -0
  74. package/dist/esm/clients/hooks.mjs.map +1 -0
  75. package/dist/esm/clients/hooks.native.js +55 -0
  76. package/dist/esm/clients/hooks.native.js.map +1 -0
  77. package/dist/esm/clients/index.mjs +11 -0
  78. package/dist/esm/clients/index.mjs.map +1 -0
  79. package/dist/esm/clients/index.native.js +11 -0
  80. package/dist/esm/clients/index.native.js.map +1 -0
  81. package/dist/esm/clients/solana.mjs +289 -0
  82. package/dist/esm/clients/solana.mjs.map +1 -0
  83. package/dist/esm/clients/solana.native.js +475 -0
  84. package/dist/esm/clients/solana.native.js.map +1 -0
  85. package/dist/esm/clients/solanaMessage.mjs +13 -0
  86. package/dist/esm/clients/solanaMessage.mjs.map +1 -0
  87. package/dist/esm/clients/solanaMessage.native.js +16 -0
  88. package/dist/esm/clients/solanaMessage.native.js.map +1 -0
  89. package/dist/esm/clients/sui.mjs +21 -0
  90. package/dist/esm/clients/sui.mjs.map +1 -0
  91. package/dist/esm/clients/sui.native.js +23 -0
  92. package/dist/esm/clients/sui.native.js.map +1 -0
  93. package/dist/esm/clients/types.mjs +12 -0
  94. package/dist/esm/clients/types.mjs.map +1 -0
  95. package/dist/esm/clients/types.native.js +132 -0
  96. package/dist/esm/clients/types.native.js.map +1 -0
  97. package/dist/esm/clients/useSolanaClient.mjs +25 -0
  98. package/dist/esm/clients/useSolanaClient.mjs.map +1 -0
  99. package/dist/esm/clients/useSolanaClient.native.js +29 -0
  100. package/dist/esm/clients/useSolanaClient.native.js.map +1 -0
  101. package/dist/esm/clients/walletStandard.mjs +33 -0
  102. package/dist/esm/clients/walletStandard.mjs.map +1 -0
  103. package/dist/esm/clients/walletStandard.native.js +38 -0
  104. package/dist/esm/clients/walletStandard.native.js.map +1 -0
  105. package/dist/esm/connectkit/connectors/walletAdapterConnector.mjs +2 -0
  106. package/dist/esm/connectkit/connectors/walletAdapterConnector.mjs.map +1 -1
  107. package/dist/esm/connectkit/connectors/walletAdapterConnector.native.js +2 -0
  108. package/dist/esm/connectkit/connectors/walletAdapterConnector.native.js.map +1 -1
  109. package/dist/esm/connectkit/siwe/SIWEProvider.mjs +4 -5
  110. package/dist/esm/connectkit/siwe/SIWEProvider.mjs.map +1 -1
  111. package/dist/esm/connectkit/siwe/SIWEProvider.native.js +4 -5
  112. package/dist/esm/connectkit/siwe/SIWEProvider.native.js.map +1 -1
  113. package/dist/esm/index.mjs +1 -0
  114. package/dist/esm/index.mjs.map +1 -1
  115. package/dist/esm/index.native.js +1 -0
  116. package/dist/esm/index.native.js.map +1 -1
  117. package/dist/esm/solana.mjs +5 -0
  118. package/dist/esm/solana.mjs.map +1 -0
  119. package/dist/esm/solana.native.js +5 -0
  120. package/dist/esm/solana.native.js.map +1 -0
  121. package/dist/jsx/clients/adapter.mjs +8 -0
  122. package/dist/jsx/clients/adapter.mjs.map +1 -0
  123. package/dist/jsx/clients/adapter.native.js +36 -0
  124. package/dist/jsx/clients/adapter.native.js.map +1 -0
  125. package/dist/jsx/clients/bitcoin.mjs +21 -0
  126. package/dist/jsx/clients/bitcoin.mjs.map +1 -0
  127. package/dist/jsx/clients/bitcoin.native.js +51 -0
  128. package/dist/jsx/clients/bitcoin.native.js.map +1 -0
  129. package/dist/jsx/clients/connector.mjs +20 -0
  130. package/dist/jsx/clients/connector.mjs.map +1 -0
  131. package/dist/jsx/clients/connector.native.js +49 -0
  132. package/dist/jsx/clients/connector.native.js.map +1 -0
  133. package/dist/jsx/clients/evm.mjs +146 -0
  134. package/dist/jsx/clients/evm.mjs.map +1 -0
  135. package/dist/jsx/clients/evm.native.js +198 -0
  136. package/dist/jsx/clients/evm.native.js.map +1 -0
  137. package/dist/jsx/clients/gpg.mjs +3 -0
  138. package/dist/jsx/clients/gpg.mjs.map +1 -0
  139. package/dist/jsx/clients/gpg.native.js +34 -0
  140. package/dist/jsx/clients/gpg.native.js.map +1 -0
  141. package/dist/jsx/clients/hooks.mjs +51 -0
  142. package/dist/jsx/clients/hooks.mjs.map +1 -0
  143. package/dist/jsx/clients/hooks.native.js +85 -0
  144. package/dist/jsx/clients/hooks.native.js.map +1 -0
  145. package/dist/jsx/clients/index.mjs +11 -0
  146. package/dist/jsx/clients/index.mjs.map +1 -0
  147. package/dist/jsx/clients/index.native.js +52 -0
  148. package/dist/jsx/clients/index.native.js.map +1 -0
  149. package/dist/jsx/clients/solana.mjs +289 -0
  150. package/dist/jsx/clients/solana.mjs.map +1 -0
  151. package/dist/jsx/clients/solana.native.js +511 -0
  152. package/dist/jsx/clients/solana.native.js.map +1 -0
  153. package/dist/jsx/clients/solanaMessage.mjs +13 -0
  154. package/dist/jsx/clients/solanaMessage.mjs.map +1 -0
  155. package/dist/jsx/clients/solanaMessage.native.js +44 -0
  156. package/dist/jsx/clients/solanaMessage.native.js.map +1 -0
  157. package/dist/jsx/clients/sui.mjs +21 -0
  158. package/dist/jsx/clients/sui.mjs.map +1 -0
  159. package/dist/jsx/clients/sui.native.js +51 -0
  160. package/dist/jsx/clients/sui.native.js.map +1 -0
  161. package/dist/jsx/clients/types.mjs +12 -0
  162. package/dist/jsx/clients/types.mjs.map +1 -0
  163. package/dist/jsx/clients/types.native.js +160 -0
  164. package/dist/jsx/clients/types.native.js.map +1 -0
  165. package/dist/jsx/clients/useSolanaClient.mjs +25 -0
  166. package/dist/jsx/clients/useSolanaClient.mjs.map +1 -0
  167. package/dist/jsx/clients/useSolanaClient.native.js +57 -0
  168. package/dist/jsx/clients/useSolanaClient.native.js.map +1 -0
  169. package/dist/jsx/clients/walletStandard.mjs +33 -0
  170. package/dist/jsx/clients/walletStandard.mjs.map +1 -0
  171. package/dist/jsx/clients/walletStandard.native.js +71 -0
  172. package/dist/jsx/clients/walletStandard.native.js.map +1 -0
  173. package/dist/jsx/connectkit/connectors/walletAdapterConnector.mjs +2 -0
  174. package/dist/jsx/connectkit/connectors/walletAdapterConnector.mjs.map +1 -1
  175. package/dist/jsx/connectkit/connectors/walletAdapterConnector.native.js +2 -0
  176. package/dist/jsx/connectkit/connectors/walletAdapterConnector.native.js.map +1 -1
  177. package/dist/jsx/connectkit/siwe/SIWEProvider.mjs +4 -5
  178. package/dist/jsx/connectkit/siwe/SIWEProvider.mjs.map +1 -1
  179. package/dist/jsx/connectkit/siwe/SIWEProvider.native.js +4 -5
  180. package/dist/jsx/connectkit/siwe/SIWEProvider.native.js.map +1 -1
  181. package/dist/jsx/index.js +1 -0
  182. package/dist/jsx/index.js.map +1 -1
  183. package/dist/jsx/index.mjs +1 -0
  184. package/dist/jsx/index.mjs.map +1 -1
  185. package/dist/jsx/index.native.js +1 -0
  186. package/dist/jsx/index.native.js.map +1 -1
  187. package/dist/jsx/solana.mjs +5 -0
  188. package/dist/jsx/solana.mjs.map +1 -0
  189. package/dist/jsx/solana.native.js +44 -0
  190. package/dist/jsx/solana.native.js.map +1 -0
  191. package/package.json +13 -6
  192. package/src/clients/adapter.ts +13 -0
  193. package/src/clients/bitcoin.ts +42 -0
  194. package/src/clients/connector.spec.ts +78 -0
  195. package/src/clients/connector.ts +36 -0
  196. package/src/clients/evm.spec.ts +265 -0
  197. package/src/clients/evm.ts +223 -0
  198. package/src/clients/gpg.spec.ts +169 -0
  199. package/src/clients/gpg.ts +8 -0
  200. package/src/clients/hooks.spec.tsx +113 -0
  201. package/src/clients/hooks.ts +51 -0
  202. package/src/clients/index.ts +40 -0
  203. package/src/clients/solana.spec.ts +444 -0
  204. package/src/clients/solana.ts +465 -0
  205. package/src/clients/solanaMessage.ts +34 -0
  206. package/src/clients/sui.ts +42 -0
  207. package/src/clients/types.ts +40 -0
  208. package/src/clients/useSolanaClient.ts +31 -0
  209. package/src/clients/walletStandard.ts +87 -0
  210. package/src/connectkit/connectors/walletAdapterConnector.ts +2 -0
  211. package/src/connectkit/siwe/SIWEProvider.spec.tsx +112 -0
  212. package/src/connectkit/siwe/SIWEProvider.tsx +6 -10
  213. package/src/index.ts +4 -0
  214. package/src/solana.ts +30 -0
  215. package/types/clients/adapter.d.ts +5 -0
  216. package/types/clients/adapter.d.ts.map +1 -0
  217. package/types/clients/bitcoin.d.ts +21 -0
  218. package/types/clients/bitcoin.d.ts.map +1 -0
  219. package/types/clients/connector.d.ts +14 -0
  220. package/types/clients/connector.d.ts.map +1 -0
  221. package/types/clients/evm.d.ts +68 -0
  222. package/types/clients/evm.d.ts.map +1 -0
  223. package/types/clients/gpg.d.ts +2 -0
  224. package/types/clients/gpg.d.ts.map +1 -0
  225. package/types/clients/hooks.d.ts +16 -0
  226. package/types/clients/hooks.d.ts.map +1 -0
  227. package/types/clients/index.d.ts +10 -0
  228. package/types/clients/index.d.ts.map +1 -0
  229. package/types/clients/solana.d.ts +111 -0
  230. package/types/clients/solana.d.ts.map +1 -0
  231. package/types/clients/solanaMessage.d.ts +18 -0
  232. package/types/clients/solanaMessage.d.ts.map +1 -0
  233. package/types/clients/sui.d.ts +21 -0
  234. package/types/clients/sui.d.ts.map +1 -0
  235. package/types/clients/types.d.ts +27 -0
  236. package/types/clients/types.d.ts.map +1 -0
  237. package/types/clients/useSolanaClient.d.ts +11 -0
  238. package/types/clients/useSolanaClient.d.ts.map +1 -0
  239. package/types/clients/walletStandard.d.ts +63 -0
  240. package/types/clients/walletStandard.d.ts.map +1 -0
  241. package/types/connectkit/connectors/walletAdapterConnector.d.ts.map +1 -1
  242. package/types/connectkit/siwe/SIWEProvider.d.ts.map +1 -1
  243. package/types/index.d.ts +1 -0
  244. package/types/index.d.ts.map +1 -1
  245. package/types/solana.d.ts +4 -0
  246. package/types/solana.d.ts.map +1 -0
@@ -0,0 +1,87 @@
1
+ // Minimal Wallet Standard plumbing for Solana: the registry handshake and the
2
+ // feature shapes the client calls. Structural types instead of @wallet-standard/*
3
+ // so the page bundle carries no extra package; Phantom, Solflare and Backpack all
4
+ // register this way.
5
+
6
+ export interface StandardWalletAccount {
7
+ readonly address: string;
8
+ readonly publicKey: Uint8Array;
9
+ readonly chains: readonly string[];
10
+ readonly features: readonly string[];
11
+ }
12
+
13
+ export interface StandardWallet {
14
+ readonly name: string;
15
+ readonly icon?: string;
16
+ readonly chains: readonly string[];
17
+ readonly accounts: readonly StandardWalletAccount[];
18
+ readonly features: Readonly<Record<string, unknown>>;
19
+ }
20
+
21
+ export const SolanaSignMessage = "solana:signMessage";
22
+ export const SolanaSignTransaction = "solana:signTransaction";
23
+ export const SolanaSignAndSendTransaction = "solana:signAndSendTransaction";
24
+ export const StandardConnect = "standard:connect";
25
+
26
+ export interface SolanaSignMessageFeature {
27
+ signMessage(
28
+ ...inputs: { account: StandardWalletAccount; message: Uint8Array }[]
29
+ ): Promise<{ signedMessage: Uint8Array; signature: Uint8Array }[]>;
30
+ }
31
+
32
+ export interface SolanaSignTransactionFeature {
33
+ signTransaction(
34
+ ...inputs: { account: StandardWalletAccount; transaction: Uint8Array; chain?: string }[]
35
+ ): Promise<{ signedTransaction: Uint8Array }[]>;
36
+ }
37
+
38
+ export interface SolanaSignAndSendTransactionFeature {
39
+ signAndSendTransaction(
40
+ ...inputs: {
41
+ account: StandardWalletAccount;
42
+ transaction: Uint8Array;
43
+ chain: string;
44
+ options?: { commitment?: "processed" | "confirmed" | "finalized"; skipPreflight?: boolean };
45
+ }[]
46
+ ): Promise<{ signature: Uint8Array }[]>;
47
+ }
48
+
49
+ export interface StandardConnectFeature {
50
+ connect(input?: { silent?: boolean }): Promise<{ accounts: readonly StandardWalletAccount[] }>;
51
+ }
52
+
53
+ /**
54
+ * Every wallet registered with the Wallet Standard right now. Wallets answer
55
+ * `app-ready` synchronously, so this can be called again to pick up late ones.
56
+ */
57
+ export function getStandardWallets(): StandardWallet[] {
58
+ if (typeof window === "undefined") return [];
59
+ const wallets: StandardWallet[] = [];
60
+ const api = {
61
+ register: (...registered: StandardWallet[]) => {
62
+ wallets.push(...registered);
63
+ return () => {};
64
+ },
65
+ };
66
+ const onRegister = (event: Event) => {
67
+ try {
68
+ ((event as CustomEvent).detail as (a: typeof api) => void)(api);
69
+ } catch {
70
+ // a wallet that throws during registration is simply not offered
71
+ }
72
+ };
73
+ window.addEventListener("wallet-standard:register-wallet", onRegister);
74
+ try {
75
+ window.dispatchEvent(new CustomEvent("wallet-standard:app-ready", { detail: api }));
76
+ } finally {
77
+ window.removeEventListener("wallet-standard:register-wallet", onRegister);
78
+ }
79
+ return [...new Set(wallets)];
80
+ }
81
+
82
+ /** Wallets that can sign Solana transactions. */
83
+ export function getSolanaWallets(): StandardWallet[] {
84
+ return getStandardWallets().filter(
85
+ (wallet) => wallet.features[SolanaSignTransaction] && wallet.features[StandardConnect],
86
+ );
87
+ }
@@ -71,6 +71,8 @@ export function walletAdapterConnector(entry: WalletConnectorEntry) {
71
71
  icon: entry.icon,
72
72
  // custom tag read by getConnectorEcosystem()/WalletProps.ecosystem
73
73
  ecosystem: entry.ecosystem,
74
+ // read by clientForConnector() to build the per-chain client
75
+ adapter: entry.adapter,
74
76
 
75
77
  async getProvider() {
76
78
  return provider;
@@ -0,0 +1,112 @@
1
+ // @vitest-environment happy-dom
2
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
+ import { act, render, waitFor } from "@testing-library/react";
4
+ import { createContext, useContext } from "react";
5
+ import { beforeEach, describe, expect, it, vi } from "vitest";
6
+ import { getBase58Decoder } from "@solana/kit";
7
+
8
+ const { mockUseAccount, mockSignMessageAsync } = vi.hoisted(() => ({
9
+ mockUseAccount: vi.fn(),
10
+ mockSignMessageAsync: vi.fn(),
11
+ }));
12
+
13
+ vi.mock("wagmi", () => ({
14
+ useAccount: mockUseAccount,
15
+ useAccountEffect: () => undefined,
16
+ useSignMessage: () => ({ signMessageAsync: mockSignMessageAsync }),
17
+ }));
18
+
19
+ vi.mock("@multiplatform.one/connectkit", () => ({
20
+ Context: createContext(null),
21
+ isWalletConnector: (c?: { type?: string }) => c?.type === "wallet",
22
+ }));
23
+
24
+ import { SIWEContext } from "./SIWEContext";
25
+ import { SIWEProvider } from "./SIWEProvider";
26
+
27
+ const solanaAddress = getBase58Decoder().decode(new Uint8Array(32).fill(7));
28
+ const b64 = (s: string) => window.btoa(unescape(encodeURIComponent(s)));
29
+
30
+ function signInWith(connector: object, address: string, chainId: number) {
31
+ mockUseAccount.mockReturnValue({ address, chain: { id: chainId }, connector });
32
+ const onSign = vi.fn(async () => undefined);
33
+ let signIn: (() => Promise<unknown>) | undefined;
34
+ let nonceReady = false;
35
+ function Probe() {
36
+ const ctx = useContext(SIWEContext);
37
+ signIn = ctx?.signIn;
38
+ nonceReady = !!ctx?.nonce.data;
39
+ return null;
40
+ }
41
+ render(
42
+ <QueryClientProvider client={new QueryClient()}>
43
+ <SIWEProvider
44
+ getNonce={async () => "nonce123"}
45
+ createMessage={({ address: a, nonce }) => `example.com login ${a} ${nonce}`}
46
+ verifyMessage={async () => true}
47
+ getSession={async () => null}
48
+ signOut={async () => true}
49
+ onSign={onSign}
50
+ >
51
+ <Probe />
52
+ </SIWEProvider>
53
+ </QueryClientProvider>,
54
+ );
55
+ return {
56
+ onSign,
57
+ async run() {
58
+ await waitFor(() => expect(nonceReady).toBe(true));
59
+ await act(async () => {
60
+ await signIn?.();
61
+ });
62
+ },
63
+ };
64
+ }
65
+
66
+ describe("SIWEProvider signing", () => {
67
+ beforeEach(() => vi.clearAllMocks());
68
+
69
+ it("signs a non-EVM wallet through its client, never the shim provider", async () => {
70
+ const adapter = { address: solanaAddress, signMessage: vi.fn(async () => "1112") };
71
+ const getProvider = vi.fn();
72
+ const connector = {
73
+ id: "wallet:solana:phantom",
74
+ type: "wallet",
75
+ ecosystem: "solana",
76
+ adapter,
77
+ getProvider,
78
+ };
79
+ const { onSign, run } = signInWith(connector, solanaAddress, 0x534f4c);
80
+ await run();
81
+ const message = `example.com login ${solanaAddress} nonce123`;
82
+ expect(adapter.signMessage).toHaveBeenCalledWith(message);
83
+ expect(getProvider).not.toHaveBeenCalled();
84
+ expect(onSign).toHaveBeenCalledWith({ username: "1112", password: b64(message), message });
85
+ });
86
+
87
+ it("signs Sui and Bitcoin wallets through their clients", async () => {
88
+ for (const [ecosystem, address, chainId] of [
89
+ ["sui", "0xsui", 0x535549],
90
+ ["bitcoin", "bc1qexample", 0x425443],
91
+ ] as const) {
92
+ const adapter = { address, signMessage: vi.fn(async () => `${ecosystem}-sig`) };
93
+ const connector = { id: `wallet:${ecosystem}`, type: "wallet", ecosystem, adapter };
94
+ const { onSign, run } = signInWith(connector, address, chainId);
95
+ await run();
96
+ expect(onSign).toHaveBeenCalledWith(
97
+ expect.objectContaining({ username: `${ecosystem}-sig` }),
98
+ );
99
+ }
100
+ });
101
+
102
+ it("keeps EVM wallets on wagmi's signMessage", async () => {
103
+ mockSignMessageAsync.mockResolvedValue("0xevmsig");
104
+ const address = "0x1111111111111111111111111111111111111111";
105
+ const { onSign, run } = signInWith({ id: "metaMask", type: "injected" }, address, 1);
106
+ await run();
107
+ expect(mockSignMessageAsync).toHaveBeenCalledWith({
108
+ message: `example.com login ${address} nonce123`,
109
+ });
110
+ expect(onSign).toHaveBeenCalledWith(expect.objectContaining({ username: "0xevmsig" }));
111
+ });
112
+ });
@@ -6,6 +6,7 @@ import { useQuery } from "@tanstack/react-query";
6
6
  import { Context as ConnectKitContext } from "@multiplatform.one/connectkit";
7
7
  import { SIWEContext, SIWEConfig, StatusState, SIWESession } from "./SIWEContext";
8
8
  import { isWalletConnector } from "@multiplatform.one/connectkit";
9
+ import { clientForConnector } from "../../clients/connector";
9
10
 
10
11
  type Props = SIWEConfig & {
11
12
  children: ReactNode;
@@ -129,18 +130,13 @@ export const SIWEProvider = ({
129
130
 
130
131
  // Ask user to sign message with their wallet. wallet (non-EVM) connectors can't
131
132
  // go through viem's signMessage — it validates the account as a 20-byte EVM
132
- // address (bc1…/base58/sui-0x all fail). Sign through the connector's provider
133
- // directly: our shim routes personal_sign → adapter.signMessage and returns the
134
- // chain-native signature (base58/base64) untouched.
133
+ // address (bc1…/base58/sui-0x all fail). Sign through the wallet's per-chain
134
+ // client instead, which returns the chain-native signature (base58/base64).
135
135
  let signature: string;
136
136
  if (connector && isWalletConnector(connector)) {
137
- const provider = (await connector.getProvider()) as {
138
- request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;
139
- };
140
- signature = (await provider.request({
141
- method: "personal_sign",
142
- params: [message, address],
143
- })) as string;
137
+ const client = clientForConnector(connector);
138
+ if (!client) throw new Error("The connected wallet has no signing client");
139
+ signature = await client.signMessage(message);
144
140
  } else {
145
141
  signature = await signMessageAsync({ message });
146
142
  }
package/src/index.ts CHANGED
@@ -64,6 +64,10 @@ export { mainnet, polygon, optimism, arbitrum, base, sepolia } from "wagmi/chain
64
64
  // Bridge (Hermes-safe; shared by web + the native WebView host)
65
65
  export * from "./bridge";
66
66
 
67
+ // Per-chain clients (EVM on viem, GPG signer, Solana/Sui/Bitcoin message signing;
68
+ // the Solana kit client is the web-only ./solana subpath)
69
+ export * from "./clients";
70
+
67
71
  // NOTE: SIWS (`./siws`) is intentionally NOT re-exported here. Its server-side
68
72
  // verify pulls @noble/curves + bs58 (ESM-only) which Hermes rejects in the RN
69
73
  // bundle ("import statement requires module mode"). It's server/web-side only —
package/src/solana.ts ADDED
@@ -0,0 +1,30 @@
1
+ // `@multiplatform.one/web3/solana`: the Solana client on @solana/kit, for web
2
+ // and the WebView bundle only. It is a subpath, with no react-native entry,
3
+ // because native signs Solana through the WebView bridge and kit must not be
4
+ // bundled there.
5
+ export {
6
+ connectSolanaWallet,
7
+ findSolanaSigner,
8
+ injectedSolanaSigner,
9
+ solanaChainFromRpcUrl,
10
+ solanaClient,
11
+ solanaRpcUrls,
12
+ standardSolanaSigner,
13
+ transferSolInstruction,
14
+ SolanaConfirmationError,
15
+ type SolanaChain,
16
+ type SolanaClient,
17
+ type SolanaClientConfig,
18
+ type SolanaCluster,
19
+ type SolanaConfirmationFailure,
20
+ type SolanaConfirmOptions,
21
+ type SolanaSigner,
22
+ type SolanaSubmission,
23
+ } from "./clients/solana";
24
+ export { useSolanaClient } from "./clients/useSolanaClient";
25
+ export {
26
+ getSolanaWallets,
27
+ getStandardWallets,
28
+ type StandardWallet,
29
+ type StandardWalletAccount,
30
+ } from "./clients/walletStandard";
@@ -0,0 +1,5 @@
1
+ import type { Ecosystem } from "@multiplatform.one/connectkit";
2
+ import type { WalletAdapter } from "../connectkit/adapters/types";
3
+ /** The wallet adapter a non-EVM shim connector carries (see walletAdapterConnector), or null. */
4
+ export declare function connectorAdapter(connector: unknown, ecosystem?: Exclude<Ecosystem, "evm">): WalletAdapter | null;
5
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/clients/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,iGAAiG;AACjG,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,OAAO,EAClB,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,GACpC,aAAa,GAAG,IAAI,CAKtB"}
@@ -0,0 +1,21 @@
1
+ import type { WalletAdapter } from "../connectkit/adapters/types";
2
+ import { type ChainClient } from "./types";
3
+ type MessageAdapter = Pick<WalletAdapter, "address" | "signMessage">;
4
+ /**
5
+ * Bitcoin client. Message signing only (BIP-322 simple), over the connected
6
+ * Bitcoin adapter. The transaction methods are the shape the PSBT work will
7
+ * fill in; until then they reject with UnsupportedClientMethodError.
8
+ */
9
+ export interface BitcoinClient extends ChainClient<"bitcoin"> {
10
+ readonly address: string;
11
+ readonly chainId: "bitcoin";
12
+ /** BIP-322 simple signature, base64. */
13
+ signMessage(message: string): Promise<string>;
14
+ /** Not implemented yet: will take a base64 PSBT and return it signed. */
15
+ signPsbt(psbt: string): Promise<never>;
16
+ /** Not implemented yet: will send `satoshis` to `to` and return the txid. */
17
+ sendBitcoin(to: string, satoshis: bigint): Promise<never>;
18
+ }
19
+ export declare function bitcoinClient(adapter: MessageAdapter): BitcoinClient;
20
+ export {};
21
+ //# sourceMappingURL=bitcoin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitcoin.d.ts","sourceRoot":"","sources":["../../src/clients/bitcoin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAgC,KAAK,WAAW,EAAyB,MAAM,SAAS,CAAC;AAEhG,KAAK,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC;AAKrE;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,WAAW,CAAC,SAAS,CAAC;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,wCAAwC;IACxC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACvC,6EAA6E;IAC7E,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;CAC3D;AAID,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAepE"}
@@ -0,0 +1,14 @@
1
+ import { type BitcoinClient } from "./bitcoin";
2
+ import { type SolanaChain, type SolanaMessageClient } from "./solanaMessage";
3
+ import { type SuiClient } from "./sui";
4
+ export interface ConnectorClientOptions {
5
+ solanaChain?: SolanaChain;
6
+ }
7
+ export type NonEvmClient = SolanaMessageClient | SuiClient | BitcoinClient;
8
+ /**
9
+ * The signing client for a connected non-EVM wallet, built over the adapter
10
+ * its shim connector carries. Sign-in uses it, so it stays free of
11
+ * @solana/kit. Null for an EVM connector or one that is not connected.
12
+ */
13
+ export declare function clientForConnector(connector: unknown, options?: ConnectorClientOptions): NonEvmClient | null;
14
+ //# sourceMappingURL=connector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/clients/connector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAuB,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClG,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlD,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,SAAS,GAAG,aAAa,CAAC;AAE3E;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,OAAO,EAClB,OAAO,GAAE,sBAA2B,GACnC,YAAY,GAAG,IAAI,CAarB"}
@@ -0,0 +1,68 @@
1
+ import { type Abi, type Account, type Address, type Chain, type ContractFunctionArgs, type ContractFunctionName, type EIP1193Provider, type Hash, type Hex, type PublicClient, type SendTransactionParameters, type TransactionReceipt, type Transport, type WalletClient, type WriteContractParameters } from "viem";
2
+ import type { ChainClient } from "./types";
3
+ /** A viem wallet client with its account and chain hoisted, the shape wagmi's getWalletClient returns. */
4
+ export type EvmWalletClient = WalletClient<Transport, Chain, Account>;
5
+ type WritableFunctionName<abi extends Abi | readonly unknown[]> = ContractFunctionName<abi, "nonpayable" | "payable">;
6
+ export type EvmWriteContractParameters<abi extends Abi | readonly unknown[] = Abi, functionName extends WritableFunctionName<abi> = WritableFunctionName<abi>, args extends ContractFunctionArgs<abi, "nonpayable" | "payable", functionName> = ContractFunctionArgs<abi, "nonpayable" | "payable", functionName>> = WriteContractParameters<abi, functionName, args, Chain, Account>;
7
+ export type EvmSendTransactionParameters = SendTransactionParameters<Chain, Account>;
8
+ export interface Erc20Actions {
9
+ balanceOf(token: Address, owner?: Address): Promise<bigint>;
10
+ allowance(token: Address, spender: Address, owner?: Address): Promise<bigint>;
11
+ decimals(token: Address): Promise<number>;
12
+ /** Simulates, then sends `transfer(to, amount)`. `amount` is in the token's base units. */
13
+ transfer(args: {
14
+ token: Address;
15
+ to: Address;
16
+ amount: bigint;
17
+ }): Promise<Hash>;
18
+ /** Simulates, then sends `approve(spender, amount)`. */
19
+ approve(args: {
20
+ token: Address;
21
+ spender: Address;
22
+ amount: bigint;
23
+ }): Promise<Hash>;
24
+ /**
25
+ * Approves `amount` only when the allowance is below it, and waits for that
26
+ * approval to be mined so a purchase call right after it sees the allowance.
27
+ * A non-zero allowance is reset to 0 first, since USDT refuses to move one
28
+ * non-zero allowance to another. Returns the final approval hash, or null
29
+ * when the allowance already covered it. Throws if an approval reverts.
30
+ */
31
+ ensureAllowance(args: {
32
+ token: Address;
33
+ spender: Address;
34
+ amount: bigint;
35
+ }): Promise<Hash | null>;
36
+ }
37
+ export interface EvmClient extends ChainClient<"evm"> {
38
+ readonly address: Address;
39
+ readonly chainId: number;
40
+ readonly chain: Chain;
41
+ /** The wallet side: anything viem's wallet actions can do. */
42
+ readonly walletClient: EvmWalletClient;
43
+ /** Reads, simulation and receipts. */
44
+ readonly publicClient: PublicClient;
45
+ /** personal_sign; returns the 0x signature. */
46
+ signMessage(message: string): Promise<Hex>;
47
+ sendTransaction(parameters: EvmSendTransactionParameters): Promise<Hash>;
48
+ writeContract<const abi extends Abi | readonly unknown[], functionName extends WritableFunctionName<abi>, args extends ContractFunctionArgs<abi, "nonpayable" | "payable", functionName>>(parameters: EvmWriteContractParameters<abi, functionName, args>): Promise<Hash>;
49
+ waitForTransactionReceipt(hash: Hash): Promise<TransactionReceipt>;
50
+ readonly erc20: Erc20Actions;
51
+ }
52
+ export type EvmClientConfig = ({
53
+ /** A viem wallet client, e.g. wagmi's `getWalletClient(config)`. */
54
+ walletClient: EvmWalletClient;
55
+ } | {
56
+ /** An EIP-1193 provider: injected, MetaMask Connect, or the native WebView bridge. */
57
+ provider: EIP1193Provider;
58
+ account: Address;
59
+ chain: Chain;
60
+ }) & {
61
+ /** Reads go here. Defaults to an http client on `rpcUrl`, else the chain's default RPC. */
62
+ publicClient?: PublicClient;
63
+ rpcUrl?: string;
64
+ };
65
+ /** Bind a viem WalletClient and PublicClient into the mpo EVM client. */
66
+ export declare function evmClient(config: EvmClientConfig): EvmClient;
67
+ export {};
68
+ //# sourceMappingURL=evm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm.d.ts","sourceRoot":"","sources":["../../src/clients/evm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { assertGpgSignature, createGpgSigner, gpgSignCommand, useGpgSigner, type GpgSigner, type GpgSignRequest, } from "@multiplatform.one/gpg/signer";
2
+ //# sourceMappingURL=gpg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpg.d.ts","sourceRoot":"","sources":["../../src/clients/gpg.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,cAAc,GACpB,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type BitcoinClient } from "./bitcoin";
2
+ import { type EvmClient } from "./evm";
3
+ import { type SuiClient } from "./sui";
4
+ /**
5
+ * The connected EVM wallet as a viem WalletClient plus a PublicClient for reads,
6
+ * wrapped in the mpo EVM client. Undefined until an EVM wallet is connected, and
7
+ * while a non-EVM wallet holds the connection.
8
+ */
9
+ export declare function useEvmClient(parameters?: {
10
+ chainId?: number;
11
+ }): EvmClient | undefined;
12
+ /** The connected Sui wallet (message signing only for now). */
13
+ export declare function useSuiClient(): SuiClient | undefined;
14
+ /** The connected Bitcoin wallet (message signing only for now). */
15
+ export declare function useBitcoinClient(): BitcoinClient | undefined;
16
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/clients/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,EAAa,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AACxE,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,SAAS,GAAG,SAAS,CAkBzF;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,SAAS,GAAG,SAAS,CAMpD;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,SAAS,CAM5D"}
@@ -0,0 +1,10 @@
1
+ export { UnsupportedClientMethodError, type ChainClient, type ClientCapability, type ClientFamily, } from "./types";
2
+ export { evmClient, type Erc20Actions, type EvmClient, type EvmClientConfig, type EvmSendTransactionParameters, type EvmWalletClient, type EvmWriteContractParameters, } from "./evm";
3
+ export { suiClient, type SuiClient } from "./sui";
4
+ export { bitcoinClient, type BitcoinClient } from "./bitcoin";
5
+ export { assertGpgSignature, createGpgSigner, gpgSignCommand, useGpgSigner, type GpgSigner, type GpgSignRequest, } from "./gpg";
6
+ export { connectorAdapter } from "./adapter";
7
+ export { clientForConnector, type ConnectorClientOptions, type NonEvmClient } from "./connector";
8
+ export { solanaMessageClient, type SolanaChain, type SolanaCluster, type SolanaMessageClient, } from "./solanaMessage";
9
+ export { useBitcoinClient, useEvmClient, useSuiClient } from "./hooks";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/clients/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,4BAA4B,EAC5B,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,0BAA0B,GAChC,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,cAAc,GACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACjG,OAAO,EACL,mBAAmB,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { type Address, type Instruction, type Rpc, type Signature, type SolanaRpcApi, type Transaction } from "@solana/kit";
2
+ import type { WalletAdapter } from "../connectkit/adapters/types";
3
+ import type { SolanaChain } from "./solanaMessage";
4
+ import { type ChainClient } from "./types";
5
+ import { type StandardWallet, type StandardWalletAccount } from "./walletStandard";
6
+ export type { SolanaChain, SolanaCluster } from "./solanaMessage";
7
+ export declare const solanaRpcUrls: Record<SolanaChain, string>;
8
+ /** Guess the cluster from an RPC URL, so a devnet `solanaRpcUrl` does not ask the wallet to sign for mainnet. */
9
+ export declare function solanaChainFromRpcUrl(rpcUrl?: string): SolanaChain;
10
+ /**
11
+ * The byte-level wallet a Solana client drives. Messages and transactions cross
12
+ * as raw bytes (wire-format transactions), so the same client runs over the
13
+ * Wallet Standard on web today and a deeplink wallet later.
14
+ */
15
+ export interface SolanaSigner {
16
+ readonly address: string;
17
+ /** Returns the 64-byte ed25519 signature. */
18
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
19
+ /** Returns the signed wire transaction. */
20
+ signTransaction(transaction: Uint8Array): Promise<Uint8Array>;
21
+ /** Returns the 64-byte transaction signature. Optional: without it the client signs, then sends over its own RPC. */
22
+ signAndSendTransaction?(transaction: Uint8Array): Promise<Uint8Array>;
23
+ }
24
+ export interface SolanaClientConfig {
25
+ signer: SolanaSigner;
26
+ /** JSON-RPC endpoint, usually `Web3Config.solanaRpcUrl`. Defaults to the chain's public endpoint. */
27
+ rpcUrl?: string;
28
+ /** A ready kit RPC client; wins over `rpcUrl`. */
29
+ rpc?: Rpc<SolanaRpcApi>;
30
+ /** Defaults to the cluster `rpcUrl` points at. */
31
+ chain?: SolanaChain;
32
+ }
33
+ /**
34
+ * A sent transaction. `lastValidBlockHeight` is known when the client saw the
35
+ * blockhash (transferSol, or a kit transaction carrying its lifetime), and is
36
+ * what lets confirmTransaction tell "expired, safe to retry" from "still pending".
37
+ */
38
+ export interface SolanaSubmission {
39
+ signature: Signature;
40
+ lastValidBlockHeight?: bigint;
41
+ }
42
+ export type SolanaConfirmationFailure = "failed" | "expired" | "timeout";
43
+ /**
44
+ * confirmTransaction's failure. `mayStillLand` is the part a caller acts on:
45
+ * resending while it is true can pay twice.
46
+ */
47
+ export declare class SolanaConfirmationError extends Error {
48
+ readonly signature: Signature;
49
+ readonly reason: SolanaConfirmationFailure;
50
+ readonly mayStillLand: boolean;
51
+ constructor(signature: Signature, reason: SolanaConfirmationFailure, detail: string);
52
+ }
53
+ export interface SolanaConfirmOptions {
54
+ commitment?: "confirmed" | "finalized";
55
+ /** Overrides the submission's. With it, failure waits for the blockhash to expire, however long that takes. */
56
+ lastValidBlockHeight?: bigint;
57
+ /** Only used without a lastValidBlockHeight; that failure says the transaction may still land. */
58
+ timeoutMs?: number;
59
+ pollMs?: number;
60
+ }
61
+ export interface SolanaClient extends ChainClient<"solana"> {
62
+ readonly address: Address;
63
+ readonly chainId: SolanaChain;
64
+ readonly rpc: Rpc<SolanaRpcApi>;
65
+ readonly signer: SolanaSigner;
66
+ /** Signs the UTF-8 bytes of a string (or raw bytes); returns the base58 signature. */
67
+ signMessage(message: string | Uint8Array): Promise<string>;
68
+ signTransaction(transaction: Transaction | Uint8Array): Promise<Transaction>;
69
+ /** The wallet signs and broadcasts when it can (Phantom asks for this); otherwise sign, then send over `rpc`. */
70
+ signAndSendTransaction(transaction: Transaction | Uint8Array): Promise<SolanaSubmission>;
71
+ /** Broadcasts an already signed transaction over `rpc`. */
72
+ sendTransaction(transaction: Transaction | Uint8Array): Promise<SolanaSubmission>;
73
+ /**
74
+ * Resolves once the transaction reaches `commitment`. Rejects with
75
+ * SolanaConfirmationError: `failed` (it landed and errored), `expired` (block
76
+ * height passed lastValidBlockHeight without it, safe to retry) or `timeout`
77
+ * (no lastValidBlockHeight to judge by, so it may still land).
78
+ */
79
+ confirmTransaction(submission: SolanaSubmission | Signature, options?: SolanaConfirmOptions): Promise<void>;
80
+ /** Lamports held by `owner`, the connected address by default. */
81
+ getBalance(owner?: string): Promise<bigint>;
82
+ /** Builds a System Program transfer, signs and sends it, and returns its lastValidBlockHeight. */
83
+ transferSol(args: {
84
+ to: string;
85
+ lamports: bigint;
86
+ }): Promise<SolanaSubmission>;
87
+ }
88
+ /** System Program `Transfer` (instruction index 2, then the lamports as a little-endian u64). */
89
+ export declare function transferSolInstruction(from: Address, to: Address, lamports: bigint): Instruction;
90
+ export declare function solanaClient(config: SolanaClientConfig): SolanaClient;
91
+ /** A SolanaSigner over one Wallet Standard wallet account (Phantom, Solflare, Backpack on web). */
92
+ export declare function standardSolanaSigner(wallet: StandardWallet, account: StandardWalletAccount, chain?: SolanaChain): SolanaSigner;
93
+ /** The Wallet Standard signer for a wallet that already holds `owner`, or null. */
94
+ export declare function findSolanaSigner(owner: string, chain?: SolanaChain): SolanaSigner | null;
95
+ /**
96
+ * Connect a Wallet Standard Solana wallet without the modal. `wallet` picks one
97
+ * by name (case-insensitive); otherwise the first registered one is used.
98
+ */
99
+ export declare function connectSolanaWallet(options?: {
100
+ wallet?: string;
101
+ chain?: SolanaChain;
102
+ silent?: boolean;
103
+ }): Promise<SolanaSigner>;
104
+ /**
105
+ * The signer behind a wallet connected through the modal's injected Solana
106
+ * adapter. Text messages go through the adapter exactly as login always has;
107
+ * transactions and non-text messages go through the Wallet Standard wallet
108
+ * holding the same address.
109
+ */
110
+ export declare function injectedSolanaSigner(adapter: Pick<WalletAdapter, "address" | "signMessage">, chain?: SolanaChain): SolanaSigner;
111
+ //# sourceMappingURL=solana.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solana.d.ts","sourceRoot":"","sources":["../../src/clients/solana.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { WalletAdapter } from "../connectkit/adapters/types";
2
+ import type { ChainClient } from "./types";
3
+ export type SolanaCluster = "mainnet" | "devnet" | "testnet" | "localnet";
4
+ /** The Wallet Standard chain id a wallet signs for. */
5
+ export type SolanaChain = `solana:${SolanaCluster}`;
6
+ /**
7
+ * A Solana wallet that only signs messages, over the modal's adapter. It needs
8
+ * no @solana/kit, which is why sign-in uses it: the full client (transactions,
9
+ * RPC) is `useSolanaClient()` from `@multiplatform.one/web3/solana`.
10
+ */
11
+ export interface SolanaMessageClient extends ChainClient<"solana"> {
12
+ readonly address: string;
13
+ readonly chainId: SolanaChain;
14
+ /** base58 ed25519 signature over the UTF-8 message. */
15
+ signMessage(message: string): Promise<string>;
16
+ }
17
+ export declare function solanaMessageClient(adapter: Pick<WalletAdapter, "address" | "signMessage">, chain?: SolanaChain): SolanaMessageClient;
18
+ //# sourceMappingURL=solanaMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solanaMessage.d.ts","sourceRoot":"","sources":["../../src/clients/solanaMessage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,SAAS,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAC1E,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG,UAAU,aAAa,EAAE,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,WAAW,CAAC,QAAQ,CAAC;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,uDAAuD;IACvD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAID,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,aAAa,CAAC,EACvD,KAAK,GAAE,WAA8B,GACpC,mBAAmB,CASrB"}
@@ -0,0 +1,21 @@
1
+ import type { WalletAdapter } from "../connectkit/adapters/types";
2
+ import { type ChainClient } from "./types";
3
+ type MessageAdapter = Pick<WalletAdapter, "address" | "signMessage">;
4
+ /**
5
+ * Sui client. Message signing only, over the connected Sui adapter. The
6
+ * transaction methods are the shape the transaction work will fill in; until
7
+ * then they reject with UnsupportedClientMethodError.
8
+ */
9
+ export interface SuiClient extends ChainClient<"sui"> {
10
+ readonly address: string;
11
+ readonly chainId: "sui:mainnet";
12
+ /** Sui's serialized signature (flag || signature || public key), base64. */
13
+ signMessage(message: string): Promise<string>;
14
+ /** Not implemented yet: will take a built transaction and return `{ bytes, signature }`. */
15
+ signTransaction(transaction: unknown): Promise<never>;
16
+ /** Not implemented yet: will return the executed transaction digest. */
17
+ signAndExecuteTransaction(transaction: unknown): Promise<never>;
18
+ }
19
+ export declare function suiClient(adapter: MessageAdapter): SuiClient;
20
+ export {};
21
+ //# sourceMappingURL=sui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../src/clients/sui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAgC,KAAK,WAAW,EAAyB,MAAM,SAAS,CAAC;AAEhG,KAAK,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC;AAKrE;;;;GAIG;AACH,MAAM,WAAW,SAAU,SAAQ,WAAW,CAAC,KAAK,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,4EAA4E;IAC5E,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,4FAA4F;IAC5F,eAAe,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACtD,wEAAwE;IACxE,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;CACjE;AAID,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,CAe5D"}