Skip to content

Commit dcd62d7

Browse files
authored
Merge pull request #729 from EdgeApp/jon/nym-mixfetch-v2
Upgrade NYM mix-fetch to v2
2 parents dab7afd + 816be23 commit dcd62d7

7 files changed

Lines changed: 41 additions & 71 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- changed: Upgrade `@nymproject/mix-fetch` to v2, which routes NYM mixnet traffic through the new smolmix-wasm tunnel (`@nymproject/mix-tunnel`). The v2 wasm + worker are inlined into the bundle, so the build no longer copies sibling `.wasm`/`web-worker-*.js` assets.
6+
57
## 2.46.1 (2026-06-29)
68

79
- changed: Upgrade yaob to v0.4.0 to share a single bridge instance with currency plugins (mismatched yaob copies give the bridge separate object-id counters that cross-wire bridged nativeIo objects).

package-lock.json

Lines changed: 14 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"*.{js,jsx,ts,tsx}": "eslint"
7979
},
8080
"dependencies": {
81-
"@nymproject/mix-fetch": "^1.4.4",
81+
"@nymproject/mix-fetch": "^2.0.0",
8282
"aes-js": "^3.1.0",
8383
"base-x": "^4.0.1",
8484
"biggystring": "^4.2.3",

src/io/browser/browser-io.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { makeLocalStorageDisklet } from 'disklet'
33
import { LogBackend, makeLog } from '../../core/log/log'
44
import { EdgeFetchOptions, EdgeFetchResponse, EdgeIo } from '../../types/types'
55
import { scrypt } from '../../util/crypto/scrypt'
6-
import { initMixFetch, mixFetchOptions } from '../../util/nym'
6+
import { initMixFetch } from '../../util/nym'
77
import { fetchCorsProxy } from './fetch-cors-proxy'
88

99
// Only try CORS proxy/bridge techniques up to 5 times
@@ -50,14 +50,7 @@ export function makeBrowserIo(logBackend: LogBackend): EdgeIo {
5050

5151
if (privacy === 'nym') {
5252
const nymFetch = await initMixFetch(log)
53-
return await nymFetch(
54-
uri,
55-
{
56-
...opts,
57-
mode: 'unsafe-ignore-cors' as RequestMode
58-
},
59-
mixFetchOptions
60-
)
53+
return await nymFetch(uri, opts)
6154
}
6255
if (corsBypass === 'always') {
6356
return await fetchCorsProxy(uri, opts)

src/io/react-native/react-native-worker.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
EdgeFetchResponse,
1818
EdgeIo
1919
} from '../../types/types'
20-
import { initMixFetch, mixFetchOptions } from '../../util/nym'
20+
import { initMixFetch } from '../../util/nym'
2121
import { hideProperties } from '../hidden-properties'
2222
import { makeNativeBridge } from './native-bridge'
2323
import { WorkerApi, YAOB_THROTTLE_MS } from './react-native-types'
@@ -177,15 +177,7 @@ async function makeIo(logBackend: LogBackend): Promise<EdgeIo> {
177177

178178
if (privacy === 'nym') {
179179
const nymFetch = await initMixFetch(log)
180-
const response = await nymFetch(
181-
uri,
182-
{
183-
...opts,
184-
mode: 'unsafe-ignore-cors' as RequestMode
185-
},
186-
mixFetchOptions
187-
)
188-
return response
180+
return await nymFetch(uri, opts)
189181
}
190182
if (corsBypass === 'always') {
191183
return await nativeFetch(uri, opts)

src/util/nym.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,53 @@
11
import {
22
createMixFetch,
3-
disconnectMixFetch,
4-
IMixFetch,
5-
IMixFetchFn,
6-
SetupMixFetchOps
3+
disconnectMixTunnel,
4+
SetupMixTunnelOpts
75
} from '@nymproject/mix-fetch'
86

97
import { EdgeLog } from '../types/types'
108

9+
/** The fetch-bound function `createMixFetch` resolves to. */
10+
type MixFetchFn = (url: string, init?: RequestInit) => Promise<Response>
11+
1112
/**
12-
* Configuration options for the NYM mixFetch client.
13+
* Configuration options for the NYM mixFetch tunnel.
1314
*/
14-
export const mixFetchOptions: SetupMixFetchOps = {
15+
export const mixFetchOptions: SetupMixTunnelOpts = {
1516
clientId: 'edge-core-js-2026-03-10',
16-
preferredGateway: '5rXcNe2a44vXisK3uqLHCzpzvEwcnsijDMU7hg4fcYk8', // with WSS
17-
preferredNetworkRequester:
18-
'5x6q9UfVHs5AohKMUqeivj7a556kVVy7QwoKige8xHxh.6CFoB3kJaDbYz6oafPJxNxNjzahpT2NtgtytcSyN9EvF@5rXcNe2a44vXisK3uqLHCzpzvEwcnsijDMU7hg4fcYk8',
1917
forceTls: true, // force WSS
20-
mixFetchOverride: {
21-
requestTimeoutMs: 300000
22-
}
18+
// Mixnet round trips are slow, so give the tunnel handshake plenty of time.
19+
// v1 tuned a 5 min `requestTimeoutMs`; v2 exposes no per-request timeout, but
20+
// the tunnel setup is where mixnet latency bites, so restore that 5 min
21+
// budget here to avoid premature failures during the handshake.
22+
connectTimeoutMs: 300000
2323
}
2424

2525
// MixFetch initialization state
26-
let mixFetchInitPromise: Promise<IMixFetch> | null = null
26+
let mixFetchInitPromise: Promise<MixFetchFn> | null = null
2727

2828
/**
2929
* Initialize the NYM mixFetch client. Must be called before using mixFetch.
3030
* Safe to call multiple times - subsequent calls return the same promise.
3131
*/
32-
export async function initMixFetch(log: EdgeLog): Promise<IMixFetchFn> {
32+
export async function initMixFetch(log: EdgeLog): Promise<MixFetchFn> {
3333
if (mixFetchInitPromise == null) {
3434
log('Initializing mixFetch...')
3535
mixFetchInitPromise = createMixFetch(mixFetchOptions)
36-
.then(mixFetchModule => {
36+
.then(mixFetch => {
3737
log('mixFetch initialized successfully')
38-
return mixFetchModule
38+
return mixFetch
3939
})
4040
.catch(async error => {
41-
// Clean up stale global state left by the failed init so the
42-
// next createMixFetch call starts fresh instead of reusing a
41+
// Tear down any partially-established tunnel left by the failed init
42+
// so the next createMixFetch call starts fresh instead of reusing a
4343
// broken singleton.
4444
try {
45-
await disconnectMixFetch()
45+
await disconnectMixTunnel()
4646
} catch {}
47-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
48-
delete (window as any).__mixFetchGlobal
4947
mixFetchInitPromise = null
5048
log.error('mixFetch initialization failed:', error)
5149
throw error
5250
})
5351
}
54-
const mixFetchModule = await mixFetchInitPromise
55-
return mixFetchModule.mixFetch
52+
return await mixFetchInitPromise
5653
}

webpack.config.js

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ module.exports = {
5050
static: bundlePath
5151
},
5252
entry: './src/io/react-native/react-native-worker.ts',
53-
experiments: {
54-
asyncWebAssembly: true
55-
},
5653
mode: debug ? 'development' : 'production',
5754
module: {
5855
rules: [
@@ -75,10 +72,6 @@ module.exports = {
7572
loader: 'babel-loader',
7673
options: { presets: ['@babel/preset-env'] }
7774
}
78-
},
79-
{
80-
test: /\.wasm$/,
81-
type: 'webassembly/async'
8275
}
8376
]
8477
},
@@ -92,29 +85,12 @@ module.exports = {
9285
plugins: [
9386
new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }),
9487
new webpack.ProvidePlugin({ process: ['process'] }),
95-
// Copy static files and mix-fetch WASM/worker files
9688
new CopyPlugin({
9789
patterns: [
9890
// HTML entry point
9991
{
10092
from: path.resolve(__dirname, 'src/index.html'),
10193
to: 'index.html'
102-
},
103-
// mix-fetch WASM files for NYM mixnet support
104-
{
105-
from: path.resolve(
106-
__dirname,
107-
'node_modules/@nymproject/mix-fetch/*.wasm'
108-
),
109-
to: '[name][ext]'
110-
},
111-
// mix-fetch web worker files
112-
{
113-
from: path.resolve(
114-
__dirname,
115-
'node_modules/@nymproject/mix-fetch/web-worker-*.js'
116-
),
117-
to: '[name][ext]'
11894
}
11995
]
12096
})

0 commit comments

Comments
 (0)