From 1bda86ee5f96c4eda0696eb086ce13f5d9cf9116 Mon Sep 17 00:00:00 2001 From: Danny Delott Date: Mon, 10 Feb 2025 09:03:11 -0800 Subject: [PATCH 1/2] Add merklDistributionAbi --- .../src/ui/rewards/merklDistributorAbi.ts | 490 ++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 apps/hyperdrive-trading/src/ui/rewards/merklDistributorAbi.ts diff --git a/apps/hyperdrive-trading/src/ui/rewards/merklDistributorAbi.ts b/apps/hyperdrive-trading/src/ui/rewards/merklDistributorAbi.ts new file mode 100644 index 000000000..21103bfbc --- /dev/null +++ b/apps/hyperdrive-trading/src/ui/rewards/merklDistributorAbi.ts @@ -0,0 +1,490 @@ +// Abi for the Merkl Distributor contract: https://app.merkl.xyz/status + +export const MerklDistributorAbi = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { inputs: [], name: "InvalidDispute", type: "error" }, + { inputs: [], name: "InvalidLengths", type: "error" }, + { inputs: [], name: "InvalidProof", type: "error" }, + { inputs: [], name: "InvalidUninitializedRoot", type: "error" }, + { inputs: [], name: "NoDispute", type: "error" }, + { inputs: [], name: "NotGovernor", type: "error" }, + { inputs: [], name: "NotTrusted", type: "error" }, + { inputs: [], name: "NotWhitelisted", type: "error" }, + { inputs: [], name: "UnresolvedDispute", type: "error" }, + { inputs: [], name: "ZeroAddress", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "previousAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "AdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "beacon", + type: "address", + }, + ], + name: "BeaconUpgraded", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { + indexed: true, + internalType: "address", + name: "token", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Claimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "_disputeAmount", + type: "uint256", + }, + ], + name: "DisputeAmountUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint48", + name: "_disputePeriod", + type: "uint48", + }, + ], + name: "DisputePeriodUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "bool", name: "valid", type: "bool" }, + ], + name: "DisputeResolved", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "_disputeToken", + type: "address", + }, + ], + name: "DisputeTokenUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "Disputed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint8", name: "version", type: "uint8" }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { indexed: false, internalType: "bool", name: "isEnabled", type: "bool" }, + ], + name: "OperatorClaimingToggled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "isWhitelisted", + type: "bool", + }, + ], + name: "OperatorToggled", + 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", + }, + ], + name: "Recovered", + type: "event", + }, + { anonymous: false, inputs: [], name: "Revoked", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "bytes32", + name: "merkleRoot", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes32", + name: "ipfsHash", + type: "bytes32", + }, + { + indexed: false, + internalType: "uint48", + name: "endOfDisputePeriod", + type: "uint48", + }, + ], + name: "TreeUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "eoa", type: "address" }, + { indexed: false, internalType: "bool", name: "trust", type: "bool" }, + ], + name: "TrustedToggled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "implementation", + type: "address", + }, + ], + name: "Upgraded", + type: "event", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "canUpdateMerkleRoot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "users", type: "address[]" }, + { internalType: "address[]", name: "tokens", type: "address[]" }, + { internalType: "uint256[]", name: "amounts", type: "uint256[]" }, + { internalType: "bytes32[][]", name: "proofs", type: "bytes32[][]" }, + ], + name: "claim", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + ], + name: "claimed", + outputs: [ + { internalType: "uint208", name: "amount", type: "uint208" }, + { internalType: "uint48", name: "timestamp", type: "uint48" }, + { internalType: "bytes32", name: "merkleRoot", type: "bytes32" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "core", + outputs: [{ internalType: "contract ICore", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "disputeAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "disputePeriod", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "disputeToken", + outputs: [{ internalType: "contract IERC20", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "string", name: "reason", type: "string" }], + name: "disputeTree", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "disputer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "endOfDisputePeriod", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getMerkleRoot", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "contract ICore", name: "_core", type: "address" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "lastTree", + outputs: [ + { internalType: "bytes32", name: "merkleRoot", type: "bytes32" }, + { internalType: "bytes32", name: "ipfsHash", type: "bytes32" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "onlyOperatorCanClaim", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + ], + name: "operators", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proxiableUUID", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "tokenAddress", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amountToRecover", type: "uint256" }, + ], + name: "recoverERC20", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bool", name: "valid", type: "bool" }], + name: "resolveDispute", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "revokeTree", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "_disputeAmount", type: "uint256" }, + ], + name: "setDisputeAmount", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint48", name: "_disputePeriod", type: "uint48" }, + ], + name: "setDisputePeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC20", + name: "_disputeToken", + type: "address", + }, + ], + name: "setDisputeToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "user", type: "address" }], + name: "toggleOnlyOperatorCanClaim", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "user", type: "address" }, + { internalType: "address", name: "operator", type: "address" }, + ], + name: "toggleOperator", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "eoa", type: "address" }], + name: "toggleTrusted", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "tree", + outputs: [ + { internalType: "bytes32", name: "merkleRoot", type: "bytes32" }, + { internalType: "bytes32", name: "ipfsHash", type: "bytes32" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "bytes32", name: "merkleRoot", type: "bytes32" }, + { internalType: "bytes32", name: "ipfsHash", type: "bytes32" }, + ], + internalType: "struct MerkleTree", + name: "_tree", + type: "tuple", + }, + ], + name: "updateTree", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newImplementation", type: "address" }, + ], + name: "upgradeTo", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newImplementation", type: "address" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "upgradeToAndCall", + outputs: [], + stateMutability: "payable", + type: "function", + }, +] as const; From 31d74e936e64503fc898c9c5c9b241d265ab1309 Mon Sep 17 00:00:00 2001 From: Danny Delott Date: Mon, 10 Feb 2025 09:03:46 -0800 Subject: [PATCH 2/2] Handle case when no merkleProof exists yet --- .../src/ui/portfolio/rewards/RewardsTableDesktop.tsx | 4 ++-- yarn.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx b/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx index dcef74736..f62c8681a 100644 --- a/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx +++ b/apps/hyperdrive-trading/src/ui/portfolio/rewards/RewardsTableDesktop.tsx @@ -266,8 +266,8 @@ function ClaimRewardsButton({ ); } - // If the reward is already claimed, disable the button - if (BigInt(reward.claimableAmount) === claimed) { + // If the reward is already claimed, or no merkle exists yet, disable the button + if (BigInt(reward.claimableAmount) === claimed || !reward.merkleProof) { return (