diff --git a/lib/price.ts b/lib/price.ts index f63e10f7..865eb60d 100644 --- a/lib/price.ts +++ b/lib/price.ts @@ -61,11 +61,11 @@ export const mcv2BondAbi = [ type: "function", name: "getRoyaltyInfo", stateMutability: "view", - inputs: [{ name: "token", type: "address" }], - outputs: [ - { name: "royalty", type: "uint256" }, - { name: "royaltyBeneficiary", type: "address" }, + inputs: [ + { name: "token", type: "address" }, + { name: "beneficiary", type: "address" }, ], + outputs: [{ name: "unclaimed", type: "uint256" }], }, { type: "function", diff --git a/packages/cli/src/commands/claim.ts b/packages/cli/src/commands/claim.ts index 261079e8..7eeb6967 100644 --- a/packages/cli/src/commands/claim.ts +++ b/packages/cli/src/commands/claim.ts @@ -17,20 +17,20 @@ export function registerClaim(program: Command): void { const tokenAddress = opts.address as Address; const client = buildClient({ ipfs: false }); + // Fetch bond data (creator = beneficiary, reserve token for display) console.log("Checking royalties..."); - const info = await client.getRoyaltyInfo(tokenAddress); + const bond = await client.publicClient.readContract({ + address: MCV2_BOND_ADDRESS, + abi: mcv2BondAbi, + functionName: "tokenBond", + args: [tokenAddress], + }); + const creator = (bond as readonly unknown[])[0] as Address; + const reserveToken = (bond as readonly unknown[])[4] as Address; - // Fetch reserve token address via tokenBond(), then read its decimals let decimals = 18; let symbol = "TOKEN"; try { - const bond = await client.publicClient.readContract({ - address: MCV2_BOND_ADDRESS, - abi: mcv2BondAbi, - functionName: "tokenBond", - args: [tokenAddress], - }); - const reserveToken = (bond as readonly unknown[])[4] as Address; const [dec, sym] = await Promise.all([ client.publicClient.readContract({ address: reserveToken, @@ -49,9 +49,10 @@ export function registerClaim(program: Command): void { // Default to 18/TOKEN if calls fail } + const info = await client.getRoyaltyInfo(tokenAddress, creator); const formatted = formatUnits(info.unclaimed, decimals); console.log(` Unclaimed: ${formatted} ${symbol}`); - console.log(` Beneficiary: ${info.beneficiary}`); + console.log(` Beneficiary: ${creator}`); if (info.unclaimed === 0n) { console.log("No royalties to claim."); diff --git a/packages/cli/src/commands/status.ts b/packages/cli/src/commands/status.ts index 175c3f16..ae9a15e5 100644 --- a/packages/cli/src/commands/status.ts +++ b/packages/cli/src/commands/status.ts @@ -54,6 +54,7 @@ export function registerStatus(program: Command): void { // ----------------------------------------------------------------- let tokenSymbol = "TOKEN"; let tokenDecimals = 18; + let bondCreator: Address | null = null; try { const bond = await client.publicClient.readContract({ address: MCV2_BOND_ADDRESS, @@ -61,6 +62,7 @@ export function registerStatus(program: Command): void { functionName: "tokenBond", args: [info.tokenAddress], }); + bondCreator = (bond as readonly unknown[])[0] as Address; const reserveToken = (bond as readonly unknown[])[4] as Address; const [sym, dec] = await Promise.all([ client.publicClient.readContract({ @@ -90,8 +92,10 @@ export function registerStatus(program: Command): void { // ----------------------------------------------------------------- let unclaimedRoyalty: bigint | null = null; try { - const royalty = await client.getRoyaltyInfo(info.tokenAddress); - unclaimedRoyalty = royalty.unclaimed; + if (bondCreator) { + const royalty = await client.getRoyaltyInfo(info.tokenAddress, bondCreator); + unclaimedRoyalty = royalty.unclaimed; + } } catch { // Token may not have a bond yet } diff --git a/packages/sdk/src/abi.ts b/packages/sdk/src/abi.ts index f4b1b173..37475f2a 100644 --- a/packages/sdk/src/abi.ts +++ b/packages/sdk/src/abi.ts @@ -131,11 +131,11 @@ export const mcv2BondAbi = [ type: "function", name: "getRoyaltyInfo", stateMutability: "view", - inputs: [{ name: "token", type: "address" }], - outputs: [ - { name: "royalty", type: "uint256" }, - { name: "royaltyBeneficiary", type: "address" }, + inputs: [ + { name: "token", type: "address" }, + { name: "beneficiary", type: "address" }, ], + outputs: [{ name: "unclaimed", type: "uint256" }], }, { type: "function", diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts index 472589d7..8e1b8481 100644 --- a/packages/sdk/src/client.ts +++ b/packages/sdk/src/client.ts @@ -101,7 +101,6 @@ export interface SetAgentWalletResult { export interface RoyaltyInfo { unclaimed: bigint; - beneficiary: Address; } export interface TokenPriceInfo { @@ -495,20 +494,18 @@ export class PlotLink { * Get unclaimed royalty info for a storyline token. * * @param tokenAddress - The storyline's ERC-20 token address - * @returns Unclaimed royalty amount and beneficiary address + * @param beneficiary - The royalty beneficiary (usually the bond creator) + * @returns Unclaimed royalty amount */ - async getRoyaltyInfo(tokenAddress: Address): Promise { - const result = await this.publicClient.readContract({ + async getRoyaltyInfo(tokenAddress: Address, beneficiary: Address): Promise { + const unclaimed = await this.publicClient.readContract({ address: this.mcv2Bond, abi: mcv2BondAbi, functionName: "getRoyaltyInfo", - args: [tokenAddress], + args: [tokenAddress, beneficiary], }); - return { - unclaimed: (result as [bigint, Address])[0], - beneficiary: (result as [bigint, Address])[1], - }; + return { unclaimed: unclaimed as bigint }; } /** diff --git a/src/app/dashboard/writer/page.tsx b/src/app/dashboard/writer/page.tsx index 877bf66d..2e2a8c11 100644 --- a/src/app/dashboard/writer/page.tsx +++ b/src/app/dashboard/writer/page.tsx @@ -68,7 +68,7 @@ export default function WriterDashboard() {
{storylines.map((s) => ( - + ))} {!isLoading && !error && storylines.length === 0 && (

@@ -80,7 +80,7 @@ export default function WriterDashboard() { ); } -function StorylineDetail({ storyline }: { storyline: Storyline }) { +function StorylineDetail({ storyline, writerAddress }: { storyline: Storyline; writerAddress: Address }) { return (

@@ -139,6 +139,7 @@ function StorylineDetail({ storyline }: { storyline: Storyline }) { )} diff --git a/src/components/ClaimRoyalties.tsx b/src/components/ClaimRoyalties.tsx index 30d40382..0c1d78be 100644 --- a/src/components/ClaimRoyalties.tsx +++ b/src/components/ClaimRoyalties.tsx @@ -13,9 +13,10 @@ type TxState = "idle" | "confirming" | "pending" | "done" | "error"; interface ClaimRoyaltiesProps { tokenAddress: Address; plotCount: number; + beneficiary: Address; } -export function ClaimRoyalties({ tokenAddress, plotCount }: ClaimRoyaltiesProps) { +export function ClaimRoyalties({ tokenAddress, plotCount, beneficiary }: ClaimRoyaltiesProps) { const [txState, setTxState] = useState("idle"); const [error, setError] = useState(null); const [claimedAmount, setClaimedAmount] = useState(BigInt(0)); @@ -26,18 +27,15 @@ export function ClaimRoyalties({ tokenAddress, plotCount }: ClaimRoyaltiesProps) // Fetch unclaimed royalty balance const { data: royaltyInfo, refetch } = useQuery({ - queryKey: ["royalty-info", tokenAddress], + queryKey: ["royalty-info", tokenAddress, beneficiary], queryFn: async () => { - const result = await publicClient.readContract({ + const unclaimed = await publicClient.readContract({ address: MCV2_BOND, abi: mcv2BondAbi, functionName: "getRoyaltyInfo", - args: [tokenAddress], + args: [tokenAddress, beneficiary], }); - return { - unclaimed: result[0], - beneficiary: result[1] as Address, - }; + return { unclaimed }; }, refetchInterval: 30000, }); diff --git a/src/components/WriterTradingStats.tsx b/src/components/WriterTradingStats.tsx index f9859981..552e8fca 100644 --- a/src/components/WriterTradingStats.tsx +++ b/src/components/WriterTradingStats.tsx @@ -38,21 +38,36 @@ export function WriterTradingStats({ storyline }: WriterTradingStatsProps) { enabled: !!tokenAddress, }); - // Fetch unclaimed royalties - const { data: royaltyData } = useQuery({ - queryKey: ["writer-royalty", tokenAddress], + // Fetch bond creator (royalty beneficiary) + const { data: bondData } = useQuery({ + queryKey: ["writer-bond", tokenAddress], queryFn: async () => { const result = await publicClient.readContract({ address: MCV2_BOND, abi: mcv2BondAbi, - functionName: "getRoyaltyInfo", + functionName: "tokenBond", args: [tokenAddress], }); - return { unclaimed: result[0] }; + return { creator: result[0] as `0x${string}` }; }, enabled: !!tokenAddress, }); + // Fetch unclaimed royalties (requires creator address as beneficiary) + const { data: royaltyData } = useQuery({ + queryKey: ["writer-royalty", tokenAddress, bondData?.creator], + queryFn: async () => { + const unclaimed = await publicClient.readContract({ + address: MCV2_BOND, + abi: mcv2BondAbi, + functionName: "getRoyaltyInfo", + args: [tokenAddress, bondData!.creator], + }); + return { unclaimed }; + }, + enabled: !!tokenAddress && !!bondData?.creator, + }); + // Fetch total donations for this storyline const { data: donationsTotal } = useQuery({ queryKey: ["writer-donations", storyline.storyline_id],