본문으로 건너뛰기
이 페이지는 영어로 된 기계 번역을 사용하므로 오류나 불명확한 언어가 포함될 수 있습니다. 가장 정확한 정보는 영어 원문을 참조하시기 바랍니다. 잦은 업데이트로 인해 일부 콘텐츠는 원래 영어로 되어 있을 수 있습니다. Crowdin에서 이 페이지의 번역을 개선하는 데 동참하여 도움을 주세요. (Crowdin translation page, Contributing guide)

Web3를 Cocos 크리에이터 프로젝트에 통합하기

이 섹션에서는 토큰 컨트랙트를 만들고, 토큰과 상호작용하는 스크립트를 작성하고, 지갑 연결, 토큰 채굴 및 잔액 검색을 위해 DApp 포털 SDK를 활용하여 웹3 기능을 Cocos 크리에이터 프로젝트에 통합해 보겠습니다. 결국, 디앱은 블록체인과 원활하게 상호 작용하여 게임 내에서 원활한 웹3.0 상호작용을 가능하게 합니다.

KIP7 스마트 컨트랙트 생성 및 배포

먼저 카이아 컨트랙트 마법사를 사용하여 스마트 컨트랙트를 생성합니다.

1단계: Kaia 계약 마법사 사용하기

  • Kaia 계약 마법사로 이동합니다.
  • KIP7(ERC20과 유사한 카이아의 토큰 표준)을 선택합니다.
  • 토큰을 구성합니다:
    • Name: 예제 토큰 (또는 다른 이름!)
    • 심볼: ET(토큰 시세)
    • 프리프린트: 100 (초기 토큰 공급량)
    • 특징: 체크 ✅ 민테이블

이 가이드에서는 소유자 수정자만 갖지 않도록 민트 함수를 조정하겠습니다. 이렇게 하려면 ownable.sol 가져오기 및 소유 가능 상속을 제거해야 합니다. 이제 조정된 코드는 다음과 같이 보일 것입니다:


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@kaiachain/contracts/KIP/token/KIP7/KIP7.sol";
contract ExampleTokens is KIP7 {
constructor() KIP7("ExampleTokens", "ET") {
_mint(msg.sender, 100 * 10 ** decimals());
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override
returns (bool)
{
return
super.supportsInterface(interfaceId);
}
function mint(uint256 amount) public {
_mint(msg.sender, amount);
}
}

정보

원래 배포자나 컨트랙트의 소유자 외에는 누구나 민트 함수를 호출할 수 있도록 유일한 소유자 수정자를 제거했습니다.

2단계: Remix IDE를 통한 배포

  1. 위의 코드를 복사하여 Remix IDE에서 새로 생성한 ET.sol 파일에 붙여넣습니다.
  2. Remix IDE에서:
  • 계약 컴파일** 버튼을 클릭합니다.
  • 플러그인 관리자에서 Kaia 플러그인을 활성화합니다.
  • 카이아 플러그인 탭의 환경 아래에서 인젝션된 공급자 - 카이아 월렛을 선택합니다.
  • 컨트랙트** 드롭다운에서 컨트랙트(예시 토큰)를 찾습니다.
  • 토큰을 배포하려면 배포를 클릭하세요!
  1. Kaia 지갑이 나타나면:
  • 배포 세부 정보를 검토합니다.
  • 확인을 클릭하여 카이아 카이로스 테스트넷에 배포합니다.
노트

배포된 계약 주소를 복사하여 저장합니다. 튜토리얼의 뒷부분에 필요하게 될 것입니다.

스크립트 파일 만들기

Web3 기능을 통합하려면 블록체인 상호작용과 UI 관리를 처리하기 위한 스크립트 파일을 만들어야 합니다.

1. 스크립트 폴더 만들기

  • 프로젝트의 자산 폴더로 이동합니다.
  • 마우스 오른쪽 버튼을 클릭하고 만들기 → 폴더를 선택합니다.

  • 이름을 스크립트로 지정합니다.

2. Web3 스크립트 파일 생성

스크립트 폴더 안에 두 개의 TypeScript 파일을 만듭니다:

  • Web3Manager.ts - 블록체인 상호작용을 처리합니다.
  • UIManager.ts - UI 요소와 사용자 상호작용을 관리합니다.

이제 프로젝트 구조가 다음과 같이 보일 것입니다:


assets/
scripts/
Web3Manager.ts
UIManager.ts

Web3Manager.ts - 블록체인 상호작용 처리하기

Web3Manager 스크립트는 모든 블록체인 관련 기능을 담당합니다.

주요 기능

  • SDK 초기화 - 디앱 포털 SDK를 설정합니다.
  • 지갑 연결 - 사용자가 지갑을 연결할 수 있습니다.
  • 토큰 발행 - 토큰 발행 기능을 활성화합니다.
  • 잔액 검색 - 사용자의 토큰 잔액을 가져옵니다.

코드 구현:


import { _decorator, Component, Node, director, EventTarget, sys } from 'cc';
const { ccclass, property } = _decorator;
// Global event bus for Web3 events
export const web3Events = new EventTarget();
@ccclass('Web3Manager')
export class Web3Manager extends Component {
private static instance: Web3Manager = null;
private sdk: any = null;
private connectedAddress: string = '';
// Configuration
private readonly CONTRACT_ADDRESS = '0xbe9b8eB864F7E363ee834054e4391fb9b4e69B90'; // REPLACE CONTRACT ADDRESS
private readonly CHAIN_ID = '1001';
private readonly CLIENT_ID = 'PASTE CLIENT ID';
onLoad() {
if (Web3Manager.instance === null) {
Web3Manager.instance = this;
director.addPersistRootNode(this.node);
this.initializeSDK();
this.tryRestoreSession();
} else {
this.node.destroy();
}
}
private async initializeSDK(): Promise<boolean> {
try {
// @ts-ignore
this.sdk = await window.DappPortalSDK.init({
clientId: this.CLIENT_ID,
chainId: this.CHAIN_ID
});
console.log("SDK initialized successfully");
web3Events.emit('sdkInitialized');
return true;
} catch (error) {
console.error("SDK initialization error:", error);
web3Events.emit('sdkInitError', error.message);
return false;
}
}
private async tryRestoreSession() {
const savedAddress = sys.localStorage.getItem('connectedAddress');
if (savedAddress) {
this.connectedAddress = savedAddress;
web3Events.emit('walletConnected', this.connectedAddress);
this.getBalance();
}
}
public async connectWallet(): Promise<void> {
try {
if (!this.sdk) {
const initialized = await this.initializeSDK();
if (!initialized) return;
}
const provider = this.sdk.getWalletProvider();
const accounts = await provider.request({
method: 'kaia_requestAccounts'
});
if (accounts && accounts.length > 0) {
this.connectedAddress = accounts[0];
sys.localStorage.setItem('connectedAddress', this.connectedAddress);
web3Events.emit('walletConnected', this.connectedAddress);
this.getBalance();
}
} catch (error) {
console.error("Wallet connection error:", error);
web3Events.emit('walletError', error.message);
}
}
public async mintToken(amount: number): Promise<void> {
try {
if (!this.connectedAddress) {
throw new Error('Wallet not connected');
}
const provider = this.sdk.getWalletProvider();
const mintSignature = '0xa0712d68';
// @ts-ignore
const amountHex = amount.toString(16).padStart(64, '0');
const data = mintSignature + amountHex;
const tx = {
from: this.connectedAddress,
to: this.CONTRACT_ADDRESS,
value: '0x0',
data: data,
gas: '0x4C4B40'
};
const txHash = await provider.request({
method: 'kaia_sendTransaction',
params: [tx]
});
// After getting txHash, immediately update balance
web3Events.emit('mintSuccess', txHash);
await this.getBalance(); // Get updated balance right after minting
} catch (error) {
console.error("Minting error:", error);
web3Events.emit('mintError', error.message);
}
}
public async getBalance(): Promise<void> {
try {
if (!this.connectedAddress) {
throw new Error('Wallet not connected');
}
const provider = this.sdk.getWalletProvider();
const balanceSignature = '0x70a08231';
// @ts-ignore
const addressParam = this.connectedAddress.substring(2).padStart(64, '0');
const data = balanceSignature + addressParam;
const result = await provider.request({
method: 'kaia_call',
params: [{
from: this.connectedAddress,
to: this.CONTRACT_ADDRESS,
data: data
}, 'latest']
});
const balance = parseInt(result, 16);
web3Events.emit('balanceReceived', balance.toString());
} catch (error) {
console.error("Balance fetch error:", error);
web3Events.emit('balanceError', error.message);
}
}
public getConnectedAddress(): string {
return this.connectedAddress || '';
}
}

주요 기능

  • initializeSDK() - 디앱 포털 SDK를 초기화합니다.
  • connectWallet() - 지갑 연결을 처리합니다.
  • mintToken(amount) - 민트 토큰을 발행합니다.
  • getBalance() - 토큰 잔액을 검색합니다.

스크립트를 실행하기 전에 다음 사항을 확인하세요:

  • Web3Manager.ts에서 YOUR_CLIENT_ID를 대체합니다.
  • 필요한 경우 계약_주소를 업데이트합니다.
  • 올바른 네트워크에 맞게 CHAIN_ID를 업데이트합니다.

UIManager.ts - UI 상호작용 처리하기

UIManager 스크립트는 모든 UI 구성 요소와 사용자 상호 작용을 관리합니다.

코드 구현:


import { _decorator, Component, Node, Label, Button } from 'cc';
import { Web3Manager, web3Events } from './Web3Manager';
const { ccclass, property } = _decorator;
@ccclass('UIManager')
export class UIManager extends Component {
@property(Label)
addressLabel: Label = null;
@property(Label)
balanceLabel: Label = null;
@property(Button)
connectButton: Button = null;
@property(Button)
mintButton: Button = null;
private web3Manager: Web3Manager = null;
start() {
this.web3Manager = this.getComponent(Web3Manager);
this.updateUIState(false);
this.setupEventListeners();
this.setupButtonHandlers();
}
private setupEventListeners() {
web3Events.on('sdkInitialized', this.onSDKInitialized, this);
web3Events.on('walletConnected', this.onWalletConnected, this);
web3Events.on('balanceReceived', this.onBalanceReceived, this);
web3Events.on('mintSuccess', this.onMintSuccess, this);
web3Events.on('walletError', this.onError, this);
web3Events.on('mintError', this.onError, this);
web3Events.on('balanceError', this.onError, this);
}
private setupButtonHandlers() {
this.connectButton.node.on('click', this.onConnectClick, this);
this.mintButton.node.on('click', this.onMintClick, this);
}
onDestroy() {
web3Events.off('sdkInitialized', this.onSDKInitialized, this);
web3Events.off('walletConnected', this.onWalletConnected, this);
web3Events.off('balanceReceived', this.onBalanceReceived, this);
web3Events.off('mintSuccess', this.onMintSuccess, this);
web3Events.off('walletError', this.onError, this);
web3Events.off('mintError', this.onError, this);
web3Events.off('balanceError', this.onError, this);
}
private updateUIState(isConnected: boolean) {
if (this.connectButton) {
this.connectButton.node.active = !isConnected;
}
if (this.mintButton) {
this.mintButton.interactable = isConnected;
}
if (this.addressLabel) {
this.addressLabel.node.active = isConnected;
}
if (this.balanceLabel) {
this.balanceLabel.node.active = isConnected;
}
}
async onConnectClick() {
await this.web3Manager.connectWallet();
}
async onMintClick() {
await this.web3Manager.mintToken(1); // Mint 1 token as example
}
onSDKInitialized() {
console.log('SDK initialized');
}
onWalletConnected(address: string) {
this.updateUIState(true);
if (this.addressLabel) {
this.addressLabel.string = `Connected: ${address.substring(0, 6)}...${address.substring(address.length - 4)}`;
}
}
onBalanceReceived(balance: string) {
if (this.balanceLabel) {
this.balanceLabel.string = `Balance: ${balance}`;
console.log('Balance updated:', balance); // Add this to debug
}
}
onMintSuccess(txHash: string) {
console.log(`Mint successful! TX: ${txHash}`);
// The balance update will happen automatically because we called getBalance() in mintToken
}
onError(error: string) {
console.error('Error:', error);
}
}

노드에 스크립트 첨부 및 UI 요소 연결하기

1. Web3UI 노드에 스크립트 첨부

  • Web3UI** 노드를 선택합니다.
  • 검사기**에서 컴포넌트 추가를 클릭합니다.
  • Web3Manager**를 검색하여 선택합니다.

  • 위 단계를 반복하여 UIManager를 추가합니다.

2. UI 요소 연결

  • Web3UI를 선택한 상태에서 인스펙터로 이동합니다.
  • 계층 구조에서 해당 UI 요소를 각 필드로 끌어다 놓습니다:
    • 주소 레이블
    • 밸런스 라벨
    • 지갑 연결 버튼
    • 민트 버튼

페이지를 개선해 주세요