create-0g-app 1.0.0 → 1.0.2

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 (44) hide show
  1. package/dist/index.js +36 -39
  2. package/dist/index.js.map +1 -1
  3. package/dist/scaffold.d.ts +8 -0
  4. package/dist/scaffold.d.ts.map +1 -0
  5. package/dist/scaffold.js +229 -0
  6. package/dist/scaffold.js.map +1 -0
  7. package/package.json +9 -2
  8. package/templates/{storage → base}/_gitignore +0 -9
  9. package/templates/base/packages/web/app/layout.tsx +42 -0
  10. package/templates/{storage → base}/packages/web/components/Navbar.module.css +2 -34
  11. package/templates/{storage → base}/packages/web/components/Navbar.tsx +3 -15
  12. package/templates/{storage → base}/packages/web/lib/wagmi.ts +2 -2
  13. package/templates/{storage → base}/packages/web/next.config.ts +1 -12
  14. package/templates/compute/packages/web/app/api/compute/route.ts +91 -0
  15. package/templates/compute/packages/web/components/ComputeSection.module.css +84 -0
  16. package/templates/compute/packages/web/components/ComputeSection.tsx +102 -0
  17. package/templates/compute/packages/web/lib/0g-compute.ts +38 -0
  18. package/templates/contracts/packages/contracts/contracts/MyContract.sol +21 -0
  19. package/templates/{storage → contracts}/packages/contracts/hardhat.config.ts +11 -21
  20. package/templates/contracts/packages/contracts/scripts/deploy.ts +33 -0
  21. package/templates/storage/packages/web/app/api/download/[rootHash]/route.ts +34 -0
  22. package/templates/storage/packages/web/app/api/upload/route.ts +51 -0
  23. package/templates/storage/packages/web/components/StorageSection.module.css +80 -0
  24. package/templates/storage/packages/web/components/StorageSection.tsx +92 -0
  25. package/templates/storage/packages/web/lib/0g-storage.ts +16 -37
  26. package/templates/storage/scripts/patch-0g-sdk.js +139 -0
  27. package/templates/storage/README.md +0 -106
  28. package/templates/storage/package-lock.json +0 -15358
  29. package/templates/storage/package.json +0 -15
  30. package/templates/storage/packages/contracts/contracts/FileRegistry.sol +0 -49
  31. package/templates/storage/packages/contracts/scripts/deploy.ts +0 -43
  32. package/templates/storage/packages/web/.env.example +0 -12
  33. package/templates/storage/packages/web/app/layout.tsx +0 -25
  34. package/templates/storage/packages/web/app/page.module.css +0 -74
  35. package/templates/storage/packages/web/app/page.tsx +0 -29
  36. package/templates/storage/packages/web/app/storage/page.module.css +0 -110
  37. package/templates/storage/packages/web/app/storage/page.tsx +0 -167
  38. package/templates/storage/packages/web/lib/abi.ts +0 -48
  39. package/templates/storage/packages/web/next-env.d.ts +0 -6
  40. package/templates/storage/packages/web/package.json +0 -26
  41. /package/templates/{storage → base}/packages/web/app/globals.css +0 -0
  42. /package/templates/{storage → base}/packages/web/app/providers.tsx +0 -0
  43. /package/templates/{storage → base}/packages/web/tsconfig.json +0 -0
  44. /package/templates/{storage → contracts}/packages/contracts/package.json +0 -0
@@ -1,40 +1,19 @@
1
- import { Indexer, ZgFile } from "@0glabs/0g-ts-sdk";
2
- import { ethers } from "ethers";
3
-
4
- const INDEXER_URL =
5
- process.env.NEXT_PUBLIC_STORAGE_INDEXER ?? "https://indexer-storage-testnet-standard.0g.ai";
6
-
7
- /**
8
- * Upload a file to 0G decentralized storage.
9
- * Returns the content ID (merkle root) that can be used to retrieve the file later.
10
- */
11
- export async function uploadFile(
12
- file: File,
13
- signer: ethers.Signer
14
- ): Promise<{ contentId: string }> {
15
- const zgFile = await ZgFile.fromNodeFileBuffer(
16
- Buffer.from(await file.arrayBuffer()),
17
- file.name
18
- );
19
-
20
- const [tree, treeErr] = await zgFile.merkleTree();
21
- if (treeErr || !tree) throw new Error(`Failed to build merkle tree: ${treeErr}`);
22
-
23
- const contentId = tree.rootHash();
24
-
25
- const indexer = new Indexer(INDEXER_URL);
26
- const [, uploadErr] = await indexer.upload(zgFile, 0, signer);
27
- if (uploadErr) throw new Error(`Upload failed: ${uploadErr}`);
28
-
29
- return { contentId };
1
+ export async function uploadFile(file: File): Promise<{ rootHash: string; txHash: string }> {
2
+ const form = new FormData();
3
+ form.append("file", file);
4
+ const res = await fetch("/api/upload", { method: "POST", body: form });
5
+ if (!res.ok) throw new Error(await res.text());
6
+ return res.json();
30
7
  }
31
8
 
32
- /**
33
- * Download a file from 0G decentralized storage by its content ID.
34
- * Returns a Blob that can be turned into an object URL for display/download.
35
- */
36
- export async function downloadFile(contentId: string): Promise<Blob> {
37
- const indexer = new Indexer(INDEXER_URL);
38
- const buffer = await indexer.download(contentId);
39
- return new Blob([buffer]);
9
+ export async function downloadFile(rootHash: string, filename?: string): Promise<void> {
10
+ const res = await fetch(`/api/download/${rootHash}`);
11
+ if (!res.ok) throw new Error(await res.text());
12
+ const blob = await res.blob();
13
+ const url = URL.createObjectURL(blob);
14
+ const a = document.createElement("a");
15
+ a.href = url;
16
+ a.download = filename ?? rootHash;
17
+ a.click();
18
+ URL.revokeObjectURL(url);
40
19
  }
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Patches @0glabs/0g-ts-sdk to match the current 0G testnet contract ABI.
4
+ *
5
+ * The Submission struct was updated on-chain to add an `address submitter` field,
6
+ * changing the submit() selector from 0xef3e12dc → 0xbc8c11f8.
7
+ * The npm package (v0.3.3) still ships the old ABI, so we patch it here.
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const SDK = '@0glabs/0g-ts-sdk';
14
+
15
+ function findSdkRoot() {
16
+ const candidates = [
17
+ path.join(__dirname, '..', 'node_modules', SDK),
18
+ path.join(__dirname, '..', 'packages', 'web', 'node_modules', SDK),
19
+ ];
20
+ for (const p of candidates) {
21
+ if (fs.existsSync(p)) return p;
22
+ }
23
+ return null;
24
+ }
25
+
26
+ const OLD_SUBMIT_ABI = ` components: [
27
+ {
28
+ internalType: "uint256",
29
+ name: "length",
30
+ type: "uint256",
31
+ },
32
+ {
33
+ internalType: "bytes",
34
+ name: "tags",
35
+ type: "bytes",
36
+ },
37
+ {
38
+ components: [
39
+ {
40
+ internalType: "bytes32",
41
+ name: "root",
42
+ type: "bytes32",
43
+ },
44
+ {
45
+ internalType: "uint256",
46
+ name: "height",
47
+ type: "uint256",
48
+ },
49
+ ],
50
+ internalType: "struct SubmissionNode[]",
51
+ name: "nodes",
52
+ type: "tuple[]",
53
+ },
54
+ ],
55
+ internalType: "struct Submission",
56
+ name: "submission",
57
+ type: "tuple",`;
58
+
59
+ const NEW_SUBMIT_ABI = ` components: [
60
+ {
61
+ components: [
62
+ {
63
+ internalType: "uint256",
64
+ name: "length",
65
+ type: "uint256",
66
+ },
67
+ {
68
+ internalType: "bytes",
69
+ name: "tags",
70
+ type: "bytes",
71
+ },
72
+ {
73
+ components: [
74
+ {
75
+ internalType: "bytes32",
76
+ name: "root",
77
+ type: "bytes32",
78
+ },
79
+ {
80
+ internalType: "uint256",
81
+ name: "height",
82
+ type: "uint256",
83
+ },
84
+ ],
85
+ internalType: "struct SubmissionNode[]",
86
+ name: "nodes",
87
+ type: "tuple[]",
88
+ },
89
+ ],
90
+ internalType: "struct SubmissionData",
91
+ name: "data",
92
+ type: "tuple",
93
+ },
94
+ {
95
+ internalType: "address",
96
+ name: "submitter",
97
+ type: "address",
98
+ },
99
+ ],
100
+ internalType: "struct Submission",
101
+ name: "submission",
102
+ type: "tuple",`;
103
+
104
+ const OLD_UPLOADER_LINE = `[submission], txOpts, retryOpts)`;
105
+ const NEW_UPLOADER_LINE = `[{ data: submission, submitter: await this.flow.runner.getAddress() }], txOpts, retryOpts)`;
106
+
107
+ function patchFile(filePath, oldStr, newStr, label) {
108
+ if (!fs.existsSync(filePath)) return;
109
+ const content = fs.readFileSync(filePath, 'utf8');
110
+ if (!content.includes(oldStr)) {
111
+ console.log(` skip (already patched): ${label}`);
112
+ return;
113
+ }
114
+ fs.writeFileSync(filePath, content.replace(oldStr, newStr));
115
+ console.log(` patched: ${label}`);
116
+ }
117
+
118
+ const sdkRoot = findSdkRoot();
119
+ if (!sdkRoot) {
120
+ console.log('patch-0g-sdk: SDK not found, skipping.');
121
+ process.exit(0);
122
+ }
123
+
124
+ console.log(`patch-0g-sdk: found SDK at ${sdkRoot}`);
125
+
126
+ for (const variant of ['lib.esm', 'lib.commonjs']) {
127
+ patchFile(
128
+ path.join(sdkRoot, variant, 'contracts', 'flow', 'factories', 'FixedPriceFlow__factory.js'),
129
+ OLD_SUBMIT_ABI, NEW_SUBMIT_ABI,
130
+ `${variant}/FixedPriceFlow__factory.js`
131
+ );
132
+ patchFile(
133
+ path.join(sdkRoot, variant, 'transfer', 'Uploader.js'),
134
+ OLD_UPLOADER_LINE, NEW_UPLOADER_LINE,
135
+ `${variant}/Uploader.js`
136
+ );
137
+ }
138
+
139
+ console.log('patch-0g-sdk: done.');
@@ -1,106 +0,0 @@
1
- # 0G Storage App
2
-
3
- A decentralized file registry built on the [0G network](https://0g.ai).
4
-
5
- - **Files** are stored on 0G's decentralized storage network via `@0glabs/0g-ts-sdk`
6
- - **Provenance** (who uploaded what, and when) is recorded on-chain via `FileRegistry.sol`
7
- - **Frontend** is a Next.js 15 app with wagmi wallet connect
8
-
9
- ## Quick Start
10
-
11
- ### 1. Install dependencies
12
-
13
- ```bash
14
- npm install
15
- ```
16
-
17
- ### 2. Configure environment
18
-
19
- ```bash
20
- cp packages/web/.env.example packages/web/.env.local
21
- ```
22
-
23
- Edit `packages/web/.env.local` and add your private key:
24
-
25
- ```env
26
- PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
27
- ```
28
-
29
- > Get testnet OG tokens from the [0G faucet](https://faucet.0g.ai) if your wallet is empty.
30
-
31
- ### 3. Start the dev server (no deploy needed)
32
-
33
- ```bash
34
- npm run dev
35
- ```
36
-
37
- Open [http://localhost:3000](http://localhost:3000). You can browse the UI, but uploads need the contract deployed first.
38
-
39
- ### 4. Deploy the contract to Galileo testnet
40
-
41
- ```bash
42
- npm run deploy
43
- ```
44
-
45
- This will:
46
- 1. Compile `FileRegistry.sol`
47
- 2. Deploy it to the 0G Galileo testnet (chain ID 16601)
48
- 3. Automatically write the contract address to `packages/web/.env.local`
49
-
50
- Restart the dev server after deploying to pick up the new address.
51
-
52
- ### 5. Verify the contract (optional)
53
-
54
- ```bash
55
- npm run verify
56
- ```
57
-
58
- View your contract on the [0G Galileo explorer](https://chainscan-galileo.0g.ai).
59
-
60
- ## Project Structure
61
-
62
- ```
63
- ├── packages/
64
- │ ├── contracts/ Solidity + Hardhat
65
- │ │ ├── contracts/
66
- │ │ │ └── FileRegistry.sol
67
- │ │ ├── scripts/
68
- │ │ │ └── deploy.ts
69
- │ │ └── hardhat.config.ts
70
- │ └── web/ Next.js frontend
71
- │ ├── app/
72
- │ ├── lib/
73
- │ │ ├── 0g-storage.ts 0G SDK wrapper
74
- │ │ ├── abi.ts FileRegistry ABI
75
- │ │ └── wagmi.ts Wallet config
76
- │ └── .env.example
77
- └── README.md
78
- ```
79
-
80
- ## How It Works
81
-
82
- 1. User connects their wallet (MetaMask or any injected wallet)
83
- 2. User drops a file onto the upload zone
84
- 3. The file is uploaded to 0G storage via the indexer — a content ID (merkle root) is returned
85
- 4. The content ID is written on-chain to `FileRegistry.sol` via `registerFile()`
86
- 5. The file gallery reads all content IDs from the contract for the connected wallet
87
- 6. Clicking "Download" fetches the file from 0G storage by content ID
88
-
89
- ## Troubleshooting
90
-
91
- **"No contract deployed yet" warning**
92
- Run `npm run deploy` and restart the dev server.
93
-
94
- **Transaction fails / insufficient funds**
95
- Get testnet OG tokens from [https://faucet.0g.ai](https://faucet.0g.ai).
96
-
97
- **Upload hangs**
98
- The 0G storage indexer may be temporarily unavailable. Check [https://docs.0g.ai](https://docs.0g.ai) for status.
99
-
100
- **Wrong network in MetaMask**
101
- Add the 0G Galileo testnet manually:
102
- - Network name: 0G Galileo Testnet
103
- - RPC URL: https://evmrpc-test.0g.ai
104
- - Chain ID: 16601
105
- - Currency: OG
106
- - Explorer: https://chainscan-galileo.0g.ai