@symbiome-forge/cow-sdk-wasm 0.1.0-alpha.4 → 0.1.0-alpha.6

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 (112) hide show
  1. package/README.md +202 -223
  2. package/dist/default/callbacks.d.ts +18 -0
  3. package/dist/default/edge.d.ts +111 -0
  4. package/dist/default/{index.mjs → edge.mjs} +23 -1
  5. package/dist/default/index.cjs +23 -0
  6. package/dist/default/index.d.ts +15 -0
  7. package/dist/default/internal.cjs +3 -2
  8. package/dist/default/internal.js +3 -2
  9. package/dist/default/module.d.ts +111 -0
  10. package/dist/default/module.mjs +323 -0
  11. package/dist/default/raw/{trading-web.d.ts → default-module.d.ts} +8 -3
  12. package/dist/default/raw/{trading-web.js → default-module.js} +4 -2
  13. package/dist/{orderbook/raw/trading-web.d.ts → default/raw/default-web.d.ts} +4 -2
  14. package/dist/{orderbook/raw/trading-web.js → default/raw/default-web.js} +3 -1
  15. package/dist/default/raw/default.cjs +3 -1
  16. package/dist/default/raw/default.d.ts +4 -0
  17. package/dist/default/raw/default.js +1 -0
  18. package/dist/orderbook/callbacks.d.ts +18 -0
  19. package/dist/orderbook/edge.d.ts +73 -0
  20. package/dist/orderbook/{index.mjs → edge.mjs} +20 -1
  21. package/dist/orderbook/index.cjs +20 -0
  22. package/dist/orderbook/index.d.ts +14 -0
  23. package/dist/orderbook/internal.cjs +3 -2
  24. package/dist/orderbook/internal.js +3 -2
  25. package/dist/orderbook/module.d.ts +73 -0
  26. package/dist/orderbook/module.mjs +164 -0
  27. package/dist/orderbook/raw/orderbook-module.d.ts +27 -0
  28. package/dist/orderbook/raw/orderbook-module.js +23 -0
  29. package/dist/orderbook/raw/orderbook-web.d.ts +24 -0
  30. package/dist/orderbook/raw/orderbook-web.js +23 -0
  31. package/dist/orderbook/raw/orderbook.cjs +3 -1
  32. package/dist/orderbook/raw/orderbook.d.ts +4 -0
  33. package/dist/orderbook/raw/orderbook.js +1 -0
  34. package/dist/raw/default-bundler/cow_sdk_wasm.d.ts +63 -15
  35. package/dist/raw/default-bundler/cow_sdk_wasm_bg.js +86 -35
  36. package/dist/raw/default-bundler/cow_sdk_wasm_bg.wasm +0 -0
  37. package/dist/raw/default-bundler/cow_sdk_wasm_bg.wasm.d.ts +4 -3
  38. package/dist/raw/default-module/cow_sdk_wasm.d.ts +3113 -0
  39. package/dist/raw/default-module/cow_sdk_wasm.js +2392 -0
  40. package/dist/raw/default-module/cow_sdk_wasm_bg.wasm.d.ts +78 -0
  41. package/dist/raw/default-nodejs/cow_sdk_wasm.cjs +86 -35
  42. package/dist/raw/default-nodejs/cow_sdk_wasm.d.ts +63 -15
  43. package/dist/raw/default-nodejs/cow_sdk_wasm_bg.wasm.d.ts +4 -3
  44. package/dist/raw/default-web/cow_sdk_wasm.d.ts +3216 -0
  45. package/dist/raw/default-web/cow_sdk_wasm.js +2489 -0
  46. package/dist/raw/default-web/cow_sdk_wasm_bg.wasm.d.ts +78 -0
  47. package/dist/raw/orderbook-bundler/cow_sdk_wasm.d.ts +18 -6
  48. package/dist/raw/orderbook-bundler/cow_sdk_wasm_bg.js +36 -24
  49. package/dist/raw/orderbook-bundler/cow_sdk_wasm_bg.wasm +0 -0
  50. package/dist/raw/orderbook-bundler/cow_sdk_wasm_bg.wasm.d.ts +3 -3
  51. package/dist/raw/orderbook-module/cow_sdk_wasm.d.ts +2037 -0
  52. package/dist/raw/orderbook-module/cow_sdk_wasm.js +1692 -0
  53. package/dist/raw/orderbook-module/cow_sdk_wasm_bg.wasm.d.ts +52 -0
  54. package/dist/raw/orderbook-nodejs/cow_sdk_wasm.cjs +36 -24
  55. package/dist/raw/orderbook-nodejs/cow_sdk_wasm.d.ts +18 -6
  56. package/dist/raw/orderbook-nodejs/cow_sdk_wasm_bg.wasm.d.ts +3 -3
  57. package/dist/raw/orderbook-web/cow_sdk_wasm.d.ts +2114 -0
  58. package/dist/raw/orderbook-web/cow_sdk_wasm.js +1789 -0
  59. package/dist/raw/orderbook-web/cow_sdk_wasm_bg.wasm.d.ts +52 -0
  60. package/dist/raw/signing-bundler/cow_sdk_wasm_bg.wasm +0 -0
  61. package/dist/raw/signing-module/cow_sdk_wasm.d.ts +774 -0
  62. package/dist/raw/signing-module/cow_sdk_wasm.js +1062 -0
  63. package/dist/raw/signing-module/cow_sdk_wasm_bg.wasm.d.ts +27 -0
  64. package/dist/raw/signing-web/cow_sdk_wasm.d.ts +826 -0
  65. package/dist/raw/signing-web/cow_sdk_wasm.js +1159 -0
  66. package/dist/raw/signing-web/cow_sdk_wasm_bg.wasm.d.ts +27 -0
  67. package/dist/raw/trading-bundler/cow_sdk_wasm.d.ts +63 -15
  68. package/dist/raw/trading-bundler/cow_sdk_wasm_bg.js +86 -35
  69. package/dist/raw/trading-bundler/cow_sdk_wasm_bg.wasm +0 -0
  70. package/dist/raw/trading-bundler/cow_sdk_wasm_bg.wasm.d.ts +4 -3
  71. package/dist/raw/trading-module/cow_sdk_wasm.d.ts +2977 -0
  72. package/dist/raw/trading-module/cow_sdk_wasm.js +2178 -0
  73. package/dist/raw/trading-module/cow_sdk_wasm_bg.wasm.d.ts +68 -0
  74. package/dist/raw/trading-nodejs/cow_sdk_wasm.cjs +86 -35
  75. package/dist/raw/trading-nodejs/cow_sdk_wasm.d.ts +63 -15
  76. package/dist/raw/trading-nodejs/cow_sdk_wasm_bg.wasm.d.ts +4 -3
  77. package/dist/raw/trading-web/cow_sdk_wasm.d.ts +67 -18
  78. package/dist/raw/trading-web/cow_sdk_wasm.js +87 -36
  79. package/dist/raw/trading-web/cow_sdk_wasm_bg.wasm.d.ts +4 -3
  80. package/dist/signing/callbacks.d.ts +18 -0
  81. package/dist/signing/edge.d.ts +37 -0
  82. package/dist/signing/{index.mjs → edge.mjs} +20 -1
  83. package/dist/signing/index.cjs +20 -0
  84. package/dist/signing/index.d.ts +14 -0
  85. package/dist/signing/internal.cjs +3 -2
  86. package/dist/signing/internal.js +3 -2
  87. package/dist/signing/module.d.ts +37 -0
  88. package/dist/signing/module.mjs +63 -0
  89. package/dist/signing/raw/signing-module.d.ts +21 -0
  90. package/dist/signing/raw/signing-module.js +17 -0
  91. package/dist/signing/raw/signing-web.d.ts +18 -0
  92. package/dist/signing/raw/signing-web.js +17 -0
  93. package/dist/signing/raw/signing.cjs +3 -1
  94. package/dist/signing/raw/signing.d.ts +4 -0
  95. package/dist/signing/raw/signing.js +1 -0
  96. package/dist/trading/callbacks.d.ts +18 -0
  97. package/dist/trading/edge.d.ts +1 -0
  98. package/dist/trading/edge.mjs +3 -0
  99. package/dist/trading/index.cjs +3 -0
  100. package/dist/trading/index.d.ts +1 -0
  101. package/dist/trading/internal.cjs +3 -2
  102. package/dist/trading/internal.js +3 -2
  103. package/dist/trading/module.d.ts +92 -0
  104. package/dist/trading/{index.mjs → module.mjs} +4 -1
  105. package/dist/{signing/raw/trading-web.d.ts → trading/raw/trading-module.d.ts} +6 -3
  106. package/dist/{signing/raw/trading-web.js → trading/raw/trading-module.js} +2 -2
  107. package/dist/trading/raw/trading.cjs +0 -6
  108. package/dist/trading/raw/trading.js +0 -6
  109. package/package.json +116 -18
  110. package/dist/default/raw/trading-web.cjs +0 -65
  111. package/dist/orderbook/raw/trading-web.cjs +0 -65
  112. package/dist/signing/raw/trading-web.cjs +0 -65
package/README.md CHANGED
@@ -1,287 +1,266 @@
1
1
  # @symbiome-forge/cow-sdk-wasm
2
2
 
3
- TypeScript-callable WebAssembly bindings for the CoW Protocol Rust SDK.
3
+ [CoW Protocol](https://cow.fi)'s Rust SDK, compiled to WebAssembly for JavaScript
4
+ and TypeScript. One protocol implementation runs in both runtimes, so the EIP-712
5
+ and EIP-1271 signatures a browser produces are byte-identical to the Rust
6
+ service's — checked against the upstream `cowprotocol/services` and
7
+ `cowprotocol/contracts` fixtures in CI, not asserted in prose.
4
8
 
5
9
  ```sh
6
10
  npm install @symbiome-forge/cow-sdk-wasm@alpha
7
11
  ```
8
12
 
9
- The package exposes a TypeScript facade over deterministic Rust protocol logic.
10
- JavaScript and TypeScript consumers get typed DTOs, explicit wallet and HTTP
11
- callbacks, per-call cancellation, per-call timeouts, and flavor-specific imports
12
- without depending on a specific wallet library.
13
+ A TypeScript facade over deterministic Rust protocol logic: typed DTOs, explicit
14
+ wallet and HTTP callbacks, per-call cancellation and timeouts, and
15
+ flavor-specific imports with no bundled wallet library.
16
+
17
+ ## Why this package
18
+
19
+ - **One source of truth.** Quote echoing, order-UID packing, app-data hashing,
20
+ and the EIP-712 / EIP-1271 signing path are the same Rust code a native
21
+ `cow-sdk` service runs, compiled to wasm — so protocol drift between a Rust
22
+ backend and a TypeScript frontend cannot happen. Every transform is proven
23
+ byte-for-byte against pinned upstream fixtures on each CI run.
24
+ - **No private key ever enters the SDK.** Signing is a callback you supply (viem,
25
+ ethers, an EIP-1193 wallet, or a Safe). There is no code path — not even a
26
+ feature-gated one — that accepts a private key or holds a wallet inside wasm
27
+ memory. The package produces typed data and transaction requests; your wallet
28
+ signs and submits.
29
+ - **The TypeScript surface is locked.** The public `.d.ts` for every flavor is a
30
+ committed snapshot that CI diffs on every build, so a contract change is a
31
+ reviewed diff, never a silent drift — the wasm analog of `cargo-public-api`.
32
+ - **Honest about fit.** For a standard browser dapp where minimal bundle size
33
+ dominates, upstream
34
+ [`@cowprotocol/cow-sdk`](https://www.npmjs.com/package/@cowprotocol/cow-sdk) is
35
+ smaller — use it. This package is for Rust ↔ TypeScript parity, single-source
36
+ embedding, edge runtimes, and embeddable signing.
37
+
38
+ ## Pick your import
39
+
40
+ Pick the **flavor** (feature set) by its base subpath. Every flavor ships the same
41
+ runtime entries over one shared wasm binary, so pick the **runtime** by the suffix:
13
42
 
14
- ## When to use this SDK
15
-
16
- | You are building... | Choose | Why |
43
+ | Import | Surface | Use when |
17
44
  | --- | --- | --- |
18
- | Browser dApp quote, sign, post, cancel (full order lifecycle) with viem, ethers, wagmi, or an EIP-1193 wallet | `@symbiome-forge/cow-sdk-wasm/trading` | Order lifecycle plus app-data, built for a browser bundler (Vite, webpack); wallet stack stays outside the package behind typed callbacks |
19
- | Browser dApp — orderbook reads and cancellation only | `@symbiome-forge/cow-sdk-wasm/orderbook` | Smaller read-focused subset, no trading or app-data |
20
- | Node.js 22 or 24 LTS backend running order flow | `@symbiome-forge/cow-sdk-wasm/trading` | Same order-lifecycle surface on the Node target, no browser polyfills |
21
- | Edge runtime — Cloudflare Workers, Deno, or Vercel Edge | `@symbiome-forge/cow-sdk-wasm/trading/edge` | The `trading` flavour's web-target build with explicit wasm module initialization |
22
- | Signer service or HSM proxy | `@symbiome-forge/cow-sdk-wasm/signing` | Signing primitives without orderbook, trading, subgraph, or IPFS clients |
23
- | Everything, including subgraph analytics and IPFS app-data | `@symbiome-forge/cow-sdk-wasm` | The full default surface |
24
- | Native Rust service, bot, solver, or treasury automation | `cow-sdk` | Avoids wasm-bindgen and npm packaging entirely |
25
- | Rust app compiled to browser WASM | `cow-sdk` with `cow-sdk-core`'s browser `FetchTransport` (the `wasm32-unknown-unknown` `transport::fetch` module) | Rust-on-wasm path; this package is for JavaScript hosts |
26
-
27
- The same `trading` flavour serves a browser dApp (bundler target), a Node backend
28
- (nodejs target), and an edge runtime (web target) from one feature set — pick the
29
- import by runtime; the package resolves the target through standard conditional
30
- exports, with `./trading/edge` as the explicit entry for Cloudflare Workers.
31
-
32
- ## Not in this crate
33
-
34
- Use the upstream TypeScript SDK packages until these capability families ship
35
- in `cow-rs`:
36
-
37
- - TWAP and composable orders.
38
- - Cross-chain bridging.
39
- - Cow Shed account abstraction.
40
- - Flash-loan helpers.
41
- - Weiroll command planning.
42
- - Hardware wallet adapters.
43
- - On-chain transaction submission; this package emits typed data or
44
- transaction requests and lets the caller's wallet submit.
45
- - WASI, WebAssembly components, TinyGo, Blazor, AssemblyScript guests, and
46
- `no_std` embedded targets.
47
-
48
- ## Quickstart
49
-
50
- ### Node.js 22 or 24 with viem
45
+ | `@symbiome-forge/cow-sdk-wasm/trading` | Full order lifecycle: quote, sign, post, cancel, app-data | A browser dapp, a Node backend, or an edge runtime running order flow one feature set serves all three; pick the runtime by suffix |
46
+ | `@symbiome-forge/cow-sdk-wasm/orderbook` | Orderbook reads, cancellation, and signing — no trading or app-data | A read-focused dapp that does not post orders |
47
+ | `@symbiome-forge/cow-sdk-wasm/signing` | Signing, UID, EIP-1271, deployment, and version helpers — the smallest flavor | A signer service or HSM-facing adapter |
48
+ | `@symbiome-forge/cow-sdk-wasm` | Everything above plus subgraph analytics and IPFS app-data | General use that needs subgraph or IPFS |
49
+
50
+ Each flavor exposes three runtime entries that share one wasm binary:
51
+
52
+ - the **base** import (above) auto-selects the build through standard conditional
53
+ exports: `node` loads the Node (CommonJS) build; `browser`, `import`, and the edge
54
+ conditions (`workerd` / `worker` / `deno` / `edge-light` / `bun`) load the
55
+ explicit-init **web** build, which instantiates its wasm through
56
+ `new URL(import.meta.url)` and so works across every bundler and with no bundler at
57
+ all call `await initialize()` once before the first call;
58
+ - **`…/edge`** is the explicit web entry for Cloudflare Workers, Deno, and Vercel
59
+ Edge pair it with **`…/edge/wasm`** for the precompiled module and call
60
+ `await initialize(wasmModule)`;
61
+ - **`…/module`** is the standards-track source-phase build (`import source` / Wasm
62
+ ESM Integration): it auto-initializes with no `initialize()` call, runs today on
63
+ Node 24, Deno, and esbuild, and is the forward path for browser bundlers as they
64
+ adopt source-phase.
65
+
66
+ So the focused flavors' entries are `…/trading/edge`, `…/trading/module`,
67
+ `…/orderbook/edge`, `…/signing/module`, and so on; the root (everything) flavor's are
68
+ `@symbiome-forge/cow-sdk-wasm/edge` and `@symbiome-forge/cow-sdk-wasm/module`. Public
69
+ imports go through these subpaths; do not import from `dist/raw` or generated
70
+ wasm-pack directories.
71
+
72
+ Building a **native Rust** service, or a Rust app you compile to wasm yourself?
73
+ Use [`cow-sdk`](https://crates.io/crates/cow-sdk) this package is for
74
+ JavaScript hosts.
75
+
76
+ ## Quickstart — a browser swap, end to end
77
+
78
+ Quote, then reuse that quote to sign and post in one call, so the amounts the user
79
+ confirms are the amounts that get posted — no second quote, no drift between
80
+ preview and signature. The wallet signs a typed-data envelope the SDK hands it;
81
+ no key reaches the package.
51
82
 
52
83
  ```ts
53
- import { TradingClient } from "@symbiome-forge/cow-sdk-wasm";
84
+ import { initialize, TradingClient } from "@symbiome-forge/cow-sdk-wasm/trading";
85
+ import { createWalletClient, custom } from "viem";
86
+ import { mainnet } from "viem/chains";
87
+
88
+ // Instantiate the wasm module once before any call. The bundled module is resolved
89
+ // from the package via `new URL(import.meta.url)`, so this works in every bundler
90
+ // and with no bundler at all — no bundler wasm plugin required.
91
+ await initialize();
92
+
93
+ const [owner] = await window.ethereum.request({ method: "eth_requestAccounts" });
94
+ const wallet = createWalletClient({ chain: mainnet, transport: custom(window.ethereum) });
54
95
 
55
96
  const trading = new TradingClient({
56
97
  chainId: 1,
57
98
  env: "prod",
58
- appCode: "my-node-service",
59
- transport: { kind: "fetch" },
60
- transportPolicy: {
61
- retryPolicy: { maxAttempts: 3, baseDelayMs: 200 },
62
- userAgent: "my-node-service/1.0"
63
- }
99
+ appCode: "my-dapp",
100
+ transport: { kind: "fetch" }
64
101
  });
65
102
 
66
- // `getQuote` returns a fully resolved `QuoteResultsDto` envelope.
103
+ // 1. Quote. `getQuote` returns a fully resolved QuoteResultsDto envelope.
104
+ // `owner` is required for a quote-only call.
67
105
  const quote = await trading.getQuote({
68
106
  kind: "sell",
69
- sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
70
- buyToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
107
+ owner,
108
+ sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
109
+ buyToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
71
110
  amount: "1000000000000000000"
72
111
  });
73
112
 
74
- // Reuse the quote to sign and post in one call; `quote.value` is the
75
- // `QuoteResultsDto` and the callback receives the EIP-712 envelope.
113
+ // 2. Reuse the quote to sign and post. The callback receives the EIP-712
114
+ // envelope and returns the signature the key stays in the wallet.
76
115
  const result = await trading.postSwapOrderFromQuote(
77
116
  quote.value,
78
- "0x1111111111111111111111111111111111111111",
79
- async (envelope) => walletClient.signTypedData(envelope),
80
- { walletConfig: { timeoutMs: 15_000 } }
81
- );
82
- // `result.value.orderId` is the posted order UID.
83
- ```
84
-
85
- ### Browser with `window.ethereum`
86
-
87
- ```ts
88
- import { signOrderWithEip1193 } from "@symbiome-forge/cow-sdk-wasm";
89
-
90
- const ethereum = window.ethereum;
91
- const [owner] = await ethereum.request({ method: "eth_requestAccounts" });
92
- const abortController = new AbortController();
93
-
94
- // The order to sign: build it yourself or map it from a fetched quote.
95
- const order = {
96
- sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
97
- buyToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
98
- receiver: owner,
99
- sellAmount: "1000000000000000000",
100
- buyAmount: "3500000000",
101
- validTo: Math.floor(Date.now() / 1000) + 3_600,
102
- appData: "0x0000000000000000000000000000000000000000000000000000000000000000",
103
- feeAmount: "0",
104
- kind: "sell",
105
- partiallyFillable: false,
106
- sellTokenBalance: "erc20",
107
- buyTokenBalance: "erc20"
108
- };
109
-
110
- const signed = await signOrderWithEip1193(
111
- order,
112
- 1,
113
117
  owner,
114
- (rpc) => ethereum.request(rpc),
115
- { signal: abortController.signal, walletConfig: { timeoutMs: 20_000 } }
118
+ (envelope) => {
119
+ // viem derives EIP712Domain from `domain`; drop it from `types`.
120
+ const types = Object.fromEntries(
121
+ Object.entries(envelope.types).filter(([name]) => name !== "EIP712Domain")
122
+ );
123
+ return wallet.signTypedData({
124
+ account: owner,
125
+ domain: envelope.domain,
126
+ types,
127
+ primaryType: envelope.primaryType,
128
+ message: envelope.message
129
+ });
130
+ },
131
+ { walletConfig: { timeoutMs: 20_000 } }
116
132
  );
117
- // `signed.value` is the SignedOrderDto.
118
- ```
119
-
120
- ### Browser with MetaMask `eth_signTypedData_v4`
121
133
 
122
- When the wallet exposes the typed-data JSON-RPC method directly, callers can
123
- pass the envelope to `eth_signTypedData_v4` from inside the typed-data signer
124
- callback. The helper hands the callback a typed-data envelope — plain `domain`,
125
- `types`, `primaryType`, and `message` objects — that the callback serializes and
126
- returns the signature string for.
127
-
128
- ```ts
129
- import { signOrderWithTypedDataSigner } from "@symbiome-forge/cow-sdk-wasm";
134
+ console.log(`https://explorer.cow.fi/mainnet/orders/${result.value.orderId}`);
135
+ trading.dispose();
136
+ ```
130
137
 
131
- const [owner] = await window.ethereum.request({ method: "eth_requestAccounts" });
138
+ Selling the native asset is the same shape: `getQuote`, then
139
+ `buildSellNativeCurrencyTxFromQuote(quote.value, owner)`, which returns the EthFlow
140
+ transaction request for the wallet to submit.
132
141
 
133
- const signed = await signOrderWithTypedDataSigner(order, 1, owner, async (envelope) => {
134
- const signature = await window.ethereum.request({
135
- method: "eth_signTypedData_v4",
136
- params: [owner, JSON.stringify(envelope)]
137
- });
138
- if (typeof signature !== "string") {
139
- throw new Error("wallet did not return a signature");
140
- }
141
- return signature;
142
- });
143
- ```
142
+ ### Cloudflare Worker (edge)
144
143
 
145
- ### Cloudflare Worker
144
+ Workers cannot compile wasm from bytes at runtime, so the edge build takes the
145
+ statically imported module through an explicit `initialize`.
146
146
 
147
147
  ```ts
148
- import initialize, {
149
- OrderBookClient
150
- } from "@symbiome-forge/cow-sdk-wasm/trading/edge";
148
+ import initialize, { OrderBookClient } from "@symbiome-forge/cow-sdk-wasm/trading/edge";
151
149
  import wasmModule from "@symbiome-forge/cow-sdk-wasm/trading/edge/wasm";
152
150
 
153
151
  export default {
154
152
  async fetch(request: Request, env: Env): Promise<Response> {
155
153
  await initialize(wasmModule);
156
-
157
154
  const client = new OrderBookClient({
158
155
  chainId: 1,
159
156
  env: "prod",
160
157
  apiKey: env.COW_PARTNER_API_KEY ?? null,
161
- transport: { kind: "fetch" },
162
- transportPolicy: { userAgent: "my-worker/1.0" }
163
- });
164
-
165
- const quote = await client.getQuote(await request.json(), {
166
- timeoutMs: 8_000
158
+ transport: { kind: "fetch" }
167
159
  });
160
+ const quote = await client.getQuote(await request.json(), { timeoutMs: 8_000 });
168
161
  client.dispose();
169
-
170
162
  return Response.json(quote);
171
163
  }
172
164
  };
173
165
  ```
174
166
 
175
- ## Choosing your import
167
+ ### Lower-level signing
176
168
 
177
- | Import | Surface | Use when |
178
- | --- | --- | --- |
179
- | `@symbiome-forge/cow-sdk-wasm` | Default facade with orderbook, signing, app-data, IPFS, trading, and subgraph | General TypeScript or Node use that needs subgraph or IPFS |
180
- | `@symbiome-forge/cow-sdk-wasm/trading` | Orderbook, trading, signing, app-data, and cancellation — the full order lifecycle | Browser dApps, Node backends, and edge runtimes running order flow |
181
- | `@symbiome-forge/cow-sdk-wasm/orderbook` | Orderbook client, cancellation helpers, and signing helpers | Read-focused dApps that do not post orders |
182
- | `@symbiome-forge/cow-sdk-wasm/signing` | Signing, UID, EIP-1271, deployment, and version helpers | Signer services and HSM-facing adapters |
183
- | `@symbiome-forge/cow-sdk-wasm/trading/edge` | The `trading` flavour's web-target facade | Edge runtimes (Cloudflare Workers, Deno, Vercel Edge) |
184
- | `@symbiome-forge/cow-sdk-wasm/trading/edge/wasm` | Raw Worker wasm module asset | Pass to the `initialize` helper |
169
+ For control over an order you build yourself, sign through an EIP-1193 wallet with
170
+ `signOrderWithEip1193(order, chainId, owner, (rpc) => ethereum.request(rpc))`, or
171
+ hand a typed-data method directly to `signOrderWithTypedDataSigner`. Both return a
172
+ `SignedOrderDto` you submit with `OrderBookClient.sendOrder`.
185
173
 
186
- Do not import from `dist/raw` or generated wasm-pack target directories. Raw
187
- wasm-bindgen output is package-internal; public imports go through the facade
188
- subpaths above.
174
+ ## The callback boundary
189
175
 
190
- ## Performance and bundle size
176
+ The package names host responsibilities as typed callbacks and never reaches past
177
+ them for a key or a provider:
191
178
 
192
- The package is built with release-size settings and a `wasm-opt -Oz` post-pass.
193
- Measured on the current alpha build:
179
+ - `TypedDataSignerCallback` signs an EIP-712 typed-data envelope.
180
+ - `Eip1193RequestCallback` answers EIP-1193 requests from an injected or hosted
181
+ provider.
182
+ - `DigestSignerCallback` — signs a raw digest for explicit EthSign flows.
183
+ - `CustomEip1271Callback` — returns a smart-account's final EIP-1271 signature.
184
+ - `ContractReadCallback` — performs a read-only `eth_call` and returns the
185
+ ABI-decoded value as a decimal string or number (e.g. viem's `readContract`
186
+ result via `String(value)`).
187
+ - `CowFetchCallback` — dispatches HTTP for Node, Workers, Deno, and custom hosts.
194
188
 
195
- | Flavor | Raw wasm | Brotli | Gzip | Gate |
196
- | --- | ---: | ---: | ---: | --- |
197
- | default | 1.63 MiB | 511 KiB | 689 KiB | 3.3 MiB raw / 900 KiB brotli |
198
- | orderbook | 1.03 MiB | 341 KiB | 447 KiB | 1.5 MiB raw / 500 KiB brotli |
199
- | signing | 0.31 MiB | 120 KiB | 142 KiB | 0.9 MiB raw / 300 KiB brotli |
200
- | trading | 1.54 MiB | 489 KiB | 657 KiB | 3.2 MiB raw / 850 KiB brotli / 3,000,000 B gzip (warn at 2,700,000 B) |
189
+ A callback may return a plain value, a Promise, or a thenable. Clients expose
190
+ `dispose()` and `[Symbol.dispose]` (so `using client = new …` works) and release
191
+ the callbacks they hold on disposal.
201
192
 
202
- The `trading` flavour emits one wasm binary shared across its bundler, nodejs, and
203
- web targets. Its web-target gzip-compressed artifact is below the current
204
- Cloudflare Workers Free compressed-size limit at the time of measurement.
205
- Full Workers support still requires release-bundle verification and Worker
206
- startup measurement; the release pipeline enforces the gzip byte budget on
207
- every build, but Wrangler deployment and `startup_time_ms` telemetry are
208
- separate operational gates.
193
+ ## Cancellation and timeouts
209
194
 
210
- Cloudflare Workers cold starts are runtime-sensitive. The package treats
211
- 300 ms as the warning threshold, 500 ms as the release gate, and 1 second as
212
- the platform-limit budget that Worker consumers should stay well below.
195
+ Every call accepts an optional `signal` (an `AbortSignal`) and `timeoutMs`.
196
+ Aborting the signal rejects the pending call with a `cancelled` `CowError`;
197
+ `timeoutMs` rejects with a `timeout` error. Both resolve the *awaited call* — an
198
+ already-dispatched HTTP request may keep running in the background until it
199
+ completes or the timeout elapses, so treat cancellation as "stop waiting," not a
200
+ guarantee that the network request is halted.
213
201
 
214
- ## Transport configuration
202
+ ## Transport
215
203
 
216
- Every client accepts one transport:
204
+ Every client takes one transport:
217
205
 
218
206
  ```ts
219
- transport: { kind: "fetch" }
220
- transport: { kind: "fetch", fetch: customFetch }
221
- transport: { kind: "callback", callback: customHttpCallback }
207
+ transport: { kind: "fetch" } // standards `fetch` (browser, Node, Workers)
208
+ transport: { kind: "fetch", fetch: customFetch } // a fetch you supply
209
+ transport: { kind: "callback", callback } // you own request dispatch
222
210
  ```
223
211
 
224
- Use `fetch` for browser, Node, and Worker runtimes that expose a standards
225
- compatible `fetch`. Use `callback` when the host must own request dispatch,
226
- fixtures, proxying, custom authentication, or observability.
212
+ Use `callback` when the host must own dispatch for fixtures, proxying, custom
213
+ authentication, or observability. Each client also takes optional
214
+ `transportPolicy` settings for retry, rate-limit, jitter, and user-agent behavior.
227
215
 
228
- Every client also accepts optional `transportPolicy` settings for retry,
229
- rate-limit, jitter, and user-agent behavior.
216
+ ## Errors
230
217
 
231
- ## Cancellation and timeouts
218
+ JavaScript-visible failures are a typed `CowError` discriminated union — transport,
219
+ app-data, signing, orderbook, subgraph, trading, wallet, cancellation, and
220
+ internal variants — with low-cardinality fields visible and URLs, headers, bodies,
221
+ and secret-shaped values redacted. The `orderbook` variant carries `retryable` and
222
+ an optional `retryAfterMs` parsed from the response `Retry-After`, mirroring the
223
+ native `OrderbookError::is_retryable` / `backoff_hint`, so a JavaScript retry loop
224
+ reaches the same verdict as the Rust one.
232
225
 
233
- Every call accepts an optional `signal` (an `AbortSignal`) and a per-call
234
- `timeoutMs`. Aborting the signal rejects the pending call promptly with a
235
- `cancelled` `CowError`; `timeoutMs` rejects with a `timeout` error. Both resolve
236
- the *awaited call* an already-dispatched HTTP request may keep running in the
237
- background until it completes or the timeout elapses, so treat cancellation as
238
- "stop waiting," not a guarantee that the network request is halted.
239
-
240
- ## Architecture
241
-
242
- The TypeScript facade is the public package contract. It:
243
-
244
- - exposes camelCase TypeScript APIs;
245
- - exposes `dispose()` and `[Symbol.dispose]` (so `using client = new …` works)
246
- while hiding the raw wasm-bindgen `free()` handle;
247
- - maps raw wasm errors into `CowError`;
248
- - adapts `transport: { kind: "fetch" }` into the callback HTTP ABI;
249
- - keeps wallet libraries outside the package behind named callback types.
250
-
251
- ## API reference
252
-
253
- The declaration snapshots under `crates/wasm/snapshots/facade/` show the
254
- public TypeScript surface for each flavor. Key exports include:
255
-
256
- - clients: `OrderBookClient`, `TradingClient`, `SubgraphClient`, `IpfsClient`;
257
- - signing helpers: `signOrderWithTypedDataSigner`, `signOrderWithEip1193`,
258
- `signOrderEthSignDigest`, `signOrderWithEip1271`,
259
- `signOrderWithCustomEip1271`;
260
- - cancellation helpers: `signCancellationWithTypedDataSigner`,
261
- `signCancellationWithEip1193`, `signCancellationEthSignDigest`,
262
- `buildCancelOrderTx`, `buildPresignTx`;
263
- - pure helpers: `domainSeparator`, `orderTypedData`, `computeOrderUid`,
264
- `deploymentAddresses`, `supportedChainIds`, `appDataInfo`,
265
- `validateAppDataDoc`, `appDataDoc`, `appDataHexToCid`,
266
- `cidToAppDataHex`, `wasmVersion`.
267
-
268
- ## When to use this package vs the upstream TypeScript SDK
269
-
270
- For most browser dapps, web apps, and CowSwap-style UIs, the upstream
271
- [`@cowprotocol/cow-sdk`](https://www.npmjs.com/package/@cowprotocol/cow-sdk)
272
- is the recommended choice; it is substantially smaller at equivalent feature
273
- subsets. This package is appropriate for specialized cases:
274
-
275
- - TypeScript services that need byte-for-byte parity with the Rust SDK's
276
- EIP-712 + EIP-1271 signing path.
277
- - Single-source-of-truth Rust + TypeScript embedding (one implementation
278
- across both runtimes).
279
- - Cloudflare Workers (size-compatible with the current Workers Free
280
- compressed-size limit at the time of measurement; the `trading` flavour's
281
- edge build is built and tested end-to-end in CI (Workers Vitest), within the
282
- Workers compressed-size budget).
283
- - Embeddable signing helpers (the `./signing` flavor is the smallest).
284
-
285
- The "When to use this SDK" table at the top of this README routes consumers
286
- by use case. The Quickstart sections above show the supported import shapes
287
- for the most common runtimes.
226
+ ## Bundle size
227
+
228
+ Built with release-size settings and a `wasm-opt -Oz` pass; measured on the
229
+ current alpha build (gzip is the compressed-transfer figure):
230
+
231
+ | Flavor | Raw wasm | Brotli | Gzip | Release gate |
232
+ | --- | ---: | ---: | ---: | --- |
233
+ | signing | 0.31 MiB | 120 KiB | 142 KiB | 0.9 MiB raw / 300 KiB brotli |
234
+ | orderbook | 1.02 MiB | 341 KiB | 447 KiB | 1.5 MiB raw / 500 KiB brotli |
235
+ | trading | 1.54 MiB | 490 KiB | 659 KiB | 3.2 MiB raw / 850 KiB brotli |
236
+ | default | 1.63 MiB | 513 KiB | 691 KiB | 3.3 MiB raw / 900 KiB brotli |
237
+
238
+ Each flavor emits one wasm binary shared across its bundler, Node, web, and
239
+ source-phase module targets — the web glue's default URL, the module glue's
240
+ `import source`, and the raw Worker module subpath all reuse the one bundler copy,
241
+ so a flavor's gzip figure above is its size on every runtime. Each flavor's gzip
242
+ size is enforced as a per-build byte budget within the current Cloudflare Workers
243
+ Free compressed-size limit. End-to-end Workers support also depends on
244
+ `wrangler deploy --dry-run` verification and a Worker startup-time gate, tracked
245
+ separately.
246
+
247
+ ## Not in this package
248
+
249
+ Use the upstream TypeScript SDK for these until they ship in `cow-rs`: TWAP and
250
+ composable orders, cross-chain bridging, CoW Shed account abstraction, flash-loan
251
+ helpers, and hardware-wallet adapters. This package emits typed data or
252
+ transaction requests and lets the caller's wallet submit on-chain; it ships no
253
+ WASI, WebAssembly-component, or `no_std` guest target.
254
+
255
+ ## More
256
+
257
+ - The public TypeScript surface for each flavor is the committed declaration
258
+ snapshot under `crates/wasm/snapshots/facade/`.
259
+ - [Architecture](https://github.com/0xSymbiome/cow-rs/blob/main/docs/architecture.md),
260
+ [Observability](https://github.com/0xSymbiome/cow-rs/blob/main/docs/observability.md),
261
+ and the
262
+ [WASM Surface Audit](https://github.com/0xSymbiome/cow-rs/blob/main/docs/audit/wasm-surface-audit.md).
263
+ - Runnable browser, Node, and Worker examples live in the
264
+ [`cow-sdk-examples`](https://github.com/0xSymbiome/cow-sdk-examples) repository.
265
+
266
+ Licensed under GPL-3.0-or-later.
@@ -52,4 +52,22 @@ export type Eip1193RequestCallback = (request: {
52
52
  export type DigestSignerCallback = (digest: string) => Promise<string> | string;
53
53
  export type CowEip1271SignCallback = (request: CowEip1271SignRequest) => Promise<string> | string;
54
54
  export type CustomEip1271Callback = CowEip1271SignCallback;
55
+ /**
56
+ * Performs a read-only contract call on behalf of the SDK and returns the
57
+ * ABI-decoded result.
58
+ *
59
+ * The callback must return the decoded value as a decimal string or number, not
60
+ * the raw `0x`-hex `eth_call` payload. With viem, pass the `readContract`
61
+ * result through `String(value)`:
62
+ *
63
+ * ```ts
64
+ * const readContract: ContractReadCallback = async ({ address, method, abiJson, argsJson }) =>
65
+ * String(await publicClient.readContract({
66
+ * address: address as `0x${string}`,
67
+ * abi: JSON.parse(abiJson),
68
+ * functionName: method,
69
+ * args: JSON.parse(argsJson)
70
+ * }));
71
+ * ```
72
+ */
55
73
  export type ContractReadCallback = (request: ContractCallDto) => Promise<string> | string;