@paulstinchcombe/kami721c-sdk
Version:
SDK for interacting with KAMI721C NFT contracts
179 lines (178 loc) • 10.3 kB
JavaScript
;
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 console_colors_1 = require("../utils/console-colors");
const dotenv_1 = __importDefault(require("dotenv"));
dotenv_1.default.config();
// === Configuration ===
const RPC_URL = process.env.RPC_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const USDC_ADDRESS = process.env.USDC_ADDRESS;
const RECEIVER_1 = process.env.ROYALTY_RECEIVER_1;
const RECEIVER_2 = process.env.ROYALTY_RECEIVER_2;
const RECEIVER_3 = process.env.ROYALTY_RECEIVER_3;
const BASE_RENTAL_PRICE = process.env.BASE_RENTAL_PRICE_PER_DAY ? BigInt(process.env.BASE_RENTAL_PRICE_PER_DAY) : 2000000n; // Default 2 USDC
// Minimal ABI for USDC interactions
const USDC_ABI = [
'function approve(address spender, uint256 amount) external returns (bool)',
'function allowance(address owner, address spender) external view returns (uint256)',
'function decimals() external view returns (uint8)',
];
// --- 1. Deploy Contract Function ---
async function deployContract(wallet) {
console_colors_1.colorLog.section('1. Deploying Contract');
if (!USDC_ADDRESS)
throw new Error('USDC_ADDRESS environment variable is required.');
const factory = new KAMI721CFactory_1.KAMI721CFactory(wallet);
const platformAddress = process.env.PLATFORM_ADDRESS || wallet.address;
const platformCommission = process.env.PLATFORM_COMMISSION_PERCENTAGE ? parseInt(process.env.PLATFORM_COMMISSION_PERCENTAGE) : 500; // 5%
const initialMintPrice = process.env.MINT_PRICE ? BigInt(process.env.MINT_PRICE) : 1000000n; // 1 USDC
const name = process.env.CONTRACT_NAME || 'KAMI Setup Example';
const symbol = process.env.CONTRACT_SYMBOL || 'KSE';
const baseURI = process.env.BASE_URI || 'https://api.example.com/setup/';
console.log('Deploying upgradeable contract via proxy with parameters:');
console.log((0, console_colors_1.formatKeyValue)('USDC Address', USDC_ADDRESS));
console.log((0, console_colors_1.formatKeyValue)('Name', name));
console.log((0, console_colors_1.formatKeyValue)('Symbol', symbol));
console.log((0, console_colors_1.formatKeyValue)('Base URI', baseURI));
console.log((0, console_colors_1.formatKeyValue)('Initial Mint Price', `${ethers_1.ethers.formatUnits(initialMintPrice, 6)} USDC`));
console.log((0, console_colors_1.formatKeyValue)('Platform Address', platformAddress));
console.log((0, console_colors_1.formatKeyValue)('Platform Commission', `${platformCommission / 100}%`));
console.log((0, console_colors_1.formatKeyValue)('Initial Owner', wallet.address));
const nftContract = await factory.deployUpgradeable(USDC_ADDRESS, name, symbol, baseURI, initialMintPrice, platformAddress, platformCommission, wallet.address);
const proxyAddress = nftContract.getAddress();
console_colors_1.colorLog.success(`Contract deployed successfully at proxy address: ${console_colors_1.logStyles.address(proxyAddress)}`);
return nftContract;
}
// --- 2. Set Royalties Function ---
async function setRoyalties(nftContract, receivers) {
console_colors_1.colorLog.section('2. Setting Royalties');
if (receivers.length !== 3) {
throw new Error('This function expects exactly 3 receiver addresses.');
}
// Assuming equal split (3333 basis points each, summing to 9999)
const royaltyData = [
{ receiver: receivers[0], feeNumerator: 3333n },
{ receiver: receivers[1], feeNumerator: 3333n },
{ receiver: receivers[2], feeNumerator: 3333n },
];
const transferRoyaltyPercentage = 1000; // 10% for transfers
console.log(`Setting mint royalties for 3 receivers: ${receivers.join(', ')}`);
const mintTx = await nftContract.setMintRoyalties(royaltyData);
console.log('Mint royalties transaction sent:', mintTx.hash);
await mintTx.wait();
console_colors_1.colorLog.success('Mint royalties set successfully.');
console.log(`Setting transfer royalties for 3 receivers: ${receivers.join(', ')}`);
const transferTx = await nftContract.setTransferRoyalties(royaltyData);
console.log('Transfer royalties transaction sent:', transferTx.hash);
await transferTx.wait();
console_colors_1.colorLog.success('Transfer royalties set successfully.');
console.log(`Setting transfer royalty percentage to ${transferRoyaltyPercentage / 100}%...`);
const percentageTx = await nftContract.setRoyaltyPercentage(transferRoyaltyPercentage);
console.log('Royalty percentage transaction sent:', percentageTx.hash);
await percentageTx.wait();
console_colors_1.colorLog.success('Transfer royalty percentage set successfully.');
}
// --- 3. Mint Token Function ---
async function mintToken(nftContract, wallet) {
console_colors_1.colorLog.section('3. Minting Token');
if (!USDC_ADDRESS)
throw new Error('USDC_ADDRESS needed for minting.');
const mintPrice = await nftContract.mintPrice();
console.log(`Mint price: ${ethers_1.ethers.formatUnits(mintPrice, 6)} USDC`);
const usdcContract = new ethers_1.Contract(USDC_ADDRESS, USDC_ABI, wallet);
const decimals = await usdcContract.decimals();
// Check allowance
const allowance = await usdcContract.allowance(wallet.address, nftContract.getAddress());
console.log(`Current USDC allowance: ${ethers_1.ethers.formatUnits(allowance, decimals)} USDC`);
if (allowance < mintPrice) {
console.log('Approving USDC spend...');
const approveTx = await usdcContract.approve(nftContract.getAddress(), mintPrice);
console.log('Approval transaction sent:', approveTx.hash);
await approveTx.wait();
console_colors_1.colorLog.success('USDC Approved');
}
else {
console.log('Sufficient USDC allowance already set.');
}
// Mint
console.log('Sending mint transaction...');
const mintTx = await nftContract.mint();
console.log('Mint transaction sent:', mintTx.hash);
const receipt = await mintTx.wait();
console_colors_1.colorLog.success(`Token minted successfully in block ${receipt?.blockNumber}`);
// Determine token ID (simplistic approach)
const totalSupply = await nftContract.totalSupply();
const tokenId = totalSupply > 0n ? totalSupply - 1n : 0n;
console.log(`Minted token ID (estimated): ${tokenId}`);
return tokenId;
}
// --- 4. Prepare for Sale Function ---
async function prepareForSale(nftContract, tokenId) {
console_colors_1.colorLog.section('4. Preparing Token for Sale');
console.log(`Approving contract ${nftContract.getAddress()} to manage token ID ${tokenId}...`);
// The owner calls approve, allowing the contract to transfer the token during sellToken
const approveTx = await nftContract.approve(nftContract.getAddress(), tokenId);
console.log('Approval transaction sent:', approveTx.hash);
await approveTx.wait();
console_colors_1.colorLog.success(`Token ${tokenId} approved for sale via contract.`);
console.log('(Note: Actual sale price is set when calling sellToken)');
}
// --- 5. Log Rental Parameters Function ---
async function logRentalParameters(nftContract, basePricePerDay) {
console_colors_1.colorLog.section('5. Logging Rental Parameters');
const platformCommPercentage = await nftContract.getPlatformCommissionPercentage();
const commissionAmount = (basePricePerDay * platformCommPercentage) / 10000n;
const totalRentalPricePerDay = basePricePerDay + commissionAmount;
console.log('Example Rental Parameters (for 1 day):');
console.log((0, console_colors_1.formatKeyValue)('Base Rental Price', `${ethers_1.ethers.formatUnits(basePricePerDay, 6)} USDC`));
console.log((0, console_colors_1.formatKeyValue)('Platform Commission', `${Number(platformCommPercentage) / 100}%`));
console.log((0, console_colors_1.formatKeyValue)('Commission Amount', `${ethers_1.ethers.formatUnits(commissionAmount, 6)} USDC`));
console.log((0, console_colors_1.formatKeyValue)('Total Price (Renter Pays)', `${ethers_1.ethers.formatUnits(totalRentalPricePerDay, 6)} USDC`));
console.log('(Note: Actual rental is initiated by calling rentToken with duration and total price)');
}
// --- Main Orchestration Function ---
async function main() {
console.log('Starting KAMI721C Deployment and Setup Script...');
if (!RPC_URL || !PRIVATE_KEY) {
throw new Error('RPC_URL and PRIVATE_KEY environment variables are required.');
}
if (!RECEIVER_1 || !RECEIVER_2 || !RECEIVER_3) {
throw new Error('ROYALTY_RECEIVER_1, ROYALTY_RECEIVER_2, and ROYALTY_RECEIVER_3 environment variables are required.');
}
const provider = new ethers_1.ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers_1.ethers.Wallet(PRIVATE_KEY, provider);
console_colors_1.colorLog.info(`Using wallet: ${console_colors_1.logStyles.address(wallet.address)} on network ${(await provider.getNetwork()).name}`);
try {
// 1. Deploy
const nftContract = await deployContract(wallet);
// Wait a moment for chain/indexer
await new Promise((resolve) => setTimeout(resolve, 3000));
// 2. Set Royalties
const royaltyReceivers = [RECEIVER_1, RECEIVER_2, RECEIVER_3];
await setRoyalties(nftContract, royaltyReceivers);
// 3. Mint Token
const mintedTokenId = await mintToken(nftContract, wallet);
// 4. Prepare for Sale
await prepareForSale(nftContract, mintedTokenId);
// 5. Log Rental Parameters
await logRentalParameters(nftContract, BASE_RENTAL_PRICE);
console_colors_1.colorLog.section('Setup Complete!');
console.log(`Contract Address: ${nftContract.getAddress()}`);
console.log(`Minted Token ID: ${mintedTokenId}`);
}
catch (error) {
console_colors_1.colorLog.error('Script failed:');
console.error(error.message);
if (error.reason)
console.error('Reason:', error.reason);
if (error.data)
console.error('Data:', error.data);
process.exit(1);
}
}
main();