Skip to main content
Before diving into advanced SDK usage, it’s important to understand a few key concepts and patterns central to Sage Protocol and its SDK. This section covers essential architectural and usage details to ensure a smooth integration process.

Application Isolation and Context (appId)

Sage Protocol isolates content and interactions per application by using a unique identifier (appId). Each application maintains distinct channels and posts, while user identities and social graphs remain global across all Sage-compatible apps. What this means for you:
  • Users have a single, global identity and consistent social relationships everywhere.
  • Each application provides tailored content and distinct community interactions..
Example React Integration using appId:
import { SageProvider } from '@sageprotocol/sdk/react';

const App = () => (
  <SageProvider
    appId="0x123..."                    // Your application's unique identifier
    channelRegistryId="0x456..."        // Registry managing channels specific to your app
    network="testnet"                   // 'mainnet' or 'testnet'
  >
    {/* Your app components */}
  </SageProvider>
);

export default App;
import { SageClient } from '@sageprotocol/sdk';

const sageClient = new SageClient({
  appId: '0x123...',                    // Your application's unique identifier
  channelRegistryId: '0x456...',        // Registry managing channels specific to your app
  network: 'testnet'                    // 'mainnet' or 'testnet'
});

await sageClient.initialize();
This structure demonstrates how applications utilize distinct contexts (appId) to maintain content isolation while benefiting from universal user identities.

Invite-Based User Creation (Temporary)

Currently, Sage Protocol requires invite codes and keys for user creation. This temporary mechanism allows applications to control growth and maintain initial engagement quality.
  • Invite Code: Unique code authorizing user creation.
  • Invite Key: Secure key accompanying the invite code.
(Note: Future protocol versions will make invite codes optional.) Example React Hook for Creating Users with Invites:
import { useUser } from '@sageprotocol/sdk/react';
import { useWallet } from '@suiet/wallet-kit';

function CreateUser() {
  const { create } = useUser();
  const { account, signAndExecuteTransaction } = useWallet();

  const handleCreateUser = async () => {
    const result = await create({
      amounts: [0, 0],
      avatar: 0,
      banner: 0,
      description: "Web3 enthusiast",
      inviteCode: "your-invite-code",
      inviteKey: "your-invite-key",
      name: "john-doe",
      self: account.address,
    });

    if (result.ok) {
      await signAndExecuteTransaction({ transaction: result.transaction });
      console.log("User successfully created!");
    } else {
      console.error(result.err);
    }
  };

  return <button onClick={handleCreateUser}>Create User</button>;
}

export default CreateUser;
const result = await sageClient.createUser({
  amounts: [0, 0],                            // required default amounts
  avatar: 0,                                  // optional avatar blob ID (default: 0)
  banner: 0,                                  // optional banner blob ID (default: 0)
  description: "Web3 enthusiast",             // profile description (markdown supported)
  inviteCode: "your-invite-code",             // required invite code
  inviteKey: "your-invite-key",               // required invite key
  name: "john-doe",                           // globally unique username
  self: walletAddress                         // user's wallet address
});

if (result.ok) {
  await signAndExecuteTransaction({ transaction: result.transaction });
  console.log("User successfully created!");
} else {
  console.error(result.err);
}

Transaction Patterns

Sage SDK operations involving blockchain transactions follow a two-step pattern:
  1. Construct Transaction: SDK methods return transaction objects to be signed.
  2. Sign and Execute Transaction: Your React app securely handles wallet interactions for transaction execution.
Example transaction workflow in React:
import { useUser } from '@sageprotocol/sdk/react';
import { useWallet } from '@suiet/wallet-kit';

const UserActionComponent = () => {
  const { create } = useUser();
  const { account, signAndExecuteTransaction } = useWallet();

  const handleAction = async () => {
    const result = await create({ /* parameters */ });

    if (result.ok) {
      await signAndExecuteTransaction({ transaction: result.transaction });
      console.log("Transaction executed successfully!");
    } else {
      console.error(result.err);
    }
  };

  return <button onClick={handleAction}>Perform Action</button>;
};

export default UserActionComponent;
const result = await sageClient.someAction({ /* parameters */ });

if (result.ok) {
  await signAndExecuteTransaction({ transaction: result.transaction });
  console.log("Transaction executed successfully!");
} else {
  console.error(result.err);
}
Replace someAction with the specific method name you’re invoking from sageClient. This accurately represents the direct JavaScript integration pattern documented in your SDK.
This approach ensures secure, transparent blockchain interactions.

Error Handling

The Sage SDK consistently provides structured results indicating success or errors. Every SDK call returns an object with:
  • ok: Boolean indicating success (true) or failure (false).
  • err: Error details if the call fails.
Recommended React Error Handling Pattern:
const result = await create({ /* parameters */ });

if (result.ok) {
  await signAndExecuteTransaction({ transaction: result.transaction });
  console.log("Success!");
} else {
  console.error("Error:", result.err);
}
Always verify transactions by checking the ok property before proceeding.

Event Monitoring and Querying

The Sage SDK provides explicit event-monitoring capabilities. Events (e.g., user creation, posts, channel updates) are emitted on-chain, enabling your application to:
  • React to user actions in real-time.
  • Gather precise analytics and track activity.
Example: Querying new user creation events using React hooks:
import { useUser } from '@sageprotocol/sdk/react';

function UserEventsComponent() {
  const { queryCreateEvents } = useUser();

  const fetchEvents = async () => {
    const result = await queryCreateEvents({});

    result.events.forEach(event => {
      console.log(`New user created: ${event.userName} (User ID: ${event.userId})`);
      console.log(`Owned User ID: ${event.userOwnedId}, Shared User ID: ${event.userSharedId}`);
      if (event.referredBy) {
        console.log(`Referred by user ID: ${event.referredBy}`);
      }
    });

    if (result.hasNextPage) {
      const nextBatch = await queryCreateEvents({ cursor: result.nextCursor });
      // Process next batch similarly
    }
  };

  return <button onClick={fetchEvents}>Fetch New Users</button>;
}

export default UserEventsComponent;
// Monitor new user creation events
const result = await sageClient.queryUserCreateEvents({});

result.events.forEach(event => {
  console.log(`New user created: ${event.userName} (User ID: ${event.userId})`);
  console.log(`Owned User ID: ${event.userOwnedId}, Shared User ID: ${event.userSharedId}`);
  if (event.referredBy) {
    console.log(`Referred by user ID: ${event.referredBy}`);
  }
});

// Continue querying from the last event fetched
if (result.hasNextPage) {
  const nextBatch = await sageClient.queryUserCreateEvents({
    cursor: result.nextCursor
  });
  // Process next batch similarly
}

React Context and Hooks

For React apps, the Sage SDK provides built-in context (SageProvider) and custom hooks (useUser, useChannel, usePost) to simplify state management and interactions with blockchain primitives. Example: Following a channel using React hooks:
import { useChannel } from '@sageprotocol/sdk/react';
import { useWallet } from '@suiet/wallet-kit';

function FollowChannel({ channelId, ownedUserId }) {
  const { follow } = useChannel();
  const { account, signAndExecuteTransaction } = useWallet();

  const handleFollow = async () => {
    const result = await follow({
      amounts: [0, 0],
      channelId,
      ownedUserId,
      self: account.address,
    });

    if (result.ok) {
      await signAndExecuteTransaction({ transaction: result.transaction });
      console.log("Channel followed successfully!");
    } else {
      console.error(result.err);
    }
  };

  return <button onClick={handleFollow}>Follow Channel</button>;
}

export default FollowChannel;
Leveraging these hooks ensures cleaner, more maintainable React code.

Next Steps

With these key concepts clarified, you’re now well-equipped to explore Sage SDK’s core primitives and fully utilize its powerful decentralized social functionalities. Proceed to:
  • Learn detailed management of the core primitives:
  • Advanced Guides: See complete examples for building sophisticated decentralized social apps.
  • API Reference: Explore comprehensive details on SDK methods and capabilities.