@effectstream/wallets 0.100.14 → 0.100.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1 +1,120 @@
1
- # Effectstream Wallets
1
+ # @effectstream/wallets
2
+
3
+ Browser wallet connectors and the runtime client an EffectStream
4
+ frontend uses to log in, sign batcher messages, send transactions, and
5
+ wait for them to be processed. Spans MetaMask (and any EVM-injected
6
+ wallet), Cardano (CIP-30), Midnight, Mina, Polkadot, Algorand, and
7
+ Avail.
8
+
9
+ - Browser wallet connectors plus the runtime client a frontend uses to log in, sign, and submit.
10
+ - Spans MetaMask + injected EVM, Cardano (CIP-30), Midnight, Mina, Polkadot, Algorand, Avail.
11
+ - Used together with `@effectstream/crypto` (server-side verification).
12
+ - High-level helpers `walletLogin` and `sendTransaction` hide the polling loop.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ bun add @effectstream/wallets
18
+ # or
19
+ npm install @effectstream/wallets
20
+ ```
21
+
22
+ ## Standalone usage
23
+
24
+ The high-level path most apps use: log in with a wallet, then send a
25
+ transaction through the batcher and wait until it lands in a block.
26
+
27
+ ```typescript
28
+ import {
29
+ walletLogin,
30
+ WalletMode,
31
+ EffectstreamConfig,
32
+ sendTransaction,
33
+ } from "@effectstream/wallets";
34
+
35
+ const config = new EffectstreamConfig({ /* …chain/batcher URLs… */ });
36
+
37
+ const wallet = await walletLogin({
38
+ config,
39
+ preference: { name: "MetaMask" },
40
+ mode: WalletMode.EvmInjected,
41
+ });
42
+
43
+ const result = await sendTransaction(wallet, "join|alice");
44
+ // result.blockHeight === number once the batcher's submission landed
45
+ ```
46
+
47
+ If you just want to discover available wallets:
48
+
49
+ ```typescript
50
+ import { allInjectedWallets, WalletMode } from "@effectstream/wallets";
51
+
52
+ const available = await allInjectedWallets({
53
+ signatureSupport: true,
54
+ transactionSupport: true,
55
+ });
56
+ const evmOptions = available[WalletMode.EvmInjected]; // [{ metadata, ... }, …]
57
+ ```
58
+
59
+ > **Browser only.** This package depends on `window.ethereum`, the
60
+ > Cardano CIP-30 API, etc. — it won't load in plain Node. Server-side
61
+ > signature verification is `@effectstream/crypto`.
62
+
63
+ ## Inside EffectStream
64
+
65
+ The client-side counterpart to `@effectstream/crypto`. Frontends
66
+ connect a wallet, sign a batcher login or transaction, and POST it to
67
+ the batcher HTTP endpoint (`@effectstream/batcher-sdk`). The node's
68
+ state machine then verifies the signature with
69
+ `CryptoManager.getCryptoManager(addressType)`. The runtime helpers
70
+ exported here (`sendTransaction`, `waitForEffectstreamBlockProcessed`)
71
+ hide the polling loop.
72
+
73
+ ## Key exports
74
+
75
+ Login + signing:
76
+
77
+ - `walletLogin(args)`: top-level helper that discovers, connects, and produces a signed batcher login.
78
+ - `EffectstreamConfig`: runtime config (chain URLs, batcher URL, ...) the helpers consume.
79
+ - `signMessage(wallet, message)` — sign an arbitrary message with the connected wallet.
80
+
81
+ Sending transactions:
82
+
83
+ - `sendTransaction(wallet, conciseInput, opts?)`: submit through the batcher and (by default) wait for processing.
84
+ - `sendBatcherTransaction(...)`: explicit batcher submission.
85
+ - `sendSelfSequencedTransaction(...)` bypasses the batcher.
86
+ - `waitForEffectstreamBlockProcessed(...)` — block-height poller used by the above.
87
+
88
+ Wallet discovery / identification:
89
+
90
+ - `WalletMode`: enum of `EvmInjected`, `EvmEthers`, `Midnight`, `Cardano`, `Polkadot`, `Algorand`, `Mina`, `AvailJs`.
91
+ - `WalletNameMap`: `Record<WalletMode, string>` for display.
92
+ - `allInjectedWallets(config)` lists installed wallets in the browser.
93
+ - `getAddressType(walletMode)` maps a `WalletMode` to its `@effectstream/utils` `AddressType`.
94
+
95
+ Types:
96
+
97
+ - `Wallet`: handle returned by `walletLogin`, used by send/sign helpers.
98
+ - `UserSignature`, `Hash`, `BatcherPostResponse`, `BatcherTrackResponse`, `PostDataResponse`, `PostDataResponseAsync`, `SignFunction`.
99
+
100
+ Lower-level connector machinery (used internally; export surface is
101
+ stable but rarely needed in app code): `connectInjectedWallet`,
102
+ `WalletModeMap`, `IProvider`, `IConnector`, `IInjectedConnector`,
103
+ `InjectionPreference`.
104
+
105
+ ## Examples
106
+
107
+ Runnable: [`src/utils.test.ts`](./src/utils.test.ts) and
108
+ [`test/examples.test.ts`](./test/examples.test.ts).
109
+
110
+ Real-world usage in templates (each imports `walletLogin`, `WalletMode`,
111
+ `EffectstreamConfig`, `sendTransaction`):
112
+
113
+ - [`templates/chess-v2/`](https://github.com/effectstream/effectstream/tree/main/templates/chess-v2)
114
+ - [`templates/evm-midnight-v2/`](https://github.com/effectstream/effectstream/tree/main/templates/evm-midnight-v2)
115
+ - [`templates/shinkai-v2/`](https://github.com/effectstream/effectstream/tree/main/templates/shinkai-v2)
116
+
117
+ ## Links
118
+
119
+ - Docs: https://effectstream.github.io/docs/packages/sdk/wallets
120
+ - Source: https://github.com/effectstream/effectstream/tree/main/packages/effectstream-sdk/wallets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effectstream/wallets",
3
- "version": "0.100.14",
3
+ "version": "0.100.16",
4
4
  "license": "MIT",
5
5
  "homepage": "https://effectstream.github.io/docs/",
6
6
  "repository": {
@@ -13,10 +13,10 @@
13
13
  },
14
14
  "exports": "./src/mod.ts",
15
15
  "dependencies": {
16
- "@effectstream/concise": "0.100.14",
17
- "@effectstream/crypto": "0.100.14",
18
- "@effectstream/event-client": "0.100.14",
19
- "@effectstream/utils": "0.100.14",
16
+ "@effectstream/concise": "0.100.16",
17
+ "@effectstream/crypto": "0.100.16",
18
+ "@effectstream/event-client": "0.100.16",
19
+ "@effectstream/utils": "0.100.16",
20
20
  "@aurowallet/mina-provider": "^1.0.12",
21
21
  "@metamask/providers": "^22.1.0",
22
22
  "@midnight-ntwrk/dapp-connector-api": "4.0.1",
@@ -15,7 +15,14 @@ import { BuiltinEvents, EventManager } from "@effectstream/event-client";
15
15
  * communication. It sets up the location of the Effectstream L2 Contact.
16
16
  */
17
17
  export class EffectstreamConfig {
18
- public appName: string;
18
+ /**
19
+ * Security namespace string the user wallet signs into every batched message.
20
+ * Must match the server's `setSecurityNamespace(...)` (or, when the server uses
21
+ * a transition object, one of its `read.prefixes`) for the primitive's
22
+ * re-verification to admit the input. `undefined` / `""` means no namespace
23
+ * (legacy null-prefixed signing).
24
+ */
25
+ public securityNamespace: string | null;
19
26
  public effectstreamL2SyncProtocolName: string;
20
27
  public effectstreamL2ContractAddress: EvmAddress;
21
28
  public effectstreamL2Abi: AbiItem[];
@@ -26,7 +33,7 @@ export class EffectstreamConfig {
26
33
  public preferBatchedMode: boolean = false;
27
34
 
28
35
  constructor(
29
- appName: string | undefined,
36
+ securityNamespace: string | undefined,
30
37
  effectstreamL2SyncProtocolName: string,
31
38
  effectstreamL2ContractAddress: EvmAddress,
32
39
  effectstreamL2Chain: Chain,
@@ -34,7 +41,9 @@ export class EffectstreamConfig {
34
41
  batcherURL: string | undefined,
35
42
  preferBatchedMode: boolean = false,
36
43
  ) {
37
- this.appName = appName ?? "";
44
+ this.securityNamespace = securityNamespace && securityNamespace.length > 0
45
+ ? securityNamespace
46
+ : null;
38
47
 
39
48
  this.effectstreamL2SyncProtocolName = effectstreamL2SyncProtocolName;
40
49
  this.effectstreamL2ContractAddress = effectstreamL2ContractAddress;
@@ -338,7 +347,7 @@ export async function sendBatcherTransaction(
338
347
  const timestamp = Date.now().toString();
339
348
  const signature = await wallet.provider.signMessage(
340
349
  createMessageForBatcher(
341
- effectstreamConfig.appName,
350
+ effectstreamConfig.securityNamespace,
342
351
  timestamp,
343
352
  wallet.provider.getAddress().address,
344
353
  wallet.provider.getAddress().type,
@@ -0,0 +1,62 @@
1
+ // Examples for the README. Wallets is browser-only — so we exercise the
2
+ // public API through a mock IInjectedConnector, the same pattern as
3
+ // src/utils.test.ts.
4
+
5
+ import { test, expect } from "bun:test";
6
+ import { connectInjectedWallet } from "../src/utils.ts";
7
+ import { WalletMode, WalletNameMap } from "../src/mod.ts";
8
+ import type { IInjectedConnector, IProvider } from "../src/IProvider.ts";
9
+ import { AddressType } from "@effectstream/utils";
10
+
11
+ const MOCK_ADDRESS = "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd";
12
+ const MOCK_METADATA = {
13
+ name: "MockWallet",
14
+ displayName: "Mock Wallet",
15
+ icon: "",
16
+ version: "1.0",
17
+ };
18
+
19
+ const mockProvider = (): IProvider<unknown> => ({
20
+ getConnection: () => ({ metadata: MOCK_METADATA, api: {} }),
21
+ getAddress: () => ({ type: AddressType.EVM, address: MOCK_ADDRESS }),
22
+ signMessage: async () => "0xsignedmessage",
23
+ });
24
+
25
+ const mockConnector = (): IInjectedConnector<unknown> => ({
26
+ connectSimple: async () => mockProvider(),
27
+ connectNamed: async (_name: string) => mockProvider(),
28
+ connectExternal: async () => mockProvider(),
29
+ });
30
+
31
+ test("README: WalletNameMap covers every WalletMode", () => {
32
+ for (
33
+ const mode of [
34
+ WalletMode.EvmInjected,
35
+ WalletMode.EvmEthers,
36
+ WalletMode.Midnight,
37
+ WalletMode.Cardano,
38
+ WalletMode.Polkadot,
39
+ WalletMode.Algorand,
40
+ WalletMode.Mina,
41
+ WalletMode.AvailJs,
42
+ ]
43
+ ) {
44
+ expect(typeof WalletNameMap[mode]).toBe("string");
45
+ expect(WalletNameMap[mode].length).toBeGreaterThan(0);
46
+ }
47
+ });
48
+
49
+ test("README: connectInjectedWallet returns an IProvider with address + sign", async () => {
50
+ const provider = await connectInjectedWallet(
51
+ "EVM",
52
+ { name: MOCK_METADATA.name },
53
+ mockConnector(),
54
+ );
55
+
56
+ const { type, address } = provider.getAddress();
57
+ expect(type).toBe(AddressType.EVM);
58
+ expect(address).toBe(MOCK_ADDRESS);
59
+
60
+ const signature = await provider.signMessage("Sign in 2026-05-14");
61
+ expect(signature).toBe("0xsignedmessage");
62
+ });