Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 65 additions & 33 deletions components/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { ethers } from "ethers";
import { useState, useCallback } from "react";
import { useAccount } from "wagmi";

import { Synapse } from "@filoz/synapse-sdk";
import { calculate as calculateCommP } from "@filoz/synapse-sdk/commp";
import { Synapse, CONTRACT_ADDRESSES, TOKENS } from "@filoz/synapse-sdk";
import { PandoraService } from "@filoz/synapse-sdk/pandora";

export function FileUploader() {
const [file, setFile] = useState<File | null>(null);
Expand All @@ -17,7 +17,7 @@ export function FileUploader() {
fileName: string;
fileSize: number;
commp: string;
txHash: string;
rootId?: number;
} | null>(null);

const handleDrag = useCallback((e: React.DragEvent) => {
Expand Down Expand Up @@ -62,44 +62,75 @@ export function FileUploader() {

// 2) Initialize ethers provider & signer
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
// (Note: Synapse.create({ provider }) will pick up the signer automatically)

// 3) Create Synapse instance
const synapse = await Synapse.create({ provider });
const balance = await synapse.payments.walletBalance();
console.log("FIL balance:", balance.toString());
const pandoraAddress = CONTRACT_ADDRESSES.PANDORA_SERVICE.calibration;
const synapse = await Synapse.create({
provider,
pandoraAddress,
});
const filBalance = await synapse.payments.walletBalance();
const usdfcBalance = await synapse.payments.walletBalance(TOKENS.USDFC);
console.log("FIL balance:", filBalance.toString());
console.log("USDFC balance:", usdfcBalance.toString());

// 4) Create (mock) StorageService
// Because the real StorageService is “pending,” this will return MockStorageService
// 4) Create StorageService using Synapse SDK v0.5
setStatus("Creating storage service...");
const storage = await synapse.createStorage({
storageProvider: "f01234", // replace with a valid provider ID or leave as mock
withCDN: false,
callbacks: {
onProviderSelected: (provider) => {
console.log("Selected storage provider:", provider.owner);
console.log("PDP URL:", provider.pdpUrl);
},
onProofSetResolved: (info) => {
if (info.isExisting) {
console.log("Using existing proof set:", info.proofSetId);
} else {
console.log("Created new proof set:", info.proofSetId);
}
},
onProofSetCreationStarted: (txHash) => {
console.log("Creating proof set, tx:", txHash);
},
},
});

// 5) Kick off upload (→ MockStorageService.upload under the hood)
setStatus("Uploading to mock storage service...");
const uploadTask = storage.upload(uint8ArrayBytes);

// 6) Wait for CommP calculation (mock)
const commp = await uploadTask.commp();
console.log("CommP (mock):", commp);
// 5) Run a preflight check
setStatus("Running preflight check...");
const preflight = await storage.preflightUpload(uint8ArrayBytes.length);

// 7) (Optional) If you want to display intermediate progress, you could do that here.
// But MockStorageService usually just resolves immediately.
setProgress(50);
setStatus("Finalizing upload...");
if (!preflight.allowanceCheck.sufficient) {
console.log("Insufficient allowances, preparing upload...");
const pandoraService = new PandoraService(provider, pandoraAddress);
const prep = await pandoraService.prepareStorageUpload(
{ dataSize: uint8ArrayBytes.length },
synapse.payments
);
for (const action of prep.actions) {
setStatus(action.description + "...");
await action.execute();
}
}

// 8) Wait for “chain commit” (mock)
const txHash = await uploadTask.done();
console.log("Mock txHash:", txHash);
// 6) Upload the file using the new API
setStatus("Uploading to storage provider...");
const result = await storage.upload(uint8ArrayBytes, {
onUploadComplete: (commp) => {
console.log("CommP:", commp);
},
onRootAdded: () => {
console.log("Root added to proof set");
}
});

setProgress(100);
setStatus("✅ File uploaded successfully (mock)!");
setStatus("✅ File uploaded successfully!");
setUploadedInfo({
fileName: file.name,
fileSize: file.size,
commp: commp.toLocaleString(),
txHash: txHash,
commp: result.commp,
rootId: result.rootId,
});
} catch (err: any) {
console.error(err);
Expand All @@ -122,7 +153,6 @@ export function FileUploader() {
return null;
}

console.log(uploadedInfo);
return (
<div className="w-full max-w-md">
<div
Expand Down Expand Up @@ -232,10 +262,12 @@ export function FileUploader() {
<span className="font-medium">CommP:</span>{" "}
{uploadedInfo.commp}
</div>
<div className="break-all">
<span className="font-medium">Tx Hash:</span>{" "}
{uploadedInfo.txHash}
</div>
{uploadedInfo.rootId != null && (
<div className="break-all">
<span className="font-medium">Root ID:</span>{" "}
{uploadedInfo.rootId}
</div>
)}
</div>
</div>
)}
Expand Down
3 changes: 3 additions & 0 deletions components/__tests__/FileUploader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ test('uploads file and shows success status', async () => {
await waitFor(() => {
expect(screen.getByText(/file uploaded successfully/i)).toBeInTheDocument();
});
await waitFor(() => {
expect(screen.getByText(/root id/i)).toBeInTheDocument();
});
});
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1',
'^@filoz/synapse-sdk$': '<rootDir>/test/__mocks__/synapse-sdk.js',
'^@filoz/synapse-sdk/pandora$': '<rootDir>/test/__mocks__/synapse-sdk.js',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy'
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts']
Expand Down
1 change: 1 addition & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import '@testing-library/jest-dom';
(global as any).__SYNAPSE_SDK_SKIP_DELAYS__ = true;
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "jest"
},
"dependencies": {
"@filoz/synapse-sdk": "^0.1.0",
"@filoz/synapse-sdk": "^0.5.0",
"@rainbow-me/rainbowkit": "^2.2.5",
"ethers": "^6.14.3",
"next": "15.3.2",
Expand Down
34 changes: 29 additions & 5 deletions test/__mocks__/synapse-sdk.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
module.exports = {
TOKENS: {
USDFC: 'USDFC',
FIL: 'FIL',
},
CONTRACT_ADDRESSES: {
PANDORA_SERVICE: {
calibration: '0xMockPandoraAddress',
},
},
PandoraService: class {
constructor() {}
prepareStorageUpload = jest.fn().mockResolvedValue({
estimatedCost: { perEpoch: 0n, perDay: 0n, perMonth: 0n },
allowanceCheck: { sufficient: true, message: '' },
actions: [],
});
},
Synapse: {
create: jest.fn(async () => ({
payments: { walletBalance: jest.fn().mockResolvedValue(BigInt(0)) },
createStorage: jest.fn().mockResolvedValue({
upload: jest.fn(() => ({
commp: jest.fn().mockResolvedValue('mock-commp'),
done: jest.fn().mockResolvedValue('0xmock')
}))
})
preflightUpload: jest.fn().mockResolvedValue({
estimatedCost: { perEpoch: 0n, perDay: 0n, perMonth: 0n },
allowanceCheck: { sufficient: true, message: '' },
selectedProvider: {},
selectedProofSetId: 1,
}),
upload: jest.fn(async (data, callbacks) => {
if (callbacks?.onUploadComplete) callbacks.onUploadComplete('mock-commp');
if (callbacks?.onRootAdded) callbacks.onRootAdded();
return { commp: 'mock-commp', size: data.length || 0, rootId: 1 };
}),
}),
})),
},
};