diff --git a/pkgs/cli/src/abi/splits.ts b/pkgs/cli/src/abi/splits.ts new file mode 100644 index 0000000..30233a0 --- /dev/null +++ b/pkgs/cli/src/abi/splits.ts @@ -0,0 +1,108 @@ +export const SPLITS_ABI = [ + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "split", + type: "address", + }, + ], + name: "SplitsCreated", + type: "event", + }, + { + inputs: [], + name: "FRACTION_TOKEN", + outputs: [ + { + internalType: "contract IFractionToken", + name: "", + type: "address", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "HATS_TIME_FRAME_MODULE", + outputs: [ + { + internalType: "contract IHatsTimeFrameModule", + name: "", + type: "address", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "SPLIT_FACTORY_V2", + outputs: [ + { + internalType: "contract ISplitFactoryV2", + name: "", + type: "address", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "TRUSTED_FORWARDER", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + components: [ + { + internalType: "uint256", + name: "hatId", + type: "uint256", + }, + { + internalType: "uint256", + name: "multiplierBottom", + type: "uint256", + }, + { + internalType: "uint256", + name: "multiplierTop", + type: "uint256", + }, + { + internalType: "address[]", + name: "wearers", + type: "address[]", + }, + ], + internalType: "struct ISplitsCreator.SplitsInfo[]", + name: "_splitsInfo", + type: "tuple[]", + }, + ], + name: "create", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/pkgs/cli/src/commands/splits.ts b/pkgs/cli/src/commands/splits.ts new file mode 100644 index 0000000..40662dc --- /dev/null +++ b/pkgs/cli/src/commands/splits.ts @@ -0,0 +1,79 @@ +import { Command } from "commander"; +import { create } from "../modules/splits"; +import { getAccount } from "../services/wallet"; +import { rootProgram } from ".."; +import { Address } from "viem"; + +export const splitsCommands = new Command(); + +// ############################################################### +// CLI init setup +// ############################################################### + +splitsCommands + .name("splits") + .description("This is a CLI splits for toban project") + .version("1.0.0"); + +// ############################################################### +// command setUp +// ############################################################### + +/** + * スプリットを作成 + */ +splitsCommands + .command("create") + .description("Create Splits") + .requiredOption("-splits, --splitsAddress ", "Splits Address") + .requiredOption( + "-hid, --hatId ", + "Hat ID", + (value, previous: string[]) => + previous ? previous.concat([value]) : [value], + [] + ) + .requiredOption( + "-mb, --multiplierBottom ", + "Multiplier Bottom", + (value, previous: string[]) => + previous ? previous.concat([value]) : [value], + [] + ) + .requiredOption( + "-mt, --multiplierTop ", + "Multiplier Top", + (value, previous: string[]) => + previous ? previous.concat([value]) : [value], + [] + ) + .requiredOption( + "-w, --wearers ", + "Wearers (comma-separated addresses)", + (value: string, previous: Address[][]) => { + const addresses = value + .split(",") + .map((addr: string) => addr.trim() as Address); + return previous ? [...previous, addresses] : [addresses]; + }, + [] + ) + .action( + async ({ + splitsAddress, + hatId, + multiplierBottom, + multiplierTop, + wearers, + }) => { + const splitsData = hatId.map((id: string, index: number) => ({ + hatId: BigInt(id), + multiplierBottom: BigInt(multiplierBottom[index]), + multiplierTop: BigInt(multiplierTop[index]), + wearers: wearers[index], + })); + + const hash = await create(splitsAddress, splitsData); + console.log("Transaction Hash:", hash); + } + ); diff --git a/pkgs/cli/src/index.ts b/pkgs/cli/src/index.ts index 034fdd3..e79ff41 100755 --- a/pkgs/cli/src/index.ts +++ b/pkgs/cli/src/index.ts @@ -3,6 +3,7 @@ import { Command } from "commander"; import { hatsCommands } from "./commands/hats"; import { walletCommands } from "./commands/wallet"; +import { splitsCommands } from "./commands/splits"; import { PublicClient, WalletClient } from "viem"; import { getPublicClient } from "./modules/viem"; import { getWalletClient } from "./services/wallet"; @@ -35,6 +36,7 @@ rootProgram rootProgram.addCommand(bigbangCommands); rootProgram.addCommand(hatsCommands); rootProgram.addCommand(walletCommands); +rootProgram.addCommand(splitsCommands); rootProgram.addCommand(pinataCommands); rootProgram.addCommand(fractionTokenCommands); diff --git a/pkgs/cli/src/modules/bigbang.ts b/pkgs/cli/src/modules/bigbang.ts index 7537f66..79b6a9e 100644 --- a/pkgs/cli/src/modules/bigbang.ts +++ b/pkgs/cli/src/modules/bigbang.ts @@ -6,6 +6,7 @@ import { Address, decodeEventLog } from "viem"; import { publicClient, walletClient } from ".."; import { bigbangContractBaseConfig } from "../config"; import { startLoading } from "../services/loading"; +import { hatIdToTreeId } from "@hatsprotocol/sdk-v1-core"; /** * プロジェクト作成 @@ -53,13 +54,20 @@ export const bigbang = async (params: { stop(); - console.log( - decodeEventLog({ + if (log) { + const decodedLog = decodeEventLog({ abi: bigbangContractBaseConfig.abi, data: log.data, topics: log.topics, - }) - ); + }); + console.log(decodedLog); + console.log( + "Tree Link:", + `https://app.hatsprotocol.xyz/trees/${String( + publicClient.chain?.id + )}/${hatIdToTreeId(BigInt(decodedLog.args.topHatId))}` + ); + } return transactionHash; }; diff --git a/pkgs/cli/src/modules/fractiontoken.ts b/pkgs/cli/src/modules/fractiontoken.ts index ef5ae5f..bec6ff1 100644 --- a/pkgs/cli/src/modules/fractiontoken.ts +++ b/pkgs/cli/src/modules/fractiontoken.ts @@ -56,13 +56,15 @@ export const sendFractionToken = async ( stop(); - console.log( - decodeEventLog({ - abi: fractionTokenBaseConfig.abi, - data: log!.data, - topics: log!.topics, - }) - ); + if (log) { + console.log( + decodeEventLog({ + abi: fractionTokenBaseConfig.abi, + data: log!.data, + topics: log!.topics, + }) + ); + } return transactionHash; }; diff --git a/pkgs/cli/src/modules/splits.ts b/pkgs/cli/src/modules/splits.ts new file mode 100644 index 0000000..04df951 --- /dev/null +++ b/pkgs/cli/src/modules/splits.ts @@ -0,0 +1,61 @@ +import { Address, decodeEventLog } from "viem"; +import { publicClient, walletClient } from ".."; +import { SPLITS_ABI } from "../abi/splits"; +import { startLoading } from "../services/loading"; + +type SplitsInfo = { + hatId: bigint; + multiplierBottom: bigint; + multiplierTop: bigint; + wearers: Address[]; +}; + +/** + * Splitsを作成 + */ +export const create = async (splitsAddress: Address, args: SplitsInfo[]) => { + const stop = startLoading(); + const { request } = await publicClient.simulateContract({ + address: splitsAddress, + abi: SPLITS_ABI, + account: walletClient.account, + functionName: "create", + args: [args], + }); + + const hash = await walletClient.writeContract(request); + + const receipt = await publicClient.waitForTransactionReceipt({ + hash, + }); + + const log = receipt.logs.find((log) => { + try { + const decodedLog = decodeEventLog({ + abi: SPLITS_ABI, + data: log.data, + topics: log.topics, + }); + return decodedLog.eventName === "SplitsCreated"; + } catch (error) {} + }); + + stop(); + + if (log) { + const decodedLog = decodeEventLog({ + abi: SPLITS_ABI, + data: log.data, + topics: log.topics, + }); + console.log(decodedLog); + console.log( + "Split Link:", + `https://app.splits.org/accounts/${ + decodedLog.args.split + }/?chainId=${String(publicClient.chain?.id)}` + ); + } + + return hash; +}; diff --git a/yarn.lock b/yarn.lock index efa562f..5a4538a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5504,7 +5504,7 @@ streamsearch@^1.1.0: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5521,15 +5521,6 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -5615,7 +5606,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5629,13 +5620,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -6174,16 +6158,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==