Files
js/packages/sdk/test/evm/before-setup.ts
T

397 lines
12 KiB
TypeScript

import {
AbiSchema,
ChainId,
CONTRACTS_MAP,
ContractType,
EditionDropInitializer,
EditionInitializer,
getNativeTokenByChainId,
MarketplaceInitializer,
MultiwrapInitializer,
NFTCollectionInitializer,
NFTDropInitializer,
PackInitializer,
SignatureDropInitializer,
SplitInitializer,
ThirdwebSDK,
TokenDropInitializer,
TokenInitializer,
VoteInitializer,
} from "../../src/evm";
import { Plugin } from "../../src/evm/types/plugins";
import { MockStorage } from "./mock/MockStorage";
import weth from "./mock/WETH9.json";
import { deployContractAndUploadMetadata } from "./utils";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import {
ContractPublisher,
ContractPublisher__factory,
DropERC1155__factory,
DropERC1155_V2__factory,
DropERC20__factory,
DropERC20_V2__factory,
DropERC721__factory,
DropERC721_V3__factory,
Marketplace__factory,
MockContractPublisher,
MockContractPublisher__factory,
Multiwrap__factory,
Pack__factory,
SignatureDrop__factory,
SignatureDrop_V4__factory,
Split__factory,
TokenERC1155__factory,
TokenERC20__factory,
TokenERC721__factory,
TWFactory,
TWFactory__factory,
TWRegistry,
TWRegistry__factory,
TWMultichainRegistryRouter,
TWMultichainRegistryRouter__factory,
TWMultichainRegistryLogic,
TWMultichainRegistryLogic__factory,
PluginMap,
PluginMap__factory,
VoteERC20__factory,
MarketplaceV3__factory,
DirectListingsLogic__factory,
EnglishAuctionsLogic__factory,
OffersLogic__factory,
} from "@thirdweb-dev/contracts-js";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { constants, ContractInterface, ethers } from "ethers";
import hardhat from "hardhat";
import { generatePluginFunctions } from "../../src/evm/common/plugin/generatePluginFunctions";
// it's there, trust me bro
const hardhatEthers = (hardhat as any).ethers;
const RPC_URL = "http://localhost:8545";
const jsonProvider = new ethers.providers.JsonRpcProvider(RPC_URL);
const defaultProvider = hardhatEthers.provider;
let registryAddress: string;
let sdk: ThirdwebSDK;
let signer: SignerWithAddress;
let signers: SignerWithAddress[];
let storage: ThirdwebStorage;
let implementations: { [key in ContractType]?: string };
let mock_weth_address: string;
let thirdwebFactory: TWFactory;
const fastForwardTime = async (timeInSeconds: number): Promise<void> => {
const now = Math.floor(Date.now() / 1000);
await defaultProvider.send("evm_mine", [now + timeInSeconds]);
};
export const expectError = (e: unknown, message: string) => {
if (e instanceof Error) {
if (!e.message.includes(message)) {
throw e;
}
} else {
throw e;
}
};
export const mochaHooks = {
beforeAll: async () => {
require("dotenv-mono").load();
signers = await hardhatEthers.getSigners();
implementations = {};
[signer] = signers;
const trustedForwarderAddress =
"0xc82BbE41f2cF04e3a8efA18F7032BDD7f6d98a81";
await jsonProvider.send("hardhat_reset", []);
const mock_weth_deployer = new ethers.ContractFactory(
weth.abi,
weth.bytecode,
)
.connect(signer)
.deploy();
const mock_weth = await (await mock_weth_deployer).deployed();
mock_weth_address = mock_weth.address;
const registry = (await new ethers.ContractFactory(
TWRegistry__factory.abi,
TWRegistry__factory.bytecode,
)
.connect(signer)
.deploy(trustedForwarderAddress)) as TWRegistry;
const registryContract = await registry.deployed();
const thirdwebFactoryDeployer = (await new ethers.ContractFactory(
TWFactory__factory.abi,
TWFactory__factory.bytecode,
)
.connect(signer)
.deploy(trustedForwarderAddress, registry.address)) as TWFactory;
thirdwebFactory = await thirdwebFactoryDeployer.deployed();
const deployTxFactory = thirdwebFactoryDeployer.deployTransaction;
await deployTxFactory.wait();
const thirdwebRegistryAddress = await thirdwebFactoryDeployer.registry();
registryAddress = thirdwebFactoryDeployer.address;
await registryContract.grantRole(
await registryContract.OPERATOR_ROLE(),
thirdwebFactoryDeployer.address,
);
// Mock publisher for tests
const mockPublisher = (await new ethers.ContractFactory(
MockContractPublisher__factory.abi,
MockContractPublisher__factory.bytecode,
)
.connect(signer)
.deploy()) as MockContractPublisher;
const contractPublisher = (await new ethers.ContractFactory(
ContractPublisher__factory.abi,
ContractPublisher__factory.bytecode,
)
.connect(signer)
.deploy(
trustedForwarderAddress,
mockPublisher.address,
)) as ContractPublisher; // TODO needs MockPublisher here
await contractPublisher.deployed();
async function deployContract(
abi: ContractInterface,
bytecode: string,
contractType: ContractType,
): Promise<string> {
switch (contractType) {
case MarketplaceInitializer.contractType:
case MultiwrapInitializer.contractType:
const nativeTokenWrapperAddress = getNativeTokenByChainId(
ChainId.Hardhat,
).wrapped.address;
return await deployContractAndUploadMetadata(abi, bytecode, signer, [
nativeTokenWrapperAddress,
]);
case PackInitializer.contractType:
const addr = getNativeTokenByChainId(ChainId.Hardhat).wrapped.address;
return await deployContractAndUploadMetadata(abi, bytecode, signer, [
addr,
trustedForwarderAddress,
]);
default:
return await deployContractAndUploadMetadata(abi, bytecode, signer);
}
}
for (const contractType in CONTRACTS_MAP) {
if (contractType === "custom" || contractType === "marketplace-v3") {
continue;
}
let factories: any[] = [];
switch (contractType) {
case TokenInitializer.contractType:
factories.push(TokenERC20__factory);
break;
case TokenDropInitializer.contractType:
factories.push(DropERC20_V2__factory, DropERC20__factory);
break;
case NFTCollectionInitializer.contractType:
factories.push(TokenERC721__factory);
break;
case NFTDropInitializer.contractType:
factories.push(DropERC721_V3__factory, DropERC721__factory);
break;
case SignatureDropInitializer.contractType:
factories.push(SignatureDrop_V4__factory, SignatureDrop__factory);
break;
case EditionInitializer.contractType:
factories.push(TokenERC1155__factory);
break;
case EditionDropInitializer.contractType:
factories.push(DropERC1155_V2__factory, DropERC1155__factory);
break;
case SplitInitializer.contractType:
factories.push(Split__factory);
break;
case VoteInitializer.contractType:
factories.push(VoteERC20__factory);
break;
case MarketplaceInitializer.contractType:
factories.push(Marketplace__factory);
break;
case PackInitializer.contractType:
factories.push(Pack__factory);
break;
case MultiwrapInitializer.contractType:
factories.push(Multiwrap__factory);
break;
default:
throw new Error(`No factory for contract: ${contractType}`);
}
for (const factory of factories) {
const addr = await deployContract(
factory.abi,
factory.bytecode,
contractType as ContractType,
);
const tx = await thirdwebFactoryDeployer.addImplementation(addr);
await tx.wait();
implementations[contractType as ContractType] = addr;
}
}
// setup marketplace-v3 and add implementation to factory
const marketplaceEntrypointAddress = await setupMarketplaceV3();
const tx = await thirdwebFactoryDeployer.addImplementation(
marketplaceEntrypointAddress,
);
await tx.wait();
implementations["marketplace-v3"] = marketplaceEntrypointAddress;
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.registryAddress = thirdwebRegistryAddress;
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.factoryAddress = thirdwebFactoryDeployer.address;
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.contractPublisherAddress = contractPublisher.address;
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.multiChainRegistryAddress = await setupMultichainRegistry(
trustedForwarderAddress,
);
storage = MockStorage();
sdk = new ThirdwebSDK(
signer,
{
secretKey: process.env.TW_SECRET_KEY,
gasSettings: {
maxPriceInGwei: 10000,
},
supportedChains: [
{
chainId: 31337,
rpc: ["http://localhost:8545"],
nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
slug: "hardhat",
},
],
},
storage,
);
},
};
// Setup multichain registry for tests
async function setupMultichainRegistry(
trustedForwarderAddress: string,
): Promise<string> {
const multichainRegistryLogicDeployer = (await new ethers.ContractFactory(
TWMultichainRegistryLogic__factory.abi,
TWMultichainRegistryLogic__factory.bytecode,
)
.connect(signer)
.deploy()) as TWMultichainRegistryLogic;
const multichainRegistryLogic =
await multichainRegistryLogicDeployer.deployed();
const plugins: Plugin[] = generatePluginFunctions(
multichainRegistryLogic.address,
AbiSchema.parse(TWMultichainRegistryLogic__factory.abi),
);
const pluginMapDeployer = (await new ethers.ContractFactory(
PluginMap__factory.abi,
PluginMap__factory.bytecode,
)
.connect(signer)
.deploy(plugins)) as PluginMap;
const pluginMap = await pluginMapDeployer.deployed();
const multichainRegistryRouterDeployer = (await new ethers.ContractFactory(
TWMultichainRegistryRouter__factory.abi,
TWMultichainRegistryRouter__factory.bytecode,
)
.connect(signer)
.deploy(pluginMap.address, [
trustedForwarderAddress,
])) as TWMultichainRegistryRouter;
const multichainRegistryRouter =
await multichainRegistryRouterDeployer.deployed();
return multichainRegistryRouter.address;
}
// Setup marketplace-v3 for tests
async function setupMarketplaceV3(): Promise<string> {
// Direct Listings
const directListingsPluginAddress = await deployContractAndUploadMetadata(
DirectListingsLogic__factory.abi,
DirectListingsLogic__factory.bytecode,
signer,
[mock_weth_address],
);
const pluginsDirectListings: Plugin[] = generatePluginFunctions(
directListingsPluginAddress,
AbiSchema.parse(DirectListingsLogic__factory.abi),
);
// English Auctions
const englishAuctionPluginAddress = await deployContractAndUploadMetadata(
EnglishAuctionsLogic__factory.abi,
EnglishAuctionsLogic__factory.bytecode,
signer,
[mock_weth_address],
);
const pluginsEnglishAuctions: Plugin[] = generatePluginFunctions(
englishAuctionPluginAddress,
AbiSchema.parse(EnglishAuctionsLogic__factory.abi),
);
// Offers
const offersLogicPluginAddress = await deployContractAndUploadMetadata(
OffersLogic__factory.abi,
OffersLogic__factory.bytecode,
signer,
);
const pluginsOffers: Plugin[] = generatePluginFunctions(
offersLogicPluginAddress,
AbiSchema.parse(OffersLogic__factory.abi),
);
// Map
const pluginMapAddress = await deployContractAndUploadMetadata(
PluginMap__factory.abi,
PluginMap__factory.bytecode,
signer,
[[...pluginsDirectListings, ...pluginsEnglishAuctions, ...pluginsOffers]],
);
// Router
const royaltyEngineAddress = constants.AddressZero;
const marketplaceV3Address = await deployContractAndUploadMetadata(
MarketplaceV3__factory.abi,
MarketplaceV3__factory.bytecode,
signer,
[pluginMapAddress, royaltyEngineAddress],
"MarketplaceV3",
);
return marketplaceV3Address;
}
export {
sdk,
signers,
jsonProvider,
defaultProvider,
registryAddress,
fastForwardTime,
storage,
implementations,
hardhatEthers,
thirdwebFactory,
};