feat: apps contract and updated scripts (#268)
* feat: FleekApps contract * feat: update scripts * wip: more helper scripts * chore: remove unused import * test: fix deploy test * chore: fix testing networks * fix: contract helper scripts
This commit is contained in:
parent
74d4a4eb9c
commit
869b9f6e78
|
|
@ -2,6 +2,7 @@
|
||||||
cache
|
cache
|
||||||
artifacts
|
artifacts
|
||||||
deployments/hardhat
|
deployments/hardhat
|
||||||
|
deployments/local
|
||||||
gas-report
|
gas-report
|
||||||
|
|
||||||
# Foundry
|
# Foundry
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pragma solidity ^0.8.7;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
|
||||||
|
import "@openzeppelin/contracts/utils/Base64.sol";
|
||||||
|
import "./util/FleekSVG.sol";
|
||||||
|
import "./FleekERC721.sol";
|
||||||
|
|
||||||
|
contract FleekApps is Initializable, ERC721Upgradeable {
|
||||||
|
using Strings for address;
|
||||||
|
using Base64 for bytes;
|
||||||
|
|
||||||
|
uint256 public bindCount;
|
||||||
|
mapping(uint256 => uint256) public bindings;
|
||||||
|
|
||||||
|
FleekERC721 private main;
|
||||||
|
|
||||||
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||||
|
constructor() {
|
||||||
|
_disableInitializers();
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize(string memory _name, string memory _symbol, address _mainAddress) public initializer {
|
||||||
|
__ERC721_init(_name, _symbol);
|
||||||
|
main = FleekERC721(_mainAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier _requireMainMinted(uint256 _tokenId) {
|
||||||
|
require(main.ownerOf(_tokenId) != address(0), "Main token does not exist");
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mint(address _to, uint256 _tokenId) public _requireMainMinted(_tokenId) {
|
||||||
|
_mint(_to, bindCount);
|
||||||
|
bindings[bindCount] = _tokenId;
|
||||||
|
bindCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenURI(uint256 _bindId) public view virtual override(ERC721Upgradeable) returns (string memory) {
|
||||||
|
(string memory name, string memory ens, string memory logo, string memory color, string memory ipfsHash) = main
|
||||||
|
.getAppData(bindings[_bindId]);
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
return string(abi.encodePacked(_baseURI(),
|
||||||
|
abi.encodePacked('{',
|
||||||
|
'"owner":"', ownerOf(_bindId).toHexString(), '",',
|
||||||
|
'"name":"', name, '",',
|
||||||
|
'"image":"', FleekSVG.generateBase64(name, ens, logo, color), '",',
|
||||||
|
'"external_url":"ipfs://', ipfsHash, '"',
|
||||||
|
'}').encode()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _baseURI() internal view virtual override returns (string memory) {
|
||||||
|
return "data:application/json;base64,";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -202,6 +202,15 @@ contract FleekERC721 is
|
||||||
return (app.name, app.description, app.externalURL, app.ENS, app.currentBuild, app.logo, app.color);
|
return (app.name, app.description, app.externalURL, app.ENS, app.currentBuild, app.logo, app.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAppData(
|
||||||
|
uint256 tokenId
|
||||||
|
) public view returns (string memory, string memory, string memory, string memory, string memory) {
|
||||||
|
_requireMinted(tokenId);
|
||||||
|
Token storage app = _apps[tokenId];
|
||||||
|
|
||||||
|
return (app.name, app.ENS, app.logo, app.color.toColorString(), app.builds[app.currentBuild].ipfsHash);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Returns the last minted tokenId.
|
* @dev Returns the last minted tokenId.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import '@openzeppelin/hardhat-upgrades';
|
||||||
import * as dotenv from 'dotenv';
|
import * as dotenv from 'dotenv';
|
||||||
import { HardhatUserConfig } from 'hardhat/types';
|
import { HardhatUserConfig } from 'hardhat/types';
|
||||||
import { task, types } from 'hardhat/config';
|
import { task, types } from 'hardhat/config';
|
||||||
import deploy from './scripts/deploy';
|
import deployFleekERC721 from './scripts/deploy/deploy-fleek-erc721';
|
||||||
|
import deployFleekApps from './scripts/deploy/deploy-fleek-apps';
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
|
@ -26,7 +27,7 @@ const {
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
const config: HardhatUserConfig = {
|
const config: HardhatUserConfig = {
|
||||||
defaultNetwork: 'hardhat',
|
defaultNetwork: 'local',
|
||||||
networks: {
|
networks: {
|
||||||
hardhat: {
|
hardhat: {
|
||||||
chainId: 31337,
|
chainId: 31337,
|
||||||
|
|
@ -57,6 +58,10 @@ const config: HardhatUserConfig = {
|
||||||
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
|
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
|
||||||
chainId: 1,
|
chainId: 1,
|
||||||
},
|
},
|
||||||
|
local: {
|
||||||
|
url: 'http://localhost:8545',
|
||||||
|
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
gasReporter: {
|
gasReporter: {
|
||||||
enabled: REPORT_GAS === 'true' || false,
|
enabled: REPORT_GAS === 'true' || false,
|
||||||
|
|
@ -97,9 +102,9 @@ export default config;
|
||||||
|
|
||||||
// Use the following command to deploy where the network flag can be replaced with the network you choose:
|
// Use the following command to deploy where the network flag can be replaced with the network you choose:
|
||||||
// npx hardhat deploy --network goerli --new-proxy-instance --name "FleekNFAs" --symbol "FLKNFA" --billing "[10000, 20000]"
|
// npx hardhat deploy --network goerli --new-proxy-instance --name "FleekNFAs" --symbol "FLKNFA" --billing "[10000, 20000]"
|
||||||
task('deploy', 'Deploy the contracts')
|
task('deploy:FleekERC721', 'Deploy the FleekERC721 contract')
|
||||||
.addFlag('newProxyInstance', 'Force to deploy a new proxy instance')
|
.addFlag('newProxyInstance', 'Force to deploy a new proxy instance')
|
||||||
.addOptionalParam('name', 'The collection name', 'FleekNFAs', types.string)
|
.addOptionalParam('name', 'The collection name', 'Fleek NFAs', types.string)
|
||||||
.addOptionalParam('symbol', 'The collection symbol', 'FLKNFA', types.string)
|
.addOptionalParam('symbol', 'The collection symbol', 'FLKNFA', types.string)
|
||||||
.addOptionalParam(
|
.addOptionalParam(
|
||||||
'billing',
|
'billing',
|
||||||
|
|
@ -107,4 +112,10 @@ task('deploy', 'Deploy the contracts')
|
||||||
[],
|
[],
|
||||||
types.json
|
types.json
|
||||||
)
|
)
|
||||||
.setAction(deploy);
|
.setAction(deployFleekERC721);
|
||||||
|
|
||||||
|
task('deploy:FleekApps', 'Deploy the FleekApps contract')
|
||||||
|
.addFlag('newProxyInstance', 'Force to deploy a new proxy instance')
|
||||||
|
.addOptionalParam('name', 'The collection name', 'NFA - Apps', types.string)
|
||||||
|
.addOptionalParam('symbol', 'The collection symbol', 'NFAA', types.string)
|
||||||
|
.setAction(deployFleekApps);
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,11 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "yarn test:hardhat && yarn test:foundry",
|
"test": "yarn test:hardhat && yarn test:foundry",
|
||||||
"test:foundry": "forge test -vvv --fork-url mainnet --fork-block-number 16876149",
|
"test:foundry": "forge test -vvv --fork-url mainnet --fork-block-number 16876149",
|
||||||
"test:hardhat": "hardhat test",
|
"test:hardhat": "hardhat test --network hardhat",
|
||||||
"format": "prettier --write \"./**/*.{js,json,sol,ts}\"",
|
"format": "prettier --write \"./**/*.{js,json,sol,ts}\"",
|
||||||
"node:hardhat": "hardhat node",
|
"node:hardhat": "hardhat node",
|
||||||
"deploy:hardhat": "hardhat deploy --network hardhat",
|
"deploy:FleekERC721": "hardhat deploy:FleekERC721",
|
||||||
"deploy:mumbai": "hardhat deploy --network mumbai",
|
"deploy:FleekApps": "hardhat deploy:FleekApps",
|
||||||
"deploy:sepolia": "hardhat deploy --network sepolia",
|
|
||||||
"deploy:goerli": "hardhat deploy --network goerli",
|
|
||||||
"compile": "hardhat compile",
|
"compile": "hardhat compile",
|
||||||
"verify:mumbai": "npx hardhat run ./scripts/verify.js --network mumbai",
|
"verify:mumbai": "npx hardhat run ./scripts/verify.js --network mumbai",
|
||||||
"verify:goerli": "npx hardhat run ./scripts/verify.js --network goerli",
|
"verify:goerli": "npx hardhat run ./scripts/verify.js --network goerli",
|
||||||
|
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
const {
|
|
||||||
deployStore,
|
|
||||||
getCurrentAddressIfSameBytecode,
|
|
||||||
} = require('./utils/deploy-store');
|
|
||||||
const { getProxyAddress, proxyStore } = require('./utils/proxy-store');
|
|
||||||
|
|
||||||
// --- Script Settings ---
|
|
||||||
const CONTRACT_NAME = 'FleekERC721';
|
|
||||||
const DEFAULT_PROXY_SETTINGS = {
|
|
||||||
unsafeAllow: ['external-library-linking'],
|
|
||||||
};
|
|
||||||
const LIBRARIES_TO_DEPLOY = ['FleekSVG'];
|
|
||||||
|
|
||||||
const libraryDeployment = async (hre) => {
|
|
||||||
console.log('Deploying Libraries...');
|
|
||||||
const libraries = {};
|
|
||||||
|
|
||||||
for (const lib of LIBRARIES_TO_DEPLOY) {
|
|
||||||
const libAddress = await getCurrentAddressIfSameBytecode(lib);
|
|
||||||
if (libAddress) {
|
|
||||||
console.log(`Library "${lib}" already deployed at ${libAddress}`);
|
|
||||||
libraries[lib] = libAddress;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const libContract = await hre.ethers.getContractFactory(lib);
|
|
||||||
const libInstance = await libContract.deploy();
|
|
||||||
await libInstance.deployed();
|
|
||||||
await deployStore(hre.network.name, lib, libInstance, false);
|
|
||||||
console.log(`Library "${lib}" deployed at ${libInstance.address}`);
|
|
||||||
libraries[lib] = libInstance.address;
|
|
||||||
}
|
|
||||||
|
|
||||||
return libraries;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = async (taskArgs, hre) => {
|
|
||||||
const { newProxyInstance, name, symbol, billing } = taskArgs;
|
|
||||||
const network = hre.network.name;
|
|
||||||
|
|
||||||
console.log(':: Starting Deployment ::');
|
|
||||||
console.log('Network:', network);
|
|
||||||
console.log('Contract:', CONTRACT_NAME);
|
|
||||||
console.log(':: Arguments ::');
|
|
||||||
console.log(taskArgs);
|
|
||||||
console.log();
|
|
||||||
|
|
||||||
const deployArguments = [name, symbol, billing];
|
|
||||||
|
|
||||||
const libraries = await libraryDeployment(hre);
|
|
||||||
|
|
||||||
const Contract = await ethers.getContractFactory(CONTRACT_NAME, {
|
|
||||||
libraries,
|
|
||||||
});
|
|
||||||
const proxyAddress = await getProxyAddress(CONTRACT_NAME, network);
|
|
||||||
|
|
||||||
let deployResult;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!proxyAddress || newProxyInstance)
|
|
||||||
throw new Error('new-proxy-instance');
|
|
||||||
console.log(`Trying to upgrade proxy contract at: "${proxyAddress}"`);
|
|
||||||
deployResult = await upgrades.upgradeProxy(
|
|
||||||
proxyAddress,
|
|
||||||
Contract,
|
|
||||||
DEFAULT_PROXY_SETTINGS
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('\x1b[32m');
|
|
||||||
console.log(
|
|
||||||
`Contract ${CONTRACT_NAME} upgraded at "${deployResult.address}" by account "${deployResult.signer.address}"`
|
|
||||||
);
|
|
||||||
console.log('\x1b[0m');
|
|
||||||
} catch (e) {
|
|
||||||
if (
|
|
||||||
e.message === 'new-proxy-instance' ||
|
|
||||||
e.message.includes("doesn't look like an ERC 1967 proxy")
|
|
||||||
) {
|
|
||||||
console.log(`Failed to upgrade proxy contract: "${e.message?.trim()}"`);
|
|
||||||
console.log('Creating new proxy contract...');
|
|
||||||
deployResult = await upgrades.deployProxy(
|
|
||||||
Contract,
|
|
||||||
deployArguments,
|
|
||||||
DEFAULT_PROXY_SETTINGS
|
|
||||||
);
|
|
||||||
await deployResult.deployed();
|
|
||||||
await proxyStore(CONTRACT_NAME, deployResult.address, network);
|
|
||||||
|
|
||||||
console.log('\x1b[32m');
|
|
||||||
console.log(
|
|
||||||
`Contract ${CONTRACT_NAME} deployed at "${deployResult.address}" by account "${deployResult.signer.address}"`
|
|
||||||
);
|
|
||||||
console.log('\x1b[0m');
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await deployStore(network, CONTRACT_NAME, deployResult);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Could not write deploy files', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return deployResult;
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
|
import { deployLibraries } from './deploy-libraries';
|
||||||
|
import { deployContractWithProxy } from './deploy-proxy-contract';
|
||||||
|
import { getContract } from '../util';
|
||||||
|
import { Contract } from 'ethers';
|
||||||
|
|
||||||
|
type TaskArgs = {
|
||||||
|
newProxyInstance: boolean;
|
||||||
|
name: string;
|
||||||
|
symbol: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async (
|
||||||
|
{ newProxyInstance, name, symbol }: TaskArgs,
|
||||||
|
hre: HardhatRuntimeEnvironment
|
||||||
|
): Promise<Contract> => {
|
||||||
|
console.log('Deploying FleekApps...');
|
||||||
|
const libraries = await deployLibraries(['FleekSVG'], hre);
|
||||||
|
|
||||||
|
const mainContract = await getContract('FleekERC721');
|
||||||
|
|
||||||
|
return deployContractWithProxy(
|
||||||
|
{
|
||||||
|
name: 'FleekApps',
|
||||||
|
newProxyInstance,
|
||||||
|
args: [name, symbol, mainContract.address],
|
||||||
|
libraries,
|
||||||
|
},
|
||||||
|
hre
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
|
import { deployLibraries } from './deploy-libraries';
|
||||||
|
import { deployContractWithProxy } from './deploy-proxy-contract';
|
||||||
|
import { Contract } from 'ethers';
|
||||||
|
|
||||||
|
type TaskArgs = {
|
||||||
|
newProxyInstance: boolean;
|
||||||
|
name: string;
|
||||||
|
symbol: string;
|
||||||
|
billing: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async (
|
||||||
|
{ newProxyInstance, name, symbol, billing }: TaskArgs,
|
||||||
|
hre: HardhatRuntimeEnvironment
|
||||||
|
): Promise<Contract> => {
|
||||||
|
console.log('Deploying FleekERC721...');
|
||||||
|
const libraries = await deployLibraries(['FleekSVG'], hre);
|
||||||
|
|
||||||
|
return deployContractWithProxy(
|
||||||
|
{
|
||||||
|
name: 'FleekERC721',
|
||||||
|
newProxyInstance,
|
||||||
|
args: [name, symbol, billing],
|
||||||
|
libraries,
|
||||||
|
},
|
||||||
|
hre
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import {
|
||||||
|
deployStore,
|
||||||
|
getCurrentAddressIfSameBytecode,
|
||||||
|
} from '../utils/deploy-store';
|
||||||
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
|
|
||||||
|
export const deployLibraries = async (
|
||||||
|
librariesToDeploy: string[],
|
||||||
|
hre: HardhatRuntimeEnvironment
|
||||||
|
) => {
|
||||||
|
console.log('Deploying Libraries...');
|
||||||
|
const libraries: Record<string, string> = {};
|
||||||
|
|
||||||
|
for (const lib of librariesToDeploy) {
|
||||||
|
const libAddress: string = await getCurrentAddressIfSameBytecode(lib);
|
||||||
|
if (libAddress) {
|
||||||
|
console.log(`Library "${lib}" already deployed at ${libAddress}`);
|
||||||
|
libraries[lib] = libAddress;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const libContract = await hre.ethers.getContractFactory(lib);
|
||||||
|
const libInstance = await libContract.deploy();
|
||||||
|
await libInstance.deployed();
|
||||||
|
await deployStore(hre.network.name, lib, libInstance, false);
|
||||||
|
console.log(`Library "${lib}" deployed at ${libInstance.address}`);
|
||||||
|
libraries[lib] = libInstance.address;
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraries;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { getProxyAddress, proxyStore } from '../utils/proxy-store';
|
||||||
|
import { deployStore } from '../utils/deploy-store';
|
||||||
|
import { UpgradeProxyOptions } from '@openzeppelin/hardhat-upgrades/dist/utils';
|
||||||
|
import { Contract } from 'ethers';
|
||||||
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
|
|
||||||
|
const DEFAULT_PROXY_SETTINGS: UpgradeProxyOptions = {
|
||||||
|
unsafeAllow: ['external-library-linking'],
|
||||||
|
};
|
||||||
|
|
||||||
|
type DeployContractArgs = {
|
||||||
|
name: string;
|
||||||
|
newProxyInstance: boolean;
|
||||||
|
args: unknown[];
|
||||||
|
libraries?: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deployContractWithProxy = async (
|
||||||
|
{ name, newProxyInstance, args, libraries }: DeployContractArgs,
|
||||||
|
hre: HardhatRuntimeEnvironment
|
||||||
|
): Promise<Contract> => {
|
||||||
|
// const { newProxyInstance, name, symbol, billing } = taskArgs;
|
||||||
|
const network = hre.network.name;
|
||||||
|
|
||||||
|
console.log(`Deploying: ${name}`);
|
||||||
|
console.log('Arguments:', args);
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
const Contract = await hre.ethers.getContractFactory(name, {
|
||||||
|
libraries,
|
||||||
|
});
|
||||||
|
const proxyAddress = await getProxyAddress(name, network);
|
||||||
|
|
||||||
|
let deployResult;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!proxyAddress || newProxyInstance)
|
||||||
|
throw new Error('new-proxy-instance');
|
||||||
|
console.log(`Trying to upgrade proxy contract at: "${proxyAddress}"`);
|
||||||
|
deployResult = await hre.upgrades.upgradeProxy(
|
||||||
|
proxyAddress,
|
||||||
|
Contract,
|
||||||
|
DEFAULT_PROXY_SETTINGS
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('\x1b[32m');
|
||||||
|
console.log(
|
||||||
|
`Contract ${name} upgraded at "${
|
||||||
|
deployResult.address
|
||||||
|
}" by account "${await deployResult.signer.getAddress()}"`
|
||||||
|
);
|
||||||
|
console.log('\x1b[0m');
|
||||||
|
} catch (e) {
|
||||||
|
if (
|
||||||
|
e instanceof Error &&
|
||||||
|
(e.message === 'new-proxy-instance' ||
|
||||||
|
e.message.includes("doesn't look like an ERC 1967 proxy"))
|
||||||
|
) {
|
||||||
|
console.log(`Failed to upgrade proxy contract: "${e.message?.trim()}"`);
|
||||||
|
console.log('Creating new proxy contract...');
|
||||||
|
deployResult = await hre.upgrades.deployProxy(
|
||||||
|
Contract,
|
||||||
|
args,
|
||||||
|
DEFAULT_PROXY_SETTINGS
|
||||||
|
);
|
||||||
|
await deployResult.deployed();
|
||||||
|
await proxyStore(name, deployResult.address, network);
|
||||||
|
|
||||||
|
console.log('\x1b[32m');
|
||||||
|
console.log(
|
||||||
|
`Contract ${name} deployed at "${
|
||||||
|
deployResult.address
|
||||||
|
}" by account "${await deployResult.signer.getAddress()}"`
|
||||||
|
);
|
||||||
|
console.log('\x1b[0m');
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deployStore(network, name, deployResult);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Could not write deploy files', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deployResult;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// npx hardhat run scripts/generate-image.ts --network local
|
||||||
|
|
||||||
|
import { getContract } from './util';
|
||||||
|
|
||||||
|
export const generateImage = async (
|
||||||
|
name: string,
|
||||||
|
ens: string,
|
||||||
|
logo: string,
|
||||||
|
color: string
|
||||||
|
) => {
|
||||||
|
const contract = await getContract('FleekSVG');
|
||||||
|
|
||||||
|
const svg = await contract.generateBase64(name, ens, logo, color);
|
||||||
|
|
||||||
|
console.log('SVG:', svg);
|
||||||
|
};
|
||||||
|
|
||||||
|
generateImage('Fleek', '', '', '#123456');
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// npx hardhat run scripts/get-app.ts --network local
|
||||||
|
|
||||||
|
import { getContract, parseDataURI } from './util';
|
||||||
|
|
||||||
|
const getApp = async (tokenId: number) => {
|
||||||
|
const contract = await getContract('FleekApps');
|
||||||
|
|
||||||
|
const transaction = await contract.tokenURI(tokenId);
|
||||||
|
|
||||||
|
const parsed = parseDataURI(transaction);
|
||||||
|
|
||||||
|
console.log('App:', parsed);
|
||||||
|
};
|
||||||
|
|
||||||
|
getApp(0);
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// npx hardhat run scripts/mint-app.ts --network local
|
||||||
|
|
||||||
|
import { getContract } from './util';
|
||||||
|
|
||||||
|
const mintApp = async (nfaId: number) => {
|
||||||
|
const contract = await getContract('FleekApps');
|
||||||
|
|
||||||
|
const transaction = await contract.mint(
|
||||||
|
'0x7ed735b7095c05d78df169f991f2b7f1a1f1a049',
|
||||||
|
nfaId
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Minted app', transaction.hash);
|
||||||
|
};
|
||||||
|
|
||||||
|
mintApp(0);
|
||||||
|
|
@ -44,8 +44,9 @@ const DEFAULT_MINTS = {
|
||||||
'aave', // name
|
'aave', // name
|
||||||
'Earn interest, borrow assets, and build applications', // description
|
'Earn interest, borrow assets, and build applications', // description
|
||||||
'https://aave.com/', // external url
|
'https://aave.com/', // external url
|
||||||
'aave.eth', // ens
|
'', // ens
|
||||||
'6ea6ad16c46ae85faced7e50555ff7368422f57', // commit hash
|
'6ea6ad16c46ae85faced7e50555ff7368422f57', // commit hash,
|
||||||
|
'bafybeifc5pgon43a2xoeevwq45ftwghzbgtjxc7k4dqlzhqh432wpahigm', // ipfs hash
|
||||||
'https://github.com/org/repo', // repo
|
'https://github.com/org/repo', // repo
|
||||||
path.resolve(__dirname, '../assets/aave.svg'), // svg
|
path.resolve(__dirname, '../assets/aave.svg'), // svg
|
||||||
],
|
],
|
||||||
|
|
@ -53,9 +54,10 @@ const DEFAULT_MINTS = {
|
||||||
'Uniswap', // name
|
'Uniswap', // name
|
||||||
'Swap, earn, and build on the leading decentralized crypto trading protocol', // description
|
'Swap, earn, and build on the leading decentralized crypto trading protocol', // description
|
||||||
'https://uniswap.org/', // external url
|
'https://uniswap.org/', // external url
|
||||||
'uniswap.eth', // ens
|
'', // ens
|
||||||
'6ea6ad16c46ae85faced7e50555ff7368422f57', // commit hash
|
'6ea6ad16c46ae85faced7e50555ff7368422f57', // commit hash
|
||||||
'https://github.com/org/repo', // repo
|
'https://github.com/org/repo', // repo
|
||||||
|
'bafybeidwf6m2lhkdifuxqucgaq547bwyxk2mljwmazvhmyryjr6yjoe3nu', // ipfs hash
|
||||||
path.resolve(__dirname, '../assets/uniswap.svg'), // svg
|
path.resolve(__dirname, '../assets/uniswap.svg'), // svg
|
||||||
],
|
],
|
||||||
yearn: [
|
yearn: [
|
||||||
|
|
@ -78,7 +80,7 @@ const DEFAULT_MINTS = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const params = DEFAULT_MINTS.fleek;
|
const params = DEFAULT_MINTS.uniswap;
|
||||||
const mintTo = '0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049';
|
const mintTo = '0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049';
|
||||||
const verifier = '0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049';
|
const verifier = '0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049';
|
||||||
|
|
||||||
|
|
@ -90,11 +92,15 @@ const verifier = '0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049';
|
||||||
console.log('SVG Path: ', svgPath);
|
console.log('SVG Path: ', svgPath);
|
||||||
params.push(await getSVGBase64(svgPath));
|
params.push(await getSVGBase64(svgPath));
|
||||||
console.log('SVG length: ', params[params.length - 1].length);
|
console.log('SVG length: ', params[params.length - 1].length);
|
||||||
params.push(await getSVGColor(svgPath));
|
params.push(
|
||||||
|
(await getSVGColor(svgPath))
|
||||||
|
.reduce((a, b, i) => a | (b << ((2 - i) * 8)), 0)
|
||||||
|
.toString()
|
||||||
|
);
|
||||||
params.push(false);
|
params.push(false);
|
||||||
params.push(verifier);
|
params.push(verifier);
|
||||||
|
|
||||||
const transaction = await contract.mint(...params);
|
const transaction = await contract.mint(...params);
|
||||||
|
|
||||||
console.log('Response: ', transaction);
|
console.log('Response: ', transaction.hash);
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// npx hardhat run scripts/owner-of.ts --network local
|
||||||
|
|
||||||
|
import { getContract } from './util';
|
||||||
|
|
||||||
|
const ownerOf = async (tokenId: number) => {
|
||||||
|
const contract = await getContract('FleekERC721');
|
||||||
|
|
||||||
|
const owner = await contract.ownerOf(tokenId);
|
||||||
|
|
||||||
|
console.log('Owner:', owner);
|
||||||
|
};
|
||||||
|
|
||||||
|
ownerOf(0);
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// npx hardhat run scripts/tokenURI.js --network mumbai/sepolia/goerli
|
// npx hardhat run scripts/tokenURI.js --network mumbai/sepolia/goerli
|
||||||
const { getContract } = require('./util');
|
const { getContract, parseDataURI } = require('./util');
|
||||||
|
|
||||||
// TODO: make this arguments
|
// TODO: make this arguments
|
||||||
const tokenId = 0;
|
const tokenId = 0;
|
||||||
|
|
@ -9,9 +9,7 @@ const tokenId = 0;
|
||||||
|
|
||||||
const transaction = await contract.tokenURI(tokenId);
|
const transaction = await contract.tokenURI(tokenId);
|
||||||
|
|
||||||
const parsed = JSON.parse(
|
const parsed = parseDataURI(transaction);
|
||||||
Buffer.from(transaction.slice(29), 'base64').toString('utf-8')
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Response: ', parsed);
|
console.log('Response: ', parsed);
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,26 @@
|
||||||
module.exports.getContract = async function (contractName) {
|
module.exports.getContract = async function (contractName) {
|
||||||
const proxyDeployments =
|
const deployment = require(`../deployments/${hre.network.name}/${contractName}.json`);
|
||||||
require(`../deployments/${hre.network.name}/proxy.json`)[contractName];
|
|
||||||
|
|
||||||
if (!proxyDeployments || !proxyDeployments.length) {
|
if (!deployment) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`No proxy deployments found for "${contractName}" under "${hre.network.name}"`
|
`No deployment found for "${contractName}" under "${hre.network.name}"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const latestDeployment = proxyDeployments[0];
|
console.log(`Using latest deployment for "${deployment.address}":`);
|
||||||
|
|
||||||
return hre.ethers.getContractAt(contractName, latestDeployment.address);
|
return hre.ethers.getContractAt(contractName, deployment.address);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.parseDataURI = function (dataURI) {
|
||||||
|
if (!dataURI.startsWith('data:')) throw new Error('Invalid data URI');
|
||||||
|
const content = dataURI.replace('data:', '');
|
||||||
|
const [type, data] = content.split(';base64,');
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'application/json':
|
||||||
|
return JSON.parse(Buffer.from(data, 'base64').toString('utf-8'));
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported data URI type: ${type}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,20 @@ const getCurrentAddressIfSameBytecode = async (contractName) => {
|
||||||
hre.network.name,
|
hre.network.name,
|
||||||
contractName
|
contractName
|
||||||
));
|
));
|
||||||
return deployData.bytecode === bytecode ? deployData.address : null;
|
|
||||||
|
if (deployData.bytecode === bytecode) {
|
||||||
|
try {
|
||||||
|
const contract = await hre.ethers.getContractAt(
|
||||||
|
contractName,
|
||||||
|
deployData.address
|
||||||
|
);
|
||||||
|
return contract.address;
|
||||||
|
} catch {
|
||||||
|
console.log(
|
||||||
|
`Contract ${contractName} at ${deployData.address} is not deployed`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ import { expect } from 'chai';
|
||||||
import * as hre from 'hardhat';
|
import * as hre from 'hardhat';
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import deploy from '../../../scripts/deploy';
|
import deploy from '../../../scripts/deploy/deploy-fleek-erc721';
|
||||||
import { getImplementationAddress } from '@openzeppelin/upgrades-core';
|
import { getImplementationAddress } from '@openzeppelin/upgrades-core';
|
||||||
import { Contract } from 'ethers';
|
import { Contract } from 'ethers';
|
||||||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||||
import { Errors, TestConstants } from '../contracts/FleekERC721/helpers';
|
import { TestConstants } from '../contracts/FleekERC721/helpers';
|
||||||
|
|
||||||
const taskArgs = {
|
const taskArgs = {
|
||||||
newProxyInstance: false,
|
newProxyInstance: false,
|
||||||
|
|
@ -28,7 +28,7 @@ const getImplementationContract = async (
|
||||||
const deployFixture = async () => {
|
const deployFixture = async () => {
|
||||||
const [owner] = await hre.ethers.getSigners();
|
const [owner] = await hre.ethers.getSigners();
|
||||||
|
|
||||||
const proxy = (await deploy(taskArgs, hre)) as Contract;
|
const proxy = await deploy(taskArgs, hre);
|
||||||
|
|
||||||
const implementation = await getImplementationContract(proxy.address);
|
const implementation = await getImplementationContract(proxy.address);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue