π§΅ 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:
- πΉ Upload documents (images, certificates, invoices) to Arweave
- πΉ Generate EIP-712 typed data linking the documents to the mint
- πΉ Sign the typed data using a custodian account
- πΉ 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β
| Step | API Operation | Method | Parameters | Outputs | Description |
|---|---|---|---|---|---|
| Upload Documents | POST /v2/erc1155/{tokenId}/upload-documents | POST | tokenId, files, physicalData | Upload ID, Arweave URLs, file hashes | Uploads documents to Arweave and returns references |
| Generate Typed Data | POST /v2/erc1155/{tokenId}/mint/eip712-typed-data | POST | tokenId, uploadId, to, amount | EIP-712 typed data object | Generates structured data for cryptographic signing |
| Sign Typed Data | POST /accounts/{accountId}/signEip712 | POST | accountId, eip712Object, passcode | Cryptographic signature | Signs the typed data with custodian account |
| Mint Tokens | POST /v2/erc1155/{tokenId}/mint | POST | tokenId, uploadId, to, amount, signature, issuedAt, nonce, deadline | Transaction ID, blockchain confirmation | Mints 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 assetLBMAcertificate: 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 assetrefinery: Name of the refinery that processed the assetmintedDate: Unix timestamp when the physical asset was createdlbmaCertNunmber: LBMA certificate numberversion: 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 tokensamount: 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 1to: Recipient address (same as in Step 2)amount: Number of tokens (same as in Step 2)signature: The EIP-712 signature from Step 3issuedAt: Unix timestamp when signature was issuednonce: Unique nonce for the transactiondeadline: 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:
- Documents uploaded β Receive
uploadId uploadIdused in typed data generation β Links documents to mint parameters- Signature includes the
uploadIdβ Authorizes mint with those specific documents - 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β
- Document Permanence: Once uploaded to Arweave, documents CANNOT be deleted or modified
- Signature Expiry: Execute the mint before the
deadlinetimestamp - Nonce Uniqueness: Each signature must have a unique nonce to prevent replay attacks
- Amount Consistency: The
amountmust match across Steps 2, 3, and 4 - Gas Costs: ERC-1155 minting with documents consumes ~200,000-300,000 gas
- Custodian Provider: The
passcodefield and signing process may vary by custodian provider
π Related Endpointsβ
- Upload Documents
- Generate EIP-712 Typed Data
- Mint ERC-1155 Tokens
- Webhook Notifications
- HMAC Authentication
π 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,nonceare identical across all steps - β Ensure signature hasn't expired (past
deadline) - β Verify the correct custodian account signed the data
π Additional Resourcesβ
- ERC-1155 Multi-Token Standard
- EIP-712 Typed Structured Data
- Arweave Documentation
- HMAC Authentication Guide
- Gas Limit Warning Guide
- Token City Support
πΌ 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β
- Secure Passcode Storage: Never hardcode custodian passcodes in your application
- HMAC Validation: Always verify HMAC signatures on webhook callbacks
- Document Verification: Verify file hashes match before uploading
- Signature Storage: Don't store or reuse signatures after execution
- Access Control: Limit who can access custodian account credentials
- Audit Trail: Log all mint operations for compliance and auditing
π Congratulations! You've successfully minted ERC-1155 NFTs with permanent document references on Arweave!