UNPKG

@paulstinchcombe/kami721c-sdk

Version:

SDK for interacting with KAMI721C NFT contracts

221 lines (220 loc) 11.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ethers_1 = require("ethers"); const KAMI721CFactory_1 = require("../factories/KAMI721CFactory"); const dotenv_1 = __importDefault(require("dotenv")); dotenv_1.default.config(); const IERC20_ABI = [ 'function approve(address spender, uint256 amount) returns (bool)', 'function balanceOf(address account) view returns (uint256)', 'function decimals() view returns (uint8)', 'function transfer(address to, uint256 amount) returns (bool)', 'function allowance(address owner, address spender) view returns (uint256)', ]; async function main() { try { // Get provider and wallet const provider = new ethers_1.ethers.JsonRpcProvider(process.env.RPC_URL); const wallet = new ethers_1.ethers.Wallet(process.env.PRIVATE_KEY, provider); console.log(`Connected with wallet: ${wallet.address}`); // Get starting nonce const startNonce = await wallet.getNonce(); console.log(`Starting nonce: ${startNonce}`); // Deploy a new contract instance const factory = new KAMI721CFactory_1.KAMI721CFactory(wallet); const nftContract = await factory.deploy(process.env.USDC_ADDRESS, 'KAMI Special NFT Collection', 'KAMI', 'https://api.kami.com/nft/', 1000000n, // 1 USDC mint price wallet.address, // Platform address 500 // 5% platform commission ); console.log(`Contract deployed at: ${nftContract.getAddress()}`); console.log(`Contract: ${await nftContract.name()}`); console.log(`Total supply: ${await nftContract.totalSupply()}`); // Create renter wallet const renterWallet = ethers_1.ethers.Wallet.createRandom().connect(provider); console.log(`Created renter wallet: ${renterWallet.address}`); // Fund renter wallet with ETH for gas const fundingTx = await wallet.sendTransaction({ to: renterWallet.address, value: ethers_1.ethers.parseEther('0.01'), }); await fundingTx.wait(); console.log('Funded renter wallet with 0.01 ETH for gas'); // Get USDC contract const usdcAddress = process.env.USDC_ADDRESS; const usdcContract = new ethers_1.ethers.Contract(usdcAddress, IERC20_ABI, wallet); const renterUsdcContract = new ethers_1.ethers.Contract(usdcAddress, IERC20_ABI, renterWallet); // Get mint price const mintPrice = await nftContract.mintPrice(); const decimals = await usdcContract.decimals(); console.log(`Mint price: ${mintPrice} USDC`); // Approve USDC spending for minting console.log('Approving USDC spending for minting...'); const approvalTx = await usdcContract.approve(nftContract.getAddress(), mintPrice); await approvalTx.wait(); console.log('USDC spending approved for minting'); // Mint a token console.log('Minting a token...'); const mintTx = await nftContract.mint(); await mintTx.wait(); console.log('Token minted successfully'); // Find the minted token const tokenId = 0; // First token minted console.log(`Using token #${tokenId}`); // Get owner's USDC balance const ownerBalance = await usdcContract.balanceOf(wallet.address); console.log(`Owner USDC balance: ${ethers_1.ethers.formatUnits(ownerBalance, decimals)} USDC`); // Set up rental parameters const rentalDuration = 86400; // 1 day in seconds const baseRentalPrice = ethers_1.ethers.parseUnits('1.0', decimals); // 1.0 USDC // Calculate total rental price including platform commission const platformCommission = await nftContract.getPlatformCommissionPercentage(); const platformCommissionAmount = (baseRentalPrice * platformCommission) / 10000n; const totalRentalPrice = baseRentalPrice + platformCommissionAmount; console.log(`Base rental price: ${ethers_1.ethers.formatUnits(baseRentalPrice, decimals)} USDC`); console.log(`Platform commission (${Number(platformCommission) / 100}%): ${ethers_1.ethers.formatUnits(platformCommissionAmount, decimals)} USDC`); console.log(`Total rental price: ${ethers_1.ethers.formatUnits(totalRentalPrice, decimals)} USDC`); // Transfer enough USDC to cover rental price and platform commission const transferAmount = totalRentalPrice; console.log(`Transferring ${ethers_1.ethers.formatUnits(transferAmount, decimals)} USDC to renter...`); const transferTx = await usdcContract.transfer(renterWallet.address, transferAmount); await transferTx.wait(); console.log('USDC transferred to renter'); // Get renter's USDC balance const renterInitialBalance = await usdcContract.balanceOf(renterWallet.address); console.log(`Renter USDC balance: ${ethers_1.ethers.formatUnits(renterInitialBalance, decimals)} USDC`); // Approve USDC spending for rental console.log('Approving USDC spending for rental...'); const rentalApprovalTx = await renterUsdcContract.approve(nftContract.getAddress(), totalRentalPrice); await rentalApprovalTx.wait(); console.log('USDC spending approved for rental'); console.log(`Token #${tokenId} exists and is owned by: ${await nftContract.ownerOf(tokenId)}`); console.log(`Renter starting nonce: ${await renterWallet.getNonce()}`); // Check and grant necessary roles const ownerRole = await nftContract.OWNER_ROLE(); const platformRole = await nftContract.PLATFORM_ROLE(); const hasOwnerRole = await nftContract.hasRole(ownerRole, wallet.address); const hasPlatformRole = await nftContract.hasRole(platformRole, wallet.address); console.log(`Wallet has OWNER_ROLE: ${hasOwnerRole}`); console.log(`Wallet has PLATFORM_ROLE: ${hasPlatformRole}`); // Grant roles if needed if (!hasOwnerRole) { console.log('Granting OWNER_ROLE to wallet...'); const grantOwnerTx = await nftContract.grantRole(ownerRole, wallet.address); await grantOwnerTx.wait(); console.log('OWNER_ROLE granted successfully'); } if (!hasPlatformRole) { console.log('Granting PLATFORM_ROLE to wallet...'); const grantPlatformTx = await nftContract.grantRole(platformRole, wallet.address); await grantPlatformTx.wait(); console.log('PLATFORM_ROLE granted successfully'); } // Attempt to rent the token directly console.log(`Attempting to rent token #${tokenId}...`); try { // Check rental conditions console.log('Checking rental conditions...'); // 1. Verify token exists and get owner console.log(`Checking if token #${tokenId} exists...`); try { const tokenOwner = await nftContract.ownerOf(tokenId); console.log(`Token owner: ${tokenOwner}`); // 2. Verify renter is not the token owner if (renterWallet.address === tokenOwner) { throw new Error('Renter cannot be the token owner'); } console.log('Renter is not the token owner ✓'); // 3. Check USDC allowance const allowance = await usdcContract.allowance(renterWallet.address, nftContract.getAddress()); console.log(`Current USDC allowance: ${ethers_1.ethers.formatUnits(allowance, decimals)} USDC`); if (allowance < totalRentalPrice) { throw new Error('Insufficient USDC allowance'); } console.log('USDC allowance is sufficient ✓'); // 4. Check USDC balance const renterBalance = await usdcContract.balanceOf(renterWallet.address); console.log(`Renter USDC balance: ${ethers_1.ethers.formatUnits(renterBalance, decimals)} USDC`); if (renterBalance < totalRentalPrice) { throw new Error('Insufficient USDC balance'); } console.log('USDC balance is sufficient ✓'); // 5. Try to check if token is already rented try { const isRented = await nftContract.isRented(tokenId); console.log(`Token rental status: ${isRented ? 'Rented' : 'Not rented'}`); if (isRented) { throw new Error('Token is already rented'); } console.log('Token is available for rent ✓'); // 6. Attempt the rental console.log('All conditions met, attempting rental...'); try { const rentalTx = await nftContract.connect(renterWallet).rentToken(tokenId, rentalDuration, totalRentalPrice); console.log('Rental transaction sent:', rentalTx.hash); const receipt = await rentalTx.wait(); console.log('Rental transaction confirmed:', receipt.hash); // Verify the rental was successful const newRentalStatus = await nftContract.isRented(tokenId); console.log(`Token is now rented: ${newRentalStatus}`); } catch (error) { console.error('Failed to perform rental operation:', error); if (error.data) { console.error('Error data:', error.data); } if (error.transaction) { console.error('Transaction data:', error.transaction); } if (error.receipt) { console.error('Transaction receipt:', error.receipt); } throw error; } } catch (error) { console.error('Failed to check rental status:', error); if (error.data) { console.error('Rental status error data:', error.data); } if (error.transaction) { console.error('Rental status transaction data:', error.transaction); } throw error; } } catch (error) { console.error('Failed to verify token existence:', error); if (error.data) { console.error('Token existence error data:', error.data); } if (error.transaction) { console.error('Token existence transaction data:', error.transaction); } throw error; } } catch (error) { console.error('Failed to perform rental operation:', error); if (error.data) { console.error('Error data:', error.data); } if (error.transaction) { console.error('Transaction data:', error.transaction); } throw error; } } catch (error) { console.error('Error:', error); if (error.data) { console.error('Error data:', error.data); } if (error.transaction) { console.error('Transaction:', error.transaction); } } } main();