Skip to content

Commit 62b69fb

Browse files
authored
Merge branch 'master' into rvagg/extra-capabilities
2 parents 318a694 + d463939 commit 62b69fb

13 files changed

Lines changed: 147 additions & 45 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"packages/synapse-sdk": "0.40.0",
3-
"packages/synapse-core": "0.3.1",
2+
"packages/synapse-sdk": "0.40.1",
3+
"packages/synapse-core": "0.3.2",
44
"packages/synapse-react": "0.2.2"
55
}

.github/workflows/add-issues-and-prs-to-fs-project-board.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ on:
1515
issues:
1616
types:
1717
- opened
18-
pull_request:
18+
# Using "pull_request_target" instead of "pull_request" to support PRs from forks.
19+
# pull_request_target has access to secrets even for fork PRs, which is necessary
20+
# for this action to authenticate and add items to the project board.
21+
# pull_request_target runs the workflow file from the base branch (main),
22+
# not from the PR branch, so attackers cannot modify this workflow via PR.
23+
# This action does not check out nor execute user code so we should be safe.
24+
# We also hardcode to specific hash to ensure no unintended changes underneath us.
25+
pull_request_target:
1926
types:
2027
- opened
2128

@@ -24,7 +31,8 @@ jobs:
2431
name: Add all issues and prs to project
2532
runs-on: ubuntu-latest
2633
steps:
27-
- uses: actions/add-to-project@v1.0.2
34+
- uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2
35+
continue-on-error: true # Don't fail if item already exists in project. actions/add-to-project does not currently handle this case gracefully.
2836
with:
2937
project-url: https://github.com/orgs/FilOzone/projects/14
3038
github-token: ${{ secrets.FILOZZY_CI_ADD_TO_PROJECT }}

.github/workflows/release-please.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ jobs:
1919
- uses: googleapis/release-please-action@v4
2020
id: release
2121
with:
22-
# needs to be personal token so release PRs can run workflows
23-
token: ${{ secrets.GITHUB_TOKEN }}
22+
# PAT so release PRs trigger other workflows (auto-label, add-issues-and-prs-to-fs-project-board).
23+
# This PAT has the permissions outlined in https://github.com/googleapis/release-please-action?tab=readme-ov-file#workflow-permissions.
24+
# Using GITHUB_TOKEN suppresses follow-on workflow runs, which would mean release please PRs wouldn't get properly labeled and added to the project board.
25+
token: ${{ secrets.FILOZZY_RELEASE_PLEASE_PAT }}
2426
config-file: .github/release-please-config.json
2527
manifest-file: .github/release-please-manifest.json
2628
npm:

packages/synapse-core/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## [0.3.2](https://github.com/FilOzone/synapse-sdk/compare/synapse-core-v0.3.1...synapse-core-v0.3.2) (2026-03-30)
4+
5+
6+
### Bug Fixes
7+
8+
* **core:** fall back to Blob fetch body when ReadableStream not supported ([#681](https://github.com/FilOzone/synapse-sdk/issues/681)) ([6142cc4](https://github.com/FilOzone/synapse-sdk/commit/6142cc4fa119b2e830c9217979ed52e780f3c1b6))
9+
10+
11+
### Chores
12+
13+
* **abi:** update ABI for 1.2.0 filecoin-services release ([#688](https://github.com/FilOzone/synapse-sdk/issues/688)) ([0259413](https://github.com/FilOzone/synapse-sdk/commit/0259413b86dd31e09c7bbc5c0d2f93cf50daadd6))
14+
315
## [0.3.1](https://github.com/FilOzone/synapse-sdk/compare/synapse-core-v0.3.0...synapse-core-v0.3.1) (2026-03-17)
416

517

packages/synapse-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@filoz/synapse-core",
3-
"version": "0.3.1",
3+
"version": "0.3.2",
44
"description": "JavaScript Standard Library for Filecoin Onchain Cloud",
55
"repository": {
66
"type": "git",

packages/synapse-core/src/abis/generated.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,8 +3224,8 @@ export const filecoinWarmStorageServiceConfig = {
32243224
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32253225

32263226
/**
3227-
* - [__View Contract on Filecoin Mainnet Filfox__](https://filfox.info/en/address/0x638a4986332bF9B889E5D7435B966C5ecdE077Fa)
3228-
* - [__View Contract on Filecoin Calibration Filscan__](https://calibration.filscan.io/address/0x53d235D474585EC102ccaB7e0cdcE951dD00f716)
3227+
* - [__View Contract on Filecoin Mainnet Filfox__](https://filfox.info/en/address/0xB1B3A3d979c1f233c1021EF98dff9c0932FF1bb9)
3228+
* - [__View Contract on Filecoin Calibration Filscan__](https://calibration.filscan.io/address/0x537320bd004a7FDd3c1932ca64BD88268301322A)
32293229
*/
32303230
export const filecoinWarmStorageServiceStateViewAbi = [
32313231
{
@@ -3522,17 +3522,17 @@ export const filecoinWarmStorageServiceStateViewAbi = [
35223522
] as const
35233523

35243524
/**
3525-
* - [__View Contract on Filecoin Mainnet Filfox__](https://filfox.info/en/address/0x638a4986332bF9B889E5D7435B966C5ecdE077Fa)
3526-
* - [__View Contract on Filecoin Calibration Filscan__](https://calibration.filscan.io/address/0x53d235D474585EC102ccaB7e0cdcE951dD00f716)
3525+
* - [__View Contract on Filecoin Mainnet Filfox__](https://filfox.info/en/address/0xB1B3A3d979c1f233c1021EF98dff9c0932FF1bb9)
3526+
* - [__View Contract on Filecoin Calibration Filscan__](https://calibration.filscan.io/address/0x537320bd004a7FDd3c1932ca64BD88268301322A)
35273527
*/
35283528
export const filecoinWarmStorageServiceStateViewAddress = {
3529-
314: '0x638a4986332bF9B889E5D7435B966C5ecdE077Fa',
3530-
314159: '0x53d235D474585EC102ccaB7e0cdcE951dD00f716',
3529+
314: '0xB1B3A3d979c1f233c1021EF98dff9c0932FF1bb9',
3530+
314159: '0x537320bd004a7FDd3c1932ca64BD88268301322A',
35313531
} as const
35323532

35333533
/**
3534-
* - [__View Contract on Filecoin Mainnet Filfox__](https://filfox.info/en/address/0x638a4986332bF9B889E5D7435B966C5ecdE077Fa)
3535-
* - [__View Contract on Filecoin Calibration Filscan__](https://calibration.filscan.io/address/0x53d235D474585EC102ccaB7e0cdcE951dD00f716)
3534+
* - [__View Contract on Filecoin Mainnet Filfox__](https://filfox.info/en/address/0xB1B3A3d979c1f233c1021EF98dff9c0932FF1bb9)
3535+
* - [__View Contract on Filecoin Calibration Filscan__](https://calibration.filscan.io/address/0x537320bd004a7FDd3c1932ca64BD88268301322A)
35363536
*/
35373537
export const filecoinWarmStorageServiceStateViewConfig = {
35383538
address: filecoinWarmStorageServiceStateViewAddress,

packages/synapse-core/src/sp/sp.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { PieceCID } from '../piece/piece.ts'
1717
import * as Piece from '../piece/piece.ts'
1818
import type * as TypedData from '../typed-data/index.ts'
1919
import { RETRY_CONSTANTS, SIZE_CONSTANTS } from '../utils/constants.ts'
20-
import { isUint8Array } from '../utils/streams.ts'
20+
import { isUint8Array, supportsStreamingFetchBody } from '../utils/streams.ts'
2121

2222
export namespace createDataSet {
2323
/**
@@ -319,7 +319,7 @@ export async function uploadPieceStreaming(
319319
? new Blob([options.data as Uint8Array<ArrayBuffer>]).stream()
320320
: (options.data as ReadableStream) // ReadableStream types dont match between browsers and Node.js
321321

322-
const size = isUint8Array(options.data) ? options.data.length : options.size
322+
let size = isUint8Array(options.data) ? options.data.length : options.size
323323

324324
// Add size tracking and progress reporting
325325
let bytesUploaded = 0
@@ -363,19 +363,48 @@ export async function uploadPieceStreaming(
363363
? dataStream.pipeThrough(trackingStream).pipeThrough(pieceCidStream)
364364
: dataStream.pipeThrough(trackingStream)
365365

366-
// PUT /pdp/piece/uploads/{uuid} with streaming body
366+
// Determine fetch body: stream it directly when the environment supports
367+
// ReadableStream as a request body (Chrome, Node.js), otherwise drain the
368+
// pipeline into a Blob first (Firefox, Safari). Draining still runs the
369+
// full TransformStream chain so CommP calculation and progress tracking
370+
// both execute regardless of path.
371+
let fetchBody: ReadableStream | Blob
372+
let fetchOptions: Record<string, string> = {}
373+
374+
if (supportsStreamingFetchBody()) {
375+
fetchBody = bodyStream
376+
fetchOptions = { duplex: 'half' }
377+
} else {
378+
const chunks: Uint8Array[] = []
379+
let totalSize = 0
380+
const reader = bodyStream.getReader()
381+
for (;;) {
382+
const { done, value } = await reader.read()
383+
if (done) break
384+
chunks.push(value)
385+
totalSize += value.length
386+
}
387+
fetchBody = new Blob(chunks as BlobPart[])
388+
// Override Content-Length with the actual accumulated size since we now
389+
// know it precisely, even for ReadableStream inputs without a pre-set size
390+
if (size == null) {
391+
size = totalSize
392+
}
393+
}
394+
395+
// PUT /pdp/piece/uploads/{uuid}
367396
const headers: Record<string, string> = {
368397
'Content-Type': 'application/octet-stream',
369398
...(size != null ? { 'Content-Length': size.toString() } : {}),
370399
}
371400

372401
const uploadResponse = await request.put(new URL(`pdp/piece/uploads/${uploadUuid}`, options.serviceURL), {
373-
body: bodyStream,
402+
body: fetchBody,
374403
headers,
375404
timeout: false, // No timeout for streaming upload
376405
signal: options.signal,
377-
duplex: 'half', // Required for streaming request bodies
378-
} as Parameters<typeof request.put>[1] & { duplex: 'half' })
406+
...fetchOptions,
407+
} as Parameters<typeof request.put>[1] & { duplex?: 'half' })
379408

380409
if (uploadResponse.error) {
381410
if (HttpError.is(uploadResponse.error)) {

packages/synapse-core/src/utils/streams.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,38 @@ export async function* uint8ArrayToAsyncIterable(
121121
export function isUint8Array(value: unknown): value is Uint8Array {
122122
return value instanceof Uint8Array || (ArrayBuffer.isView(value) && value.constructor.name === 'Uint8Array')
123123
}
124+
125+
let _supportsStreamBody: boolean | undefined
126+
127+
/**
128+
* Detect whether the current environment supports ReadableStream as a fetch
129+
* request body. Firefox stringifies the stream to "[object ReadableStream]"
130+
* instead of consuming it, and Safari silently ignores the stream body and
131+
* the duplex option. This check catches both: a browser that stringifies will
132+
* set Content-Type to text/plain (string body), and one that ignores duplex
133+
* will fail the duplexAccessed gate. The try/catch handles any future browser
134+
* that throws on the Request constructor.
135+
*
136+
* Result is memoized after the first call.
137+
*
138+
* @see https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests
139+
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=1387483
140+
*/
141+
export function supportsStreamingFetchBody(): boolean {
142+
if (_supportsStreamBody !== undefined) return _supportsStreamBody
143+
try {
144+
let duplexAccessed = false
145+
const hasContentType = new Request('', {
146+
body: new ReadableStream(),
147+
method: 'POST',
148+
get duplex() {
149+
duplexAccessed = true
150+
return 'half'
151+
},
152+
} as RequestInit).headers.has('Content-Type')
153+
_supportsStreamBody = duplexAccessed && !hasContentType
154+
} catch {
155+
_supportsStreamBody = false
156+
}
157+
return _supportsStreamBody
158+
}

packages/synapse-sdk/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## [0.40.1](https://github.com/FilOzone/synapse-sdk/compare/synapse-sdk-v0.40.0...synapse-sdk-v0.40.1) (2026-03-30)
4+
5+
6+
### Bug Fixes
7+
8+
* installation instructions ([#692](https://github.com/FilOzone/synapse-sdk/issues/692)) ([966a389](https://github.com/FilOzone/synapse-sdk/commit/966a3898391435eaf581be23e23dfed88162020b))
9+
* **storage:** trim provider resolver & pass all erorrs through ([#702](https://github.com/FilOzone/synapse-sdk/issues/702)) ([02a0fc6](https://github.com/FilOzone/synapse-sdk/commit/02a0fc638f7ef00a5194601022e3f44fcd779ffd))
10+
311
## [0.40.0](https://github.com/FilOzone/synapse-sdk/compare/synapse-sdk-v0.39.0...synapse-sdk-v0.40.0) (2026-03-17)
412

513

packages/synapse-sdk/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ The SDK handles all the complexity of blockchain interactions, provider selectio
3333
## Installation
3434

3535
```bash
36-
pnpm install @filoz/synapse-sdk ethers
36+
pnpm install @filoz/synapse-sdk viem
3737
```
3838

39-
Note: `ethers` v6 is a peer dependency and must be installed separately.
39+
Note: `viem` is a peer dependency and must be installed separately.
4040

4141
## Docs
4242

0 commit comments

Comments
 (0)