diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index 7582b79..2748911 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -29,89 +29,6 @@ const STACKS_ACCENT = "#fc6432"; const publicClient = createPublicClient({ chain: celo, transport: http() }); -interface ProcessedMembersResult { - members: string[]; - error?: string; -} - -function processCeloMembers(raw: string, creatorAddress?: string): ProcessedMembersResult { - if (!creatorAddress) { - return { members: [], error: "Wallet not connected" }; - } - - let list = raw - .split("\n") - .map((s) => s.trim()) - .filter(Boolean); - - // Validate format of input addresses - for (const m of list) { - if (!/^0x[a-fA-F0-9]{40}$/.test(m)) { - return { members: [], error: `Invalid Celo address format: "${m}"` }; - } - } - - const creatorClean = creatorAddress.toLowerCase(); - list = list.filter((m) => m.toLowerCase() !== creatorClean); - list.unshift(creatorAddress); - - // Check for duplicates - const lowercased = list.map((m) => m.toLowerCase()); - const unique = new Set(lowercased); - if (unique.size !== list.length) { - return { members: [], error: "Duplicate member addresses are not allowed" }; - } - - if (list.length < 2) { - return { members: [], error: "A circle must have at least 2 members (including yourself)" }; - } - - if (list.length > 10) { - return { members: [], error: "A circle can have a maximum of 10 members" }; - } - - return { members: list }; -} - -function processStacksMembers(raw: string, creatorAddress?: string): ProcessedMembersResult { - if (!creatorAddress) { - return { members: [], error: "Wallet not connected" }; - } - - let list = raw - .split("\n") - .map((s) => s.trim()) - .filter(Boolean); - - // Validate format of input addresses - for (const m of list) { - if (!/^S[PMT][0-9a-zA-Z]{37,42}$/.test(m)) { - return { members: [], error: `Invalid Stacks address format: "${m}"` }; - } - } - - const creatorClean = creatorAddress.toLowerCase(); - list = list.filter((m) => m.toLowerCase() !== creatorClean); - list.unshift(creatorAddress); - - // Check for duplicates - const lowercased = list.map((m) => m.toLowerCase()); - const unique = new Set(lowercased); - if (unique.size !== list.length) { - return { members: [], error: "Duplicate member addresses are not allowed" }; - } - - if (list.length < 2) { - return { members: [], error: "A circle must have at least 2 members (including yourself)" }; - } - - if (list.length > 10) { - return { members: [], error: "A circle can have a maximum of 10 members" }; - } - - return { members: list }; -} - export default function Home() { // --- Global State --- const [activeChain, setActiveChain] = useState<"celo" | "stacks">("celo"); @@ -143,7 +60,6 @@ export default function Home() { isOpen: boolean; title: string; details: { label: string; value: string }[]; - memberRotation?: string[]; estimatedFee: string; isLoadingFee: boolean; onConfirm: () => Promise | void; @@ -181,10 +97,14 @@ export default function Home() { const accent = activeChain === "celo" ? CELO_ACCENT : STACKS_ACCENT; // --- Celo Handlers --- - const handleCeloCreate = async (validatedMembers: string[]) => { + const handleCeloCreate = async () => { try { setCeloStatus("⏳ Submitting..."); const weiAmount = parseUnits(contributionCelo, 18); + const memberList = membersRaw + .split("\n") + .map((s) => s.trim()) + .filter(Boolean); const walletClient = createWalletClient({ chain: celo, transport: custom(window.ethereum as any), @@ -193,7 +113,7 @@ export default function Home() { address: SUSUCHAIN_CELO_ADDRESS, abi: SUSUCHAIN_CELO_ABI, functionName: "createCircle", - args: [circleName, weiAmount, BigInt(cycleDays), validatedMembers], + args: [circleName, weiAmount, BigInt(cycleDays), memberList], account: address as `0x${string}`, }); setCeloStatus(`✅ TX: ${hash}`); @@ -203,7 +123,7 @@ export default function Home() { chain: "celo", contractAddress: SUSUCHAIN_CELO_ADDRESS, functionName: "createCircle", - arguments: [circleName, contributionCelo, cycleDays, validatedMembers.join("\n")], + arguments: [circleName, contributionCelo, cycleDays, membersRaw], account: address || undefined, }); } @@ -299,12 +219,10 @@ export default function Home() { return; } - const res = processCeloMembers(membersRaw, address); - if (res.error) { - setCeloStatus(`❌ ${res.error}`); - return; - } - const validatedMembers = res.members; + const memberList = membersRaw + .split("\n") + .map((s) => s.trim()) + .filter(Boolean); setModalConfig({ isOpen: true, @@ -313,14 +231,13 @@ export default function Home() { { label: "Circle Name", value: circleName }, { label: "Contribution Amount", value: `${contributionCelo} CELO` }, { label: "Cycle Duration", value: `${cycleDays} days` }, - { label: "Total Members", value: `${validatedMembers.length} addresses` }, + { label: "Total Members", value: `${memberList.length} addresses` }, ], - memberRotation: validatedMembers, estimatedFee: "Estimating fee...", isLoadingFee: true, onConfirm: async () => { setModalConfig(null); - await handleCeloCreate(validatedMembers); + await handleCeloCreate(); }, }); @@ -330,7 +247,7 @@ export default function Home() { address: SUSUCHAIN_CELO_ADDRESS, abi: SUSUCHAIN_CELO_ABI, functionName: "createCircle", - args: [circleName, weiAmount, BigInt(cycleDays), validatedMembers], + args: [circleName, weiAmount, BigInt(cycleDays), memberList], account: address as `0x${string}`, }); const gasPrice = await publicClient.getGasPrice(); @@ -415,10 +332,14 @@ export default function Home() { }; // --- Stacks Handlers --- - const handleStacksCreate = (validatedMembers: string[]) => { + const handleStacksCreate = () => { try { const microSTX = Math.floor(parseFloat(sContribution) * 1_000_000); - callCreateCircle(sName, microSTX, validatedMembers, (data: any) => { + const memberList = sMembers + .split("\n") + .map((s) => s.trim()) + .filter(Boolean); + callCreateCircle(sName, microSTX, memberList, (data: any) => { setSStatus( `✅ TX: ${data.txId} — link: https://explorer.hiro.so/txid/${data.txId}` ); @@ -429,7 +350,7 @@ export default function Home() { chain: "stacks", contractAddress: STACKS_CONTRACT_ADDRESS, functionName: "create-circle", - arguments: [sName, sContribution, validatedMembers.join("\n")], + arguments: [sName, sContribution, sMembers], account: stacksAddress || undefined, }); } @@ -474,27 +395,23 @@ export default function Home() { setSStatus("❌ Please fill in all fields"); return; } - const res = processStacksMembers(sMembers, stacksAddress); - if (res.error) { - setSStatus(`❌ ${res.error}`); - return; - } - const validatedMembers = res.members; - + const memberList = sMembers + .split("\n") + .map((s) => s.trim()) + .filter(Boolean); setModalConfig({ isOpen: true, title: "Confirm Stacks circle creation", details: [ { label: "Circle Name", value: sName }, { label: "Contribution Amount", value: `${sContribution} STX` }, - { label: "Total Members", value: `${validatedMembers.length} addresses` }, + { label: "Total Members", value: `${memberList.length} addresses` }, ], - memberRotation: validatedMembers, estimatedFee: "0.001800 STX", isLoadingFee: false, onConfirm: () => { setModalConfig(null); - handleStacksCreate(validatedMembers); + handleStacksCreate(); }, }); }; @@ -1044,42 +961,6 @@ export default function Home() { ))} - {modalConfig.memberRotation && modalConfig.memberRotation.length > 0 && ( -
-
Rotation / Payout Order
-
- {modalConfig.memberRotation.map((member, idx) => { - const isCelo = activeChain === "celo"; - const accentColor = isCelo ? CELO_ACCENT : STACKS_ACCENT; - const badgeBg = isCelo ? "rgba(252, 255, 82, 0.1)" : "rgba(252, 100, 50, 0.1)"; - const badgeBorder = isCelo ? "rgba(252, 255, 82, 0.2)" : "rgba(252, 100, 50, 0.2)"; - const isCreator = idx === 0; - - return ( -
- {idx + 1}. - - {truncate(member)} - - {isCreator && ( - - Creator - - )} -
- ); - })} -
-
- )} -
Estimated Network Fee
@@ -1458,52 +1339,6 @@ const styles: Record = { cursor: "pointer", transition: "all 0.2s", }, - modalRotationSection: { - backgroundColor: "#1a1a1a", - border: "1px solid #222", - borderRadius: 8, - padding: 14, - marginBottom: 20, - }, - modalRotationTitle: { - fontSize: 11, - fontWeight: 700, - color: "#a3a3a3", - textTransform: "uppercase" as const, - letterSpacing: "0.05em", - marginTop: 0, - marginBottom: 10, - }, - modalRotationList: { - display: "flex", - flexDirection: "column" as const, - gap: 6, - }, - modalRotationItem: { - display: "flex", - alignItems: "center", - gap: 8, - fontSize: 13, - }, - modalRotationIndex: { - fontFamily: "monospace", - color: "#9ca3af", - fontWeight: 700, - width: 16, - }, - modalRotationAddr: { - fontFamily: "monospace", - color: "#fff", - flex: 1, - }, - modalRotationBadge: { - fontSize: 9, - fontWeight: 700, - textTransform: "uppercase" as const, - padding: "2px 6px", - borderRadius: 4, - border: "1px solid", - }, footer: { marginTop: "auto", paddingTop: 40, diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 41819dc..66c97c9 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -12,16 +12,12 @@ Install the SDK alongside its peer dependencies: npm install susuchain-sdk viem @stacks/network @stacks/transactions @stacks/connect ``` -> **Note:** `@stacks/connect` is an optional peer dependency — only required for browser wallet helpers. - ## Features - **Multi-Chain ABI & Addresses**: Instantly access Solidity ABIs and mainnet contract addresses for both Celo and Stacks. - **Stacks Browser Helpers**: Pre-packaged wallet triggers to easily call `create-circle`, `contribute`, and `trigger-payout` using the Leather wallet. - **Stacks Server-Side Builders**: Construct and sign Stacks transactions with a private key for backend or scripting environments. -- **Stacks Read-Only Helpers**: Query on-chain Stacks state (`get-circle`, `get-circle-count`, `has-member-paid`, `is-member`) from Node.js. -- **Celo Transaction Param Builders**: Generate ready-to-use contract call parameter objects for viem wallet clients (both read and write operations). -- **TypeScript Interfaces**: Fully typed option interfaces for all builders. +- **Celo Transaction Param Builders**: Generate ready-to-use contract call parameter objects for viem wallet clients. ## Usage @@ -65,7 +61,7 @@ async function getCircleDetails(circleId: number) { } ``` -### Celo Server-Side Transactions (Write) +### Celo Server-Side Transactions Build contract call parameters and pass them to a viem wallet client: @@ -95,57 +91,6 @@ const contributeParams = buildCeloContributeParams({ valueWei: 1000000000000000000n, }); const txHash = await wallet.writeContract(contributeParams); - -// Withdraw pending payouts -const withdrawParams = buildCeloWithdrawParams(); -await wallet.writeContract(withdrawParams); -``` - -### Celo Server-Side Read Operations - -Use param builders with a viem public client to query on-chain state: - -```typescript -import { createPublicClient, http } from 'viem'; -import { celo } from 'viem/chains'; -import { - buildCeloGetCircleParams, - buildCeloCircleCountParams, - buildCeloIsMemberParams, - buildCeloHasPaidParams, - buildCeloGetMemberCountParams, - buildCeloRoundBalanceParams, - buildCeloPendingWithdrawalsParams, -} from 'susuchain-sdk'; - -const client = createPublicClient({ chain: celo, transport: http() }); - -// Get total circle count -const count = await client.readContract(buildCeloCircleCountParams()); - -// Get circle details -const circle = await client.readContract(buildCeloGetCircleParams(0)); - -// Check membership -const isMember = await client.readContract( - buildCeloIsMemberParams({ circleId: 0, user: '0xAbc...' }) -); - -// Check payment status -const hasPaid = await client.readContract( - buildCeloHasPaidParams({ circleId: 0, round: 0, member: '0xAbc...' }) -); - -// Get member count -const memberCount = await client.readContract(buildCeloGetMemberCountParams(0)); - -// Get round balance -const balance = await client.readContract(buildCeloRoundBalanceParams(0)); - -// Check pending withdrawals -const pending = await client.readContract( - buildCeloPendingWithdrawalsParams('0xAbc...') -); ``` ### Stacks Integration (Leather Wallet) @@ -192,33 +137,6 @@ const result = await broadcastTx({ transaction: tx }); console.log('Broadcast result:', result); ``` -### Stacks Read-Only Queries - -Query on-chain Stacks state from server-side Node.js: - -```typescript -import { - readGetCircle, - readGetCircleCount, - readHasMemberPaid, - readIsMember, -} from 'susuchain-sdk'; - -const senderAddress = 'SP2T02XBVN9RAZ4360DSWF3JCG79B1QY2NR21RB0Q'; - -// Get circle details -const circle = await readGetCircle(0, senderAddress); - -// Get total circle count -const count = await readGetCircleCount(senderAddress); - -// Check if a member has paid -const hasPaid = await readHasMemberPaid(0, 0, 'SP3...', senderAddress); - -// Check membership -const isMember = await readIsMember(0, 'SP3...', senderAddress); -``` - ## Exported Constants ### Celo @@ -243,40 +161,13 @@ const isMember = await readIsMember(0, 'SP3...', senderAddress); - `buildTriggerPayoutTx(opts)`: Build and sign a `trigger-payout` transaction. - `broadcastTx(opts)`: Broadcast a signed transaction to the Stacks network. -### Read-Only Helpers (Stacks) -- `readGetCircle(circleId, senderAddress)`: Query circle details. -- `readGetCircleCount(senderAddress)`: Query total circle count. -- `readHasMemberPaid(circleId, round, member, senderAddress)`: Check payment status. -- `readIsMember(circleId, user, senderAddress)`: Check membership. - -### Parameter Builders — Write (Celo) +### Parameter Builders (Celo) - `buildCeloCreateCircleParams(opts)`: Returns viem-compatible params for `createCircle`. - `buildCeloContributeParams(opts)`: Returns viem-compatible params for `contribute`. -- `buildCeloWithdrawParams()`: Returns viem-compatible params for `withdraw`. - -### Parameter Builders — Read (Celo) -- `buildCeloGetCircleParams(circleId)`: Returns params for `getCircle`. -- `buildCeloIsMemberParams(opts)`: Returns params for `isMember`. -- `buildCeloGetMemberCountParams(circleId)`: Returns params for `getMemberCount`. -- `buildCeloHasPaidParams(opts)`: Returns params for `hasPaid`. -- `buildCeloCircleCountParams()`: Returns params for `circleCount`. -- `buildCeloRoundBalanceParams(circleId)`: Returns params for `roundBalance`. -- `buildCeloPendingWithdrawalsParams(account)`: Returns params for `pendingWithdrawals`. - -## Exported TypeScript Interfaces - -- `CreateCircleTxOptions`: Options for Stacks `buildCreateCircleTx`. -- `ContributeTxOptions`: Options for Stacks `buildContributeTx`. -- `TriggerPayoutTxOptions`: Options for Stacks `buildTriggerPayoutTx`. -- `BroadcastTxOptions`: Options for `broadcastTx`. -- `CeloCreateCircleOptions`: Options for `buildCeloCreateCircleParams`. -- `CeloContributeOptions`: Options for `buildCeloContributeParams`. -- `CeloHasPaidOptions`: Options for `buildCeloHasPaidParams`. -- `CeloIsMemberOptions`: Options for `buildCeloIsMemberParams`. ## Tracking -This release satisfies clean ES Modules and CommonJS packaging guidelines in alignment with issues #25 and #27. +This release satisfies clean ES Modules and CommonJS packaging guidelines in alignment with issue #27. ## License diff --git a/packages/sdk/src/abi.json b/packages/sdk/src/abi.json index c0ecc9f..157f23f 100644 --- a/packages/sdk/src/abi.json +++ b/packages/sdk/src/abi.json @@ -3,21 +3,6 @@ "contractName": "SusuChain", "sourceName": "contracts/SusuChain.sol", "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EnforcedPause", - "type": "error" - }, - { - "inputs": [], - "name": "ExpectedPause", - "type": "error" - }, { "anonymous": false, "inputs": [ @@ -43,25 +28,6 @@ "name": "CircleCreated", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "minAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxAmount", - "type": "uint256" - } - ], - "name": "ContributionLimitsUpdated", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -93,50 +59,6 @@ "name": "ContributionMade", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "circleId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "round", - "type": "uint256" - } - ], - "name": "PayoutFailed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -168,38 +90,6 @@ "name": "PayoutSent", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, { "inputs": [], "name": "circleCount", @@ -252,21 +142,6 @@ "internalType": "bool", "name": "active", "type": "bool" - }, - { - "internalType": "uint256", - "name": "roundDuration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gracePeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "penaltyFee", - "type": "uint256" } ], "stateMutability": "view", @@ -299,17 +174,7 @@ }, { "internalType": "uint256", - "name": "roundDurationDays", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gracePeriodDays", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "penaltyFee", + "name": "cycleDurationDays", "type": "uint256" }, { @@ -367,21 +232,6 @@ "internalType": "bool", "name": "active", "type": "bool" - }, - { - "internalType": "uint256", - "name": "roundDuration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gracePeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "penaltyFee", - "type": "uint256" } ], "stateMutability": "view", @@ -459,84 +309,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "maxContributionAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minContributionAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "pendingWithdrawals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -555,42 +327,10 @@ ], "stateMutability": "view", "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_minAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxAmount", - "type": "uint256" - } - ], - "name": "setContributionLimits", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" } ], - "bytecode": "0x6080604052348015600f57600080fd5b50600680546001600160a01b0319163317905566038d7ea4c6800060075569021e19e0c9bab240000060085561185b8061004a6000396000f3fe6080604052600436106101095760003560e01c80637d9e10f511610095578063c1cbbca711610064578063c1cbbca714610317578063c66388221461032a578063c67e04d81461034a578063cf0b11171461036a578063f3f437031461038057600080fd5b80637d9e10f5146102755780638456cb59146102955780638da5cb5b146102aa578063bc5e0f30146102e257600080fd5b80633f4ba83a116100dc5780633f4ba83a146101cc57806345d5149f146101e15780635c975abb146101f75780635ce9284f1461020f57806364ccecde1461023f57600080fd5b806319cc1ec41461010e5780632cd19e62146101375780632f33afb6146101645780633ccfd60b146101b5575b600080fd5b34801561011a57600080fd5b5061012460085481565b6040519081526020015b60405180910390f35b34801561014357600080fd5b5061012461015236600461121f565b60036020526000908152604090205481565b34801561017057600080fd5b506101a561017f366004611254565b600260209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161012e565b3480156101c157600080fd5b506101ca6103ad565b005b3480156101d857600080fd5b506101ca6104e3565b3480156101ed57600080fd5b5061012460075481565b34801561020357600080fd5b5060005460ff166101a5565b34801561021b57600080fd5b5061012461022a36600461121f565b60009081526001602052604090206003015490565b34801561024b57600080fd5b5061025f61025a36600461121f565b610517565b60405161012e9a999897969594939291906112cf565b34801561028157600080fd5b506101a5610290366004611378565b610685565b3480156102a157600080fd5b506101ca6106fa565b3480156102b657600080fd5b506006546102ca906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b3480156102ee57600080fd5b506103026102fd36600461121f565b61072c565b60405161012e999897969594939291906113a4565b6101ca61032536600461121f565b610801565b34801561033657600080fd5b506101ca6103453660046114c9565b610b48565b34801561035657600080fd5b506101ca6103653660046115b0565b610e4a565b34801561037657600080fd5b5061012460045481565b34801561038c57600080fd5b5061012461039b3660046115d2565b60056020526000908152604090205481565b6103b5610f0b565b336000908152600560205260409020548061040f5760405162461bcd60e51b8152602060048201526015602482015274139bc81c195b991a5b99c81dda5d1a191c985dd85b605a1b60448201526064015b60405180910390fd5b336000818152600560205260408082208290555190919083908381818185875af1925050503d8060008114610460576040519150601f19603f3d011682016040523d82523d6000602084013e610465565b606091505b50509050806104aa5760405162461bcd60e51b815260206004820152601160248201527015da5d1a191c985dd85b0819985a5b1959607a1b6044820152606401610406565b60405182815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a25050565b6006546001600160a01b0316331461050d5760405162461bcd60e51b8152600401610406906115f4565b610515610f2f565b565b606060008060606000806000806000806000600160008d81526020019081526020016000209050806000018160010154826002015483600301846004015485600501548660060160009054906101000a900460ff1687600701548860080154896009015489805461058790611639565b80601f01602080910402602001604051908101604052809291908181526020018280546105b390611639565b80156106005780601f106105d557610100808354040283529160200191610600565b820191906000526020600020905b8154815290600101906020018083116105e357829003601f168201915b505050505099508680548060200260200160405190810160405280929190818152602001828054801561065c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161063e575b505050505096509a509a509a509a509a509a509a509a509a509a50509193959799509193959799565b6000828152600160205260408120815b60038201548110156106ed57836001600160a01b03168260030182815481106106c0576106c0611673565b6000918252602090912001546001600160a01b0316036106e5576001925050506106f4565b600101610695565b5060009150505b92915050565b6006546001600160a01b031633146107245760405162461bcd60e51b8152600401610406906115f4565b610515610f81565b60016020526000908152604090208054819061074790611639565b80601f016020809104026020016040519081016040528092919081815260200182805461077390611639565b80156107c05780601f10610795576101008083540402835291602001916107c0565b820191906000526020600020905b8154815290600101906020018083116107a357829003601f168201915b50505060018401546002850154600486015460058701546006880154600789015460088a01546009909a015498999598949750929550909360ff9091169289565b610809610f0b565b6000818152600160205260409020600681015460ff166108625760405162461bcd60e51b8152602060048201526014602482015273436972636c65206973206e6f742061637469766560601b6044820152606401610406565b3460000361086e575050565b600081600701548260050154610884919061169f565b90506000826008015482610898919061169f565b4211905060008360010154905081156108bd5760098401546108ba908261169f565b90505b80341461090c5760405162461bcd60e51b815260206004820152601960248201527f57726f6e6720636f6e747269627574696f6e20616d6f756e74000000000000006044820152606401610406565b6000805b600386015481101561096657336001600160a01b031686600301828154811061093b5761093b611673565b6000918252602090912001546001600160a01b03160361095e5760019150610966565b600101610910565b50806109a35760405162461bcd60e51b815260206004820152600c60248201526b2737ba10309036b2b6b132b960a11b6044820152606401610406565b600086815260026020908152604080832060048901548452825280832033845290915290205460ff1615610a195760405162461bcd60e51b815260206004820152601760248201527f416c72656164792070616964207468697320726f756e640000000000000000006044820152606401610406565b60008681526002602090815260408083206004890154845282528083203384528252808320805460ff19166001179055888352600390915281208054349290610a6390849061169f565b90915550506004850154604080513481526020810192909252339188917ff9b7589b7a8d939b9da5dae90770378fe5fd7802be5d66432e85bedbdbfbcb7a910160405180910390a3600160005b6003870154811015610b2f57600088815260026020908152604080832060048b01548452909152812060038901805491929184908110610af257610af2611673565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16610b275760009150610b2f565b600101610ab0565b508015610b3f57610b3f87610fbe565b50505050505050565b610b50610f0b565b600281511015610ba25760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2032206d656d626572732072657175697265640000000000006044820152606401610406565b60005b8151811015610c7a576000610bbb82600161169f565b90505b8251811015610c7157828181518110610bd957610bd9611673565b60200260200101516001600160a01b0316838381518110610bfc57610bfc611673565b60200260200101516001600160a01b031603610c695760405162461bcd60e51b815260206004820152602660248201527f4475706c6963617465206d656d62657220616464726573736573206e6f7420616044820152651b1b1bddd95960d21b6064820152608401610406565b600101610bbe565b50600101610ba5565b50600754851015610cc45760405162461bcd60e51b8152602060048201526014602482015273436f6e747269627574696f6e20746f6f206c6f7760601b6044820152606401610406565b600854851115610d0e5760405162461bcd60e51b8152602060048201526015602482015274086dedce8e4d2c4eae8d2dedc40e8dede40d0d2ced605b1b6044820152606401610406565b6004805460009182610d1f836116b2565b909155506000818152600160205260409020909150610d3e888261171a565b50600081815260016020819052604090912001869055610d6185620151806117d9565b600082815260016020908152604090912060028101929092558351610d8c92600301918501906111a5565b506000818152600160208190526040822060048101929092554260058301556006909101805460ff19169091179055610dc885620151806117d9565b600082815260016020526040902060070155610de784620151806117d9565b600082815260016020526040908190206008810192909255600990910184905551339082907f6f657d36deb3b1aa2e949c5df40eac9d79359a73c2402cefa7aee870f9ceafc090610e39908b906117f0565b60405180910390a350505050505050565b6006546001600160a01b03163314610e745760405162461bcd60e51b8152600401610406906115f4565b80821115610ec45760405162461bcd60e51b815260206004820152601e60248201527f4d696e206c696d6974206d757374206265203c3d206d6178206c696d697400006044820152606401610406565b6007829055600881905560408051838152602081018390527f33aa92491b46a02a93d5a2523a688c5bb3f0192474ba74d63d506220094099ff910160405180910390a15050565b60005460ff16156105155760405163d93c066560e01b815260040160405180910390fd5b610f37611182565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610f89610f0b565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f643390565b6000818152600160205260408120600481015460038201805492939192610fe59084611803565b81548110610ff557610ff5611673565b60009182526020808320909101548683526003909152604082208054908390556004860180546001600160a01b0390931694509092611033836116b2565b9091555050426005850155600384015460048501540361105a5760068401805460ff191690555b6000826001600160a01b03168261c35090604051600060405180830381858888f193505050503d80600081146110ac576040519150601f19603f3d011682016040523d82523d6000602084013e6110b1565b606091505b5050905080156111065760408051838152602081018690526001600160a01b0385169188917fa66924c8a65f84761475175d1d8db947a42ff99992d9881649ceaec7045fe581910160405180910390a361117a565b6001600160a01b0383166000908152600560205260408120805484929061112e90849061169f565b909155505060408051838152602081018690526001600160a01b0385169188917f101f1a97913c28a4330dc8ff2f1f5251f4ef7008012d8f60bad8056958bf908b910160405180910390a35b505050505050565b60005460ff1661051557604051638dfc202b60e01b815260040160405180910390fd5b8280548282559060005260206000209081019282156111fa579160200282015b828111156111fa57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906111c5565b5061120692915061120a565b5090565b5b80821115611206576000815560010161120b565b60006020828403121561123157600080fd5b5035919050565b80356001600160a01b038116811461124f57600080fd5b919050565b60008060006060848603121561126957600080fd5b833592506020840135915061128060408501611238565b90509250925092565b6000815180845260005b818110156112af57602081850181015186830182015201611293565b506000602082860101526020601f19601f83011685010191505092915050565b610140815260006112e461014083018d611289565b8b60208401528a60408401528281036060840152808a5180835260208301915060208c01925060005b818110156113345783516001600160a01b031683526020938401939092019160010161130d565b505080925050508760808301528660a083015261135560c083018715159052565b8460e083015283610100830152826101208301529b9a5050505050505050505050565b6000806040838503121561138b57600080fd5b8235915061139b60208401611238565b90509250929050565b610120815260006113b961012083018c611289565b602083019a909a525060408101979097526060870195909552608086019390935290151560a085015260c084015260e083015261010090910152919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611437576114376113f8565b604052919050565b600082601f83011261145057600080fd5b813567ffffffffffffffff81111561146a5761146a6113f8565b8060051b61147a6020820161140e565b9182526020818501810192908101908684111561149657600080fd5b6020860192505b838310156114bf576114ae83611238565b82526020928301929091019061149d565b9695505050505050565b60008060008060008060c087890312156114e257600080fd5b863567ffffffffffffffff8111156114f957600080fd5b8701601f8101891361150a57600080fd5b803567ffffffffffffffff811115611524576115246113f8565b611537601f8201601f191660200161140e565b8181528a602083850101111561154c57600080fd5b8160208401602083013760006020928201830152975088013595505060408701359350606087013592506080870135915060a087013567ffffffffffffffff81111561159757600080fd5b6115a389828a0161143f565b9150509295509295509295565b600080604083850312156115c357600080fd5b50508035926020909101359150565b6000602082840312156115e457600080fd5b6115ed82611238565b9392505050565b60208082526025908201527f4f6e6c7920746865206f776e65722063616e2063616c6c20746869732066756e60408201526431ba34b7b760d91b606082015260800190565b600181811c9082168061164d57607f821691505b60208210810361166d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156106f4576106f4611689565b6000600182016116c4576116c4611689565b5060010190565b601f82111561171557806000526020600020601f840160051c810160208510156116f25750805b601f840160051c820191505b8181101561171257600081556001016116fe565b50505b505050565b815167ffffffffffffffff811115611734576117346113f8565b611748816117428454611639565b846116cb565b6020601f82116001811461177c57600083156117645750848201515b600019600385901b1c1916600184901b178455611712565b600084815260208120601f198516915b828110156117ac578785015182556020948501946001909201910161178c565b50848210156117ca5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b80820281158282048414176106f4576106f4611689565b6020815260006115ed6020830184611289565b60008261182057634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212203694871b9ba7b69c480be81f93e437b95de98dc4c9b459f9bcfd28034ee8b9a864736f6c634300081c0033", - "deployedBytecode": "0x6080604052600436106101095760003560e01c80637d9e10f511610095578063c1cbbca711610064578063c1cbbca714610317578063c66388221461032a578063c67e04d81461034a578063cf0b11171461036a578063f3f437031461038057600080fd5b80637d9e10f5146102755780638456cb59146102955780638da5cb5b146102aa578063bc5e0f30146102e257600080fd5b80633f4ba83a116100dc5780633f4ba83a146101cc57806345d5149f146101e15780635c975abb146101f75780635ce9284f1461020f57806364ccecde1461023f57600080fd5b806319cc1ec41461010e5780632cd19e62146101375780632f33afb6146101645780633ccfd60b146101b5575b600080fd5b34801561011a57600080fd5b5061012460085481565b6040519081526020015b60405180910390f35b34801561014357600080fd5b5061012461015236600461121f565b60036020526000908152604090205481565b34801561017057600080fd5b506101a561017f366004611254565b600260209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161012e565b3480156101c157600080fd5b506101ca6103ad565b005b3480156101d857600080fd5b506101ca6104e3565b3480156101ed57600080fd5b5061012460075481565b34801561020357600080fd5b5060005460ff166101a5565b34801561021b57600080fd5b5061012461022a36600461121f565b60009081526001602052604090206003015490565b34801561024b57600080fd5b5061025f61025a36600461121f565b610517565b60405161012e9a999897969594939291906112cf565b34801561028157600080fd5b506101a5610290366004611378565b610685565b3480156102a157600080fd5b506101ca6106fa565b3480156102b657600080fd5b506006546102ca906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b3480156102ee57600080fd5b506103026102fd36600461121f565b61072c565b60405161012e999897969594939291906113a4565b6101ca61032536600461121f565b610801565b34801561033657600080fd5b506101ca6103453660046114c9565b610b48565b34801561035657600080fd5b506101ca6103653660046115b0565b610e4a565b34801561037657600080fd5b5061012460045481565b34801561038c57600080fd5b5061012461039b3660046115d2565b60056020526000908152604090205481565b6103b5610f0b565b336000908152600560205260409020548061040f5760405162461bcd60e51b8152602060048201526015602482015274139bc81c195b991a5b99c81dda5d1a191c985dd85b605a1b60448201526064015b60405180910390fd5b336000818152600560205260408082208290555190919083908381818185875af1925050503d8060008114610460576040519150601f19603f3d011682016040523d82523d6000602084013e610465565b606091505b50509050806104aa5760405162461bcd60e51b815260206004820152601160248201527015da5d1a191c985dd85b0819985a5b1959607a1b6044820152606401610406565b60405182815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a25050565b6006546001600160a01b0316331461050d5760405162461bcd60e51b8152600401610406906115f4565b610515610f2f565b565b606060008060606000806000806000806000600160008d81526020019081526020016000209050806000018160010154826002015483600301846004015485600501548660060160009054906101000a900460ff1687600701548860080154896009015489805461058790611639565b80601f01602080910402602001604051908101604052809291908181526020018280546105b390611639565b80156106005780601f106105d557610100808354040283529160200191610600565b820191906000526020600020905b8154815290600101906020018083116105e357829003601f168201915b505050505099508680548060200260200160405190810160405280929190818152602001828054801561065c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161063e575b505050505096509a509a509a509a509a509a509a509a509a509a50509193959799509193959799565b6000828152600160205260408120815b60038201548110156106ed57836001600160a01b03168260030182815481106106c0576106c0611673565b6000918252602090912001546001600160a01b0316036106e5576001925050506106f4565b600101610695565b5060009150505b92915050565b6006546001600160a01b031633146107245760405162461bcd60e51b8152600401610406906115f4565b610515610f81565b60016020526000908152604090208054819061074790611639565b80601f016020809104026020016040519081016040528092919081815260200182805461077390611639565b80156107c05780601f10610795576101008083540402835291602001916107c0565b820191906000526020600020905b8154815290600101906020018083116107a357829003601f168201915b50505060018401546002850154600486015460058701546006880154600789015460088a01546009909a015498999598949750929550909360ff9091169289565b610809610f0b565b6000818152600160205260409020600681015460ff166108625760405162461bcd60e51b8152602060048201526014602482015273436972636c65206973206e6f742061637469766560601b6044820152606401610406565b3460000361086e575050565b600081600701548260050154610884919061169f565b90506000826008015482610898919061169f565b4211905060008360010154905081156108bd5760098401546108ba908261169f565b90505b80341461090c5760405162461bcd60e51b815260206004820152601960248201527f57726f6e6720636f6e747269627574696f6e20616d6f756e74000000000000006044820152606401610406565b6000805b600386015481101561096657336001600160a01b031686600301828154811061093b5761093b611673565b6000918252602090912001546001600160a01b03160361095e5760019150610966565b600101610910565b50806109a35760405162461bcd60e51b815260206004820152600c60248201526b2737ba10309036b2b6b132b960a11b6044820152606401610406565b600086815260026020908152604080832060048901548452825280832033845290915290205460ff1615610a195760405162461bcd60e51b815260206004820152601760248201527f416c72656164792070616964207468697320726f756e640000000000000000006044820152606401610406565b60008681526002602090815260408083206004890154845282528083203384528252808320805460ff19166001179055888352600390915281208054349290610a6390849061169f565b90915550506004850154604080513481526020810192909252339188917ff9b7589b7a8d939b9da5dae90770378fe5fd7802be5d66432e85bedbdbfbcb7a910160405180910390a3600160005b6003870154811015610b2f57600088815260026020908152604080832060048b01548452909152812060038901805491929184908110610af257610af2611673565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16610b275760009150610b2f565b600101610ab0565b508015610b3f57610b3f87610fbe565b50505050505050565b610b50610f0b565b600281511015610ba25760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2032206d656d626572732072657175697265640000000000006044820152606401610406565b60005b8151811015610c7a576000610bbb82600161169f565b90505b8251811015610c7157828181518110610bd957610bd9611673565b60200260200101516001600160a01b0316838381518110610bfc57610bfc611673565b60200260200101516001600160a01b031603610c695760405162461bcd60e51b815260206004820152602660248201527f4475706c6963617465206d656d62657220616464726573736573206e6f7420616044820152651b1b1bddd95960d21b6064820152608401610406565b600101610bbe565b50600101610ba5565b50600754851015610cc45760405162461bcd60e51b8152602060048201526014602482015273436f6e747269627574696f6e20746f6f206c6f7760601b6044820152606401610406565b600854851115610d0e5760405162461bcd60e51b8152602060048201526015602482015274086dedce8e4d2c4eae8d2dedc40e8dede40d0d2ced605b1b6044820152606401610406565b6004805460009182610d1f836116b2565b909155506000818152600160205260409020909150610d3e888261171a565b50600081815260016020819052604090912001869055610d6185620151806117d9565b600082815260016020908152604090912060028101929092558351610d8c92600301918501906111a5565b506000818152600160208190526040822060048101929092554260058301556006909101805460ff19169091179055610dc885620151806117d9565b600082815260016020526040902060070155610de784620151806117d9565b600082815260016020526040908190206008810192909255600990910184905551339082907f6f657d36deb3b1aa2e949c5df40eac9d79359a73c2402cefa7aee870f9ceafc090610e39908b906117f0565b60405180910390a350505050505050565b6006546001600160a01b03163314610e745760405162461bcd60e51b8152600401610406906115f4565b80821115610ec45760405162461bcd60e51b815260206004820152601e60248201527f4d696e206c696d6974206d757374206265203c3d206d6178206c696d697400006044820152606401610406565b6007829055600881905560408051838152602081018390527f33aa92491b46a02a93d5a2523a688c5bb3f0192474ba74d63d506220094099ff910160405180910390a15050565b60005460ff16156105155760405163d93c066560e01b815260040160405180910390fd5b610f37611182565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610f89610f0b565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f643390565b6000818152600160205260408120600481015460038201805492939192610fe59084611803565b81548110610ff557610ff5611673565b60009182526020808320909101548683526003909152604082208054908390556004860180546001600160a01b0390931694509092611033836116b2565b9091555050426005850155600384015460048501540361105a5760068401805460ff191690555b6000826001600160a01b03168261c35090604051600060405180830381858888f193505050503d80600081146110ac576040519150601f19603f3d011682016040523d82523d6000602084013e6110b1565b606091505b5050905080156111065760408051838152602081018690526001600160a01b0385169188917fa66924c8a65f84761475175d1d8db947a42ff99992d9881649ceaec7045fe581910160405180910390a361117a565b6001600160a01b0383166000908152600560205260408120805484929061112e90849061169f565b909155505060408051838152602081018690526001600160a01b0385169188917f101f1a97913c28a4330dc8ff2f1f5251f4ef7008012d8f60bad8056958bf908b910160405180910390a35b505050505050565b60005460ff1661051557604051638dfc202b60e01b815260040160405180910390fd5b8280548282559060005260206000209081019282156111fa579160200282015b828111156111fa57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906111c5565b5061120692915061120a565b5090565b5b80821115611206576000815560010161120b565b60006020828403121561123157600080fd5b5035919050565b80356001600160a01b038116811461124f57600080fd5b919050565b60008060006060848603121561126957600080fd5b833592506020840135915061128060408501611238565b90509250925092565b6000815180845260005b818110156112af57602081850181015186830182015201611293565b506000602082860101526020601f19601f83011685010191505092915050565b610140815260006112e461014083018d611289565b8b60208401528a60408401528281036060840152808a5180835260208301915060208c01925060005b818110156113345783516001600160a01b031683526020938401939092019160010161130d565b505080925050508760808301528660a083015261135560c083018715159052565b8460e083015283610100830152826101208301529b9a5050505050505050505050565b6000806040838503121561138b57600080fd5b8235915061139b60208401611238565b90509250929050565b610120815260006113b961012083018c611289565b602083019a909a525060408101979097526060870195909552608086019390935290151560a085015260c084015260e083015261010090910152919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611437576114376113f8565b604052919050565b600082601f83011261145057600080fd5b813567ffffffffffffffff81111561146a5761146a6113f8565b8060051b61147a6020820161140e565b9182526020818501810192908101908684111561149657600080fd5b6020860192505b838310156114bf576114ae83611238565b82526020928301929091019061149d565b9695505050505050565b60008060008060008060c087890312156114e257600080fd5b863567ffffffffffffffff8111156114f957600080fd5b8701601f8101891361150a57600080fd5b803567ffffffffffffffff811115611524576115246113f8565b611537601f8201601f191660200161140e565b8181528a602083850101111561154c57600080fd5b8160208401602083013760006020928201830152975088013595505060408701359350606087013592506080870135915060a087013567ffffffffffffffff81111561159757600080fd5b6115a389828a0161143f565b9150509295509295509295565b600080604083850312156115c357600080fd5b50508035926020909101359150565b6000602082840312156115e457600080fd5b6115ed82611238565b9392505050565b60208082526025908201527f4f6e6c7920746865206f776e65722063616e2063616c6c20746869732066756e60408201526431ba34b7b760d91b606082015260800190565b600181811c9082168061164d57607f821691505b60208210810361166d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156106f4576106f4611689565b6000600182016116c4576116c4611689565b5060010190565b601f82111561171557806000526020600020601f840160051c810160208510156116f25750805b601f840160051c820191505b8181101561171257600081556001016116fe565b50505b505050565b815167ffffffffffffffff811115611734576117346113f8565b611748816117428454611639565b846116cb565b6020601f82116001811461177c57600083156117645750848201515b600019600385901b1c1916600184901b178455611712565b600084815260208120601f198516915b828110156117ac578785015182556020948501946001909201910161178c565b50848210156117ca5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b80820281158282048414176106f4576106f4611689565b6020815260006115ed6020830184611289565b60008261182057634e487b7160e01b600052601260045260246000fd5b50069056fea26469706673582212203694871b9ba7b69c480be81f93e437b95de98dc4c9b459f9bcfd28034ee8b9a864736f6c634300081c0033", + "bytecode": "0x6080604052348015600f57600080fd5b506110978061001f6000396000f3fe6080604052600436106100865760003560e01c80637d9e10f5116100595780637d9e10f51461017f578063bc5e0f301461019f578063c1cbbca7146101d1578063c45d2852146101e6578063cf0b11171461020657600080fd5b80632cd19e621461008b5780632f33afb6146100cb5780635ce9284f1461011c57806364ccecde1461014c575b600080fd5b34801561009757600080fd5b506100b86100a6366004610b1e565b60026020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156100d757600080fd5b5061010c6100e6366004610b53565b600160209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016100c2565b34801561012857600080fd5b506100b8610137366004610b1e565b60009081526020819052604090206003015490565b34801561015857600080fd5b5061016c610167366004610b1e565b61021c565b6040516100c29796959493929190610bce565b34801561018b57600080fd5b5061010c61019a366004610c5e565b61036d565b3480156101ab57600080fd5b506101bf6101ba366004610b1e565b6103e2565b6040516100c296959493929190610c8a565b6101e46101df366004610b1e565b6104a2565b005b3480156101f257600080fd5b506101e4610201366004610d99565b61078c565b34801561021257600080fd5b506100b860035481565b606060008060606000806000806000808a81526020019081526020016000209050806000018160010154826002015483600301846004015485600501548660060160009054906101000a900460ff1686805461027790610e6e565b80601f01602080910402602001604051908101604052809291908181526020018280546102a390610e6e565b80156102f05780601f106102c5576101008083540402835291602001916102f0565b820191906000526020600020905b8154815290600101906020018083116102d357829003601f168201915b505050505096508380548060200260200160405190810160405280929190818152602001828054801561034c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161032e575b50505050509350975097509750975097509750975050919395979092949650565b6000828152602081905260408120815b60038201548110156103d557836001600160a01b03168260030182815481106103a8576103a8610ea8565b6000918252602090912001546001600160a01b0316036103cd576001925050506103dc565b60010161037d565b5060009150505b92915050565b6000602081905290815260409020805481906103fd90610e6e565b80601f016020809104026020016040519081016040528092919081815260200182805461042990610e6e565b80156104765780601f1061044b57610100808354040283529160200191610476565b820191906000526020600020905b81548152906001019060200180831161045957829003601f168201915b505050600184015460028501546004860154600587015460069097015495969295919450925060ff1686565b6000818152602081905260409020600681015460ff166105005760405162461bcd60e51b8152602060048201526014602482015273436972636c65206973206e6f742061637469766560601b60448201526064015b60405180910390fd5b806001015434146105535760405162461bcd60e51b815260206004820152601960248201527f57726f6e6720636f6e747269627574696f6e20616d6f756e740000000000000060448201526064016104f7565b6000805b60038301548110156105ad57336001600160a01b031683600301828154811061058257610582610ea8565b6000918252602090912001546001600160a01b0316036105a557600191506105ad565b600101610557565b50806105ea5760405162461bcd60e51b815260206004820152600c60248201526b2737ba10309036b2b6b132b960a11b60448201526064016104f7565b600083815260016020908152604080832060048601548452825280832033845290915290205460ff16156106605760405162461bcd60e51b815260206004820152601760248201527f416c72656164792070616964207468697320726f756e6400000000000000000060448201526064016104f7565b60008381526001602081815260408084206004870154855282528084203385528252808420805460ff191690931790925585835260029052812080543492906106aa908490610ed4565b90915550506004820154604080513481526020810192909252339185917ff9b7589b7a8d939b9da5dae90770378fe5fd7802be5d66432e85bedbdbfbcb7a910160405180910390a3600160005b60038401548110156107765760008581526001602090815260408083206004880154845290915281206003860180549192918490811061073957610739610ea8565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661076e5760009150610776565b6001016106f7565b5080156107865761078684610927565b50505050565b6002815110156107de5760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2032206d656d6265727320726571756972656400000000000060448201526064016104f7565b6000831161083d5760405162461bcd60e51b815260206004820152602660248201527f436f6e747269627574696f6e206d7573742062652067726561746572207468616044820152656e207a65726f60d01b60648201526084016104f7565b600380546000918261084e83610ee7565b90915550600081815260208190526040902090915061086d8682610f4f565b50600081815260208190526040902060010184905561088f836201518061100e565b600082815260208181526040909120600281019290925583516108b89260030191850190610aa4565b5060008181526020819052604080822060048101929092554260058301556006909101805460ff1916600117905551339082907f6f657d36deb3b1aa2e949c5df40eac9d79359a73c2402cefa7aee870f9ceafc090610918908990611025565b60405180910390a35050505050565b600081815260208190526040812060048101546003820180549293919261094e908461103f565b8154811061095e5761095e610ea8565b60009182526020808320909101548683526002909152604082208054908390556004860180546001600160a01b039093169450909261099c83610ee7565b909155505042600585015560038401546004850154036109c35760068401805460ff191690555b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a10576040519150601f19603f3d011682016040523d82523d6000602084013e610a15565b606091505b5050905080610a565760405162461bcd60e51b815260206004820152600d60248201526c14185e5bdd5d0819985a5b1959609a1b60448201526064016104f7565b60408051838152602081018690526001600160a01b0385169188917fa66924c8a65f84761475175d1d8db947a42ff99992d9881649ceaec7045fe581910160405180910390a3505050505050565b828054828255906000526020600020908101928215610af9579160200282015b82811115610af957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190610ac4565b50610b05929150610b09565b5090565b5b80821115610b055760008155600101610b0a565b600060208284031215610b3057600080fd5b5035919050565b80356001600160a01b0381168114610b4e57600080fd5b919050565b600080600060608486031215610b6857600080fd5b8335925060208401359150610b7f60408501610b37565b90509250925092565b6000815180845260005b81811015610bae57602081850181015186830182015201610b92565b506000602082860101526020601f19601f83011685010191505092915050565b60e081526000610be160e083018a610b88565b886020840152876040840152828103606084015280875180835260208301915060208901925060005b81811015610c315783516001600160a01b0316835260209384019390920191600101610c0a565b505080925050508460808301528360a0830152610c5260c083018415159052565b98975050505050505050565b60008060408385031215610c7157600080fd5b82359150610c8160208401610b37565b90509250929050565b60c081526000610c9d60c0830189610b88565b602083019790975250604081019490945260608401929092526080830152151560a090910152919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610d0757610d07610cc8565b604052919050565b600082601f830112610d2057600080fd5b813567ffffffffffffffff811115610d3a57610d3a610cc8565b8060051b610d4a60208201610cde565b91825260208185018101929081019086841115610d6657600080fd5b6020860192505b83831015610d8f57610d7e83610b37565b825260209283019290910190610d6d565b9695505050505050565b60008060008060808587031215610daf57600080fd5b843567ffffffffffffffff811115610dc657600080fd5b8501601f81018713610dd757600080fd5b803567ffffffffffffffff811115610df157610df1610cc8565b610e04601f8201601f1916602001610cde565b818152886020838501011115610e1957600080fd5b8160208401602083013760006020928201830152955086013593505060408501359150606085013567ffffffffffffffff811115610e5657600080fd5b610e6287828801610d0f565b91505092959194509250565b600181811c90821680610e8257607f821691505b602082108103610ea257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156103dc576103dc610ebe565b600060018201610ef957610ef9610ebe565b5060010190565b601f821115610f4a57806000526020600020601f840160051c81016020851015610f275750805b601f840160051c820191505b81811015610f475760008155600101610f33565b50505b505050565b815167ffffffffffffffff811115610f6957610f69610cc8565b610f7d81610f778454610e6e565b84610f00565b6020601f821160018114610fb15760008315610f995750848201515b600019600385901b1c1916600184901b178455610f47565b600084815260208120601f198516915b82811015610fe15787850151825560209485019460019092019101610fc1565b5084821015610fff5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b80820281158282048414176103dc576103dc610ebe565b6020815260006110386020830184610b88565b9392505050565b60008261105c57634e487b7160e01b600052601260045260246000fd5b50069056fea264697066735822122085fc015faf93e710b19c708ec8505a717e697a3d02dbdae260bdc314fc47b22364736f6c634300081c0033", + "deployedBytecode": "0x6080604052600436106100865760003560e01c80637d9e10f5116100595780637d9e10f51461017f578063bc5e0f301461019f578063c1cbbca7146101d1578063c45d2852146101e6578063cf0b11171461020657600080fd5b80632cd19e621461008b5780632f33afb6146100cb5780635ce9284f1461011c57806364ccecde1461014c575b600080fd5b34801561009757600080fd5b506100b86100a6366004610b1e565b60026020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156100d757600080fd5b5061010c6100e6366004610b53565b600160209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016100c2565b34801561012857600080fd5b506100b8610137366004610b1e565b60009081526020819052604090206003015490565b34801561015857600080fd5b5061016c610167366004610b1e565b61021c565b6040516100c29796959493929190610bce565b34801561018b57600080fd5b5061010c61019a366004610c5e565b61036d565b3480156101ab57600080fd5b506101bf6101ba366004610b1e565b6103e2565b6040516100c296959493929190610c8a565b6101e46101df366004610b1e565b6104a2565b005b3480156101f257600080fd5b506101e4610201366004610d99565b61078c565b34801561021257600080fd5b506100b860035481565b606060008060606000806000806000808a81526020019081526020016000209050806000018160010154826002015483600301846004015485600501548660060160009054906101000a900460ff1686805461027790610e6e565b80601f01602080910402602001604051908101604052809291908181526020018280546102a390610e6e565b80156102f05780601f106102c5576101008083540402835291602001916102f0565b820191906000526020600020905b8154815290600101906020018083116102d357829003601f168201915b505050505096508380548060200260200160405190810160405280929190818152602001828054801561034c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161032e575b50505050509350975097509750975097509750975050919395979092949650565b6000828152602081905260408120815b60038201548110156103d557836001600160a01b03168260030182815481106103a8576103a8610ea8565b6000918252602090912001546001600160a01b0316036103cd576001925050506103dc565b60010161037d565b5060009150505b92915050565b6000602081905290815260409020805481906103fd90610e6e565b80601f016020809104026020016040519081016040528092919081815260200182805461042990610e6e565b80156104765780601f1061044b57610100808354040283529160200191610476565b820191906000526020600020905b81548152906001019060200180831161045957829003601f168201915b505050600184015460028501546004860154600587015460069097015495969295919450925060ff1686565b6000818152602081905260409020600681015460ff166105005760405162461bcd60e51b8152602060048201526014602482015273436972636c65206973206e6f742061637469766560601b60448201526064015b60405180910390fd5b806001015434146105535760405162461bcd60e51b815260206004820152601960248201527f57726f6e6720636f6e747269627574696f6e20616d6f756e740000000000000060448201526064016104f7565b6000805b60038301548110156105ad57336001600160a01b031683600301828154811061058257610582610ea8565b6000918252602090912001546001600160a01b0316036105a557600191506105ad565b600101610557565b50806105ea5760405162461bcd60e51b815260206004820152600c60248201526b2737ba10309036b2b6b132b960a11b60448201526064016104f7565b600083815260016020908152604080832060048601548452825280832033845290915290205460ff16156106605760405162461bcd60e51b815260206004820152601760248201527f416c72656164792070616964207468697320726f756e6400000000000000000060448201526064016104f7565b60008381526001602081815260408084206004870154855282528084203385528252808420805460ff191690931790925585835260029052812080543492906106aa908490610ed4565b90915550506004820154604080513481526020810192909252339185917ff9b7589b7a8d939b9da5dae90770378fe5fd7802be5d66432e85bedbdbfbcb7a910160405180910390a3600160005b60038401548110156107765760008581526001602090815260408083206004880154845290915281206003860180549192918490811061073957610739610ea8565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661076e5760009150610776565b6001016106f7565b5080156107865761078684610927565b50505050565b6002815110156107de5760405162461bcd60e51b815260206004820152601a60248201527f4d696e696d756d2032206d656d6265727320726571756972656400000000000060448201526064016104f7565b6000831161083d5760405162461bcd60e51b815260206004820152602660248201527f436f6e747269627574696f6e206d7573742062652067726561746572207468616044820152656e207a65726f60d01b60648201526084016104f7565b600380546000918261084e83610ee7565b90915550600081815260208190526040902090915061086d8682610f4f565b50600081815260208190526040902060010184905561088f836201518061100e565b600082815260208181526040909120600281019290925583516108b89260030191850190610aa4565b5060008181526020819052604080822060048101929092554260058301556006909101805460ff1916600117905551339082907f6f657d36deb3b1aa2e949c5df40eac9d79359a73c2402cefa7aee870f9ceafc090610918908990611025565b60405180910390a35050505050565b600081815260208190526040812060048101546003820180549293919261094e908461103f565b8154811061095e5761095e610ea8565b60009182526020808320909101548683526002909152604082208054908390556004860180546001600160a01b039093169450909261099c83610ee7565b909155505042600585015560038401546004850154036109c35760068401805460ff191690555b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a10576040519150601f19603f3d011682016040523d82523d6000602084013e610a15565b606091505b5050905080610a565760405162461bcd60e51b815260206004820152600d60248201526c14185e5bdd5d0819985a5b1959609a1b60448201526064016104f7565b60408051838152602081018690526001600160a01b0385169188917fa66924c8a65f84761475175d1d8db947a42ff99992d9881649ceaec7045fe581910160405180910390a3505050505050565b828054828255906000526020600020908101928215610af9579160200282015b82811115610af957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190610ac4565b50610b05929150610b09565b5090565b5b80821115610b055760008155600101610b0a565b600060208284031215610b3057600080fd5b5035919050565b80356001600160a01b0381168114610b4e57600080fd5b919050565b600080600060608486031215610b6857600080fd5b8335925060208401359150610b7f60408501610b37565b90509250925092565b6000815180845260005b81811015610bae57602081850181015186830182015201610b92565b506000602082860101526020601f19601f83011685010191505092915050565b60e081526000610be160e083018a610b88565b886020840152876040840152828103606084015280875180835260208301915060208901925060005b81811015610c315783516001600160a01b0316835260209384019390920191600101610c0a565b505080925050508460808301528360a0830152610c5260c083018415159052565b98975050505050505050565b60008060408385031215610c7157600080fd5b82359150610c8160208401610b37565b90509250929050565b60c081526000610c9d60c0830189610b88565b602083019790975250604081019490945260608401929092526080830152151560a090910152919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610d0757610d07610cc8565b604052919050565b600082601f830112610d2057600080fd5b813567ffffffffffffffff811115610d3a57610d3a610cc8565b8060051b610d4a60208201610cde565b91825260208185018101929081019086841115610d6657600080fd5b6020860192505b83831015610d8f57610d7e83610b37565b825260209283019290910190610d6d565b9695505050505050565b60008060008060808587031215610daf57600080fd5b843567ffffffffffffffff811115610dc657600080fd5b8501601f81018713610dd757600080fd5b803567ffffffffffffffff811115610df157610df1610cc8565b610e04601f8201601f1916602001610cde565b818152886020838501011115610e1957600080fd5b8160208401602083013760006020928201830152955086013593505060408501359150606085013567ffffffffffffffff811115610e5657600080fd5b610e6287828801610d0f565b91505092959194509250565b600181811c90821680610e8257607f821691505b602082108103610ea257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156103dc576103dc610ebe565b600060018201610ef957610ef9610ebe565b5060010190565b601f821115610f4a57806000526020600020601f840160051c81016020851015610f275750805b601f840160051c820191505b81811015610f475760008155600101610f33565b50505b505050565b815167ffffffffffffffff811115610f6957610f69610cc8565b610f7d81610f778454610e6e565b84610f00565b6020601f821160018114610fb15760008315610f995750848201515b600019600385901b1c1916600184901b178455610f47565b600084815260208120601f198516915b82811015610fe15787850151825560209485019460019092019101610fc1565b5084821015610fff5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b80820281158282048414176103dc576103dc610ebe565b6020815260006110386020830184610b88565b9392505050565b60008261105c57634e487b7160e01b600052601260045260246000fd5b50069056fea264697066735822122085fc015faf93e710b19c708ec8505a717e697a3d02dbdae260bdc314fc47b22364736f6c634300081c0033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index fd8e2af..57eabd6 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,93 +1,17 @@ import SusuChainJSON from "./abi.json"; -// ────────────────────────────────────────────── -// Constants -// ────────────────────────────────────────────── - -/** Full Solidity ABI for the SusuChain contract on Celo */ +// Celo exports export const SUSUCHAIN_CELO_ABI = SusuChainJSON.abi; - -/** Deployed SusuChain contract address on Celo Mainnet */ export const SUSUCHAIN_CELO_ADDRESS = "0x20B421Db767D3496E4489Db5C3122C1fD4625525"; -/** Deployed Stacks contract principal */ +// Stacks exports export const STACKS_CONTRACT_ADDRESS = "SP2T02XBVN9RAZ4360DSWF3JCG79B1QY2NR21RB0Q"; - -/** Stacks contract name */ export const STACKS_CONTRACT_NAME = "susuchain"; // Re-export Stacks network helpers import { STACKS_MAINNET } from "@stacks/network"; export const STACKS_NETWORK = STACKS_MAINNET; -// ────────────────────────────────────────────── -// TypeScript Interfaces -// ────────────────────────────────────────────── - -/** Options for building a Stacks create-circle transaction */ -export interface CreateCircleTxOptions { - senderKey: string; - name: string; - contributionMicroSTX: number; - members: string[]; - fee?: number; - nonce?: number; -} - -/** Options for building a Stacks contribute transaction */ -export interface ContributeTxOptions { - senderKey: string; - circleId: number; - fee?: number; - nonce?: number; -} - -/** Options for building a Stacks trigger-payout transaction */ -export interface TriggerPayoutTxOptions { - senderKey: string; - circleId: number; - fee?: number; - nonce?: number; -} - -/** Options for broadcasting a signed Stacks transaction */ -export interface BroadcastTxOptions { - transaction: StacksTransactionWire; -} - -/** Options for building Celo createCircle params */ -export interface CeloCreateCircleOptions { - name: string; - contributionWei: bigint; - roundDurationDays: number; - gracePeriodDays: number; - penaltyFee: bigint; - members: string[]; -} - -/** Options for building Celo contribute params */ -export interface CeloContributeOptions { - circleId: number; - valueWei: bigint; -} - -/** Options for building Celo hasPaid params */ -export interface CeloHasPaidOptions { - circleId: number; - round: number; - member: string; -} - -/** Options for building Celo isMember params */ -export interface CeloIsMemberOptions { - circleId: number; - user: string; -} - -// ────────────────────────────────────────────── -// Stacks Imports -// ────────────────────────────────────────────── - // Browser-based helper functions for Stacks (requires Leather wallet injected provider) import { openContractCall } from "@stacks/connect"; import { @@ -99,14 +23,9 @@ import { PostConditionMode, makeContractCall, broadcastTransaction, - fetchCallReadOnlyFunction, } from "@stacks/transactions"; import type { StacksTransactionWire, TxBroadcastResult } from "@stacks/transactions"; -// ────────────────────────────────────────────── -// Stacks Browser Wallet Helpers -// ────────────────────────────────────────────── - /** * Open Leather wallet to call create-circle * @param name Savings circle name (max 50 chars) @@ -180,15 +99,14 @@ export function callTriggerPayout( }); } -// ────────────────────────────────────────────── -// Stacks Server-Side Transaction Builders -// ────────────────────────────────────────────── - -/** - * Build and sign a create-circle transaction for server-side use - * @param opts Transaction options including senderKey - */ -export async function buildCreateCircleTx(opts: CreateCircleTxOptions): Promise { +export async function buildCreateCircleTx(opts: { + senderKey: string; + name: string; + contributionMicroSTX: number; + members: string[]; + fee?: number; + nonce?: number; +}): Promise { const tx = await makeContractCall({ contractAddress: STACKS_CONTRACT_ADDRESS, contractName: STACKS_CONTRACT_NAME, @@ -206,11 +124,12 @@ export async function buildCreateCircleTx(opts: CreateCircleTxOptions): Promise< return tx; } -/** - * Build and sign a contribute transaction for server-side use - * @param opts Transaction options including senderKey and circleId - */ -export async function buildContributeTx(opts: ContributeTxOptions): Promise { +export async function buildContributeTx(opts: { + senderKey: string; + circleId: number; + fee?: number; + nonce?: number; +}): Promise { const tx = await makeContractCall({ contractAddress: STACKS_CONTRACT_ADDRESS, contractName: STACKS_CONTRACT_NAME, @@ -225,11 +144,12 @@ export async function buildContributeTx(opts: ContributeTxOptions): Promise { +export async function buildTriggerPayoutTx(opts: { + senderKey: string; + circleId: number; + fee?: number; + nonce?: number; +}): Promise { const tx = await makeContractCall({ contractAddress: STACKS_CONTRACT_ADDRESS, contractName: STACKS_CONTRACT_NAME, @@ -244,11 +164,9 @@ export async function buildTriggerPayoutTx(opts: TriggerPayoutTxOptions): Promis return tx; } -/** - * Broadcast a signed Stacks transaction to the network - * @param opts Options containing the signed transaction - */ -export async function broadcastTx(opts: BroadcastTxOptions): Promise { +export async function broadcastTx(opts: { + transaction: StacksTransactionWire; +}): Promise { const result = await broadcastTransaction({ transaction: opts.transaction, network: STACKS_NETWORK, @@ -256,94 +174,14 @@ export async function broadcastTx(opts: BroadcastTxOptions): Promise e.name === "createCircle" && e.type === "function" -); -if (!createCircleABI || createCircleABI.inputs.length !== 6) { - throw new Error( - `Expected createCircle ABI to have 6 inputs, got ${createCircleABI ? createCircleABI.inputs.length : "not found"}` - ); -} -const withdrawABI = SUSUCHAIN_CELO_ABI.find( - (e) => e.name === "withdraw" && e.type === "function" -); -if (!withdrawABI) { - throw new Error("ABI is missing withdraw function"); -} - -// ── Stacks Server-Side Builders ── - -const stacksBuilders = { +const builders = { buildCreateCircleTx, buildContributeTx, buildTriggerPayoutTx, broadcastTx, -}; - -for (const [name, fn] of Object.entries(stacksBuilders)) { - if (typeof fn !== "function") { - throw new Error(`Expected ${name} to be a function, got ${typeof fn}`); - } -} - -// ── Stacks Read-Only Builders ── - -const stacksReaders = { - readGetCircle, - readGetCircleCount, - readHasMemberPaid, - readIsMember, -}; - -for (const [name, fn] of Object.entries(stacksReaders)) { - if (typeof fn !== "function") { - throw new Error(`Expected ${name} to be a function, got ${typeof fn}`); - } -} - -// ── Celo Param Builders ── - -const celoBuilders = { buildCeloCreateCircleParams, buildCeloContributeParams, - buildCeloWithdrawParams, - buildCeloGetCircleParams, - buildCeloIsMemberParams, - buildCeloGetMemberCountParams, - buildCeloHasPaidParams, - buildCeloCircleCountParams, - buildCeloRoundBalanceParams, - buildCeloPendingWithdrawalsParams, }; -for (const [name, fn] of Object.entries(celoBuilders)) { +for (const [name, fn] of Object.entries(builders)) { if (typeof fn !== "function") { throw new Error(`Expected ${name} to be a function, got ${typeof fn}`); } } -// ── Celo Builder Return Value Validation ── - -const createParams = buildCeloCreateCircleParams({ - name: "Test", - contributionWei: 1000000000000000000n, - roundDurationDays: 30, - gracePeriodDays: 3, - penaltyFee: 0n, - members: ["0x1234567890123456789012345678901234567890"], -}); -if (createParams.functionName !== "createCircle") { - throw new Error("buildCeloCreateCircleParams returned wrong functionName"); -} -if (createParams.args.length !== 6) { - throw new Error(`buildCeloCreateCircleParams returned ${createParams.args.length} args, expected 6`); -} - -const withdrawParams = buildCeloWithdrawParams(); -if (withdrawParams.functionName !== "withdraw") { - throw new Error("buildCeloWithdrawParams returned wrong functionName"); -} - -const circleCountParams = buildCeloCircleCountParams(); -if (circleCountParams.functionName !== "circleCount") { - throw new Error("buildCeloCircleCountParams returned wrong functionName"); -} - -const getCircleParams = buildCeloGetCircleParams(0); -if (getCircleParams.functionName !== "getCircle") { - throw new Error("buildCeloGetCircleParams returned wrong functionName"); -} - -const hasPaidParams = buildCeloHasPaidParams({ - circleId: 0, - round: 0, - member: "0x1234567890123456789012345678901234567890", -}); -if (hasPaidParams.functionName !== "hasPaid") { - throw new Error("buildCeloHasPaidParams returned wrong functionName"); -} - console.log("CommonJS exports validated successfully."); diff --git a/packages/sdk/test-esm.mjs b/packages/sdk/test-esm.mjs index ca8768a..6421ad2 100644 --- a/packages/sdk/test-esm.mjs +++ b/packages/sdk/test-esm.mjs @@ -1,33 +1,14 @@ import { SUSUCHAIN_CELO_ADDRESS, - SUSUCHAIN_CELO_ABI, STACKS_CONTRACT_NAME, - STACKS_CONTRACT_ADDRESS, - // Stacks server-side builders buildCreateCircleTx, buildContributeTx, buildTriggerPayoutTx, broadcastTx, - // Stacks read-only builders - readGetCircle, - readGetCircleCount, - readHasMemberPaid, - readIsMember, - // Celo param builders buildCeloCreateCircleParams, buildCeloContributeParams, - buildCeloWithdrawParams, - buildCeloGetCircleParams, - buildCeloIsMemberParams, - buildCeloGetMemberCountParams, - buildCeloHasPaidParams, - buildCeloCircleCountParams, - buildCeloRoundBalanceParams, - buildCeloPendingWithdrawalsParams, } from "./dist/index.mjs"; -// ── Constants ── - if (SUSUCHAIN_CELO_ADDRESS !== "0x20B421Db767D3496E4489Db5C3122C1fD4625525") { throw new Error("Invalid Celo contract address exported in ES Module"); } @@ -35,113 +16,19 @@ if (STACKS_CONTRACT_NAME !== "susuchain") { throw new Error("Invalid Stacks contract name exported in ES Module"); } -// ── ABI Validation ── - -const createCircleABI = SUSUCHAIN_CELO_ABI.find( - (e) => e.name === "createCircle" && e.type === "function" -); -if (!createCircleABI || createCircleABI.inputs.length !== 6) { - throw new Error( - `Expected createCircle ABI to have 6 inputs, got ${createCircleABI ? createCircleABI.inputs.length : "not found"}` - ); -} -const withdrawABI = SUSUCHAIN_CELO_ABI.find( - (e) => e.name === "withdraw" && e.type === "function" -); -if (!withdrawABI) { - throw new Error("ABI is missing withdraw function"); -} - -// ── Stacks Server-Side Builders ── - -const stacksBuilders = { +const builders = { buildCreateCircleTx, buildContributeTx, buildTriggerPayoutTx, broadcastTx, -}; - -for (const [name, fn] of Object.entries(stacksBuilders)) { - if (typeof fn !== "function") { - throw new Error(`Expected ${name} to be a function, got ${typeof fn}`); - } -} - -// ── Stacks Read-Only Builders ── - -const stacksReaders = { - readGetCircle, - readGetCircleCount, - readHasMemberPaid, - readIsMember, -}; - -for (const [name, fn] of Object.entries(stacksReaders)) { - if (typeof fn !== "function") { - throw new Error(`Expected ${name} to be a function, got ${typeof fn}`); - } -} - -// ── Celo Param Builders ── - -const celoBuilders = { buildCeloCreateCircleParams, buildCeloContributeParams, - buildCeloWithdrawParams, - buildCeloGetCircleParams, - buildCeloIsMemberParams, - buildCeloGetMemberCountParams, - buildCeloHasPaidParams, - buildCeloCircleCountParams, - buildCeloRoundBalanceParams, - buildCeloPendingWithdrawalsParams, }; -for (const [name, fn] of Object.entries(celoBuilders)) { +for (const [name, fn] of Object.entries(builders)) { if (typeof fn !== "function") { throw new Error(`Expected ${name} to be a function, got ${typeof fn}`); } } -// ── Celo Builder Return Value Validation ── - -const createParams = buildCeloCreateCircleParams({ - name: "Test", - contributionWei: 1000000000000000000n, - roundDurationDays: 30, - gracePeriodDays: 3, - penaltyFee: 0n, - members: ["0x1234567890123456789012345678901234567890"], -}); -if (createParams.functionName !== "createCircle") { - throw new Error("buildCeloCreateCircleParams returned wrong functionName"); -} -if (createParams.args.length !== 6) { - throw new Error(`buildCeloCreateCircleParams returned ${createParams.args.length} args, expected 6`); -} - -const withdrawParams = buildCeloWithdrawParams(); -if (withdrawParams.functionName !== "withdraw") { - throw new Error("buildCeloWithdrawParams returned wrong functionName"); -} - -const circleCountParams = buildCeloCircleCountParams(); -if (circleCountParams.functionName !== "circleCount") { - throw new Error("buildCeloCircleCountParams returned wrong functionName"); -} - -const getCircleParams = buildCeloGetCircleParams(0); -if (getCircleParams.functionName !== "getCircle") { - throw new Error("buildCeloGetCircleParams returned wrong functionName"); -} - -const hasPaidParams = buildCeloHasPaidParams({ - circleId: 0, - round: 0, - member: "0x1234567890123456789012345678901234567890", -}); -if (hasPaidParams.functionName !== "hasPaid") { - throw new Error("buildCeloHasPaidParams returned wrong functionName"); -} - console.log("ES Module exports validated successfully.");