MIJI DApp Server Docs

Contracts API Guide

모든 컨트랙트/민팅/트랜스퍼 관련 보호 API는 x-api-key + X-CORPORATE-ID 헤더를 동시에 요구합니다. 예시:

x-api-key: ${GLOBAL_SECRET_KEY}
X-CORPORATE-ID: ${CORPORATE_ID}

POST /contracts/deploy

컨트랙트를 즉시 배포하지 않고 Bull 큐에 작업으로 적재합니다. 응답은 MongoDB에 적재된 DeployedContract 문서입니다.

Headers

Name Required Value
x-api-key Yes 서버에 설정된 글로벌 API 키
X-CORPORATE-ID Yes corporateAccounts 컬렉션에 등록된 기업 ID
Content-Type Yes application/json

Request Body

필드 타입 필수 설명
chainId string 배포 대상 체인 ID (ALLOWED_CHAIN_IDS 환경 변수에서 정의, 기본값 43114)
name string 컨트랙트 이름 (최대 50자)
symbol string 심볼 (최대 8자)
currentOwnerAddress string 배포 직후 소유자 주소. 미입력 시 서버가 기업 시크릿키 지갑 주소를 자동 설정합니다.
ercStandard string '721' 또는 '1155'
contractType string 'standard'(전송 가능) 또는 'certificate'(전송 불가·메타데이터 불변)
royaltyReceiver string 로열티 수취 주소 (기본값: currentOwnerAddress) — certificate 타입은 미사용
royaltyFeeBps number basis point 단위 로열티 비율 (미입력 시 0%) — certificate 타입은 미사용
metadataBaseUri string(url) 배포 직후 컨트랙트에 세팅할 메타데이터 Base URI. 미입력 시 .envMETADATA_BASE_URI를 사용하거나 비워둡니다. (certificate 타입은 무시)
trustedForwarder string EIP-2771 Trusted Forwarder 주소. 미지정 시 .env의 기본값을 사용합니다.
transferOwnerAddress string 배포 후 최종 오너로 즉시 이전할 주소. 입력 시 배포 → (서버가 오너일 때만) Base URI 설정 → transferOwnership를 자동 큐잉하여 이 주소로 이전합니다.

Sample

curl -X POST https://api.example.com/contracts/deploy \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43114",
    "name": "Miji Ticket",
    "symbol": "MTKT",
    // currentOwnerAddress 생략 가능. 미입력 시 기업 시크릿키 주소로 자동 설정됨
    "ercStandard": "721",
    "contractType": "standard",
    "royaltyReceiver": "0x5678def0...def0",
    "royaltyFeeBps": 750,
    "metadataBaseUri": "https://api.example.com/metadata",
    "trustedForwarder": "0x9876...5432",
    "transferOwnerAddress": "0xExternalFinalOwner..." // 최종 오너
  }'

Sample (certificate 배포)

curl -X POST https://api.example.com/contracts/deploy \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43114",
    "name": "Miji Certificate",
    "symbol": "MCERT",
    // currentOwnerAddress 생략 가능. 미입력 시 기업 시크릿키 주소로 자동 설정됨
    "ercStandard": "1155",
    "contractType": "certificate",
    "trustedForwarder": "0x9876...5432"
  }'

certificate 타입은 전송/approve가 전부 차단됩니다. 민팅/소각만 가능하며, 메타데이터는 민팅 시 tokenUri + metadataHash로 불변 저장됩니다(민팅 API 참고).

Base URI 설정과 오너 이전 플로우

성공 응답 (201)

{
  "_id": "6750121f7b3d9f1a6c4c4051",
  "chainId": "43114",
  "name": "Miji Ticket",
  "symbol": "MTKT",
  "ercStandard": "721",
  "status": "DEPLOYING",
  "currentOwnerAddress": "0x1234abcd...abcd",
  "royaltyReceiver": "0x5678def0...def0",
  "royaltyFeeBps": 750,
  "createdAt": "2025-11-18T06:11:43.511Z",
  "updatedAt": "2025-11-18T06:11:43.511Z"
}

이후 Processor가 성공적으로 배포하면 status가 ACTIVE, 주소/트랜잭션 해시가 채워집니다. 실패 시 FAILEDerrorMessage가 저장됩니다.
선택적으로 metadataBaseUri를 전달하면 배포 직후 컨트랙트에 다음과 같이 Base URI가 설정됩니다.

따라서 기본값을 https://api.example.com/metadata로 두면 민팅된 토큰의 tokenURI
https://api.example.com/metadata/<contractAddress>/<tokenId> 형태가 되어, 본 서버의 GET /metadata/:contractAddress/:tokenId와 바로 호환됩니다.


POST /contracts/forwarder

EIP-2771 MinimalForwarder 컨트랙트를 배포합니다. 대납(Gasless) 트랜잭션을 중계하는 인프라용 컨트랙트입니다.

Request Body

필드 타입 필수 설명
chainId string 배포 대상 체인 ID
alias string Forwarder 별칭 (관리용)

Sample

curl -X POST https://api.example.com/contracts/forwarder \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "alias": "Fuji Forwarder 1"
  }'

POST /contracts/read

컨트랙트의 View(읽기 전용) 함수를 호출하여 현재 상태를 조회합니다. 가스비가 소모되지 않습니다.
기본적으로 ERC-721, ERC-1155, ERC-20 및 Forwarder의 표준 함수 ABI가 내장되어 있어 별도 abi 파라미터 없이 호출 가능합니다.

Request Body

필드 타입 필수 설명
chainId string 조회할 체인 ID
contractAddress string 컨트랙트 주소
method string 호출할 함수 이름 (예: ownerOf, balanceOf)
args array 함수 인자 배열
abi array 커스텀 ABI (미지정 시 표준 ABI 사용)

Sample 1-1: 소유자 조회 (ERC-721, ownerOf)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "ownerOf",
    "args": ["1"]
  }'

Response: "0xabcd..." (토큰 1번의 소유자 주소)

ERC-721은 ownerOf(tokenId)로 단일 소유자 주소를 반환합니다.

Sample 1-2: 보유량 조회 (ERC-1155, balanceOf)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "balanceOf",
    "args": ["0xOwnerAddress", "1"]
  }'

Response: "5" (지갑이 보유한 해당 tokenId 수량, 문자열)

ERC-1155에서는 balanceOf(address, tokenId)로 조회해야 합니다. 721과 달리 주소/토큰ID 두 개 모두 필요합니다.

Sample 1-3: 컨트랙트 오너 조회 (owner)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "owner"
  }'

Response: "0xABCD..." (컨트랙트의 Ownable 오너 주소)

주의: owner()는 컨트랙트 소유자(관리자 지갑)를 반환하고, ownerOf(tokenId)는 특정 토큰의 소유자를 반환합니다. 혼동하지 마세요.

Sample 1-4: 메타데이터 해시 조회 (getMetadataHash)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "getMetadataHash",
    "args": ["1"]
  }'

Response: "0x...metadataHash" (bytes32 문자열)

인증서(contractType=certificate) 전용 메타데이터 불변성 검증에 사용합니다.

Sample 1-5: 인터페이스 지원 여부 (supportsInterface)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "supportsInterface",
    "args": ["0x80ac58cd"]
  }'

Response: true 또는 false
0x80ac58cd(ERC-721), 0xd9b67a26(ERC-1155), 0x2a55205a(ERC-2981) 등 표준 인터페이스 지원 여부를 확인할 수 있습니다.


인증서 변조 방지 검증 가이드

누구나 온체인 호출로 검증할 수 있으며, 별도 서비스 종속이 필요 없습니다.

1) 온체인 해시 조회

2) 오프체인 메타데이터 수집

3) 표준화(canonicalize) 후 SHA-256 해시 계산

4) 해시 비교

참고

Sample 3-1: 메타데이터 URI 조회 (ERC-721: tokenURI)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "tokenURI",
    "args": ["1"]
  }'

Response: "https://api.example.com/metadata/<contractAddress>/1"

ERC-721은 tokenURI(tokenId)를 호출합니다. 배포 시 metadataBaseUri를 넣지 않았다면 호출 시 컨트랙트가 revert할 수 있습니다.

Sample 3-2: 메타데이터 URI 조회 (ERC-1155: uri)

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0x1234...",
    "method": "uri",
    "args": ["1"]
  }'

Response: "https://api.example.com/metadata/<contractAddress>/{id}"
{id}는 OpenSea 규격대로 토큰 ID(16진수, 0x 접두어 없는 zero-pad)로 치환됩니다.

ERC-1155는 tokenURI 메서드가 없으므로 반드시 uri(tokenId)로 조회하세요. 배포 시 metadataBaseUri가 비어 있으면 호출이 실패합니다.

Sample 4: Trusted Forwarder 확인 (isTrustedForwarder)

대납(Gasless) 트랜잭션을 위해 특정 Forwarder 컨트랙트를 신뢰하는지 확인합니다.

curl -X POST https://api.example.com/contracts/read \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43113",
    "contractAddress": "0xNFTContract...",
    "method": "isTrustedForwarder",
    "args": ["0xForwarderAddress..."]
  }'

Response: true 또는 false (boolean)


POST /contracts/transfer-ownership

컨트랙트 소유자를 온체인에서 변경합니다. 호출하면 작업이 큐에 적재되고, 처리 결과는 웹훅(ownership.transferred / ownership.failed)으로 전달됩니다. 호출 지갑은 해당 컨트랙트의 현재 오너(기업 시크릿키)여야 합니다.

Request Body

필드 타입 필수 설명
chainId string 체인 ID
contractAddress string 대상 컨트랙트 주소
newOwnerAddress string 변경할 새 오너 주소

Sample

curl -X POST https://api.example.com/contracts/transfer-ownership \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43114",
    "contractAddress": "0x1234...",
    "newOwnerAddress": "0xabcd..."
  }'

성공 응답 (200)

{
  "status": "QUEUED",
  "jobId": "12345",
  "contractId": "6750121f7b3d9f1a6c4c4051",
  "contractAddress": "0x1234...",
  "newOwner": "0xabcd..."
}

처리 완료 시 기업별 웹훅이 설정되어 있으면 ownership.transferred(성공) / ownership.failed(실패) 이벤트가 전달됩니다. 배포 시 trustedForwarder를 올바르게 넣어두면, 추후 메타트랜잭션 기반 대납 민팅/운영을 재배포 없이 확장할 수 있습니다.


민팅 시 주의 (certificate 타입)

민팅 예시 (certificate, ERC-721)

curl -X POST https://api.example.com/minting/orders \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43114",
    "contractAddress": "0xCERT721...",
    "receiverAddress": "0xReceiver...",
    "tokenId": "1",
    "metadataId": "6740f7a329d9f9323f8a9c91",
    "tokenUri": "https://cdn.example.com/meta/1.json",
    "metadataHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  }'

민팅 예시 (certificate, ERC-1155)

curl -X POST https://api.example.com/minting/orders \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "43114",
    "contractAddress": "0xCERT1155...",
    "receiverAddress": "0xReceiver...",
    "tokenId": "1001",
    "amount": 1,
    "metadataId": "6740f7a329d9f9323f8a9c91",
    "tokenUri": "https://cdn.example.com/meta/1001.json",
    "metadataHash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
  }'

GET /contracts/:id

POST /contracts/deploy 호출 시 받은 _id를 사용해 현재 상태를 조회합니다.

Headers

Name Required Value
x-api-key Yes 글로벌 API 키
X-CORPORATE-ID Yes corporateAccounts 식별자

Sample

curl -X GET https://api.example.com/contracts/691c1552f28bd9c4cb602c0d \
  -H "x-api-key: ${GLOBAL_SECRET_KEY}" \
  -H "X-CORPORATE-ID: ${CORPORATE_ID}"

응답

DeployedContract 문서를 그대로 반환합니다. 상태/주소/트랜잭션 해시/오류 메시지를 확인할 수 있습니다.