Decentralized board and task coordination dApp on the Sui blockchain.
Current testnet package ID: 0xa8432da223503968a2c93317ca027aa49c222eeca2ea5cd56fb37a4139fe1452
cd app/syncflow
npm install
npm run dev # http://localhost:5173Production build (static output in app/syncflow/dist):
npm run buildSyncFlow is a full-stack decentralized project management system built on Sui. It includes Move smart contracts for on-chain task coordination and a TypeScript SDK for seamless frontend integration.
SyncFlow/
βββ move/syncflow/ # Sui Move smart contracts
β βββ sources/ # Contract source files
β β βββ board.move # Board management
β β βββ task.move # Task & subtask management
β β βββ models.move # Shared models & constants
β β βββ permissions.move # Authorization helpers
β βββ tests/ # Move test suite (28 tests)
β
βββ typescript/ # TypeScript SDK for frontend
β βββ src/
β β βββ client/ # SyncFlowClient for blockchain interaction
β β βββ hooks/ # React Query hooks
β β βββ types/ # TypeScript type definitions
β β βββ config/ # Configuration & constants
β β βββ utils/ # Utility functions
β β βββ contexts/ # React context providers
β β βββ services/ # Event listeners
β βββ package.json
β
βββ app/ # Frontend application (React)
board.move- Board storage, roles, and metadata managementtask.move- Tasks, subtasks, and participant logicmodels.move- Shared data structures and constantspermissions.move- Permission verification helpers
β
Role-based access control (Admin & Contributor roles)
β
Board creation and management
β
Task lifecycle management (ToDo β InProgress β Review β Done)
β
Task deletion (admin only)
β
Participant management
β
Invitations (add admin/contributor)
β
Event emission for all major actions
β
Comprehensive test suite (28 tests passing)
- Type-Safe: Full TypeScript definitions matching Move structs
- React Hooks: Ready-to-use hooks with React Query integration
- Transaction Builders: Easy transaction construction for all operations
- Event Listeners: Real-time contract event subscriptions
- Utilities: Formatters, validators, statistics helpers
- Board creator is automatically an admin
- Can add/remove other admins
- Can add/remove contributors
- Can create, edit, and delete tasks
- Can create, edit, and delete subtasks
- Can update board metadata
- Can manage participants
- Can create tasks
- Can edit tasks
- Can update task status
- Can create and edit subtasks
- Can manage participants
- Cannot delete tasks or subtasks
- Cannot manage board members
- Cannot change board metadata
struct Board has key {
id: UID,
name: String,
description: String,
owner: address,
admins: Table<address, bool>,
contributors: Table<address, bool>,
task_ids: vector<ID>,
created_at: u64,
updated_at: u64,
}struct Task has key {
id: UID,
board_id: ID,
name: String,
description: String,
status: u8, // 0=ToDo, 1=InProgress, 2=Review, 3=Done
participants: vector<address>,
created_by: address,
due_date: u64,
created_at: u64,
updated_at: u64,
subtasks: vector<ID>,
}struct Subtask has key {
id: UID,
task_id: ID,
name: String,
description: String,
completed: bool,
}- Sui CLI for smart contract deployment
- Node.js 18+ and npm for TypeScript/React development
cd move/syncflow
sui move build
sui move test # Verify all 28 tests pass
sui client publish --gas-budget 100000000Save the PACKAGE_ID from the deployment output.
cd typescript
npm install
# Create .env file
cp .env.example .env
# Update REACT_APP_PACKAGE_ID with your deployed package IDnpm run build # Compile TypeScript
npm run dev # Watch mode for development
npm test # Run testsimport { SyncFlowProvider } from './typescript/src';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<SyncFlowProvider packageId="YOUR_PACKAGE_ID">
<YourApp />
</SyncFlowProvider>
</QueryClientProvider>
);
}import { useBoard, useBoardTasks } from './typescript/src';
function BoardView({ boardId }: { boardId: string }) {
const { data: board, isLoading } = useBoard(boardId);
const { data: tasks } = useBoardTasks(boardId);
if (isLoading) return <div>Loading...</div>;
return (
<div>
<h1>{board?.name}</h1>
<p>{board?.description}</p>
<div>Tasks: {tasks?.length}</div>
</div>
);
}import {
useCreateTaskMutation,
useUpdateTaskStatusMutation
} from './typescript/src';
function TaskCreator({ boardId }: { boardId: string }) {
const createTask = useCreateTaskMutation();
const updateStatus = useUpdateTaskStatusMutation();
const handleCreate = async () => {
await createTask.mutateAsync({
boardId,
name: "New Task",
description: "Task description",
dueDate: Date.now() + 86400000, // 24 hours from now
});
};
const handleUpdateStatus = async (taskId: string) => {
await updateStatus.mutateAsync({
boardId,
taskId,
newStatus: 1, // InProgress
});
};
return <button onClick={handleCreate}>Create Task</button>;
}board::create_board(name, description, clock, ctx)board::update_board(board, new_name, new_description, clock, ctx)board::add_admin(board, user_address, clock, ctx)
board::remove_admin(board, user_address, clock, ctx)board::add_contributor(board, user_address, clock, ctx)
board::remove_contributor(board, user_address, clock, ctx)task::create_task(board, name, description, due_date, clock, ctx)task::update_task(board, task, name, description, due_date, clock, ctx)
task::update_task_status(board, task, new_status, clock, ctx)task::delete_task(board, task, clock, ctx)task::add_participant(board, task, user_address, clock, ctx)
task::remove_participant(board, task, user_address, clock, ctx)task::create_subtask(board, task, name, description, clock, ctx)task::update_subtask(board, subtask, name, description, clock, ctx)
task::toggle_subtask_status(board, subtask, clock, ctx)task::delete_subtask(board, task, subtask, clock, ctx)0- ToDo1- InProgress2- Review3- Done
- β Board creation
- β Board updates
- β Admin management
- β Contributor management
- β Permission enforcement
- β Owner protection (owner cannot be removed as admin)
- β Multiple admins and contributors
- β Task creation by admin
- β Task creation by contributor
- β Task updates
- β Status transitions
- β Task deletion (admin only)
- β Participant management
- β Subtask lifecycle
- β Subtask status toggling
- β Subtask deletion (admin only)
- β Permission enforcement
- β Complete task lifecycle (ToDo β InProgress β Review β Done)
The system emits events for all major operations:
BoardCreatedBoardUpdatedAdminAdded/AdminRemovedContributorAdded/ContributorRemovedTaskRegistered/TaskRemoved
TaskCreatedTaskUpdatedTaskStatusChangedTaskDeletedParticipantAdded/ParticipantRemoved
SubtaskCreatedSubtaskUpdatedSubtaskStatusToggledSubtaskDeleted
201- ENotAdmin: User is not an admin202- ECannotRemoveOwner: Cannot remove board owner as admin203- ETaskNotFound: Task ID not found in board
300- EInvalidStatus: Invalid task status value302- EParticipantNotFound: Participant not found in task303- ESubtaskNotFound: Subtask not found in task
100- ENotAdmin: User is not an admin101- ENotContributor: User is not a contributor102- ENotAuthorized: User is neither admin nor contributor
- Update
Move.tomlwith deployment addresses - Run
sui move buildsuccessfully - Run
sui move test- all 28 tests pass - Deploy with
sui client publish --gas-budget 100000000 - Save PACKAGE_ID from deployment
- Update
.envin typescript folder with PACKAGE_ID - Build TypeScript SDK with
npm run build - Verify no TypeScript compilation errors
cd move/syncflow
sui move testTest Results: All 28 tests passing
- 13 board management tests
- 15 task/subtask tests
cd typescript
npm testβ
Smart contracts complete and tested
β
TypeScript SDK complete and compiled
β
React hooks with React Query integration
β
Event listener service
β³ Frontend React app (in progress)
β³ Wallet integration (planned)
MIT
Contributions are welcome! Please ensure:
- All Move tests pass
- TypeScript compiles without errors
- Code follows existing patterns
- Add tests for new features
Built with β€οΈ on Sui