@seedprotocol/publish
v0.4.18
Published
Publish UI components and helpers for Seed Protocol
Readme
@seedprotocol/publish
Publish UI components and helpers for Seed Protocol.
The publish flow (ConnectButton, etc.) runs ensureEasSchemasForItem before getPublishPayload, which registers EAS schemas and adds naming attestations so EASSCAN displays them. If you build a custom publish flow that calls item.getPublishPayload() directly, you must run schema setup first or use this package's flow.
initPublish() or PublishProvider registers the revocation executor, so item.unpublish() works when the publish package is configured. See docs/ATTESTATION_REVOCATION.md for permanence and UX guidance.
Setup
Wrap your app with PublishProvider. The provider includes:
- Thirdweb's required context (React Query, connection manager)
- SeedProvider (React Query for Seed SDK hooks like
useItems,useModels,useSchemas)
You can optionally pass queryClient or queryClientRef to customize the Seed QueryClient.
thirdwebClientId and uploadApiBaseUrl are required in config. Other values (account factory, EAS contract) are defined as constants in the package.
Option A: Config via provider
import { PublishProvider, ConnectButton } from '@seedprotocol/publish'
function App() {
return (
<PublishProvider
config={{
thirdwebClientId: import.meta.env.VITE_THIRDWEB_CLIENT_ID,
uploadApiBaseUrl: import.meta.env.VITE_UPLOAD_API_BASE_URL,
}}
>
<ConnectButton />
</PublishProvider>
)
}Option B: Config via initPublish
import { PublishProvider, ConnectButton, initPublish } from '@seedprotocol/publish'
initPublish({
thirdwebClientId: import.meta.env.VITE_THIRDWEB_CLIENT_ID,
uploadApiBaseUrl: import.meta.env.VITE_UPLOAD_API_BASE_URL,
})
function App() {
return (
<PublishProvider>
<ConnectButton />
</PublishProvider>
)
}useIntegerLocalIds
When using the new contract that expects uint256 localIdIndex/publishLocalIdIndex instead of string localId/publishLocalId (gas-efficient), set useIntegerLocalIds: true:
<PublishProvider
config={{
thirdwebClientId: '...',
uploadApiBaseUrl: '...',
useIntegerLocalIds: true, // Use integer-based payload for new contract
}}
>
<App />
</PublishProvider>To revert to the old contract (string-based), set useIntegerLocalIds: false or omit the flag. No code changes required beyond config.
Experimental: Arweave bundler (instant uploads)
When using your own gateway with an Arweave bundler, you can enable instant uploads instead of the default reimbursement + chunk upload flow. This is experimental and not yet validated for production.
Set useArweaveBundler: true. The bundler uses the same uploadApiBaseUrl (e.g. ${uploadApiBaseUrl}/upload/batch).
<PublishProvider
config={{
thirdwebClientId: import.meta.env.VITE_THIRDWEB_CLIENT_ID,
uploadApiBaseUrl: import.meta.env.VITE_UPLOAD_API_BASE_URL,
useArweaveBundler: true,
}}
>
<App />
</PublishProvider>When using the bundler, you must provide a signer at publish time via PublishManager.createPublish options:
// Signer passed at publish time (recommended for apps where signer isn't available at startup)
PublishManager.createPublish(item, address, account, {
signDataItems: async (uploads) => {
// Sign with wallet (ArConnect, MetaMask, etc.)
return uploads.map((u) => ({ transaction: { id: '...' }, versionId: u.versionLocalId, modelName: u.itemPropertyName }))
},
})
// Or for backend/scripts with a private key:
PublishManager.createPublish(item, address, account, {
dataItemSigner: myArweaveSigner,
})You can also provide signDataItems or dataItemSigner in the PublishProvider config as a fallback when the signer is available at startup.
Development
bun install
bun run build