Concepts
One-signature uploads
A 30-block upload needs 30 store extrinsics. PotDrive asks your wallet once.
The problem
Each block must be its own store extrinsic (see why). A browser wallet pops up once per signature. Forty prompts for a small website is not a product.
The flow
- Prepare. The browser chunks, hashes and builds the DAG. No network, no keys.
- Estimate. One state read finds blocks Portaldot already holds. Two
paymentInfocalls give the linear fee model. The budget is the fees for new blocks plus 15%, two sweep fees and two existential deposits. - Authorize. PotDrive generates an sr25519 key from a fresh mnemonic, in memory. Your wallet signs one
utility.batchAll:balances.transferKeepAlive(uploadKey, budget), plusrevive.call(registry, register(…))if the registry is deployed. Ownership is recorded under your account, not the key's. - Store. The upload key sends one
storeper new block. It pre-assigns nonces and keeps four in flight, and reports each block's inclusion block and transaction index from theStoredevent. - Verify. PotDrive fetches the root back with
bitswap_v1_getand re-hashes it. - Sweep. The key sends its entire remaining balance back with
balances.transferAll.

Safety of the upload key
Blast radius
The key only ever holds the budget for this upload, and only until the sweep a few blocks later. It has no proxy rights and no registry rights. It is a funded throwaway.
Closed tabs
Before funding, the mnemonic is written to localStorage with the owner and root. If the tab closes mid-upload, the Drive finds it next time and offers to return the balance. Blocks already stored stay on chain, and re-uploading the same file skips them because they dedupe.
recover
import { recoverSession } from "@potdrive/sdk";
await recoverSession(api, mnemonic, ownerAddress); // transferAll back to the ownerProgress events
| Event | When |
|---|---|
estimate | Fees, reused and new bytes, budget, total. |
session | The upload key's address, before funding. |
authorized | The single wallet transaction is in a block. |
block | Every status change of every block: queued, skipped, sent, inBlock, finalized, failed. |
verified | The root came back over bitswap and matched its hash. |
swept | Unspent budget returned. |
done | The result: root CID, private key if any, block placements. |