Skip to main content
For the complete documentation index, see llms.txt

Create your first Midnight contract

이 quick start는 환경이 Compact 컨트랙트를 컴파일하고 테스트할 수 있는지 점검하고, Compact이 어떤 모습인지 보여줍니다. 메시지를 저장하는 컨트랙트를 작성해 컴파일하고, example-hello-world 리포지토리의 테스트를 로컬 네트워크에서 실행합니다. 테스트 토큰이나 공개 네트워크는 필요하지 않습니다.

Prerequisites​

  • Compact toolchain 0.31.1 버전. Install the toolchain을 따라 설치한 뒤 compact compile --version으로 확인하세요. 각 네트워크가 지원하는 버전은 support matrix에 정리돼 있습니다.
  • Node.js 22 또는 24. 프로젝트 의존성은 Node.js 23에서는 설치되지 않습니다.
  • Yarn. corepack enable을 한 번 실행하면 프로젝트가 고정해 둔 Yarn 버전을 사용합니다.
  • 실행 중인 Docker Desktop, 또는 Compose v2를 지원하는 다른 Docker 엔진.
  • Git.

Set up the project​

리포지토리를 클론하고 의존성을 설치하세요:

git clone https://github.com/midnightntwrk/example-hello-world.git
cd example-hello-world
yarn install

이후의 모든 명령은 example-hello-world 디렉터리에서 실행하세요.

Write the contract​

다음 내용으로 contracts/hello-world.compact를 생성하세요:

contracts/hello-world.compact
pragma language_version 0.23;

export ledger message: Opaque<"string">;

export circuit storeMessage(newMessage: Opaque<"string">): [] {
message = disclose(newMessage);
}
  • pragma language_version 0.23;은 Compact 언어 버전을 선언합니다. 컴파일러가 해당 버전을 지원하지 않으면 파일을 거부합니다.
  • export ledger message는 공개 온체인 상태를 선언합니다. 문자열을 담는 message라는 필드입니다.
  • export circuit storeMessage는 circuit을 선언합니다. circuit은 트랜잭션이 호출하는 함수에 해당하는 Compact의 구성 요소입니다.
  • newMessage는 비공개입니다. circuit 인자는 기본적으로 비공개이기 때문입니다. disclose()는 그 값을 ledger에 저장해 공개하겠다는 의도를 컴파일러에 알립니다. 이 함수가 없으면 potential witness-value disclosure must be declared but is not 오류와 함께 컴파일이 실패합니다.

Compile the contract​

컴파일 스크립트를 실행하세요:

yarn compile

스크립트는 compact compile contracts/hello-world.compact contracts/managed/hello-world를 실행합니다. 컴파일러는 컨트랙트를 영지식 circuit으로 변환하고, proving key와 verifier key를 생성하며, DApp 코드가 가져다 쓰는 JavaScript와 TypeScript를 만듭니다. 출력에는 circuit 하나가 표시됩니다:

Compiling 1 circuits:
circuit "storeMessage" (k=6, rows=26)
Overall progress [====================] 1/1

스크립트나 코딩 에이전트에서 명령을 실행하면 첫 줄만 보입니다. 정작 확인해야 할 것은 아래의 파일들입니다.

출력은 contracts/managed/hello-world에 생성됩니다:

contracts/managed/hello-world/
├── compiler/ contract-info.json, a description of the contract for other tools
├── contract/ index.js and index.d.ts, the contract implementation
├── keys/ storeMessage.prover and storeMessage.verifier
└── zkir/ storeMessage.zkir and storeMessage.bzkir, the circuit in ZKIR

Test the contract on a local network​

리포지토리의 테스트는 컴파일한 컨트랙트를 배포하고, Hello World!로 storeMessage를 호출한 뒤, ledger에서 메시지를 다시 읽어 옵니다. 테스트는 Docker에서 돌아가는 로컬 네트워크를 상대로 실행되며, 네트워크가 시작될 때 자금이 충전되는 지갑을 사용합니다.

  1. 로컬 네트워크를 시작하세요:

    yarn env:up

    Midnight node, indexer, proof server가 시작되고 셋 모두 정상 상태가 되면 반환됩니다.

  2. 지갑의 DUST를 사용할 수 있을 때까지 기다리세요:

    yarn wait:dust

    갓 띄운 네트워크는 지갑이 수수료를 낼 수 있기까지 몇 초가 필요합니다. 스크립트는 DUST ready를 출력하고 종료됩니다.

  3. 테스트를 실행하세요:

    yarn test:local

    실행이 끝나면 테스트 두 개가 모두 통과합니다:

    [11:53:49.163] INFO (63955): Wallet sync complete after 23 emissions
    [11:53:49.174] INFO (63955): Providers initialized on 'local'. Ready to test!
    [11:53:49.177] INFO (63955): Creating private state...
    [11:54:09.014] INFO (63955): Setting the contract address...
    [11:54:09.014] INFO (63955): Contract deployed at: 2e5b69411fcabd3e803fd2971fdae2ffe4482e7f3d0174d50b8a4f0f3abb29fb
    ✓ src/test/hw.test.ts (2 tests) 37897ms
    ✓ Deploys the contract 19846ms
    ✓ Stores Hello World! 17347ms

    Test Files 1 passed (1)
    Tests 2 passed (2)

    컨트랙트 주소와 소요 시간은 환경마다 다릅니다. 두 테스트가 모두 통과하면 환경이 준비된 것입니다.

  4. 로컬 네트워크를 중지하세요:

    yarn env:down

Troubleshooting​

SymptomFix
language version X.Y.Z mismatch (X.Y.Z는 컴파일러의 언어 버전, 예: 0.22.0)컴파일러가 컨트랙트의 언어 버전을 지원하지 않습니다. compact update 0.31.1로 toolchain 0.31.1을 설치하세요.
Cannot find module './managed/hello-world/contract/index.js'컨트랙트가 컴파일되지 않았습니다. 테스트 전에 yarn compile을 실행하세요.
Cannot connect to the Docker daemonDocker가 실행되고 있지 않습니다. Docker Desktop을 시작하고 엔진이 올라올 때까지 기다린 뒤 yarn env:up을 다시 실행하세요.
첫 시작에서 yarn env:up이 container ...-indexer-1 exited (1)로 실패node가 첫 블록을 생성하기 전에 indexer가 먼저 시작됐습니다. yarn env:up을 다시 실행하세요.
테스트 도중 Wallet.InsufficientFunds지갑의 DUST가 사용 가능해지기 전에 테스트가 실행됐습니다. yarn wait:dust를 실행한 뒤 yarn test:local을 다시 실행하세요.
RPC-CORE: subscribeRuntimeVersion(): RuntimeVersion:: disconnected ... 1000:: Normal Closure오류가 아닙니다. 지갑 설정 중 연결이 정상적으로 닫히는 것이며, 실행은 계속됩니다.

Next steps​