Skip to main content

🧡 Mint ERC-1155 NFT with Documents

Welcome to the complete guide for the "Mint ERC-1155 NFT with Documents" workflow for the Token City API.

This workflow enables you to upload documents associated with NFTs, generate cryptographic signatures, and mint ERC-1155 tokens on the blockchain with verifiable document references.

🌟 Objective: Mint ERC-1155 tokens with associated documentation (invoices, certificates, images, etc.) securely stored on Arweave and linked on-chain.


πŸ“š OpenAPI Documentation​


✨ Workflow Summary​

This workflow automates the complete process of minting ERC-1155 NFTs with document verification:

  1. πŸ”Ή Upload documents (images, certificates, invoices) to Arweave
  2. πŸ”Ή Generate EIP-712 typed data linking the documents to the mint
  3. πŸ”Ή Sign the typed data using a custodian account
  4. πŸ”Ή Execute the mint transaction on blockchain

Prerequisites:

πŸ”Ή You have a custodian account with minting permissions πŸ”Ή You have the physical asset metadata (for gold/silver NFTs)


🏷️ ERC-1155 Token Standard​

ERC-1155 is a multi-token standard that allows:

  • Fungibility: Multiple identical tokens under the same token ID
  • Semi-Fungibility: Each token ID can represent a unique asset class
  • Batch Operations: Mint, transfer, or burn multiple token types in one transaction
  • Document Linking: Associate metadata and documents with each token ID

πŸ“‹ Workflow Steps Table​

StepAPI OperationMethodParametersOutputsDescription
Upload DocumentsPOST /v2/erc1155/{tokenId}/upload-documentsPOSTtokenId, files, physicalDataUpload ID, Arweave URLs, file hashesUploads documents to Arweave and returns references
Generate Typed DataPOST /v2/erc1155/{tokenId}/mint/eip712-typed-dataPOSTtokenId, uploadId, to, amountEIP-712 typed data objectGenerates structured data for cryptographic signing
Sign Typed DataPOST /accounts/{accountId}/signEip712POSTaccountId, eip712Object, passcodeCryptographic signatureSigns the typed data with custodian account
Mint TokensPOST /v2/erc1155/{tokenId}/mintPOSTtokenId, uploadId, to, amount, signature, issuedAt, nonce, deadlineTransaction ID, blockchain confirmationMints ERC-1155 tokens with linked documents

🎨 Workflow Visualizations​

🌊 Mermaid Sequence Diagram​


πŸ“ Step-by-Step Implementation​

Step 1: Upload Documents to Arweave​

Upload all documents associated with the NFT (images, certificates, invoices, etc.). These documents will be permanently stored on Arweave.

Endpoint: POST /v2/erc1155/{tokenId}/upload-documents

Path Parameters:

  • tokenId: The ERC-1155 token contract ID

Request Body (multipart/form-data):

{
"image": "<binary file>",
"imageBack": "<binary file>",
"LBMAcertificate": "<binary file>",
"invoice": "<binary file>",
"wheight": "1000",
"purity": "9999",
"serialNumber": "GLD-2025-001234",
"refinery": "Valcambi",
"mintedDate": "1706515200",
"lbmaCertNunmber": "LBMA-2025-5678",
"version": "1"
}

Field Descriptions:

  • image: Front image of the physical asset (PNG, JPEG)
  • imageBack: Back image of the physical asset
  • LBMAcertificate: LBMA certification document (PNG,JPEG)
  • chemicalAssay: Chemical assay certificate (PDF)
  • invoice: Purchase invoice or proof of ownership (PDF)
  • wheight: Weight in grams (e.g., "1000" for 1kg)
  • purity: Purity in basis points (e.g., "9999" for 99.99%)
  • serialNumber: Unique serial number of the physical asset
  • refinery: Name of the refinery that processed the asset
  • mintedDate: Unix timestamp when the physical asset was created
  • lbmaCertNunmber: LBMA certificate number
  • version: Document schema version

Response:

{
"success": true,
"uploadId": "c426c2ac-4356-4ee7-aa13-b7ec71dd1533",
"data": {
"image": {
"arweaveId": "AZ5Y5By5oBPFuYrqRdWsB4yWrc4cYZJNyUbFUuxiNut9",
"arweaveUrl": "https://arweave.net/AZ5Y5By5oBPFuYrqRdWsB4yWrc4cYZJNyUbFUuxiNut9",
"fileName": "gold-bar-front.jpeg",
"mimeType": "image/jpeg",
"fileSize": 67111,
"fileHash": "sha256:5f1090db9db9d72a1e066ad9c13159cd1ef5d86cfe4df31ec24376d651b1abec",
"category": "image"
},
"imageBack": {
"arweaveId": "7xj3CRzskC2CRPCwNxtX2QdNHis49rV9s2ArRdpnwmBv",
"arweaveUrl": "https://arweave.net/7xj3CRzskC2CRPCwNxtX2QdNHis49rV9s2ArRdpnwmBv",
"fileName": "gold-bar-back.jpeg",
"mimeType": "image/jpeg",
"fileSize": 64328,
"fileHash": "sha256:a3f2c8e9f1d7b5a3c4e6d8f9a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0",
"category": "image"
},
"LBMAcertificate": {
"arweaveId": "Bx9Z8Cy7pCQGvZsrSeFtC5zXsd5dZKOzVcGVvyoOmwu0",
"arweaveUrl": "https://arweave.net/Bx9Z8Cy7pCQGvZsrSeFtC5zXsd5dZKOzVcGVvyoOmwu0",
"fileName": "lbma-certificate.pdf",
"mimeType": "application/pdf",
"fileSize": 145678,
"fileHash": "sha256:b4e1f2a3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1",
"category": "certificate"
},
"invoice": {
"arweaveId": "Cy0A9Dz8qDRHwAtsTgGuD6aYte6eALPaWdHWwzpPnxv1",
"arweaveUrl": "https://arweave.net/Cy0A9Dz8qDRHwAtsTgGuD6aYte6eALPaWdHWwzpPnxv1",
"fileName": "purchase-invoice.pdf",
"mimeType": "application/pdf",
"fileSize": 89234,
"fileHash": "sha256:c5f2a3b4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2",
"category": "document"
}
}
}

Important: Save the uploadId - you'll need it for the next steps to link these documents to the minted tokens.


Step 2: Generate EIP-712 Typed Data for Mint​

Generate the structured data that will be cryptographically signed to authorize the mint operation.

Endpoint: POST /v2/erc1155/{tokenId}/mint/eip712-typed-data

Path Parameters:

  • tokenId: The ERC-1155 token contract ID

Request Body:

{
"uploadId": "c426c2ac-4356-4ee7-aa13-b7ec71dd1533",
"to": "0xC5a4F3c0FDE5C2A951EC46193cE3aFdC0fF55383",
"amount": "100"
}

Field Descriptions:

  • uploadId: The upload ID returned in Step 1 (links documents to this mint)
  • to: Recipient blockchain address for the minted tokens
  • amount: Number of fungible tokens to mint under the same token ID (e.g., "100" for 100 identical tokens under same NFT)

Response:

{
"primaryType": "MintData",
"domain": {
"name": "BaseToken",
"version": "1.0.0",
"chainId": 137,
"verifyingContract": "0x1234567890abcdef1234567890abcdef12345678"
},
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"MintData": [
{ "name": "to", "type": "address" },
{ "name": "amount", "type": "uint256" },
{ "name": "docType", "type": "uint8" },
{ "name": "contentHash", "type": "bytes32" },
{ "name": "arweaveRefs", "type": "ArweaveReferences" },
{ "name": "issuedAt", "type": "uint64" },
{ "name": "version", "type": "uint32" },
{ "name": "nonce", "type": "uint256" },
{ "name": "deadline", "type": "uint256" },
{ "name": "physicalMetadata", "type": "PhysicalGoldMetadata" }
],
"ArweaveReferences": [
{ "name": "metadataUri", "type": "string" },
{ "name": "certificateUri", "type": "string" },
{ "name": "additionalDocsUri", "type": "string" }
],
"PhysicalGoldMetadata": [
{ "name": "serialNumber", "type": "bytes32" },
{ "name": "refinery", "type": "bytes32" },
{ "name": "purity", "type": "uint16" },
{ "name": "totalPhysicalWeight", "type": "uint256" },
{ "name": "mintedDate", "type": "uint64" },
{ "name": "lbmaCertNumber", "type": "bytes32" }
]
},
"message": {
"to": "0xC5a4F3c0FDE5C2A951EC46193cE3aFdC0fF55383",
"amount": "100",
"docType": 1,
"contentHash": "0x5f1090db9db9d72a1e066ad9c13159cd1ef5d86cfe4df31ec24376d651b1abec",
"arweaveRefs": {
"metadataUri": "ar://AZ5Y5By5oBPFuYrqRdWsB4yWrc4cYZJNyUbFUuxiNut9",
"certificateUri": "ar://Bx9Z8Cy7pCQGvZsrSeFtC5zXsd5dZKOzVcGVvyoOmwu0",
"additionalDocsUri": "ar://Cy0A9Dz8qDRHwAtsTgGuD6aYte6eALPaWdHWwzpPnxv1"
},
"issuedAt": 1706515200,
"version": 1,
"nonce": "1",
"deadline": "1706601600",
"physicalMetadata": {
"serialNumber": "0x474c442d323032352d303031323334000000000000000000000000000000000000",
"refinery": "0x56616c63616d6269000000000000000000000000000000000000000000000000",
"purity": 9999,
"totalPhysicalWeight": "1000000",
"mintedDate": 1706515200,
"lbmaCertNumber": "0x4c424d412d323032352d35363738000000000000000000000000000000000000"
}
}
}

Important: Save this entire EIP-712 object - you'll need it for the signing step.


Step 3: Sign the Typed Data with Custodian Account​

Use your custodian account to cryptographically sign the EIP-712 typed data, authorizing the mint operation.

Endpoint: POST /accounts/{accountId}/signEip712

Path Parameters:

  • accountId: The custodian account address (e.g., 0x1234...)

Request Body:

{
"passcode": "123456",
"eip712Object": {
"primaryType": "MintData",
"domain": {
"name": "BaseToken",
"version": "1.0.0",
"chainId": 137,
"verifyingContract": "0x1234567890abcdef1234567890abcdef12345678"
},
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"MintData": [
{ "name": "to", "type": "address" },
{ "name": "amount", "type": "uint256" },
{ "name": "docType", "type": "uint8" },
{ "name": "contentHash", "type": "bytes32" },
{ "name": "arweaveRefs", "type": "ArweaveReferences" },
{ "name": "issuedAt", "type": "uint64" },
{ "name": "version", "type": "uint32" },
{ "name": "nonce", "type": "uint256" },
{ "name": "deadline", "type": "uint256" },
{ "name": "physicalMetadata", "type": "PhysicalGoldMetadata" }
],
"ArweaveReferences": [
{ "name": "metadataUri", "type": "string" },
{ "name": "certificateUri", "type": "string" },
{ "name": "additionalDocsUri", "type": "string" }
],
"PhysicalGoldMetadata": [
{ "name": "serialNumber", "type": "bytes32" },
{ "name": "refinery", "type": "bytes32" },
{ "name": "purity", "type": "uint16" },
{ "name": "totalPhysicalWeight", "type": "uint256" },
{ "name": "mintedDate", "type": "uint64" },
{ "name": "lbmaCertNumber", "type": "bytes32" }
]
},
"message": {
"to": "0xC5a4F3c0FDE5C2A951EC46193cE3aFdC0fF55383",
"amount": "100",
"docType": 1,
"contentHash": "0x5f1090db9db9d72a1e066ad9c13159cd1ef5d86cfe4df31ec24376d651b1abec",
"arweaveRefs": {
"metadataUri": "ar://AZ5Y5By5oBPFuYrqRdWsB4yWrc4cYZJNyUbFUuxiNut9",
"certificateUri": "ar://Bx9Z8Cy7pCQGvZsrSeFtC5zXsd5dZKOzVcGVvyoOmwu0",
"additionalDocsUri": "ar://Cy0A9Dz8qDRHwAtsTgGuD6aYte6eALPaWdHWwzpPnxv1"
},
"issuedAt": 1706515200,
"version": 1,
"nonce": "1",
"deadline": "1706601600",
"physicalMetadata": {
"serialNumber": "0x474c442d323032352d303031323334000000000000000000000000000000000000",
"refinery": "0x56616c63616d6269000000000000000000000000000000000000000000000000",
"purity": 9999,
"totalPhysicalWeight": "1000000",
"mintedDate": 1706515200,
"lbmaCertNumber": "0x4c424d412d323032352d35363738000000000000000000000000000000000000"
}
}
}
}

Field Descriptions:

  • passcode: Your custodian account passcode/PIN (provider-specific)
  • eip712Object: The complete typed data object from Step 2

Response:

{
"eip712Signature": "0x2aaa703789b16e7f6ccbe426e7a8b77ee46de84942c26cf01579300d821b40d72f10820d4e57ba9d9d531b0f231db6466811b431620b08e235e45205f6e3952c1b"
}

Important: Save the eip712Signature - you'll use it to execute the mint in the final step.


Step 4: Execute the Mint Transaction​

Execute the final mint transaction on the blockchain using the signature from Step 3.

Endpoint: POST /v2/erc1155/{tokenId}/mint

Path Parameters:

  • tokenId: The ERC-1155 token contract ID

Request Body:

{
"uploadId": "c426c2ac-4356-4ee7-aa13-b7ec71dd1533",
"to": "0xC5a4F3c0FDE5C2A951EC46193cE3aFdC0fF55383",
"amount": "100",
"signature": "0x2aaa703789b16e7f6ccbe426e7a8b77ee46de84942c26cf01579300d821b40d72f10820d4e57ba9d9d531b0f231db6466811b431620b08e235e45205f6e3952c1b",
"issuedAt": "1706515200",
"nonce": "1",
"deadline": "1706601600"
}

Field Descriptions:

  • uploadId: The upload ID from Step 1
  • to: Recipient address (same as in Step 2)
  • amount: Number of tokens (same as in Step 2)
  • signature: The EIP-712 signature from Step 3
  • issuedAt: Unix timestamp when signature was issued
  • nonce: Unique nonce for the transaction
  • deadline: Expiration timestamp for the signature

Response:

{
"id": "567e7895-c76b-12d3-a456-426614174000"
}

TX_MINED Webhook:

After the transaction is confirmed on the blockchain, you'll receive a webhook notification:

{
"type": "TX_MINED",
"event": {
"txUUID": "567e7895-c76b-12d3-a456-426614174000",
"txHash": "0xa1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"timestamp": 1706515800,
"blockNumber": 12345678,
"gasUsed": "287364"
}
}

πŸ’‘ Key Concepts​

What is EIP-712?​

EIP-712 is a standard for hashing and signing typed structured data. It provides:

  • Type Safety: Structured data with explicit types
  • Readability: Users can see what they're signing
  • Security: Prevents signature replay attacks across different contracts/chains
  • Verification: Smart contracts can verify the signature on-chain

Arweave Permanent Storage​

Documents are stored on Arweave, a decentralized storage protocol that provides:

  • Permanence: Files stored forever with a one-time payment
  • Immutability: Content cannot be changed or deleted
  • Verifiability: Each file has a unique hash for verification
  • Decentralization: No single point of failure

Upload ID Linking​

The uploadId is the critical link between your documents and the minted tokens:

  1. Documents uploaded β†’ Receive uploadId
  2. uploadId used in typed data generation β†’ Links documents to mint parameters
  3. Signature includes the uploadId β†’ Authorizes mint with those specific documents
  4. Final mint includes uploadId β†’ On-chain record of document association

Signature Deadline​

The deadline parameter prevents signature reuse:

  • Set to a reasonable future timestamp (e.g., 1 hour from signing)
  • Signature becomes invalid after the deadline
  • Prevents old signatures from being replayed maliciously

⚠️ Important Notes​

  1. Document Permanence: Once uploaded to Arweave, documents CANNOT be deleted or modified
  2. Signature Expiry: Execute the mint before the deadline timestamp
  3. Nonce Uniqueness: Each signature must have a unique nonce to prevent replay attacks
  4. Amount Consistency: The amount must match across Steps 2, 3, and 4
  5. Gas Costs: ERC-1155 minting with documents consumes ~200,000-300,000 gas
  6. Custodian Provider: The passcode field and signing process may vary by custodian provider


πŸ†˜ Troubleshooting​

Documents Not Uploading​

If document upload fails:

  • βœ“ Check file size limits (typically 10MB per file)
  • βœ“ Verify MIME types are supported (JPEG, PNG, PDF)
  • βœ“ Ensure HMAC authentication is correct

Invalid Signature Error​

If mint fails with invalid signature:

  • βœ“ Verify the entire EIP-712 object matches between Steps 2 and 3
  • βœ“ Check that to, amount, nonce are identical across all steps
  • βœ“ Ensure signature hasn't expired (past deadline)
  • βœ“ Verify the correct custodian account signed the data

πŸ“š Additional Resources​


πŸ’Ό Use Case Examples​

Example 1: Tokenizing Physical Gold Bars​

A gold vault tokenizes 100 identical 1kg gold bars as ERC-1155 tokens.

Upload Documents:

  • Front/back images of the bars
  • LBMA certification
  • Chemical assay report
  • Purchase invoice

Result: 100 fungible tokens (same token ID) representing identical parts of same gold bar, all linked to the same documentation.


Example 2: Art Collection NFTs​

An art gallery mints limited edition prints (25 copies of the same artwork).

Upload Documents:

  • High-resolution artwork image
  • Certificate of authenticity
  • Artist biography
  • Gallery provenance

Result: 25 semi-fungible tokens representing the limited edition, each with verifiable provenance.


πŸ”’ Security Best Practices​

  1. Secure Passcode Storage: Never hardcode custodian passcodes in your application
  2. HMAC Validation: Always verify HMAC signatures on webhook callbacks
  3. Document Verification: Verify file hashes match before uploading
  4. Signature Storage: Don't store or reuse signatures after execution
  5. Access Control: Limit who can access custodian account credentials
  6. Audit Trail: Log all mint operations for compliance and auditing

πŸŽ‰ Congratulations! You've successfully minted ERC-1155 NFTs with permanent document references on Arweave!