Skip to content

Commit d3a5d95

Browse files
[FEATRUE DONE] AI whisperer
1 parent 33b0a11 commit d3a5d95

File tree

6 files changed

+114
-0
lines changed

6 files changed

+114
-0
lines changed

Diff for: docs/abi/AIWhispererNFT.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"type":"constructor","inputs":[{"name":"baseTokenURI_","type":"string","internalType":"string"},{"name":"minter_","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"approve","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"balanceOf","inputs":[{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getApproved","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"isApprovedForAll","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"minter","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"ownerOf","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"safeTransferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"safeTransferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setApprovalForAll","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setBaseURI","inputs":[{"name":"baseTokenURI_","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setMinter","inputs":[{"name":"newMinter","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"tokenURI","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"ApprovalForAll","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Minted","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"MinterUpdated","inputs":[{"name":"oldMinter","type":"address","indexed":true,"internalType":"address"},{"name":"newMinter","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false}]

Diff for: docs/deploy/cyber_testnet-111557560/contract.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@
2424
| CyberNFT(Impl) | 0xb8776d0b58ad7cd1a78f4ee8e7fb65d28ebd322c |
2525
| CyberNFT(Proxy) | 0x60a1b9c6900c6cef0e08b939cc00635ad7df02a1 |
2626
| CyberNFTV2(Impl) | 0x2079739052cb3bb9b8d1cb783ac9afc906b3a857 |
27+
| AIWhispererNFT | 0x182ea3daa2182ca25d933fb9a6936f61b0f6aae4 |

Diff for: misc/gen_abi.ts

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const writeAbi = async () => {
2929
"CyberNFTV2.sol/CyberNFTV2.json",
3030
"CyberMintNFTRelayHook.sol/CyberMintNFTRelayHook.json",
3131
"CyberIDPermissionedRelayHook.sol/CyberIDPermissionedRelayHook.json",
32+
"AIWhispererNFT.sol/AIWhispererNFT.json",
3233
];
3334
const ps = folders.map(async (file) => {
3435
const f = await fs.readFile(path.join("./out", file), "utf8");

Diff for: package.json

+2
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@
252252
"deploy_work_in_crypto_nft:op": "source .env.op.owner && FOUNDRY_PROFILE=prd forge script script/DeployWorkInCryptoNFT.s.sol:DeployWorkInCryptoNFT --rpc-url $RPC_URL --private-key $PRIVATE_KEY --slow --broadcast --verify --etherscan-api-key $API_KEY -vvv",
253253
"deploy_work_in_crypto_nft:cyber_testnet": "source .env.cyber_testnet && FOUNDRY_PROFILE=stg forge script script/DeployWorkInCryptoNFT.s.sol:DeployWorkInCryptoNFT --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --slow --verify --verifier blockscout --verifier-url https://api.socialscan.io/cyber-testnet/v1/explorer/command_api/contract --chain-id 111557560 -vvv",
254254
"deploy_work_in_crypto_nft:cyber": "source .env.cyber && FOUNDRY_PROFILE=prd forge script script/DeployWorkInCryptoNFT.s.sol:DeployWorkInCryptoNFT --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --slow --verify --verifier blockscout --verifier-url https://api.socialscan.io/cyber/v1/explorer/command_api/contract --chain-id 7560 -vvv",
255+
"deploy_ai_whisperer_nft:cyber_testnet": "source .env.cyber_testnet.owner && FOUNDRY_PROFILE=stg forge script script/DeployAIWhisperer.s.sol:DeployAIWhisperer --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --slow --verify --verifier blockscout --verifier-url https://api.socialscan.io/cyber-testnet/v1/explorer/command_api/contract --chain-id 111557560 -vvv",
256+
"deploy_ai_whisperer_nft:cyber": "source .env.cyber.owner && FOUNDRY_PROFILE=prd forge script script/DeployAIWhisperer.s.sol:DeployAIWhisperer --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --slow --verify --verifier blockscout --verifier-url https://api.socialscan.io/cyber/v1/explorer/command_api/contract --chain-id 7560 -vvv",
255257
"set_state:amoy": "source .env.amoy.owner && FOUNDRY_PROFILE=stg forge script script/SetInitialState.s.sol:SetInitialState --rpc-url $RPC_URL --private-key $PRIVATE_KEY --with-gas-price 5gwei --broadcast --slow -vvv",
256258
"set_state:imx_testnet": "source .env.imx_testnet.owner && FOUNDRY_PROFILE=stg forge script script/SetInitialState.s.sol:SetInitialState --rpc-url $RPC_URL --private-key $PRIVATE_KEY --with-gas-price 11gwei --legacy --broadcast --slow -vvv"
257259
},

Diff for: script/DeployAIWhisperer.s.sol

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
pragma solidity 0.8.14;
4+
5+
import "forge-std/Script.sol";
6+
import { DeploySetting } from "./libraries/DeploySetting.sol";
7+
import { LibDeploy } from "./libraries/LibDeploy.sol";
8+
9+
import { AIWhispererNFT } from "../src/periphery/AIWhispererNFT.sol";
10+
11+
contract DeployAIWhisperer is Script, DeploySetting {
12+
function run() external {
13+
_setDeployParams();
14+
vm.startBroadcast();
15+
16+
if (block.chainid == DeploySetting.CYBER) {
17+
AIWhispererNFT nft = new AIWhispererNFT(
18+
"https://metadata.cyberconnect.dev/nfts/aiwhisperer/",
19+
0x0e3Ba6BE9b3AAf4c6dE0C9AEe2b2c565E29437Ae
20+
);
21+
LibDeploy._write(vm, "AIWhispererNFT", address(nft));
22+
} else if (block.chainid == DeploySetting.CYBER_TESTNET) {
23+
AIWhispererNFT nft = new AIWhispererNFT(
24+
"https://metadata.stg.cyberconnect.dev/nfts/aiwhisperer/",
25+
0x0e3Ba6BE9b3AAf4c6dE0C9AEe2b2c565E29437Ae
26+
);
27+
LibDeploy._write(vm, "AIWhispererNFT", address(nft));
28+
}
29+
vm.stopBroadcast();
30+
}
31+
}

Diff for: src/periphery/AIWhispererNFT.sol

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
pragma solidity 0.8.14;
4+
5+
import { ERC721 } from "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
6+
import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol";
7+
import { Strings } from "openzeppelin-contracts/contracts/utils/Strings.sol";
8+
9+
contract AIWhispererNFT is ERC721, Ownable {
10+
using Strings for uint256;
11+
12+
/*//////////////////////////////////////////////////////////////
13+
EVENTS
14+
//////////////////////////////////////////////////////////////*/
15+
16+
event Minted(address indexed to, uint256 indexed tokenId);
17+
event MinterUpdated(address indexed oldMinter, address indexed newMinter);
18+
19+
/*//////////////////////////////////////////////////////////////
20+
STORAGE
21+
//////////////////////////////////////////////////////////////*/
22+
23+
string private _baseTokenURI;
24+
address public minter;
25+
uint256 public totalSupply;
26+
27+
/*//////////////////////////////////////////////////////////////
28+
CONSTRUCTOR
29+
//////////////////////////////////////////////////////////////*/
30+
31+
constructor(
32+
string memory baseTokenURI_,
33+
address minter_
34+
) ERC721("AI Whisperer", "AIWHISPERER") {
35+
_baseTokenURI = baseTokenURI_;
36+
minter = minter_;
37+
}
38+
39+
/*//////////////////////////////////////////////////////////////
40+
EXTERNAL
41+
//////////////////////////////////////////////////////////////*/
42+
43+
function mint(address to, uint256 tokenId) external {
44+
require(msg.sender == minter, "NOT_MINTER");
45+
46+
_mint(to, tokenId);
47+
totalSupply++;
48+
emit Minted(to, tokenId);
49+
}
50+
51+
/*//////////////////////////////////////////////////////////////
52+
OVERRIDE
53+
//////////////////////////////////////////////////////////////*/
54+
55+
function tokenURI(
56+
uint256 tokenId
57+
) public view override returns (string memory) {
58+
_requireMinted(tokenId);
59+
return
60+
string(
61+
abi.encodePacked(_baseTokenURI, tokenId.toString(), ".json")
62+
);
63+
}
64+
65+
/*//////////////////////////////////////////////////////////////
66+
ONLY OWNER
67+
//////////////////////////////////////////////////////////////*/
68+
69+
function setMinter(address newMinter) external onlyOwner {
70+
address oldMinter = minter;
71+
minter = newMinter;
72+
emit MinterUpdated(oldMinter, newMinter);
73+
}
74+
75+
function setBaseURI(string memory baseTokenURI_) external onlyOwner {
76+
_baseTokenURI = baseTokenURI_;
77+
}
78+
}

0 commit comments

Comments
 (0)