본문으로 건너뛰기
버전: 3.5.0

송금 성공 판단 방법

iost, irc20, irc21 토큰의 송금을 판정하는 방법은 거의 동일하며, receipt에서 토큰 심볼만 구분하면 됩니다.

송금 트랜잭션의 성공 판정​

트랜잭션이 송금을 포함하고 그 송금이 성공했음을 확인하려면 다음 두 가지를 판단해야 합니다. 트랜잭션이 불가역(irreversible) 상태인지, 그리고 트랜잭션이 송금 정보를 포함하면서 성공적으로 실행되었는지입니다.

트랜잭션의 불가역 여부 판단​

트랜잭션이 불가역인지 판단하는 방법은 세 가지가 있습니다.

  • getTxByHash API를 호출하여 반환값의 status 필드가 IRREVERSIBLE이면 트랜잭션이 불가역입니다.
  • getTxReceiptByTxHash API를 호출(이 API는 불가역 트랜잭션에 대해서만 TxReceipt를 반환합니다)하여 반환값이 존재하면 트랜잭션이 불가역입니다.
  • getBlockByNumber 또는 getBlockByHash API를 호출하여 반환값의 status 필드가 IRREVERSIBLE이면 해당 블록의 모든 트랜잭션이 불가역입니다.

트랜잭션이 송금을 포함하며 성공 실행되었는지 판단​

트랜잭션에 송금이 포함되어 있는지 판단하는 유일한 방법은 tx_receipt의 receipts 필드를 확인하는 것입니다. tx_receipt는 getTxByHash API와 getTxReceiptByTxHash API로 얻을 수 있고, getBlockByNumber 와 getBlockByHash API가 반환하는 블록 구조에도 트랜잭션들의 tx_receipt가 포함됩니다. 성공한 송금 트랜잭션의 receipts는 다음과 같은 형태입니다.

"tx_receipt": {
"tx_hash": "CHeKFLzzpcfZ2Fo9gHwRM7PFkZy5SoEKSda2ZrTYfHQf",
"gas_usage": 8750,
"ram_usage": {},
"status_code": "SUCCESS",
"message": "",
"returns": [
"[]"
],
"receipts": [
{
"func_name": "token.iost/transfer",
"content": "[\"iost\",\"fromacc\",\"toacc\",\"1.0000\",\"\"]"
}
]
},

receipts 필드는 리스트입니다. 한 항목의 func_name 필드가 token.iost/transfer이면 그 트랜잭션에 송금이 포함된 것입니다(iost든 irc20이든 irc21이든 func_name은 동일하게 token.iost/transfer입니다). 송금의 토큰 심볼, 계정, 금액은 해당 항목의 content 필드에서 추가로 파싱해야 합니다. content 필드는 다섯 개의 문자열을 담은 배열의 JSON 직렬화 결과입니다. JSON 역직렬화하면 첫 번째 요소가 토큰 심볼(토큰 심볼은 모든 토큰에서 유일합니다), 두 번째가 송금 계정명, 세 번째가 수령 계정명, 네 번째가 송금 금액, 다섯 번째가 memo입니다. 네 번째 요소인 송금 금액을 다룰 때 [0-9.] 이외의 문자가 포함된 문자열이 발견되면 그 송금은 무시해야 합니다. 그 외의 경우라면 해당 문자열을 직접 float으로 변환해 후속 처리에 사용할 수 있습니다.

트랜잭션 실행이 성공했음을 확인하려면 tx_receipt의 status_code 필드가 SUCCESS와 같은지 확인해야 합니다.

자주 발생하는 실수​

actions로 송금 성공을 판정​

actions는 트랜잭션의 동작 목록이고 receipts는 트랜잭션의 실행 결과입니다. 트랜잭션의 actions 필드만 보고 송금의 성공을 판정하는 것은 엄밀하지 않습니다. 일부 특수한 경우(예: 지연 트랜잭션)에서는 tx_receipt의 status_code가 SUCCESS라도 트랜잭션이 실제로 성공적으로 실행되지 않았을 수 있고, 반대로 송금 트랜잭션이 실제로 성공했다면 반드시 receipts가 있어야 합니다. 따라서 송금 성공 여부는 actions가 아니라 receipts 필드로만 판단해야 합니다.

송금 금액 문자열을 직접 float으로 변환​

메인넷 token.iost 컨트랙트의 송금은 토큰 decimal에 맞춰 송금 금액을 절단한 뒤 그 결과를 float으로 변환하는 방식으로 처리됩니다. 따라서 다음과 같은 송금에서

"receipts": [
{
"func_name": "token.iost/transfer",
"content": "[\"iost\",\"aaaaa\",\"bbbbb\",\"1.20294517598E7\",\"\"]"
}
]

실제로 송금된 토큰 양은 1.20294517입니다. "1.20294517598E7"를 그대로 float으로 변환하면 예상과 다른 결과가 나올 수 있습니다. 따라서 송금 금액 문자열에 [0-9.] 이외의 문자가 포함되어 있으면 해당 송금은 무시할 것을 권장합니다.

토큰 심볼 미확인​

송금을 판정할 때 반드시 토큰 이름, 즉 content 필드의 첫 번째 요소를 확인해야 합니다. 다음과 같은 송금에서 토큰 이름을 확인하지 않고 iost 토큰 송금으로 처리하면 문제가 발생합니다.

"receipts": [
{
"func_name": "token.iost/transfer",
"content": "[\"sometoken\",\"aaaaa\",\"bbbbb\",\"1.20294517\",\"\"]"
}
]

트랜잭션 실행 상태를 확인하지 않음​

ram이 부족할 때 송금 트랜잭션은 실패해도 receipts는 여전히 생성됩니다. 예를 들어 다음과 같은 경우입니다.

"tx_receipt": {
"tx_hash": "xxxxxxxxxxxxxxxxx",
"gas_usage": 186277,
"ram_usage": {},
"status_code": "BALANCE_NOT_ENOUGH",
"message": "balance not enough after executing actions: pay ram failed. id: irisye need 335, actual 115",
"returns": [
"[\"\"]"
],
"receipts": [
{
"func_name": "token.iost/transfer",
"content": "[\"iost\",\"aaaaaaa\",\"vote.iost\",\"10\",\"\"]"
}
]
},

status_code 필드를 확인하지 않으면 송금이 성공했다고 잘못 판단하게 됩니다.

요약​

송금 성공을 확인하려면 다음을 모두 판단해야 합니다.

  • 트랜잭션이 불가역이어야 합니다.
  • tx_receipt.status_code가 SUCCESS여야 합니다.
  • tx_receipt.receipts 중 func_name이 token.iost/transfer인 항목이 있어야 합니다.
  • content 필드의 첫 번째 요소(토큰 심볼)가 기대하는 값인지 확인합니다.
  • content 필드의 네 번째 요소(금액)에 부적절한 문자가 없는지 확인합니다.