@citizenwallet/sdk
v2.0.130
Published
An sdk to easily work with citizen wallet.
Maintainers
Readme
An easy-to-use SDK for building frontend interfaces that interact with a community server and any related smart contracts that we use. This SDK is frontend framework agnostic and includes types, API calls, and state management.
Introduction
Welcome to the official SDK for our platform.
We hope you find this SDK useful, and we're excited to see what you build with it!
Installation
To install the SDK, run the following command in your terminal:
Deno add jsr:@citizenwallet/sdkInstallation (npm)
To install the SDK, run the following command in your terminal:
npm install --save @citizenwallet/sdkGetting Started
Understanding CommunityConfig
The CommunityConfig class is the foundation of the SDK. Almost all SDK functions require a CommunityConfig instance as their first parameter. This config object contains all the information about a community, including blockchain networks, contract addresses, tokens, and more.
Loading Configuration
Step 1: Fetch the Configuration JSON
Community configurations are typically hosted as JSON files. You can fetch them from a URL:
import { CommunityConfig, type Config } from "@citizenwallet/sdk";
async function loadConfig(configUrl: string): Promise<CommunityConfig> {
const response = await fetch(configUrl);
const configData: Config = await response.json();
return new CommunityConfig(configData);
}
// Example: Load config from a community's domain
const config = await loadConfig("https://example.com/config/community.json");Step 2: Use CommunityConfig in SDK Functions
Once you have a CommunityConfig instance, you can use it with any SDK function:
import {
CommunityConfig,
getAccountAddress,
getAccountBalance,
BundlerService,
LogsService
} from "@citizenwallet/sdk";
// Initialize config
const config = await loadConfig("https://example.com/config/community.json");
// Use config in SDK functions
const accountAddress = await getAccountAddress(config, userAddress);
const balance = await getAccountBalance(config, accountAddress);
// Create service instances
const bundler = new BundlerService(config);
const logsService = new LogsService(config);Configuration Structure
The configuration JSON follows a specific structure. Here's a minimal example:
{
"community": {
"name": "Community Name",
"alias": "community-alias",
"primary_token": {
"address": "0x...",
"chain_id": 42220
},
"primary_account_factory": {
"address": "0x...",
"chain_id": 42220
}
},
"tokens": {
"42220:0x...": {
"standard": "erc20",
"name": "Token Name",
"symbol": "TKN",
"decimals": 18,
"address": "0x...",
"chain_id": 42220
}
},
"chains": {
"42220": {
"id": 42220,
"node": {
"url": "https://...",
"ws_url": "wss://..."
}
}
},
"accounts": {
"42220:0x...": {
"chain_id": 42220,
"entrypoint_address": "0x...",
"paymaster_address": "0x...",
"account_factory_address": "0x...",
"paymaster_type": "cw"
}
},
"scan": {
"url": "https://explorer.example.com",
"name": "Explorer Name"
},
"ipfs": {
"url": "https://ipfs.example.com"
},
"config_location": "https://example.com/config/community.json",
"version": 4
}See the community.json file in this repository for a complete example.
Quick Example
Here's a complete example showing how to use the SDK:
import {
CommunityConfig,
getAccountAddress,
getAccountBalance,
BundlerService
} from "@citizenwallet/sdk";
import { Wallet } from "ethers";
// Load configuration
async function main() {
const response = await fetch("https://example.com/config/community.json");
const configData = await response.json();
const config = new CommunityConfig(configData);
// Get smart account address for a user
const userAddress = "0x1234...";
const accountAddress = await getAccountAddress(config, userAddress);
// Check account balance
const balance = await getAccountBalance(config, accountAddress);
// Send tokens using bundler
const signer = new Wallet(privateKey);
const bundler = new BundlerService(config);
const txHash = await bundler.sendERC20Token(
signer,
config.primaryToken.address,
accountAddress,
recipientAddress,
amount,
"Transfer description"
);
console.log("Transaction hash:", txHash);
}Important: Always instantiate CommunityConfig before using any SDK functions. The config is required for all operations.
API Reference
Configuration
Types and Interfaces
Config- Main configuration interfaceConfigCommunity- Community configurationConfigToken- Token configurationConfigAccount- Account configurationConfigChain- Chain configurationConfigIPFS- IPFS configurationConfigPlugin- Plugin configuration
CommunityConfig Class
The main configuration class that provides helper methods for accessing community settings.
import { CommunityConfig } from "@citizenwallet/sdk";
const config = new CommunityConfig(configData);
// Access primary token
const token = config.primaryToken;
// Access primary network
const network = config.primaryNetwork;
// Access RPC URL
const rpcUrl = config.primaryRPCUrl;
// Access account configuration
const accountConfig = config.primaryAccountConfig;
// Access session configuration
const sessionConfig = config.primarySessionConfig;
// Access card configuration
const cardConfig = config.primaryCardConfig;
// Get token by project name
const projectToken = config.getProjectToken("project-name");Constants
Networks
Predefined network configurations for supported blockchains:
import { NETWORKS } from "@citizenwallet/sdk";
// Available networks: 100 (Gnosis), 137 (Polygon), 8453 (Base), 42220 (CELO), 42161 (Arbitrum)
const gnosisNetwork = NETWORKS["100"];Profiles
Profile management functions for community members.
formatProfileImageLinks(ipfsUrl: string, profile: Profile): Profile
Formats profile image URLs to use the provided IPFS domain.
formatUsernameToBytes32(username: string): string
Converts a username to bytes32 format for smart contract interaction.
getProfileFromId(ipfsDomain: string, config: CommunityConfig, id: string): Promise<ProfileWithTokenId | null>
Retrieves a profile by its token ID.
getProfileFromAddress(ipfsDomain: string, config: CommunityConfig, address: string): Promise<ProfileWithTokenId | null>
Retrieves a profile by wallet address.
getProfileFromUsername(ipfsDomain: string, config: CommunityConfig, username: string): Promise<ProfileWithTokenId | null>
Retrieves a profile by username.
hasProfileAdminRole(config: CommunityConfig, address: string): Promise<boolean>
Checks if an address has profile admin role.
checkUsernameAvailability(config: CommunityConfig, username: string): Promise<boolean>
Checks if a username is available for registration.
Logs
Transaction log management and querying.
LogsService Class
Service for querying transaction logs with pagination and filtering.
import { LogsService } from "@citizenwallet/sdk";
const logsService = new LogsService(config);
// Get a specific log
const log = await logsService.getLog(tokenAddress, hash);
// Get logs with pagination and filtering
const logs = await logsService.getLogs(tokenAddress, topic, {
limit: 10,
offset: 0,
maxDate: "2024-01-01T00:00:00Z",
data: { key: "value" },
});
// Get all logs
const allLogs = await logsService.getAllLogs(tokenAddress, topic);
// Get new logs since a date
const newLogs = await logsService.getNewLogs(tokenAddress, topic, {
fromDate: "2024-01-01T00:00:00Z",
});Event Signatures
TRANSFER_EVENT_SIGNATURE- ERC20 transfer event signature
Bundler
Smart account transaction bundling and execution.
BundlerService Class
Service for creating and submitting user operations to the bundler.
import { BundlerService } from "@citizenwallet/sdk";
const bundler = new BundlerService(config);
// Send ERC20 tokens
const txHash = await bundler.sendERC20Token(
signer,
tokenAddress,
fromAddress,
toAddress,
amount,
description
);
// Mint ERC20 tokens
const txHash = await bundler.mintERC20Token(
signer,
tokenAddress,
fromAddress,
toAddress,
amount,
description
);
// Burn ERC20 tokens
const txHash = await bundler.burnFromERC20Token(
signer,
tokenAddress,
senderAddress,
fromAddress,
amount,
description
);
// Set profile
const txHash = await bundler.setProfile(
signer,
signerAccountAddress,
profileAccountAddress,
username,
ipfsHash
);
// Burn profile
const txHash = await bundler.burnProfile(
signer,
signerAccountAddress,
profileAccountAddress
);
// Grant role
const txHash = await bundler.grantRole(
signer,
tokenAddress,
senderAddress,
role,
accountAddress
);
// Revoke role
const txHash = await bundler.revokeRole(
signer,
tokenAddress,
senderAddress,
role,
accountAddress
);
// Execute custom call
const txHash = await bundler.call(
signer,
contractAddress,
senderAddress,
calldata,
value,
userOpData,
extraData
);IPFS
IPFS integration utilities.
downloadJsonFromIpfs<T>(ipfsDomain: string, uri: string): Promise<T>
Downloads and parses JSON data from IPFS.
Vouchers
Voucher creation and parsing for token distribution.
createVoucher(config: CommunityConfig, voucherName: string, voucherCreator: string, voucherSigner: BaseWallet): Promise<{voucherLink: string, voucherAccountAddress: string}>
Creates a voucher for token distribution.
parseVoucher(data: string): {voucher: Voucher, signer: BaseWallet}
Parses a voucher from a URL or data string.
Deep Links
QR code parsing and deep link generation.
generateLegacyReceiveLink(baseUrl: string, config: CommunityConfig, account: string, amount?: string, description?: string): string
Generates a legacy receive link for token transfers.
parseQRFormat(raw: string): QRFormat
Determines the format of a QR code or URI.
parseQRCode(raw: string): ParseQRData
Parses QR code data into structured format.
parseMessageFromReceiveLink(raw: string): string | null
Extracts message from a receive link.
Accounts
Account management and verification functions.
getENSAddress(mainnetRpcUrl: string, domain: string): Promise<string | null>
Resolves ENS domain to address.
getAccountAddress(config: CommunityConfig, address: string, salt?: bigint): Promise<string | null>
Gets the smart account address for a given owner and salt.
getAccountBalance(config: CommunityConfig, address: string): Promise<bigint | null>
Gets the token balance for an account.
verifyAccountOwnership(config: CommunityConfig, accountAddress: string, message: string, signature: string): Promise<boolean>
Verifies account ownership through signature validation.
isSafeOwner(config: CommunityConfig, accountAddress: string, ownerAddress: string): Promise<boolean>
Checks if an address is an owner of a Safe account.
Receive
Receive link generation.
generateReceiveLink(baseUrl: string, config: CommunityConfig, account: string, amount?: string, description?: string): string
Generates a receive link for token transfers.
Transactions
Transaction utilities.
waitForTxSuccess(config: CommunityConfig, txHash: string, timeout?: number): Promise<boolean>
Waits for a transaction to be confirmed and checks its success status.
Cards
Card management functions.
getCardAddress(config: CommunityConfig, hashedSerial: string, instanceId?: string): Promise<string | null>
Gets the card address for a given serial number and instance.
instanceOwner(config: CommunityConfig, instanceId?: string): Promise<string | null>
Gets the owner of a card instance.
Calldata
Smart contract call data generation.
tokenTransferCallData(to: string, value: bigint): Uint8Array
Generates calldata for ERC20 token transfers.
tokenMintCallData(to: string, value: bigint): Uint8Array
Generates calldata for ERC20 token minting.
createInstanceCallData(config: CommunityConfig, contracts: string[], instanceId?: string): Uint8Array
Generates calldata for creating card instances.
updateInstanceContractsCallData(config: CommunityConfig, contracts: string[], instanceId?: string): Uint8Array
Generates calldata for updating instance contracts.
updateWhitelistCallData(config: CommunityConfig, addresses: string[], instanceId?: string): Uint8Array
Generates calldata for updating whitelist.
callOnCardCallData(config: CommunityConfig, hashedSerial: string, to: string, value: bigint, data: Uint8Array, instanceId?: string): Uint8Array
Generates calldata for executing calls on cards.
addOwnerCallData(config: CommunityConfig, hashedSerial: string, newOwner: string, instanceId?: string): Uint8Array
Generates calldata for adding card owners.
generateCalldataLink(baseUrl: string, config: CommunityConfig, address: string, value: bigint, calldata: string): string
Generates a deep link with calldata for execution.
Event Topics
tokenTransferEventTopic- ERC20 transfer event topictokenTransferSingleEventTopic- ERC1155 transfer single event topicroleGrantedEventTopic- Role granted event topicroleRevokedEventTopic- Role revoked event topic
Utils
Crypto
Cryptographic utilities and role management.
isFunctionInABI(func: string, abi: any[]): boolean
Checks if a function exists in an ABI.
hasRole(tokenAddress: string, role: string, account: string, provider: JsonRpcProvider): Promise<boolean>
Checks if an account has a specific role.
Role Constants
MINTER_ROLE- ERC20 minter role hashPROFILE_ADMIN_ROLE- Profile admin role hash
Gzip
Compression utilities for voucher and deep link data.
compress(data: string): string- Compresses data using gzipdecompress(data: string): string- Decompresses gzipped data
Alias
Domain parsing utilities.
parseAliasFromDomain(domain: string, basePath: string): string
Extracts community alias from a domain.
Connect
Authentication and connection utilities.
generateConnectionMessage(accountAddress: string, expiryTimeStamp: string, redirectUrl?: string): string
Generates a connection message for signature authentication.
generateConnectedHeaders(signer: Signer, accountAddress: string, expiryTimeStamp: string, redirectUrl?: string): Promise<object>
Generates authentication headers for API requests.
createConnectedUrl(url: string, signer: Signer, accountAddress: string, expiryTimeStamp: string, redirectUrl?: string): Promise<string>
Creates a URL with authentication parameters.
verifyConnectedHeaders(config: CommunityConfig, headers: Headers): Promise<string | null>
Verifies authentication headers and returns the account address.
verifyConnectedUrl(config: CommunityConfig, options: {url?: string, params?: URLSearchParams}): Promise<string | null>
Verifies authentication parameters from a URL and returns the account address.
Session
Session management for secure interactions.
generateSessionSalt(params: {source: string, type: string}): string
Generates a unique salt for session identification.
generateSessionRequestHash(params: {community: CommunityConfig, sessionOwner: string, salt: string, expiry: number}): string
Generates a hash for session request verification.
generateSessionHash(params: {sessionRequestHash: string, challenge: number | string}): string
Generates the final session hash with challenge.
verifySessionRequest(params: {community: CommunityConfig, sessionOwner: string, source: string, type: string, expiry: number, signature: string}): boolean
Verifies a session request signature.
verifySessionConfirm(params: {sessionOwner: string, sessionHash: string, signedSessionHash: string}): boolean
Verifies a session confirmation signature.
requestSession(params: {community: CommunityConfig, signer: Wallet, sessionSalt: string, sessionRequestHash: string, signedSessionRequestHash: string, signedSessionHash: string, sessionExpiry: number}): Promise<string>
Submits a session request to the blockchain.
verifyIncomingSessionRequest(params: {community: CommunityConfig, signer: Wallet, sessionRequestHash: string, sessionHash: string}): Promise<boolean>
Verifies an incoming session request.
confirmSession(params: {community: CommunityConfig, signer: Wallet, sessionRequestHash: string, sessionHash: string, signedSessionHash: string}): Promise<string>
Confirms a session on the blockchain.
isSessionExpired(params: {community: CommunityConfig, account: string, owner: string}): Promise<boolean>
Checks if a session has expired.
getTwoFAAddress(params: {community: CommunityConfig, source: string, type: string}): Promise<string | null>
Gets the 2FA address for a session.
revokeSession(params: {community: CommunityConfig, signer: Wallet, account: string}): Promise<string | null>
Revokes an active session.
Token
Token metadata utilities.
getTokenDecimals(config: CommunityConfig): Promise<bigint | null>
Gets the decimal places of the primary token.
getTokenName(config: CommunityConfig): Promise<string | null>
Gets the name of the primary token.
getTokenSymbol(config: CommunityConfig): Promise<string | null>
Gets the symbol of the primary token.
getTokenMetadata(config: CommunityConfig): Promise<{decimals: bigint | null, name: string | null, symbol: string | null} | null>
Gets all metadata for the primary token.
Vouchers
A voucher is actually simply a random private key which is used to generate a Smart Account that we top up and send to someone with some metadata.
You are effectively creating an account, topping it up, describing what it is and sending that over to the other person.
Create a voucher
import { createVoucher } from "@citizenwallet/sdk";
const communityAlias = "bread"; // config.community.alias
const voucherName = "Voucher for X tokens";
const creatorAddress = "0x59D17ec3d96C52d4539eed43f33492679ae4aCf7"; // since the user who is redeeming will only see a transaction from the voucher to them, this allows displaying the original creator on the UI.
const signer = ethers.Wallet.createRandom(); // generate a random account which will be used for the voucher.
const voucher = await createVoucher(
config,
voucherName,
creatorAddress,
signer
);Example:
{
"voucherLink": "https://app.citizenwallet.xyz/#/?voucher=H4sIAEFF7WYAAw3JyQ3AMAgEwIoiLeYy5YDBJaT-5D3vemZEhHHS83INkWm5G4uo6MJkN4f_jFiEuhZnI3sHyJkaH_18VYRDAAAA¶ms=H4sIAEFF7WYAAw3LsRLCIAwA0L_p4qIkEDIwSC3_kUI4vdNyR6nn59vlbU_eL9nD2lXKlE9H6-H6s_y4kWYo7GZrClpg1YJQAZCNIxZFmStNknM7tnEWMItjghRNrQ6i95YpMSzI0Zv7SmhIgFOZNvloGLqPy7cd-an9D-Zqgw6DAAAA",
"voucherAccountAddress": "0x32E6973FB2ff63B88597F93E49B82Ab7427a39Fd"
}Parse a voucher
import { parseVoucher } from "@citizenwallet/sdk";
const parsed = parseVoucher(voucher.voucherLink);Example:
{
"voucher": {
"alias": "bread",
"creator": "0x59D17ec3d96C52d4539eed43f33492679ae4aCf7",
"account": "0x32E6973FB2ff63B88597F93E49B82Ab7427a39Fd",
"name": "test voucher"
},
"signer": {
"provider": null,
"address": "0x60fab84316061E5c7C2eD09a2c4Be454B6B1fC69"
}
}signer = type ethers.Wallet
Config
Every community and their currency has a configuration in a json format.
The SDK provides types for accessing properties as well as a class with helper functions.
Building (npm)
To build the SDK, run the following command in your terminal:
npm run buildThis will compile the TypeScript code to JavaScript.
Watching for Changes (npm)
To automatically recompile the SDK when a file changes, run the following command in your terminal:
npm run watchContributing
We welcome contributions! Please see our contributing guidelines for more details.
License
This project is licensed under the MIT license.
