Appearance
Frontend integration
For most apps, prefer the hosted HTTP API at https://ebg-tokenizer.u3dev.deno.net/ so clients send JSON only and do not hold minter keys.
You can also call the factory directly from a web app (e.g. with wagmi) if the connected wallet has the right onchain roles. This page mirrors the shapes used onchain and in the HTTP API; the full tuple includes image_url and certificate_url (see Certificate data model).
wagmi — create collection
typescript
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { factoryAbi } from './abis/factory'
const FACTORY_ADDRESS = '0x...' as const
function CreateCertificate() {
const { writeContract, data: hash, isPending } = useWriteContract()
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
hash,
})
const createCertificate = async () => {
try {
await writeContract({
address: FACTORY_ADDRESS,
abi: factoryAbi,
functionName: 'create_certificate',
args: [
'EBG Cert', // name_ (max 25 chars)
'EBG', // symbol_ (max 5 chars)
'https://api.example.com/metadata/', // base_uri_ (max 80 chars)
],
})
} catch (error) {
console.error('Failed to create certificate:', error)
}
}
return (
<div>
<button
onClick={createCertificate}
disabled={isPending || isConfirming}
>
{isPending ? 'Creating...' : isConfirming ? 'Confirming...' : 'Create certificate'}
</button>
{isSuccess && <p>Certificate collection created.</p>}
</div>
)
}wagmi — mint through factory
mint_certificate takes the collection address, the certificate struct as a tuple, and the recipient address. All ten struct fields must be provided in order.
typescript
function MintCertificate() {
const { writeContract, data: hash, isPending } = useWriteContract()
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
hash,
})
const mintCertificate = async () => {
const certificateData = [
1734567890n, // registration_date
'DLV-001', // delivery_correlative
'John', // participant_names
'Doe', // participant_last_names
'EBG Course', // course_name
40n, // hours_number
10n, // sessions_number
'EBG Academy', // issuing_institution
'https://example.com/img.png', // image_url
'https://example.com/cert.pdf', // certificate_url
] as const
try {
await writeContract({
address: FACTORY_ADDRESS,
abi: factoryAbi,
functionName: 'mint_certificate',
args: ['0x...', certificateData, '0x...'], // certificate_, data_, to_
})
} catch (error) {
console.error('Failed to mint certificate:', error)
}
}
return (
<div>
<button
onClick={mintCertificate}
disabled={isPending || isConfirming}
>
{isPending ? 'Minting...' : isConfirming ? 'Confirming...' : 'Mint certificate'}
</button>
{isSuccess && <p>Certificate minted.</p>}
</div>
)
}ABI snippets
Use the full factory ABI from your block explorer, RPC provider, or contract publisher. Minimal create_certificate and mint_certificate entries for the flows above:
typescript
export const factoryAbi = [
{
inputs: [
{ name: 'name_', type: 'string' },
{ name: 'symbol_', type: 'string' },
{ name: 'base_uri_', type: 'string' },
],
name: 'create_certificate',
outputs: [{ name: '', type: 'address' }],
stateMutability: 'nonpayable',
type: 'function',
},
{
inputs: [
{ name: 'certificate_', type: 'address' },
{
name: 'data_',
type: 'tuple',
components: [
{ name: 'registration_date', type: 'uint256' },
{ name: 'delivery_correlative', type: 'string' },
{ name: 'participant_names', type: 'string' },
{ name: 'participant_last_names', type: 'string' },
{ name: 'course_name', type: 'string' },
{ name: 'hours_number', type: 'uint256' },
{ name: 'sessions_number', type: 'uint256' },
{ name: 'issuing_institution', type: 'string' },
{ name: 'image_url', type: 'string' },
{ name: 'certificate_url', type: 'string' },
],
},
{ name: 'to_', type: 'address' },
],
name: 'mint_certificate',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
] as constFor tuple field order when encoding mint_certificate, see Certificate data model.