Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 305 lines 11 kB view raw
1/** 2 * Keeps FA2 v4 Contract - Read-Only Tests 3 * 4 * These tests verify the production contract via TzKT API without making any transactions. 5 * Safe to run against mainnet contract: KT1ER1GyoeRNhkv6E57yKbBbEKi5ynKbaH3W 6 */ 7 8import { getContract, CONTRACTS, EXPECTED_STORAGE, stringToBytes } from './helpers/keeps-test-helper.mjs'; 9import { 10 getContractStorage, 11 getContractEntrypoints, 12 getTokenMetadata, 13 getAllTokens, 14 getOperations, 15 getBigMapKeys 16} from './helpers/tzkt-helper.mjs'; 17 18const RUN_KEEPS_NETWORK_TESTS = 19 process.env.RUN_KEEPS_NETWORK_TESTS === 'true' || 20 process.env.RUN_KEEPS_V4_NETWORK_TESTS === 'true'; 21const describeIfNetworkEnabled = RUN_KEEPS_NETWORK_TESTS ? describe : xdescribe; 22 23if (!RUN_KEEPS_NETWORK_TESTS) { 24 console.log( 25 '⏭️ Skipping keeps network read-only tests (set RUN_KEEPS_NETWORK_TESTS=true to enable)' 26 ); 27} 28 29describeIfNetworkEnabled("🔐 Keeps FA2 v4 Contract - Read-Only Tests", () => { 30 let contract, address; 31 const network = 'mainnet'; 32 33 beforeAll(async () => { 34 console.log('\n🧪 Starting Keeps v4 read-only test suite...\n'); 35 console.log(`🎯 Target contract: ${CONTRACTS.mainnet}`); 36 console.log(`🎯 Expected admin: ${EXPECTED_STORAGE.mainnet.administrator}`); 37 ({ contract, address } = await getContract(network, false)); 38 }); 39 40 afterAll(() => { 41 console.log('\n✅ Read-only test suite complete!\n'); 42 }); 43 44 describe("📋 Contract Configuration", () => { 45 it("should have correct contract address", () => { 46 expect(address).toBe(CONTRACTS.mainnet); 47 }); 48 49 it("should have correct administrator", async () => { 50 const storage = await getContractStorage(address, network); 51 expect(storage.administrator).toBe(EXPECTED_STORAGE.mainnet.administrator); 52 }); 53 54 it("should have default royalty of 10%", async () => { 55 const storage = await getContractStorage(address, network); 56 expect(parseInt(storage.default_royalty_bps)).toBe(EXPECTED_STORAGE.mainnet.default_royalty_bps); 57 }); 58 59 it("should not be paused", async () => { 60 const storage = await getContractStorage(address, network); 61 expect(storage.paused).toBe(EXPECTED_STORAGE.mainnet.paused); 62 }); 63 64 it("should have keep_fee configured", async () => { 65 const storage = await getContractStorage(address, network); 66 expect(storage.keep_fee).toBeDefined(); 67 console.log(` 📊 Current keep fee: ${storage.keep_fee} mutez`); 68 }); 69 70 it("should have contract metadata", async () => { 71 const storage = await getContractStorage(address, network); 72 expect(storage.metadata).toBeDefined(); 73 }); 74 75 it("should have contract_metadata_locked flag", async () => { 76 const storage = await getContractStorage(address, network); 77 expect(typeof storage.contract_metadata_locked).toBe('boolean'); 78 }); 79 }); 80 81 describe("🎯 Contract Entrypoints", () => { 82 let entrypoints; 83 84 beforeAll(async () => { 85 entrypoints = await getContractEntrypoints(address, network); 86 }); 87 88 it("should have all 12 custom Keeps entrypoints", () => { 89 const customEntrypoints = [ 90 'keep', 91 'edit_metadata', 92 'lock_metadata', 93 'set_contract_metadata', 94 'lock_contract_metadata', 95 'set_keep_fee', 96 'withdraw_fees', 97 'burn_keep', 98 'pause', 99 'unpause', 100 'set_default_royalty', 101 'admin_transfer' 102 ]; 103 104 const entrypointNames = entrypoints.map(ep => ep.name); 105 customEntrypoints.forEach(name => { 106 expect(entrypointNames).toContain(name); 107 }); 108 109 console.log(` ✅ Found ${customEntrypoints.length} custom entrypoints`); 110 }); 111 112 it("should have all 6 FA2 standard entrypoints", () => { 113 const fa2Entrypoints = [ 114 'transfer', 115 'update_operators', 116 'balance_of', 117 'mint', 118 'burn', 119 'set_administrator' 120 ]; 121 122 const entrypointNames = entrypoints.map(ep => ep.name); 123 fa2Entrypoints.forEach(name => { 124 expect(entrypointNames).toContain(name); 125 }); 126 127 console.log(` ✅ Found ${fa2Entrypoints.length} FA2 standard entrypoints`); 128 }); 129 130 it("should have v4 entrypoints (pause, unpause, set_default_royalty, admin_transfer)", () => { 131 const v4Entrypoints = ['pause', 'unpause', 'set_default_royalty', 'admin_transfer']; 132 const entrypointNames = entrypoints.map(ep => ep.name); 133 134 v4Entrypoints.forEach(name => { 135 expect(entrypointNames).toContain(name); 136 }); 137 138 console.log(` ✅ Found all 4 v4-specific entrypoints`); 139 }); 140 }); 141 142 describe("🪙 Token Metadata", () => { 143 it("should have minted tokens", async () => { 144 const storage = await getContractStorage(address, network); 145 const nextTokenId = parseInt(storage.next_token_id); 146 147 expect(nextTokenId).toBeGreaterThan(0); 148 console.log(` 📊 Total tokens minted: ${nextTokenId}`); 149 }); 150 151 it("should fetch token metadata from TzKT", async () => { 152 const storage = await getContractStorage(address, network); 153 const nextTokenId = parseInt(storage.next_token_id); 154 155 if (nextTokenId > 0) { 156 // Fetch first token 157 const tokens = await getTokenMetadata(address, 0, network); 158 159 expect(tokens.length).toBeGreaterThan(0); 160 expect(tokens[0].metadata).toBeDefined(); 161 console.log(` ✅ Token #0 metadata: ${tokens[0].metadata.name}`); 162 } else { 163 console.log(` ⚠️ No tokens minted yet, skipping metadata test`); 164 } 165 }); 166 167 it("should have proper token metadata structure (TZIP-21)", async () => { 168 const storage = await getContractStorage(address, network); 169 const nextTokenId = parseInt(storage.next_token_id); 170 171 if (nextTokenId > 0) { 172 const tokens = await getTokenMetadata(address, 0, network); 173 const metadata = tokens[0].metadata; 174 175 // Check TZIP-21 required fields 176 expect(metadata.name).toBeDefined(); 177 expect(metadata.symbol).toBeDefined(); 178 expect(metadata.decimals).toBeDefined(); 179 180 // Check Keeps-specific fields 181 expect(metadata.artifactUri).toBeDefined(); 182 expect(metadata.displayUri).toBeDefined(); 183 expect(metadata.thumbnailUri).toBeDefined(); 184 185 console.log(` ✅ Token metadata follows TZIP-21 standard`); 186 } 187 }); 188 }); 189 190 describe("💾 Storage BigMaps", () => { 191 it("should have content_hashes bigmap", async () => { 192 const storage = await getContractStorage(address, network); 193 expect(storage.content_hashes).toBeDefined(); 194 console.log(` 📊 Content hashes bigmap ID: ${storage.content_hashes}`); 195 }); 196 197 it("should have token_creators bigmap", async () => { 198 const storage = await getContractStorage(address, network); 199 expect(storage.token_creators).toBeDefined(); 200 console.log(` 📊 Token creators bigmap ID: ${storage.token_creators}`); 201 }); 202 203 it("should have metadata_locked bigmap", async () => { 204 const storage = await getContractStorage(address, network); 205 expect(storage.metadata_locked).toBeDefined(); 206 console.log(` 📊 Metadata locked bigmap ID: ${storage.metadata_locked}`); 207 }); 208 209 it("should have ledger bigmap", async () => { 210 const storage = await getContractStorage(address, network); 211 expect(storage.ledger).toBeDefined(); 212 console.log(` 📊 Ledger bigmap ID: ${storage.ledger}`); 213 }); 214 215 it("should have token_metadata bigmap", async () => { 216 const storage = await getContractStorage(address, network); 217 expect(storage.token_metadata).toBeDefined(); 218 console.log(` 📊 Token metadata bigmap ID: ${storage.token_metadata}`); 219 }); 220 221 it("should have operators bigmap", async () => { 222 const storage = await getContractStorage(address, network); 223 expect(storage.operators).toBeDefined(); 224 console.log(` 📊 Operators bigmap ID: ${storage.operators}`); 225 }); 226 }); 227 228 describe("📜 Operation History", () => { 229 it("should have mint operations (keep entrypoint)", async () => { 230 const operations = await getOperations(address, 'keep', network, 5); 231 232 if (operations.length > 0) { 233 console.log(` ✅ Found ${operations.length} mint operations`); 234 console.log(` 📊 Latest mint: ${operations[0].hash} (block ${operations[0].level})`); 235 } else { 236 console.log(` ⚠️ No mint operations found yet`); 237 } 238 }); 239 240 it("should verify all operations were successful", async () => { 241 const operations = await getOperations(address, 'keep', network, 10); 242 243 operations.forEach(op => { 244 expect(op.status).toBe('applied'); 245 }); 246 247 if (operations.length > 0) { 248 console.log(` ✅ All ${operations.length} operations successful`); 249 } 250 }); 251 252 it("should have operation sender information", async () => { 253 const operations = await getOperations(address, 'keep', network, 1); 254 255 if (operations.length > 0) { 256 const op = operations[0]; 257 expect(op.sender).toBeDefined(); 258 expect(op.sender.address).toBeDefined(); 259 console.log(` 📊 Latest mint sender: ${op.sender.address}`); 260 } 261 }); 262 }); 263 264 describe("🔍 Contract Verification", () => { 265 it("should be a valid FA2 contract", async () => { 266 const storage = await getContractStorage(address, network); 267 268 // Check FA2 required storage 269 expect(storage.ledger).toBeDefined(); 270 expect(storage.operators).toBeDefined(); 271 expect(storage.token_metadata).toBeDefined(); 272 273 console.log(` ✅ Contract has FA2 storage structure`); 274 }); 275 276 it("should have v4-specific storage (pause, royalty)", async () => { 277 const storage = await getContractStorage(address, network); 278 279 // v4 specific fields 280 expect(storage.paused).toBeDefined(); 281 expect(storage.default_royalty_bps).toBeDefined(); 282 283 console.log(` ✅ Contract has v4-specific storage fields`); 284 }); 285 286 it("should have creator tracking (v3 feature)", async () => { 287 const storage = await getContractStorage(address, network); 288 expect(storage.token_creators).toBeDefined(); 289 console.log(` ✅ Contract has creator tracking (v3 feature)`); 290 }); 291 292 it("should have content hash deduplication (v3 feature)", async () => { 293 const storage = await getContractStorage(address, network); 294 expect(storage.content_hashes).toBeDefined(); 295 console.log(` ✅ Contract has content hash deduplication (v3 feature)`); 296 }); 297 298 it("should have metadata locking support (v3 feature)", async () => { 299 const storage = await getContractStorage(address, network); 300 expect(storage.metadata_locked).toBeDefined(); 301 expect(storage.contract_metadata_locked).toBeDefined(); 302 console.log(` ✅ Contract has metadata locking support (v3 feature)`); 303 }); 304 }); 305});