sendTransaction에 관하여

안녕하세요. 제가 궁금한점이 생겨서 이렇게 글을 쓰게 됬습니다.

먼저 이더리움에서 트랜잭션을 보내는 방법과 klay에서 트랜잭션을 보내는 부분이 좀 달라서 헷갈리는 부분이있습니다.

먼저 web3.js를 사용하게 되면
const data = await wtContract.methods
.vote(info.contentNum, info.userAddress, info.select)
.encodeABI();
const nonce = await web3.eth.getTransactionCount(
serverAddress,
‘latest’
);
const gasprice = await web3.eth.getGasPrice();
const gasPrice = Math.round(
Number(gasprice) + Number(gasprice / 10)
);

				const tx = {
					from: serverAddress,
					to: process.env.WTTOKENCA,
					nonce: nonce,
					gasPrice: gasPrice, // maximum price of gas you are willing to pay for this 
					gasLimit: 5000000,
					data: data,
				};

				const signedTx = await web3.eth.accounts.signTransaction(
					tx,
					serverPrivateKey
				);
				const hash = await web3.eth.sendSignedTransaction(
					signedTx.rawTransaction
				);

이런식으로 TX를 구성하고, 그다음 privateKey를 이용해서 서명한다음 .sendSignedTransaction 함수를 이용해서 보냅니다. 그러나 klaytn doc에서는
const create = await caver.klay.accounts.wallet.add(serverPrivateKey);

	console.log(create);

	caver.klay.sendTransaction({
		type: 'SMART_CONTRACT_EXECUTION',
		from: serverAddress,
		to: process.env.WTTOKENCA,
		data: wtContract.methods.mintToken(user,caver.utils.toPeb('30','KLAY')).encodeABI(),
		gas: '300000',
	})
	.then(function(receipt){
		console.log(receipt);
	});

이렇게 보내도 트랜잭션이 생성됩니다. web3.js는 롭스텐을 kalytn은 바오밥네트워크를 사용했습니다.

다시 정리해 보자면 klaytn에서 보내는 트랜잭션에서는 서명을 어디서 해주는 건지 궁금합니다. 또한 nonce부분은 필요가 없는 것일까요??
또, type부분을 지정해주지 않으면 안되는 것인지 이것또한 궁금합니다.

마지막으로… 멍청한 질문일 수도 있지만 caver.klaly.sendTransaction 이것과 caver.rpc.klay.sendTransaction은 무슨차이가 있는 것일까요?? 이 rpc가 있고 없고의 차이가 무엇인지 궁금합니다.

안녕하세요, caver-js 개발 담당팀에서 좀더 구체적인 답변을 드릴 것으로 생각하지만, 흥미가 생겨 caver 소스코드를 조금 조사해 보고 커뮤니티 활성 측면에서 개인적인 관점에서 조사 결과로 설명드립니다. 정확한 답변이 아닐 수도 있지만, 잘못된 설명이 있으면 이는 담당 개발팀에서 교정해주시리라 기대합니다 ^^;

  1. caver-js 소스코드를 보시면 caver.rpc.klay 또는 caver.klay 내에 있는 모든 method들은 caver-core-method 라는 모듈에서 처리 됩니다. 클레이튼은 이 method 내에서 caver object 에 지갑이 설정되어있는 경우 서명을 자동으로 하도록 코딩되어 있습니다. web3.js 는 제가 내부적으로 소스를 확인해보지 못했지만, caver의 경우 아래 소스를 확인하시면, klay_sendTransaction을 호출 받는 경우, account 내에 지갑이 등록되어있는 경우 서명후 처리하도록 다루는 것을 확인할 수 있습니다. 아마 편의적 요소로 설계해서 넣지 않았을까 생각됩니다.
  1. nonce 부분은 Ethereum의 경우에는 transaction 처리가 gas fee에 따라 순서가 바뀔 수 있는 부분이라 transaction 전송 순서를 이후에 확인할수 있게 첨부하는 것이 중요하지만, Klaytn에서는 현재로서는 first come first in으로 transaction을 받기때문에, nonce가 중요하지 않은것으로 알고 있습니다.

  2. tx type 부분은 함수가 실행되기 전에 파라미터가 validator (caver-js/validateFunction.js at dev · klaytn/caver-js (github.com)) 의 validateParams 메소드를 통해 검증이 이루어집니다. 이때 caver-js/constants.js at dev · klaytn/caver-js (github.com) 에 정의된 TxType을 검증하기때문에, 정확한 type을 기입하시는게 중요하다고 생각합니다. TxType은 RPC 서버에서 함수호출시의 구분자로 사용될 것이기 때문에, 기입이 안되면 RPC서버에서 처리하는데 문제가 있지 않을까 생각해요.

  3. caver.klay.sendTransation은 caver 1.4.1 이전 버젼의 backward compatibility를 위해 유지하고 있는것 같습니다. 이는 caver의 공식 문서를 보시면, caver.klay 가 최신문서부터 누락된 걸로 유추해볼 수 있습니다. 실제 caver.klay를 보시면, caver-rtm을 경유해서 root path에 있는 rpc.json( caver-js/rpc.json at dev · klaytn/caver-js (github.com)) 파일에 정의된 정보를 이용해 caver-core-method 에서 함수를 빌드하는 구조고, caver.rpc.klay를 보시면 caver-rpc/klay.js ( caver-js/klay.js at dev · klaytn/caver-js (github.com)) 에 동일한 정보를 이용해 함수를 빌드하지만, json이 아닌 js 파일로 작성되어서 후자쪽이 문서화가 체계적으로 되어있는 것을 확인하실 수 있습니다. 따라서 가능하면 caver.rpc.klay 를 사용하시는 편이 좋을것으로 생각됩니다.

답변 되셨으면 좋겠습니다. 감사합니다.

1 Like

글 잘읽었습니다. 감사합니다. 혹시 한가지더 궁금함이 생겨서 댓글을 남깁니다.

await caver.klay.accounts.wallet.add(serverPrivateKey);

			const txHash = await caver.klay.sendTransaction({
				type: 'SMART_CONTRACT_EXECUTION',
				from: serverAddress,
				to: process.env.WTTOKENCA,
				data: wtContract.methods
				.createContent()
				.encodeABI(),
				gas: '300000',
			})

이런식으로 트랜잭션을 남기면 잘 됩니다. 하지만 한번더 실행을 하게 되면
Account exists with 0x0b72d6d24902482c7d407d40f6d159e8e5fcd6b7 이런 오류가 발생합니다.

그래서 이미 walllet에 저장되어있다고 생각하고
await caver.klay.accounts.wallet.add(serverPrivateKey);
을 삭제하고 트랜잭션을 날리게 되면 unknown account 이오류를 만나게됩니다.
혹시 한번만 add를 하고 다른 트랜잭션들을 날릴때는 add를 안할 수 있는 방법은 없을까요?
아니면 트랜잭션을 날릴때마다 await caver.klay.accounts.wallet.add(serverPrivateKey); 이 함수를 추가해줘야 할까요?

해당 Tx 는 브라우져 콘솔을 이용하시는 건가요? 아니면 node.js 를 이용하시는 것인가요?

현재 저는 node를 사용하고 있습니다