### Install and Run Project Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/tutorials-and-examples/circles-x-gnosis-app-starter-kit.md Install dependencies and start the development server for the starter kit. ```bash npm install npm run dev ``` -------------------------------- ### Get Token Balances Example Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Example demonstrating how to fetch the current token balances. ```typescript const tokens = await avatar.balances.getTokenBalances(); ``` -------------------------------- ### End-to-End Setup Example for Circles SDK Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/getting-started-with-the-sdk.md A complete example demonstrating SDK initialization, avatar retrieval, profile fetching, trust graph analysis, and token holder queries. This pattern can be adapted for various frontend and backend contexts. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; import { createBrowserRunner } from './runner'; // use the helper from section 5 async function bootstrapCircles() { const runner = createBrowserRunner(); await runner.init(); const sdk = new Sdk(circlesConfig[100], runner); const avatar = await sdk.getAvatar(runner.address!); console.log(await avatar.profile.get()); const trustGraph = await sdk.data.getTrustRelations(avatar.address); console.log(`Trustees: ${trustGraph.length}`); const topHolders = sdk.tokens.getHolders(avatar.address, 3); await topHolders.queryNextPage(); console.log('Top holders', topHolders.currentPage?.results ?? []); } bootstrapCircles().catch(console.error); ``` -------------------------------- ### Full Example: Find Groups and Memberships Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/group-avatars/find-groups-and-memberships.md A comprehensive example demonstrating how to initialize the SDK, find groups by name, and retrieve group memberships for an avatar, including pagination. ```typescript const sdk = new Sdk({ rpcUrl: 'https://rpc.aboutcircles.com' }); const rpc = sdk.rpc; // Find groups whose names start with "Community" const groupsResult = await rpc.group.findGroups(10, { nameStartsWith: 'Community' }); console.log('Found groups:', groupsResult); // Find memberships for a specific avatar const avatarAddress = '0x123...'; const memberships = rpc.group.getGroupMemberships(avatarAddress, 10); await memberships.queryNextPage(); console.log('Group memberships:', memberships.currentPage?.results); ``` -------------------------------- ### Install Circles SDK Packages Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/getting-started-with-the-sdk.md Install the core SDK packages and viem for your dApp. Pinning these versions ensures alignment across bundlers. ```bash npm i @aboutcircles/sdk \ @aboutcircles/sdk-core \ @aboutcircles/sdk-types \ @aboutcircles/sdk-runner \ @aboutcircles/sdk-rpc \ @aboutcircles/sdk-transfers \ @aboutcircles/sdk-pathfinder \ @aboutcircles/sdk-profiles \ viem ``` -------------------------------- ### Install Circles SDK Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-sdk-overview.md Install the primary npm package for the Circles SDK to begin integration. ```bash npm install @aboutcircles/sdk ``` -------------------------------- ### Advanced Transfer Example Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Example demonstrating how to perform an advanced transfer with the `useWrappedBalances` option enabled. ```typescript const receipt = await avatar.transfer.advanced('0xRecipient', BigInt(10e18), { useWrappedBalances: true }); ``` -------------------------------- ### Get Multiple Profiles by CIDs (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Fetch multiple user profiles simultaneously by listing their CIDs in the 'cids' query parameter, separated by commas. ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/getBatch?cids=Qm12345abcdef,Qm678bbdj" ``` -------------------------------- ### Add Trust Example Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Example of adding a trust relationship for an indefinite period. ```typescript await avatar.trust.add('0xFriend'); // indefinite ``` -------------------------------- ### Get a Profile by CID (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Retrieve a specific user profile by providing its Content Identifier (CID) as a query parameter. ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/get?cid=Qm12345abcdef" ``` -------------------------------- ### Initialize Circles SDK with Browser Runner Source: https://context7.com/aboutcircles/circles-docs/llms.txt Initialize the Sdk with a network config and a browser-based EOA runner (MetaMask/Rabby). This setup allows for state-changing transactions. Ensure the wallet is connected to Gnosis Chain. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; import { createPublicClient, createWalletClient, custom, http } from 'viem'; import { gnosis } from 'viem/chains'; import type { Address, TransactionReceipt, TransactionRequest, ContractRunner } from '@aboutcircles/sdk-types'; const circlesRPC = 'https://rpc.aboutcircles.com'; // Build a browser EOA runner (MetaMask / Rabby) const createBrowserRunner = (): ContractRunner => { const publicClient = createPublicClient({ chain: gnosis, transport: http(circlesRPC) }); const walletClient = createWalletClient({ chain: gnosis, transport: custom(window.ethereum) }); const runner: ContractRunner = { publicClient, address: undefined, async init() { const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' }); this.address = account as Address; if ((await walletClient.getChainId()) !== gnosis.id) { throw new Error('Please switch your wallet to Gnosis Chain (chainId 100).'); } }, estimateGas: (tx: TransactionRequest) => publicClient.estimateGas({ account: runner.address!, ...tx }), call: (tx: TransactionRequest) => publicClient.call({ account: tx.from || runner.address!, ...tx }), resolveName: (name: string) => publicClient.getEnsAddress({ name }), async sendTransaction(txs: TransactionRequest[]): Promise { if (!runner.address) throw new Error('Call init() first.'); let receipt: TransactionReceipt | undefined; for (const tx of txs) { const hash = await walletClient.sendTransaction({ account: runner.address, ...tx }); receipt = await publicClient.waitForTransactionReceipt({ hash }); } if (!receipt) throw new Error('No transactions submitted.'); return receipt; }, }; return runner; }; // Initialize const runner = createBrowserRunner(); await runner.init(); const sdk = new Sdk(circlesConfig[100], runner); const avatar = await sdk.getAvatar(runner.address!); console.log(await avatar.profile.get()); // Output: { name: 'Alice', description: '...', ... } ``` -------------------------------- ### Search Profiles by Description (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Query for user profiles based on keywords present in their description field. ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/search?description=Circles" ``` -------------------------------- ### Search Profiles by Address (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Locate user profiles associated with a specific wallet address. ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/search?address=0x1234567890abcdef" ``` -------------------------------- ### Search Profiles by Name (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Find user profiles by matching a given name. The search is case-insensitive. ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/search?name=John" ``` -------------------------------- ### Search Profiles by CID (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Find user profiles by their Content Identifier (CID). ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/search?CID=Qm12345abcdef" ``` -------------------------------- ### Search Profiles with Multiple Criteria (GET request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Perform a comprehensive search for user profiles by combining multiple search parameters such as name, description, address, and CID. ```bash curl -X GET "https://rpc.aboutcircles.com/profiles/search?name=John&description=blockchain&address=0x1234567890abcdef&CID=Qm12345abcdef" ``` -------------------------------- ### sdk.register.asHuman Source: https://context7.com/aboutcircles/circles-docs/llms.txt Invites a new user and registers them on the Circles V2 hub. The inviter escrows 100 CRC; the invitee gets 48 CRC as a welcome bonus. ```APIDOC ## sdk.register.asHuman — Register a Human Avatar Invite a new user and register them on the Circles V2 hub. The inviter escrows 100 CRC; the invitee gets 48 CRC as a welcome bonus. ```typescript // --- Inviter side --- const inviterSdk = new Sdk(circlesConfig[100], inviterRunner); const inviter = await inviterSdk.getAvatar('0xInviterAddress'); await inviter.invite.send('0xInviteeEOAAddress'); // Escrows 100 CRC and adds trust for the invitee // --- Invitee side --- const inviteeSdk = new Sdk(circlesConfig[100], inviteeRunner); const newAvatar = await inviteeSdk.register.asHuman('0xInviterAddress', { name: 'Alice', description: 'New Circles member', imageUrl: 'https://example.com/alice.png', previewImageUrl: 'data:image/jpeg;base64,...', // 256x256, ≤150 KB }); console.log('Registered at:', newAvatar.address); // Optionally redeem a specific invitation if multiple inviters exist await newAvatar.invite.redeem('0xInviterAddress'); ``` ``` -------------------------------- ### Profiles REST API Source: https://context7.com/aboutcircles/circles-docs/llms.txt This section outlines the REST API endpoints for querying and creating profiles. It provides examples for creating profiles, retrieving single or multiple profiles by CID, and searching profiles using various criteria like name, wallet address, or CID. ```APIDOC ## Profiles REST API Query and create profiles via HTTP without the SDK. ```bash # Create a profile curl -X POST "https://rpc.aboutcircles.com/profiles/pin" \ -H "Content-Type: application/json" \ -d '{ "name": "John Doe", "description": "A blockchain developer", "previewImageUrl": "https://example.com/preview.jpg", "imageUrl": "https://example.com/image.jpg", "extensions": { "twitter": "@johndoe", "github": "johndoe" } }' # Get a profile by CID curl -X GET "https://rpc.aboutcircles.com/profiles/get?cid=Qm12345abcdef" # Get multiple profiles by CIDs curl -X GET "https://rpc.aboutcircles.com/profiles/getBatch?cids=Qm12345abcdef,Qm678bbdj" # Search profiles by name curl -X GET "https://rpc.aboutcircles.com/profiles/search?name=John" # Search profiles by wallet address curl -X GET "https://rpc.aboutcircles.com/profiles/search?address=0x1234567890abcdef" # Search profiles by CID curl -X GET "https://rpc.aboutcircles.com/profiles/search?CID=Qm12345abcdef" # Multi-criteria search curl -X GET "https://rpc.aboutcircles.com/profiles/search?name=John&description=blockchain&address=0x1234567890abcdef" ``` ``` -------------------------------- ### Get Avatar by Address Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Retrieves an avatar instance using its wallet address. No setup required. ```typescript sdk.getAvatar(avatarAddress: string): Promise; ``` ```typescript const avatar = await sdk.getAvatar('0x123...abc'); ``` -------------------------------- ### Initialize RPC Access Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/group-avatars/find-groups-and-memberships.md Instantiate the SDK and access the RPC client. It's recommended to reuse the RPC client from an existing SDK instance. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { CirclesRpc } from '@aboutcircles/sdk-rpc'; // Preferred: reuse the RPC client from an SDK instance const sdk = new Sdk({ rpcUrl: 'https://rpc.aboutcircles.com' }); const rpc = sdk.rpc; ``` -------------------------------- ### Create a Profile (POST request) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Use this endpoint to create a new user profile. Ensure the Content-Type header is set to application/json and provide profile details in the request body. ```bash curl -X POST "https://rpc.aboutcircles.com/profiles/pin" \ -H "Content-Type: application/json" \ -d '{ "name": "John Doe", "description": "A blockchain developer", "previewImageUrl": "https://example.com/preview.jpg", "imageUrl": "https://example.com/image.jpg", "extensions": { "twitter": "@johndoe", "github": "johndoe" } }' ``` -------------------------------- ### Creating and Pinning a Profile with SDK Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-profiles.md Uses the SDK's `profiles.create` method to pin profile data to IPFS. This is typically done when building forms or admin panels. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; const runner = /* your ContractRunner */; await runner.init(); const sdk = new Sdk(circlesConfig[100], runner); const profile = { name: 'John Doe', description: 'Web3 Developer', previewImageUrl: 'data:image/jpeg;base64,...', }; const profileCid = await sdk.profiles.create(profile); console.log('Pinned profile CID:', profileCid); ``` -------------------------------- ### Sdk Class Constructor Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/circles-sdk-interface.md Initializes the Sdk class. A config object can be provided, defaulting to Gnosis. A contractRunner is required for any state-changing operations. ```APIDOC ## Sdk Class Constructor: `new Sdk(config?: CirclesConfig, contractRunner?: ContractRunner)` * `config` defaults to `circlesConfig[100]` (Gnosis) * `contractRunner` required for any state-changing call (see ContractRunner below) ``` -------------------------------- ### avatar.transfer.getMaxAmountAdvanced Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Helper function to get the maximum transferable amount with advanced pathfinding options. ```APIDOC ## avatar.transfer.getMaxAmountAdvanced ### Description Helper function to get the maximum transferable amount with advanced pathfinding options. ### Method Signature ```ts avatar.transfer.getMaxAmountAdvanced(to: string, options?: PathfindingOptions): Promise; ``` ### Parameters * **to** (string) - Required - The recipient's address. * **options** (PathfindingOptions) - Optional - Pathfinding configurations. ### Response * **bigint** - The maximum transferable amount. ``` -------------------------------- ### Create a Base Group with SDK Source: https://context7.com/aboutcircles/circles-docs/llms.txt Deploys a BaseGroup with profile pinning, factory deployment, and address extraction. Requires SDK initialization and group profile details. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; import type { GroupProfile } from '@aboutcircles/sdk-types'; const sdk = new Sdk(circlesConfig[100], runner); const config = circlesConfig[100]; const groupProfile: GroupProfile = { name: 'My Community Group', symbol: 'MCG', // required for groups description: 'A community group for local initiatives', imageUrl: 'https://example.com/group.jpg', }; const groupAvatar = await sdk.register.asGroup( runner.address!, // owner config.coreMembersGroupDeployer, // service config.standardTreasury, // feeCollection [], // initialConditions (membership contracts) groupProfile.name, groupProfile.symbol, groupProfile ); console.log('Group deployed at:', groupAvatar.address); ``` -------------------------------- ### Create a Base Group with SDK Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/group-avatars/create-base-groups-for-your-community.md Use `sdk.register.asGroup` to create a new base group. This function handles profile pinning, factory deployment, and address extraction. Ensure you have a `ContractRunner` instance tied to your wallet. ```typescript import { Sdk } from '@aboutcircles/sdk'; const sdk = new Sdk( { rpcUrl: 'https://rpc.aboutcircles.com' }, runner // ContractRunner tied to your wallet ); const groupAvatar = await sdk.register.asGroup( '0xOwner', '0xService', '0xFeeCollection', ['0xCondition1', '0xCondition2'], // initial membership conditions 'My Base Group', 'MBG', { name: 'My Base Group', symbol: 'MBG', description: 'A base group for coordination', imageUrl: '', // optional previewImageUrl: '', // optional } ); console.log('Base group created at:', groupAvatar.address); ``` -------------------------------- ### avatar.transfer.getMaxAmount Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Helper function to get the maximum transferable amount to a specified recipient address. ```APIDOC ## avatar.transfer.getMaxAmount ### Description Helper function to get the maximum transferable amount to a specified recipient address. ### Method Signature ```ts avatar.transfer.getMaxAmount(to: string): Promise; ``` ### Parameters * **to** (string) - Required - The recipient's address. ### Response * **bigint** - The maximum transferable amount. ``` -------------------------------- ### Create a Base Group Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/group-avatars/create-base-groups-for-your-community.md This snippet demonstrates how to create a new base group using the `sdk.register.asGroup` method, which handles profile pinning, factory deployment, and address extraction. ```APIDOC ## Create a Base Group `sdk.register.asGroup` wraps profile pinning, factory deployment, and address extraction. ```ts import { Sdk } from '@aboutcircles/sdk'; const sdk = new Sdk( { rpcUrl: 'https://rpc.aboutcircles.com' }, runner // ContractRunner tied to your wallet ); const groupAvatar = await sdk.register.asGroup( '0xOwner', '0xService', '0xFeeCollection', ['0xCondition1', '0xCondition2'], // initial membership conditions 'My Base Group', 'MBG', { name: 'My Base Group', symbol: 'MBG', description: 'A base group for coordination', imageUrl: '', // optional previewImageUrl: '', // optional } ); console.log('Base group created at:', groupAvatar.address); ``` The returned instance is a `BaseGroupAvatar`, ready for trust, membership, and admin actions. ``` -------------------------------- ### Get a Profile by CID Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Retrieves a single user profile using its Content Identifier (CID). ```APIDOC ## GET /profiles/get ### Description Retrieves a user profile by its CID. ### Method GET ### Endpoint /profiles/get ### Query Parameters - **cid** (string) - Required - The Content Identifier of the profile to retrieve. ### Response Example { "example": "response body" } ``` -------------------------------- ### Create a Profile Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Creates a new user profile with provided details. ```APIDOC ## POST /profiles/pin ### Description Creates a new user profile. ### Method POST ### Endpoint /profiles/pin ### Request Body - **name** (string) - Required - The name of the user. - **description** (string) - Optional - A brief description of the user. - **previewImageUrl** (string) - Optional - URL for a preview image. - **imageUrl** (string) - Optional - URL for the main image. - **extensions** (object) - Optional - Additional key-value pairs for extensions like Twitter or GitHub. - **twitter** (string) - Optional - Twitter handle. - **github** (string) - Optional - GitHub username. ### Request Example { "name": "John Doe", "description": "A blockchain developer", "previewImageUrl": "https://example.com/preview.jpg", "imageUrl": "https://example.com/image.jpg", "extensions": { "twitter": "@johndoe", "github": "johndoe" } } ``` -------------------------------- ### Initialize the Circles SDK Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/getting-started-with-the-sdk.md Initialize the SDK with configuration and a runner. The runner is required for state-changing transactions. Defaults to mainnet if config is omitted. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; const runner = createBrowserRunner(); await runner.init(); const sdk = new Sdk(circlesConfig[100], runner); // config defaults to mainnet if omitted const avatar = await sdk.getAvatar(runner.address!); const balances = await avatar.balances.getTokenBalances(); const trustGraph = await sdk.data.getTrustRelations(avatar.address); const demurragedWrapper = await sdk.tokens.getDemurragedWrapper(avatar.address); const members = sdk.groups.getMembers('0xGroupAddress...'); await members.queryNextPage(); // fetch first page when you need it ``` -------------------------------- ### Get Group Memberships Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Queries the group memberships of an avatar, returning a list of all groups the avatar is a member of. ```APIDOC ## Get group memberships You can query the group memberships of an avatar using the `getGroupMemberships(avatar: string, pageSize: number): CirclesQuery` method to get a list of all groups an avatar is a member of. The result rows contain the following properties: `group`, `member`, `expiryTime`. ```typescript const query = data.getGroupMemberships("0x...", 25); const hasResults = await query.queryNextPage(); if (!hasResults) { console.log("No trust events yet"); return; } const rows = query.currentPage.results; rows.forEach(row => console.log(row)); ``` ``` -------------------------------- ### Get Multiple Profiles by CIDs Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-circles-profiles.md Retrieves multiple user profiles by providing a comma-separated list of CIDs. ```APIDOC ## GET /profiles/getBatch ### Description Retrieves multiple user profiles by their CIDs. ### Method GET ### Endpoint /profiles/getBatch ### Query Parameters - **cids** (string) - Required - A comma-separated list of Content Identifiers. ### Response Example { "example": "response body" } ``` -------------------------------- ### sdk.register.asGroup Source: https://context7.com/aboutcircles/circles-docs/llms.txt Deploys a BaseGroup with profile pinning, factory deployment, and address extraction in a single call. This is used to create new community groups. ```APIDOC ## `sdk.register.asGroup` — Create a Base Group Deploy a BaseGroup with profile pinning, factory deployment, and address extraction in one call. ### Method ```typescript await sdk.register.asGroup( owner: string, service: string, feeCollection: string, initialConditions: any[], name: string, symbol: string, groupProfile: GroupProfile ): Promise ``` ### Parameters - **owner** (string) - The address of the group owner. - **service** (string) - The service address for group deployment. - **feeCollection** (string) - The address for fee collection. - **initialConditions** (any[]) - An array of initial membership contracts. - **name** (string) - The name of the group. - **symbol** (string) - The symbol for the group (required). - **groupProfile** (GroupProfile) - An object containing the group's profile information (name, symbol, description, imageUrl). ### Request Example ```typescript const groupProfile = { name: 'My Community Group', symbol: 'MCG', description: 'A community group for local initiatives', imageUrl: 'https://example.com/group.jpg', }; const groupAvatar = await sdk.register.asGroup( runner.address!, config.coreMembersGroupDeployer, config.standardTreasury, [], groupProfile.name, groupProfile.symbol, groupProfile ); ``` ### Response - **BaseGroupAvatar** - An object representing the deployed BaseGroup, ready for trust, membership, and admin operations. ``` -------------------------------- ### Create a Browser-Friendly Contract Runner with Viem Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/getting-started-with-the-sdk.md Implement a minimal `ContractRunner` for single-signers like MetaMask. It requests wallet access, enforces the correct chain ID, and delegates gas estimation, read-only calls, and ENS resolution to Viem. ```typescript import { createPublicClient, createWalletClient, custom, http } from 'viem'; import { gnosis } from 'viem/chains'; import type { Address, TransactionReceipt, TransactionRequest } from '@aboutcircles/sdk-types'; const circlesRPC = 'https://rpc.aboutcircles.com'; export const createBrowserRunner = () => { const publicClient = createPublicClient({ chain: gnosis, transport: http(circlesRPC), }); const walletClient = createWalletClient({ chain: gnosis, transport: custom(window.ethereum), }); const runner: ContractRunner = { publicClient, address: walletClient.account?.address, async init() { const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' }); this.address = account as Address; const currentChain = await walletClient.getChainId(); if (currentChain !== gnosis.id) { throw new Error('Please switch your wallet to Gnosis Chain (chainId 100).'); } }, estimateGas: (tx: TransactionRequest) => publicClient.estimateGas({ account: runner.address!, ...tx }), call: (tx: TransactionRequest) => publicClient.call({ account: tx.from || runner.address!, ...tx }), resolveName: (name: string) => publicClient.getEnsAddress({ name }), async sendTransaction(txs: TransactionRequest[]): Promise { if (!runner.address) throw new Error('Runner not initialised. Call init() first.'); let receipt: TransactionReceipt | undefined; for (const tx of txs) { const hash = await walletClient.sendTransaction({ account: runner.address, ...tx, }); receipt = await publicClient.waitForTransactionReceipt({ hash }); } if (!receipt) { throw new Error('No transactions submitted.'); } return receipt; }, }; return runner; }; ``` -------------------------------- ### Get Avatar Profile Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/handle-profile-of-an-avatar.md Fetches the current profile associated with the avatar. If no profile exists, it will return `undefined`. ```APIDOC ## Get Avatar Profile ### Description Fetches the current profile associated with the avatar. If no profile exists, it will return `undefined`. ### Method ```typescript inviteeAvatar.profile.get() ``` ### Response #### Success Response - `Profile` (object) - The avatar's profile data, or `undefined` if no profile exists. ### Response Example ```json { "name": "Avatar Name", "description": "Description of the avatar.", "avatarUrl": "ipfs://QmYourImageCIDHere" } ``` ``` -------------------------------- ### Get Avatar Profile Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/handle-profile-of-an-avatar.md Fetches the current profile associated with the avatar. Returns undefined if no profile exists. ```typescript const profile = await inviteeAvatar.profile.get(); if (profile) { console.log(profile.name, profile.description); } ``` -------------------------------- ### Initialize Circles SDK Provider in React Source: https://context7.com/aboutcircles/circles-docs/llms.txt Sets up the Circles SDK context for a React application, supporting Safe wallet integration. Ensure window.ethereum is available for full functionality; otherwise, it initializes a read-only SDK. ```typescript import React, { createContext, useCallback, useEffect, useState } from 'react'; import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; import { SafeBrowserRunner } from '@aboutcircles/sdk-runner'; import { createPublicClient, http } from 'viem'; import { gnosis } from 'viem/chains'; export const CirclesSDKContext = createContext(null); export const CirclesSDKProvider = ({ children, safeAddress }) => { const [sdk, setSdk] = useState(null); const [runner, setRunner] = useState(null); const [address, setAddress] = useState(null); const [isConnected, setIsConnected] = useState(false); const initSdk = useCallback(async () => { try { if (!window.ethereum || !safeAddress) { // Read-only SDK without runner setSdk(new Sdk(circlesConfig[100])); setIsConnected(true); return; } const publicClient = createPublicClient({ chain: gnosis, transport: http(circlesConfig[100].circlesRpcUrl), }); const safeRunner = new SafeBrowserRunner(publicClient, window.ethereum, safeAddress); await safeRunner.init(); setRunner(safeRunner); setAddress(safeAddress); const sdkInstance = new Sdk(circlesConfig[100], safeRunner); setSdk(sdkInstance); setIsConnected(true); } catch (err) { console.error('Error initializing Circles SDK', err); setIsConnected(false); } }, [safeAddress]); useEffect(() => { initSdk(); }, [initSdk]); return ( {children} ); }; ``` -------------------------------- ### Import SDK Building Blocks Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/getting-started-with-the-sdk.md Import the main Sdk class and other essential components like Core, circlesConfig, and ContractRunner. Optional modules can be imported for lower-level access. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { Core, circlesConfig, type CirclesConfig } from '@aboutcircles/sdk-core'; import type { ContractRunner } from '@aboutcircles/sdk-types'; import { createPublicClient, createWalletClient, custom, http } from 'viem'; import { gnosis } from 'viem/chains'; // Optional modules for lower-level access when you need them import { CirclesRpc } from '@aboutcircles/sdk-rpc'; import { TransferBuilder } from '@aboutcircles/sdk-transfers'; import { Profiles } from '@aboutcircles/sdk-profiles'; ``` -------------------------------- ### sdk.register.asOrganization Source: https://context7.com/aboutcircles/circles-docs/llms.txt Creates a non-minting organization that can participate in the trust network and receive Circles. ```APIDOC ## sdk.register.asOrganization — Register an Organization Avatar Create a non-minting organization that can participate in the trust network and receive Circles. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; const sdk = new Sdk(circlesConfig[100], runner); // Register with inline profile const orgAvatar = await sdk.register.asOrganization({ name: 'My Organization', description: 'Circles-enabled community treasury', imageUrl: 'https://example.com/org.png', previewImageUrl: '', }); console.log('Organization avatar:', orgAvatar.address); // Register with an existing profile CID const orgFromCid = await sdk.register.asOrganization('QmExistingProfileCid'); console.log('Org from CID:', orgFromCid.address); ``` ``` -------------------------------- ### Get Existing Avatar Profile Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/inviting-and-accepting-human-avatars.md Retrieve the profile details of an existing avatar if you have their address. This includes their name and description. ```APIDOC ## Get Existing Avatar Profile ### Description Retrieve the profile information (name and description) of an existing avatar using its address. ### Method `avatar.profile.get()` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Request Example ```typescript const profile = await inviteeAvatar.profile.get(); if (profile) { console.log(profile.name, profile.description); } ``` ### Response #### Success Response (200) - **name** (string) - The name of the avatar. - **description** (string) - The description of the avatar. #### Response Example ```json { "name": "Alice", "description": "New Circles member" } ``` ``` -------------------------------- ### Initialize CirclesRpc and CirclesQuery Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/utilising-circlesquery-class.md Instantiate the `CirclesRpc` client with the RPC endpoint and then create a `CirclesQuery` instance, passing the RPC client and your query definition. ```typescript const circlesRpc = new CirclesRpc('https://rpc.aboutcircles.com/'); ``` ```typescript const query = new CirclesQuery(circlesRpc, queryDefinition); ``` -------------------------------- ### Get Token Balances Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/get-token-balances-of-an-avatar.md Returns an array of `TokenBalanceRow` entries for every token relevant to the avatar in the current context. ```APIDOC ## Get Token Balances ### Description Returns an array of `TokenBalanceRow` entries for every token relevant to the avatar in the current context. ### Method `avatar.balances.getTokenBalances()` ### Parameters None ### Response #### Success Response (Array) - Returns an array of objects, where each object has: - **token** (string): The token identifier. - **amount** (BigNumber): The balance of the token. ``` -------------------------------- ### Sdk Methods - General Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/circles-sdk-interface.md Methods available on the Sdk class for general operations. ```APIDOC #### Sdk methods * `getAvatar(address)` → `HumanAvatar | OrganisationAvatar | BaseGroupAvatar` ``` -------------------------------- ### Get Invited By Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Queries who invited a specific avatar. Returns the inviting avatar's address or undefined if the avatar was not invited. ```APIDOC ## Get invited by You can query who invited an other avatar by calling `getInvitedBy(avatar:string): Promise`. If the avatar wasn't invited, the method returns undefined. ```typescript const invitedBy = await data.getInvitedBy("0x..."); ``` ``` -------------------------------- ### Instantiate Lower-Level SDK Packages Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/getting-started-with-the-sdk.md Access underlying SDK modules like `Core`, `CirclesRpc`, `TransferBuilder`, and `Profiles` for granular control over analytics, dry-run tooling, and custom transfer flows. Ensure consistent configuration by reusing the same `circlesConfig` object. ```typescript import { Core, circlesConfig } from '@aboutcircles/sdk-core'; import { CirclesRpc } from '@aboutcircles/sdk-rpc'; import { TransferBuilder } from '@aboutcircles/sdk-transfers'; import { Profiles } from '@aboutcircles/sdk-profiles'; const config = circlesConfig[100]; const core = new Core(config); const rpc = new CirclesRpc(config.circlesRpcUrl); const transferBuilder = new TransferBuilder(core); const profilesClient = new Profiles(config.profileServiceUrl); ``` -------------------------------- ### Get Maximum Transferable Amount Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/transfer-personal-circles-tokens-to-different-avatar.md Computes the largest flow permitted by your trust graph and current balances using pathfinding. ```APIDOC ## Get Maximum Transferable Amount ### Description Computes the largest flow permitted by your trust graph and current balances. ### Method `avatar.transfer.getMaxAmount(recipientAddress: string): Promise` ### Parameters #### Path Parameters - **recipientAddress** (string) - Required - The address of the recipient avatar. ### Response #### Success Response (Promise) - **Returns** (BigInt) - The maximum transferable amount. ### Request Example ```ts const maxTransferable = await avatar.transfer.getMaxAmount('0xRecipient'); console.log(`Maximum transferable amount: ${maxTransferable.toString()}`); ``` ``` -------------------------------- ### Get Individual Token Balances Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/get-token-balances-of-an-avatar.md Returns an array of TokenBalanceRow entries for every token relevant to the avatar in the current context. ```ts const tokenBalances = await avatar.balances.getTokenBalances(); tokenBalances.forEach((balance) => { console.log(`Token: ${balance.token}, Balance: ${balance.amount}`); }); ``` -------------------------------- ### register.asOrganization Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md Registers a new organization avatar with provided profile data. ```APIDOC ## register.asOrganization ### Description Registers an organization avatar with profile data. ### Method Signature ```ts register.asOrganization(profile: Profile | string): Promise; ``` ### Parameters #### Path Parameters - **profile** (Profile | string) - Required - Profile object or CID string; must include `name`. ### Returns - Promise ### Example ```ts const org = await sdk.register.asOrganization({ name: 'Org', description: 'Example org' }); ``` ``` -------------------------------- ### Get Transaction History Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Queries all incoming and outgoing Circles transfers for an avatar, including minting and transfers for both v1 and v2 protocols. ```APIDOC ## getTransactionHistory ### Description Can be used to query all incoming and outgoing Circles transfers from and to an avatar. This includes minting and transfers of personal and group Circles for v1 and v2. The results are ordered in descending order. ### Method `getTransactionHistory(avatar: string, pageSize: number): CirclesQuery` ### Parameters #### Path Parameters - **avatar** (string) - Required - The avatar address to query. - **pageSize** (number) - Required - The number of results to retrieve per page. ### Response #### Success Response (200) - **CirclesQuery** - An object that allows paginating through transaction history. - **timestamp** (number) - When the transaction happened - **transactionHash** (string) - **version** (number) - If the transaction happened in Circles v1 or v2 - **operator** (string) - (v2 only) the operator that facilitated the transaction - **from** (string) - the sender address - **to** (string) - the receiver address - **id** (string) - in v1: the token address, in v2: the token id - **value** (bigint) - the transferred raw value for the given version - **timeCircles** (number) - a floating point number representation of the `value` for display purposes - **tokenAddress** (string) - an address representation of the numeric tokenid (v2) or the actual erc20 token address of a v1 personal token ### Request Example ```typescript const query = data.getTransactionHistory("0x...", 25); const hasResults = await query.queryNextPage(); if (!hasResults) { console.log("No transactions yet"); return; } const rows = query.currentPage.results; ows.forEach(row => console.log(row)); ``` ``` -------------------------------- ### Sdk Methods - Profiles Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/circles-sdk-interface.md Methods for creating and retrieving profiles using IPFS. ```APIDOC **Profiles (`sdk.profiles.*`)** * `create(profile)` → `cid` * `get(cid)` → `Profile | undefined` ``` -------------------------------- ### Get Maximum Transferable Amount with Pathfinder Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/transfer-personal-circles-tokens-to-different-avatar.md Computes the largest flow permitted by your trust graph and current balances using pathfinding. ```typescript const maxTransferable = await avatar.transfer.getMaxAmount('0xRecipient'); console.log(`Maximum transferable amount: ${maxTransferable.toString()}`); ``` -------------------------------- ### Get Total Balance (v1, v2) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Calculates the total Circles balance of an avatar by summing all its token holdings for both v1 and v2 protocols. ```APIDOC ## getTotalBalance / getTotalBalanceV2 ### Description The total Circles balance of an avatar is the sum of all it's personalized and group token holdings. There is a separate method for each Circles version. ### Method `getTotalBalance(avatar:string): Promise` `getTotalBalanceV2(avatar:string): Promise` ### Parameters #### Path Parameters - **avatar** (string) - Required - The avatar address to query. #### Query Parameters - **asTimeCircles** (boolean) - Optional - Controls the return value format. `true` (default) returns a floating point number as a string, `false` returns a bigint number as a string. ### Response #### Success Response (200) - **string** - The total balance as a string. ### Request Example ```typescript const totalBalanceV1 = await data.getTotalBalance("0x..."); const totalBalanceV2 = await data.getTotalBalanceV2("0x..."); ``` ``` -------------------------------- ### Get Invitations Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Returns a list of invitations sent by a specified avatar, including details like timestamp, transaction hash, inviter, and invited avatar. ```APIDOC ## Get invited users Avatars can invite others to join Circles. The `getInvitations(avatar: string, pageSize: number): CirclesQuery` method returns a list of invitations sent by the specified avatar. Th e result rows contain the follwing properties: `timestamp`, `transactionHash`, `inviter`, `invited`. ```typescript const query = data.getInvitations("0x...", 25); const hasResults = await query.queryNextPage(); if (!hasResults) { console.log("No trust events yet"); return; } const rows = query.currentPage.results; rows.forEach(row => console.log(row)); ``` ``` -------------------------------- ### Global Profile Service with SDK Source: https://context7.com/aboutcircles/circles-docs/llms.txt Allows pinning or retrieving profiles without an avatar instance, suitable for batch jobs and server-side flows. Requires an initialized Sdk instance. ```typescript import { Sdk } from '@aboutcircles/sdk'; import { circlesConfig } from '@aboutcircles/sdk-core'; const sdk = new Sdk(circlesConfig[100], runner); // Pin a new profile const cid = await sdk.profiles.create({ name: 'John Doe', description: 'Web3 Developer', previewImageUrl: 'data:image/jpeg;base64,...', imageUrl: 'https://example.com/john.jpg', }); console.log('Pinned CID:', cid); // Output: Pinned CID: QmXyz123... // Retrieve by CID const fetchedProfile = await sdk.profiles.get(cid); console.log(fetchedProfile?.name); // Output: John Doe ``` -------------------------------- ### Get Avatar Info Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Retrieves basic information about a Circles avatar, including signup timestamp, Circles version, avatar type, and profile CID. ```APIDOC ## getAvatarInfo ### Description Finds basic information about an avatar. This includes the signup timestamp, circles version, avatar type (human, organization or group), and token address/id as well as it's profile CID (if any). ### Method `getAvatarInfo(avatar: string): Promise` ### Parameters #### Path Parameters - **avatar** (string) - Required - The avatar address to query. ### Response #### Success Response (200) - **AvatarRow** - An object containing avatar information or undefined if the avatar is not found. ### Request Example ```typescript const avatarInfo = await data.getAvatarInfo("0x..."); if (avatarInfo) { console.log("Avatar is signed up at Circles"); } else { console.log("Avatar is not signed up at Circles"); } ``` ``` -------------------------------- ### Get Total Circles Balance Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/get-token-balances-of-an-avatar.md Automatically checks the correct hub version. Returns the sum of all Circles holdings (unwrapped + wrapped) for the avatar address. ```ts const totalBalance = await avatar.balances.getTotal(); console.log(`Total Circles balance: ${totalBalance.toString()}`); ``` -------------------------------- ### Notes on ContractRunner and Pathfinding Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/circles-sdk-interface.md Important notes regarding the usage of ContractRunner for write operations and pathfinding options for transfers. ```APIDOC ### Notes * Provide a `ContractRunner` for any write call; you can use `SafeBrowserRunner`/`SafeContractRunner` or your own viem-based runner. * Pathfinding options for transfers mirror `FindPathParams` (`useWrappedBalances`, token include/exclude lists, `maxTransfers`, `simulatedBalances`, etc.). ``` -------------------------------- ### Initialize CirclesRpc and CirclesData (Gnosis Chain) Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/subscribing-to-avatar-events.md Initialize the CirclesRpc and CirclesData classes for Gnosis Chain. Ensure you have a valid RPC endpoint. ```typescript const circlesRpc = new CirclesRpc("https://rpc.aboutcircles.com/"); const data = new CirclesData(circlesRpc); ``` -------------------------------- ### Get Max Transfer Amount Helpers Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk-reference/sdk-methods.md These helper methods retrieve the maximum transferable amount. `getMaxAmount` is for standard transfers, while `getMaxAmountAdvanced` considers pathfinding options. ```typescript avatar.transfer.getMaxAmount(to: string): Promise; ``` ```typescript avatar.transfer.getMaxAmountAdvanced(to: string, options?: PathfindingOptions): Promise; ``` -------------------------------- ### Get Trust Relations Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/querying-circles-profiles-and-data/query-data.md Retrieves effective trust events for a given avatar, excluding expired or removed relations. Useful for understanding the history of trust relationships. ```APIDOC ## Get trust relations The `getTrustRelations(avatar: string, pageSize: number): CirclesQuery` method can be used to query the effective trust events for an avatar. Already expired or removed trust relations are omitted from the results. ```typescript const trustsQuery = data.getTrustRelations("0x...", 25); const hasResults = await query.queryNextPage(); if (!hasResults) { console.log("No trust events yet"); return; } const rows = query.currentPage.results; rows.forEach(row => console.log(row)); ``` **Note:** The results of this method contain one row per incoming or outgoing event. For displaying a contact list, consider using `getAggregatedTrustRelations` instead. ``` -------------------------------- ### Accepting an Invitation and Registering as Human Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/personal-human-avatars/inviting-and-accepting-human-avatars.md This snippet demonstrates how an invitee can accept an invitation and register as a human avatar on the Circles network, providing their name and description. ```APIDOC ## Accepting Invitation and Registering as Human ### Description Accept an invitation and register as a new human avatar. You can provide a name and description for your profile. ### Method `inviteeSdk.register.asHuman(inviterAddress: string, profileData: { name: string, description: string })` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **name** (string) - Required - The name of the new human avatar. - **description** (string) - Optional - A description for the new human avatar. ### Request Example ```typescript const inviteeAvatar = await inviteeSdk.register.asHuman('0xInviterAddress', { name: 'Alice', description: 'New Circles member', }); ``` ### Response #### Success Response (200) - Returns the newly created `HumanAvatar` object. #### Response Example - None explicitly documented. ``` -------------------------------- ### Get Group Memberships for an Avatar Source: https://github.com/aboutcircles/circles-docs/blob/gitbook/docs/circles-sdk/circles-avatars/group-avatars/find-groups-and-memberships.md Retrieves group memberships for a specific avatar. This method returns a `PagedQuery` object, allowing iteration through results using `queryNextPage()`. ```APIDOC ## getGroupMemberships ### Description Fetches group memberships for a given avatar, supporting pagination. ### Method Signature `getGroupMemberships(avatarAddress: string, limit: number)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * `avatarAddress` (string) - Required - The address of the avatar for which to fetch memberships. * `limit` (number) - Required - The number of memberships to retrieve per page. ### Request Example ```ts const membershipsQuery = rpc.group.getGroupMemberships('0xAvatar', 5); await membershipsQuery.queryNextPage(); // first page console.log('Memberships:', membershipsQuery.currentPage?.results); ``` ### Response #### Success Response (200) Returns a `PagedQuery` object. The `currentPage` property contains the results for the current page. #### Response Example ```json { "currentPage": { "results": [ { "groupId": "0xgroupid...", "avatarAddress": "0xAvatar", "role": "member", "joinedAt": "2023-01-01T12:00:00Z" } ], "hasMore": true } } ``` ```