Visión General
CreateKit soporta la gestión de listas blancas sofisticadas utilizando árboles de Merkle para la verificación eficiente en términos de gas. Esto te permite crear experiencias de acuñación exclusivas para direcciones específicas manteniendo la escalabilidad y seguridad.Fundamentos de las Listas Blancas
Cómo Funcionan las Listas Blancas
- Generación Fuera de la Cadena: Crear un árbol de Merkle a partir de direcciones en la lista blanca
- Almacenamiento en la Cadena: Almacenar solo la raíz de Merkle en el contrato inteligente
- Verificación de Prueba: Los usuarios proporcionan una prueba de Merkle al acuñar
- Eficiencia de Gas: Los costos de verificación son constantes independientemente del tamaño de la lista blanca
Escalable
Soporta miles de direcciones con costos mínimos de gas
Seguro
Verificación de direcciones garantizada criptográficamente
Flexible
Fácil de generar y actualizar configuraciones de lista blanca
Transparente
Verificable en la cadena sin revelar la lista completa
Configuración de Listas Blancas
Creación Básica de Lista Blanca
Crear Lista Blanca
Copy
Ask AI
import { WhitelistManager } from '@b3dotfun/basemint'
// Definir direcciones en la lista blanca
const whitelistedAddresses = [
{ address: "0x1234567890123456789012345678901234567890" },
{ address: "0x2345678901234567890123456789012345678901" },
{ address: "0x3456789012345678901234567890123456789012" },
{ address: "0x4567890123456789012345678901234567890123" },
{ address: "0x5678901234567890123456789012345678901234" }
]
// Crear gestor de lista blanca
const whitelist = new WhitelistManager(whitelistedAddresses)
// Obtener raíz de Merkle para el despliegue del contrato
const merkleRoot = whitelist.getRoot()
console.log(`Raíz de Merkle: ${merkleRoot}`)
// Verificar que la lista blanca esté construida correctamente
console.log(`La lista blanca contiene ${whitelistedAddresses.length} direcciones`)
Configuración Avanzada de Lista Blanca
Lista Blanca con Metadatos
Copy
Ask AI
// Las entradas de la lista blanca pueden incluir metadatos adicionales
const advancedWhitelist = [
{
address: "0x1234567890123456789012345678901234567890",
allocation: 5, // Máx 5 tokens para esta dirección
tier: "gold"
},
{
address: "0x2345678901234567890123456789012345678901",
allocation: 3,
tier: "silver"
},
{
address: "0x3456789012345678901234567890123456789012",
allocation: 1,
tier: "bronze"
}
]
// Crear lista blanca (solo se usan direcciones para el árbol de Merkle)
const whitelist = new WhitelistManager(
advancedWhitelist.map(entry => ({ address: entry.address }))
)
// Almacenar metadatos por separado para la lógica de la aplicación
const allocationMap = new Map(
advancedWhitelist.map(entry => [entry.address, entry.allocation])
)
Integración de Colecciones
Colección Habilitada para Lista Blanca
Configuración de Colección con Lista Blanca
Copy
Ask AI
import { CollectionManager } from '@b3dotfun/basemint'
// Crear colección con lista blanca habilitada
const whitelistCollection = {
name: "Colección Exclusiva",
symbol: "EXCL",
creator: account.address,
gameOwner: account.address,
// Configuración de lista blanca
isWhitelistEnabled: true,
whitelistMerkleRoot: merkleRoot,
// Configuraciones de la colección
maxSupply: 1000n,
mintPrice: parseEther("0.01"),
maxPerWallet: 3n,
// Opcional: Combinar con acceso basado en tiempo
startTime: BigInt(Math.floor(Date.now() / 1000) + 3600), // La lista blanca comienza en 1 hora
endTime: BigInt(Math.floor(Date.now() / 1000) + 86400 * 7), // Termina en 7 días
}
// Generar firmas y desplegar
const creatorSignature = await collectionManager.generateCreatorSignature(
walletClient,
whitelistCollection
)
const predictedAddress = collectionManager.predictCollectionAddress(
whitelistCollection,
creatorSignature
)
console.log(`La colección de lista blanca se desplegará en: ${predictedAddress}`)
Modelos de Acceso Híbridos
Acceso Fasado
Copy
Ask AI
// Crear colecciones con diferentes fases de acceso
const phasedCollection = {
name: "Colección de Acceso Fasado",
symbol: "PAC",
creator: account.address,
gameOwner: account.address,
// Fase 1: Solo lista blanca (primeras 24 horas)
isWhitelistEnabled: true,
whitelistMerkleRoot: merkleRoot,
startTime: BigInt(Math.floor(Date.now() / 1000)),
// Nota: Para la fase 2 (acceso público), necesitarás lógica adicional
// para deshabilitar la verificación de la lista blanca después de cierto tiempo
}
// En tu aplicación, implementa la lógica de fases
async function checkMintingPhase(collection: any): Promise<'whitelist' | 'public' | 'ended'> {
const now = BigInt(Math.floor(Date.now() / 1000))
const startTime = await collection.startTime()
const endTime = await collection.endTime()
const whitelistPhaseEnd = startTime + 86400n // 24 horas
if (now < startTime) {
throw new Error("La acuñación aún no ha comenzado")
} else if (now < whitelistPhaseEnd) {
return 'whitelist'
} else if (now < endTime) {
return 'public'
} else {
return 'ended'
}
}
Verificación de Lista Blanca
Generación de Pruebas
Generar Pruebas de Merkle
Copy
Ask AI
// Generar prueba para una dirección específica
function generateProofForAddress(whitelist: WhitelistManager, address: string): string[] {
try {
const proof = whitelist.getProof(address)
console.log(`Prueba generada para ${address}:`, proof)
return proof
} catch (error) {
console.error(`Falló al generar la prueba para ${address}:`, error)
throw new Error(`Dirección ${address} no en lista blanca`)
}
}
// Verificar prueba localmente (opcional)
function verifyWhitelistProof(
whitelist: WhitelistManager,
address: string,
proof: string[]
): boolean {
const isValid = whitelist.verify(address, proof)
console.log(`Verificación de prueba para ${address}: ${isValid ? '✅ Válida' : '❌ Inválida'}`)
return isValid
}
// Ejemplo de uso
const userAddress = "0x1234567890123456789012345678901234567890"
const proof = generateProofForAddress(whitelist, userAddress)
const isValid = verifyWhitelistProof(whitelist, userAddress, proof)
Generación de Pruebas en Lote
Generación de Pruebas en Lote
Copy
Ask AI
// Generar pruebas para múltiples direcciones
function generateBatchProofs(
whitelist: WhitelistManager,
addresses: string[]
): Map<string, string[]> {
const proofMap = new Map<string, string[]>()
for (const address of addresses) {
try {
const proof = whitelist.getProof(address)
proofMap.set(address, proof)
console.log(`✅ Prueba generada para ${address}`)
} catch (error) {
console.error(`❌ Falló al generar prueba para ${address}:`, error)
}
}
return proofMap
}
// Generar pruebas para todas las direcciones en la lista blanca
const allAddresses = whitelistedAddresses.map(entry => entry.address)
const allProofs = generateBatchProofs(whitelist, allAddresses)
// Guardar pruebas en un archivo o base de datos para uso en el frontend
const proofData = {
merkleRoot,
proofs: Object.fromEntries(allProofs)
}
// Ejemplo: Guardar en archivo JSON
import { writeFileSync } from 'fs'
writeFileSync('whitelist-proofs.json', JSON.stringify(proofData, null, 2))
Acuñación con Listas Blancas
Acuñación Básica con Lista Blanca
Acuñar con Lista Blanca
Copy
Ask AI
async function mintWithWhitelist(
collection: any,
walletClient: any,
whitelist: WhitelistManager,
quantity: bigint = 1n
) {
const userAddress = walletClient.account.address
try {
// Generar prueba para el usuario
const proof = whitelist.getProof(userAddress)
// Verificar prueba localmente (opcional)
const isValid = whitelist.verify(userAddress, proof)
if (!isValid) {
throw new Error("Prueba de lista blanca inválida")
}
// Obtener precio de acuñación
const mintPrice = await collection.mintPrice()
const totalPrice = mintPrice * quantity
// Acuñar con prueba de lista blanca
const tx = await collection.mint(
walletClient,
quantity,
undefined, // URI de metadatos
totalPrice,
proof // Prueba de lista blanca
)
console.log(`✅ Acuñación con lista blanca exitosa: ${tx}`)
return tx
} catch (error: any) {
if (error.message.includes('Prueba de Merkle inválida')) {
console.error('❌ Dirección no en lista blanca o prueba inválida')
} else {
console.error('❌ Acuñación con lista blanca fallida:', error)
}
throw error
}
}
// Uso
await mintWithWhitelist(collection, walletClient, whitelist, 2n)
Acuñación Avanzada con Lista Blanca
Lógica Avanzada de Lista Blanca
Copy
Ask AI
async function advancedWhitelistMint(
collection: any,
walletClient: any,
whitelist: WhitelistManager,
allocationMap: Map<string, number>,
quantity: bigint
) {
const userAddress = walletClient.account.address
// Verificar la asignación del usuario
const maxAllocation = allocationMap.get(userAddress) || 0
if (maxAllocation === 0) {
throw new Error("Dirección no en lista blanca")
}
// Verificar saldo actual contra asignación
const currentBalance = await collection.balanceOf(userAddress)
const newBalance = currentBalance + quantity
if (newBalance > BigInt(maxAllocation)) {
throw new Error(`Excedería la asignación. Máx: ${maxAllocation}, Actual: ${currentBalance}`)
}
// Generar prueba y acuñar
const proof = whitelist.getProof(userAddress)
const mintPrice = await collection.mintPrice()
const tx = await collection.mint(
walletClient,
quantity,
undefined,
mintPrice * quantity,
proof
)
console.log(`✅ Acuñación avanzada con lista blanca exitosa: ${tx}`)
return tx
}
Integración en el Frontend
Hook de React para Estado de Lista Blanca
Hook useWhitelistStatus
Copy
Ask AI
import { useState, useEffect } from 'react'
import { useAccount } from 'wagmi'
interface WhitelistStatus {
isWhitelisted: boolean
proof: string[] | null
allocation: number
loading: boolean
error: string | null
}
export function useWhitelistStatus(
whitelist: WhitelistManager,
allocationMap?: Map<string, number>
): WhitelistStatus {
const { address } = useAccount()
const [status, setStatus] = useState<WhitelistStatus>({
isWhitelisted: false,
proof: null,
allocation: 0,
loading: true,
error: null
})
useEffect(() => {
async function checkWhitelistStatus() {
if (!address) {
setStatus({
isWhitelisted: false,
proof: null,
allocation: 0,
loading: false,
error: null
})
return
}
try {
setStatus(prev => ({ ...prev, loading: true, error: null }))
// Generar prueba
const proof = whitelist.getProof(address)
const isValid = whitelist.verify(address, proof)
const allocation = allocationMap?.get(address) || 0
setStatus({
isWhitelisted: isValid,
proof: isValid ? proof : null,
allocation,
loading: false,
error: null
})
} catch (error: any) {
setStatus({
isWhitelisted: false,
proof: null,
allocation: 0,
loading: false,
error: error.message
})
}
}
checkWhitelistStatus()
}, [address, whitelist, allocationMap])
return status
}
Componente de Estado de Lista Blanca
Componente WhitelistStatus
Copy
Ask AI
import React from 'react'
import { useWhitelistStatus } from './useWhitelistStatus'
interface WhitelistStatusProps {
whitelist: WhitelistManager
allocationMap?: Map<string, number>
}
export function WhitelistStatus({ whitelist, allocationMap }: WhitelistStatusProps) {
const { isWhitelisted, allocation, loading, error } = useWhitelistStatus(
whitelist,
allocationMap
)
if (loading) {
return <div className="animate-pulse">Verificando estado de lista blanca...</div>
}
if (error) {
return <div className="text-red-500">Error: {error}</div>
}
return (
<div className={`p-4 rounded-lg ${isWhitelisted ? 'bg-green-100' : 'bg-gray-100'}`}>
{isWhitelisted ? (
<div className="text-green-800">
<h3 className="font-bold">✅ En Lista Blanca</h3>
<p>Puedes acuñar hasta {allocation} tokens</p>
</div>
) : (
<div className="text-gray-800">
<h3 className="font-bold">❌ No En Lista Blanca</h3>
<p>Tu dirección no es elegible para la acuñación de lista blanca</p>
</div>
)}
</div>
)
}
Múltiples Listas Blancas
Sistema de Lista Blanca por Niveles
Listas Blancas por Niveles
Copy
Ask AI
// Crear diferentes niveles con distintos beneficios
const goldTierAddresses = [
{ address: "0x1111..." },
{ address: "0x2222..." }
]
const silverTierAddresses = [
{ address: "0x3333..." },
{ address: "0x4444..." }
]
const bronzeTierAddresses = [
{ address: "0x5555..." },
{ address: "0x6666..." }
]
// Crear listas blancas separadas para cada nivel
const goldWhitelist = new WhitelistManager(goldTierAddresses)
const silverWhitelist = new WhitelistManager(silverTierAddresses)
const bronzeWhitelist = new WhitelistManager(bronzeTierAddresses)
// Para el contrato inteligente, podrías combinar todos los niveles
const allTierAddresses = [
...goldTierAddresses,
...silverTierAddresses,
...bronzeTierAddresses
]
const combinedWhitelist = new WhitelistManager(allTierAddresses)
// Lógica de aplicación para beneficios por nivel
const tierBenefits = {
gold: { maxMint: 10, discount: 0.2 },
silver: { maxMint: 5, discount: 0.1 },
bronze: { maxMint: 2, discount: 0.05 }
}
function getTierForAddress(address: string): 'gold' | 'silver' | 'bronze' | null {
if (goldTierAddresses.some(entry => entry.address === address)) return 'gold'
if (silverTierAddresses.some(entry => entry.address === address)) return 'silver'
if (bronzeTierAddresses.some(entry => entry.address === address)) return 'bronze'
return null
}
Acceso por Niveles Basado en Tiempo
Acceso por Niveles Fasado
Copy
Ask AI
async function getActiveTierForTime(timestamp: number): Promise<'gold' | 'silver' | 'bronze' | 'public' | null> {
const phaseStartTime = 1640995200 // Ejemplo de marca de tiempo
const hoursSinceStart = (timestamp - phaseStartTime) / 3600
if (hoursSinceStart < 0) return null // No ha comenzado
if (hoursSinceStart < 1) return 'gold' // Primera hora: solo nivel oro
if (hoursSinceStart < 4) return 'silver' // Próximas 3 horas: oro + plata
if (hoursSinceStart < 24) return 'bronze' // Próximas 20 horas: todos los niveles
return 'public' // Después de 24 horas: acceso público
}
async function mintWithTierAccess