@totems/evm 1.0.7 → 1.0.9
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/artifacts/IMarket.json +1011 -0
- package/artifacts/ITotems.json +1477 -0
- package/artifacts/ModMarket.json +1060 -0
- package/artifacts/ProxyMod.json +334 -0
- package/artifacts/Totems.json +1503 -0
- package/package.json +4 -5
- package/test/helpers.d.ts +8 -2
- package/test/helpers.ts +525 -0
- package/test/helpers.js +0 -297
package/test/helpers.js
DELETED
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
// test/helpers.ts
|
|
2
|
-
import {network} from "hardhat";
|
|
3
|
-
import {keccak256, toBytes, decodeErrorResult} from "viem";
|
|
4
|
-
function errorSelector(signature) {
|
|
5
|
-
return keccak256(toBytes(signature)).slice(0, 10);
|
|
6
|
-
}
|
|
7
|
-
var getErrorData = function(error) {
|
|
8
|
-
const data = error?.cause?.cause?.data || error?.cause?.data || error?.data || error?.message?.match(/return data: (0x[a-fA-F0-9]+)/)?.[1] || error?.message?.match(/data: (0x[a-fA-F0-9]+)/)?.[1];
|
|
9
|
-
return data || null;
|
|
10
|
-
};
|
|
11
|
-
async function expectCustomError(promise, expectedSelector, errorName) {
|
|
12
|
-
try {
|
|
13
|
-
await promise;
|
|
14
|
-
throw new Error(`Expected ${errorName} but transaction succeeded`);
|
|
15
|
-
} catch (e) {
|
|
16
|
-
if (e.message?.startsWith(`Expected ${errorName}`))
|
|
17
|
-
throw e;
|
|
18
|
-
const data = getErrorData(e);
|
|
19
|
-
if (!data) {
|
|
20
|
-
throw new Error(`Expected ${errorName} but got error without revert data: ${e.message}`);
|
|
21
|
-
}
|
|
22
|
-
const actualSelector = data.slice(0, 10).toLowerCase();
|
|
23
|
-
const expected = expectedSelector.toLowerCase();
|
|
24
|
-
if (actualSelector !== expected) {
|
|
25
|
-
throw new Error(`Expected ${errorName} (${expected}) but got selector ${actualSelector}\nFull data: ${data}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async function expectRevertMessage(promise, expectedMessage) {
|
|
30
|
-
const ERROR_STRING_SELECTOR = "0x08c379a0";
|
|
31
|
-
try {
|
|
32
|
-
await promise;
|
|
33
|
-
throw new Error(`Expected revert with "${expectedMessage}" but transaction succeeded`);
|
|
34
|
-
} catch (e) {
|
|
35
|
-
if (e.message?.startsWith("Expected revert"))
|
|
36
|
-
throw e;
|
|
37
|
-
const data = getErrorData(e);
|
|
38
|
-
if (!data) {
|
|
39
|
-
const matches = typeof expectedMessage === "string" ? e.message?.includes(expectedMessage) : expectedMessage.test(e.message);
|
|
40
|
-
if (!matches) {
|
|
41
|
-
throw new Error(`Expected revert with "${expectedMessage}" but got: ${e.message}`);
|
|
42
|
-
}
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const selector = data.slice(0, 10).toLowerCase();
|
|
46
|
-
if (selector !== ERROR_STRING_SELECTOR) {
|
|
47
|
-
const matches = typeof expectedMessage === "string" ? e.message?.includes(expectedMessage) : expectedMessage.test(e.message);
|
|
48
|
-
if (!matches) {
|
|
49
|
-
throw new Error(`Expected string revert but got custom error with selector ${selector}`);
|
|
50
|
-
}
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
try {
|
|
54
|
-
const abi = [{
|
|
55
|
-
type: "error",
|
|
56
|
-
name: "Error",
|
|
57
|
-
inputs: [{ name: "message", type: "string" }]
|
|
58
|
-
}];
|
|
59
|
-
const decoded = decodeErrorResult({ abi, data });
|
|
60
|
-
const message = decoded.args[0];
|
|
61
|
-
const matches = typeof expectedMessage === "string" ? message.includes(expectedMessage) : expectedMessage.test(message);
|
|
62
|
-
if (!matches) {
|
|
63
|
-
throw new Error(`Expected revert with "${expectedMessage}" but got "${message}"`);
|
|
64
|
-
}
|
|
65
|
-
} catch (decodeError) {
|
|
66
|
-
const matches = typeof expectedMessage === "string" ? e.message?.includes(expectedMessage) : expectedMessage.test(e.message);
|
|
67
|
-
if (!matches) {
|
|
68
|
-
throw new Error(`Expected revert with "${expectedMessage}" but decoding failed: ${e.message}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
74
|
-
var ErrorSelectors = {
|
|
75
|
-
InvalidModEventOrigin: errorSelector("InvalidModEventOrigin()"),
|
|
76
|
-
NotLicensed: errorSelector("NotLicensed()"),
|
|
77
|
-
Unauthorized: errorSelector("Unauthorized()"),
|
|
78
|
-
TotemNotFound: errorSelector("TotemNotFound(string)"),
|
|
79
|
-
TotemNotActive: errorSelector("TotemNotActive()"),
|
|
80
|
-
InsufficientBalance: errorSelector("InsufficientBalance(uint256,uint256)"),
|
|
81
|
-
CantSetLicense: errorSelector("CantSetLicense()")
|
|
82
|
-
};
|
|
83
|
-
var MIN_BASE_FEE = 500000000000000n;
|
|
84
|
-
var BURNED_FEE = 100000000000000n;
|
|
85
|
-
var Hook = {
|
|
86
|
-
Created: 0,
|
|
87
|
-
Mint: 1,
|
|
88
|
-
Burn: 2,
|
|
89
|
-
Transfer: 3,
|
|
90
|
-
TransferOwnership: 4
|
|
91
|
-
};
|
|
92
|
-
var setupTotemsTest = async (minBaseFee = MIN_BASE_FEE, burnedFee = BURNED_FEE) => {
|
|
93
|
-
const { viem } = await network.connect();
|
|
94
|
-
const publicClient = await viem.getPublicClient();
|
|
95
|
-
const walletClient = await viem.getWalletClient();
|
|
96
|
-
const addresses = await walletClient.getAddresses();
|
|
97
|
-
const proxyModInitializer = addresses[0];
|
|
98
|
-
const proxyMod = await viem.deployContract("ProxyMod", [
|
|
99
|
-
proxyModInitializer
|
|
100
|
-
]);
|
|
101
|
-
let market = await viem.deployContract("ModMarket", [minBaseFee, burnedFee]);
|
|
102
|
-
let totems = await viem.deployContract("Totems", [
|
|
103
|
-
market.address,
|
|
104
|
-
proxyMod.address,
|
|
105
|
-
minBaseFee,
|
|
106
|
-
burnedFee
|
|
107
|
-
]);
|
|
108
|
-
totems = await viem.getContractAt("ITotems", totems.address);
|
|
109
|
-
market = await viem.getContractAt("IMarket", market.address);
|
|
110
|
-
await proxyMod.write.initialize([totems.address, market.address], { account: proxyModInitializer });
|
|
111
|
-
return {
|
|
112
|
-
viem,
|
|
113
|
-
publicClient,
|
|
114
|
-
market,
|
|
115
|
-
totems,
|
|
116
|
-
accounts: addresses.slice(0, addresses.length),
|
|
117
|
-
proxyModSeller: addresses[0],
|
|
118
|
-
proxyMod
|
|
119
|
-
};
|
|
120
|
-
};
|
|
121
|
-
var modDetails = (details) => Object.assign({
|
|
122
|
-
name: "Test Mod",
|
|
123
|
-
summary: "A test mod",
|
|
124
|
-
markdown: "## Test Mod\nThis is a test mod.",
|
|
125
|
-
image: "https://example.com/image.png",
|
|
126
|
-
website: "https://example.com",
|
|
127
|
-
websiteTickerPath: "/path/to/{ticker}",
|
|
128
|
-
isMinter: false,
|
|
129
|
-
needsUnlimited: false
|
|
130
|
-
}, details || {});
|
|
131
|
-
var publishMod = async (market, seller, contract, hooks = [], details = modDetails(), requiredActions = [], referrer = ZERO_ADDRESS, price = 1000000n, fee = undefined) => {
|
|
132
|
-
fee = fee ?? await market.read.getFee([referrer]);
|
|
133
|
-
return market.write.publish([
|
|
134
|
-
contract,
|
|
135
|
-
hooks,
|
|
136
|
-
price,
|
|
137
|
-
details,
|
|
138
|
-
requiredActions,
|
|
139
|
-
referrer
|
|
140
|
-
], { value: fee, account: seller });
|
|
141
|
-
};
|
|
142
|
-
var totemDetails = (ticker, decimals) => {
|
|
143
|
-
return {
|
|
144
|
-
ticker,
|
|
145
|
-
decimals,
|
|
146
|
-
name: `${ticker} Totem`,
|
|
147
|
-
description: `This is the ${ticker} totem.`,
|
|
148
|
-
image: `https://example.com/${ticker.toLowerCase()}.png`,
|
|
149
|
-
website: `https://example.com/${ticker.toLowerCase()}`,
|
|
150
|
-
seed: "0x1110762033e7a10db4502359a19a61eb81312834769b8419047a2c9ae03ee847"
|
|
151
|
-
};
|
|
152
|
-
};
|
|
153
|
-
var createTotem = async (totems, market, creator, ticker, decimals, allocations, mods, referrer = ZERO_ADDRESS, details = undefined) => {
|
|
154
|
-
const baseFee = await totems.read.getFee([referrer]);
|
|
155
|
-
const _mods = Object.assign({
|
|
156
|
-
transfer: [],
|
|
157
|
-
mint: [],
|
|
158
|
-
burn: [],
|
|
159
|
-
created: [],
|
|
160
|
-
transferOwnership: []
|
|
161
|
-
}, mods || {});
|
|
162
|
-
const uniqueMods = new Set;
|
|
163
|
-
Object.values(_mods).forEach((modList) => {
|
|
164
|
-
modList.forEach((m) => uniqueMods.add(m));
|
|
165
|
-
});
|
|
166
|
-
const modsFee = await market.read.getModsFee([[...uniqueMods]]);
|
|
167
|
-
return await totems.write.create([
|
|
168
|
-
details ? Object.assign({
|
|
169
|
-
ticker,
|
|
170
|
-
decimals
|
|
171
|
-
}, details) : totemDetails(ticker, decimals),
|
|
172
|
-
allocations.map((a) => ({
|
|
173
|
-
...a,
|
|
174
|
-
label: a.label || "",
|
|
175
|
-
isMinter: a.hasOwnProperty("isMinter") ? a.isMinter : false
|
|
176
|
-
})),
|
|
177
|
-
_mods,
|
|
178
|
-
referrer
|
|
179
|
-
], { account: creator, value: baseFee + modsFee });
|
|
180
|
-
};
|
|
181
|
-
var transfer = async (totems, ticker, from, to, amount, memo = "") => {
|
|
182
|
-
return await totems.write.transfer([
|
|
183
|
-
ticker,
|
|
184
|
-
from,
|
|
185
|
-
to,
|
|
186
|
-
amount,
|
|
187
|
-
memo
|
|
188
|
-
], { account: from });
|
|
189
|
-
};
|
|
190
|
-
var mint = async (totems, mod, minter, ticker, amount, memo = "", payment = 0n) => {
|
|
191
|
-
return await totems.write.mint([
|
|
192
|
-
mod,
|
|
193
|
-
minter,
|
|
194
|
-
ticker,
|
|
195
|
-
amount,
|
|
196
|
-
memo
|
|
197
|
-
], { account: minter, value: payment });
|
|
198
|
-
};
|
|
199
|
-
var burn = async (totems, ticker, owner, amount, memo = "") => {
|
|
200
|
-
return await totems.write.burn([
|
|
201
|
-
ticker,
|
|
202
|
-
owner,
|
|
203
|
-
amount,
|
|
204
|
-
memo
|
|
205
|
-
], { account: owner });
|
|
206
|
-
};
|
|
207
|
-
var getBalance = async (totems, ticker, account) => {
|
|
208
|
-
return await totems.read.getBalance([ticker, account]);
|
|
209
|
-
};
|
|
210
|
-
var getTotem = async (totems, ticker) => {
|
|
211
|
-
return await totems.read.getTotem([ticker]);
|
|
212
|
-
};
|
|
213
|
-
var getTotems = async (totems, tickers) => {
|
|
214
|
-
return await totems.read.getTotems([tickers]);
|
|
215
|
-
};
|
|
216
|
-
var getStats = async (totems, ticker) => {
|
|
217
|
-
return await totems.read.getStats([ticker]);
|
|
218
|
-
};
|
|
219
|
-
var transferOwnership = async (totems, ticker, currentOwner, newOwner) => {
|
|
220
|
-
return await totems.write.transferOwnership([
|
|
221
|
-
ticker,
|
|
222
|
-
newOwner
|
|
223
|
-
], { account: currentOwner });
|
|
224
|
-
};
|
|
225
|
-
var getMod = async (market, mod) => {
|
|
226
|
-
return await market.read.getMod([mod]);
|
|
227
|
-
};
|
|
228
|
-
var getMods = async (market, mods) => {
|
|
229
|
-
return await market.read.getMods([mods]);
|
|
230
|
-
};
|
|
231
|
-
var getModFee = async (market, mod) => {
|
|
232
|
-
return await market.read.getModFee([mod]);
|
|
233
|
-
};
|
|
234
|
-
var getModsFee = async (market, mods) => {
|
|
235
|
-
return await market.read.getModsFee([mods]);
|
|
236
|
-
};
|
|
237
|
-
var isLicensed = async (totems, ticker, mod) => {
|
|
238
|
-
return await totems.read.isLicensed([ticker, mod]);
|
|
239
|
-
};
|
|
240
|
-
var getRelays = async (totems, ticker) => {
|
|
241
|
-
return await totems.read.getRelays([ticker]);
|
|
242
|
-
};
|
|
243
|
-
var getSupportedHooks = async (market, mod) => {
|
|
244
|
-
return await market.read.getSupportedHooks([mod]);
|
|
245
|
-
};
|
|
246
|
-
var isUnlimitedMinter = async (market, mod) => {
|
|
247
|
-
return await market.read.isUnlimitedMinter([mod]);
|
|
248
|
-
};
|
|
249
|
-
var addMod = async (proxyMod, totems, market, ticker, hooks, mod, caller, referrer = ZERO_ADDRESS) => {
|
|
250
|
-
const modFee = await market.read.getModFee([mod]);
|
|
251
|
-
const referrerFee = await totems.read.getFee([referrer]);
|
|
252
|
-
return await proxyMod.write.addMod([
|
|
253
|
-
ticker,
|
|
254
|
-
hooks,
|
|
255
|
-
mod,
|
|
256
|
-
referrer
|
|
257
|
-
], { account: caller, value: modFee + referrerFee });
|
|
258
|
-
};
|
|
259
|
-
var removeMod = async (proxyMod, ticker, mod, caller) => {
|
|
260
|
-
return await proxyMod.write.removeMod([
|
|
261
|
-
ticker,
|
|
262
|
-
mod
|
|
263
|
-
], { account: caller });
|
|
264
|
-
};
|
|
265
|
-
export {
|
|
266
|
-
transferOwnership,
|
|
267
|
-
transfer,
|
|
268
|
-
totemDetails,
|
|
269
|
-
setupTotemsTest,
|
|
270
|
-
removeMod,
|
|
271
|
-
publishMod,
|
|
272
|
-
modDetails,
|
|
273
|
-
mint,
|
|
274
|
-
isUnlimitedMinter,
|
|
275
|
-
isLicensed,
|
|
276
|
-
getTotems,
|
|
277
|
-
getTotem,
|
|
278
|
-
getSupportedHooks,
|
|
279
|
-
getStats,
|
|
280
|
-
getRelays,
|
|
281
|
-
getModsFee,
|
|
282
|
-
getMods,
|
|
283
|
-
getModFee,
|
|
284
|
-
getMod,
|
|
285
|
-
getBalance,
|
|
286
|
-
expectRevertMessage,
|
|
287
|
-
expectCustomError,
|
|
288
|
-
errorSelector,
|
|
289
|
-
createTotem,
|
|
290
|
-
burn,
|
|
291
|
-
addMod,
|
|
292
|
-
ZERO_ADDRESS,
|
|
293
|
-
MIN_BASE_FEE,
|
|
294
|
-
Hook,
|
|
295
|
-
ErrorSelectors,
|
|
296
|
-
BURNED_FEE
|
|
297
|
-
};
|