TypeScript SDK
TypeScript helpers for Mosaic wallet transactions, quotes, metadata, and indexed reads.
@usemosiac/ts-sdk exports transaction builders. Each builder returns an unsigned WalletTx.
Install
npm install @usemosiac/ts-sdkpnpm add @usemosiac/ts-sdkyarn add @usemosiac/ts-sdkbun add @usemosiac/ts-sdkImport
import {
canonicalJson,
createMosaicApiClient,
createMosaicSdk,
metadataToDataUri,
quoteCreateAmount,
} from "@usemosiac/ts-sdk";Configure
const GIWA_SEPOLIA_CHAIN_ID = 91342;
const MOSAIC_ADDRESS = "0x7ebC4d9EfA037dFaAfBB80025A09B249eCFf4F84" as const;
const TEST_USDC_ADDRESS = "0x25ceeBa0a118DA5C346a5328D7cC5f26aa331d17" as const;
const sdk = createMosaicSdk({
chainId: GIWA_SEPOLIA_CHAIN_ID,
contractAddress: MOSAIC_ADDRESS,
usdcAddress: TEST_USDC_ADDRESS,
});Active values:
| Field | Value |
|---|---|
chainId | 91342 |
contractAddress | 0x7ebC4d9EfA037dFaAfBB80025A09B249eCFf4F84 |
usdcAddress | 0x25ceeBa0a118DA5C346a5328D7cC5f26aa331d17 |
Explicit configuration above is required for the active deployment and uses the package's public API.
Create Bounty
import { keccak256, stringToBytes } from "viem";
const metadata = {
version: 1,
title: "Find a reproducible bug",
brief: "Submit a minimal reproduction and a fix suggestion.",
};
const metadataHash = keccak256(stringToBytes(canonicalJson(metadata)));
const funding = quoteCreateAmount(50_000_000n);
const approve = sdk.approveUsdc(funding.totalAmount);
const create = sdk.createBounty({
metadataUri: metadataToDataUri(metadata),
metadataHash,
rewardAmount: funding.rewardAmount,
duration: 86_400,
});Send approve before create. The contract pulls reward plus post fee during createBounty.
Submit Work
const submit = sdk.submit({
bountyId: 1n,
metadataUri: "ar://submission-json",
metadataHash: "0x1111111111111111111111111111111111111111111111111111111111111111",
});The contract pulls the bounty submission bond during submit.
Dispute Work
const dispute = sdk.dispute({
submissionId: 4n,
metadataUri: "ar://dispute-json",
metadataHash: "0x2222222222222222222222222222222222222222222222222222222222222222",
});The contract pulls the dispute bond during dispute. The caller must be a whitelisted grout.
Transaction Result
Every transaction helper returns:
type WalletTx = {
chainId: number;
to: `0x${string}`;
data: `0x${string}`;
value: `0x${string}`;
};value is always 0x0.
Transaction Helpers
| Helper | Contract Call |
|---|---|
approveUsdc(amount) | USDC approve(contractAddress, amount) |
createBounty(input) | createBounty(string,bytes32,uint256,uint64) |
submit(input) | submit(uint256,string,bytes32) |
dispute(input) | dispute(uint256,string,bytes32) |
finalize(bountyId) | finalize(uint256) |
advanceReviewCursor(bountyId) | advanceReviewCursor(uint256) |
refundExpired(bountyId) | refundExpired(uint256) |
refundSubmissionBond(submissionId) | refundSubmissionBond(uint256) |
cancelResolvedDispute(challengeId) | cancelResolvedDispute(uint256) |
withdraw() | withdraw() |
withdrawTo(recipient) | withdrawTo(address) |
Read API Client
const api = createMosaicApiClient({ baseUrl: "https://api.example" });
const bounties = await api.listBounties();
const deployment = "chain_id=91342&contract_address=0x7ebC4d9EfA037dFaAfBB80025A09B249eCFf4F84";
const bounty = await fetch(`https://api.example/bounties/1?${deployment}`).then((response) => response.json());
const submissions = await fetch(`https://api.example/submissions?bounty_id=1&${deployment}`).then((response) => response.json());
const disputes = await fetch(`https://api.example/disputes?submission_id=1&${deployment}`).then((response) => response.json());| Method | HTTP Request |
|---|---|
listBounties() | GET /bounties |
getBounty(bountyId) | GET /bounties/{bountyId} |
listSubmissions() | GET /submissions |
listSubmissions(bountyId) | GET /submissions?bounty_id=... |
listDisputes() | GET /disputes |
listDisputes(submissionId) | GET /disputes?submission_id=... |
The client throws mortar request failed {status} when the HTTP response is not OK.
The published 0.1.0 TypeScript client does not qualify requests by deployment. Use direct Mortar requests with both chain_id and contract_address for collision-safe reads until 0.2.0 is published. Paginated and overview routes are documented in Reference.
Metadata Helpers
| Helper | Return |
|---|---|
canonicalJson(value) | JSON string with sorted object keys and no undefined fields. |
metadataToDataUri(metadata) | data:application/json,... URI containing canonical JSON. |
parseMetadataUri(uri) | Parsed inline JSON or null. |
quoteCreateAmount(rewardAmount, config?) | Reward, submission bond, post fee, and total poster funding. |
Validation Errors
invalid address: address must match0xplus 40 hex characters.bytes32 value must be 32 bytes: hash must be 32 bytes.number must be a safe uint: usebigintor a decimal string for large values.uint{bits} value out of range: unsigned integer exceeds the ABI type width.
