@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 +120 -1
- package/package.json +5 -5
- package/src/effectstream.ts +13 -4
- package/test/examples.test.ts +62 -0
package/README.md
CHANGED
|
@@ -1 +1,120 @@
|
|
|
1
|
-
#
|
|
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.
|
|
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.
|
|
17
|
-
"@effectstream/crypto": "0.100.
|
|
18
|
-
"@effectstream/event-client": "0.100.
|
|
19
|
-
"@effectstream/utils": "0.100.
|
|
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",
|
package/src/effectstream.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
+
});
|