ProjectsClient
ProjectsClient is the main entry point for interacting with the Inkd Protocol. It handles x402 payments automatically.
import { ProjectsClient } from "@inkd/sdk"
const client = new ProjectsClient({
privateKey: process.env.INKD_PRIVATE_KEY,
})Projects
createProject
Register a new project on-chain. Costs $0.10+ USDC (paid automatically via x402).
const project = await client.createProject({
name: "my-agent", // required, max 64 chars, globally unique
description: "My agent project", // optional, max 1024 chars
license: "MIT", // optional, SPDX identifier
isPublic: true, // optional, default true
isAgent: true, // optional, marks as AI agent
agentEndpoint: "https://...", // optional, agent HTTP endpoint
readmeHash: "ar://...", // optional, Arweave README hash
})
console.log(project.id) // "10"
console.log(project.txHash) // "0xabc..."{
id: string // on-chain project ID
name: string
owner: string // your wallet address
txHash: string
blockNumber: string
}Throws: NameTaken, NameTooLong, InsufficientFunds
getProject
const project = await client.getProject(10)
console.log(project.name) // "my-agent"
console.log(project.owner) // "0x..."
console.log(project.versionCount) // 2Returns: Full project object from the registry.
listProjects
const { data, total } = await client.listProjects({
offset: 0,
limit: 20,
})
for (const project of data) {
console.log(project.name, project.owner)
}getOwnerProjects
const projects = await client.getOwnerProjects("0xYourAddress")Versions
pushVersion
Upload content to Arweave and record it on-chain. Fee = Arweave cost + 20% markup (min $0.10 USDC).
// With local file — uploads to Arweave automatically
const version = await client.pushVersion({
projectId: 10,
file: "./dist/agent.js", // path or Buffer
versionTag: "v1.0.0",
changelog: "Initial release",
})
// With existing Arweave hash
const version = await client.pushVersion({
projectId: 10,
arweaveHash: "ar://QmAbc123...",
versionTag: "v1.0.0",
changelog: "Initial release",
})
console.log(version.arweaveHash) // "ar://QmAbc123..."
console.log(version.arweaveUrl) // "https://arweave.net/QmAbc123..."
console.log(version.txHash) // "0xdef..."{
projectId: string
versionIndex: string
versionTag: string
arweaveHash: string
arweaveUrl: string
txHash: string
blockNumber: string
}Throws: ProjectNotFound, NotOwnerOrCollaborator, EmptyArweaveHash, EmptyVersionTag
getVersion
const version = await client.getVersion(10, 0) // projectId, versionIndex
console.log(version.versionTag) // "v1.0.0"
console.log(version.arweaveHash) // "ar://QmAbc123..."
console.log(version.pushedBy) // "0x..."
console.log(version.pushedAt) // Unix timestamplistVersions
const { data } = await client.listVersions(10)
for (const version of data) {
console.log(`${version.versionTag} → ${version.arweaveHash}`)
}estimateVersionCost
Get the exact USDC fee for pushing a version before paying:
const estimate = await client.estimateVersionCost({ bytes: 102400 })
console.log(estimate.totalUsd) // "$0.0055"
console.log(estimate.total) // "5520" (USDC, 6 decimals)Collaborators
addCollaborator
Grant push access to another address. Owner only. Max 50 collaborators per project.
await client.addCollaborator({
projectId: 10,
collaborator: "0xCollaboratorAddress",
})removeCollaborator
await client.removeCollaborator({
projectId: 10,
collaborator: "0xCollaboratorAddress",
})isCollaborator
const isCollab = await client.isCollaborator(10, "0xAddress")
// true | falseContent
uploadContent
Upload a file to Arweave directly, without pushing a version. Returns an ar:// hash.
import { readFileSync } from "fs"
const result = await client.uploadContent({
data: readFileSync("./dist/agent.js"),
contentType: "application/javascript",
filename: "agent.js", // optional
})
console.log(result.hash) // "ar://QmAbc123..."
console.log(result.url) // "https://arweave.net/QmAbc123..."Full agent example
import { ProjectsClient } from "@inkd/sdk"
import { readFileSync } from "fs"
const client = new ProjectsClient({
privateKey: process.env.INKD_PRIVATE_KEY,
})
async function deploy() {
// Create project (idempotent in practice — catch NameTaken)
let projectId: string
try {
const project = await client.createProject({
name: "my-agent",
license: "MIT",
isAgent: true,
})
projectId = project.id
console.log(`Created project #${projectId}`)
} catch (err: any) {
if (err.code === "NameTaken") {
const existing = await client.getProject("my-agent")
projectId = existing.id
} else throw err
}
// Push version
const version = await client.pushVersion({
projectId: projectId,
file: "./dist/agent.js",
versionTag: `v${process.env.npm_package_version}`,
changelog: process.env.CHANGELOG ?? "",
})
console.log(`Pushed ${version.versionTag} → ${version.arweaveHash}`)
}
deploy().catch(console.error)Private Uploads
Store content end-to-end encrypted on Arweave. Only authorized wallets can decrypt.
// Upload encrypted — requires privateKey in config
const result = await client.pushPrivateVersion(projectId, {
content: fs.readFileSync("./model.bin"),
tag: "v1.0.0",
contentType: "application/octet-stream",
});
console.log(result.isPrivate); // true
console.log(result.contentHash); // ar:// of encrypted blob
console.log(result.metadataHash); // ar:// of access manifest (wrapped keys)
// Decrypt
const plaintext = await client.decryptVersion(
result.contentHash,
result.metadataHash
);See Private Uploads for the full security model.
