From 1f95062e31a82a818c5f061943ba418d31a12102 Mon Sep 17 00:00:00 2001 From: yu23ki14 Date: Tue, 30 Sep 2025 23:51:58 +0900 Subject: [PATCH] add message data --- .../contracts/thankstoken/IThanksToken.sol | 15 ++- .../contracts/thankstoken/ThanksToken.sol | 10 +- pkgs/contract/scripts/deploy/thankstoken.ts | 60 ++++++++++ pkgs/contract/test/IntegrationTest.ts | 1 + pkgs/contract/test/SplitsCreator.ts | 4 +- pkgs/contract/test/ThanksToken.ts | 12 +- pkgs/frontend/abi/thankstoken.ts | 16 +++ .../assistcredit/AmountSelector.tsx | 27 ++++- .../assistcredit/SendConfirmation.tsx | 105 +++++++++--------- .../app/components/thankstoken/History.tsx | 11 +- .../app/routes/$treeId_.thankstoken.send.tsx | 11 +- pkgs/frontend/codegen.ts | 2 +- pkgs/frontend/gql/gql.ts | 4 +- pkgs/frontend/gql/graphql.ts | 32 +++++- pkgs/frontend/hooks/useThanksToken.ts | 13 ++- pkgs/subgraph/abis/ThanksToken.json | 70 +++++++++--- pkgs/subgraph/config/base.json | 4 +- pkgs/subgraph/config/sepolia.json | 2 +- pkgs/subgraph/schema.graphql | 31 +----- pkgs/subgraph/src/thanksTokenMapping.ts | 1 + 20 files changed, 303 insertions(+), 128 deletions(-) create mode 100644 pkgs/contract/scripts/deploy/thankstoken.ts diff --git a/pkgs/contract/contracts/thankstoken/IThanksToken.sol b/pkgs/contract/contracts/thankstoken/IThanksToken.sol index 2db86f3..6118e02 100644 --- a/pkgs/contract/contracts/thankstoken/IThanksToken.sol +++ b/pkgs/contract/contracts/thankstoken/IThanksToken.sol @@ -18,12 +18,14 @@ interface IThanksToken is IERC20 { * @param to The address to mint tokens to * @param amount The amount of tokens to mint * @param relatedRoles Array of roles related to the sender + * @param data Additional data with no specified format * @return success Whether the operation was successful */ function mint( address to, uint256 amount, - RelatedRole[] memory relatedRoles + RelatedRole[] memory relatedRoles, + bytes memory data ) external returns (bool); /** @@ -31,12 +33,14 @@ interface IThanksToken is IERC20 { * @param to Array of addresses to mint tokens to * @param amounts Array of amounts of tokens to mint * @param relatedRoles Array of roles related to the sender + * @param data Additional data with no specified format * @return success Whether the operation was successful */ function batchMint( address[] memory to, uint256[] memory amounts, - RelatedRole[] memory relatedRoles + RelatedRole[] memory relatedRoles, + bytes memory data ) external returns (bool); /** @@ -81,5 +85,10 @@ interface IThanksToken is IERC20 { * @param to The recipient of the minted tokens * @param amount The amount of tokens minted */ - event TokenMinted(address indexed from, address indexed to, uint256 amount); + event TokenMinted( + address indexed from, + address indexed to, + uint256 amount, + bytes data + ); } diff --git a/pkgs/contract/contracts/thankstoken/ThanksToken.sol b/pkgs/contract/contracts/thankstoken/ThanksToken.sol index b9b5b32..dc5ddaf 100644 --- a/pkgs/contract/contracts/thankstoken/ThanksToken.sol +++ b/pkgs/contract/contracts/thankstoken/ThanksToken.sol @@ -108,7 +108,8 @@ contract ThanksToken is Clone, ERC20("", ""), IThanksToken { function mint( address to, uint256 amount, - RelatedRole[] memory relatedRoles + RelatedRole[] memory relatedRoles, + bytes memory data ) public override returns (bool) { require(to != msg.sender, "Cannot mint to yourself"); require(amount > 0, "Amount must be greater than 0"); @@ -131,7 +132,7 @@ contract ThanksToken is Clone, ERC20("", ""), IThanksToken { _isParticipant[to] = true; } - emit TokenMinted(msg.sender, to, amount); + emit TokenMinted(msg.sender, to, amount, data); return true; } @@ -139,7 +140,8 @@ contract ThanksToken is Clone, ERC20("", ""), IThanksToken { function batchMint( address[] memory to, uint256[] memory amounts, - RelatedRole[] memory relatedRoles + RelatedRole[] memory relatedRoles, + bytes memory data ) public override returns (bool) { require(to.length == amounts.length, "Arrays length mismatch"); @@ -165,7 +167,7 @@ contract ThanksToken is Clone, ERC20("", ""), IThanksToken { _isParticipant[to[i]] = true; } - emit TokenMinted(msg.sender, to[i], amounts[i]); + emit TokenMinted(msg.sender, to[i], amounts[i], data); } if (!_isParticipant[msg.sender]) { diff --git a/pkgs/contract/scripts/deploy/thankstoken.ts b/pkgs/contract/scripts/deploy/thankstoken.ts new file mode 100644 index 0000000..3e0f2b8 --- /dev/null +++ b/pkgs/contract/scripts/deploy/thankstoken.ts @@ -0,0 +1,60 @@ +import { ethers, network } from "hardhat"; +import type { Address } from "viem"; +import { + deployThanksToken, + deployThanksTokenFactory, +} from "../../helpers/deploy/ThanksToken"; + +const deploy = async () => { + console.log( + "##################################### [Create2 Deploy START] #####################################", + ); + + const [deployerSigner] = await ethers.getSigners(); + const deployerAddress = await deployerSigner.getAddress(); + + console.log("Deploying ThanksToken..."); + const { ThanksToken } = await deployThanksToken(); + const thanksTokenAddress = ThanksToken.address; + + console.log("Deploying ThanksTokenFactory..."); + + const { + ThanksTokenFactory, + ThanksTokenFactoryImplAddress, + ThanksTokenFactoryInitData, + } = await deployThanksTokenFactory({ + initialOwner: deployerAddress as Address, + implementation: thanksTokenAddress, + hatsAddress: process.env.HATS_ADDRESS as Address, + }); + const thanksTokenFactoryAddress = ThanksTokenFactory.address; + + // Set bigbang address to thanks token factory + const ThanksTokenFactoryContract = await ethers.getContractAt( + "ThanksTokenFactory", + thanksTokenFactoryAddress, + ); + await ThanksTokenFactoryContract.setBigBang( + "0xfB4FA9Dbb82a36566154A038e5f3865fbAC92422", + ); + + console.log("Successfully deployed contracts!πŸŽ‰"); + console.log("Verify contract with these commands...\n"); + + console.log( + "ThanksToken:\n", + `pnpm contract hardhat verify ${thanksTokenAddress} --network ${network.name}\n`, + ); + console.log( + "ThanksTokenFactory:\n", + `pnpm contract hardhat verify ${ThanksTokenFactoryImplAddress} --network ${network.name} &&`, + `pnpm contract hardhat verify ${thanksTokenFactoryAddress} ${ThanksTokenFactoryImplAddress} ${ThanksTokenFactoryInitData} --network ${network.name}\n`, + ); + + console.log( + "\n##################################### [Create2 Deploy END] #####################################", + ); +}; + +deploy(); diff --git a/pkgs/contract/test/IntegrationTest.ts b/pkgs/contract/test/IntegrationTest.ts index 0072f52..0609f90 100644 --- a/pkgs/contract/test/IntegrationTest.ts +++ b/pkgs/contract/test/IntegrationTest.ts @@ -436,6 +436,7 @@ describe("IntegrationTest", () => { wearer: address1.account?.address!, }, ], + "0x", ], { account: address1.account }, ); diff --git a/pkgs/contract/test/SplitsCreator.ts b/pkgs/contract/test/SplitsCreator.ts index 50908ea..2b805f8 100644 --- a/pkgs/contract/test/SplitsCreator.ts +++ b/pkgs/contract/test/SplitsCreator.ts @@ -1938,7 +1938,7 @@ describe("CreateSplit with thanks token weight", () => { expect(Number(mintableAmount1)).to.be.greaterThan(0); await ThanksToken.write.mint( - [address2.account?.address!, mintableAmount1 / 2n, relatedRoles1], + [address2.account?.address!, mintableAmount1 / 2n, relatedRoles1, "0x"], { account: address1.account }, ); @@ -1951,7 +1951,7 @@ describe("CreateSplit with thanks token weight", () => { expect(Number(mintableAmount2)).to.be.greaterThan(0); await ThanksToken.write.mint( - [address3.account?.address!, mintableAmount2 / 2n, relatedRoles2], + [address3.account?.address!, mintableAmount2 / 2n, relatedRoles2, "0x"], { account: address2.account }, ); diff --git a/pkgs/contract/test/ThanksToken.ts b/pkgs/contract/test/ThanksToken.ts index 6d60276..d61795b 100644 --- a/pkgs/contract/test/ThanksToken.ts +++ b/pkgs/contract/test/ThanksToken.ts @@ -397,7 +397,7 @@ describe("ThanksToken", () => { expect(Number(mintableAmount)).to.be.equal(600000000000000000000); await DeployedThanksToken.write.mint( - [address2Validated, mintableAmount / 2n, relatedRoles], + [address2Validated, mintableAmount / 2n, relatedRoles, "0x"], { account: address1.account, }, @@ -542,7 +542,7 @@ describe("ThanksToken", () => { try { await DeployedThanksToken.write.mint( - [address2Validated, amountToMint, relatedRoles], + [address2Validated, amountToMint, relatedRoles, "0x"], { account: address1.account }, ); } catch (error: any) { @@ -678,7 +678,7 @@ describe("ThanksToken", () => { try { await DeployedThanksToken.write.mint( - [address1Validated, 1n, relatedRoles], + [address1Validated, 1n, relatedRoles, "0x"], { account: address1.account }, ); // If we get here, the mint succeeded when it should have failed @@ -697,7 +697,7 @@ describe("ThanksToken", () => { ]; try { await DeployedThanksToken.write.mint( - [address2Validated, 1000000n, relatedRoles], + [address2Validated, 1000000n, relatedRoles, "0x"], { account: address1.account }, ); // If we get here, the mint succeeded when it should have failed @@ -735,7 +735,7 @@ describe("ThanksToken", () => { // Mint from address1 to address3, who is a new participant await DeployedThanksToken.write.mint( - [address3Validated, mintableAmount, relatedRoles], + [address3Validated, mintableAmount, relatedRoles, "0x"], { account: address1.account }, ); @@ -757,7 +757,7 @@ describe("ThanksToken", () => { expect(mintableAmount2 > 0n).to.be.true; await DeployedThanksToken.write.mint( - [address2Validated, mintableAmount2, relatedRoles], + [address2Validated, mintableAmount2, relatedRoles, "0x"], { account: address1.account }, ); diff --git a/pkgs/frontend/abi/thankstoken.ts b/pkgs/frontend/abi/thankstoken.ts index e05a663..88ff680 100644 --- a/pkgs/frontend/abi/thankstoken.ts +++ b/pkgs/frontend/abi/thankstoken.ts @@ -131,6 +131,12 @@ export const THANKS_TOKEN_ABI = [ name: "amount", type: "uint256", }, + { + indexed: false, + internalType: "bytes", + name: "data", + type: "bytes", + }, ], name: "TokenMinted", type: "event", @@ -353,6 +359,11 @@ export const THANKS_TOKEN_ABI = [ name: "relatedRoles", type: "tuple[]", }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, ], name: "batchMint", outputs: [ @@ -433,6 +444,11 @@ export const THANKS_TOKEN_ABI = [ name: "relatedRoles", type: "tuple[]", }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, ], name: "mint", outputs: [ diff --git a/pkgs/frontend/app/components/assistcredit/AmountSelector.tsx b/pkgs/frontend/app/components/assistcredit/AmountSelector.tsx index 59ab89b..527af4e 100644 --- a/pkgs/frontend/app/components/assistcredit/AmountSelector.tsx +++ b/pkgs/frontend/app/components/assistcredit/AmountSelector.tsx @@ -1,4 +1,12 @@ -import { Box, Flex, HStack, Stack, Text, VStack } from "@chakra-ui/react"; +import { + Box, + Flex, + HStack, + Stack, + Text, + Textarea, + VStack, +} from "@chakra-ui/react"; import { Slider, useSlider } from "@chakra-ui/react/slider"; import type { NameData } from "namestone-sdk"; import { useEffect, useState } from "react"; @@ -24,6 +32,8 @@ const getNearestEmoji = (amount: number): number => { interface AmountSelectorProps { amount: number; setAmount: (amount: number) => void; + data?: string; + setData?: (data: string) => void; onNext: () => void; isLoading: boolean; me?: NameData; @@ -36,6 +46,8 @@ interface AmountSelectorProps { const AmountSelector = ({ amount, setAmount, + data, + setData, onNext, isLoading, me, @@ -166,6 +178,19 @@ const AmountSelector = ({ + + {setData && ( + +