import assert from "assert"; import Web3 from "web3"; import { abiNftMall } from "../abis/abiBENftMall"; import { abiChipLocker } from "../abis/abiChipLocker"; import { abiERC1155 } from "../abis/abiERC1155"; import { abiEvolveFactory } from "../abis/abiUserEvolveFactory"; import { abiMinterFactory } from "../abis/abiUserMinterFactory"; import { ZERO_ADDRESS } from "../config/constants"; import { getAddressByName, universalChainCb } from "../util/chain.util"; import { SAMPLE_GAS } from "./ChainCommon"; export class JCStandard { private web3: Web3; constructor(web3: Web3) { this.web3 = web3; } async buyNft721({ addresses, values, signature, gas, estimate, }: { addresses: string[]; values: string[]; signature: string; gas?: number; estimate: number; }) { let address = jc.wallet.currentChainCfg.contracts.nftMall; const contract = new this.web3.eth.Contract(abiNftMall, address, { //@ts-ignore from: jc.wallet.currentAccAddr, }); if (!gas) { try { gas = await contract.methods .buy721NFT(addresses, values, signature) .estimateGas(); } catch (err) {} gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } //@ts-ignore if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } //@ts-ignore let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } //@ts-ignore if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; // payment token const feeAddress = await jc.wallet.getFeeAddress("nftMall"); details.push({ address: addresses[2], from: jc.wallet.currentAccAddr, to: feeAddress, value: values[1], }); // nft minted details.push({ address: addresses[1], from: ZERO_ADDRESS, to: jc.wallet.currentAccAddr, id: values[0], }); const logData = { gas, title: "buy_erc721", details, }; return universalChainCb( logData, contract.methods.buy721NFT(addresses, values, signature).send({ gas }) ); } async buyNft1155({ addresses, values, ids, amounts, signature, gas, estimate, }: { addresses: string[]; values: string[]; ids: string[]; amounts: string[]; signature: string; gas?: number; estimate: number; }) { let address = jc.wallet.currentChainCfg.contracts.nftMall; const contract = new this.web3.eth.Contract(abiNftMall, address, { //@ts-ignore from: jc.wallet.currentAccAddr, }); if (!gas) { try { gas = await contract.methods .buy1155NFT(addresses, values, ids, amounts, signature) .estimateGas(); } catch (err) {} gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } //@ts-ignore if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } //@ts-ignore let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } //@ts-ignore if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; // payment token const feeAddress = await jc.wallet.getFeeAddress("nftMall"); details.push({ address: addresses[2], from: jc.wallet.currentAccAddr, to: feeAddress, // can't fetch address in contract, use seller instead value: values[0], }); // 1155 token minted for (let i = 0, l = ids.length; i < l; i++) { details.push({ address: addresses[1], from: ZERO_ADDRESS, to: jc.wallet.currentAccAddr, id: ids[i], value: amounts[i], }); } const logData = { gas, title: "buy_erc1155", details, }; return universalChainCb( logData, contract.methods .buy1155NFT(addresses, values, ids, amounts, signature) .send({ gas }) ); } async evolve721NFT({ nftAddress, tokenIds, startTime, nonce, signature, gas, estimate, }: { nftAddress: string; tokenIds: string[]; startTime: number; nonce: string; signature: string; gas?: number; estimate: number; }) { let address = jc.wallet.currentChainCfg.contracts.evolveFactory; const contract = new this.web3.eth.Contract(abiEvolveFactory, address, { //@ts-ignore from: jc.wallet.currentAccAddr, }); if (!gas) { try { gas = await contract.methods .evolve721NFT(nftAddress, tokenIds, startTime, nonce, signature) .estimateGas(); } catch (err) {} gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } //@ts-ignore if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } //@ts-ignore let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } //@ts-ignore if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; // nft evolved details.push({ address: nftAddress, from: jc.wallet.currentAccAddr, to: jc.wallet.currentAccAddr, id: tokenIds[0], }); // nft burn details.push({ address: nftAddress, from: jc.wallet.currentAccAddr, to: ZERO_ADDRESS, id: tokenIds[1], }); const logData = { gas, title: "evolve_721", details, }; return universalChainCb( logData, contract.methods .evolve721NFT(nftAddress, tokenIds, startTime, nonce, signature) .send({ gas }) ); } async evolveChip({ tokenIds, startTime, nonce, signature, gas, estimate, }: { tokenIds: string[]; startTime: number; nonce: string; signature: string; gas?: number; estimate: number; }) { let address = jc.wallet.currentChainCfg.contracts.evolveFactory; const contract = new this.web3.eth.Contract(abiEvolveFactory, address, { //@ts-ignore from: jc.wallet.currentAccAddr, }); if (gas) { try { gas = await contract.methods .evolveChip(tokenIds, startTime, nonce, signature) .estimateGas(); } catch (err) {} gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } //@ts-ignore if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } //@ts-ignore let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } //@ts-ignore if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; const chipAddress = getAddressByName("chip"); assert(!!chipAddress, "chip address not found"); // chip evolved details.push({ address: chipAddress, from: jc.wallet.currentAccAddr, to: jc.wallet.currentAccAddr, id: tokenIds[0], value: 1, }); // chip burn for (let i = 1, l = tokenIds.length; i < l; i++) { details.push({ address: chipAddress, from: jc.wallet.currentAccAddr, to: ZERO_ADDRESS, id: tokenIds[i], value: 1, }); } const logData = { gas, title: "evolve_chip", details, }; return universalChainCb( logData, contract.methods .evolveChip(tokenIds, startTime, nonce, signature) .send({ gas }) ); } async mintShardBatchUser({ tokenIds, amounts, startTime, nonce, signature, gas, estimate, }: { tokenIds: string[]; amounts: number[]; startTime: number; nonce: string; signature: string; gas?: number; estimate: number; }) { let address = jc.wallet.currentChainCfg.contracts.minterFactory; const contract = new this.web3.eth.Contract(abiMinterFactory, address, { //@ts-ignore from: jc.wallet.currentAccAddr, }); if (!gas) { try { gas = await contract.methods .mintShardBatchUser(tokenIds, amounts, startTime, nonce, signature) .estimateGas(); } catch (err) {} gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } //@ts-ignore if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } //@ts-ignore let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } //@ts-ignore if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; const shardAddress = getAddressByName("shard"); assert(!!shardAddress, "shard address not found"); // shard for (let i = 0, l = tokenIds.length; i < l; i++) { details.push({ address: shardAddress, from: ZERO_ADDRESS, to: jc.wallet.currentAccAddr, id: tokenIds[i], value: amounts[i], }); } const logData = { gas, title: "mint_shard", details, }; return universalChainCb( logData, contract.methods .mintShardBatchUser(tokenIds, amounts, startTime, nonce, signature) .send({ gas }) ); } async shardMixByUser({ tokenId, nftType, payToken, payAmount, ids, amounts, startTime, nonce, signature, gas, estimate, }: { tokenId: string; nftType: number; payToken: string; payAmount: number; ids: string[]; amounts: number[]; startTime: number; nonce: string; signature: string; gas?: number; estimate: number; }) { let address = jc.wallet.currentChainCfg.contracts.minterFactory; const contract = new this.web3.eth.Contract(abiMinterFactory, address, { //@ts-ignore from: jc.wallet.currentAccAddr, }); if (!gas) { try { gas = await contract.methods .shardMixByUser( tokenId, nftType, payToken, payAmount, ids, amounts, startTime, nonce, signature ) .estimateGas(); } catch (err) {} gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } //@ts-ignore if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } //@ts-ignore let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } //@ts-ignore if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; const shardAddress = getAddressByName("shard"); assert(!!shardAddress, "shard address not found"); // nft mint const nftTypeName = nftType === 0 ? "hero" : "weapon"; const nftAddress = getAddressByName(nftTypeName); assert(!!nftAddress, "nft address not found"); details.push({ address: nftAddress, from: ZERO_ADDRESS, to: jc.wallet.currentAccAddr, id: tokenId, value: 1, }); // payment token const feeAddress = await jc.wallet.getFeeAddress("nftFactory"); details.push({ address: payToken, from: jc.wallet.currentAccAddr, to: feeAddress, value: payAmount, }); // shard burn for (let i = 0, l = ids.length; i < l; i++) { details.push({ address: shardAddress, from: jc.wallet.currentAccAddr, to: ZERO_ADDRESS, id: ids[i], value: amounts[i], }); } const logData = { gas, title: "shard_mix", details, }; return universalChainCb( logData, contract.methods .shardMixByUser( tokenId, nftType, payToken, payAmount, ids, amounts, startTime, nonce, signature ) .send({ gas }) ); } async pluginChip({ addresses, values, chipIds, slots, signature, gas, estimate, }: { addresses: string[]; values: string[]; chipIds: string[]; slots: string[]; signature: string; gas?: number; estimate: number; }) { let lockerAddress = jc.wallet.currentChainCfg.contracts.chipLocker; const contract = new this.web3.eth.Contract(abiChipLocker, lockerAddress, { from: jc.wallet.currentAccAddr, }); let chipInstance = new this.web3.eth.Contract(abiERC1155, addresses[1], { from: jc.wallet.currentAccAddr, }); if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } let gas1 = SAMPLE_GAS; let gas0 = SAMPLE_GAS; try { gas1 = await chipInstance.methods .setApprovalForAll(lockerAddress, true) .estimateGas(); gas0 = await contract.methods .pluginChip(addresses, values, chipIds, slots, signature) .estimateGas(); } catch (err) {} if (!gas) { gas1 = gas1 ? (gas1 * 1.1) | 1 : SAMPLE_GAS; gas0 = gas0 ? (gas0 * 1.1) | 1 : SAMPLE_GAS; gas = gas0 + gas1; } else { gas0 = gas - gas1; } if (gas < gas1) { throw "gas is too low"; } if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas1); if (!ethEnough) { throw "eth not enough"; } } await chipInstance.methods .setApprovalForAll(lockerAddress, true) .send({ gas: gas1 }); if (jc.wallet.isInternal) { let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas0); if (!ethEnough) { throw "eth not enough"; } } if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; // target nft details.push({ address: addresses[0], from: jc.wallet.currentAccAddr, to: jc.wallet.currentAccAddr, id: values[0], }); // chip plugin for (let i = 0, l = chipIds.length; i < l; i++) { details.push({ address: addresses[1], from: jc.wallet.currentAccAddr, to: lockerAddress, id: chipIds[i], value: 1, }); } const logData = { gas, title: "plug_chip", details, }; return universalChainCb( logData, contract.methods .pluginChip(addresses, values, chipIds, slots, signature) .send({ gas }) ); } async unplugChip({ addresses, values, chipIds, slots, signature, gas, estimate, }: { addresses: string[]; values: string[]; chipIds: string[]; slots: string[]; signature: string; gas?: number; estimate: number; }) { let lockerAddress = jc.wallet.currentChainCfg.contracts.chipLocker; const contract = new this.web3.eth.Contract(abiChipLocker, lockerAddress, { from: jc.wallet.currentAccAddr, }); if (!gas) { try { gas = await contract.methods .unplugChip(addresses, values, chipIds, slots, signature) .estimateGas(); } catch (err) { console.log(err); } gas = gas ? (gas * 1.1) | 1 : SAMPLE_GAS; } if (jc.wallet.isInternal) { if (estimate) { return jc.wallet.generateGasShow(gas); } let ethEnough = await jc.wallet.chainCommon.checkEthEnough(gas); if (!ethEnough) { throw "eth not enough"; } } if (!jc.wallet.isInternal) { setTimeout(() => { // @ts-ignore jumpToWallet(); }, 1500); } const details = []; // target nft details.push({ address: addresses[0], from: jc.wallet.currentAccAddr, to: jc.wallet.currentAccAddr, id: values[0], }); // chip plugin for (let i = 0, l = chipIds.length; i < l; i++) { details.push({ address: addresses[1], from: lockerAddress, to: jc.wallet.currentAccAddr, id: chipIds[i], value: 1, }); } const logData = { gas, title: "unplug_chip", details, }; return universalChainCb( logData, contract.methods .unplugChip(addresses, values, chipIds, slots, signature) .send({ gas }) ); } }