@zoralabs/comments-contracts 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +49 -31
- package/README.md +10 -39
- package/abis/AddDelegateCommenterRole.json +9 -0
- package/abis/CallerAndCommenter.json +62 -0
- package/abis/CallerAndCommenterImpl.json +1218 -0
- package/abis/CallerAndCommenterMintAndCommentTest.json +771 -0
- package/abis/CallerAndCommenterSwapAndCommentTest.json +844 -0
- package/abis/CallerAndCommenterTestBase.json +577 -0
- package/abis/CommentsImpl.json +189 -59
- package/abis/CommentsImplConstants.json +106 -0
- package/abis/CommentsPermitTest.json +26 -6
- package/abis/CommentsTest.json +58 -10
- package/abis/Comments_mintAndCommentTest.json +11 -4
- package/abis/Comments_smartWallet.json +711 -0
- package/abis/DeployCallerAndCommenterImpl.json +9 -0
- package/abis/DeployImpl.json +0 -13
- package/abis/DeployNonDeterministic.json +0 -13
- package/abis/DeployScript.json +0 -13
- package/abis/EIP712Upgradeable.json +74 -0
- package/abis/EIP712UpgradeableWithChainId.json +49 -0
- package/abis/ERC20.json +310 -0
- package/abis/GenerateDeterministicParams.json +0 -13
- package/abis/ICallerAndCommenter.json +797 -0
- package/abis/IComments.json +629 -9
- package/abis/IERC20.json +39 -42
- package/abis/IERC20Metadata.json +224 -0
- package/abis/{CommentsDeployerBase.json → IMultiOwnable.json} +8 -2
- package/abis/IProtocolRewards.json +19 -0
- package/abis/ISecondarySwap.json +45 -0
- package/abis/IZoraCreator1155.json +51 -0
- package/abis/IZoraTimedSaleStrategy.json +91 -0
- package/abis/Mock1155.json +75 -1
- package/abis/Mock1155NoCreatorRewardRecipient.json +605 -0
- package/abis/Mock1155NoOwner.json +566 -0
- package/abis/{MockMinter.json → MockDelegateCommenter.json} +12 -2
- package/abis/MockERC20z.json +315 -0
- package/abis/MockMultiOwnable.json +212 -0
- package/abis/MockSecondarySwap.json +95 -0
- package/abis/MockZoraTimedSale.json +139 -0
- package/abis/Ownable2StepUpgradeable.json +138 -0
- package/abis/UnorderedNoncesUpgradeable.json +4 -4
- package/addresses/1.json +9 -0
- package/addresses/10.json +9 -0
- package/addresses/11155111.json +9 -0
- package/addresses/11155420.json +9 -0
- package/addresses/42161.json +9 -0
- package/addresses/7777777.json +9 -0
- package/addresses/81457.json +9 -0
- package/addresses/8453.json +9 -0
- package/addresses/84532.json +9 -0
- package/addresses/999999999.json +7 -2
- package/deterministicConfig/callerAndCommenter.json +8 -0
- package/deterministicConfig/comments.json +2 -2
- package/dist/index.cjs +724 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +723 -35
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/wagmiGenerated.d.ts +1102 -57
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/package/types.ts +4 -1
- package/package/wagmiGenerated.ts +728 -32
- package/package.json +12 -11
- package/script/AddDelegateCommenterRole.s.sol +24 -0
- package/script/CommentsDeployerBase.sol +102 -19
- package/script/Deploy.s.sol +2 -44
- package/script/DeployCallerAndCommenterImpl.s.sol +29 -0
- package/script/DeployImpl.s.sol +1 -0
- package/script/DeployNonDeterministic.s.sol +22 -13
- package/script/GenerateDeterministicParams.s.sol +32 -4
- package/scripts/generateCommentsTestData.ts +170 -79
- package/src/CommentsImpl.sol +267 -134
- package/src/CommentsImplConstants.sol +44 -0
- package/src/interfaces/ICallerAndCommenter.sol +215 -0
- package/src/interfaces/IComments.sol +189 -42
- package/src/interfaces/IMultiOwnable.sol +10 -0
- package/src/interfaces/ISecondarySwap.sol +40 -0
- package/src/interfaces/IZoraCreator1155.sol +6 -1
- package/src/interfaces/IZoraCreator1155TypesV1.sol +46 -0
- package/src/interfaces/IZoraTimedSaleStrategy.sol +25 -0
- package/src/proxy/CallerAndCommenter.sol +43 -0
- package/src/utils/CallerAndCommenterImpl.sol +376 -0
- package/src/utils/EIP712UpgradeableWithChainId.sol +12 -23
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/CallerAndCommenterTestBase.sol +77 -0
- package/test/CallerAndCommenter_mintAndComment.t copy.sol +214 -0
- package/test/CallerAndCommenter_swapAndComment.t.sol +523 -0
- package/test/Comments.t.sol +166 -29
- package/test/CommentsTestBase.sol +12 -20
- package/test/Comments_delegateComment.t.sol +129 -0
- package/test/Comments_permit.t.sol +131 -44
- package/test/Comments_smartWallet.t.sol +152 -0
- package/test/mocks/Mock1155.sol +12 -1
- package/test/mocks/Mock1155NoCreatorRewardRecipient.sol +65 -0
- package/test/mocks/Mock1155NoOwner.sol +53 -0
- package/test/mocks/MockDelegateCommenter.sol +36 -0
- package/test/mocks/MockIZoraCreator1155.sol +16 -0
- package/test/mocks/MockSecondarySwap.sol +30 -0
- package/test/mocks/MockZoraTimedSale.sol +38 -0
- package/wagmi.config.ts +3 -1
- package/abis/ProxyDeployerScript.json +0 -15
- package/scripts/backfillComments.ts +0 -176
- package/scripts/queries.ts +0 -73
- package/scripts/queryAndSaveComments.ts +0 -48
- package/scripts/queryQuantityOfComments.ts +0 -53
- package/scripts/writeComments.ts +0 -198
- package/src/deployments/CommentsDeployment.sol +0 -14
- package/test/Comments_mintAndComment.t.sol +0 -101
- package/test/mocks/MockMinter.sol +0 -29
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
import {IComments} from "../../src/interfaces/IComments.sol";
|
|
5
|
+
import {Mock1155} from "./Mock1155.sol";
|
|
6
|
+
|
|
7
|
+
contract MockDelegateCommenter {
|
|
8
|
+
IComments immutable comments;
|
|
9
|
+
uint256 MINT_FEE = 0.000111 ether;
|
|
10
|
+
uint256 constant SPARKS_VALUE = 0.000001 ether;
|
|
11
|
+
|
|
12
|
+
constructor(address _comments) {
|
|
13
|
+
comments = IComments(_comments);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
IComments.CommentIdentifier emptyCommentIdentifier;
|
|
17
|
+
|
|
18
|
+
function forwardComment(address collection, uint256 tokenId, string calldata comment) external {
|
|
19
|
+
comments.delegateComment(msg.sender, collection, tokenId, comment, emptyCommentIdentifier, address(0), address(0));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function mintAndCommentWithSpark(
|
|
23
|
+
uint256 quantity,
|
|
24
|
+
address collection,
|
|
25
|
+
uint256 tokenId,
|
|
26
|
+
string calldata comment,
|
|
27
|
+
address referrer,
|
|
28
|
+
uint256 sparksQuantity
|
|
29
|
+
) external payable {
|
|
30
|
+
require(msg.value == SPARKS_VALUE * sparksQuantity + MINT_FEE * quantity, "Invalid value");
|
|
31
|
+
Mock1155(collection).mint(msg.sender, tokenId, quantity, "");
|
|
32
|
+
|
|
33
|
+
// get sparks value to send to comments contract
|
|
34
|
+
comments.delegateComment{value: SPARKS_VALUE * sparksQuantity}(msg.sender, collection, tokenId, comment, emptyCommentIdentifier, address(0), referrer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.23;
|
|
3
|
+
|
|
4
|
+
import {IERC1155} from "@openzeppelin/contracts/interfaces/IERC1155.sol";
|
|
5
|
+
import {IZoraCreator1155TypesV1} from "../../src/interfaces/IZoraCreator1155TypesV1.sol";
|
|
6
|
+
|
|
7
|
+
// For testing without getCreatorRewardRecipient
|
|
8
|
+
interface IZoraCreator1155 is IERC1155, IZoraCreator1155TypesV1 {
|
|
9
|
+
function isAdminOrRole(address user, uint256 tokenId, uint256 role) external view returns (bool);
|
|
10
|
+
|
|
11
|
+
function supportsInterface(bytes4 interfaceId) external view returns (bool);
|
|
12
|
+
|
|
13
|
+
function config() external view returns (address owner, uint96 __gap1, address payable fundsRecipient, uint96 __gap2, address transferHook, uint96 __gap3);
|
|
14
|
+
|
|
15
|
+
function setFundsRecipient(address payable fundsRecipient) external;
|
|
16
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import {ISecondarySwap} from "../../src/interfaces/ISecondarySwap.sol";
|
|
5
|
+
import {Mock1155} from "./Mock1155.sol";
|
|
6
|
+
import {MockZoraTimedSale} from "./MockZoraTimedSale.sol";
|
|
7
|
+
import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol";
|
|
8
|
+
|
|
9
|
+
contract MockSecondarySwap is ISecondarySwap {
|
|
10
|
+
MockZoraTimedSale immutable mockTimedSale;
|
|
11
|
+
|
|
12
|
+
constructor(MockZoraTimedSale _mockTimedSale) {
|
|
13
|
+
mockTimedSale = _mockTimedSale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function buy1155(address erc20zAddress, uint256 num1155ToBuy, address payable recipient, address payable, uint256, uint160) external payable {
|
|
17
|
+
(address collection, uint256 tokenId) = mockTimedSale.collectionForErc20z(erc20zAddress);
|
|
18
|
+
if (collection == address(0)) revert("ERC20z not set");
|
|
19
|
+
Mock1155(collection).mint(recipient, tokenId, num1155ToBuy, "");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function onERC1155Received(address, address, uint256 tokenId, uint256, bytes calldata) external view returns (bytes4) {
|
|
23
|
+
address collection = msg.sender;
|
|
24
|
+
address erc20zAddress = mockTimedSale.sale(collection, tokenId).erc20zAddress;
|
|
25
|
+
if (erc20zAddress == address(0)) {
|
|
26
|
+
revert SaleNotSet();
|
|
27
|
+
}
|
|
28
|
+
return IERC1155Receiver.onERC1155Received.selector;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import {Mock1155} from "./Mock1155.sol";
|
|
5
|
+
import {IZoraTimedSaleStrategy} from "../../src/interfaces/IZoraTimedSaleStrategy.sol";
|
|
6
|
+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
7
|
+
|
|
8
|
+
contract MockERC20z is ERC20 {
|
|
9
|
+
constructor() ERC20("ERC20z", "ERC20z") {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
contract MockZoraTimedSale is IZoraTimedSaleStrategy {
|
|
13
|
+
uint256 constant MINT_FEE = 0.000111 ether;
|
|
14
|
+
|
|
15
|
+
function mint(address mintTo, uint256 quantity, address collection, uint256 tokenId, address, string calldata) external payable {
|
|
16
|
+
if (msg.value != MINT_FEE * quantity) revert("Incorrect mint fee");
|
|
17
|
+
Mock1155(collection).mint{value: msg.value}(mintTo, tokenId, quantity, "");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
struct CollectionAndTokenId {
|
|
21
|
+
address collection;
|
|
22
|
+
uint256 tokenId;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
mapping(address => mapping(uint256 => address)) internal saleStorage;
|
|
26
|
+
mapping(address => CollectionAndTokenId) public collectionForErc20z;
|
|
27
|
+
|
|
28
|
+
function setSale(address collection, uint256 tokenId) external returns (address erc20z) {
|
|
29
|
+
erc20z = address(new MockERC20z());
|
|
30
|
+
saleStorage[collection][tokenId] = erc20z;
|
|
31
|
+
collectionForErc20z[erc20z] = CollectionAndTokenId(collection, tokenId);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function sale(address collection, uint256 tokenId) external view returns (SaleStorage memory _sale) {
|
|
35
|
+
address erc20z = saleStorage[collection][tokenId];
|
|
36
|
+
_sale.erc20zAddress = payable(erc20z);
|
|
37
|
+
}
|
|
38
|
+
}
|
package/wagmi.config.ts
CHANGED
|
@@ -8,7 +8,9 @@ export default defineConfig({
|
|
|
8
8
|
forge: {
|
|
9
9
|
build: false,
|
|
10
10
|
},
|
|
11
|
-
include: ["CommentsImpl"].map(
|
|
11
|
+
include: ["CommentsImpl", "CallerAndCommenterImpl"].map(
|
|
12
|
+
(contractName) => `${contractName}.json`,
|
|
13
|
+
),
|
|
12
14
|
}),
|
|
13
15
|
],
|
|
14
16
|
});
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { WalletClient, PublicClient, Transport, Chain, Account } from "viem";
|
|
2
|
-
import { getChainNamePositionalArg, getChainConfig } from "./utils";
|
|
3
|
-
import { queryCommentsPage, MintComment } from "./queries";
|
|
4
|
-
import {
|
|
5
|
-
writeCommentsToContract,
|
|
6
|
-
getBackfillerAccount,
|
|
7
|
-
filterCommentsThatAreAlreadyOnChain,
|
|
8
|
-
} from "./writeComments";
|
|
9
|
-
|
|
10
|
-
const queryAndWriteCommentsOfPage = async ({
|
|
11
|
-
subgraph,
|
|
12
|
-
pageSize,
|
|
13
|
-
page,
|
|
14
|
-
walletClient,
|
|
15
|
-
publicClient,
|
|
16
|
-
chainId,
|
|
17
|
-
backfiller,
|
|
18
|
-
}: {
|
|
19
|
-
subgraph: string;
|
|
20
|
-
pageSize: number;
|
|
21
|
-
page: number;
|
|
22
|
-
walletClient: WalletClient<Transport, Chain>;
|
|
23
|
-
|
|
24
|
-
publicClient: PublicClient;
|
|
25
|
-
chainId: number;
|
|
26
|
-
backfiller: Account;
|
|
27
|
-
}): Promise<boolean> => {
|
|
28
|
-
// query and page through each batch of comments
|
|
29
|
-
// for each page, write to the comments contract the comment
|
|
30
|
-
// if there is an empty array, return
|
|
31
|
-
|
|
32
|
-
const pagedComments = await queryCommentsPage({
|
|
33
|
-
subgraph,
|
|
34
|
-
page,
|
|
35
|
-
pageSize,
|
|
36
|
-
skip: 0,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (pagedComments.length === 0) {
|
|
40
|
-
console.log("no comments returned from query");
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const filteredComments = await filterCommentsThatAreAlreadyOnChain({
|
|
45
|
-
publicClient,
|
|
46
|
-
chainId,
|
|
47
|
-
comments: pagedComments,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
if (filteredComments.length === 0) {
|
|
51
|
-
console.log("no comments returned that are not already on chain");
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
console.log({
|
|
56
|
-
pagedComments: pagedComments.length,
|
|
57
|
-
filteredComments: filteredComments.length,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const processCommentsInChunks = async (
|
|
61
|
-
filteredComments: MintComment[],
|
|
62
|
-
initialChunkSize: number,
|
|
63
|
-
walletClient: WalletClient<Transport, Chain>,
|
|
64
|
-
publicClient: PublicClient,
|
|
65
|
-
chainId: number,
|
|
66
|
-
) => {
|
|
67
|
-
let chunkSize = initialChunkSize;
|
|
68
|
-
|
|
69
|
-
while (chunkSize > 0) {
|
|
70
|
-
try {
|
|
71
|
-
const chunks: MintComment[][] = [];
|
|
72
|
-
for (let i = 0; i < filteredComments.length; i += chunkSize) {
|
|
73
|
-
chunks.push([...filteredComments].slice(i, i + chunkSize));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
console.log(`processing ${chunks.length} chunks of size ${chunkSize}`);
|
|
77
|
-
|
|
78
|
-
for (let index = 0; index < chunks.length; index++) {
|
|
79
|
-
const chunk = chunks[index];
|
|
80
|
-
if (chunk.length > 0) {
|
|
81
|
-
console.log(
|
|
82
|
-
`writing chunk ${index + 1} of ${chunks.length}, size ${chunk.length}`,
|
|
83
|
-
);
|
|
84
|
-
await writeCommentsToContract({
|
|
85
|
-
comments: chunk,
|
|
86
|
-
walletClient,
|
|
87
|
-
publicClient,
|
|
88
|
-
chainId,
|
|
89
|
-
account: backfiller,
|
|
90
|
-
write: true,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// If we've made it here without errors, we're done
|
|
96
|
-
return;
|
|
97
|
-
} catch (error) {
|
|
98
|
-
console.log(error);
|
|
99
|
-
console.error(
|
|
100
|
-
`failed with chunk size ${chunkSize}. Retrying with smaller chunks.`,
|
|
101
|
-
);
|
|
102
|
-
chunkSize -= 100;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
console.error("failed to process comments even with minimum chunk size.");
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
await processCommentsInChunks(
|
|
110
|
-
filteredComments,
|
|
111
|
-
700,
|
|
112
|
-
walletClient,
|
|
113
|
-
publicClient,
|
|
114
|
-
chainId,
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
return true;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const queryAndWriteComments = async ({
|
|
121
|
-
subgraph,
|
|
122
|
-
pageSize,
|
|
123
|
-
walletClient,
|
|
124
|
-
publicClient,
|
|
125
|
-
chainId,
|
|
126
|
-
}: {
|
|
127
|
-
subgraph: string;
|
|
128
|
-
pageSize: number;
|
|
129
|
-
walletClient: WalletClient<Transport, Chain>;
|
|
130
|
-
publicClient: PublicClient;
|
|
131
|
-
chainId: number;
|
|
132
|
-
}) => {
|
|
133
|
-
let page = 0;
|
|
134
|
-
|
|
135
|
-
const backfiller = getBackfillerAccount();
|
|
136
|
-
|
|
137
|
-
while (true) {
|
|
138
|
-
const gotSomeComments = await queryAndWriteCommentsOfPage({
|
|
139
|
-
subgraph,
|
|
140
|
-
pageSize,
|
|
141
|
-
walletClient,
|
|
142
|
-
publicClient,
|
|
143
|
-
chainId,
|
|
144
|
-
backfiller,
|
|
145
|
-
page,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
if (!gotSomeComments) {
|
|
149
|
-
console.log("done querying comments");
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
page += 1;
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const backfillComments = async (chainName: string) => {
|
|
158
|
-
const { publicClient, walletClient, chainId, subgraph } =
|
|
159
|
-
await getChainConfig(chainName);
|
|
160
|
-
|
|
161
|
-
const pageSize = 1000;
|
|
162
|
-
|
|
163
|
-
await queryAndWriteComments({
|
|
164
|
-
subgraph,
|
|
165
|
-
pageSize,
|
|
166
|
-
walletClient,
|
|
167
|
-
publicClient,
|
|
168
|
-
chainId,
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
export const main = async () => {
|
|
173
|
-
await backfillComments(getChainNamePositionalArg());
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
main();
|
package/scripts/queries.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { Address, PublicClient, Hex } from "viem";
|
|
2
|
-
import { commentsImplABI } from "../package/wagmiGenerated";
|
|
3
|
-
|
|
4
|
-
export type MintComment = {
|
|
5
|
-
tokenAndContract: {
|
|
6
|
-
address: Address;
|
|
7
|
-
tokenId: string;
|
|
8
|
-
};
|
|
9
|
-
sender: Address;
|
|
10
|
-
txn: {
|
|
11
|
-
id: Hex;
|
|
12
|
-
block: string;
|
|
13
|
-
logIndex: string;
|
|
14
|
-
};
|
|
15
|
-
timestamp: string;
|
|
16
|
-
comment: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const queryCommentsPage = async ({
|
|
20
|
-
subgraph,
|
|
21
|
-
pageSize,
|
|
22
|
-
page,
|
|
23
|
-
skip = 0,
|
|
24
|
-
}: {
|
|
25
|
-
subgraph: string;
|
|
26
|
-
pageSize: number;
|
|
27
|
-
page: number;
|
|
28
|
-
skip?: number;
|
|
29
|
-
}) => {
|
|
30
|
-
const query = `
|
|
31
|
-
query MintComments {
|
|
32
|
-
mintComments(
|
|
33
|
-
first: ${pageSize},
|
|
34
|
-
skip: ${page * pageSize + skip},
|
|
35
|
-
orderBy: timestamp,
|
|
36
|
-
orderDirection: asc
|
|
37
|
-
) {
|
|
38
|
-
tokenAndContract {
|
|
39
|
-
address
|
|
40
|
-
tokenId
|
|
41
|
-
}
|
|
42
|
-
sender
|
|
43
|
-
txn {
|
|
44
|
-
id
|
|
45
|
-
block
|
|
46
|
-
logIndex
|
|
47
|
-
}
|
|
48
|
-
timestamp
|
|
49
|
-
comment
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
// post to subgraph url with query
|
|
55
|
-
const response = await fetch(subgraph, {
|
|
56
|
-
method: "POST",
|
|
57
|
-
headers: {
|
|
58
|
-
"Content-Type": "application/json",
|
|
59
|
-
},
|
|
60
|
-
body: JSON.stringify({ query }),
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const responseJson = await response.json();
|
|
64
|
-
|
|
65
|
-
if (!responseJson.data) {
|
|
66
|
-
console.error("Errored querying graphql");
|
|
67
|
-
console.error(responseJson);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const mintComments = responseJson.data.mintComments;
|
|
71
|
-
|
|
72
|
-
return mintComments as MintComment[];
|
|
73
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { getChainNamePositionalArg } from "./utils";
|
|
2
|
-
import { getChainConfig } from "./utils";
|
|
3
|
-
import { queryCommentsPage } from "./queries";
|
|
4
|
-
import { saveComments } from "./savedCommentsDump";
|
|
5
|
-
|
|
6
|
-
export const queryAndSaveComments = async (chainName: string) => {
|
|
7
|
-
const { subgraph } = await getChainConfig(chainName);
|
|
8
|
-
|
|
9
|
-
const pageSize = 1000;
|
|
10
|
-
let page = 0;
|
|
11
|
-
|
|
12
|
-
// iterate over all pages until comments are empty
|
|
13
|
-
const batchSize = 20;
|
|
14
|
-
let hasMoreComments = true;
|
|
15
|
-
|
|
16
|
-
// Clear the file at the beginning
|
|
17
|
-
await saveComments(chainName, []);
|
|
18
|
-
|
|
19
|
-
while (hasMoreComments) {
|
|
20
|
-
const batchPromises = Array.from({ length: batchSize }, (_, i) =>
|
|
21
|
-
queryCommentsPage({
|
|
22
|
-
subgraph,
|
|
23
|
-
pageSize: pageSize,
|
|
24
|
-
page: page + i,
|
|
25
|
-
}),
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
const batchResults = await Promise.all(batchPromises);
|
|
29
|
-
|
|
30
|
-
for (let i = 0; i < batchResults.length; i++) {
|
|
31
|
-
const commentsPage = batchResults[i];
|
|
32
|
-
if (commentsPage.length > 0) {
|
|
33
|
-
console.log(`Queried page ${page}: ${commentsPage.length} comments`);
|
|
34
|
-
await saveComments(chainName, commentsPage, true); // Use append mode
|
|
35
|
-
page++;
|
|
36
|
-
} else {
|
|
37
|
-
hasMoreComments = false;
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const main = async () => {
|
|
45
|
-
await queryAndSaveComments(getChainNamePositionalArg());
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
main();
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { getChainConfig } from "./utils";
|
|
2
|
-
import { queryCommentsPage } from "./queries";
|
|
3
|
-
import { getChainNamePositionalArg } from "./utils";
|
|
4
|
-
|
|
5
|
-
export const queryQuantityOfComments = async (chainName: string) => {
|
|
6
|
-
const { subgraph } = await getChainConfig(chainName);
|
|
7
|
-
|
|
8
|
-
// do a breadth first search to find the total number of comments;
|
|
9
|
-
// we want to find the lowest page that has comments, and from that page, we know
|
|
10
|
-
// the total number of comments
|
|
11
|
-
|
|
12
|
-
// midpoint is 500k, we go up to 1 million
|
|
13
|
-
|
|
14
|
-
const low = 100_000 / pageSize;
|
|
15
|
-
const high = 2_000_000 / pageSize;
|
|
16
|
-
|
|
17
|
-
const { page, quantity } = await search(low, high, subgraph);
|
|
18
|
-
|
|
19
|
-
console.log(`Found last page ${page} with ${quantity} comments`);
|
|
20
|
-
|
|
21
|
-
const totalComments = page * pageSize + quantity;
|
|
22
|
-
|
|
23
|
-
console.log(`Total comments: ${totalComments}`);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const pageSize = 1000;
|
|
27
|
-
|
|
28
|
-
// recursive binary search to find the last page of comments
|
|
29
|
-
const search = async (low: number, high: number, subgraph: string) => {
|
|
30
|
-
const midpoint = Math.floor(low + (high - low) / 2);
|
|
31
|
-
const commentsPage = await queryCommentsPage({
|
|
32
|
-
subgraph,
|
|
33
|
-
pageSize,
|
|
34
|
-
page: midpoint,
|
|
35
|
-
});
|
|
36
|
-
console.log(
|
|
37
|
-
`Found ${commentsPage.length} comments on page ${midpoint}, comments so far ${midpoint * pageSize}`,
|
|
38
|
-
);
|
|
39
|
-
if (commentsPage.length === 0) {
|
|
40
|
-
return await search(low, midpoint, subgraph);
|
|
41
|
-
``;
|
|
42
|
-
}
|
|
43
|
-
if (commentsPage.length < pageSize) {
|
|
44
|
-
return { page: midpoint, quantity: commentsPage.length };
|
|
45
|
-
}
|
|
46
|
-
return await search(midpoint, high, subgraph);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const main = async () => {
|
|
50
|
-
await queryQuantityOfComments(getChainNamePositionalArg());
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
main();
|
package/scripts/writeComments.ts
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Address,
|
|
3
|
-
WalletClient,
|
|
4
|
-
PublicClient,
|
|
5
|
-
toHex,
|
|
6
|
-
BaseError,
|
|
7
|
-
ContractFunctionRevertedError,
|
|
8
|
-
ExecutionRevertedError,
|
|
9
|
-
TransactionExecutionError,
|
|
10
|
-
ContractFunctionExecutionError,
|
|
11
|
-
Account,
|
|
12
|
-
Hex,
|
|
13
|
-
Chain,
|
|
14
|
-
Transport,
|
|
15
|
-
} from "viem";
|
|
16
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
17
|
-
import { getCommentsAddress } from "./getCommentsAddresses";
|
|
18
|
-
import { commentsImplABI } from "../package/wagmiGenerated";
|
|
19
|
-
import { CommentIdentifier } from "../package/types";
|
|
20
|
-
import { MintComment } from "./queries";
|
|
21
|
-
|
|
22
|
-
const blockAndLogIndexToId = (
|
|
23
|
-
blockString: string,
|
|
24
|
-
logIndexString: string,
|
|
25
|
-
): Hex => {
|
|
26
|
-
const blockNumber = BigInt(blockString);
|
|
27
|
-
const logIndex = BigInt(logIndexString);
|
|
28
|
-
|
|
29
|
-
// Use a larger shift (192 bits instead of 128)
|
|
30
|
-
const blockAndLogIndex = (blockNumber << 200n) | logIndex;
|
|
31
|
-
|
|
32
|
-
return toHex(blockAndLogIndex, { size: 32 });
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const getBackfillerAccount = () => {
|
|
36
|
-
const privateKey = process.env.PRIVATE_KEY as Address;
|
|
37
|
-
return privateKeyToAccount(privateKey);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const parseError = (err: Error) => {
|
|
41
|
-
if (err instanceof BaseError) {
|
|
42
|
-
const revertError = err.walk(
|
|
43
|
-
(_err) =>
|
|
44
|
-
_err instanceof ContractFunctionRevertedError ||
|
|
45
|
-
_err instanceof ExecutionRevertedError ||
|
|
46
|
-
_err instanceof TransactionExecutionError ||
|
|
47
|
-
_err instanceof ContractFunctionExecutionError,
|
|
48
|
-
);
|
|
49
|
-
if (
|
|
50
|
-
revertError instanceof ContractFunctionRevertedError ||
|
|
51
|
-
revertError instanceof ExecutionRevertedError ||
|
|
52
|
-
revertError instanceof TransactionExecutionError ||
|
|
53
|
-
revertError instanceof ContractFunctionExecutionError
|
|
54
|
-
) {
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
const errorName = revertError.data?.errorName ?? "";
|
|
57
|
-
console.error("reverted", {
|
|
58
|
-
errorName,
|
|
59
|
-
// details: revertError.details,
|
|
60
|
-
message: revertError.message,
|
|
61
|
-
shortMessage: revertError.shortMessage,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
throw err;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
console.error("Unknown error", err.name);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
function toCommentIdentifier(comment: MintComment): CommentIdentifier {
|
|
72
|
-
return {
|
|
73
|
-
commenter: comment.sender,
|
|
74
|
-
contractAddress: comment.tokenAndContract.address,
|
|
75
|
-
tokenId: BigInt(comment.tokenAndContract.tokenId),
|
|
76
|
-
nonce: blockAndLogIndexToId(comment.txn.block, comment.txn.logIndex),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const writeCommentsToContract = async ({
|
|
81
|
-
comments,
|
|
82
|
-
walletClient,
|
|
83
|
-
publicClient,
|
|
84
|
-
chainId,
|
|
85
|
-
account,
|
|
86
|
-
write = true,
|
|
87
|
-
}: {
|
|
88
|
-
comments: MintComment[];
|
|
89
|
-
walletClient: WalletClient<Transport, Chain>;
|
|
90
|
-
publicClient: PublicClient;
|
|
91
|
-
chainId: number;
|
|
92
|
-
account: Account;
|
|
93
|
-
// if the transaction should be written to the chain
|
|
94
|
-
write?: boolean;
|
|
95
|
-
}) => {
|
|
96
|
-
const commentsAddress = (await getCommentsAddress(chainId)).COMMENTS;
|
|
97
|
-
|
|
98
|
-
const commentIdentifiers = comments.map((comment): CommentIdentifier => {
|
|
99
|
-
try {
|
|
100
|
-
return {
|
|
101
|
-
commenter: comment.sender,
|
|
102
|
-
contractAddress: comment.tokenAndContract.address,
|
|
103
|
-
tokenId: BigInt(comment.tokenAndContract.tokenId),
|
|
104
|
-
nonce: blockAndLogIndexToId(comment.txn.block, comment.txn.logIndex),
|
|
105
|
-
};
|
|
106
|
-
} catch (err) {
|
|
107
|
-
console.error("Failed to parse comment", comment);
|
|
108
|
-
throw err;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const texts = comments.map((comment) => comment.comment);
|
|
113
|
-
|
|
114
|
-
const timestamps = comments.map((comment) => BigInt(comment.timestamp));
|
|
115
|
-
|
|
116
|
-
const originalTransactionHashes = comments.map((comment) => comment.txn.id);
|
|
117
|
-
|
|
118
|
-
if (!write) {
|
|
119
|
-
console.log("simulating");
|
|
120
|
-
|
|
121
|
-
try {
|
|
122
|
-
const simulated = await publicClient.simulateContract({
|
|
123
|
-
abi: commentsImplABI,
|
|
124
|
-
address: commentsAddress,
|
|
125
|
-
functionName: "backfillBatchAddComment",
|
|
126
|
-
args: [
|
|
127
|
-
commentIdentifiers,
|
|
128
|
-
texts,
|
|
129
|
-
timestamps,
|
|
130
|
-
originalTransactionHashes,
|
|
131
|
-
],
|
|
132
|
-
account,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
console.log("simulated:", {
|
|
136
|
-
gas: simulated.request.gas,
|
|
137
|
-
gasPrice: simulated.request.gasPrice,
|
|
138
|
-
});
|
|
139
|
-
} catch (err) {
|
|
140
|
-
parseError(err);
|
|
141
|
-
}
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
console.log("writing comments");
|
|
146
|
-
|
|
147
|
-
let hash;
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
hash = await walletClient.writeContract({
|
|
151
|
-
abi: commentsImplABI,
|
|
152
|
-
address: commentsAddress,
|
|
153
|
-
functionName: "backfillBatchAddComment",
|
|
154
|
-
args: [commentIdentifiers, texts, timestamps, originalTransactionHashes],
|
|
155
|
-
account,
|
|
156
|
-
});
|
|
157
|
-
} catch (err) {
|
|
158
|
-
parseError(err);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const receipt = await publicClient.waitForTransactionReceipt({
|
|
163
|
-
hash,
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
if (receipt.status !== "success") {
|
|
167
|
-
throw new Error("Transaction failed");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
console.log("wrote comments", {
|
|
171
|
-
status: receipt.status,
|
|
172
|
-
gasUsed: receipt.gasUsed,
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
export const filterCommentsThatAreAlreadyOnChain = async ({
|
|
177
|
-
comments,
|
|
178
|
-
chainId,
|
|
179
|
-
publicClient,
|
|
180
|
-
}: {
|
|
181
|
-
comments: MintComment[];
|
|
182
|
-
chainId: number;
|
|
183
|
-
publicClient: PublicClient;
|
|
184
|
-
}) => {
|
|
185
|
-
const commentsAddress = (await getCommentsAddress(chainId)).COMMENTS;
|
|
186
|
-
|
|
187
|
-
const result = await publicClient.multicall({
|
|
188
|
-
allowFailure: false,
|
|
189
|
-
contracts: comments.map((comment) => ({
|
|
190
|
-
abi: commentsImplABI,
|
|
191
|
-
address: commentsAddress,
|
|
192
|
-
functionName: "hashAndCheckCommentExists",
|
|
193
|
-
args: [toCommentIdentifier(comment)],
|
|
194
|
-
})),
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
return comments.filter((_, index) => !result[index][1]);
|
|
198
|
-
};
|