목차

반응형

보통 유니티 프로젝트라 하면 싱글톤으로 시작해서 싱글톤으로 끝난다.

제페토의 타입스크립트로 싱글톤을 어떻게 구현해야 하나 찾아봤다.

갖다 쓸 사람 갖다 쓰세요.

 

ObstacleManager라는 매니저를 만든다고 가정하면 아래와 같은 코드가 나온다.

export default class ObstacleManager extends ZepetoScriptBehaviour {

    private static instance: ObstacleManager;
    static getInstance() {
        return this.instance || (this.instance = new this());
    }

    Start() {
        ObstacleManager.instance = this;

    }
}

Start() 안의 부분은 내가 지어낸 건데 보통 대부분의 언어는 싱글톤을 만들면 초기 인스턴스를 설정해주는 부분이 없으나 유니티는 저 부분이 매우 필요하다.

 

(먼가 글하나 날로 먹는 것 같아서 살짝 TMI를 넣어본다.)

이 말이 이해가 안 가는 사람은 아직 유니티에서 싱글톤의 초기 인스턴스가 필요한 형태의 특수성을 이해할 정도로 더 많이 쓰지 않았다는 것이다. 쉽게 말하자면 유니티 프로젝트 안에 싱글톤 매니저 만들고 인스펙터에서 초기값 이것저것 설정해놓는 부분이 있는데 그거 자체가 이미 싱글톤 인스턴스가 생성된 것이라고 보면 된다. 그래서 저 코드가 없으면 당신이 설정해놓은 싱글톤 인스턴스가 스태틱 인스턴스에 안 들어가서 설정해놓은 초기값을 못쓰고 스태틱 그냥 새로운 인스턴스를 만들어버린다.

 

더 깔끔한 방법이 없나 아쉽긴 한데... 저 정도만으로 해도 크게 문제 될 건 없을 것 같다.

ObstacleManager.getInstance().SpawnCar() 이런 식으로 호출해서 사용하면 된다.

반응형
반응형

증상

nodejs의 web3 라이브러리를 사용하여 스마트컨트랙트로 구현한 이벤트를 구독하는데 시간이 지나면 이벤트 리스닝이 끊기는 경우가 있다.

 

원인

원인은 web3 프로바이더를 설정할때 옵션으로 프로바이더의 통신이 끊기지 않도록 설정해주지 않아서 그렇다.

 

인터넷에 보통 아래 2개 형태의 코드가 떠돌아다니는데 프로바이더 설정에 대한 내용이 빠져있다.

const Web3 = require('web3');
require('dotenv').config()

// ENTER A VALID RPC URL!
const web3 = new Web3(process.env.NODE_URL);

//ENTER SMART CONTRACT ADDRESS BELOW. see abi.js if you want to modify the abi
const CONTRACT_ADDRESS = "0xE1C8f3d529BEa8E3fA1FAC5B416335a2f998EE1C";
const CONTRACT_ABI = require('./abi.json');
const contract = new web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRESS);

async function getEvents() {
    let latest_block = await web3.eth.getBlockNumber();
    let historical_block = latest_block - 10000; // you can also change the value to 'latest' if you have a upgraded rpc
    console.log("latest: ", latest_block, "historical block: ", historical_block);
    const events = await contract.getPastEvents(
        'Transfer', // change if your looking for a different event
        { fromBlock: historical_block, toBlock: 'latest' }
    );
    await getTransferDetails(events);
};

async function getTransferDetails(data_events) {
    for (i = 0; i < data_events.length; i++) {
        let from = data_events[i]['returnValues']['from'];
        let to = data_events[i]['returnValues']['to'];
        let amount = data_events[i]['returnValues']['amount'];
        let converted_amount = web3.utils.fromWei(amount);
        if (converted_amount > 32) { //checking for transcations with above 32 eth as an example
            console.log("From:", from, "- To:", to, "- Value:", converted_amount);
        }
    };
};


getEvents(CONTRACT_ABI, CONTRACT_ADDRESS);
var Web3 = require('web3');
var abi = '...';
var contractAddress = '0x62e7Dd1Af52d5A08D401b1e156cC4CB1d2f89d57';
var eventName = 'Transfer';
//var web3;
var etat;
const web3 = new Web3(new Web3.providers.WebsocketProvider('http://127.0.0.1:8545'));
/*
var MyContract = new web3.eth.Contract(JSON.parse(abi));
var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');

// watch for an event with {some: 'args'}
var myEvent = myContractInstance.Transfer({}, {fromBlock: 0, toBlock: 'latest'});
myEvent.watch(function(error, result){
    console.log(result)
});

// would get all past logs again.
var myResults = myEvent.get(function(error, logs){ console.log(logs) });



// would stop and uninstall the filter
myEvent.stopWatching();
*/



var TokenContract = new web3.eth.Contract(JSON.parse(abi),contractAddress);
TokenContract.events.allEvents({ fromBlock: 'latest' }, console.log)
console.log('1********************************************************************************')
console.log(TokenContract);
console.log('2********************************************************************************')
var event = TokenContract.events.Transfer();
console.log(event);
console.log('3********************************************************************************')

TokenContract.once('Transfer', {
}, function(error, event){ console.log(event); });

event.watch(function(error, result){
    if (!error) {
        alert("wait for a while, check for block Synchronization or block creation");
        console.log(result);
        console.log('pas d erreur');
    }else {
        console.log(error);
        console.log('erreur')
    }
});

 

해결방법

웹3 프로바이더 인스턴스 생성 시 옵션 정보를 넣어주는 것으로 해결 가능하다.

아래와 같이 코드를 짜면 해결된다. 추가로 web3-provider-ws 라는 라이브러리를 사용했다.

var express = require('express');
var router = express.Router();
const { item, itemPreset } = require('../models');
const debug = (...messages) => console.log(...messages)

var Web3WsProvider = require('web3-providers-ws');
var Web3 = require('web3');
const options = {
    timeout: 30000, // ms

    clientConfig: {
        // Useful if requests are large
        maxReceivedFrameSize: 100000000,   // bytes - default: 1MiB
        maxReceivedMessageSize: 100000000, // bytes - default: 8MiB

        // Useful to keep a connection alive
        keepalive: true,
        keepaliveInterval: 60000 // ms
    },

    // Enable auto reconnection
    reconnect: {
        auto: true,
        delay: 5000, // ms
        maxAttempts: 5,
        onTimeout: false
    }
};

var web3 = new Web3();
web3.setProvider(new Web3WsProvider('wss://speedy-nodes-nyc.moralis.io/12341234/bsc/mainnet/ws', options));

const contract = require("../artifacts/contracts/Furniture.sol/Furniture.json")
const googleCloudStorage = require("../scripts/googleCloudStorage");
const contractAddress = process.env.contractAddress
const nftContract = new web3.eth.Contract(contract.abi, contractAddress)


var eventMintFurniture = nftContract.events.eventMint({}).on("data", async event => {
    console.log("Mint")
    let result = event.returnValues
    let msgSender = result[0]
    let tokenId = parseInt(result[1])
    // ... your logic

}).on("connected", event => {
    console.log('eventMintFurniture connected')
}).on("error", event => {
    console.log('eventMintFurniture error')
    console.log(event)
}).on("end", event => {
    refreshProvider(web3, 'wss://ropsten.infura.io/ws/v3/925d17c78a0b41f5907df58579ce44bd')
    console.log("eventMintFurniture end")
})

 

 

참고

https://web3js.readthedocs.io/en/v1.5.2/web3-eth.html#configuration

반응형
반응형

윈도우 11을 쓰다보면 익스플로러가 진짜 속이 미어터지도록 느려진다.

정뚝떨!

 

구글링 해보니까 나만 그런게 아니라 많은 사람들이 윈도우 11로 업그레이드 하고나서 익스플로러 렉이 엄청 심해졌다는 불만이 많다.

 

해결방법을 찾았다. 윈도우 11의 상태에서 익스플로러만 다시 예전의 윈도우 10의 익스플로러로 바꾸는 방법이다.

 

WinaeroTweaker-1.33.0.0-setup.exe
2.51MB

위 파일을 다운받아서 설치한다.

 

설치한 프로그램을 시작하고 Windows 11 > Enable Ribbon > Enablef the Ribbon UI in File Explorer를 활성화 해준다.

그러면 아래 Explorer 재시작 요청이 뜨는데 수락해주면 된다.

 

그러면 익스플로러가 예전 형태로 돌아오는데

속도도 다시 빨라졌다!

반응형
반응형

증상

node 백엔드에서 구글 클라우드 스토리지 서비스를 사용하여 파일을 업로드하려고 했으나 자꾸 아래와 같이 접근 권한 오류 발생했다.

storage-service-account@******.iam.gserviceaccount.com does not have storage.objects.create access to the Google Cloud Storage object.

 

원인

구글 스토리지 서비스 계정에 권한을 부여하지 않아서 그렇다.

 

스토리지니까 대충 저거 부여하면 되는 줄 알았더니 아니다.

더 정확히 찾아봐야 한다.

 

아래 링크에서 본인이 사용하려고 하는 명령어는 어떤 권한이 필요한지 확인해보고 부여하도록 하자.

https://cloud.google.com/iam/docs/understanding-roles

 

역할 이해  |  Cloud IAM 문서  |  Google Cloud

역할에는 Google Cloud 리소스에서 특정 작업을 수행할 수 있는 일련의 권한이 포함되어 있습니다. 사용자, 그룹, 서비스 계정을 포함하여 주 구성원에게 권한을 제공하려면 주 구성원에게 역할을

cloud.google.com

 

해결방법

이렇게 3개의 관리자 권한을 주면 대체로 해결된다.

 

본인은 권한을 제대로 부여했는데 작동하지 않아서 구글 커맨드라인 콘솔에서 특정 계정에 부여된 권한 부여 및 조회하는 명령어도 찾아봤다.

 

구글 서비스 계정 양식

cloud-storage-service@******.iam.gserviceaccount.com

 

권한 부여

gcloud projects add-iam-policy-binding cloud-storage-service --member "serviceAccount:cloud-storage-service@******.iam.gserviceaccount.com" --role "roles/storage.objectViewer"

gcloud projects add-iam-policy-binding x-*** --member=serviceAccount:cloud-storage-service@******.iam.gserviceaccount.com --role=roles/storage.admin

gcloud projects add-iam-policy-binding x-*** --member=serviceAccount:cloud-storage-service@******.iam.gserviceaccount.com --role=roles/storage.objectCreator

 

권한 조회

gcloud projects get-iam-policy x-*** --flatten="bindings[].members" --format="table(bindings.role)" --filter="bindings.members:cloud-storage-service@******.iam.gserviceaccount.com"

권한을 조회하면 위와 같이 현재 계정에 부여된 권한이 나온다.

 

본인은 그냥 버킷 이름을 제대로 안 써서 계속 권한이 없다고 나온 것이었다.

반응형
반응형

2021년 4월쯤 퇴사하고 올해 12월에 다시 회사로 출근하게 됐다.

특이한점은 학교를 다니면서 회사를 다닐 수 있는(나에게 아주 좋은) 조건으로 근무형태를 합의봤다.

내가 일을 열정적으로 잘한다는걸 아는 회사라서 학교에 쓰는 시간만큼 회사에 더 집중해줄거라고 믿어준다고 한다.

 

그건 그거고 그 회사에서 하는 일은 게임에 블록체인, NFT, 토큰, 코인을 붙여서 요즘 핫한 P2E 게임을 개발하는 것이다.

음... P2E게임 요즘 진짜 핫하다.

P2E 산업 전선에 서게되었는데 앞장서서 개발하는 사람 중 한명이 될 수 있도록 노력해보겠다.

개발만 할줄알아서 되는 게 아니라 부가적으로 알아야하는 개념이 매우 많다.

그런 개념과 연습코드도 공유하면서 개발해보자 한다.

반응형
반응형

증상

nodejs의 sequilize로 ORM 설정하고 생성된 테이블에 데이터를 넣은 뒤 findall로 데이터를 조회하려고 해도 아무것도 조회가 안된다.

 

원인

sequlize는 기본적으로 설정한 테이블 이름에 s를 붙여서 쿼리를 생성한다.

(정말 라이브러리 제작자 오지랖이 너무너무 넓어서 생긴 이슈다. 니들만쓰냐?)

 

sequlize 관련 함수 실행시 테이블 정보에 s가 붙는지 확인해보자.

또한 조회부터 하지 말고 삽입부터 해보고 생성된 테이블에 s가 붙었는지 확인해보자.

 

해결방법

sequlize ORM 정의할때 위와 같이 freezeTableName:true 옵션값에 true를 주도록 하자.

그러면 원하는 테이블 이름과 정확히 일치하는 쿼리가 생성된다.

 

추가사항

만약 본인이 이 문제로 들어왔다면 추가로 아래 문제도 발생할 가능성이 높으니까 이것까지 보고가라

 

자꾸 테이블에 id 필드가 자동으로 생성됩니다.

ORM 생성시 특정 필드에 아래 옵션값을 넣어주면 pk역할을 하는 id 필드가 안생긴다.

primaryKey: true로 해결

아래 링크 참고

https://stackoverflow.com/questions/29233896/sequelize-table-without-column-id

 

자꾸 테이블에 `createdAt`, `updatedAt` 컬럼이 알아서 생성됩니다.

ORM에 정의시 아래 옵션 넣어주기

timestamps: false 로 해결

https://newbedev.com/sequelize-unknown-column-createdat-in-field-list

 

진짜 역대급 오지랖이다.

왜 본인들의 스타일을 강요해서 무조건 에러를 만들어 버리는걸까...?

 

 

반응형
반응형

증상

가나슈를 작동해서 노드를 가동하고 truffle로 붙어서 스마트컨트랙트의 함수를 실행하거나 컴파일을 하면 아래와 같이 오류가 뜨면서 작동하지 않는다.

 

Saving migration to chain.
Error: Returned error: VM Exception while processing transaction: invalid opcode
    at Migration._deploy (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:99:1)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at Migration._load (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:56:1)
    at Migration.run (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:217:1)
    at Object.runMigrations (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:150:1)
    at Object.runFrom (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:110:1)
    at Object.runAll (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:114:1)
    at Object.run (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:79:1)
    at runMigrations (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:258:1)
    at Object.run (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:223:1)
    at Command.run (************************\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\command.js:183:1)
Truffle v5.4.24 (core: 5.4.24)
Node v16.13.1
PS ************************\Desktop\project\blockchain\realestate>

 

원인

본인은 가나슈 gui 버전을 돌리는데 cli 버전으로 돌리면 괜찮다는 글을 봤다.

gui 가나슈의 버그라고 한다.

 

해결방법

가나슈 gui가 아닌 cli를 설치해서 가동한다.

 

npm install ganache-cli

위 명령어로 가나슈 cli를 설치한다.

 

ganache-cli -a

cmd를 켜서 가나슈 노드를 작동하고 이전에 했던것처럼 명령어를 가동한다.

 

잘된다.

 

아래 링크 참고

https://ethereum.stackexchange.com/questions/83222/vm-exception-while-processing-transaction-invalid-opcode-error

 

vm exception while processing transaction: invalid opcode error

I've been running this code on remix ide on injected web3 with my ganache server in on state, then also i'm getting this error of invalid opcode. The code runs perfectly in rinkeby test network. p...

ethereum.stackexchange.com

 

반응형
반응형

증상

truffle develop --log

명령어를 사용하면 트러플 노드의 로그가 쌓여야하는데 전혀 로그가 안쌓인다.

 

 

원인

관리자 권한으로 하지 않아서 그렇다.

 

해결방법

관리자 권한으로 실행하고 다시한번 해보자.

잘된다.

반응형
반응형

증상

3

geth 명령어 사용시 flag provided but not defined: -rpc와 같은 에러메시지가 발생한다.

 

원인

geth 사용시 버전에 따라 명령어의 파라미터 이름이 다르다.

flag provided but not defined: -rpc는 rpc라는 파라미터 이름이 http로 교체되어서 발생하는 메시지다.

 

해결방법

--rpc => --http 로 바꿔줘야한다.

 

비슷한 사례

--minerthreads =>  --miner.threads

--rpcport는 => --http.port

--rpccorsdomain => --http.corsdomain

 

본인이 써야하는 파라미터의 이름은 아래링크가서 2개 참고하면서 직접 찾아서 바꾸도록 하자.

https://stackoverflow.com/questions/69463898/flag-provided-but-not-defined-rpc

https://geth.ethereum.org/docs/interface/command-line-options

 

 

 

geth --networkid 4386 --mine --miner.threads 2 --datadir "./" --nodiscover --http --http.port "8545" --http.corsdomain "*" --nat "any" --http.api eth,web3,personal,net --password ./password.sec

 

반응형
반응형

증상

솔리디티 컴파일 도중 payable 함수를 사용할때 아래와 같은 에러메시지를 받는다.

 

Desktop\project\token>npx hardhat run ./scripts/deploy.js --network ropsten
Compiling 1 file with 0.8.0
ParserError: Expected a state variable declaration. If you intended this as a fallback function or a function to handle plain ether transactions, use the "fallback" keyword or the "receive" keyword instead.
   --> contracts/HITO.sol:150:32:
    |
150 |     function () public payable {
    |                                ^


Error HH600: Compilation failed

For more info go to https://hardhat.org/HH600 or run Hardhat with --show-stack-traces

 

 

 

원인

솔리디티 버전이 올라가면서 payable 함수는 function이 아니라 fallback으로 수현해야한다.

 

해결방법

아래와 같이 수정하면 된다.

 

 

참고 링크

https://ethereum.stackexchange.com/questions/89833/compiler-solc-expected-a-state-variable-declaration

 

Compiler solc expected a state variable declaration

I try example from book Mastering Ethereum: contract Faucet { function withdraw(uint withdraw_amount) public { require(withdraw_amount<=10000000000000000); msg.sender.transfer(

ethereum.stackexchange.com

 

반응형