diff --git a/packages/contracts/README.md b/packages/contracts/README.md new file mode 100644 index 0000000..9dd5a96 --- /dev/null +++ b/packages/contracts/README.md @@ -0,0 +1,423 @@ +# @oaknetwork/contracts + +TypeScript SDK for interacting with Oak Network smart contracts. Provides a type-safe client with full read/write access to all Oak protocol contracts. + +## Installation + +```bash +pnpm add @oaknetwork/contracts +``` + +## Quick Start + +```typescript +import { createOakContractsClient, CHAIN_IDS, toHex } from "@oaknetwork/contracts"; + +const oak = createOakContractsClient({ + chainId: CHAIN_IDS.CELO_TESTNET_SEPOLIA, + rpcUrl: "https://forno.celo-sepolia.celo-testnet.org", + privateKey: "0x...", +}); +``` + +## Client Configuration + +Two config shapes are supported: + +### Simple (chainId + rpcUrl + privateKey) + +```typescript +const oak = createOakContractsClient({ + chainId: CHAIN_IDS.CELO_TESTNET_SEPOLIA, + rpcUrl: "https://forno.celo-sepolia.celo-testnet.org", + privateKey: "0x...", +}); +``` + +### Full (bring your own clients) + +```typescript +import { + createOakContractsClient, + createPublicClient, + createWalletClient, + http, + getChainFromId, + CHAIN_IDS, +} from "@oaknetwork/contracts"; + +const chain = getChainFromId(CHAIN_IDS.CELO_TESTNET_SEPOLIA); +const provider = createPublicClient({ chain, transport: http(RPC_URL) }); +const signer = createWalletClient({ account, chain, transport: http(RPC_URL) }); + +const oak = createOakContractsClient({ chain, provider, signer }); +``` + +## Supported Chain IDs + +```typescript +import { CHAIN_IDS } from "@oaknetwork/contracts"; + +CHAIN_IDS.ETHEREUM_MAINNET // 1 +CHAIN_IDS.CELO_MAINNET // 42220 +CHAIN_IDS.ETHEREUM_TESTNET_SEPOLIA // 11155111 +CHAIN_IDS.ETHEREUM_TESTNET_GOERLI // 5 +CHAIN_IDS.CELO_TESTNET_SEPOLIA // 11142220 +``` + +## Contracts + +### GlobalParams + +Protocol-wide configuration registry. + +```typescript +const gp = oak.globalParams("0x..."); + +// Reads +const admin = await gp.getProtocolAdminAddress(); +const fee = await gp.getProtocolFeePercent(); // bigint bps (e.g. 100 = 1%) +const count = await gp.getNumberOfListedPlatforms(); +const isListed = await gp.checkIfPlatformIsListed(platformHash); +const platAdmin = await gp.getPlatformAdminAddress(platformHash); +const platFee = await gp.getPlatformFeePercent(platformHash); +const delay = await gp.getPlatformClaimDelay(platformHash); +const adapter = await gp.getPlatformAdapter(platformHash); +const tokens = await gp.getTokensForCurrency(currency); // Address[] +const lineItem = await gp.getPlatformLineItemType(platformHash, typeId); +const value = await gp.getFromRegistry(key); + +// Writes +await gp.enlistPlatform(platformHash, adminAddress, feePercent, adapterAddress); +await gp.delistPlatform(platformHash); +await gp.updatePlatformAdminAddress(platformHash, newAdmin); +await gp.updatePlatformClaimDelay(platformHash, delaySeconds); +await gp.updateProtocolAdminAddress(newAdmin); +await gp.updateProtocolFeePercent(newFeePercent); +await gp.setPlatformAdapter(platformHash, adapterAddress); +await gp.setPlatformLineItemType(platformHash, typeId, label, countsTowardGoal, applyProtocolFee, canRefund, instantTransfer); +await gp.removePlatformLineItemType(platformHash, typeId); +await gp.addTokenToCurrency(currency, tokenAddress); +await gp.removeTokenFromCurrency(currency, tokenAddress); +await gp.addPlatformData(platformHash, platformDataKey); +await gp.removePlatformData(platformHash, platformDataKey); +await gp.addToRegistry(key, value); +await gp.transferOwnership(newOwner); +``` + +--- + +### CampaignInfoFactory + +Deploys new CampaignInfo contracts. + +```typescript +import { + createOakContractsClient, + keccak256, + toHex, + getCurrentTimestamp, + addDays, + CHAIN_IDS, +} from "@oaknetwork/contracts"; + +const factory = oak.campaignInfoFactory("0x..."); + +const PLATFORM_HASH = keccak256(toHex("my-platform")); +const CURRENCY = toHex("USD", { size: 32 }); +const identifierHash = keccak256(toHex("my-campaign-slug")); +const now = getCurrentTimestamp(); + +// Reads +const infoAddress = await factory.identifierToCampaignInfo(identifierHash); +const isValid = await factory.isValidCampaignInfo(infoAddress); + +// Writes +const txHash = await factory.createCampaign({ + creator: "0x...", + identifierHash, + selectedPlatformHash: [PLATFORM_HASH], + campaignData: { + launchTime: now + 3_600n, // 1 hour from now + deadline: addDays(now, 30), // 30 days from now + goalAmount: 1_000_000n, + currency: CURRENCY, + }, + nftName: "My Campaign NFT", + nftSymbol: "MCN", + nftImageURI: "https://example.com/nft.png", + contractURI: "https://example.com/contract.json", +}); + +const receipt = await oak.waitForReceipt(txHash); +const campaignAddress = await factory.identifierToCampaignInfo(identifierHash); +``` + +--- + +### TreasuryFactory + +Deploys treasury contracts for a given CampaignInfo. + +```typescript +const tf = oak.treasuryFactory("0x..."); + +// Deploy +const txHash = await tf.deploy(platformHash, infoAddress, implementationId); + +// Implementation management +await tf.registerTreasuryImplementation(platformHash, implementationId, implAddress); +await tf.approveTreasuryImplementation(platformHash, implementationId); +await tf.disapproveTreasuryImplementation(implAddress); +await tf.removeTreasuryImplementation(platformHash, implementationId); +``` + +--- + +### CampaignInfo + +Per-campaign configuration and state. + +```typescript +const ci = oak.campaignInfo("0x..."); + +// Reads +const launchTime = await ci.getLaunchTime(); +const deadline = await ci.getDeadline(); +const goalAmount = await ci.getGoalAmount(); +const currency = await ci.getCampaignCurrency(); +const totalRaised = await ci.getTotalRaisedAmount(); +const available = await ci.getAvailableRaisedAmount(); +const isLocked = await ci.isLocked(); +const isCancelled = await ci.cancelled(); +const config = await ci.getCampaignConfig(); +const tokens = await ci.getAcceptedTokens(); + +// Writes +await ci.updateDeadline(newDeadline); +await ci.updateGoalAmount(newGoal); +await ci.pauseCampaign(message); +await ci.unpauseCampaign(message); +await ci.cancelCampaign(message); +``` + +--- + +### PaymentTreasury + +Handles fiat-style payments via a payment gateway. + +```typescript +const pt = oak.paymentTreasury("0x..."); + +// Reads +const raised = await pt.getRaisedAmount(); +const refunded = await pt.getRefundedAmount(); +const payment = await pt.getPaymentData(paymentId); + +// Writes +const txHash = await pt.createPayment(paymentId, buyerId, itemId, paymentToken, amount, expiration, lineItems, externalFees); +await pt.confirmPayment(paymentId, buyerAddress); +await pt.claimRefund(paymentId, refundAddress); +await pt.claimRefundSelf(paymentId); +await pt.disburseFees(); +await pt.withdraw(); +await pt.pauseTreasury(message); +await pt.unpauseTreasury(message); +await pt.cancelTreasury(message); +``` + +--- + +### AllOrNothing Treasury + +Crowdfunding treasury — funds only released if goal is met, otherwise backers can claim refunds. + +```typescript +const aon = oak.allOrNothingTreasury("0x..."); + +// Reads +const raised = await aon.getRaisedAmount(); +const reward = await aon.getReward(rewardName); + +// Writes +await aon.addRewards(rewardNames, rewards); +await aon.pledgeForAReward(backer, pledgeToken, shippingFee, rewardNames); +await aon.pledgeWithoutAReward(backer, pledgeToken, pledgeAmount); +await aon.claimRefund(tokenId); +await aon.disburseFees(); +await aon.withdraw(); +await aon.pauseTreasury(message); +await aon.unpauseTreasury(message); +await aon.cancelTreasury(message); + +// ERC-721 +const owner = await aon.ownerOf(tokenId); +const uri = await aon.tokenURI(tokenId); +await aon.safeTransferFrom(from, to, tokenId); +``` + +--- + +### KeepWhatsRaised Treasury + +Crowdfunding treasury — creator keeps all funds raised regardless of goal. + +```typescript +const kwr = oak.keepWhatsRaisedTreasury("0x..."); + +// Reads +const raised = await kwr.getRaisedAmount(); +const available = await kwr.getAvailableRaisedAmount(); +const reward = await kwr.getReward(rewardName); + +// Writes +await kwr.configureTreasury(config, campaignData, feeKeys, feeValues); +await kwr.addRewards(rewardNames, rewards); +await kwr.pledgeForAReward(pledgeId, backer, token, tip, rewardNames); +await kwr.pledgeWithoutAReward(pledgeId, backer, token, amount, tip); +await kwr.approveWithdrawal(); +await kwr.claimFund(); +await kwr.claimTip(); +await kwr.claimRefund(tokenId); +await kwr.disburseFees(); +await kwr.withdraw(token, amount); +await kwr.pauseTreasury(message); +await kwr.unpauseTreasury(message); +await kwr.cancelTreasury(message); +``` + +--- + +### ItemRegistry + +Manages items available for purchase in campaigns. + +```typescript +const ir = oak.itemRegistry("0x..."); + +// Read +const item = await ir.getItem(ownerAddress, itemId); + +// Writes +await ir.addItem(itemId, item); +await ir.addItemsBatch(itemIds, items); +``` + +--- + +## Error Handling + +Contract revert errors can be decoded into typed SDK errors: + +```typescript +import { parseContractError } from "@oaknetwork/contracts"; + +function handleError(err) { + // Walk the cause chain to find raw revert data + let current = err; + while (current) { + if (typeof current.data === "string" && current.data.startsWith("0x")) { + const parsed = parseContractError(current.data); + if (parsed) { + console.error("Reverted:", parsed.name); + console.error("Args:", parsed.args); + if (parsed.recoveryHint) console.error("Hint:", parsed.recoveryHint); + return; + } + } + current = current.cause; + } + console.error("Unknown error:", err.message); +} + +try { + const txHash = await factory.createCampaign({ ... }); +} catch (err) { + handleError(err); +} +``` + +Recognized error types: +- `GlobalParams*` — platform/protocol configuration errors +- `CampaignInfoFactory*` — campaign creation errors + +--- + +## Utility Functions + +```typescript +import { + keccak256, + id, + toHex, + stringToHex, + parseEther, + formatEther, + parseUnits, + isAddress, + getAddress, + getCurrentTimestamp, + addDays, + getChainFromId, + createJsonRpcProvider, + createWallet, + createBrowserProvider, + getSigner, + CHAIN_IDS, + BPS_DENOMINATOR, + BYTES32_ZERO, + DATA_REGISTRY_KEYS, + scopedToPlatform, +} from "@oaknetwork/contracts"; + +// Hash a string to bytes32 +const platformHash = keccak256(toHex("my-platform")); + +// Encode string to fixed bytes32 +const currency = toHex("USD", { size: 32 }); + +// Timestamp helpers +const now = getCurrentTimestamp(); // bigint seconds +const deadline = addDays(now, 30); // 30 days from now + +// Fee calculations (fees are in basis points, 10_000 = 100%) +const feeAmount = (raisedAmount * platformFee) / BPS_DENOMINATOR; + +// Browser wallet (frontend) +const chain = getChainFromId(CHAIN_IDS.CELO_TESTNET_SEPOLIA); +const provider = createBrowserProvider(window.ethereum, chain); +const signer = await getSigner(window.ethereum, chain); +``` + +--- + +## Exported Entry Points + +| Entry point | Contents | +|-----------------------------------|--------------------------------------------| +| `@oaknetwork/contracts` | Everything — client, types, utils, errors | +| `@oaknetwork/contracts/utils` | Utility functions only (no client) | +| `@oaknetwork/contracts/contracts` | Contract entity factories only | +| `@oaknetwork/contracts/client` | `createOakContractsClient` only | +| `@oaknetwork/contracts/errors` | Error classes and `parseContractError` only | + +--- + +## Local Development & Testing + +```bash +# Install dependencies +pnpm install + +# Build +pnpm build + +# Run smoke test (edit addresses in test-example.mjs first) +node test-example.mjs + +# Run unit tests +pnpm test +``` + +The `test-example.mjs` file at the package root contains runnable examples for all three contract groups (GlobalParams reads, CampaignInfoFactory, TreasuryFactory). Each section can be toggled by uncommenting the relevant block. diff --git a/packages/contracts/jest.config.js b/packages/contracts/jest.config.cjs similarity index 100% rename from packages/contracts/jest.config.js rename to packages/contracts/jest.config.cjs diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 76a30e0..1c44e71 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -5,20 +5,47 @@ "publishConfig": { "access": "public" }, + "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./utils": { + "types": "./dist/utils/index.d.ts", + "import": "./dist/utils/index.js" + }, + "./contracts": { + "types": "./dist/contracts/index.d.ts", + "import": "./dist/contracts/index.js" + }, + "./client": { + "types": "./dist/client/index.d.ts", + "import": "./dist/client/index.js" + }, + "./errors": { + "types": "./dist/errors/index.d.ts", + "import": "./dist/errors/index.js" + } + }, "scripts": { - "build": "tsc", - "prepublishOnly": "npm run build", + "build": "tsup", + "prepublishOnly": "pnpm run build", "test": "jest --coverage", "test:watch": "jest --watchAll" }, + "dependencies": { + "viem": "^2.23.0" + }, "devDependencies": { "@types/jest": "^30.0.0", "@types/node": "^20.14.11", "jest": "^30.0.5", "ts-jest": "^29.4.6", "ts-node": "^10.9.2", + "tsup": "^8.5.1", "typescript": "^5.5.4" }, "author": "oaknetwork", diff --git a/packages/contracts/src/abis/all-or-nothing.ts b/packages/contracts/src/abis/all-or-nothing.ts new file mode 100644 index 0000000..5861c7e --- /dev/null +++ b/packages/contracts/src/abis/all-or-nothing.ts @@ -0,0 +1,451 @@ +const REWARD_TIER_COMPONENTS = [ + { internalType: "uint256", name: "rewardValue", type: "uint256" }, + { internalType: "bool", name: "isRewardTier", type: "bool" }, + { internalType: "bytes32[]", name: "itemId", type: "bytes32[]" }, + { internalType: "uint256[]", name: "itemValue", type: "uint256[]" }, + { internalType: "uint256[]", name: "itemQuantity", type: "uint256[]" }, +] as const; + +export const ALL_OR_NOTHING_ABI = [ + { inputs: [], name: "AccessCheckerUnauthorized", type: "error" }, + { inputs: [], name: "AllOrNothingFeeNotDisbursed", type: "error" }, + { inputs: [], name: "AllOrNothingInvalidInput", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "AllOrNothingNotClaimable", + type: "error", + }, + { inputs: [], name: "AllOrNothingNotSuccessful", type: "error" }, + { inputs: [], name: "AllOrNothingRewardExists", type: "error" }, + { inputs: [], name: "AllOrNothingTransferFailed", type: "error" }, + { inputs: [], name: "AllOrNothingUnAuthorized", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "inputTime", type: "uint256" }, + { internalType: "uint256", name: "currentTime", type: "uint256" }, + ], + name: "CurrentTimeIsGreater", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "inputTime", type: "uint256" }, + { internalType: "uint256", name: "currentTime", type: "uint256" }, + ], + name: "CurrentTimeIsLess", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "initialTime", type: "uint256" }, + { internalType: "uint256", name: "finalTime", type: "uint256" }, + ], + name: "CurrentTimeIsNotWithinRange", + type: "error", + }, + { inputs: [], name: "AllOrNothingFeeAlreadyDisbursed", type: "error" }, + { + inputs: [{ internalType: "address", name: "token", type: "address" }], + name: "AllOrNothingTokenNotAccepted", + type: "error", + }, + { inputs: [], name: "TreasuryCampaignInfoIsPaused", type: "error" }, + { inputs: [], name: "TreasuryFeeNotDisbursed", type: "error" }, + { inputs: [], name: "TreasurySuccessConditionNotFulfilled", type: "error" }, + { inputs: [], name: "TreasuryTransferFailed", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "owner", type: "address" }, + { indexed: true, internalType: "address", name: "approved", type: "address" }, + { indexed: true, internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "owner", type: "address" }, + { indexed: true, internalType: "address", name: "operator", type: "address" }, + { indexed: false, internalType: "bool", name: "approved", type: "bool" }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: false, internalType: "uint256", name: "protocolShare", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "platformShare", type: "uint256" }, + ], + name: "FeesDisbursed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "account", type: "address" }, + { indexed: false, internalType: "bytes32", name: "message", type: "bytes32" }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "backer", type: "address" }, + { indexed: true, internalType: "address", name: "pledgeToken", type: "address" }, + { indexed: false, internalType: "bytes32", name: "reward", type: "bytes32" }, + { indexed: false, internalType: "uint256", name: "pledgeAmount", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "shippingFee", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "tokenId", type: "uint256" }, + { indexed: false, internalType: "bytes32[]", name: "rewards", type: "bytes32[]" }, + ], + name: "Receipt", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "tokenId", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "refundAmount", type: "uint256" }, + { indexed: false, internalType: "address", name: "claimer", type: "address" }, + ], + name: "RefundClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "bytes32[]", name: "rewardNames", type: "bytes32[]" }, + { + components: [...REWARD_TIER_COMPONENTS], + indexed: false, + internalType: "struct AllOrNothing.Reward[]", + name: "rewards", + type: "tuple[]", + }, + ], + name: "RewardsAdded", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "bytes32", name: "rewardName", type: "bytes32" }], + name: "RewardRemoved", + type: "event", + }, + { anonymous: false, inputs: [], name: "SuccessConditionNotFulfilled", type: "event" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { indexed: true, internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "Transfer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "account", type: "address" }, + { indexed: false, internalType: "bytes32", name: "message", type: "bytes32" }, + ], + name: "Unpaused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: false, internalType: "address", name: "to", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "WithdrawalSuccessful", + type: "event", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "pauseTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "unpauseTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "cancelTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "cancelled", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32[]", name: "rewardNames", type: "bytes32[]" }, + { + components: [...REWARD_TIER_COMPONENTS], + internalType: "struct AllOrNothing.Reward[]", + name: "rewards", + type: "tuple[]", + }, + ], + name: "addRewards", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "_platformHash", type: "bytes32" }, + { internalType: "address", name: "_infoAddress", type: "address" }, + { internalType: "address", name: "_trustedForwarder", type: "address" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "claimRefund", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "disburseFees", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "getApproved", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getLifetimeRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "rewardName", type: "bytes32" }], + name: "getReward", + outputs: [ + { + components: REWARD_TIER_COMPONENTS, + internalType: "struct AllOrNothing.Reward", + name: "reward", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getPlatformHash", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getRefundedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getPlatformFeePercent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "operator", type: "address" }, + ], + name: "isApprovedForAll", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "ownerOf", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "backer", type: "address" }, + { internalType: "address", name: "pledgeToken", type: "address" }, + { internalType: "uint256", name: "shippingFee", type: "uint256" }, + { internalType: "bytes32[]", name: "rewardNames", type: "bytes32[]" }, + ], + name: "pledgeForAReward", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "backer", type: "address" }, + { internalType: "address", name: "pledgeToken", type: "address" }, + { internalType: "uint256", name: "pledgeAmount", type: "uint256" }, + ], + name: "pledgeWithoutAReward", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "rewardName", type: "bytes32" }], + name: "removeReward", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "operator", type: "address" }, + { internalType: "bool", name: "approved", type: "bool" }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "tokenURI", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/abis/campaign-info-factory.ts b/packages/contracts/src/abis/campaign-info-factory.ts new file mode 100644 index 0000000..cfc804e --- /dev/null +++ b/packages/contracts/src/abis/campaign-info-factory.ts @@ -0,0 +1,130 @@ +/** + * CampaignInfoFactory ABI — from provided ICampaignInfoFactory + CampaignInfoFactory.sol. + * UUPS; no constructor; initialize + createCampaign (with NFT params), updateImplementation. + */ +const CAMPAIGN_DATA_COMPONENTS = [ + { internalType: "uint256", name: "launchTime", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint256", name: "goalAmount", type: "uint256" }, + { internalType: "bytes32", name: "currency", type: "bytes32" }, +] as const; + +export const CAMPAIGN_INFO_FACTORY_ABI = [ + { inputs: [], name: "CampaignInfoFactoryInvalidInput", type: "error" }, + { inputs: [], name: "CampaignInfoFactoryCampaignInitializationFailed", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "platformHash", type: "bytes32" }], + name: "CampaignInfoFactoryPlatformNotListed", + type: "error", + }, + { + inputs: [ + { internalType: "bytes32", name: "identifierHash", type: "bytes32" }, + { internalType: "address", name: "cloneExists", type: "address" }, + ], + name: "CampaignInfoFactoryCampaignWithSameIdentifierExists", + type: "error", + }, + { inputs: [], name: "CampaignInfoInvalidTokenList", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "identifierHash", type: "bytes32" }, + { indexed: true, internalType: "address", name: "campaignInfoAddress", type: "address" }, + ], + name: "CampaignInfoFactoryCampaignCreated", + type: "event", + }, + { + anonymous: false, + inputs: [], + name: "CampaignInfoFactoryCampaignInitialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "previousOwner", type: "address" }, + { indexed: true, internalType: "address", name: "newOwner", type: "address" }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + inputs: [ + { internalType: "address", name: "creator", type: "address" }, + { internalType: "bytes32", name: "identifierHash", type: "bytes32" }, + { internalType: "bytes32[]", name: "selectedPlatformHash", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "platformDataKey", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "platformDataValue", type: "bytes32[]" }, + { + components: [...CAMPAIGN_DATA_COMPONENTS], + internalType: "struct ICampaignData.CampaignData", + name: "campaignData", + type: "tuple", + }, + { internalType: "string", name: "nftName", type: "string" }, + { internalType: "string", name: "nftSymbol", type: "string" }, + { internalType: "string", name: "nftImageURI", type: "string" }, + { internalType: "string", name: "contractURI", type: "string" }, + ], + name: "createCampaign", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "identifierHash", type: "bytes32" }], + name: "identifierToCampaignInfo", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "initialOwner", type: "address" }, + { internalType: "contract IGlobalParams", name: "globalParams", type: "address" }, + { internalType: "address", name: "campaignImplementation", type: "address" }, + { internalType: "address", name: "treasuryFactoryAddress", type: "address" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "campaignInfo", type: "address" }], + name: "isValidCampaignInfo", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newImplementation", type: "address" }], + name: "updateImplementation", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/abis/campaign-info.ts b/packages/contracts/src/abis/campaign-info.ts new file mode 100644 index 0000000..c79aa1d --- /dev/null +++ b/packages/contracts/src/abis/campaign-info.ts @@ -0,0 +1,486 @@ +const CAMPAIGN_DATA_COMPONENTS = [ + { internalType: "uint256", name: "launchTime", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint256", name: "goalAmount", type: "uint256" }, + { internalType: "bytes32", name: "currency", type: "bytes32" }, +] as const; + +export const CAMPAIGN_INFO_ABI = [ + { inputs: [], name: "AdminAccessCheckerUnauthorized", type: "error" }, + { inputs: [], name: "CampaignInfoInvalidInput", type: "error" }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "bool", name: "selection", type: "bool" }, + ], + name: "CampaignInfoInvalidPlatformUpdate", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "CampaignInfoPlatformNotSelected", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "platformHash", type: "bytes32" }], + name: "CampaignInfoPlatformAlreadyApproved", + type: "error", + }, + { inputs: [], name: "CampaignInfoUnauthorized", type: "error" }, + { inputs: [], name: "CampaignInfoIsLocked", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "inputTime", type: "uint256" }, + { internalType: "uint256", name: "currentTime", type: "uint256" }, + ], + name: "CurrentTimeIsGreater", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "inputTime", type: "uint256" }, + { internalType: "uint256", name: "currentTime", type: "uint256" }, + ], + name: "CurrentTimeIsLess", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "initialTime", type: "uint256" }, + { internalType: "uint256", name: "finalTime", type: "uint256" }, + ], + name: "CurrentTimeIsNotWithinRange", + type: "error", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "newDeadline", type: "uint256" }], + name: "CampaignInfoDeadlineUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "newGoalAmount", type: "uint256" }], + name: "CampaignInfoGoalAmountUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "newLaunchTime", type: "uint256" }], + name: "CampaignInfoLaunchTimeUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: true, internalType: "address", name: "platformTreasury", type: "address" }, + ], + name: "CampaignInfoPlatformInfoUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: false, internalType: "bool", name: "selection", type: "bool" }, + ], + name: "CampaignInfoSelectedPlatformUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "previousOwner", type: "address" }, + { indexed: true, internalType: "address", name: "newOwner", type: "address" }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "account", type: "address" }, + { indexed: false, internalType: "bytes32", name: "message", type: "bytes32" }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "account", type: "address" }, + { indexed: false, internalType: "bytes32", name: "message", type: "bytes32" }, + ], + name: "Unpaused", + type: "event", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "_cancelCampaign", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "_pauseCampaign", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "address", name: "platformTreasuryAddress", type: "address" }, + ], + name: "_setPlatformInfo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "_unpauseCampaign", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "checkIfPlatformSelected", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getGoalAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getIdentifierHash", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getLaunchTime", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "getPlatformAdminAddress", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformDataKey", type: "bytes32" }], + name: "getPlatformData", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "getPlatformFeePercent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getProtocolAdminAddress", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getProtocolFeePercent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getCampaignCurrency", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getAcceptedTokens", + outputs: [{ internalType: "address[]", name: "", type: "address[]" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "token", type: "address" }], + name: "isTokenAccepted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformHash", type: "bytes32" }], + name: "getPlatformClaimDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getTotalRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getTotalLifetimeRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getTotalRefundedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getTotalAvailableRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getTotalCancelledAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getTotalExpectedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "key", type: "bytes32" }], + name: "getDataFromRegistry", + outputs: [{ internalType: "bytes32", name: "value", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getBufferTime", + outputs: [{ internalType: "uint256", name: "bufferTime", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + ], + name: "getLineItemType", + outputs: [ + { internalType: "bool", name: "exists", type: "bool" }, + { internalType: "string", name: "label", type: "string" }, + { internalType: "bool", name: "countsTowardGoal", type: "bool" }, + { internalType: "bool", name: "applyProtocolFee", type: "bool" }, + { internalType: "bool", name: "canRefund", type: "bool" }, + { internalType: "bool", name: "instantTransfer", type: "bool" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getCampaignConfig", + outputs: [ + { + components: [ + { internalType: "address", name: "treasuryFactory", type: "address" }, + { internalType: "uint256", name: "protocolFeePercent", type: "uint256" }, + { internalType: "bytes32", name: "identifierHash", type: "bytes32" }, + ], + internalType: "struct CampaignInfo.Config", + name: "config", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getApprovedPlatformHashes", + outputs: [{ internalType: "bytes32[]", name: "", type: "bytes32[]" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "isLocked", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformHash", type: "bytes32" }], + name: "checkIfPlatformApproved", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "cancelled", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "creator", type: "address" }, + { internalType: "contract IGlobalParams", name: "globalParams", type: "address" }, + { internalType: "bytes32[]", name: "selectedPlatformHash", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "platformDataKey", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "platformDataValue", type: "bytes32[]" }, + { + components: [...CAMPAIGN_DATA_COMPONENTS], + internalType: "struct ICampaignData.CampaignData", + name: "campaignData", + type: "tuple", + }, + { internalType: "address[]", name: "acceptedTokens", type: "address[]" }, + { internalType: "string", name: "nftName", type: "string" }, + { internalType: "string", name: "nftSymbol", type: "string" }, + { internalType: "string", name: "nftImageURI", type: "string" }, + { internalType: "string", name: "nftContractURI", type: "string" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "backer", type: "address" }, + { internalType: "bytes32", name: "reward", type: "bytes32" }, + { internalType: "address", name: "tokenAddress", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "uint256", name: "shippingFee", type: "uint256" }, + { internalType: "uint256", name: "tipAmount", type: "uint256" }, + ], + name: "mintNFTForPledge", + outputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "string", name: "newImageURI", type: "string" }], + name: "setImageURI", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "string", name: "newContractURI", type: "string" }], + name: "updateContractURI", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "account", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "deadline", type: "uint256" }], + name: "updateDeadline", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "goalAmount", type: "uint256" }], + name: "updateGoalAmount", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "launchTime", type: "uint256" }], + name: "updateLaunchTime", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "bool", name: "selection", type: "bool" }, + { internalType: "bytes32[]", name: "platformDataKey", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "platformDataValue", type: "bytes32[]" }, + ], + name: "updateSelectedPlatform", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/abis/global-params.ts b/packages/contracts/src/abis/global-params.ts new file mode 100644 index 0000000..e60760e --- /dev/null +++ b/packages/contracts/src/abis/global-params.ts @@ -0,0 +1,442 @@ +export const GLOBAL_PARAMS_ABI = [ + { inputs: [], name: "GlobalParamsInvalidInput", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "GlobalParamsPlatformAdminNotSet", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "GlobalParamsPlatformAlreadyListed", + type: "error", + }, + { inputs: [], name: "GlobalParamsPlatformDataAlreadySet", type: "error" }, + { inputs: [], name: "GlobalParamsPlatformDataNotSet", type: "error" }, + { inputs: [], name: "GlobalParamsPlatformDataSlotTaken", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "GlobalParamsPlatformFeePercentIsZero", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "GlobalParamsPlatformNotListed", + type: "error", + }, + { inputs: [], name: "GlobalParamsUnauthorized", type: "error" }, + { inputs: [], name: "GlobalParamsCurrencyTokenLengthMismatch", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "currency", type: "bytes32" }], + name: "GlobalParamsCurrencyHasNoTokens", + type: "error", + }, + { + inputs: [ + { internalType: "bytes32", name: "currency", type: "bytes32" }, + { internalType: "address", name: "token", type: "address" }, + ], + name: "GlobalParamsTokenNotInCurrency", + type: "error", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + ], + name: "GlobalParamsPlatformLineItemTypeNotFound", + type: "error", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "previousOwner", type: "address" }, + { indexed: true, internalType: "address", name: "newOwner", type: "address" }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "address", name: "account", type: "address" }], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: true, internalType: "address", name: "newAdminAddress", type: "address" }, + ], + name: "PlatformAdminAddressUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: true, internalType: "bytes32", name: "platformDataKey", type: "bytes32" }, + ], + name: "PlatformDataAdded", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: false, internalType: "bytes32", name: "platformDataKey", type: "bytes32" }, + ], + name: "PlatformDataRemoved", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "PlatformDelisted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: true, internalType: "address", name: "platformAdminAddress", type: "address" }, + { indexed: false, internalType: "uint256", name: "platformFeePercent", type: "uint256" }, + ], + name: "PlatformEnlisted", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "address", name: "newAdminAddress", type: "address" }], + name: "ProtocolAdminAddressUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "newFeePercent", type: "uint256" }], + name: "ProtocolFeePercentUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "currency", type: "bytes32" }, + { indexed: true, internalType: "address", name: "token", type: "address" }, + ], + name: "TokenAddedToCurrency", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "currency", type: "bytes32" }, + { indexed: true, internalType: "address", name: "token", type: "address" }, + ], + name: "TokenRemovedFromCurrency", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: true, internalType: "address", name: "platformAdapter", type: "address" }, + ], + name: "PlatformAdapterSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { indexed: false, internalType: "uint256", name: "claimDelay", type: "uint256" }, + ], + name: "PlatformClaimDelayUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "address", name: "account", type: "address" }], + name: "Unpaused", + type: "event", + }, + { + inputs: [ + { internalType: "bytes32", name: "key", type: "bytes32" }, + { internalType: "bytes32", name: "value", type: "bytes32" }, + ], + name: "addToRegistry", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "bytes32", name: "platformDataKey", type: "bytes32" }, + ], + name: "addPlatformData", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "currency", type: "bytes32" }, + { internalType: "address", name: "token", type: "address" }, + ], + name: "addTokenToCurrency", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformDataKey", type: "bytes32" }], + name: "checkIfPlatformDataKeyValid", + outputs: [{ internalType: "bool", name: "isValid", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "checkIfPlatformIsListed", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "delistPlatform", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "address", name: "platformAdminAddress", type: "address" }, + { internalType: "uint256", name: "platformFeePercent", type: "uint256" }, + { internalType: "address", name: "platformAdapter", type: "address" }, + ], + name: "enlistPlatform", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "key", type: "bytes32" }], + name: "getFromRegistry", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getNumberOfListedPlatforms", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "getPlatformAdminAddress", + outputs: [{ internalType: "address", name: "account", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformDataKey", type: "bytes32" }], + name: "getPlatformDataOwner", + outputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "getPlatformAdapter", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "getPlatformClaimDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "platformBytes", type: "bytes32" }], + name: "getPlatformFeePercent", + outputs: [{ internalType: "uint256", name: "platformFeePercent", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + ], + name: "getPlatformLineItemType", + outputs: [ + { internalType: "bool", name: "exists", type: "bool" }, + { internalType: "string", name: "label", type: "string" }, + { internalType: "bool", name: "countsTowardGoal", type: "bool" }, + { internalType: "bool", name: "applyProtocolFee", type: "bool" }, + { internalType: "bool", name: "canRefund", type: "bool" }, + { internalType: "bool", name: "instantTransfer", type: "bool" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "protocolAdminAddress", type: "address" }, + { internalType: "uint256", name: "protocolFeePercent", type: "uint256" }, + { internalType: "bytes32[]", name: "currencies", type: "bytes32[]" }, + { internalType: "address[][]", name: "tokensPerCurrency", type: "address[][]" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "getProtocolAdminAddress", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getProtocolFeePercent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "currency", type: "bytes32" }], + name: "getTokensForCurrency", + outputs: [{ internalType: "address[]", name: "", type: "address[]" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "bytes32", name: "platformDataKey", type: "bytes32" }, + ], + name: "removePlatformData", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + ], + name: "removePlatformLineItemType", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "currency", type: "bytes32" }, + { internalType: "address", name: "token", type: "address" }, + ], + name: "removeTokenFromCurrency", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "address", name: "platformAdapter", type: "address" }, + ], + name: "setPlatformAdapter", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + { internalType: "string", name: "label", type: "string" }, + { internalType: "bool", name: "countsTowardGoal", type: "bool" }, + { internalType: "bool", name: "applyProtocolFee", type: "bool" }, + { internalType: "bool", name: "canRefund", type: "bool" }, + { internalType: "bool", name: "instantTransfer", type: "bool" }, + ], + name: "setPlatformLineItemType", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "address", name: "platformAdminAddress", type: "address" }, + ], + name: "updatePlatformAdminAddress", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformBytes", type: "bytes32" }, + { internalType: "uint256", name: "claimDelay", type: "uint256" }, + ], + name: "updatePlatformClaimDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "protocolAdminAddress", type: "address" }], + name: "updateProtocolAdminAddress", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "protocolFeePercent", type: "uint256" }], + name: "updateProtocolFeePercent", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; + +export type GlobalParamsAbi = typeof GLOBAL_PARAMS_ABI; diff --git a/packages/contracts/src/abis/item-registry.ts b/packages/contracts/src/abis/item-registry.ts new file mode 100644 index 0000000..b679f1f --- /dev/null +++ b/packages/contracts/src/abis/item-registry.ts @@ -0,0 +1,75 @@ +const ITEM_COMPONENTS = [ + { internalType: "uint256", name: "actualWeight", type: "uint256" }, + { internalType: "uint256", name: "height", type: "uint256" }, + { internalType: "uint256", name: "width", type: "uint256" }, + { internalType: "uint256", name: "length", type: "uint256" }, + { internalType: "bytes32", name: "category", type: "bytes32" }, + { internalType: "bytes32", name: "declaredCurrency", type: "bytes32" }, +] as const; + +export const ITEM_REGISTRY_ABI = [ + { inputs: [], name: "ItemRegistryMismatchedArraysLength", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "owner", type: "address" }, + { indexed: true, internalType: "bytes32", name: "itemId", type: "bytes32" }, + { + components: ITEM_COMPONENTS, + indexed: false, + internalType: "struct IItem.Item", + name: "item", + type: "tuple", + }, + ], + name: "ItemAdded", + type: "event", + }, + { + inputs: [ + { internalType: "bytes32", name: "itemId", type: "bytes32" }, + { + components: ITEM_COMPONENTS, + internalType: "struct IItem.Item", + name: "item", + type: "tuple", + }, + ], + name: "addItem", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32[]", name: "itemIds", type: "bytes32[]" }, + { + components: [...ITEM_COMPONENTS], + internalType: "struct IItem.Item[]", + name: "items", + type: "tuple[]", + }, + ], + name: "addItemsBatch", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "bytes32", name: "itemId", type: "bytes32" }, + ], + name: "getItem", + outputs: [ + { + components: ITEM_COMPONENTS, + internalType: "struct IItem.Item", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/abis/keep-whats-raised.ts b/packages/contracts/src/abis/keep-whats-raised.ts new file mode 100644 index 0000000..b96ed30 --- /dev/null +++ b/packages/contracts/src/abis/keep-whats-raised.ts @@ -0,0 +1,702 @@ +/** + * KeepWhatsRaised treasury ABI — pledgeId-based pledges and withdraw(token, amount). + * Matches the provided KeepWhatsRaised contract (no Fiat; different signatures from AllOrNothing). + */ +const REWARD_TIER_COMPONENTS = [ + { internalType: "uint256", name: "rewardValue", type: "uint256" }, + { internalType: "bool", name: "isRewardTier", type: "bool" }, + { internalType: "bytes32[]", name: "itemId", type: "bytes32[]" }, + { internalType: "uint256[]", name: "itemValue", type: "uint256[]" }, + { internalType: "uint256[]", name: "itemQuantity", type: "uint256[]" }, +] as const; + +const CONFIG_COMPONENTS = [ + { internalType: "uint256", name: "minimumWithdrawalForFeeExemption", type: "uint256" }, + { internalType: "uint256", name: "withdrawalDelay", type: "uint256" }, + { internalType: "uint256", name: "refundDelay", type: "uint256" }, + { internalType: "uint256", name: "configLockPeriod", type: "uint256" }, + { internalType: "bool", name: "isColombianCreator", type: "bool" }, +] as const; + +const FEE_KEYS_COMPONENTS = [ + { internalType: "bytes32", name: "flatFeeKey", type: "bytes32" }, + { internalType: "bytes32", name: "cumulativeFlatFeeKey", type: "bytes32" }, + { internalType: "bytes32[]", name: "grossPercentageFeeKeys", type: "bytes32[]" }, +] as const; + +const FEE_VALUES_COMPONENTS = [ + { internalType: "uint256", name: "flatFeeValue", type: "uint256" }, + { internalType: "uint256", name: "cumulativeFlatFeeValue", type: "uint256" }, + { internalType: "uint256[]", name: "grossPercentageFeeValues", type: "uint256[]" }, +] as const; + +const CAMPAIGN_DATA_COMPONENTS = [ + { internalType: "uint256", name: "launchTime", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint256", name: "goalAmount", type: "uint256" }, + { internalType: "bytes32", name: "currency", type: "bytes32" }, +] as const; + +export const KEEP_WHATS_RAISED_ABI = [ + { inputs: [], name: "AccessCheckerUnauthorized", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedUnAuthorized", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedInvalidInput", type: "error" }, + { + inputs: [{ internalType: "address", name: "token", type: "address" }], + name: "KeepWhatsRaisedTokenNotAccepted", + type: "error", + }, + { inputs: [], name: "KeepWhatsRaisedRewardExists", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedDisabled", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedAlreadyEnabled", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "availableAmount", type: "uint256" }, + { internalType: "uint256", name: "withdrawalAmount", type: "uint256" }, + { internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "KeepWhatsRaisedInsufficientFundsForWithdrawalAndFee", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "withdrawalAmount", type: "uint256" }, + { internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "KeepWhatsRaisedInsufficientFundsForFee", + type: "error", + }, + { inputs: [], name: "KeepWhatsRaisedAlreadyWithdrawn", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedAlreadyClaimed", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "KeepWhatsRaisedNotClaimable", + type: "error", + }, + { inputs: [], name: "KeepWhatsRaisedNotClaimableAdmin", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedConfigLocked", type: "error" }, + { inputs: [], name: "KeepWhatsRaisedDisbursementBlocked", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "pledgeId", type: "bytes32" }], + name: "KeepWhatsRaisedPledgeAlreadyProcessed", + type: "error", + }, + { inputs: [], name: "TreasuryCampaignInfoIsPaused", type: "error" }, + { inputs: [], name: "TreasuryFeeNotDisbursed", type: "error" }, + { inputs: [], name: "TreasuryTransferFailed", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "owner", type: "address" }, + { indexed: true, internalType: "address", name: "approved", type: "address" }, + { indexed: true, internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "owner", type: "address" }, + { indexed: true, internalType: "address", name: "operator", type: "address" }, + { indexed: false, internalType: "bool", name: "approved", type: "bool" }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: false, internalType: "uint256", name: "protocolShare", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "platformShare", type: "uint256" }, + ], + name: "FeesDisbursed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "account", type: "address" }, + { indexed: false, internalType: "bytes32", name: "message", type: "bytes32" }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "backer", type: "address" }, + { indexed: true, internalType: "address", name: "pledgeToken", type: "address" }, + { indexed: false, internalType: "bytes32", name: "reward", type: "bytes32" }, + { indexed: false, internalType: "uint256", name: "pledgeAmount", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "tip", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "tokenId", type: "uint256" }, + { indexed: false, internalType: "bytes32[]", name: "rewards", type: "bytes32[]" }, + ], + name: "Receipt", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "bytes32[]", name: "rewardNames", type: "bytes32[]" }, + { + components: [...REWARD_TIER_COMPONENTS], + indexed: false, + internalType: "struct IReward.Reward[]", + name: "rewards", + type: "tuple[]", + }, + ], + name: "RewardsAdded", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "bytes32", name: "rewardName", type: "bytes32" }], + name: "RewardRemoved", + type: "event", + }, + { + anonymous: false, + inputs: [], + name: "WithdrawalApproved", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + components: [...CONFIG_COMPONENTS], + indexed: false, + internalType: "struct KeepWhatsRaised.Config", + name: "config", + type: "tuple", + }, + { + components: [...CAMPAIGN_DATA_COMPONENTS], + indexed: false, + internalType: "struct ICampaignData.CampaignData", + name: "campaignData", + type: "tuple", + }, + { + components: [...FEE_KEYS_COMPONENTS], + indexed: false, + internalType: "struct KeepWhatsRaised.FeeKeys", + name: "feeKeys", + type: "tuple", + }, + { + components: [...FEE_VALUES_COMPONENTS], + indexed: false, + internalType: "struct KeepWhatsRaised.FeeValues", + name: "feeValues", + type: "tuple", + }, + ], + name: "TreasuryConfigured", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + { indexed: true, internalType: "address", name: "claimer", type: "address" }, + ], + name: "TipClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + { indexed: true, internalType: "address", name: "claimer", type: "address" }, + ], + name: "FundClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "tokenId", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "refundAmount", type: "uint256" }, + { indexed: true, internalType: "address", name: "claimer", type: "address" }, + ], + name: "RefundClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "newDeadline", type: "uint256" }], + name: "KeepWhatsRaisedDeadlineUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "newGoalAmount", type: "uint256" }], + name: "KeepWhatsRaisedGoalAmountUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "pledgeId", type: "bytes32" }, + { indexed: false, internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "KeepWhatsRaisedPaymentGatewayFeeSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "to", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "WithdrawalWithFeeSuccessful", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { indexed: true, internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "Transfer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "account", type: "address" }, + { indexed: false, internalType: "bytes32", name: "message", type: "bytes32" }, + ], + name: "Unpaused", + type: "event", + }, + { + inputs: [ + { internalType: "bytes32", name: "_platformHash", type: "bytes32" }, + { internalType: "address", name: "_infoAddress", type: "address" }, + { internalType: "address", name: "_trustedForwarder", type: "address" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "pauseTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "unpauseTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "cancelTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "cancelled", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32[]", name: "rewardNames", type: "bytes32[]" }, + { + components: [...REWARD_TIER_COMPONENTS], + internalType: "struct KeepWhatsRaised.Reward[]", + name: "rewards", + type: "tuple[]", + }, + ], + name: "addRewards", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "claimRefund", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "disburseFees", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "getApproved", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getAvailableRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getWithdrawalApprovalStatus", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getLaunchTime", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getGoalAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "pledgeId", type: "bytes32" }], + name: "getPaymentGatewayFee", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "feeKey", type: "bytes32" }], + name: "getFeeValue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "pledgeId", type: "bytes32" }, + { internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "setPaymentGatewayFee", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "approveWithdrawal", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [...CONFIG_COMPONENTS], + internalType: "struct KeepWhatsRaised.Config", + name: "config", + type: "tuple", + }, + { + components: [...CAMPAIGN_DATA_COMPONENTS], + internalType: "struct ICampaignData.CampaignData", + name: "campaignData", + type: "tuple", + }, + { + components: [...FEE_KEYS_COMPONENTS], + internalType: "struct KeepWhatsRaised.FeeKeys", + name: "feeKeys", + type: "tuple", + }, + { + components: [...FEE_VALUES_COMPONENTS], + internalType: "struct KeepWhatsRaised.FeeValues", + name: "feeValues", + type: "tuple", + }, + ], + name: "configureTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "deadline", type: "uint256" }], + name: "updateDeadline", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "goalAmount", type: "uint256" }], + name: "updateGoalAmount", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "pledgeId", type: "bytes32" }, + { internalType: "address", name: "backer", type: "address" }, + { internalType: "address", name: "pledgeToken", type: "address" }, + { internalType: "uint256", name: "pledgeAmount", type: "uint256" }, + { internalType: "uint256", name: "tip", type: "uint256" }, + { internalType: "uint256", name: "fee", type: "uint256" }, + { internalType: "bytes32[]", name: "reward", type: "bytes32[]" }, + { internalType: "bool", name: "isPledgeForAReward", type: "bool" }, + ], + name: "setFeeAndPledge", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "claimTip", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "claimFund", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "getLifetimeRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "rewardName", type: "bytes32" }], + name: "getReward", + outputs: [ + { + components: REWARD_TIER_COMPONENTS, + internalType: "struct KeepWhatsRaised.Reward", + name: "reward", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getPlatformHash", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getRefundedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getPlatformFeePercent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "operator", type: "address" }, + ], + name: "isApprovedForAll", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "ownerOf", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "pledgeId", type: "bytes32" }, + { internalType: "address", name: "backer", type: "address" }, + { internalType: "address", name: "pledgeToken", type: "address" }, + { internalType: "uint256", name: "tip", type: "uint256" }, + { internalType: "bytes32[]", name: "rewardNames", type: "bytes32[]" }, + ], + name: "pledgeForAReward", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "pledgeId", type: "bytes32" }, + { internalType: "address", name: "backer", type: "address" }, + { internalType: "address", name: "pledgeToken", type: "address" }, + { internalType: "uint256", name: "pledgeAmount", type: "uint256" }, + { internalType: "uint256", name: "tip", type: "uint256" }, + ], + name: "pledgeWithoutAReward", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "rewardName", type: "bytes32" }], + name: "removeReward", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "operator", type: "address" }, + { internalType: "bool", name: "approved", type: "bool" }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "tokenURI", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "token", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/abis/payment-treasury.ts b/packages/contracts/src/abis/payment-treasury.ts new file mode 100644 index 0000000..f8f9b08 --- /dev/null +++ b/packages/contracts/src/abis/payment-treasury.ts @@ -0,0 +1,465 @@ +/** + * PaymentTreasury / TimeConstrainedPaymentTreasury ABI — from ICampaignPaymentTreasury. + * Same interface for both; use this ABI for either contract. + */ +const PAYMENT_LINE_ITEM_COMPONENTS = [ + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "string", name: "label", type: "string" }, + { internalType: "bool", name: "countsTowardGoal", type: "bool" }, + { internalType: "bool", name: "applyProtocolFee", type: "bool" }, + { internalType: "bool", name: "canRefund", type: "bool" }, + { internalType: "bool", name: "instantTransfer", type: "bool" }, +] as const; + +const LINE_ITEM_COMPONENTS = [ + { internalType: "bytes32", name: "typeId", type: "bytes32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, +] as const; + +const EXTERNAL_FEES_COMPONENTS = [ + { internalType: "bytes32", name: "feeType", type: "bytes32" }, + { internalType: "uint256", name: "feeAmount", type: "uint256" }, +] as const; + +export const PAYMENT_TREASURY_ABI = [ + { inputs: [], name: "PaymentTreasuryUnAuthorized", type: "error" }, + { inputs: [], name: "PaymentTreasuryInvalidInput", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryPaymentAlreadyExist", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryPaymentAlreadyConfirmed", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryPaymentAlreadyExpired", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryPaymentNotExist", + type: "error", + }, + { inputs: [], name: "PaymentTreasuryCampaignInfoIsPaused", type: "error" }, + { + inputs: [{ internalType: "address", name: "token", type: "address" }], + name: "PaymentTreasuryTokenNotAccepted", + type: "error", + }, + { inputs: [], name: "PaymentTreasurySuccessConditionNotFulfilled", type: "error" }, + { inputs: [], name: "PaymentTreasuryFeeNotDisbursed", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryPaymentNotConfirmed", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryPaymentNotClaimable", + type: "error", + }, + { inputs: [], name: "PaymentTreasuryAlreadyWithdrawn", type: "error" }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentTreasuryCryptoPayment", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "withdrawalAmount", type: "uint256" }, + { internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "PaymentTreasuryInsufficientFundsForFee", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "required", type: "uint256" }, + { internalType: "uint256", name: "available", type: "uint256" }, + ], + name: "PaymentTreasuryInsufficientBalance", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "expiration", type: "uint256" }, + { internalType: "uint256", name: "maxExpiration", type: "uint256" }, + ], + name: "PaymentTreasuryExpirationExceedsMax", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "claimableAt", type: "uint256" }], + name: "PaymentTreasuryClaimWindowNotReached", + type: "error", + }, + { inputs: [], name: "PaymentTreasuryNoFundsToClaim", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "address", name: "buyerAddress", type: "address" }, + { indexed: true, internalType: "bytes32", name: "paymentId", type: "bytes32" }, + { indexed: false, internalType: "bytes32", name: "buyerId", type: "bytes32" }, + { indexed: true, internalType: "bytes32", name: "itemId", type: "bytes32" }, + { indexed: true, internalType: "address", name: "paymentToken", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "expiration", type: "uint256" }, + { indexed: false, internalType: "bool", name: "isCryptoPayment", type: "bool" }, + ], + name: "PaymentCreated", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentCancelled", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "PaymentConfirmed", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "bytes32[]", name: "paymentIds", type: "bytes32[]" }], + name: "PaymentBatchConfirmed", + type: "event", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "bytes32[]", name: "paymentIds", type: "bytes32[]" }], + name: "PaymentBatchCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: false, internalType: "uint256", name: "protocolShare", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "platformShare", type: "uint256" }, + ], + name: "FeesDisbursed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "fee", type: "uint256" }, + ], + name: "WithdrawalWithFeeSuccessful", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "paymentId", type: "bytes32" }, + { indexed: false, internalType: "uint256", name: "refundAmount", type: "uint256" }, + { indexed: true, internalType: "address", name: "claimer", type: "address" }, + ], + name: "RefundClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + { indexed: true, internalType: "address", name: "platformAdmin", type: "address" }, + ], + name: "NonGoalLineItemsClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "token", type: "address" }, + { indexed: false, internalType: "uint256", name: "platformAmount", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "protocolAmount", type: "uint256" }, + ], + name: "ExpiredFundsClaimed", + type: "event", + }, + { + inputs: [ + { internalType: "bytes32", name: "_platformHash", type: "bytes32" }, + { internalType: "address", name: "_infoAddress", type: "address" }, + { internalType: "address", name: "_trustedForwarder", type: "address" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "getplatformHash", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getplatformFeePercent", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getAvailableRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "getPaymentData", + outputs: [ + { + components: [ + { internalType: "address", name: "buyerAddress", type: "address" }, + { internalType: "bytes32", name: "buyerId", type: "bytes32" }, + { internalType: "bytes32", name: "itemId", type: "bytes32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "uint256", name: "expiration", type: "uint256" }, + { internalType: "bool", name: "isConfirmed", type: "bool" }, + { internalType: "bool", name: "isCryptoPayment", type: "bool" }, + { internalType: "uint256", name: "lineItemCount", type: "uint256" }, + { internalType: "address", name: "paymentToken", type: "address" }, + { + components: [...PAYMENT_LINE_ITEM_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.PaymentLineItem[]", + name: "lineItems", + type: "tuple[]", + }, + { + components: [...EXTERNAL_FEES_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.ExternalFees[]", + name: "externalFees", + type: "tuple[]", + }, + ], + internalType: "struct ICampaignPaymentTreasury.PaymentData", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getLifetimeRaisedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getRefundedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getExpectedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "cancelled", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "paymentId", type: "bytes32" }, + { internalType: "bytes32", name: "buyerId", type: "bytes32" }, + { internalType: "bytes32", name: "itemId", type: "bytes32" }, + { internalType: "address", name: "paymentToken", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "uint256", name: "expiration", type: "uint256" }, + { + components: [...LINE_ITEM_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.LineItem[]", + name: "lineItems", + type: "tuple[]", + }, + { + components: [...EXTERNAL_FEES_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.ExternalFees[]", + name: "externalFees", + type: "tuple[]", + }, + ], + name: "createPayment", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32[]", name: "paymentIds", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "buyerIds", type: "bytes32[]" }, + { internalType: "bytes32[]", name: "itemIds", type: "bytes32[]" }, + { internalType: "address[]", name: "paymentTokens", type: "address[]" }, + { internalType: "uint256[]", name: "amounts", type: "uint256[]" }, + { internalType: "uint256[]", name: "expirations", type: "uint256[]" }, + { + components: [...LINE_ITEM_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.LineItem[][]", + name: "lineItemsArray", + type: "tuple[][]", + }, + { + components: [...EXTERNAL_FEES_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.ExternalFees[][]", + name: "externalFeesArray", + type: "tuple[][]", + }, + ], + name: "createPaymentBatch", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "paymentId", type: "bytes32" }, + { internalType: "bytes32", name: "itemId", type: "bytes32" }, + { internalType: "address", name: "buyerAddress", type: "address" }, + { internalType: "address", name: "paymentToken", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { + components: [...LINE_ITEM_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.LineItem[]", + name: "lineItems", + type: "tuple[]", + }, + { + components: [...EXTERNAL_FEES_COMPONENTS], + internalType: "struct ICampaignPaymentTreasury.ExternalFees[]", + name: "externalFees", + type: "tuple[]", + }, + ], + name: "processCryptoPayment", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "cancelPayment", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "paymentId", type: "bytes32" }, + { internalType: "address", name: "buyerAddress", type: "address" }, + ], + name: "confirmPayment", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32[]", name: "paymentIds", type: "bytes32[]" }, + { internalType: "address[]", name: "buyerAddresses", type: "address[]" }, + ], + name: "confirmPaymentBatch", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "disburseFees", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "paymentId", type: "bytes32" }, + { internalType: "address", name: "refundAddress", type: "address" }, + ], + name: "claimRefund", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "paymentId", type: "bytes32" }], + name: "claimRefund", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "claimExpiredFunds", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "token", type: "address" }], + name: "claimNonGoalLineItems", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "pauseTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "unpauseTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "message", type: "bytes32" }], + name: "cancelTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/abis/treasury-factory.ts b/packages/contracts/src/abis/treasury-factory.ts new file mode 100644 index 0000000..1ba9eb8 --- /dev/null +++ b/packages/contracts/src/abis/treasury-factory.ts @@ -0,0 +1,110 @@ +/** + * TreasuryFactory ABI — from provided ITreasuryFactory + TreasuryFactory.sol. + * UUPS; initialize(globalParams); register/approve/disapprove/remove implementation; deploy returns address. + */ +export const TREASURY_FACTORY_ABI = [ + { inputs: [], name: "AdminAccessCheckerUnauthorized", type: "error" }, + { inputs: [], name: "TreasuryFactoryUnauthorized", type: "error" }, + { inputs: [], name: "TreasuryFactoryInvalidKey", type: "error" }, + { inputs: [], name: "TreasuryFactoryTreasuryCreationFailed", type: "error" }, + { inputs: [], name: "TreasuryFactoryInvalidAddress", type: "error" }, + { inputs: [], name: "TreasuryFactoryImplementationNotSet", type: "error" }, + { inputs: [], name: "TreasuryFactoryImplementationNotSetOrApproved", type: "error" }, + { inputs: [], name: "TreasuryFactoryTreasuryInitializationFailed", type: "error" }, + { inputs: [], name: "TreasuryFactorySettingPlatformInfoFailed", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { indexed: true, internalType: "uint256", name: "implementationId", type: "uint256" }, + { indexed: true, internalType: "address", name: "infoAddress", type: "address" }, + { indexed: false, internalType: "address", name: "treasuryAddress", type: "address" }, + ], + name: "TreasuryFactoryTreasuryDeployed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { indexed: true, internalType: "uint256", name: "implementationId", type: "uint256" }, + { indexed: true, internalType: "address", name: "implementation", type: "address" }, + ], + name: "TreasuryImplementationRegistered", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { indexed: true, internalType: "uint256", name: "implementationId", type: "uint256" }, + ], + name: "TreasuryImplementationRemoved", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "implementation", type: "address" }, + { indexed: false, internalType: "bool", name: "isApproved", type: "bool" }, + ], + name: "TreasuryImplementationApproval", + type: "event", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "uint256", name: "implementationId", type: "uint256" }, + { internalType: "address", name: "implementation", type: "address" }, + ], + name: "registerTreasuryImplementation", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "uint256", name: "implementationId", type: "uint256" }, + ], + name: "approveTreasuryImplementation", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "implementation", type: "address" }], + name: "disapproveTreasuryImplementation", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "uint256", name: "implementationId", type: "uint256" }, + ], + name: "removeTreasuryImplementation", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "platformHash", type: "bytes32" }, + { internalType: "address", name: "infoAddress", type: "address" }, + { internalType: "uint256", name: "implementationId", type: "uint256" }, + ], + name: "deploy", + outputs: [{ internalType: "address", name: "clone", type: "address" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "contract IGlobalParams", name: "globalParams", type: "address" }], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/contracts/src/client/index.ts b/packages/contracts/src/client/index.ts new file mode 100644 index 0000000..609cbfd --- /dev/null +++ b/packages/contracts/src/client/index.ts @@ -0,0 +1,164 @@ +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import type { Address, Hex, PublicClient, WalletClient } from "viem"; +import type { Chain } from "viem/chains"; +import type { + ChainIdentifier, + OakContractsClient, + OakContractsClientConfig, + PublicOakContractsClientConfig, + FullOakContractsClientConfig, + SimpleOakContractsClientConfig, + TransactionReceipt, + GlobalParamsEntity, + CampaignInfoFactoryEntity, + TreasuryFactoryEntity, + CampaignInfoEntity, + PaymentTreasuryEntity, + AllOrNothingTreasuryEntity, + KeepWhatsRaisedTreasuryEntity, + ItemRegistryEntity, +} from "../types"; +import { DEFAULT_CLIENT_OPTIONS, type OakContractsClientOptions } from "../types"; +import { getChainFromId } from "../utils/chain-registry"; +import { createGlobalParamsEntity } from "../contracts/global-params"; +import { createCampaignInfoFactoryEntity } from "../contracts/campaign-info-factory"; +import { createTreasuryFactoryEntity } from "../contracts/treasury-factory"; +import { createCampaignInfoEntity } from "../contracts/campaign-info"; +import { createPaymentTreasuryEntity } from "../contracts/payment-treasury"; +import { createAllOrNothingEntity } from "../contracts/all-or-nothing"; +import { createKeepWhatsRaisedEntity } from "../contracts/keep-whats-raised"; +import { createItemRegistryEntity } from "../contracts/item-registry"; + +/** + * Type guard for simple client config (chainId + rpcUrl + privateKey). + */ +function isSimpleConfig( + config: OakContractsClientConfig, +): config is SimpleOakContractsClientConfig { + return ( + "chainId" in config && + "rpcUrl" in config && + "privateKey" in config && + typeof (config as SimpleOakContractsClientConfig).chainId === "number" && + typeof (config as SimpleOakContractsClientConfig).rpcUrl === "string" && + (config as SimpleOakContractsClientConfig).rpcUrl.length > 0 && + typeof (config as SimpleOakContractsClientConfig).privateKey === "string" && + (config as SimpleOakContractsClientConfig).privateKey.startsWith("0x") + ); +} + +/** + * Resolves a chain identifier (number or Chain object) to a Chain object. + */ +function resolveChain(chain: ChainIdentifier): Chain { + if (typeof chain === "number") { + return getChainFromId(chain); + } + return chain; +} + +/** + * Builds viem publicClient and walletClient from the given config. + */ +function buildClients(config: OakContractsClientConfig, options: OakContractsClientOptions): { + chain: Chain; + publicClient: PublicClient; + walletClient: WalletClient; +} { + if (isSimpleConfig(config)) { + const chain = getChainFromId(config.chainId); + const transport = http(config.rpcUrl, { timeout: options.timeout }); + const publicClient = createPublicClient({ chain, transport }); + const account = privateKeyToAccount(config.privateKey); + const walletClient = createWalletClient({ account, chain, transport }); + return { chain, publicClient, walletClient }; + } + + const fullConfig = config as FullOakContractsClientConfig; + const chain = resolveChain(fullConfig.chain); + return { + chain, + publicClient: fullConfig.provider as PublicClient, + walletClient: fullConfig.signer as WalletClient, + }; +} + +/** + * Creates a new Oak Contracts SDK client instance. + * Supports simple config (chainId, rpcUrl, privateKey) or full config (chain, provider, signer). + * + * @param config - Simple: `{ chainId, rpcUrl, privateKey }` or full: `{ chain, provider, signer }` + * @returns Configured OakContractsClient + * + * @example + * ```typescript + * const oak = createOakContractsClient({ + * chainId: CHAIN_IDS.CELO_TESTNET_SEPOLIA, + * rpcUrl: "https://forno.celo-sepolia.org", + * privateKey: "0x...", + * }); + * + * const gp = oak.globalParams(GP_ADDRESS); + * const admin = await gp.getProtocolAdminAddress(); + * + * const factory = oak.campaignInfoFactory(FACTORY_ADDRESS); + * const txHash = await factory.createCampaign({ creator, identifierHash, campaignData, ... }); + * ``` + */ +export function createOakContractsClient( + config: OakContractsClientConfig, +): OakContractsClient { + const options: OakContractsClientOptions = { + ...DEFAULT_CLIENT_OPTIONS, + ...config?.options, + }; + + const { chain, publicClient, walletClient } = buildClients(config, options); + const publicConfig: PublicOakContractsClientConfig = { chain }; + + async function waitForReceipt(txHash: Hex): Promise { + const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, timeout: options.timeout }); + return { + blockNumber: receipt.blockNumber, + gasUsed: receipt.gasUsed, + logs: receipt.logs.map((log) => ({ + topics: log.topics as readonly Hex[], + data: log.data, + })), + }; + } + + return { + config: publicConfig, + options, + publicClient, + walletClient, + waitForReceipt, + + globalParams(address: Address): GlobalParamsEntity { + return createGlobalParamsEntity(address, publicClient, walletClient, chain); + }, + campaignInfoFactory(address: Address): CampaignInfoFactoryEntity { + return createCampaignInfoFactoryEntity(address, publicClient, walletClient, chain); + }, + treasuryFactory(address: Address): TreasuryFactoryEntity { + return createTreasuryFactoryEntity(address, walletClient, chain); + }, + campaignInfo(address: Address): CampaignInfoEntity { + return createCampaignInfoEntity(address, publicClient, walletClient, chain); + }, + paymentTreasury(address: Address): PaymentTreasuryEntity { + return createPaymentTreasuryEntity(address, publicClient, walletClient, chain); + }, + allOrNothingTreasury(address: Address): AllOrNothingTreasuryEntity { + return createAllOrNothingEntity(address, publicClient, walletClient, chain); + }, + keepWhatsRaisedTreasury(address: Address): KeepWhatsRaisedTreasuryEntity { + return createKeepWhatsRaisedEntity(address, publicClient, walletClient, chain); + }, + itemRegistry(address: Address): ItemRegistryEntity { + return createItemRegistryEntity(address, publicClient, walletClient, chain); + }, + }; +} diff --git a/packages/contracts/src/constants/index.ts b/packages/contracts/src/constants/index.ts new file mode 100644 index 0000000..2d8a2bb --- /dev/null +++ b/packages/contracts/src/constants/index.ts @@ -0,0 +1,51 @@ +import { keccak256, toHex, encodeAbiParameters, type Hex } from "viem"; + +/** + * Common chain IDs for use with createOakContractsClient({ chainId, rpcUrl, privateKey }). + * Naming convention: {CHAIN}_{MAINNET|TESTNET} + */ +export const CHAIN_IDS = { + // Mainnets + ETHEREUM_MAINNET: 1, + CELO_MAINNET: 42220, + // Testnets + ETHEREUM_TESTNET_SEPOLIA: 11155111, + ETHEREUM_TESTNET_GOERLI: 5, + CELO_TESTNET_SEPOLIA: 11142220, +} as const; + +/** Basis points denominator used for fee calculations (100% = 10_000 bps) */ +export const BPS_DENOMINATOR = 10_000n; + +/** Zero bytes32 value */ +export const BYTES32_ZERO: Hex = `0x${"00".repeat(32)}`; + +/** ERC-165 interface IDs */ +export const INTERFACE_IDS = { + ERC721: "0x80ac58cd", + ERC721Metadata: "0x5b5e139f", + ERC2612: "0xd505accf", +} as const; + +/** + * Data registry keys used in GlobalParams (matches DataRegistryKeys.sol). + * Use these when reading/writing GlobalParams data registry or with getDataFromRegistry. + */ +export const DATA_REGISTRY_KEYS = { + BUFFER_TIME: keccak256(toHex("bufferTime")), + MAX_PAYMENT_EXPIRATION: keccak256(toHex("maxPaymentExpiration")), + CAMPAIGN_LAUNCH_BUFFER: keccak256(toHex("campaignLaunchBuffer")), + MINIMUM_CAMPAIGN_DURATION: keccak256(toHex("minimumCampaignDuration")), +} as const; + +/** + * Generates a namespaced registry key scoped to a platform (matches DataRegistryKeys.scopedToPlatform). + */ +export function scopedToPlatform(baseKey: Hex, platformHash: Hex): Hex { + return keccak256( + encodeAbiParameters( + [{ type: "bytes32" }, { type: "bytes32" }], + [baseKey, platformHash], + ), + ); +} diff --git a/packages/contracts/src/contracts/all-or-nothing.ts b/packages/contracts/src/contracts/all-or-nothing.ts new file mode 100644 index 0000000..e7798bb --- /dev/null +++ b/packages/contracts/src/contracts/all-or-nothing.ts @@ -0,0 +1,155 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { ALL_OR_NOTHING_ABI } from "../abis/all-or-nothing"; +import type { AllOrNothingTreasuryEntity, TieredReward } from "../types"; + +/** + * Creates an AllOrNothing treasury entity with full read/write access. + * + * @param address - Deployed AllOrNothing treasury contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns AllOrNothingTreasuryEntity + * + * @example + * ```typescript + * const aon = createAllOrNothingEntity(AON_ADDRESS, publicClient, walletClient, chain); + * const raised = await aon.getRaisedAmount(); + * await aon.pledgeForAReward(backer, token, shippingFee, rewardNames); + * ``` + */ +export function createAllOrNothingEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): AllOrNothingTreasuryEntity { + const contract = { address, abi: ALL_OR_NOTHING_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + // ── Reads ──────────────────────────────────────────────────────────────── + + async getRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getRaisedAmount" }); + }, + async getLifetimeRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getLifetimeRaisedAmount" }); + }, + async getRefundedAmount() { + return publicClient.readContract({ ...contract, functionName: "getRefundedAmount" }); + }, + async getReward(rewardName: Hex): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getReward", args: [rewardName] }); + return result as unknown as TieredReward; + }, + async getPlatformHash() { + return publicClient.readContract({ ...contract, functionName: "getPlatformHash" }); + }, + async getPlatformFeePercent() { + return publicClient.readContract({ ...contract, functionName: "getPlatformFeePercent" }); + }, + async paused() { + return publicClient.readContract({ ...contract, functionName: "paused" }); + }, + async cancelled() { + return publicClient.readContract({ ...contract, functionName: "cancelled" }); + }, + async balanceOf(owner: Address) { + return publicClient.readContract({ ...contract, functionName: "balanceOf", args: [owner] }); + }, + async ownerOf(tokenId: bigint) { + return publicClient.readContract({ ...contract, functionName: "ownerOf", args: [tokenId] }); + }, + async tokenURI(tokenId: bigint) { + return publicClient.readContract({ ...contract, functionName: "tokenURI", args: [tokenId] }); + }, + async name() { + return publicClient.readContract({ ...contract, functionName: "name" }); + }, + async symbol() { + return publicClient.readContract({ ...contract, functionName: "symbol" }); + }, + async getApproved(tokenId: bigint) { + return publicClient.readContract({ ...contract, functionName: "getApproved", args: [tokenId] }); + }, + async isApprovedForAll(owner: Address, operator: Address) { + return publicClient.readContract({ ...contract, functionName: "isApprovedForAll", args: [owner, operator] }); + }, + async supportsInterface(interfaceId: Hex) { + return publicClient.readContract({ ...contract, functionName: "supportsInterface", args: [interfaceId as `0x${string}`] }); + }, + + // ── Writes ─────────────────────────────────────────────────────────────── + + async pauseTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pauseTreasury", args: [message] }); + }, + async unpauseTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "unpauseTreasury", args: [message] }); + }, + async cancelTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "cancelTreasury", args: [message] }); + }, + async addRewards(rewardNames: readonly Hex[], rewards: readonly TieredReward[]) { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "addRewards", + args: [[...rewardNames], rewards.map((r) => ({ rewardValue: r.rewardValue, isRewardTier: r.isRewardTier, itemId: [...r.itemId], itemValue: [...r.itemValue], itemQuantity: [...r.itemQuantity] }))], + }); + }, + async removeReward(rewardName: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "removeReward", args: [rewardName] }); + }, + async pledgeForAReward(backer: Address, pledgeToken: Address, shippingFee: bigint, rewardNames: readonly Hex[]) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pledgeForAReward", args: [backer, pledgeToken, shippingFee, [...rewardNames]] }); + }, + async pledgeWithoutAReward(backer: Address, pledgeToken: Address, pledgeAmount: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pledgeWithoutAReward", args: [backer, pledgeToken, pledgeAmount] }); + }, + async claimRefund(tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimRefund", args: [tokenId] }); + }, + async disburseFees() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "disburseFees", args: [] }); + }, + async withdraw() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "withdraw", args: [] }); + }, + async burn(tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "burn", args: [tokenId] }); + }, + async approve(to: Address, tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "approve", args: [to, tokenId] }); + }, + async setApprovalForAll(operator: Address, approved: boolean) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setApprovalForAll", args: [operator, approved] }); + }, + async safeTransferFrom(from: Address, to: Address, tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "safeTransferFrom", args: [from, to, tokenId] }); + }, + async transferFrom(from: Address, to: Address, tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "transferFrom", args: [from, to, tokenId] }); + }, + }; +} diff --git a/packages/contracts/src/contracts/campaign-info-factory.ts b/packages/contracts/src/contracts/campaign-info-factory.ts new file mode 100644 index 0000000..9807e7e --- /dev/null +++ b/packages/contracts/src/contracts/campaign-info-factory.ts @@ -0,0 +1,121 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { CAMPAIGN_INFO_FACTORY_ABI } from "../abis/campaign-info-factory"; +import type { CampaignInfoFactoryEntity, CreateCampaignParams } from "../types"; + +/** + * Creates a CampaignInfoFactory entity with full read/write access. + * + * @param address - Deployed CampaignInfoFactory contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns CampaignInfoFactoryEntity + * + * @example + * ```typescript + * const factory = createCampaignInfoFactoryEntity(FACTORY_ADDRESS, publicClient, walletClient, chain); + * const txHash = await factory.createCampaign({ creator, identifierHash, campaignData, ... }); + * const address = await factory.identifierToCampaignInfo(identifierHash); + * ``` + */ +export function createCampaignInfoFactoryEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): CampaignInfoFactoryEntity { + const contract = { address, abi: CAMPAIGN_INFO_FACTORY_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + // ── Writes ────────────────────────────────────────────────────────────── + + async createCampaign(params: CreateCampaignParams): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "createCampaign", + args: [ + params.creator, + params.identifierHash, + [...params.selectedPlatformHash], + [...(params.platformDataKey ?? [])], + [...(params.platformDataValue ?? [])], + { + launchTime: params.campaignData.launchTime, + deadline: params.campaignData.deadline, + goalAmount: params.campaignData.goalAmount, + currency: params.campaignData.currency, + }, + params.nftName, + params.nftSymbol, + params.nftImageURI, + params.contractURI, + ], + }); + }, + + async updateImplementation(newImplementation: Address): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "updateImplementation", + args: [newImplementation], + }); + }, + + async transferOwnership(newOwner: Address): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "transferOwnership", + args: [newOwner], + }); + }, + + async renounceOwnership(): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "renounceOwnership", + args: [], + }); + }, + + // ── Reads ──────────────────────────────────────────────────────────────── + + async identifierToCampaignInfo(identifierHash: Hex): Promise
{ + return publicClient.readContract({ + ...contract, + functionName: "identifierToCampaignInfo", + args: [identifierHash], + }); + }, + + async isValidCampaignInfo(campaignInfo: Address): Promise { + return publicClient.readContract({ + ...contract, + functionName: "isValidCampaignInfo", + args: [campaignInfo], + }); + }, + + async owner(): Promise
{ + return publicClient.readContract({ ...contract, functionName: "owner" }); + }, + }; +} diff --git a/packages/contracts/src/contracts/campaign-info.ts b/packages/contracts/src/contracts/campaign-info.ts new file mode 100644 index 0000000..6bce90c --- /dev/null +++ b/packages/contracts/src/contracts/campaign-info.ts @@ -0,0 +1,191 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { CAMPAIGN_INFO_ABI } from "../abis/campaign-info"; +import type { CampaignInfoEntity, LineItemTypeInfo, CampaignConfig } from "../types"; + +/** + * Creates a CampaignInfo entity with full read/write access. + * + * @param address - Deployed CampaignInfo contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns CampaignInfoEntity + * + * @example + * ```typescript + * const ci = createCampaignInfoEntity(CAMPAIGN_INFO_ADDRESS, publicClient, walletClient, chain); + * const deadline = await ci.getDeadline(); + * await ci.updateDeadline(newDeadline); + * ``` + */ +export function createCampaignInfoEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): CampaignInfoEntity { + const contract = { address, abi: CAMPAIGN_INFO_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + // ── Reads ──────────────────────────────────────────────────────────────── + + async getLaunchTime() { + return publicClient.readContract({ ...contract, functionName: "getLaunchTime" }); + }, + async getDeadline() { + return publicClient.readContract({ ...contract, functionName: "getDeadline" }); + }, + async getGoalAmount() { + return publicClient.readContract({ ...contract, functionName: "getGoalAmount" }); + }, + async getCampaignCurrency() { + return publicClient.readContract({ ...contract, functionName: "getCampaignCurrency" }); + }, + async getIdentifierHash() { + return publicClient.readContract({ ...contract, functionName: "getIdentifierHash" }); + }, + async checkIfPlatformSelected(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "checkIfPlatformSelected", args: [platformBytes] }); + }, + async checkIfPlatformApproved(platformHash: Hex) { + return publicClient.readContract({ ...contract, functionName: "checkIfPlatformApproved", args: [platformHash] }); + }, + async getPlatformAdminAddress(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformAdminAddress", args: [platformBytes] }); + }, + async getPlatformData(platformDataKey: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformData", args: [platformDataKey] }); + }, + async getPlatformFeePercent(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformFeePercent", args: [platformBytes] }); + }, + async getPlatformClaimDelay(platformHash: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformClaimDelay", args: [platformHash] }); + }, + async getProtocolAdminAddress() { + return publicClient.readContract({ ...contract, functionName: "getProtocolAdminAddress" }); + }, + async getProtocolFeePercent() { + return publicClient.readContract({ ...contract, functionName: "getProtocolFeePercent" }); + }, + async getAcceptedTokens() { + return publicClient.readContract({ ...contract, functionName: "getAcceptedTokens" }); + }, + async isTokenAccepted(token: Address) { + return publicClient.readContract({ ...contract, functionName: "isTokenAccepted", args: [token] }); + }, + async getTotalRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getTotalRaisedAmount" }); + }, + async getTotalLifetimeRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getTotalLifetimeRaisedAmount" }); + }, + async getTotalRefundedAmount() { + return publicClient.readContract({ ...contract, functionName: "getTotalRefundedAmount" }); + }, + async getTotalAvailableRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getTotalAvailableRaisedAmount" }); + }, + async getTotalCancelledAmount() { + return publicClient.readContract({ ...contract, functionName: "getTotalCancelledAmount" }); + }, + async getTotalExpectedAmount() { + return publicClient.readContract({ ...contract, functionName: "getTotalExpectedAmount" }); + }, + async getDataFromRegistry(key: Hex) { + return publicClient.readContract({ ...contract, functionName: "getDataFromRegistry", args: [key] }); + }, + async getBufferTime() { + return publicClient.readContract({ ...contract, functionName: "getBufferTime" }); + }, + async getLineItemType(platformHash: Hex, typeId: Hex): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getLineItemType", args: [platformHash, typeId] }); + return result as unknown as LineItemTypeInfo; + }, + async getCampaignConfig(): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getCampaignConfig" }); + return result as unknown as CampaignConfig; + }, + async getApprovedPlatformHashes() { + return publicClient.readContract({ ...contract, functionName: "getApprovedPlatformHashes" }); + }, + async isLocked() { + return publicClient.readContract({ ...contract, functionName: "isLocked" }); + }, + async cancelled() { + return publicClient.readContract({ ...contract, functionName: "cancelled" }); + }, + async owner() { + return publicClient.readContract({ ...contract, functionName: "owner" }); + }, + async paused() { + return publicClient.readContract({ ...contract, functionName: "paused" }); + }, + + // ── Writes ─────────────────────────────────────────────────────────────── + + async updateDeadline(deadline: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateDeadline", args: [deadline] }); + }, + async updateGoalAmount(goalAmount: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateGoalAmount", args: [goalAmount] }); + }, + async updateLaunchTime(launchTime: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateLaunchTime", args: [launchTime] }); + }, + async updateSelectedPlatform(platformHash: Hex, selection: boolean, platformDataKey: readonly Hex[], platformDataValue: readonly Hex[]) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateSelectedPlatform", args: [platformHash, selection, [...platformDataKey], [...platformDataValue]] }); + }, + async setImageURI(newImageURI: string) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setImageURI", args: [newImageURI] }); + }, + async updateContractURI(newContractURI: string) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateContractURI", args: [newContractURI] }); + }, + async mintNFTForPledge(backer: Address, reward: Hex, tokenAddress: Address, amount: bigint, shippingFee: bigint, tipAmount: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "mintNFTForPledge", args: [backer, reward, tokenAddress, amount, shippingFee, tipAmount] }); + }, + async burn(tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "burn", args: [tokenId] }); + }, + async pauseCampaign(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "_pauseCampaign", args: [message] }); + }, + async unpauseCampaign(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "_unpauseCampaign", args: [message] }); + }, + async cancelCampaign(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "_cancelCampaign", args: [message] }); + }, + async setPlatformInfo(platformBytes: Hex, platformTreasuryAddress: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "_setPlatformInfo", args: [platformBytes, platformTreasuryAddress] }); + }, + async transferOwnership(newOwner: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "transferOwnership", args: [newOwner] }); + }, + async renounceOwnership() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "renounceOwnership", args: [] }); + }, + }; +} diff --git a/packages/contracts/src/contracts/global-params.ts b/packages/contracts/src/contracts/global-params.ts new file mode 100644 index 0000000..fb9fb3f --- /dev/null +++ b/packages/contracts/src/contracts/global-params.ts @@ -0,0 +1,154 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { GLOBAL_PARAMS_ABI } from "../abis/global-params"; +import type { GlobalParamsEntity, LineItemTypeInfo } from "../types"; + +/** + * Creates a GlobalParams entity with full read/write access. + * + * @param address - Deployed GlobalParams contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns GlobalParamsEntity + * + * @example + * ```typescript + * const gp = createGlobalParamsEntity(GP_ADDRESS, publicClient, walletClient, chain); + * const admin = await gp.getProtocolAdminAddress(); + * await gp.enlistPlatform(platformHash, adminAddr, 500n, adapterAddr); + * ``` + */ +export function createGlobalParamsEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): GlobalParamsEntity { + const contract = { address, abi: GLOBAL_PARAMS_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + // ── Reads ──────────────────────────────────────────────────────────────── + + async getProtocolAdminAddress() { + return publicClient.readContract({ ...contract, functionName: "getProtocolAdminAddress" }); + }, + async getProtocolFeePercent() { + return publicClient.readContract({ ...contract, functionName: "getProtocolFeePercent" }); + }, + async getNumberOfListedPlatforms() { + return publicClient.readContract({ ...contract, functionName: "getNumberOfListedPlatforms" }); + }, + async checkIfPlatformIsListed(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "checkIfPlatformIsListed", args: [platformBytes] }); + }, + async checkIfPlatformDataKeyValid(platformDataKey: Hex) { + return publicClient.readContract({ ...contract, functionName: "checkIfPlatformDataKeyValid", args: [platformDataKey] }); + }, + async getPlatformAdminAddress(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformAdminAddress", args: [platformBytes] }); + }, + async getPlatformFeePercent(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformFeePercent", args: [platformBytes] }); + }, + async getPlatformClaimDelay(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformClaimDelay", args: [platformBytes] }); + }, + async getPlatformAdapter(platformBytes: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformAdapter", args: [platformBytes] }); + }, + async getPlatformDataOwner(platformDataKey: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPlatformDataOwner", args: [platformDataKey] }); + }, + async getPlatformLineItemType(platformHash: Hex, typeId: Hex): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getPlatformLineItemType", args: [platformHash, typeId] }); + // viem returns named tuple outputs as an object + return result as unknown as LineItemTypeInfo; + }, + async getTokensForCurrency(currency: Hex) { + return publicClient.readContract({ ...contract, functionName: "getTokensForCurrency", args: [currency] }); + }, + async getFromRegistry(key: Hex) { + return publicClient.readContract({ ...contract, functionName: "getFromRegistry", args: [key] }); + }, + async owner() { + return publicClient.readContract({ ...contract, functionName: "owner" }); + }, + async paused() { + return publicClient.readContract({ ...contract, functionName: "paused" }); + }, + + // ── Writes ─────────────────────────────────────────────────────────────── + + async enlistPlatform(platformHash: Hex, platformAdminAddress: Address, platformFeePercent: bigint, platformAdapter: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "enlistPlatform", args: [platformHash, platformAdminAddress, platformFeePercent, platformAdapter] }); + }, + async delistPlatform(platformBytes: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "delistPlatform", args: [platformBytes] }); + }, + async updatePlatformAdminAddress(platformBytes: Hex, platformAdminAddress: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updatePlatformAdminAddress", args: [platformBytes, platformAdminAddress] }); + }, + async updatePlatformClaimDelay(platformBytes: Hex, claimDelay: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updatePlatformClaimDelay", args: [platformBytes, claimDelay] }); + }, + async updateProtocolAdminAddress(protocolAdminAddress: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateProtocolAdminAddress", args: [protocolAdminAddress] }); + }, + async updateProtocolFeePercent(protocolFeePercent: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateProtocolFeePercent", args: [protocolFeePercent] }); + }, + async setPlatformAdapter(platformBytes: Hex, platformAdapter: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setPlatformAdapter", args: [platformBytes, platformAdapter] }); + }, + async setPlatformLineItemType(platformHash: Hex, typeId: Hex, label: string, countsTowardGoal: boolean, applyProtocolFee: boolean, canRefund: boolean, instantTransfer: boolean) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setPlatformLineItemType", args: [platformHash, typeId, label, countsTowardGoal, applyProtocolFee, canRefund, instantTransfer] }); + }, + async removePlatformLineItemType(platformHash: Hex, typeId: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "removePlatformLineItemType", args: [platformHash, typeId] }); + }, + async addTokenToCurrency(currency: Hex, token: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "addTokenToCurrency", args: [currency, token] }); + }, + async removeTokenFromCurrency(currency: Hex, token: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "removeTokenFromCurrency", args: [currency, token] }); + }, + async addPlatformData(platformBytes: Hex, platformDataKey: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "addPlatformData", args: [platformBytes, platformDataKey] }); + }, + async removePlatformData(platformBytes: Hex, platformDataKey: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "removePlatformData", args: [platformBytes, platformDataKey] }); + }, + async addToRegistry(key: Hex, value: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "addToRegistry", args: [key, value] }); + }, + async transferOwnership(newOwner: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "transferOwnership", args: [newOwner] }); + }, + async renounceOwnership() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "renounceOwnership", args: [] }); + }, + }; +} diff --git a/packages/contracts/src/contracts/index.ts b/packages/contracts/src/contracts/index.ts new file mode 100644 index 0000000..44a1f55 --- /dev/null +++ b/packages/contracts/src/contracts/index.ts @@ -0,0 +1,8 @@ +export { createGlobalParamsEntity } from "./global-params"; +export { createCampaignInfoFactoryEntity } from "./campaign-info-factory"; +export { createTreasuryFactoryEntity } from "./treasury-factory"; +export { createCampaignInfoEntity } from "./campaign-info"; +export { createPaymentTreasuryEntity } from "./payment-treasury"; +export { createAllOrNothingEntity } from "./all-or-nothing"; +export { createKeepWhatsRaisedEntity } from "./keep-whats-raised"; +export { createItemRegistryEntity } from "./item-registry"; diff --git a/packages/contracts/src/contracts/item-registry.ts b/packages/contracts/src/contracts/item-registry.ts new file mode 100644 index 0000000..306ea02 --- /dev/null +++ b/packages/contracts/src/contracts/item-registry.ts @@ -0,0 +1,58 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { ITEM_REGISTRY_ABI } from "../abis/item-registry"; +import type { ItemRegistryEntity, Item } from "../types"; + +/** + * Creates an ItemRegistry entity with full read/write access. + * + * @param address - Deployed ItemRegistry contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns ItemRegistryEntity + * + * @example + * ```typescript + * const ir = createItemRegistryEntity(IR_ADDRESS, publicClient, walletClient, chain); + * const item = await ir.getItem(ownerAddress, itemId); + * await ir.addItem(itemId, { actualWeight, height, width, length, category, declaredCurrency }); + * ``` + */ +export function createItemRegistryEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): ItemRegistryEntity { + const contract = { address, abi: ITEM_REGISTRY_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + async getItem(owner: Address, itemId: Hex): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getItem", args: [owner, itemId] }); + return result as unknown as Item; + }, + + async addItem(itemId: Hex, item: Item): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "addItem", + args: [itemId, { actualWeight: item.actualWeight, height: item.height, width: item.width, length: item.length, category: item.category, declaredCurrency: item.declaredCurrency }], + }); + }, + + async addItemsBatch(itemIds: readonly Hex[], items: readonly Item[]): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "addItemsBatch", + args: [[...itemIds], items.map((item) => ({ actualWeight: item.actualWeight, height: item.height, width: item.width, length: item.length, category: item.category, declaredCurrency: item.declaredCurrency }))], + }); + }, + }; +} diff --git a/packages/contracts/src/contracts/keep-whats-raised.ts b/packages/contracts/src/contracts/keep-whats-raised.ts new file mode 100644 index 0000000..51a20ee --- /dev/null +++ b/packages/contracts/src/contracts/keep-whats-raised.ts @@ -0,0 +1,212 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { KEEP_WHATS_RAISED_ABI } from "../abis/keep-whats-raised"; +import type { KeepWhatsRaisedTreasuryEntity, TieredReward, CampaignData, KeepWhatsRaisedConfig, KeepWhatsRaisedFeeKeys, KeepWhatsRaisedFeeValues } from "../types"; + +/** + * Creates a KeepWhatsRaised treasury entity with full read/write access. + * + * @param address - Deployed KeepWhatsRaised treasury contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns KeepWhatsRaisedTreasuryEntity + * + * @example + * ```typescript + * const kwr = createKeepWhatsRaisedEntity(KWR_ADDRESS, publicClient, walletClient, chain); + * await kwr.configureTreasury(config, campaignData, feeKeys, feeValues); + * await kwr.pledgeForAReward(pledgeId, backer, token, tip, rewardNames); + * ``` + */ +export function createKeepWhatsRaisedEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): KeepWhatsRaisedTreasuryEntity { + const contract = { address, abi: KEEP_WHATS_RAISED_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + // ── Reads ──────────────────────────────────────────────────────────────── + + async getRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getRaisedAmount" }); + }, + async getLifetimeRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getLifetimeRaisedAmount" }); + }, + async getRefundedAmount() { + return publicClient.readContract({ ...contract, functionName: "getRefundedAmount" }); + }, + async getAvailableRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getAvailableRaisedAmount" }); + }, + async getReward(rewardName: Hex): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getReward", args: [rewardName] }); + return result as unknown as TieredReward; + }, + async getPlatformHash() { + return publicClient.readContract({ ...contract, functionName: "getPlatformHash" }); + }, + async getPlatformFeePercent() { + return publicClient.readContract({ ...contract, functionName: "getPlatformFeePercent" }); + }, + async getWithdrawalApprovalStatus() { + return publicClient.readContract({ ...contract, functionName: "getWithdrawalApprovalStatus" }); + }, + async getLaunchTime() { + return publicClient.readContract({ ...contract, functionName: "getLaunchTime" }); + }, + async getDeadline() { + return publicClient.readContract({ ...contract, functionName: "getDeadline" }); + }, + async getGoalAmount() { + return publicClient.readContract({ ...contract, functionName: "getGoalAmount" }); + }, + async getPaymentGatewayFee(pledgeId: Hex) { + return publicClient.readContract({ ...contract, functionName: "getPaymentGatewayFee", args: [pledgeId] }); + }, + async getFeeValue(feeKey: Hex) { + return publicClient.readContract({ ...contract, functionName: "getFeeValue", args: [feeKey] }); + }, + async paused() { + return publicClient.readContract({ ...contract, functionName: "paused" }); + }, + async cancelled() { + return publicClient.readContract({ ...contract, functionName: "cancelled" }); + }, + async balanceOf(owner: Address) { + return publicClient.readContract({ ...contract, functionName: "balanceOf", args: [owner] }); + }, + async ownerOf(tokenId: bigint) { + return publicClient.readContract({ ...contract, functionName: "ownerOf", args: [tokenId] }); + }, + async tokenURI(tokenId: bigint) { + return publicClient.readContract({ ...contract, functionName: "tokenURI", args: [tokenId] }); + }, + async name() { + return publicClient.readContract({ ...contract, functionName: "name" }); + }, + async symbol() { + return publicClient.readContract({ ...contract, functionName: "symbol" }); + }, + async getApproved(tokenId: bigint) { + return publicClient.readContract({ ...contract, functionName: "getApproved", args: [tokenId] }); + }, + async isApprovedForAll(owner: Address, operator: Address) { + return publicClient.readContract({ ...contract, functionName: "isApprovedForAll", args: [owner, operator] }); + }, + async supportsInterface(interfaceId: Hex) { + return publicClient.readContract({ ...contract, functionName: "supportsInterface", args: [interfaceId as `0x${string}`] }); + }, + + // ── Writes ─────────────────────────────────────────────────────────────── + + async pauseTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pauseTreasury", args: [message] }); + }, + async unpauseTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "unpauseTreasury", args: [message] }); + }, + async cancelTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "cancelTreasury", args: [message] }); + }, + async configureTreasury(config: KeepWhatsRaisedConfig, campaignData: CampaignData, feeKeys: KeepWhatsRaisedFeeKeys, feeValues: KeepWhatsRaisedFeeValues) { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "configureTreasury", + args: [ + { minimumWithdrawalForFeeExemption: config.minimumWithdrawalForFeeExemption, withdrawalDelay: config.withdrawalDelay, refundDelay: config.refundDelay, configLockPeriod: config.configLockPeriod, isColombianCreator: config.isColombianCreator }, + { launchTime: campaignData.launchTime, deadline: campaignData.deadline, goalAmount: campaignData.goalAmount, currency: campaignData.currency }, + { flatFeeKey: feeKeys.flatFeeKey, cumulativeFlatFeeKey: feeKeys.cumulativeFlatFeeKey, grossPercentageFeeKeys: [...feeKeys.grossPercentageFeeKeys] }, + { flatFeeValue: feeValues.flatFeeValue, cumulativeFlatFeeValue: feeValues.cumulativeFlatFeeValue, grossPercentageFeeValues: [...feeValues.grossPercentageFeeValues] }, + ], + }); + }, + async addRewards(rewardNames: readonly Hex[], rewards: readonly TieredReward[]) { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "addRewards", + args: [[...rewardNames], rewards.map((r) => ({ rewardValue: r.rewardValue, isRewardTier: r.isRewardTier, itemId: [...r.itemId], itemValue: [...r.itemValue], itemQuantity: [...r.itemQuantity] }))], + }); + }, + async removeReward(rewardName: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "removeReward", args: [rewardName] }); + }, + async approveWithdrawal() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "approveWithdrawal", args: [] }); + }, + async setPaymentGatewayFee(pledgeId: Hex, fee: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setPaymentGatewayFee", args: [pledgeId, fee] }); + }, + async setFeeAndPledge(pledgeId: Hex, backer: Address, pledgeToken: Address, pledgeAmount: bigint, tip: bigint, fee: bigint, reward: readonly Hex[], isPledgeForAReward: boolean) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setFeeAndPledge", args: [pledgeId, backer, pledgeToken, pledgeAmount, tip, fee, [...reward], isPledgeForAReward] }); + }, + async pledgeForAReward(pledgeId: Hex, backer: Address, pledgeToken: Address, tip: bigint, rewardNames: readonly Hex[]) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pledgeForAReward", args: [pledgeId, backer, pledgeToken, tip, [...rewardNames]] }); + }, + async pledgeWithoutAReward(pledgeId: Hex, backer: Address, pledgeToken: Address, pledgeAmount: bigint, tip: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pledgeWithoutAReward", args: [pledgeId, backer, pledgeToken, pledgeAmount, tip] }); + }, + async claimRefund(tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimRefund", args: [tokenId] }); + }, + async claimTip() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimTip", args: [] }); + }, + async claimFund() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimFund", args: [] }); + }, + async disburseFees() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "disburseFees", args: [] }); + }, + async withdraw(token: Address, amount: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "withdraw", args: [token, amount] }); + }, + async updateDeadline(deadline: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateDeadline", args: [deadline] }); + }, + async updateGoalAmount(goalAmount: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "updateGoalAmount", args: [goalAmount] }); + }, + async approve(to: Address, tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "approve", args: [to, tokenId] }); + }, + async setApprovalForAll(operator: Address, approved: boolean) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "setApprovalForAll", args: [operator, approved] }); + }, + async safeTransferFrom(from: Address, to: Address, tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "safeTransferFrom", args: [from, to, tokenId] }); + }, + async transferFrom(from: Address, to: Address, tokenId: bigint) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "transferFrom", args: [from, to, tokenId] }); + }, + }; +} diff --git a/packages/contracts/src/contracts/payment-treasury.ts b/packages/contracts/src/contracts/payment-treasury.ts new file mode 100644 index 0000000..ea51de5 --- /dev/null +++ b/packages/contracts/src/contracts/payment-treasury.ts @@ -0,0 +1,140 @@ +import type { Address, Hex, PublicClient, WalletClient, Chain } from "viem"; +import { PAYMENT_TREASURY_ABI } from "../abis/payment-treasury"; +import type { PaymentTreasuryEntity, PaymentData, LineItem, ExternalFees } from "../types"; + +/** + * Creates a PaymentTreasury entity with full read/write access. + * + * @param address - Deployed PaymentTreasury (or TimeConstrainedPaymentTreasury) contract address + * @param publicClient - Viem PublicClient for on-chain reads + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns PaymentTreasuryEntity + * + * @example + * ```typescript + * const pt = createPaymentTreasuryEntity(PT_ADDRESS, publicClient, walletClient, chain); + * const data = await pt.getPaymentData(paymentId); + * await pt.confirmPayment(paymentId, buyerAddress); + * ``` + */ +export function createPaymentTreasuryEntity( + address: Address, + publicClient: PublicClient, + walletClient: WalletClient, + chain: Chain, +): PaymentTreasuryEntity { + const contract = { address, abi: PAYMENT_TREASURY_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + // ── Reads ──────────────────────────────────────────────────────────────── + + async getPlatformHash() { + return publicClient.readContract({ ...contract, functionName: "getplatformHash" }); + }, + async getPlatformFeePercent() { + return publicClient.readContract({ ...contract, functionName: "getplatformFeePercent" }); + }, + async getRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getRaisedAmount" }); + }, + async getAvailableRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getAvailableRaisedAmount" }); + }, + async getLifetimeRaisedAmount() { + return publicClient.readContract({ ...contract, functionName: "getLifetimeRaisedAmount" }); + }, + async getRefundedAmount() { + return publicClient.readContract({ ...contract, functionName: "getRefundedAmount" }); + }, + async getExpectedAmount() { + return publicClient.readContract({ ...contract, functionName: "getExpectedAmount" }); + }, + async getPaymentData(paymentId: Hex): Promise { + const result = await publicClient.readContract({ ...contract, functionName: "getPaymentData", args: [paymentId] }); + return result as unknown as PaymentData; + }, + async cancelled() { + return publicClient.readContract({ ...contract, functionName: "cancelled" }); + }, + + // ── Writes ─────────────────────────────────────────────────────────────── + + async createPayment(paymentId: Hex, buyerId: Hex, itemId: Hex, paymentToken: Address, amount: bigint, expiration: bigint, lineItems: readonly LineItem[], externalFees: readonly ExternalFees[]) { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "createPayment", + args: [paymentId, buyerId, itemId, paymentToken, amount, expiration, [...lineItems] as { typeId: Hex; amount: bigint }[], [...externalFees] as { feeType: Hex; feeAmount: bigint }[]], + }); + }, + async createPaymentBatch(paymentIds: readonly Hex[], buyerIds: readonly Hex[], itemIds: readonly Hex[], paymentTokens: readonly Address[], amounts: readonly bigint[], expirations: readonly bigint[], lineItemsArray: readonly (readonly LineItem[])[], externalFeesArray: readonly (readonly ExternalFees[])[]) { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "createPaymentBatch", + args: [[...paymentIds], [...buyerIds], [...itemIds], [...paymentTokens], [...amounts], [...expirations], lineItemsArray.map((li) => [...li]) as { typeId: Hex; amount: bigint }[][], externalFeesArray.map((ef) => [...ef]) as { feeType: Hex; feeAmount: bigint }[][]], + }); + }, + async processCryptoPayment(paymentId: Hex, itemId: Hex, buyerAddress: Address, paymentToken: Address, amount: bigint, lineItems: readonly LineItem[], externalFees: readonly ExternalFees[]) { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, chain, account, functionName: "processCryptoPayment", + args: [paymentId, itemId, buyerAddress, paymentToken, amount, [...lineItems] as { typeId: Hex; amount: bigint }[], [...externalFees] as { feeType: Hex; feeAmount: bigint }[]], + }); + }, + async cancelPayment(paymentId: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "cancelPayment", args: [paymentId] }); + }, + async confirmPayment(paymentId: Hex, buyerAddress: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "confirmPayment", args: [paymentId, buyerAddress] }); + }, + async confirmPaymentBatch(paymentIds: readonly Hex[], buyerAddresses: readonly Address[]) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "confirmPaymentBatch", args: [[...paymentIds], [...buyerAddresses]] }); + }, + async disburseFees() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "disburseFees", args: [] }); + }, + async withdraw() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "withdraw", args: [] }); + }, + async claimRefund(paymentId: Hex, refundAddress: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimRefund", args: [paymentId, refundAddress] }); + }, + async claimRefundSelf(paymentId: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimRefund", args: [paymentId] }); + }, + async claimExpiredFunds() { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimExpiredFunds", args: [] }); + }, + async claimNonGoalLineItems(token: Address) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "claimNonGoalLineItems", args: [token] }); + }, + async pauseTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "pauseTreasury", args: [message] }); + }, + async unpauseTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "unpauseTreasury", args: [message] }); + }, + async cancelTreasury(message: Hex) { + const account = requireAccount(); + return walletClient.writeContract({ ...contract, chain, account, functionName: "cancelTreasury", args: [message] }); + }, + }; +} diff --git a/packages/contracts/src/contracts/treasury-factory.ts b/packages/contracts/src/contracts/treasury-factory.ts new file mode 100644 index 0000000..93e2c7f --- /dev/null +++ b/packages/contracts/src/contracts/treasury-factory.ts @@ -0,0 +1,89 @@ +import type { Address, Hex, WalletClient, Chain } from "viem"; +import { TREASURY_FACTORY_ABI } from "../abis/treasury-factory"; +import type { TreasuryFactoryEntity } from "../types"; + +/** + * Creates a TreasuryFactory entity with full implementation management and deploy. + * + * @param address - Deployed TreasuryFactory contract address + * @param walletClient - Viem WalletClient for sending transactions + * @param chain - Chain object (required for writeContract) + * @returns TreasuryFactoryEntity + * + * @example + * ```typescript + * const tf = createTreasuryFactoryEntity(TF_ADDRESS, walletClient, chain); + * const txHash = await tf.deploy(platformHash, infoAddress, implementationId); + * ``` + */ +export function createTreasuryFactoryEntity( + address: Address, + walletClient: WalletClient, + chain: Chain, +): TreasuryFactoryEntity { + const contract = { address, abi: TREASURY_FACTORY_ABI } as const; + + function requireAccount() { + if (!walletClient.account) { + throw new Error("Wallet client has no account; cannot send transaction."); + } + return walletClient.account; + } + + return { + async deploy(platformHash: Hex, infoAddress: Address, implementationId: bigint): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "deploy", + args: [platformHash, infoAddress, implementationId], + }); + }, + + async registerTreasuryImplementation(platformHash: Hex, implementationId: bigint, implementation: Address): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "registerTreasuryImplementation", + args: [platformHash, implementationId, implementation], + }); + }, + + async approveTreasuryImplementation(platformHash: Hex, implementationId: bigint): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "approveTreasuryImplementation", + args: [platformHash, implementationId], + }); + }, + + async disapproveTreasuryImplementation(implementation: Address): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "disapproveTreasuryImplementation", + args: [implementation], + }); + }, + + async removeTreasuryImplementation(platformHash: Hex, implementationId: bigint): Promise { + const account = requireAccount(); + return walletClient.writeContract({ + ...contract, + chain, + account, + functionName: "removeTreasuryImplementation", + args: [platformHash, implementationId], + }); + }, + }; +} diff --git a/packages/contracts/src/errors/all-or-nothing.ts b/packages/contracts/src/errors/all-or-nothing.ts new file mode 100644 index 0000000..307ff50 --- /dev/null +++ b/packages/contracts/src/errors/all-or-nothing.ts @@ -0,0 +1,127 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class AllOrNothingFeeNotDisbursedError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingFeeNotDisbursed"; + readonly args: Record = {}; + readonly recoveryHint = "Fees have not been disbursed yet. Call disburseFees() before withdrawing."; + + constructor() { + super("AllOrNothingFeeNotDisbursed()"); + Object.setPrototypeOf(this, AllOrNothingFeeNotDisbursedError.prototype); + } +} + +export class AllOrNothingFeeAlreadyDisbursedError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingFeeAlreadyDisbursed"; + readonly args: Record = {}; + readonly recoveryHint = "Fees have already been disbursed for this campaign."; + + constructor() { + super("AllOrNothingFeeAlreadyDisbursed()"); + Object.setPrototypeOf(this, AllOrNothingFeeAlreadyDisbursedError.prototype); + } +} + +export class AllOrNothingInvalidInputError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingInvalidInput"; + readonly args: Record = {}; + readonly recoveryHint = "One or more inputs are invalid. Check all provided parameters."; + + constructor() { + super("AllOrNothingInvalidInput()"); + Object.setPrototypeOf(this, AllOrNothingInvalidInputError.prototype); + } +} + +export class AllOrNothingNotClaimableError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingNotClaimable"; + readonly args: { tokenId: string }; + readonly recoveryHint = + "This pledge NFT is not claimable as a refund. The campaign may have succeeded or the refund window has not opened."; + + constructor(args: { tokenId: string }) { + super(`AllOrNothingNotClaimable(tokenId: ${args.tokenId})`); + this.args = args; + Object.setPrototypeOf(this, AllOrNothingNotClaimableError.prototype); + } +} + +export class AllOrNothingNotSuccessfulError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingNotSuccessful"; + readonly args: Record = {}; + readonly recoveryHint = "The campaign has not reached its goal. This operation requires a successful campaign."; + + constructor() { + super("AllOrNothingNotSuccessful()"); + Object.setPrototypeOf(this, AllOrNothingNotSuccessfulError.prototype); + } +} + +export class AllOrNothingRewardExistsError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingRewardExists"; + readonly args: Record = {}; + readonly recoveryHint = "A reward with this name already exists. Use a different reward name or remove the existing one first."; + + constructor() { + super("AllOrNothingRewardExists()"); + Object.setPrototypeOf(this, AllOrNothingRewardExistsError.prototype); + } +} + +export class AllOrNothingTransferFailedError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingTransferFailed"; + readonly args: Record = {}; + readonly recoveryHint = "Token transfer failed. Check token balances and allowances."; + + constructor() { + super("AllOrNothingTransferFailed()"); + Object.setPrototypeOf(this, AllOrNothingTransferFailedError.prototype); + } +} + +export class AllOrNothingUnAuthorizedError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingUnAuthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized for this operation on the AllOrNothing treasury."; + + constructor() { + super("AllOrNothingUnAuthorized()"); + Object.setPrototypeOf(this, AllOrNothingUnAuthorizedError.prototype); + } +} + +export class AllOrNothingTokenNotAcceptedError extends Error implements ContractErrorBase { + readonly name = "AllOrNothingTokenNotAccepted"; + readonly args: { token: string }; + readonly recoveryHint = "This token is not accepted for pledging. Use an accepted token for this campaign."; + + constructor(args: { token: string }) { + super(`AllOrNothingTokenNotAccepted(token: ${args.token})`); + this.args = args; + Object.setPrototypeOf(this, AllOrNothingTokenNotAcceptedError.prototype); + } +} + +export class TreasurySuccessConditionNotFulfilledError extends Error implements ContractErrorBase { + readonly name = "TreasurySuccessConditionNotFulfilled"; + readonly args: Record = {}; + readonly recoveryHint = + "The campaign success condition has not been fulfilled. The goal amount must be reached before withdrawing."; + + constructor() { + super("TreasurySuccessConditionNotFulfilled()"); + Object.setPrototypeOf(this, TreasurySuccessConditionNotFulfilledError.prototype); + } +} + +export type AllOrNothingError = + | AllOrNothingFeeNotDisbursedError + | AllOrNothingFeeAlreadyDisbursedError + | AllOrNothingInvalidInputError + | AllOrNothingNotClaimableError + | AllOrNothingNotSuccessfulError + | AllOrNothingRewardExistsError + | AllOrNothingTransferFailedError + | AllOrNothingUnAuthorizedError + | AllOrNothingTokenNotAcceptedError + | TreasurySuccessConditionNotFulfilledError; diff --git a/packages/contracts/src/errors/campaign-info-factory.ts b/packages/contracts/src/errors/campaign-info-factory.ts new file mode 100644 index 0000000..c039237 --- /dev/null +++ b/packages/contracts/src/errors/campaign-info-factory.ts @@ -0,0 +1,77 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class CampaignInfoFactoryCampaignInitializationFailedError + extends Error + implements ContractErrorBase +{ + readonly name = "CampaignInfoFactoryCampaignInitializationFailed"; + readonly args: Record = {}; + readonly recoveryHint = + "Campaign initialization failed. Check campaign data, platform listing, and implementation."; + + constructor() { + super("CampaignInfoFactoryCampaignInitializationFailed()"); + Object.setPrototypeOf(this, CampaignInfoFactoryCampaignInitializationFailedError.prototype); + } +} + +export class CampaignInfoFactoryInvalidInputError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoFactoryInvalidInput"; + readonly args: Record = {}; + readonly recoveryHint = + "Invalid input for campaign creation. Check creator, platforms, and campaign data."; + + constructor() { + super("CampaignInfoFactoryInvalidInput()"); + Object.setPrototypeOf(this, CampaignInfoFactoryInvalidInputError.prototype); + } +} + +export class CampaignInfoFactoryPlatformNotListedError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoFactoryPlatformNotListed"; + readonly args: { platformHash: string }; + readonly recoveryHint = "The given platform is not listed in GlobalParams. Enlist the platform first."; + + constructor(args: { platformHash: string }) { + super(`CampaignInfoFactoryPlatformNotListed(platformHash: ${args.platformHash})`); + this.args = args; + Object.setPrototypeOf(this, CampaignInfoFactoryPlatformNotListedError.prototype); + } +} + +export class CampaignInfoFactoryCampaignWithSameIdentifierExistsError + extends Error + implements ContractErrorBase +{ + readonly name = "CampaignInfoFactoryCampaignWithSameIdentifierExists"; + readonly args: { identifierHash: string; cloneExists: string }; + readonly recoveryHint = + "A campaign with this identifier already exists. Use a different identifier or the existing campaign."; + + constructor(args: { identifierHash: string; cloneExists: string }) { + super( + `CampaignInfoFactoryCampaignWithSameIdentifierExists(identifierHash: ${args.identifierHash}, cloneExists: ${args.cloneExists})`, + ); + this.args = args; + Object.setPrototypeOf(this, CampaignInfoFactoryCampaignWithSameIdentifierExistsError.prototype); + } +} + +export class CampaignInfoInvalidTokenListError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoInvalidTokenList"; + readonly args: Record = {}; + readonly recoveryHint = + "Campaign currency tokens do not match GlobalParams for the campaign currency. Fix token list."; + + constructor() { + super("CampaignInfoInvalidTokenList()"); + Object.setPrototypeOf(this, CampaignInfoInvalidTokenListError.prototype); + } +} + +export type CampaignInfoFactoryError = + | CampaignInfoFactoryCampaignInitializationFailedError + | CampaignInfoFactoryInvalidInputError + | CampaignInfoFactoryPlatformNotListedError + | CampaignInfoFactoryCampaignWithSameIdentifierExistsError + | CampaignInfoInvalidTokenListError; diff --git a/packages/contracts/src/errors/campaign-info.ts b/packages/contracts/src/errors/campaign-info.ts new file mode 100644 index 0000000..38632b1 --- /dev/null +++ b/packages/contracts/src/errors/campaign-info.ts @@ -0,0 +1,81 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class CampaignInfoInvalidInputError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoInvalidInput"; + readonly args: Record = {}; + readonly recoveryHint = "One or more campaign info inputs are invalid. Check all provided parameters."; + + constructor() { + super("CampaignInfoInvalidInput()"); + Object.setPrototypeOf(this, CampaignInfoInvalidInputError.prototype); + } +} + +export class CampaignInfoInvalidPlatformUpdateError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoInvalidPlatformUpdate"; + readonly args: { platformBytes: string; selection: boolean }; + readonly recoveryHint = + "Invalid platform selection update. The platform may already be in the requested state."; + + constructor(args: { platformBytes: string; selection: boolean }) { + super( + `CampaignInfoInvalidPlatformUpdate(platformBytes: ${args.platformBytes}, selection: ${args.selection})`, + ); + this.args = args; + Object.setPrototypeOf(this, CampaignInfoInvalidPlatformUpdateError.prototype); + } +} + +export class CampaignInfoPlatformNotSelectedError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoPlatformNotSelected"; + readonly args: { platformBytes: string }; + readonly recoveryHint = "The platform is not selected for this campaign. Select the platform first."; + + constructor(args: { platformBytes: string }) { + super(`CampaignInfoPlatformNotSelected(platformBytes: ${args.platformBytes})`); + this.args = args; + Object.setPrototypeOf(this, CampaignInfoPlatformNotSelectedError.prototype); + } +} + +export class CampaignInfoPlatformAlreadyApprovedError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoPlatformAlreadyApproved"; + readonly args: { platformHash: string }; + readonly recoveryHint = "The platform is already approved for this campaign. No action required."; + + constructor(args: { platformHash: string }) { + super(`CampaignInfoPlatformAlreadyApproved(platformHash: ${args.platformHash})`); + this.args = args; + Object.setPrototypeOf(this, CampaignInfoPlatformAlreadyApprovedError.prototype); + } +} + +export class CampaignInfoUnauthorizedError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoUnauthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized for this campaign operation."; + + constructor() { + super("CampaignInfoUnauthorized()"); + Object.setPrototypeOf(this, CampaignInfoUnauthorizedError.prototype); + } +} + +export class CampaignInfoIsLockedError extends Error implements ContractErrorBase { + readonly name = "CampaignInfoIsLocked"; + readonly args: Record = {}; + readonly recoveryHint = "The campaign info is locked and cannot be modified."; + + constructor() { + super("CampaignInfoIsLocked()"); + Object.setPrototypeOf(this, CampaignInfoIsLockedError.prototype); + } +} + +export type CampaignInfoError = + | CampaignInfoInvalidInputError + | CampaignInfoInvalidPlatformUpdateError + | CampaignInfoPlatformNotSelectedError + | CampaignInfoPlatformAlreadyApprovedError + | CampaignInfoUnauthorizedError + | CampaignInfoIsLockedError; diff --git a/packages/contracts/src/errors/contract-error.ts b/packages/contracts/src/errors/contract-error.ts new file mode 100644 index 0000000..2bbc088 --- /dev/null +++ b/packages/contracts/src/errors/contract-error.ts @@ -0,0 +1,10 @@ +/** + * Base type for contract revert errors. All typed SDK errors extend this. + * Preserves decoded parameters from the chain for logging and retries. + */ +export interface ContractErrorBase { + readonly name: string; + readonly args: Record; + /** Optional human-readable recovery suggestion for developers. */ + readonly recoveryHint?: string; +} diff --git a/packages/contracts/src/errors/global-params.ts b/packages/contracts/src/errors/global-params.ts new file mode 100644 index 0000000..f3d6659 --- /dev/null +++ b/packages/contracts/src/errors/global-params.ts @@ -0,0 +1,174 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class GlobalParamsInvalidInputError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsInvalidInput"; + readonly args: Record = {}; + readonly recoveryHint = + "One or more inputs are invalid. Check addresses, fee percent, and platform bytes."; + + constructor() { + super("GlobalParamsInvalidInput()"); + Object.setPrototypeOf(this, GlobalParamsInvalidInputError.prototype); + } +} + +export class GlobalParamsPlatformAdminNotSetError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformAdminNotSet"; + readonly args: { platformBytes: string }; + readonly recoveryHint = "Set the platform admin address before performing this operation."; + + constructor(args: { platformBytes: string }) { + super(`GlobalParamsPlatformAdminNotSet(platformBytes: ${args.platformBytes})`); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsPlatformAdminNotSetError.prototype); + } +} + +export class GlobalParamsPlatformAlreadyListedError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformAlreadyListed"; + readonly args: { platformBytes: string }; + readonly recoveryHint = + "Platform is already listed. Use a different platform hash or update the existing platform."; + + constructor(args: { platformBytes: string }) { + super(`GlobalParamsPlatformAlreadyListed(platformBytes: ${args.platformBytes})`); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsPlatformAlreadyListedError.prototype); + } +} + +export class GlobalParamsPlatformDataAlreadySetError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformDataAlreadySet"; + readonly args: Record = {}; + readonly recoveryHint = "Platform data for this key is already set. Use a different key or update."; + + constructor() { + super("GlobalParamsPlatformDataAlreadySet()"); + Object.setPrototypeOf(this, GlobalParamsPlatformDataAlreadySetError.prototype); + } +} + +export class GlobalParamsPlatformDataNotSetError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformDataNotSet"; + readonly args: Record = {}; + readonly recoveryHint = "Platform data is not set. Add platform data first."; + + constructor() { + super("GlobalParamsPlatformDataNotSet()"); + Object.setPrototypeOf(this, GlobalParamsPlatformDataNotSetError.prototype); + } +} + +export class GlobalParamsPlatformDataSlotTakenError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformDataSlotTaken"; + readonly args: Record = {}; + readonly recoveryHint = "This platform data slot is already taken. Use a different key."; + + constructor() { + super("GlobalParamsPlatformDataSlotTaken()"); + Object.setPrototypeOf(this, GlobalParamsPlatformDataSlotTakenError.prototype); + } +} + +export class GlobalParamsPlatformFeePercentIsZeroError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformFeePercentIsZero"; + readonly args: { platformBytes: string }; + readonly recoveryHint = "Platform fee percent must be greater than zero."; + + constructor(args: { platformBytes: string }) { + super(`GlobalParamsPlatformFeePercentIsZero(platformBytes: ${args.platformBytes})`); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsPlatformFeePercentIsZeroError.prototype); + } +} + +export class GlobalParamsPlatformNotListedError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformNotListed"; + readonly args: { platformBytes: string }; + readonly recoveryHint = + "Platform is not enlisted in GlobalParams. Enlist the platform first."; + + constructor(args: { platformBytes: string }) { + super(`GlobalParamsPlatformNotListed(platformBytes: ${args.platformBytes})`); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsPlatformNotListedError.prototype); + } +} + +export class GlobalParamsUnauthorizedError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsUnauthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized for this operation."; + + constructor() { + super("GlobalParamsUnauthorized()"); + Object.setPrototypeOf(this, GlobalParamsUnauthorizedError.prototype); + } +} + +export class GlobalParamsCurrencyTokenLengthMismatchError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsCurrencyTokenLengthMismatch"; + readonly args: Record = {}; + readonly recoveryHint = + "Length of currencies array must match length of tokensPerCurrency. Check initialize or currency config."; + + constructor() { + super("GlobalParamsCurrencyTokenLengthMismatch()"); + Object.setPrototypeOf(this, GlobalParamsCurrencyTokenLengthMismatchError.prototype); + } +} + +export class GlobalParamsCurrencyHasNoTokensError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsCurrencyHasNoTokens"; + readonly args: { currency: string }; + readonly recoveryHint = "This currency has no accepted tokens. Add at least one token for the currency."; + + constructor(args: { currency: string }) { + super(`GlobalParamsCurrencyHasNoTokens(currency: ${args.currency})`); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsCurrencyHasNoTokensError.prototype); + } +} + +export class GlobalParamsTokenNotInCurrencyError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsTokenNotInCurrency"; + readonly args: { currency: string; token: string }; + readonly recoveryHint = + "The given token is not in the accepted list for this currency. Use an approved token."; + + constructor(args: { currency: string; token: string }) { + super(`GlobalParamsTokenNotInCurrency(currency: ${args.currency}, token: ${args.token})`); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsTokenNotInCurrencyError.prototype); + } +} + +export class GlobalParamsPlatformLineItemTypeNotFoundError extends Error implements ContractErrorBase { + readonly name = "GlobalParamsPlatformLineItemTypeNotFound"; + readonly args: { platformHash: string; typeId: string }; + readonly recoveryHint = + "Platform line item type not found. Register the line item type for this platform first."; + + constructor(args: { platformHash: string; typeId: string }) { + super( + `GlobalParamsPlatformLineItemTypeNotFound(platformHash: ${args.platformHash}, typeId: ${args.typeId})`, + ); + this.args = args; + Object.setPrototypeOf(this, GlobalParamsPlatformLineItemTypeNotFoundError.prototype); + } +} + +export type GlobalParamsError = + | GlobalParamsInvalidInputError + | GlobalParamsPlatformAdminNotSetError + | GlobalParamsPlatformAlreadyListedError + | GlobalParamsPlatformDataAlreadySetError + | GlobalParamsPlatformDataNotSetError + | GlobalParamsPlatformDataSlotTakenError + | GlobalParamsPlatformFeePercentIsZeroError + | GlobalParamsPlatformNotListedError + | GlobalParamsUnauthorizedError + | GlobalParamsCurrencyTokenLengthMismatchError + | GlobalParamsCurrencyHasNoTokensError + | GlobalParamsTokenNotInCurrencyError + | GlobalParamsPlatformLineItemTypeNotFoundError; diff --git a/packages/contracts/src/errors/index.ts b/packages/contracts/src/errors/index.ts new file mode 100644 index 0000000..1d675c5 --- /dev/null +++ b/packages/contracts/src/errors/index.ts @@ -0,0 +1,130 @@ +export type { ContractErrorBase } from "./contract-error.js"; +export { parseContractError } from "./parse-contract-error.js"; + +export { + GlobalParamsCurrencyHasNoTokensError, + GlobalParamsCurrencyTokenLengthMismatchError, + GlobalParamsInvalidInputError, + GlobalParamsPlatformAdminNotSetError, + GlobalParamsPlatformAlreadyListedError, + GlobalParamsPlatformDataAlreadySetError, + GlobalParamsPlatformDataNotSetError, + GlobalParamsPlatformDataSlotTakenError, + GlobalParamsPlatformFeePercentIsZeroError, + GlobalParamsPlatformLineItemTypeNotFoundError, + GlobalParamsPlatformNotListedError, + GlobalParamsTokenNotInCurrencyError, + GlobalParamsUnauthorizedError, +} from "./global-params.js"; +export type { GlobalParamsError } from "./global-params.js"; + +export { + CampaignInfoFactoryCampaignInitializationFailedError, + CampaignInfoFactoryCampaignWithSameIdentifierExistsError, + CampaignInfoFactoryInvalidInputError, + CampaignInfoFactoryPlatformNotListedError, + CampaignInfoInvalidTokenListError, +} from "./campaign-info-factory.js"; +export type { CampaignInfoFactoryError } from "./campaign-info-factory.js"; + +export { + CampaignInfoInvalidInputError, + CampaignInfoInvalidPlatformUpdateError, + CampaignInfoIsLockedError, + CampaignInfoPlatformAlreadyApprovedError, + CampaignInfoPlatformNotSelectedError, + CampaignInfoUnauthorizedError, +} from "./campaign-info.js"; +export type { CampaignInfoError } from "./campaign-info.js"; + +export { + AllOrNothingFeeAlreadyDisbursedError, + AllOrNothingFeeNotDisbursedError, + AllOrNothingInvalidInputError, + AllOrNothingNotClaimableError, + AllOrNothingNotSuccessfulError, + AllOrNothingRewardExistsError, + AllOrNothingTokenNotAcceptedError, + AllOrNothingTransferFailedError, + AllOrNothingUnAuthorizedError, + TreasurySuccessConditionNotFulfilledError, +} from "./all-or-nothing.js"; +export type { AllOrNothingError } from "./all-or-nothing.js"; + +export { + KeepWhatsRaisedAlreadyClaimedError, + KeepWhatsRaisedAlreadyEnabledError, + KeepWhatsRaisedAlreadyWithdrawnError, + KeepWhatsRaisedConfigLockedError, + KeepWhatsRaisedDisabledError, + KeepWhatsRaisedDisbursementBlockedError, + KeepWhatsRaisedInsufficientFundsForFeeError, + KeepWhatsRaisedInsufficientFundsForWithdrawalAndFeeError, + KeepWhatsRaisedInvalidInputError, + KeepWhatsRaisedNotClaimableAdminError, + KeepWhatsRaisedNotClaimableError, + KeepWhatsRaisedPledgeAlreadyProcessedError, + KeepWhatsRaisedRewardExistsError, + KeepWhatsRaisedTokenNotAcceptedError, + KeepWhatsRaisedUnAuthorizedError, +} from "./keep-whats-raised.js"; +export type { KeepWhatsRaisedError } from "./keep-whats-raised.js"; + +export { ItemRegistryMismatchedArraysLengthError } from "./item-registry.js"; +export type { ItemRegistryError } from "./item-registry.js"; + +export { + PaymentTreasuryAlreadyWithdrawnError, + PaymentTreasuryCampaignInfoIsPausedError, + PaymentTreasuryClaimWindowNotReachedError, + PaymentTreasuryCryptoPaymentError, + PaymentTreasuryExpirationExceedsMaxError, + PaymentTreasuryFeeNotDisbursedError, + PaymentTreasuryInsufficientBalanceError, + PaymentTreasuryInsufficientFundsForFeeError, + PaymentTreasuryInvalidInputError, + PaymentTreasuryNoFundsToClaimError, + PaymentTreasuryPaymentAlreadyConfirmedError, + PaymentTreasuryPaymentAlreadyExpiredError, + PaymentTreasuryPaymentAlreadyExistError, + PaymentTreasuryPaymentNotClaimableError, + PaymentTreasuryPaymentNotConfirmedError, + PaymentTreasuryPaymentNotExistError, + PaymentTreasurySuccessConditionNotFulfilledError, + PaymentTreasuryTokenNotAcceptedError, + PaymentTreasuryUnAuthorizedError, +} from "./payment-treasury.js"; +export type { PaymentTreasuryError } from "./payment-treasury.js"; + +export { + TreasuryFactoryImplementationNotSetError, + TreasuryFactoryImplementationNotSetOrApprovedError, + TreasuryFactoryInvalidAddressError, + TreasuryFactoryInvalidKeyError, + TreasuryFactorySettingPlatformInfoFailedError, + TreasuryFactoryTreasuryCreationFailedError, + TreasuryFactoryTreasuryInitializationFailedError, + TreasuryFactoryUnauthorizedError, +} from "./treasury-factory.js"; +export type { TreasuryFactoryError } from "./treasury-factory.js"; + +export { + AccessCheckerUnauthorizedError, + AdminAccessCheckerUnauthorizedError, + CurrentTimeIsGreaterError, + CurrentTimeIsLessError, + CurrentTimeIsNotWithinRangeError, + TreasuryCampaignInfoIsPausedError, + TreasuryFeeNotDisbursedError, + TreasuryTransferFailedError, +} from "./shared.js"; +export type { SharedError } from "./shared.js"; + +import type { ContractErrorBase } from "./contract-error.js"; + +/** + * Returns a human-readable recovery suggestion for a typed contract error, if available. + */ +export function getRecoveryHint(error: ContractErrorBase): string | undefined { + return error.recoveryHint; +} diff --git a/packages/contracts/src/errors/item-registry.ts b/packages/contracts/src/errors/item-registry.ts new file mode 100644 index 0000000..c0f1d6b --- /dev/null +++ b/packages/contracts/src/errors/item-registry.ts @@ -0,0 +1,15 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class ItemRegistryMismatchedArraysLengthError extends Error implements ContractErrorBase { + readonly name = "ItemRegistryMismatchedArraysLength"; + readonly args: Record = {}; + readonly recoveryHint = + "The itemIds and items arrays must have the same length. Ensure both arrays are equal in size."; + + constructor() { + super("ItemRegistryMismatchedArraysLength()"); + Object.setPrototypeOf(this, ItemRegistryMismatchedArraysLengthError.prototype); + } +} + +export type ItemRegistryError = ItemRegistryMismatchedArraysLengthError; diff --git a/packages/contracts/src/errors/keep-whats-raised.ts b/packages/contracts/src/errors/keep-whats-raised.ts new file mode 100644 index 0000000..e8b3545 --- /dev/null +++ b/packages/contracts/src/errors/keep-whats-raised.ts @@ -0,0 +1,204 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class KeepWhatsRaisedUnAuthorizedError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedUnAuthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized for this operation on the KeepWhatsRaised treasury."; + + constructor() { + super("KeepWhatsRaisedUnAuthorized()"); + Object.setPrototypeOf(this, KeepWhatsRaisedUnAuthorizedError.prototype); + } +} + +export class KeepWhatsRaisedInvalidInputError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedInvalidInput"; + readonly args: Record = {}; + readonly recoveryHint = "One or more inputs are invalid. Check all provided parameters."; + + constructor() { + super("KeepWhatsRaisedInvalidInput()"); + Object.setPrototypeOf(this, KeepWhatsRaisedInvalidInputError.prototype); + } +} + +export class KeepWhatsRaisedTokenNotAcceptedError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedTokenNotAccepted"; + readonly args: { token: string }; + readonly recoveryHint = "This token is not accepted for pledging. Use an accepted token for this campaign."; + + constructor(args: { token: string }) { + super(`KeepWhatsRaisedTokenNotAccepted(token: ${args.token})`); + this.args = args; + Object.setPrototypeOf(this, KeepWhatsRaisedTokenNotAcceptedError.prototype); + } +} + +export class KeepWhatsRaisedRewardExistsError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedRewardExists"; + readonly args: Record = {}; + readonly recoveryHint = "A reward with this name already exists. Use a different reward name or remove the existing one first."; + + constructor() { + super("KeepWhatsRaisedRewardExists()"); + Object.setPrototypeOf(this, KeepWhatsRaisedRewardExistsError.prototype); + } +} + +export class KeepWhatsRaisedDisabledError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedDisabled"; + readonly args: Record = {}; + readonly recoveryHint = "The KeepWhatsRaised treasury is disabled. Enable it before performing this operation."; + + constructor() { + super("KeepWhatsRaisedDisabled()"); + Object.setPrototypeOf(this, KeepWhatsRaisedDisabledError.prototype); + } +} + +export class KeepWhatsRaisedAlreadyEnabledError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedAlreadyEnabled"; + readonly args: Record = {}; + readonly recoveryHint = "The KeepWhatsRaised treasury is already enabled."; + + constructor() { + super("KeepWhatsRaisedAlreadyEnabled()"); + Object.setPrototypeOf(this, KeepWhatsRaisedAlreadyEnabledError.prototype); + } +} + +export class KeepWhatsRaisedInsufficientFundsForWithdrawalAndFeeError + extends Error + implements ContractErrorBase +{ + readonly name = "KeepWhatsRaisedInsufficientFundsForWithdrawalAndFee"; + readonly args: { availableAmount: string; withdrawalAmount: string; fee: string }; + readonly recoveryHint = + "Insufficient funds to cover both the withdrawal amount and fee. Reduce the withdrawal amount or wait for more pledges."; + + constructor(args: { availableAmount: string; withdrawalAmount: string; fee: string }) { + super( + `KeepWhatsRaisedInsufficientFundsForWithdrawalAndFee(availableAmount: ${args.availableAmount}, withdrawalAmount: ${args.withdrawalAmount}, fee: ${args.fee})`, + ); + this.args = args; + Object.setPrototypeOf( + this, + KeepWhatsRaisedInsufficientFundsForWithdrawalAndFeeError.prototype, + ); + } +} + +export class KeepWhatsRaisedInsufficientFundsForFeeError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedInsufficientFundsForFee"; + readonly args: { withdrawalAmount: string; fee: string }; + readonly recoveryHint = + "Insufficient funds to cover the withdrawal fee. Ensure the treasury has enough balance to pay the fee."; + + constructor(args: { withdrawalAmount: string; fee: string }) { + super( + `KeepWhatsRaisedInsufficientFundsForFee(withdrawalAmount: ${args.withdrawalAmount}, fee: ${args.fee})`, + ); + this.args = args; + Object.setPrototypeOf(this, KeepWhatsRaisedInsufficientFundsForFeeError.prototype); + } +} + +export class KeepWhatsRaisedAlreadyWithdrawnError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedAlreadyWithdrawn"; + readonly args: Record = {}; + readonly recoveryHint = "Funds have already been withdrawn from this treasury."; + + constructor() { + super("KeepWhatsRaisedAlreadyWithdrawn()"); + Object.setPrototypeOf(this, KeepWhatsRaisedAlreadyWithdrawnError.prototype); + } +} + +export class KeepWhatsRaisedAlreadyClaimedError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedAlreadyClaimed"; + readonly args: Record = {}; + readonly recoveryHint = "This pledge has already been claimed or refunded."; + + constructor() { + super("KeepWhatsRaisedAlreadyClaimed()"); + Object.setPrototypeOf(this, KeepWhatsRaisedAlreadyClaimedError.prototype); + } +} + +export class KeepWhatsRaisedNotClaimableError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedNotClaimable"; + readonly args: { tokenId: string }; + readonly recoveryHint = + "This pledge NFT is not claimable for a refund. The campaign may still be active or refund conditions are not met."; + + constructor(args: { tokenId: string }) { + super(`KeepWhatsRaisedNotClaimable(tokenId: ${args.tokenId})`); + this.args = args; + Object.setPrototypeOf(this, KeepWhatsRaisedNotClaimableError.prototype); + } +} + +export class KeepWhatsRaisedNotClaimableAdminError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedNotClaimableAdmin"; + readonly args: Record = {}; + readonly recoveryHint = + "The admin claim conditions are not met. Ensure the campaign is in the correct state before claiming."; + + constructor() { + super("KeepWhatsRaisedNotClaimableAdmin()"); + Object.setPrototypeOf(this, KeepWhatsRaisedNotClaimableAdminError.prototype); + } +} + +export class KeepWhatsRaisedConfigLockedError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedConfigLocked"; + readonly args: Record = {}; + readonly recoveryHint = + "The treasury configuration is locked and cannot be modified. Wait for the lock period to expire."; + + constructor() { + super("KeepWhatsRaisedConfigLocked()"); + Object.setPrototypeOf(this, KeepWhatsRaisedConfigLockedError.prototype); + } +} + +export class KeepWhatsRaisedDisbursementBlockedError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedDisbursementBlocked"; + readonly args: Record = {}; + readonly recoveryHint = + "Fee disbursement is blocked. Ensure all required conditions are met before disbursing fees."; + + constructor() { + super("KeepWhatsRaisedDisbursementBlocked()"); + Object.setPrototypeOf(this, KeepWhatsRaisedDisbursementBlockedError.prototype); + } +} + +export class KeepWhatsRaisedPledgeAlreadyProcessedError extends Error implements ContractErrorBase { + readonly name = "KeepWhatsRaisedPledgeAlreadyProcessed"; + readonly args: { pledgeId: string }; + readonly recoveryHint = "This pledge ID has already been processed. Each pledge ID can only be used once."; + + constructor(args: { pledgeId: string }) { + super(`KeepWhatsRaisedPledgeAlreadyProcessed(pledgeId: ${args.pledgeId})`); + this.args = args; + Object.setPrototypeOf(this, KeepWhatsRaisedPledgeAlreadyProcessedError.prototype); + } +} + +export type KeepWhatsRaisedError = + | KeepWhatsRaisedUnAuthorizedError + | KeepWhatsRaisedInvalidInputError + | KeepWhatsRaisedTokenNotAcceptedError + | KeepWhatsRaisedRewardExistsError + | KeepWhatsRaisedDisabledError + | KeepWhatsRaisedAlreadyEnabledError + | KeepWhatsRaisedInsufficientFundsForWithdrawalAndFeeError + | KeepWhatsRaisedInsufficientFundsForFeeError + | KeepWhatsRaisedAlreadyWithdrawnError + | KeepWhatsRaisedAlreadyClaimedError + | KeepWhatsRaisedNotClaimableError + | KeepWhatsRaisedNotClaimableAdminError + | KeepWhatsRaisedConfigLockedError + | KeepWhatsRaisedDisbursementBlockedError + | KeepWhatsRaisedPledgeAlreadyProcessedError; diff --git a/packages/contracts/src/errors/parse-contract-error.ts b/packages/contracts/src/errors/parse-contract-error.ts new file mode 100644 index 0000000..e92952d --- /dev/null +++ b/packages/contracts/src/errors/parse-contract-error.ts @@ -0,0 +1,527 @@ +import { decodeErrorResult, type Hex } from "viem"; +import { GLOBAL_PARAMS_ABI } from "../abis/global-params.js"; +import { CAMPAIGN_INFO_FACTORY_ABI } from "../abis/campaign-info-factory.js"; +import { CAMPAIGN_INFO_ABI } from "../abis/campaign-info.js"; +import { ALL_OR_NOTHING_ABI } from "../abis/all-or-nothing.js"; +import { KEEP_WHATS_RAISED_ABI } from "../abis/keep-whats-raised.js"; +import { ITEM_REGISTRY_ABI } from "../abis/item-registry.js"; +import { PAYMENT_TREASURY_ABI } from "../abis/payment-treasury.js"; +import { TREASURY_FACTORY_ABI } from "../abis/treasury-factory.js"; +import type { ContractErrorBase } from "./contract-error.js"; +import { + GlobalParamsCurrencyHasNoTokensError, + GlobalParamsCurrencyTokenLengthMismatchError, + GlobalParamsInvalidInputError, + GlobalParamsPlatformAdminNotSetError, + GlobalParamsPlatformAlreadyListedError, + GlobalParamsPlatformDataAlreadySetError, + GlobalParamsPlatformDataNotSetError, + GlobalParamsPlatformDataSlotTakenError, + GlobalParamsPlatformFeePercentIsZeroError, + GlobalParamsPlatformLineItemTypeNotFoundError, + GlobalParamsPlatformNotListedError, + GlobalParamsTokenNotInCurrencyError, + GlobalParamsUnauthorizedError, +} from "./global-params.js"; +import { + CampaignInfoFactoryCampaignInitializationFailedError, + CampaignInfoFactoryCampaignWithSameIdentifierExistsError, + CampaignInfoFactoryInvalidInputError, + CampaignInfoFactoryPlatformNotListedError, + CampaignInfoInvalidTokenListError, +} from "./campaign-info-factory.js"; +import { + CampaignInfoInvalidInputError, + CampaignInfoInvalidPlatformUpdateError, + CampaignInfoIsLockedError, + CampaignInfoPlatformAlreadyApprovedError, + CampaignInfoPlatformNotSelectedError, + CampaignInfoUnauthorizedError, +} from "./campaign-info.js"; +import { + AllOrNothingFeeAlreadyDisbursedError, + AllOrNothingFeeNotDisbursedError, + AllOrNothingInvalidInputError, + AllOrNothingNotClaimableError, + AllOrNothingNotSuccessfulError, + AllOrNothingRewardExistsError, + AllOrNothingTokenNotAcceptedError, + AllOrNothingTransferFailedError, + AllOrNothingUnAuthorizedError, + TreasurySuccessConditionNotFulfilledError, +} from "./all-or-nothing.js"; +import { + KeepWhatsRaisedAlreadyClaimedError, + KeepWhatsRaisedAlreadyEnabledError, + KeepWhatsRaisedAlreadyWithdrawnError, + KeepWhatsRaisedConfigLockedError, + KeepWhatsRaisedDisabledError, + KeepWhatsRaisedDisbursementBlockedError, + KeepWhatsRaisedInsufficientFundsForFeeError, + KeepWhatsRaisedInsufficientFundsForWithdrawalAndFeeError, + KeepWhatsRaisedInvalidInputError, + KeepWhatsRaisedNotClaimableAdminError, + KeepWhatsRaisedNotClaimableError, + KeepWhatsRaisedPledgeAlreadyProcessedError, + KeepWhatsRaisedRewardExistsError, + KeepWhatsRaisedTokenNotAcceptedError, + KeepWhatsRaisedUnAuthorizedError, +} from "./keep-whats-raised.js"; +import { ItemRegistryMismatchedArraysLengthError } from "./item-registry.js"; +import { + PaymentTreasuryAlreadyWithdrawnError, + PaymentTreasuryCampaignInfoIsPausedError, + PaymentTreasuryClaimWindowNotReachedError, + PaymentTreasuryCryptoPaymentError, + PaymentTreasuryExpirationExceedsMaxError, + PaymentTreasuryFeeNotDisbursedError, + PaymentTreasuryInsufficientBalanceError, + PaymentTreasuryInsufficientFundsForFeeError, + PaymentTreasuryInvalidInputError, + PaymentTreasuryNoFundsToClaimError, + PaymentTreasuryPaymentAlreadyConfirmedError, + PaymentTreasuryPaymentAlreadyExpiredError, + PaymentTreasuryPaymentAlreadyExistError, + PaymentTreasuryPaymentNotClaimableError, + PaymentTreasuryPaymentNotConfirmedError, + PaymentTreasuryPaymentNotExistError, + PaymentTreasurySuccessConditionNotFulfilledError, + PaymentTreasuryTokenNotAcceptedError, + PaymentTreasuryUnAuthorizedError, +} from "./payment-treasury.js"; +import { + TreasuryFactoryImplementationNotSetError, + TreasuryFactoryImplementationNotSetOrApprovedError, + TreasuryFactoryInvalidAddressError, + TreasuryFactoryInvalidKeyError, + TreasuryFactorySettingPlatformInfoFailedError, + TreasuryFactoryTreasuryCreationFailedError, + TreasuryFactoryTreasuryInitializationFailedError, + TreasuryFactoryUnauthorizedError, +} from "./treasury-factory.js"; +import { + AccessCheckerUnauthorizedError, + AdminAccessCheckerUnauthorizedError, + CurrentTimeIsGreaterError, + CurrentTimeIsLessError, + CurrentTimeIsNotWithinRangeError, + TreasuryCampaignInfoIsPausedError, + TreasuryFeeNotDisbursedError, + TreasuryTransferFailedError, +} from "./shared.js"; + +function isHex(data: string): data is Hex { + return typeof data === "string" && data.startsWith("0x") && /^0x[0-9a-fA-F]*$/.test(data); +} + +function decodeArgs( + abi: readonly { type: string; name?: string; inputs?: readonly { name: string }[] }[], + errorName: string, + decodedArgs: readonly unknown[], +): Record { + const args: Record = {}; + const errorAbi = abi.find((item) => item.type === "error" && item.name === errorName); + if (errorAbi && "inputs" in errorAbi && errorAbi.inputs) { + errorAbi.inputs.forEach((input, i) => { + if (input.name && decodedArgs[i] !== undefined) { + args[input.name] = decodedArgs[i]; + } + }); + } + return args; +} + +function toSharedError(name: string, args: Record): ContractErrorBase | null { + switch (name) { + case "AccessCheckerUnauthorized": + return new AccessCheckerUnauthorizedError(); + case "AdminAccessCheckerUnauthorized": + return new AdminAccessCheckerUnauthorizedError(); + case "CurrentTimeIsGreater": + return new CurrentTimeIsGreaterError({ + inputTime: args["inputTime"] as string, + currentTime: args["currentTime"] as string, + }); + case "CurrentTimeIsLess": + return new CurrentTimeIsLessError({ + inputTime: args["inputTime"] as string, + currentTime: args["currentTime"] as string, + }); + case "CurrentTimeIsNotWithinRange": + return new CurrentTimeIsNotWithinRangeError({ + initialTime: args["initialTime"] as string, + finalTime: args["finalTime"] as string, + }); + case "TreasuryCampaignInfoIsPaused": + return new TreasuryCampaignInfoIsPausedError(); + case "TreasuryFeeNotDisbursed": + return new TreasuryFeeNotDisbursedError(); + case "TreasuryTransferFailed": + return new TreasuryTransferFailedError(); + default: + return null; + } +} + +function toGlobalParamsError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "GlobalParamsInvalidInput": + return new GlobalParamsInvalidInputError(); + case "GlobalParamsPlatformAdminNotSet": + return new GlobalParamsPlatformAdminNotSetError({ + platformBytes: args["platformBytes"] as string, + }); + case "GlobalParamsPlatformAlreadyListed": + return new GlobalParamsPlatformAlreadyListedError({ + platformBytes: args["platformBytes"] as string, + }); + case "GlobalParamsPlatformDataAlreadySet": + return new GlobalParamsPlatformDataAlreadySetError(); + case "GlobalParamsPlatformDataNotSet": + return new GlobalParamsPlatformDataNotSetError(); + case "GlobalParamsPlatformDataSlotTaken": + return new GlobalParamsPlatformDataSlotTakenError(); + case "GlobalParamsPlatformFeePercentIsZero": + return new GlobalParamsPlatformFeePercentIsZeroError({ + platformBytes: args["platformBytes"] as string, + }); + case "GlobalParamsPlatformNotListed": + return new GlobalParamsPlatformNotListedError({ + platformBytes: args["platformBytes"] as string, + }); + case "GlobalParamsUnauthorized": + return new GlobalParamsUnauthorizedError(); + case "GlobalParamsCurrencyTokenLengthMismatch": + return new GlobalParamsCurrencyTokenLengthMismatchError(); + case "GlobalParamsCurrencyHasNoTokens": + return new GlobalParamsCurrencyHasNoTokensError({ + currency: args["currency"] as string, + }); + case "GlobalParamsTokenNotInCurrency": + return new GlobalParamsTokenNotInCurrencyError({ + currency: args["currency"] as string, + token: args["token"] as string, + }); + case "GlobalParamsPlatformLineItemTypeNotFound": + return new GlobalParamsPlatformLineItemTypeNotFoundError({ + platformHash: args["platformHash"] as string, + typeId: args["typeId"] as string, + }); + default: + return new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`); + } +} + +function toCampaignInfoFactoryError( + name: string, + args: Record, +): ContractErrorBase { + switch (name) { + case "CampaignInfoFactoryCampaignInitializationFailed": + return new CampaignInfoFactoryCampaignInitializationFailedError(); + case "CampaignInfoFactoryInvalidInput": + return new CampaignInfoFactoryInvalidInputError(); + case "CampaignInfoFactoryPlatformNotListed": + return new CampaignInfoFactoryPlatformNotListedError({ + platformHash: args["platformHash"] as string, + }); + case "CampaignInfoFactoryCampaignWithSameIdentifierExists": + return new CampaignInfoFactoryCampaignWithSameIdentifierExistsError({ + identifierHash: args["identifierHash"] as string, + cloneExists: args["cloneExists"] as string, + }); + case "CampaignInfoInvalidTokenList": + return new CampaignInfoInvalidTokenListError(); + default: + return ( + toSharedError(name, args) ?? + new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`) + ); + } +} + +function toCampaignInfoError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "CampaignInfoInvalidInput": + return new CampaignInfoInvalidInputError(); + case "CampaignInfoInvalidPlatformUpdate": + return new CampaignInfoInvalidPlatformUpdateError({ + platformBytes: args["platformBytes"] as string, + selection: args["selection"] as boolean, + }); + case "CampaignInfoPlatformNotSelected": + return new CampaignInfoPlatformNotSelectedError({ + platformBytes: args["platformBytes"] as string, + }); + case "CampaignInfoPlatformAlreadyApproved": + return new CampaignInfoPlatformAlreadyApprovedError({ + platformHash: args["platformHash"] as string, + }); + case "CampaignInfoUnauthorized": + return new CampaignInfoUnauthorizedError(); + case "CampaignInfoIsLocked": + return new CampaignInfoIsLockedError(); + default: + return ( + toSharedError(name, args) ?? + new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`) + ); + } +} + +function toAllOrNothingError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "AllOrNothingFeeNotDisbursed": + return new AllOrNothingFeeNotDisbursedError(); + case "AllOrNothingFeeAlreadyDisbursed": + return new AllOrNothingFeeAlreadyDisbursedError(); + case "AllOrNothingInvalidInput": + return new AllOrNothingInvalidInputError(); + case "AllOrNothingNotClaimable": + return new AllOrNothingNotClaimableError({ tokenId: args["tokenId"] as string }); + case "AllOrNothingNotSuccessful": + return new AllOrNothingNotSuccessfulError(); + case "AllOrNothingRewardExists": + return new AllOrNothingRewardExistsError(); + case "AllOrNothingTransferFailed": + return new AllOrNothingTransferFailedError(); + case "AllOrNothingUnAuthorized": + return new AllOrNothingUnAuthorizedError(); + case "AllOrNothingTokenNotAccepted": + return new AllOrNothingTokenNotAcceptedError({ token: args["token"] as string }); + case "TreasurySuccessConditionNotFulfilled": + return new TreasurySuccessConditionNotFulfilledError(); + default: + return ( + toSharedError(name, args) ?? + new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`) + ); + } +} + +function toKeepWhatsRaisedError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "KeepWhatsRaisedUnAuthorized": + return new KeepWhatsRaisedUnAuthorizedError(); + case "KeepWhatsRaisedInvalidInput": + return new KeepWhatsRaisedInvalidInputError(); + case "KeepWhatsRaisedTokenNotAccepted": + return new KeepWhatsRaisedTokenNotAcceptedError({ token: args["token"] as string }); + case "KeepWhatsRaisedRewardExists": + return new KeepWhatsRaisedRewardExistsError(); + case "KeepWhatsRaisedDisabled": + return new KeepWhatsRaisedDisabledError(); + case "KeepWhatsRaisedAlreadyEnabled": + return new KeepWhatsRaisedAlreadyEnabledError(); + case "KeepWhatsRaisedInsufficientFundsForWithdrawalAndFee": + return new KeepWhatsRaisedInsufficientFundsForWithdrawalAndFeeError({ + availableAmount: args["availableAmount"] as string, + withdrawalAmount: args["withdrawalAmount"] as string, + fee: args["fee"] as string, + }); + case "KeepWhatsRaisedInsufficientFundsForFee": + return new KeepWhatsRaisedInsufficientFundsForFeeError({ + withdrawalAmount: args["withdrawalAmount"] as string, + fee: args["fee"] as string, + }); + case "KeepWhatsRaisedAlreadyWithdrawn": + return new KeepWhatsRaisedAlreadyWithdrawnError(); + case "KeepWhatsRaisedAlreadyClaimed": + return new KeepWhatsRaisedAlreadyClaimedError(); + case "KeepWhatsRaisedNotClaimable": + return new KeepWhatsRaisedNotClaimableError({ tokenId: args["tokenId"] as string }); + case "KeepWhatsRaisedNotClaimableAdmin": + return new KeepWhatsRaisedNotClaimableAdminError(); + case "KeepWhatsRaisedConfigLocked": + return new KeepWhatsRaisedConfigLockedError(); + case "KeepWhatsRaisedDisbursementBlocked": + return new KeepWhatsRaisedDisbursementBlockedError(); + case "KeepWhatsRaisedPledgeAlreadyProcessed": + return new KeepWhatsRaisedPledgeAlreadyProcessedError({ + pledgeId: args["pledgeId"] as string, + }); + default: + return ( + toSharedError(name, args) ?? + new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`) + ); + } +} + +function toItemRegistryError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "ItemRegistryMismatchedArraysLength": + return new ItemRegistryMismatchedArraysLengthError(); + default: + return new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`); + } +} + +function toPaymentTreasuryError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "PaymentTreasuryUnAuthorized": + return new PaymentTreasuryUnAuthorizedError(); + case "PaymentTreasuryInvalidInput": + return new PaymentTreasuryInvalidInputError(); + case "PaymentTreasuryPaymentAlreadyExist": + return new PaymentTreasuryPaymentAlreadyExistError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryPaymentAlreadyConfirmed": + return new PaymentTreasuryPaymentAlreadyConfirmedError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryPaymentAlreadyExpired": + return new PaymentTreasuryPaymentAlreadyExpiredError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryPaymentNotExist": + return new PaymentTreasuryPaymentNotExistError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryCampaignInfoIsPaused": + return new PaymentTreasuryCampaignInfoIsPausedError(); + case "PaymentTreasuryTokenNotAccepted": + return new PaymentTreasuryTokenNotAcceptedError({ token: args["token"] as string }); + case "PaymentTreasurySuccessConditionNotFulfilled": + return new PaymentTreasurySuccessConditionNotFulfilledError(); + case "PaymentTreasuryFeeNotDisbursed": + return new PaymentTreasuryFeeNotDisbursedError(); + case "PaymentTreasuryPaymentNotConfirmed": + return new PaymentTreasuryPaymentNotConfirmedError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryPaymentNotClaimable": + return new PaymentTreasuryPaymentNotClaimableError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryAlreadyWithdrawn": + return new PaymentTreasuryAlreadyWithdrawnError(); + case "PaymentTreasuryCryptoPayment": + return new PaymentTreasuryCryptoPaymentError({ + paymentId: args["paymentId"] as string, + }); + case "PaymentTreasuryInsufficientFundsForFee": + return new PaymentTreasuryInsufficientFundsForFeeError({ + withdrawalAmount: args["withdrawalAmount"] as string, + fee: args["fee"] as string, + }); + case "PaymentTreasuryInsufficientBalance": + return new PaymentTreasuryInsufficientBalanceError({ + required: args["required"] as string, + available: args["available"] as string, + }); + case "PaymentTreasuryExpirationExceedsMax": + return new PaymentTreasuryExpirationExceedsMaxError({ + expiration: args["expiration"] as string, + maxExpiration: args["maxExpiration"] as string, + }); + case "PaymentTreasuryClaimWindowNotReached": + return new PaymentTreasuryClaimWindowNotReachedError({ + claimableAt: args["claimableAt"] as string, + }); + case "PaymentTreasuryNoFundsToClaim": + return new PaymentTreasuryNoFundsToClaimError(); + default: + return new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`); + } +} + +function toTreasuryFactoryError(name: string, args: Record): ContractErrorBase { + switch (name) { + case "TreasuryFactoryUnauthorized": + return new TreasuryFactoryUnauthorizedError(); + case "TreasuryFactoryInvalidKey": + return new TreasuryFactoryInvalidKeyError(); + case "TreasuryFactoryTreasuryCreationFailed": + return new TreasuryFactoryTreasuryCreationFailedError(); + case "TreasuryFactoryInvalidAddress": + return new TreasuryFactoryInvalidAddressError(); + case "TreasuryFactoryImplementationNotSet": + return new TreasuryFactoryImplementationNotSetError(); + case "TreasuryFactoryImplementationNotSetOrApproved": + return new TreasuryFactoryImplementationNotSetOrApprovedError(); + case "TreasuryFactoryTreasuryInitializationFailed": + return new TreasuryFactoryTreasuryInitializationFailedError(); + case "TreasuryFactorySettingPlatformInfoFailed": + return new TreasuryFactorySettingPlatformInfoFailedError(); + default: + return ( + toSharedError(name, args) ?? + new (class extends Error implements ContractErrorBase { + readonly name = name; + readonly args = args; + })(`${name}(${JSON.stringify(args)})`) + ); + } +} + +type AbiEntry = { type: string; name?: string; inputs?: readonly { name: string }[] }; + +function tryDecode( + abi: readonly AbiEntry[], + data: Hex, + toError: (name: string, args: Record) => ContractErrorBase, +): ContractErrorBase | null { + try { + const decoded = decodeErrorResult({ abi: abi as Parameters[0]["abi"], data }); + const decodedArgs = (decoded.args ?? []) as readonly unknown[]; + const args = decodeArgs(abi, decoded.errorName, decodedArgs); + return toError(decoded.errorName, args); + } catch { + return null; + } +} + +/** + * Parses raw revert data from a contract call and returns a typed SDK error if the error + * is recognized. Supports: GlobalParams, CampaignInfoFactory, CampaignInfo, AllOrNothing, + * KeepWhatsRaised, ItemRegistry, PaymentTreasury, TreasuryFactory. + * Returns null if the data is not valid or not from a known contract. + * + * Use this when you have raw revert data (e.g. from a provider or estimateGas) and want + * to get a typed, discriminable error with decoded args and optional recovery hints. + * + * @param revertData - Hex string (0x + selector + encoded args), e.g. from catch (e) \{ e.data \} + * @returns Typed ContractErrorBase instance or null + */ +export function parseContractError(revertData: string): ContractErrorBase | null { + if (!revertData || !isHex(revertData) || revertData.length < 10) { + return null; + } + + const data = revertData as Hex; + + return ( + tryDecode(GLOBAL_PARAMS_ABI, data, toGlobalParamsError) ?? + tryDecode(CAMPAIGN_INFO_FACTORY_ABI, data, toCampaignInfoFactoryError) ?? + tryDecode(CAMPAIGN_INFO_ABI, data, toCampaignInfoError) ?? + tryDecode(ALL_OR_NOTHING_ABI, data, toAllOrNothingError) ?? + tryDecode(KEEP_WHATS_RAISED_ABI, data, toKeepWhatsRaisedError) ?? + tryDecode(ITEM_REGISTRY_ABI, data, toItemRegistryError) ?? + tryDecode(PAYMENT_TREASURY_ABI, data, toPaymentTreasuryError) ?? + tryDecode(TREASURY_FACTORY_ABI, data, toTreasuryFactoryError) ?? + null + ); +} diff --git a/packages/contracts/src/errors/payment-treasury.ts b/packages/contracts/src/errors/payment-treasury.ts new file mode 100644 index 0000000..80fd23b --- /dev/null +++ b/packages/contracts/src/errors/payment-treasury.ts @@ -0,0 +1,259 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class PaymentTreasuryUnAuthorizedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryUnAuthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized for this operation on the PaymentTreasury."; + + constructor() { + super("PaymentTreasuryUnAuthorized()"); + Object.setPrototypeOf(this, PaymentTreasuryUnAuthorizedError.prototype); + } +} + +export class PaymentTreasuryInvalidInputError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryInvalidInput"; + readonly args: Record = {}; + readonly recoveryHint = "One or more inputs are invalid. Check all provided parameters."; + + constructor() { + super("PaymentTreasuryInvalidInput()"); + Object.setPrototypeOf(this, PaymentTreasuryInvalidInputError.prototype); + } +} + +export class PaymentTreasuryPaymentAlreadyExistError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryPaymentAlreadyExist"; + readonly args: { paymentId: string }; + readonly recoveryHint = "A payment with this ID already exists. Use a unique payment ID."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryPaymentAlreadyExist(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryPaymentAlreadyExistError.prototype); + } +} + +export class PaymentTreasuryPaymentAlreadyConfirmedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryPaymentAlreadyConfirmed"; + readonly args: { paymentId: string }; + readonly recoveryHint = "This payment has already been confirmed and cannot be confirmed again."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryPaymentAlreadyConfirmed(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryPaymentAlreadyConfirmedError.prototype); + } +} + +export class PaymentTreasuryPaymentAlreadyExpiredError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryPaymentAlreadyExpired"; + readonly args: { paymentId: string }; + readonly recoveryHint = "This payment has expired and can no longer be confirmed or modified."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryPaymentAlreadyExpired(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryPaymentAlreadyExpiredError.prototype); + } +} + +export class PaymentTreasuryPaymentNotExistError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryPaymentNotExist"; + readonly args: { paymentId: string }; + readonly recoveryHint = "No payment found with this ID. Check the payment ID and try again."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryPaymentNotExist(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryPaymentNotExistError.prototype); + } +} + +export class PaymentTreasuryCampaignInfoIsPausedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryCampaignInfoIsPaused"; + readonly args: Record = {}; + readonly recoveryHint = "The campaign is paused. Unpause the campaign before performing this operation."; + + constructor() { + super("PaymentTreasuryCampaignInfoIsPaused()"); + Object.setPrototypeOf(this, PaymentTreasuryCampaignInfoIsPausedError.prototype); + } +} + +export class PaymentTreasuryTokenNotAcceptedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryTokenNotAccepted"; + readonly args: { token: string }; + readonly recoveryHint = "This token is not accepted for payment. Use an accepted token for this campaign."; + + constructor(args: { token: string }) { + super(`PaymentTreasuryTokenNotAccepted(token: ${args.token})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryTokenNotAcceptedError.prototype); + } +} + +export class PaymentTreasurySuccessConditionNotFulfilledError + extends Error + implements ContractErrorBase +{ + readonly name = "PaymentTreasurySuccessConditionNotFulfilled"; + readonly args: Record = {}; + readonly recoveryHint = + "The campaign success condition has not been fulfilled. The goal amount must be reached before withdrawing."; + + constructor() { + super("PaymentTreasurySuccessConditionNotFulfilled()"); + Object.setPrototypeOf(this, PaymentTreasurySuccessConditionNotFulfilledError.prototype); + } +} + +export class PaymentTreasuryFeeNotDisbursedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryFeeNotDisbursed"; + readonly args: Record = {}; + readonly recoveryHint = "Fees have not been disbursed yet. Call disburseFees() before withdrawing."; + + constructor() { + super("PaymentTreasuryFeeNotDisbursed()"); + Object.setPrototypeOf(this, PaymentTreasuryFeeNotDisbursedError.prototype); + } +} + +export class PaymentTreasuryPaymentNotConfirmedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryPaymentNotConfirmed"; + readonly args: { paymentId: string }; + readonly recoveryHint = "This payment has not been confirmed yet. Confirm the payment before claiming."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryPaymentNotConfirmed(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryPaymentNotConfirmedError.prototype); + } +} + +export class PaymentTreasuryPaymentNotClaimableError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryPaymentNotClaimable"; + readonly args: { paymentId: string }; + readonly recoveryHint = + "This payment is not claimable. It may not be confirmed, may have expired, or the claim window has not been reached."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryPaymentNotClaimable(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryPaymentNotClaimableError.prototype); + } +} + +export class PaymentTreasuryAlreadyWithdrawnError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryAlreadyWithdrawn"; + readonly args: Record = {}; + readonly recoveryHint = "Funds have already been withdrawn from this treasury."; + + constructor() { + super("PaymentTreasuryAlreadyWithdrawn()"); + Object.setPrototypeOf(this, PaymentTreasuryAlreadyWithdrawnError.prototype); + } +} + +export class PaymentTreasuryCryptoPaymentError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryCryptoPayment"; + readonly args: { paymentId: string }; + readonly recoveryHint = + "This payment is a crypto payment and cannot be processed through this flow. Use processCryptoPayment() instead."; + + constructor(args: { paymentId: string }) { + super(`PaymentTreasuryCryptoPayment(paymentId: ${args.paymentId})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryCryptoPaymentError.prototype); + } +} + +export class PaymentTreasuryInsufficientFundsForFeeError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryInsufficientFundsForFee"; + readonly args: { withdrawalAmount: string; fee: string }; + readonly recoveryHint = + "Insufficient funds to cover the withdrawal fee. Ensure the treasury has enough balance to pay the fee."; + + constructor(args: { withdrawalAmount: string; fee: string }) { + super( + `PaymentTreasuryInsufficientFundsForFee(withdrawalAmount: ${args.withdrawalAmount}, fee: ${args.fee})`, + ); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryInsufficientFundsForFeeError.prototype); + } +} + +export class PaymentTreasuryInsufficientBalanceError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryInsufficientBalance"; + readonly args: { required: string; available: string }; + readonly recoveryHint = + "Insufficient balance in the treasury. The required amount exceeds the available funds."; + + constructor(args: { required: string; available: string }) { + super( + `PaymentTreasuryInsufficientBalance(required: ${args.required}, available: ${args.available})`, + ); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryInsufficientBalanceError.prototype); + } +} + +export class PaymentTreasuryExpirationExceedsMaxError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryExpirationExceedsMax"; + readonly args: { expiration: string; maxExpiration: string }; + readonly recoveryHint = + "The payment expiration exceeds the maximum allowed expiration. Use a shorter expiration time."; + + constructor(args: { expiration: string; maxExpiration: string }) { + super( + `PaymentTreasuryExpirationExceedsMax(expiration: ${args.expiration}, maxExpiration: ${args.maxExpiration})`, + ); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryExpirationExceedsMaxError.prototype); + } +} + +export class PaymentTreasuryClaimWindowNotReachedError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryClaimWindowNotReached"; + readonly args: { claimableAt: string }; + readonly recoveryHint = + "The claim window has not been reached yet. Wait until the claimableAt timestamp before claiming."; + + constructor(args: { claimableAt: string }) { + super(`PaymentTreasuryClaimWindowNotReached(claimableAt: ${args.claimableAt})`); + this.args = args; + Object.setPrototypeOf(this, PaymentTreasuryClaimWindowNotReachedError.prototype); + } +} + +export class PaymentTreasuryNoFundsToClaimError extends Error implements ContractErrorBase { + readonly name = "PaymentTreasuryNoFundsToClaim"; + readonly args: Record = {}; + readonly recoveryHint = "There are no funds available to claim at this time."; + + constructor() { + super("PaymentTreasuryNoFundsToClaim()"); + Object.setPrototypeOf(this, PaymentTreasuryNoFundsToClaimError.prototype); + } +} + +export type PaymentTreasuryError = + | PaymentTreasuryUnAuthorizedError + | PaymentTreasuryInvalidInputError + | PaymentTreasuryPaymentAlreadyExistError + | PaymentTreasuryPaymentAlreadyConfirmedError + | PaymentTreasuryPaymentAlreadyExpiredError + | PaymentTreasuryPaymentNotExistError + | PaymentTreasuryCampaignInfoIsPausedError + | PaymentTreasuryTokenNotAcceptedError + | PaymentTreasurySuccessConditionNotFulfilledError + | PaymentTreasuryFeeNotDisbursedError + | PaymentTreasuryPaymentNotConfirmedError + | PaymentTreasuryPaymentNotClaimableError + | PaymentTreasuryAlreadyWithdrawnError + | PaymentTreasuryCryptoPaymentError + | PaymentTreasuryInsufficientFundsForFeeError + | PaymentTreasuryInsufficientBalanceError + | PaymentTreasuryExpirationExceedsMaxError + | PaymentTreasuryClaimWindowNotReachedError + | PaymentTreasuryNoFundsToClaimError; diff --git a/packages/contracts/src/errors/shared.ts b/packages/contracts/src/errors/shared.ts new file mode 100644 index 0000000..51306d1 --- /dev/null +++ b/packages/contracts/src/errors/shared.ts @@ -0,0 +1,105 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class AccessCheckerUnauthorizedError extends Error implements ContractErrorBase { + readonly name = "AccessCheckerUnauthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized. Check access control permissions."; + + constructor() { + super("AccessCheckerUnauthorized()"); + Object.setPrototypeOf(this, AccessCheckerUnauthorizedError.prototype); + } +} + +export class AdminAccessCheckerUnauthorizedError extends Error implements ContractErrorBase { + readonly name = "AdminAccessCheckerUnauthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not an admin. Only admins can perform this operation."; + + constructor() { + super("AdminAccessCheckerUnauthorized()"); + Object.setPrototypeOf(this, AdminAccessCheckerUnauthorizedError.prototype); + } +} + +export class CurrentTimeIsGreaterError extends Error implements ContractErrorBase { + readonly name = "CurrentTimeIsGreater"; + readonly args: { inputTime: string; currentTime: string }; + readonly recoveryHint = "The input time is in the past. Provide a future timestamp."; + + constructor(args: { inputTime: string; currentTime: string }) { + super(`CurrentTimeIsGreater(inputTime: ${args.inputTime}, currentTime: ${args.currentTime})`); + this.args = args; + Object.setPrototypeOf(this, CurrentTimeIsGreaterError.prototype); + } +} + +export class CurrentTimeIsLessError extends Error implements ContractErrorBase { + readonly name = "CurrentTimeIsLess"; + readonly args: { inputTime: string; currentTime: string }; + readonly recoveryHint = "The operation is not yet available. Wait until the specified time has passed."; + + constructor(args: { inputTime: string; currentTime: string }) { + super(`CurrentTimeIsLess(inputTime: ${args.inputTime}, currentTime: ${args.currentTime})`); + this.args = args; + Object.setPrototypeOf(this, CurrentTimeIsLessError.prototype); + } +} + +export class CurrentTimeIsNotWithinRangeError extends Error implements ContractErrorBase { + readonly name = "CurrentTimeIsNotWithinRange"; + readonly args: { initialTime: string; finalTime: string }; + readonly recoveryHint = + "Current time is outside the allowed range. The operation is only valid between the initial and final times."; + + constructor(args: { initialTime: string; finalTime: string }) { + super( + `CurrentTimeIsNotWithinRange(initialTime: ${args.initialTime}, finalTime: ${args.finalTime})`, + ); + this.args = args; + Object.setPrototypeOf(this, CurrentTimeIsNotWithinRangeError.prototype); + } +} + +export class TreasuryCampaignInfoIsPausedError extends Error implements ContractErrorBase { + readonly name = "TreasuryCampaignInfoIsPaused"; + readonly args: Record = {}; + readonly recoveryHint = "The campaign is paused. Unpause the campaign before performing this operation."; + + constructor() { + super("TreasuryCampaignInfoIsPaused()"); + Object.setPrototypeOf(this, TreasuryCampaignInfoIsPausedError.prototype); + } +} + +export class TreasuryFeeNotDisbursedError extends Error implements ContractErrorBase { + readonly name = "TreasuryFeeNotDisbursed"; + readonly args: Record = {}; + readonly recoveryHint = "Fees have not been disbursed yet. Call disburseFees() before this operation."; + + constructor() { + super("TreasuryFeeNotDisbursed()"); + Object.setPrototypeOf(this, TreasuryFeeNotDisbursedError.prototype); + } +} + +export class TreasuryTransferFailedError extends Error implements ContractErrorBase { + readonly name = "TreasuryTransferFailed"; + readonly args: Record = {}; + readonly recoveryHint = "Token transfer failed. Check token balances and allowances."; + + constructor() { + super("TreasuryTransferFailed()"); + Object.setPrototypeOf(this, TreasuryTransferFailedError.prototype); + } +} + +export type SharedError = + | AccessCheckerUnauthorizedError + | AdminAccessCheckerUnauthorizedError + | CurrentTimeIsGreaterError + | CurrentTimeIsLessError + | CurrentTimeIsNotWithinRangeError + | TreasuryCampaignInfoIsPausedError + | TreasuryFeeNotDisbursedError + | TreasuryTransferFailedError; diff --git a/packages/contracts/src/errors/treasury-factory.ts b/packages/contracts/src/errors/treasury-factory.ts new file mode 100644 index 0000000..d881bc0 --- /dev/null +++ b/packages/contracts/src/errors/treasury-factory.ts @@ -0,0 +1,112 @@ +import type { ContractErrorBase } from "./contract-error.js"; + +export class TreasuryFactoryUnauthorizedError extends Error implements ContractErrorBase { + readonly name = "TreasuryFactoryUnauthorized"; + readonly args: Record = {}; + readonly recoveryHint = "Caller is not authorized for this operation on the TreasuryFactory."; + + constructor() { + super("TreasuryFactoryUnauthorized()"); + Object.setPrototypeOf(this, TreasuryFactoryUnauthorizedError.prototype); + } +} + +export class TreasuryFactoryInvalidKeyError extends Error implements ContractErrorBase { + readonly name = "TreasuryFactoryInvalidKey"; + readonly args: Record = {}; + readonly recoveryHint = "The provided implementation key is invalid. Check the platform hash and implementation ID."; + + constructor() { + super("TreasuryFactoryInvalidKey()"); + Object.setPrototypeOf(this, TreasuryFactoryInvalidKeyError.prototype); + } +} + +export class TreasuryFactoryTreasuryCreationFailedError extends Error implements ContractErrorBase { + readonly name = "TreasuryFactoryTreasuryCreationFailed"; + readonly args: Record = {}; + readonly recoveryHint = "Treasury clone creation failed. Check the implementation address and try again."; + + constructor() { + super("TreasuryFactoryTreasuryCreationFailed()"); + Object.setPrototypeOf(this, TreasuryFactoryTreasuryCreationFailedError.prototype); + } +} + +export class TreasuryFactoryInvalidAddressError extends Error implements ContractErrorBase { + readonly name = "TreasuryFactoryInvalidAddress"; + readonly args: Record = {}; + readonly recoveryHint = "One or more provided addresses are invalid. Ensure all addresses are non-zero."; + + constructor() { + super("TreasuryFactoryInvalidAddress()"); + Object.setPrototypeOf(this, TreasuryFactoryInvalidAddressError.prototype); + } +} + +export class TreasuryFactoryImplementationNotSetError extends Error implements ContractErrorBase { + readonly name = "TreasuryFactoryImplementationNotSet"; + readonly args: Record = {}; + readonly recoveryHint = + "No implementation is registered for this platform and implementation ID. Register the implementation first."; + + constructor() { + super("TreasuryFactoryImplementationNotSet()"); + Object.setPrototypeOf(this, TreasuryFactoryImplementationNotSetError.prototype); + } +} + +export class TreasuryFactoryImplementationNotSetOrApprovedError + extends Error + implements ContractErrorBase +{ + readonly name = "TreasuryFactoryImplementationNotSetOrApproved"; + readonly args: Record = {}; + readonly recoveryHint = + "The implementation is not registered or not approved. Register and approve the implementation before deploying."; + + constructor() { + super("TreasuryFactoryImplementationNotSetOrApproved()"); + Object.setPrototypeOf(this, TreasuryFactoryImplementationNotSetOrApprovedError.prototype); + } +} + +export class TreasuryFactoryTreasuryInitializationFailedError + extends Error + implements ContractErrorBase +{ + readonly name = "TreasuryFactoryTreasuryInitializationFailed"; + readonly args: Record = {}; + readonly recoveryHint = + "Treasury initialization failed after cloning. Check the implementation and initialization parameters."; + + constructor() { + super("TreasuryFactoryTreasuryInitializationFailed()"); + Object.setPrototypeOf(this, TreasuryFactoryTreasuryInitializationFailedError.prototype); + } +} + +export class TreasuryFactorySettingPlatformInfoFailedError + extends Error + implements ContractErrorBase +{ + readonly name = "TreasuryFactorySettingPlatformInfoFailed"; + readonly args: Record = {}; + readonly recoveryHint = + "Setting platform info on the deployed treasury failed. Check the treasury implementation and platform data."; + + constructor() { + super("TreasuryFactorySettingPlatformInfoFailed()"); + Object.setPrototypeOf(this, TreasuryFactorySettingPlatformInfoFailedError.prototype); + } +} + +export type TreasuryFactoryError = + | TreasuryFactoryUnauthorizedError + | TreasuryFactoryInvalidKeyError + | TreasuryFactoryTreasuryCreationFailedError + | TreasuryFactoryInvalidAddressError + | TreasuryFactoryImplementationNotSetError + | TreasuryFactoryImplementationNotSetOrApprovedError + | TreasuryFactoryTreasuryInitializationFailedError + | TreasuryFactorySettingPlatformInfoFailedError; diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index a75b354..c8fd6e4 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -1,10 +1,31 @@ -// Contract definitions and types -// Add your contract code here - -/** - * Placeholder function to ensure coverage collection works - * Remove this once you add actual contract code - */ -export function placeholder(): void { - // This ensures coverage is calculated -} +export { createOakContractsClient } from "./client"; + +export * from "./utils"; +export * from "./types"; + +export type { + Account, + Address, + Hex, + PublicClient, + WalletClient, +} from "viem"; +export type { Chain } from "viem/chains"; + +export { + createPublicClient, + createWalletClient, + http, + custom, + stringToHex, + toHex, + parseEther, + formatEther, + parseUnits, + isAddress, + getAddress, +} from "viem"; +export { mainnet, sepolia, goerli } from "viem/chains"; + +export * from "./constants"; +export * from "./errors"; diff --git a/packages/contracts/src/types/client.ts b/packages/contracts/src/types/client.ts new file mode 100644 index 0000000..34b153e --- /dev/null +++ b/packages/contracts/src/types/client.ts @@ -0,0 +1,534 @@ +import type { + Account, + Address, + Hex, + PublicClient, + WalletClient, +} from "viem"; +import type { Chain } from "viem/chains"; +import type { OakContractsClientOptions } from "./config-options"; + +// Re-export Chain for convenience +export type { Chain }; + +// ─── Shared protocol struct types ───────────────────────────────────────────── + +/** ICampaignData.CampaignData -- used by CampaignInfo and CampaignInfoFactory */ +export interface CampaignData { + launchTime: bigint; + deadline: bigint; + goalAmount: bigint; + /** bytes32 currency identifier (e.g. keccak256("USD")) */ + currency: Hex; +} + +/** + * Reward struct for AllOrNothing and KeepWhatsRaised treasuries. + * Includes the `isRewardTier` flag to distinguish tiers from flat rewards. + */ +export interface TieredReward { + rewardValue: bigint; + isRewardTier: boolean; + itemId: readonly Hex[]; + itemValue: readonly bigint[]; + itemQuantity: readonly bigint[]; +} + +/** ICampaignPaymentTreasury.LineItem -- line item in a payment (typeId + amount). */ +export interface LineItem { + typeId: Hex; + amount: bigint; +} + +/** IItem.Item -- used by ItemRegistry */ +export interface Item { + actualWeight: bigint; + height: bigint; + width: bigint; + length: bigint; + /** bytes32 category identifier */ + category: Hex; + /** bytes32 declared currency identifier */ + declaredCurrency: Hex; +} + +/** + * ICampaignPaymentTreasury.PaymentLineItem -- stored with configuration snapshot. + * All uint256 values are bigint; bytes32 are hex strings. + */ +export interface PaymentLineItem { + typeId: Hex; + amount: bigint; + label: string; + countsTowardGoal: boolean; + applyProtocolFee: boolean; + canRefund: boolean; + instantTransfer: boolean; +} + +/** ICampaignPaymentTreasury.ExternalFees -- informational external fee metadata. */ +export interface ExternalFees { + feeType: Hex; + feeAmount: bigint; +} + +/** + * ICampaignPaymentTreasury.PaymentData -- comprehensive payment snapshot. + * Mirrors the on-chain struct; lineItems and externalFees include config snapshots. + */ +export interface PaymentData { + buyerAddress: Address; + buyerId: Hex; + itemId: Hex; + amount: bigint; + expiration: bigint; + isConfirmed: boolean; + isCryptoPayment: boolean; + lineItemCount: bigint; + paymentToken: Address; + lineItems: readonly PaymentLineItem[]; + externalFees: readonly ExternalFees[]; +} + +/** EIP-2612 permit parameters */ +export interface PermitParams { + owner: Address; + spender: Address; + value: bigint; + deadline: bigint; + v: number; + r: Hex; + s: Hex; +} + +/** + * Return type for getLineItemType / getPlatformLineItemType. + */ +export interface LineItemTypeInfo { + exists: boolean; + label: string; + countsTowardGoal: boolean; + applyProtocolFee: boolean; + canRefund: boolean; + instantTransfer: boolean; +} + +/** Return type for CampaignInfo.getCampaignConfig. */ +export interface CampaignConfig { + treasuryFactory: Address; + protocolFeePercent: bigint; + identifierHash: Hex; +} + +/** Config struct for KeepWhatsRaised.configureTreasury. */ +export interface KeepWhatsRaisedConfig { + minimumWithdrawalForFeeExemption: bigint; + withdrawalDelay: bigint; + refundDelay: bigint; + configLockPeriod: bigint; + isColombianCreator: boolean; +} + +/** FeeKeys struct for KeepWhatsRaised.configureTreasury. */ +export interface KeepWhatsRaisedFeeKeys { + flatFeeKey: Hex; + cumulativeFlatFeeKey: Hex; + grossPercentageFeeKeys: readonly Hex[]; +} + +/** FeeValues struct for KeepWhatsRaised.configureTreasury. */ +export interface KeepWhatsRaisedFeeValues { + flatFeeValue: bigint; + cumulativeFlatFeeValue: bigint; + grossPercentageFeeValues: readonly bigint[]; +} + +// ─── Client config types ─────────────────────────────────────────────────────── + +/** + * Chain identifier - can be a chain ID number or a Chain object from viem + */ +export type ChainIdentifier = number | Chain; + +/** + * Provider interface - wraps viem's PublicClient + * This is a type alias for viem's PublicClient to provide a familiar API + */ +export type JsonRpcProvider = PublicClient; + +/** + * Signer interface - wraps viem's WalletClient with Account + * This is a type alias for viem's WalletClient with Account to provide a familiar API + */ +export interface Wallet extends WalletClient { + account: Account; +} + +/** + * Simple configuration for creating an Oak Contracts SDK client from chainId + RPC + private key. + * Use this for backend scripts or when you have a single signer. + */ +export interface SimpleOakContractsClientConfig { + /** Chain ID (e.g. CHAIN_IDS.CELO_TESTNET_SEPOLIA) */ + chainId: number; + /** RPC URL for the chain */ + rpcUrl: string; + /** Private key as hex string (0x-prefixed) */ + privateKey: `0x${string}`; + /** Optional client options */ + options?: Partial; +} + +/** + * Configuration for creating an Oak Contracts SDK client with explicit provider and signer. + */ +export interface FullOakContractsClientConfig { + /** Chain identifier (chain ID number or Chain object) */ + chain: ChainIdentifier; + /** Provider instance (wrapped viem PublicClient) */ + provider: JsonRpcProvider; + /** Signer instance (wrapped viem WalletClient with Account) */ + signer: Wallet; + /** Optional client options */ + options?: Partial; +} + +/** + * Configuration for creating an Oak Contracts SDK client. + * Either simple (chainId, rpcUrl, privateKey) or full (chain, provider, signer). + */ +export type OakContractsClientConfig = + | SimpleOakContractsClientConfig + | FullOakContractsClientConfig; + +/** + * Public client configuration (without sensitive data) + */ +export interface PublicOakContractsClientConfig { + chain: Chain; +} + +// ─── Entity interfaces ───────────────────────────────────────────────────────── + +/** + * GlobalParams entity — read and write methods for a GlobalParams contract instance. + */ +export interface GlobalParamsEntity { + // Reads + getProtocolAdminAddress(): Promise
; + getProtocolFeePercent(): Promise; + getNumberOfListedPlatforms(): Promise; + checkIfPlatformIsListed(platformBytes: Hex): Promise; + checkIfPlatformDataKeyValid(platformDataKey: Hex): Promise; + getPlatformAdminAddress(platformBytes: Hex): Promise
; + getPlatformFeePercent(platformBytes: Hex): Promise; + getPlatformClaimDelay(platformBytes: Hex): Promise; + getPlatformAdapter(platformBytes: Hex): Promise
; + getPlatformDataOwner(platformDataKey: Hex): Promise; + getPlatformLineItemType(platformHash: Hex, typeId: Hex): Promise; + getTokensForCurrency(currency: Hex): Promise; + getFromRegistry(key: Hex): Promise; + owner(): Promise
; + paused(): Promise; + // Writes + enlistPlatform(platformHash: Hex, platformAdminAddress: Address, platformFeePercent: bigint, platformAdapter: Address): Promise; + delistPlatform(platformBytes: Hex): Promise; + updatePlatformAdminAddress(platformBytes: Hex, platformAdminAddress: Address): Promise; + updatePlatformClaimDelay(platformBytes: Hex, claimDelay: bigint): Promise; + updateProtocolAdminAddress(protocolAdminAddress: Address): Promise; + updateProtocolFeePercent(protocolFeePercent: bigint): Promise; + setPlatformAdapter(platformBytes: Hex, platformAdapter: Address): Promise; + setPlatformLineItemType(platformHash: Hex, typeId: Hex, label: string, countsTowardGoal: boolean, applyProtocolFee: boolean, canRefund: boolean, instantTransfer: boolean): Promise; + removePlatformLineItemType(platformHash: Hex, typeId: Hex): Promise; + addTokenToCurrency(currency: Hex, token: Address): Promise; + removeTokenFromCurrency(currency: Hex, token: Address): Promise; + addPlatformData(platformBytes: Hex, platformDataKey: Hex): Promise; + removePlatformData(platformBytes: Hex, platformDataKey: Hex): Promise; + addToRegistry(key: Hex, value: Hex): Promise; + transferOwnership(newOwner: Address): Promise; + renounceOwnership(): Promise; +} + +/** + * Campaign data shape for createCampaign (matches ICampaignData.CampaignData). + */ +export interface CreateCampaignData { + launchTime: bigint; + deadline: bigint; + goalAmount: bigint; + currency: Hex; +} + +/** + * Parameters for createCampaign on CampaignInfoFactory. + */ +export interface CreateCampaignParams { + creator: Address; + identifierHash: Hex; + selectedPlatformHash: readonly Hex[]; + /** Optional platform-specific data keys (parallel array with platformDataValue) */ + platformDataKey?: readonly Hex[]; + /** Optional platform-specific data values (parallel array with platformDataKey) */ + platformDataValue?: readonly Hex[]; + campaignData: CreateCampaignData; + nftName: string; + nftSymbol: string; + nftImageURI: string; + contractURI: string; +} + +/** + * CampaignInfoFactory entity — createCampaign (write) and identifier/ownership reads. + */ +export interface CampaignInfoFactoryEntity { + createCampaign(params: CreateCampaignParams): Promise; + identifierToCampaignInfo(identifierHash: Hex): Promise
; + isValidCampaignInfo(campaignInfo: Address): Promise; + owner(): Promise
; + updateImplementation(newImplementation: Address): Promise; + transferOwnership(newOwner: Address): Promise; + renounceOwnership(): Promise; +} + +/** + * TreasuryFactory entity — deploy and manage treasury implementations. + */ +export interface TreasuryFactoryEntity { + deploy(platformHash: Hex, infoAddress: Address, implementationId: bigint): Promise; + registerTreasuryImplementation(platformHash: Hex, implementationId: bigint, implementation: Address): Promise; + approveTreasuryImplementation(platformHash: Hex, implementationId: bigint): Promise; + disapproveTreasuryImplementation(implementation: Address): Promise; + removeTreasuryImplementation(platformHash: Hex, implementationId: bigint): Promise; +} + +/** + * CampaignInfo entity — full reads and writes for a deployed CampaignInfo contract. + */ +export interface CampaignInfoEntity { + // Reads + getLaunchTime(): Promise; + getDeadline(): Promise; + getGoalAmount(): Promise; + getCampaignCurrency(): Promise; + getIdentifierHash(): Promise; + checkIfPlatformSelected(platformBytes: Hex): Promise; + checkIfPlatformApproved(platformHash: Hex): Promise; + getPlatformAdminAddress(platformBytes: Hex): Promise
; + getPlatformData(platformDataKey: Hex): Promise; + getPlatformFeePercent(platformBytes: Hex): Promise; + getPlatformClaimDelay(platformHash: Hex): Promise; + getProtocolAdminAddress(): Promise
; + getProtocolFeePercent(): Promise; + getAcceptedTokens(): Promise; + isTokenAccepted(token: Address): Promise; + getTotalRaisedAmount(): Promise; + getTotalLifetimeRaisedAmount(): Promise; + getTotalRefundedAmount(): Promise; + getTotalAvailableRaisedAmount(): Promise; + getTotalCancelledAmount(): Promise; + getTotalExpectedAmount(): Promise; + getDataFromRegistry(key: Hex): Promise; + getBufferTime(): Promise; + getLineItemType(platformHash: Hex, typeId: Hex): Promise; + getCampaignConfig(): Promise; + getApprovedPlatformHashes(): Promise; + isLocked(): Promise; + cancelled(): Promise; + owner(): Promise
; + paused(): Promise; + // Writes + updateDeadline(deadline: bigint): Promise; + updateGoalAmount(goalAmount: bigint): Promise; + updateLaunchTime(launchTime: bigint): Promise; + updateSelectedPlatform(platformHash: Hex, selection: boolean, platformDataKey: readonly Hex[], platformDataValue: readonly Hex[]): Promise; + setImageURI(newImageURI: string): Promise; + updateContractURI(newContractURI: string): Promise; + /** Mints an NFT for a pledge; returns the tx hash (tokenId is in the receipt events). */ + mintNFTForPledge(backer: Address, reward: Hex, tokenAddress: Address, amount: bigint, shippingFee: bigint, tipAmount: bigint): Promise; + burn(tokenId: bigint): Promise; + pauseCampaign(message: Hex): Promise; + unpauseCampaign(message: Hex): Promise; + cancelCampaign(message: Hex): Promise; + setPlatformInfo(platformBytes: Hex, platformTreasuryAddress: Address): Promise; + transferOwnership(newOwner: Address): Promise; + renounceOwnership(): Promise; +} + +/** + * PaymentTreasury entity — full reads and writes for a deployed PaymentTreasury contract. + */ +export interface PaymentTreasuryEntity { + // Reads + getPlatformHash(): Promise; + getPlatformFeePercent(): Promise; + getRaisedAmount(): Promise; + getAvailableRaisedAmount(): Promise; + getLifetimeRaisedAmount(): Promise; + getRefundedAmount(): Promise; + getExpectedAmount(): Promise; + getPaymentData(paymentId: Hex): Promise; + cancelled(): Promise; + // Writes + createPayment(paymentId: Hex, buyerId: Hex, itemId: Hex, paymentToken: Address, amount: bigint, expiration: bigint, lineItems: readonly LineItem[], externalFees: readonly ExternalFees[]): Promise; + createPaymentBatch(paymentIds: readonly Hex[], buyerIds: readonly Hex[], itemIds: readonly Hex[], paymentTokens: readonly Address[], amounts: readonly bigint[], expirations: readonly bigint[], lineItemsArray: readonly (readonly LineItem[])[], externalFeesArray: readonly (readonly ExternalFees[])[]): Promise; + processCryptoPayment(paymentId: Hex, itemId: Hex, buyerAddress: Address, paymentToken: Address, amount: bigint, lineItems: readonly LineItem[], externalFees: readonly ExternalFees[]): Promise; + cancelPayment(paymentId: Hex): Promise; + confirmPayment(paymentId: Hex, buyerAddress: Address): Promise; + confirmPaymentBatch(paymentIds: readonly Hex[], buyerAddresses: readonly Address[]): Promise; + disburseFees(): Promise; + withdraw(): Promise; + /** Claim refund to a specific address. */ + claimRefund(paymentId: Hex, refundAddress: Address): Promise; + /** Claim refund to the caller's address. */ + claimRefundSelf(paymentId: Hex): Promise; + claimExpiredFunds(): Promise; + claimNonGoalLineItems(token: Address): Promise; + pauseTreasury(message: Hex): Promise; + unpauseTreasury(message: Hex): Promise; + cancelTreasury(message: Hex): Promise; +} + +/** + * AllOrNothing treasury entity — full reads and writes including ERC721 and pledge operations. + */ +export interface AllOrNothingTreasuryEntity { + // Reads + getRaisedAmount(): Promise; + getLifetimeRaisedAmount(): Promise; + getRefundedAmount(): Promise; + getReward(rewardName: Hex): Promise; + getPlatformHash(): Promise; + getPlatformFeePercent(): Promise; + paused(): Promise; + cancelled(): Promise; + balanceOf(owner: Address): Promise; + ownerOf(tokenId: bigint): Promise
; + tokenURI(tokenId: bigint): Promise; + name(): Promise; + symbol(): Promise; + getApproved(tokenId: bigint): Promise
; + isApprovedForAll(owner: Address, operator: Address): Promise; + supportsInterface(interfaceId: Hex): Promise; + // Writes + pauseTreasury(message: Hex): Promise; + unpauseTreasury(message: Hex): Promise; + cancelTreasury(message: Hex): Promise; + addRewards(rewardNames: readonly Hex[], rewards: readonly TieredReward[]): Promise; + removeReward(rewardName: Hex): Promise; + pledgeForAReward(backer: Address, pledgeToken: Address, shippingFee: bigint, rewardNames: readonly Hex[]): Promise; + pledgeWithoutAReward(backer: Address, pledgeToken: Address, pledgeAmount: bigint): Promise; + claimRefund(tokenId: bigint): Promise; + disburseFees(): Promise; + withdraw(): Promise; + burn(tokenId: bigint): Promise; + approve(to: Address, tokenId: bigint): Promise; + setApprovalForAll(operator: Address, approved: boolean): Promise; + safeTransferFrom(from: Address, to: Address, tokenId: bigint): Promise; + transferFrom(from: Address, to: Address, tokenId: bigint): Promise; +} + +/** + * KeepWhatsRaised treasury entity — full reads and writes including pledge-based operations. + */ +export interface KeepWhatsRaisedTreasuryEntity { + // Reads + getRaisedAmount(): Promise; + getLifetimeRaisedAmount(): Promise; + getRefundedAmount(): Promise; + getAvailableRaisedAmount(): Promise; + getReward(rewardName: Hex): Promise; + getPlatformHash(): Promise; + getPlatformFeePercent(): Promise; + getWithdrawalApprovalStatus(): Promise; + getLaunchTime(): Promise; + getDeadline(): Promise; + getGoalAmount(): Promise; + getPaymentGatewayFee(pledgeId: Hex): Promise; + getFeeValue(feeKey: Hex): Promise; + paused(): Promise; + cancelled(): Promise; + balanceOf(owner: Address): Promise; + ownerOf(tokenId: bigint): Promise
; + tokenURI(tokenId: bigint): Promise; + name(): Promise; + symbol(): Promise; + getApproved(tokenId: bigint): Promise
; + isApprovedForAll(owner: Address, operator: Address): Promise; + supportsInterface(interfaceId: Hex): Promise; + // Writes + pauseTreasury(message: Hex): Promise; + unpauseTreasury(message: Hex): Promise; + cancelTreasury(message: Hex): Promise; + configureTreasury(config: KeepWhatsRaisedConfig, campaignData: CampaignData, feeKeys: KeepWhatsRaisedFeeKeys, feeValues: KeepWhatsRaisedFeeValues): Promise; + addRewards(rewardNames: readonly Hex[], rewards: readonly TieredReward[]): Promise; + removeReward(rewardName: Hex): Promise; + approveWithdrawal(): Promise; + setPaymentGatewayFee(pledgeId: Hex, fee: bigint): Promise; + setFeeAndPledge(pledgeId: Hex, backer: Address, pledgeToken: Address, pledgeAmount: bigint, tip: bigint, fee: bigint, reward: readonly Hex[], isPledgeForAReward: boolean): Promise; + pledgeForAReward(pledgeId: Hex, backer: Address, pledgeToken: Address, tip: bigint, rewardNames: readonly Hex[]): Promise; + pledgeWithoutAReward(pledgeId: Hex, backer: Address, pledgeToken: Address, pledgeAmount: bigint, tip: bigint): Promise; + claimRefund(tokenId: bigint): Promise; + claimTip(): Promise; + claimFund(): Promise; + disburseFees(): Promise; + withdraw(token: Address, amount: bigint): Promise; + updateDeadline(deadline: bigint): Promise; + updateGoalAmount(goalAmount: bigint): Promise; + approve(to: Address, tokenId: bigint): Promise; + setApprovalForAll(operator: Address, approved: boolean): Promise; + safeTransferFrom(from: Address, to: Address, tokenId: bigint): Promise; + transferFrom(from: Address, to: Address, tokenId: bigint): Promise; +} + +/** + * ItemRegistry entity — add and retrieve items. + */ +export interface ItemRegistryEntity { + getItem(owner: Address, itemId: Hex): Promise; + addItem(itemId: Hex, item: Item): Promise; + addItemsBatch(itemIds: readonly Hex[], items: readonly Item[]): Promise; +} + +// ─── Receipt type ────────────────────────────────────────────────────────────── + +/** + * Transaction receipt returned by waitForReceipt. + */ +export interface TransactionReceipt { + blockNumber: bigint; + gasUsed: bigint; + logs: readonly { topics: readonly Hex[]; data: Hex }[]; +} + +// ─── Main client interface ───────────────────────────────────────────────────── + +/** + * Oak Contracts SDK Client interface. + * Supports both simple (chainId/rpcUrl/privateKey) and full (chain/provider/signer) config. + */ +export interface OakContractsClient { + readonly config: PublicOakContractsClientConfig; + readonly options: OakContractsClientOptions; + /** Viem public client for reads and waitForTransactionReceipt */ + readonly publicClient: PublicClient; + /** Viem wallet client (with account when using privateKey or signer) */ + readonly walletClient: WalletClient; + /** Wait for a transaction to be mined; returns receipt with blockNumber, gasUsed, logs */ + waitForReceipt(txHash: Hex): Promise; + /** Get a GlobalParams entity for the given contract address */ + globalParams(address: Address): GlobalParamsEntity; + /** Get a CampaignInfoFactory entity for the given contract address */ + campaignInfoFactory(address: Address): CampaignInfoFactoryEntity; + /** Get a TreasuryFactory entity for the given contract address */ + treasuryFactory(address: Address): TreasuryFactoryEntity; + /** Get a CampaignInfo entity for the given contract address */ + campaignInfo(address: Address): CampaignInfoEntity; + /** Get a PaymentTreasury entity for the given contract address */ + paymentTreasury(address: Address): PaymentTreasuryEntity; + /** Get an AllOrNothing treasury entity for the given contract address */ + allOrNothingTreasury(address: Address): AllOrNothingTreasuryEntity; + /** Get a KeepWhatsRaised treasury entity for the given contract address */ + keepWhatsRaisedTreasury(address: Address): KeepWhatsRaisedTreasuryEntity; + /** Get an ItemRegistry entity for the given contract address */ + itemRegistry(address: Address): ItemRegistryEntity; +} diff --git a/packages/contracts/src/types/config-options.ts b/packages/contracts/src/types/config-options.ts new file mode 100644 index 0000000..e5ad101 --- /dev/null +++ b/packages/contracts/src/types/config-options.ts @@ -0,0 +1,15 @@ +/** + * Client options configuration + */ +export interface OakContractsClientOptions { + /** + * Request timeout in milliseconds. + * Applied to HTTP transport calls (readContract, writeContract) and waitForTransactionReceipt. + * @default 30000 + */ + timeout?: number; +} + +export const DEFAULT_CLIENT_OPTIONS: OakContractsClientOptions = { + timeout: 30000, +}; diff --git a/packages/contracts/src/types/index.ts b/packages/contracts/src/types/index.ts new file mode 100644 index 0000000..8e4a487 --- /dev/null +++ b/packages/contracts/src/types/index.ts @@ -0,0 +1,7 @@ +/** + * All protocol types are defined in client.ts and re-exported here. + * Struct types (CampaignData, TieredReward, LineItem, etc.) live alongside + * the entity interfaces so they can reference each other without circular imports. + */ +export * from "./client"; +export * from "./config-options"; diff --git a/packages/contracts/src/utils/chain-registry.ts b/packages/contracts/src/utils/chain-registry.ts new file mode 100644 index 0000000..4ac676d --- /dev/null +++ b/packages/contracts/src/utils/chain-registry.ts @@ -0,0 +1,66 @@ +import { defineChain } from "viem"; +import { mainnet, sepolia, goerli } from "viem/chains"; +import type { Chain } from "viem/chains"; + +/** Celo Mainnet */ +const celoMainnet = defineChain({ + id: 42220, + name: "Celo", + nativeCurrency: { decimals: 18, name: "CELO", symbol: "CELO" }, + rpcUrls: { + default: { http: ["https://forno.celo.org"] }, + }, +}); + +/** Celo Sepolia testnet */ +const celoSepolia = defineChain({ + id: 11142220, + name: "Celo Sepolia", + nativeCurrency: { decimals: 18, name: "CELO", symbol: "CELO" }, + rpcUrls: { + default: { http: ["https://forno.celo-sepolia.celo-testnet.org"] }, + }, +}); + +/** + * Registry mapping chain IDs to Chain objects + * Contains common Ethereum and Celo chains + */ +const CHAIN_REGISTRY: Record = { + 1: mainnet, + 42220: celoMainnet, + 11155111: sepolia, + 5: goerli, + 11142220: celoSepolia, +}; + +/** + * Resolves a chain ID number to a Chain object + * @param chainId - Chain ID number + * @returns Chain object + */ +export function getChainFromId(chainId: number): Chain { + // Check if we have a predefined chain for this ID + const predefinedChain = CHAIN_REGISTRY[chainId]; + if (predefinedChain) { + return predefinedChain; + } + + // For unknown chain IDs, create a minimal chain object + // This allows the SDK to work with any chain ID, though some features + // may require a full chain definition + return defineChain({ + id: chainId, + name: `Chain ${chainId}`, + nativeCurrency: { + decimals: 18, + name: "Ether", + symbol: "ETH", + }, + rpcUrls: { + default: { + http: [], + }, + }, + }); +} diff --git a/packages/contracts/src/utils/index.ts b/packages/contracts/src/utils/index.ts new file mode 100644 index 0000000..6cd077b --- /dev/null +++ b/packages/contracts/src/utils/index.ts @@ -0,0 +1,201 @@ +// Re-export viem utility functions directly +export { + parseEther, + formatEther, + parseUnits, + isAddress, + getAddress, + stringToHex, + toHex, +} from "viem"; + +// Re-export chain IDs for simple client config +export { CHAIN_IDS } from "../constants"; + +import { + keccak256 as viemKeccak256, + stringToHex, + type Hex, + createPublicClient, + createWalletClient, + http, + custom, + type Account, + type EIP1193Provider, + type PublicClient, + type WalletClient, +} from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import type { Chain } from "viem/chains"; +import type { JsonRpcProvider, Wallet } from "../types"; + +/** + * Hash data using keccak256 + * @param data - String (will be converted to hex) or Uint8Array to hash + * @returns Hex string hash + */ +export function keccak256(data: string | Uint8Array): `0x${string}` { + if (typeof data === "string") { + // If it's already a hex string, use it directly; otherwise convert + if (data.startsWith("0x")) { + return viemKeccak256(data as Hex) as `0x${string}`; + } + return viemKeccak256(stringToHex(data)) as `0x${string}`; + } + return viemKeccak256(data) as `0x${string}`; +} + +/** + * Hash a string using keccak256 (alias for id) + * This is equivalent to keccak256(stringToHex(input)) + * @param input - String to hash + * @returns Hex string hash + */ +export function id(input: string): `0x${string}` { + return keccak256(stringToHex(input)); +} + +/** + * Get current Unix timestamp in seconds + * @returns Current timestamp as bigint + */ +export function getCurrentTimestamp(): bigint { + return BigInt(Math.floor(Date.now() / 1000)); +} + +/** + * Add days to a timestamp + * @param timestamp - Unix timestamp in seconds + * @param days - Number of days to add + * @returns New timestamp as bigint + */ +export function addDays(timestamp: bigint, days: number): bigint { + const secondsPerDay = BigInt(86400); + return timestamp + BigInt(days) * secondsPerDay; +} + +// Export chain registry utility +export { getChainFromId } from "./chain-registry"; + +/** + * Creates a JsonRpcProvider (wrapped viem PublicClient) from an RPC URL + * @param rpcUrl - RPC URL string + * @param chain - Chain configuration + * @returns JsonRpcProvider instance + * + * @example + * ```typescript + * import { createJsonRpcProvider, mainnet } from '@oaknetwork/contracts' + * + * const provider = createJsonRpcProvider('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY', mainnet) + * ``` + */ +export function createJsonRpcProvider( + rpcUrl: string, + chain: Chain, +): JsonRpcProvider { + return createPublicClient({ + chain, + transport: http(rpcUrl), + }) as JsonRpcProvider; +} + +/** + * Creates a Wallet (wrapped viem WalletClient) from a private key + * @param privateKey - Private key as hex string + * @param provider - Provider instance (PublicClient) - used to get chain config + * @param rpcUrl - Optional RPC URL. If not provided, will attempt to use the provider's transport + * @returns Wallet instance + * + * @example + * ```typescript + * import { createWallet, createJsonRpcProvider, mainnet } from '@oaknetwork/contracts' + * + * const provider = createJsonRpcProvider(rpcUrl, mainnet) + * const signer = createWallet(privateKey, provider, rpcUrl) + * ``` + */ +export function createWallet( + privateKey: `0x${string}`, + provider: PublicClient, + rpcUrl?: string, +): Wallet { + const transport = rpcUrl ? http(rpcUrl) : custom(provider as unknown as EIP1193Provider); + + const account = privateKeyToAccount(privateKey); + + const walletClient = createWalletClient({ + account, + chain: provider.chain, + transport, + }); + + return { + ...walletClient, + account, + } as Wallet; +} + +/** + * Creates a BrowserProvider (wrapped viem PublicClient) from window.ethereum + * This is a helper for frontend usage with MetaMask or other injected wallets + * @param ethereum - window.ethereum object (EIP-1193 provider) + * @param chain - Chain configuration + * @returns JsonRpcProvider instance + * + * @example + * ```typescript + * import { createBrowserProvider, mainnet } from '@oaknetwork/contracts' + * + * const provider = createBrowserProvider(window.ethereum, mainnet) + * ``` + */ +export function createBrowserProvider( + ethereum: EIP1193Provider, + chain: Chain, +): JsonRpcProvider { + return createPublicClient({ + chain, + transport: custom(ethereum), + }) as JsonRpcProvider; +} + +/** + * Gets a signer from a browser provider (for use with MetaMask, etc.) + * This creates a WalletClient from the browser provider's ethereum object + * @param ethereum - window.ethereum object (EIP-1193 provider) + * @param chain - Chain configuration + * @returns Promise that resolves to a Wallet instance + * + * @example + * ```typescript + * import { createBrowserProvider, getSigner, mainnet } from '@oaknetwork/contracts' + * + * const provider = createBrowserProvider(window.ethereum, mainnet) + * const signer = await getSigner(window.ethereum, mainnet) + * ``` + */ +export async function getSigner( + ethereum: EIP1193Provider, + chain: Chain, +): Promise { + // Request accounts from the provider + const accounts = await ethereum.request({ + method: "eth_requestAccounts", + }); + + if (!accounts || accounts.length === 0) { + throw new Error("No accounts found. Please connect your wallet."); + } + + const walletClient = createWalletClient({ + account: accounts[0] as `0x${string}`, + chain, + transport: custom(ethereum), + }); + + return { + ...walletClient, + account: walletClient.account as Account, + } as Wallet; +} diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index 309e9ce..b723b07 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -1,7 +1,8 @@ { "compilerOptions": { - "target": "ES2018", - "module": "commonjs", + "target": "ES2020", + "lib": ["ES2021", "DOM"], + "module": "ES2022", "outDir": "./dist", "rootDir": "./src", "strict": true, @@ -9,7 +10,8 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "declaration": true, - "moduleResolution": "node" + "moduleResolution": "bundler", + "noEmitOnError": false }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] diff --git a/packages/contracts/tsup.config.ts b/packages/contracts/tsup.config.ts new file mode 100644 index 0000000..4080a74 --- /dev/null +++ b/packages/contracts/tsup.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + index: "src/index.ts", + "utils/index": "src/utils/index.ts", + "contracts/index": "src/contracts/index.ts", + "client/index": "src/client/index.ts", + "errors/index": "src/errors/index.ts", + }, + format: ["esm"], + dts: true, + splitting: false, + clean: true, + sourcemap: false, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94a164c..29cf8a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,11 @@ importers: specifier: ^30.0.0 version: 30.0.0 - packages/payments: + packages/contracts: + dependencies: + viem: + specifier: ^2.23.0 + version: 2.47.0(typescript@5.9.3) devDependencies: '@types/jest': specifier: ^30.0.0 @@ -27,26 +31,23 @@ importers: '@types/node': specifier: ^20.14.11 version: 20.19.33 - dotenv: - specifier: ^17.2.1 - version: 17.3.1 jest: specifier: ^30.0.5 version: 30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)) - nock: - specifier: ^14.0.10 - version: 14.0.11 ts-jest: specifier: ^29.4.6 - version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.27.3)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)))(typescript@5.9.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.19.33)(typescript@5.9.3) + tsup: + specifier: ^8.5.1 + version: 8.5.1(typescript@5.9.3) typescript: specifier: ^5.5.4 version: 5.9.3 - packages/contracts: + packages/payments: devDependencies: '@types/jest': specifier: ^30.0.0 @@ -54,12 +55,18 @@ importers: '@types/node': specifier: ^20.14.11 version: 20.19.33 + dotenv: + specifier: ^17.2.1 + version: 17.3.1 jest: specifier: ^30.0.5 version: 30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)) + nock: + specifier: ^14.0.10 + version: 14.0.11 ts-jest: specifier: ^29.4.6 - version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.27.3)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)))(typescript@5.9.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.19.33)(typescript@5.9.3) @@ -69,6 +76,9 @@ importers: packages: + '@adraffy/ens-normalize@1.11.1': + resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -306,6 +316,162 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} @@ -441,6 +607,18 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@noble/ciphers@1.3.0': + resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.9.1': + resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -470,6 +648,140 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + + '@scure/bip32@1.7.0': + resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} + + '@scure/bip39@1.6.0': + resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} + '@sinclair/typebox@0.34.48': resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} @@ -506,6 +818,9 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -631,6 +946,17 @@ packages: cpu: [x64] os: [win32] + abitype@1.2.3: + resolution: {integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3.22.0 || ^4.0.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + acorn-walk@8.3.5: resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} engines: {node: '>=0.4.0'} @@ -668,6 +994,9 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -746,6 +1075,16 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -772,6 +1111,10 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -801,6 +1144,17 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -875,6 +1229,11 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -888,6 +1247,9 @@ packages: engines: {node: '>=4'} hasBin: true + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -916,6 +1278,15 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -924,6 +1295,9 @@ packages: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -1051,6 +1425,11 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isows@1.0.7: + resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} + peerDependencies: + ws: '*' + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -1202,6 +1581,10 @@ packages: node-notifier: optional: true + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1236,9 +1619,17 @@ packages: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -1255,6 +1646,9 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -1291,6 +1685,9 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} + mlly@1.8.1: + resolution: {integrity: sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==} + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1298,6 +1695,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + napi-postinstall@0.3.4: resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -1327,6 +1727,10 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -1337,6 +1741,14 @@ packages: outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + ox@0.14.0: + resolution: {integrity: sha512-WLOB7IKnmI3Ol6RAqY7CJdZKl8QaI44LN91OGF1061YIeN6bL5IsFcdp7+oQShRyamE/8fW/CBRWhJAOzI35Dw==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} @@ -1387,6 +1799,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1410,6 +1825,27 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} @@ -1439,6 +1875,10 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -1455,6 +1895,11 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1496,6 +1941,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} @@ -1545,6 +1994,11 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1565,6 +2019,20 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -1572,6 +2040,13 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + ts-jest@29.4.6: resolution: {integrity: sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} @@ -1616,6 +2091,25 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} @@ -1633,6 +2127,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} @@ -1661,6 +2158,14 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} + viem@2.47.0: + resolution: {integrity: sha512-jU5e1E1s5E5M1y+YrELDnNar/34U8NXfVcRfxtVETigs2gS1vvW2ngnBoQUGBwLnNr0kNv+NUu4m10OqHByoFw==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} @@ -1684,6 +2189,18 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -1709,6 +2226,8 @@ packages: snapshots: + '@adraffy/ens-normalize@1.11.1': {} + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -2064,6 +2583,84 @@ snapshots: tslib: 2.8.1 optional: true + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + '@inquirer/external-editor@1.0.3(@types/node@20.19.33)': dependencies: chardet: 2.1.1 @@ -2325,6 +2922,14 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@noble/ciphers@1.3.0': {} + + '@noble/curves@1.9.1': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.8.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2351,6 +2956,94 @@ snapshots: '@pkgr/core@0.2.9': {} + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + + '@scure/base@1.2.6': {} + + '@scure/bip32@1.7.0': + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + + '@scure/bip39@1.6.0': + dependencies: + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + '@sinclair/typebox@0.34.48': {} '@sinonjs/commons@3.0.1': @@ -2395,6 +3088,8 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@types/estree@1.0.8': {} + '@types/istanbul-lib-coverage@2.0.6': {} '@types/istanbul-lib-report@3.0.3': @@ -2485,6 +3180,10 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + abitype@1.2.3(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + acorn-walk@8.3.5: dependencies: acorn: 8.16.0 @@ -2509,6 +3208,8 @@ snapshots: ansi-styles@6.2.3: {} + any-promise@1.3.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -2610,6 +3311,13 @@ snapshots: buffer-from@1.1.2: {} + bundle-require@5.1.0(esbuild@0.27.3): + dependencies: + esbuild: 0.27.3 + load-tsconfig: 0.2.5 + + cac@6.7.14: {} + callsites@3.1.0: {} camelcase@5.3.1: {} @@ -2627,6 +3335,10 @@ snapshots: chardet@2.1.1: {} + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + ci-info@3.9.0: {} ci-info@4.4.0: {} @@ -2649,6 +3361,12 @@ snapshots: color-name@1.1.4: {} + commander@4.1.1: {} + + confbox@0.1.8: {} + + consola@3.4.2: {} + convert-source-map@2.0.0: {} create-require@1.1.1: {} @@ -2698,12 +3416,43 @@ snapshots: dependencies: is-arrayish: 0.2.1 + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + escalade@3.2.0: {} escape-string-regexp@2.0.0: {} esprima@4.0.1: {} + eventemitter3@5.0.1: {} + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -2747,6 +3496,10 @@ snapshots: dependencies: bser: 2.1.1 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2756,6 +3509,12 @@ snapshots: locate-path: 5.0.0 path-exists: 4.0.0 + fix-dts-default-cjs-exports@1.0.1: + dependencies: + magic-string: 0.30.21 + mlly: 1.8.1 + rollup: 4.59.0 + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -2864,6 +3623,10 @@ snapshots: isexe@2.0.0: {} + isows@1.0.7(ws@8.18.3): + dependencies: + ws: 8.18.3 + istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@6.0.3: @@ -3213,6 +3976,8 @@ snapshots: - supports-color - ts-node + joycon@3.1.1: {} + js-tokens@4.0.0: {} js-yaml@3.14.2: @@ -3238,8 +4003,12 @@ snapshots: leven@3.1.0: {} + lilconfig@3.1.3: {} + lines-and-columns@1.2.4: {} + load-tsconfig@0.2.5: {} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -3254,6 +4023,10 @@ snapshots: dependencies: yallist: 3.1.1 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + make-dir@4.0.0: dependencies: semver: 7.7.4 @@ -3283,10 +4056,23 @@ snapshots: minipass@7.1.3: {} + mlly@1.8.1: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.3 + mri@1.2.0: {} ms@2.1.3: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -3309,6 +4095,8 @@ snapshots: dependencies: path-key: 3.1.1 + object-assign@4.1.1: {} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -3317,6 +4105,21 @@ snapshots: outvariant@1.4.3: {} + ox@0.14.0(typescript@5.9.3): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.2.3(typescript@5.9.3) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - zod + p-filter@2.1.0: dependencies: p-map: 2.1.0 @@ -3361,6 +4164,8 @@ snapshots: path-type@4.0.0: {} + pathe@2.0.3: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -3375,6 +4180,16 @@ snapshots: dependencies: find-up: 4.1.0 + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.1 + pathe: 2.0.3 + + postcss-load-config@6.0.1: + dependencies: + lilconfig: 3.1.3 + prettier@2.8.8: {} pretty-format@30.2.0: @@ -3400,6 +4215,8 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readdirp@4.1.2: {} + require-directory@2.1.1: {} resolve-cwd@3.0.0: @@ -3410,6 +4227,37 @@ snapshots: reusify@1.1.0: {} + rollup@4.59.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 + fsevents: 2.3.3 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -3439,6 +4287,8 @@ snapshots: source-map@0.6.1: {} + source-map@0.7.6: {} + spawndamnit@3.0.1: dependencies: cross-spawn: 7.0.6 @@ -3485,6 +4335,16 @@ snapshots: strip-json-comments@3.1.1: {} + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.15 + ts-interface-checker: 0.1.13 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -3505,13 +4365,32 @@ snapshots: glob: 10.5.0 minimatch: 10.2.2 + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tinyexec@0.3.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tmpl@1.0.5: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)))(typescript@5.9.3): + tree-kill@1.2.2: {} + + ts-interface-checker@0.1.13: {} + + ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.27.3)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.33)(ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3)))(typescript@5.9.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -3529,6 +4408,7 @@ snapshots: '@jest/transform': 30.2.0 '@jest/types': 30.2.0 babel-jest: 30.2.0(@babel/core@7.29.0) + esbuild: 0.27.3 jest-util: 30.2.0 ts-node@10.9.2(@types/node@20.19.33)(typescript@5.9.3): @@ -3552,6 +4432,33 @@ snapshots: tslib@2.8.1: optional: true + tsup@8.5.1(typescript@5.9.3): + dependencies: + bundle-require: 5.1.0(esbuild@0.27.3) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3 + esbuild: 0.27.3 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1 + resolve-from: 5.0.0 + rollup: 4.59.0 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + type-detect@4.0.8: {} type-fest@0.21.3: {} @@ -3560,6 +4467,8 @@ snapshots: typescript@5.9.3: {} + ufo@1.6.3: {} + uglify-js@3.19.3: optional: true @@ -3605,6 +4514,23 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 + viem@2.47.0(typescript@5.9.3): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.2.3(typescript@5.9.3) + isows: 1.0.7(ws@8.18.3) + ox: 0.14.0(typescript@5.9.3) + ws: 8.18.3 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + walker@1.0.8: dependencies: makeerror: 1.0.12 @@ -3632,6 +4558,8 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 + ws@8.18.3: {} + y18n@5.0.8: {} yallist@3.1.1: {}