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

Midnight.js

Midnight.js는 스마트 컨트랙트를 배포하고 호출하며, 암호화된 private state를 관리하고, 영지식 증명을 생성해 Midnight 네트워크에 트랜잭션을 제출하는 도구를 제공합니다.

이 문서에서는 Midnight.js SDK의 구조와 패키지 구성, 그리고 시작하는 방법을 전반적으로 설명합니다.

Prerequisites

Midnight.js를 사용하기 전에 다음이 준비되어 있어야 합니다.

Packages

Midnight.js는 모듈식 구조를 따르며, 각 패키지가 하나의 기능을 담당합니다.

Core

core 패키지는 SDK의 기반 기능을 제공합니다.

패키지용도
@midnight-ntwrk/midnight-js-types공통 타입, 인터페이스, provider 계약
@midnight-ntwrk/midnight-js-contracts컨트랙트 배포, circuit 호출, 트랜잭션 제출
@midnight-ntwrk/midnight-js-network-id런타임 및 ledger WASM API용 네트워크 식별자 설정
@midnight-ntwrk/midnight-js-utils공통 유틸리티(hex 인코딩, bech32m, assertion)

Providers

provider 패키지는 증명 생성, private state 관리, 공개 데이터 조회 기능을 담당합니다.

패키지용도
@midnight-ntwrk/midnight-js-indexer-public-data-providerGraphQL 기반 블록체인 데이터 provider(쿼리 및 구독)
@midnight-ntwrk/midnight-js-level-private-state-providerLevelDB를 사용한 AES-256-GCM 암호화 영속 상태 저장소
@midnight-ntwrk/midnight-js-http-client-proof-providerMidnight proof server용 HTTP 클라이언트
@midnight-ntwrk/midnight-js-fetch-zk-config-providerFetch API를 사용하는 브라우저 호환 영지식 아티팩트 provider
@midnight-ntwrk/midnight-js-node-zk-config-providerNode.js 파일 시스템 기반 ZK 아티팩트 provider
@midnight-ntwrk/midnight-js-logger-provider애플리케이션별 Pino 로거 설정

Tooling

tooling 패키지는 Compact smart contract 컴파일에 필요한 도구를 제공합니다.

패키지용도
@midnight-ntwrk/midnight-js-compact컨트랙트 컴파일을 위한 Compact 컴파일러 관리자

Installation

SDK 전체를 하나의 진입점으로 제공하는 barrel 패키지를 설치하려면 다음과 같이 실행하세요.

npm install @midnight-ntwrk/midnight-js

개별 패키지를 설치하려면 다음과 같이 실행하세요.

npm install @midnight-ntwrk/midnight-js-types
npm install @midnight-ntwrk/midnight-js-contracts
npm install @midnight-ntwrk/midnight-js-network-id
npm install @midnight-ntwrk/midnight-js-utils
npm install @midnight-ntwrk/midnight-js-indexer-public-data-provider
npm install @midnight-ntwrk/midnight-js-level-private-state-provider
npm install @midnight-ntwrk/midnight-js-http-client-proof-provider
npm install @midnight-ntwrk/midnight-js-fetch-zk-config-provider
npm install @midnight-ntwrk/midnight-js-node-zk-config-provider
npm install @midnight-ntwrk/midnight-js-logger-provider
npm install @midnight-ntwrk/ledger-v8
important

SDK 버전이 Midnight Network의 다른 컴포넌트와 어떻게 맞물리는지는 호환성 매트릭스에서 항상 먼저 확인하세요.

Configure the network

네트워크 ID는 SDK가 사용할 네트워크를 지정합니다. Midnight Network에서 작업하려면 목적에 맞는 네트워크 ID를 설정해야 합니다. 다른 Midnight.js 라이브러리와 컴포넌트도 이 네트워크 ID를 기준으로 네트워크 작업을 수행합니다.

import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';

setNetworkId('preprod');

export const CONFIG = {
indexer: 'https://indexer.preprod.midnight.network/api/v4/graphql',
indexerWS: 'wss://indexer.preprod.midnight.network/api/v4/graphql/ws',
node: 'https://rpc.preprod.midnight.network',
proofServer: 'http://127.0.0.1:6300',
};

사용할 수 있는 네트워크는 다음과 같습니다.

NetworkNetwork ID
Mainnetmainnet
Previewpreview
Preprodpreprod
Undeployedundeployed

Node.js 환경에서는 GraphQL 구독을 위해 WebSocket을 활성화하세요.

import { WebSocket } from 'ws';

globalThis.WebSocket = WebSocket;

Configure providers

provider는 교체 가능한 모듈식 컴포넌트로, Midnight 블록체인에 트랜잭션을 구성하고 제출하는 데 필요한 기능을 하나씩 나눠 담당합니다.

import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-private-state-provider';
import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
import { httpClientProofProvider } from '@midnight-ntwrk/midnight-js-http-client-proof-provider';
import { FetchZkConfigProvider } from '@midnight-ntwrk/midnight-js-fetch-zk-config-provider';
import * as ledger from '@midnight-ntwrk/ledger-v8';

const zkConfigProvider = new FetchZkConfigProvider(zkArtifactsUrl);

const providers: MidnightProviders = {
privateStateProvider: levelPrivateStateProvider({
privateStoragePasswordProvider: () => password,
accountId: walletAddress,
}),
publicDataProvider: indexerPublicDataProvider(queryUrl, subscriptionUrl),
zkConfigProvider,
proofProvider: httpClientProofProvider(proofServerUrl, zkConfigProvider),
walletProvider, // from @midnight-ntwrk/wallet-sdk-facade
midnightProvider, // from @midnight-ntwrk/wallet-sdk-facade
};
info

walletProvidermidnightProvider는 트랜잭션 밸런싱과 블록체인 제출을 담당하며, Wallet SDK 패키지가 제공합니다. 자세한 내용은 Wallet SDK 문서를 참고하세요.

proof provider에 ZK 설정을 넘길 때는 FetchZkConfigProviderNodeZkConfigProvider 중 하나를 사용합니다.

Fetch ZK configuration provider

HTTP/HTTPS로 proving key, verifier key, ZK 중간 표현을 가져오는 ZK 설정 provider입니다.

FetchZkConfigProvider 사용 예시는 다음과 같습니다.

import { FetchZkConfigProvider } from '@midnight-ntwrk/midnight-js-fetch-zk-config-provider';

const zkConfigProvider = new FetchZkConfigProvider('https://example.com/zk-artifacts');

const proverKey = await zkConfigProvider.getProverKey('myCircuit');
const verifierKey = await zkConfigProvider.getVerifierKey('myCircuit');
const zkir = await zkConfigProvider.getZKIR('myCircuit');

Node ZK configuration provider

파일 시스템에서 proving key, verifier key, ZK 중간 표현을 가져오는 ZK 설정 provider입니다.

NodeZkConfigProvider 사용 예시는 다음과 같습니다.

import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';

const zkConfigProvider = new NodeZkConfigProvider('/path/to/zk-artifacts');

const proverKey = await zkConfigProvider.getProverKey('myCircuit');
const verifierKey = await zkConfigProvider.getVerifierKey('myCircuit');
const zkir = await zkConfigProvider.getZKIR('myCircuit');

DApp Connector proof provider

영지식 증명 생성을 DApp Connector 지갑에 위임하는 proof provider 구현입니다. DApp이 브라우저에서 동작하고 증명 생성을 사용자 지갑이 맡는 경우에 사용하세요.

@midnight-ntwrk/dapp-connector-proof-provider 패키지를 설치하세요.

npm install @midnight-ntwrk/dapp-connector-proof-provider

dappConnectorProofProvider 함수로 proof provider를 만듭니다.

import { dappConnectorProofProvider } from '@midnight-ntwrk/midnight-js-dapp-connector-proof-provider';

const proofProvider = await dappConnectorProofProvider(
walletConnectedAPI,
zkConfigProvider,
costModel
);

const provenTx = await proofProvider.proveTx(unprovenTx);

dappConnectorProofProvider 함수에는 다음 매개변수가 반드시 필요합니다.

  • walletConnectedAPI: 증명 생성 기능을 갖춘 DApp Connector 지갑 API
  • zkConfigProvider: ZK 설정 아티팩트를 제공하는 provider
  • costModel: 트랜잭션 증명에 사용할 비용 모델
note

지갑 연결은 DApp Connector API가 처리하며, walletConnectedAPI 매개변수도 여기서 나옵니다. 자세한 내용은 DApp Connector API 레퍼런스를 참고하세요.

Deploy a smart contract

deployContract 메서드는 스마트 컨트랙트를 블록체인에 배포합니다. 매개변수는 다음과 같습니다.

  • providers: provider 객체
  • compiledContract: 컴파일된 컨트랙트
  • privateStateId: private state ID
  • initialPrivateState: 초기 private state
import { deployContract } from '@midnight-ntwrk/midnight-js-contracts';

const deployed = await deployContract(providers, {
compiledContract,
privateStateId: 'my-state',
initialPrivateState: { counter: 0n },
});

deployContract 메서드는 deployedContract promise를 반환합니다. 이 객체에는 컨트랙트 주소와 private state ID가 담겨 있습니다.

const contractAddress = deployed.deployTxData.public.contractAddress;
console.log(`Contract Address: ${contractAddress}`);

Interact with the contract

배포된 컨트랙트를 다루려면 findDeployedContract 메서드로 컨트랙트 객체를 가져오세요.

import { findDeployedContract } from '@midnight-ntwrk/midnight-js-contracts';

const contract = await findDeployedContract(providers, {
contractAddress: contractAddress,
compiledContract,
privateStateId: 'my-state',
initialPrivateState: {},
});

이 메서드의 매개변수는 다음과 같습니다.

  • providers: provider 객체
  • 다음 속성을 담은 options 객체
    • contractAddress: 컨트랙트 주소
    • compiledContract: 컴파일된 컨트랙트
    • privateStateId: private state ID
    • initialPrivateState: 초기 private state

컨트랙트 객체를 초기화하고 나면 callTx 속성으로 스마트 컨트랙트의 circuit을 호출할 수 있습니다.

const transaction = await contract.callTx.someCircuit(circuitArguments);

이 호출은 새 트랜잭션을 만들어 블록체인에 제출합니다. 트랜잭션 정보는 다음과 같이 확인합니다.

const transaction = await contract.callTx.someCircuit(circuitArguments);
console.log('Transaction ID:', transaction.public.txId);
console.log(`Block: ${transaction.public.blockHeight}\n`);

Transaction submission

트랜잭션 페이로드나 options 객체를 이미 만들어 둔 경우, 아래 헬퍼로 설정된 provider를 통해 call·deploy·일반 트랜잭션을 제출할 수 있습니다. contract.callTx.* 편의 메서드를 쓰지 않고 제출 과정을 직접 제어할 때 유용합니다.

import { submitCallTx, submitDeployTx, submitTx } from '@midnight-ntwrk/midnight-js-contracts';

// Submit a call transaction
await submitCallTx(providers, callOptions);

// Submit a deploy transaction
await submitDeployTx(providers, deployOptions);

// Generic transaction submission
await submitTx(providers, txData);

Query state

스마트 컨트랙트를 배포한 뒤에는 getStatesgetPublicStates 메서드로 컨트랙트의 private state와 public state를 조회할 수 있습니다.

import { getStates, getPublicStates } from '@midnight-ntwrk/midnight-js-contracts';

const states = await getStates(providers, contractAddress, privateStateId);
const publicStates = await getPublicStates(providers, contractAddress);

getStates 메서드는 지정한 provider를 통해, 주어진 식별자에 해당하는 배포된 스마트 컨트랙트의 Zswap 상태, ledger 상태, private state를 가져옵니다.

매개변수는 다음과 같습니다.

  • providers: provider 객체
  • contractAddress: 컨트랙트 주소
  • privateStateId: private state ID

getPublicStates 메서드는 배포된 스마트 컨트랙트에서 외부에 공개되는 상태(Zswap과 ledger)만 가져옵니다. 매개변수는 다음과 같습니다.

  • providers: provider 객체
  • contractAddress: 컨트랙트 주소

컨트랙트의 unshielded 잔액은 getUnshieldedBalances 메서드에 provider 객체와 컨트랙트 주소를 넘겨 조회합니다.

const balances = await getUnshieldedBalances(providers, contractAddress);
console.log('Unshielded Balances:', balances);

Key concepts

Midnight.js SDK의 동작 방식을 이해하려면 다음 개념을 알아두어야 합니다.

Contract model

컨트랙트 모델에서는 다음 용어를 사용합니다.

  • Circuit: 로컬에서 실행되어 영지식 증명을 생성하는 스마트 컨트랙트 함수
  • Witness: 최종 사용자의 기기에서 실행되는 비공개 연산
  • Private state: circuit이 갱신하는 사용자 로컬 상태로, 온체인에 저장되지 않음
  • Ledger state: 온체인에 공개되는 컨트랙트 상태

ZK artifacts

ZK 아티팩트는 영지식 증명을 만들기 위해 Compact 컴파일러가 생성하는 파일입니다. 다음 파일이 포함됩니다.

  • Prover key: 영지식 증명을 생성할 때 쓰는 바이너리
  • Verifier key: 온체인에서 증명을 검증할 때 쓰는 바이너리
  • ZKIR: 컴파일된 컨트랙트의 영지식 중간 표현(Zero-Knowledge Intermediate Representation)

Transaction flow

컨트랙트 호출을 제출하면 먼저 로컬에서 실행되어 증명이 없는 트랜잭션이 만들어집니다. 그다음 타입이 지정된 provider들이 차례로 증명을 생성하고, 트랜잭션을 밸런싱한 뒤 네트워크에 전파합니다.아래 다이어그램이 그 흐름을 정리한 것입니다.

Transaction status

트랜잭션 상태는 다음 세 가지입니다.

  • SucceedEntirely: 트랜잭션의 모든 구간이 성공
  • FailFallible: guaranteed 구간은 성공했으나 fallible 구간이 실패
  • FailEntirely: 트랜잭션이 유효하지 않음