Skip to content

Commit

Permalink
fix: make Transaction Receipt and Record consistent with other SDKs (#…
Browse files Browse the repository at this point in the history
…1187)

* fix: make receipt and record consistent with other SDKs

Signed-off-by: Ivan Ivanov <[email protected]>

* chore: fix PR feedback

Signed-off-by: Ivan Ivanov <[email protected]>

---------

Signed-off-by: Ivan Ivanov <[email protected]>
  • Loading branch information
0xivanov authored Dec 13, 2024
1 parent e3d3b65 commit 4193992
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 26 deletions.
39 changes: 33 additions & 6 deletions transaction_receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
type TransactionReceipt struct {
Status Status
ExchangeRate *ExchangeRate
NextExchangeRate *ExchangeRate
TopicID *TopicID
FileID *FileID
ContractID *ContractID
Expand Down Expand Up @@ -53,8 +54,8 @@ func (receipt *TransactionReceipt) _ToMap() map[string]interface{} {
ExpirationTime string `json:"expirationTime"`
}

const layout = "2006-01-02T15:04:05.000Z"
if receipt.ExchangeRate != nil {
const layout = "2006-01-02T15:04:05.000Z"
expiration := time.Unix(receipt.ExchangeRate.expirationTime.Seconds, 0)
expirationStr := expiration.UTC().Format(layout)

Expand All @@ -64,6 +65,16 @@ func (receipt *TransactionReceipt) _ToMap() map[string]interface{} {
ExpirationTime: expirationStr,
}
}
if receipt.NextExchangeRate != nil {
expiration := time.Unix(receipt.NextExchangeRate.expirationTime.Seconds, 0)
expirationStr := expiration.UTC().Format(layout)

m["nextExchangeRate"] = ExchangeRateJSON{
Hbars: receipt.NextExchangeRate.Hbars,
Cents: receipt.NextExchangeRate.cents,
ExpirationTime: expirationStr,
}
}

// Handling fields with possible nil values
fields := map[string]interface{}{
Expand Down Expand Up @@ -122,9 +133,16 @@ func _TransactionReceiptFromProtobuf(protoResponse *services.TransactionGetRecei
}

var rate *ExchangeRate
var nextRate *ExchangeRate
if protoReceipt.ExchangeRate != nil {
exchangeRateValue := _ExchangeRateFromProtobuf(protoReceipt.ExchangeRate.GetCurrentRate())
rate = &exchangeRateValue
if exchangeRateValue.expirationTime != nil {
rate = &exchangeRateValue
}
nextExchangeRateValue := _ExchangeRateFromProtobuf(protoReceipt.ExchangeRate.GetNextRate())
if nextExchangeRateValue.expirationTime != nil {
nextRate = &nextExchangeRateValue
}
}

var topicSequenceHash []byte
Expand Down Expand Up @@ -166,6 +184,7 @@ func _TransactionReceiptFromProtobuf(protoResponse *services.TransactionGetRecei
return TransactionReceipt{
Status: Status(protoReceipt.Status),
ExchangeRate: rate,
NextExchangeRate: nextRate,
TopicID: topicID,
FileID: fileID,
ContractID: contractID,
Expand Down Expand Up @@ -196,11 +215,19 @@ func (receipt TransactionReceipt) _ToProtobuf() *services.TransactionGetReceiptR
NodeId: receipt.NodeID,
}

var currentExchangeRate *services.ExchangeRate
if receipt.ExchangeRate != nil {
receiptFinal.ExchangeRate = &services.ExchangeRateSet{
CurrentRate: receipt.ExchangeRate._ToProtobuf(),
NextRate: receipt.ExchangeRate._ToProtobuf(),
}
currentExchangeRate = receipt.ExchangeRate._ToProtobuf()
}

var nextExchangeRate *services.ExchangeRate
if receipt.NextExchangeRate != nil {
nextExchangeRate = receipt.NextExchangeRate._ToProtobuf()
}

receiptFinal.ExchangeRate = &services.ExchangeRateSet{
CurrentRate: currentExchangeRate,
NextRate: nextExchangeRate,
}

if receipt.TopicID != nil {
Expand Down
23 changes: 23 additions & 0 deletions transaction_receipt_query_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,26 @@ func TestIntegrationFileUpdateTransactionHandleFeeScheduleUpload(t *testing.T) {

assert.Equal(t, StatusFeeScheduleFilePartUploaded, receipt.Status)
}

func TestIntegrationTransactionReceiptQueryGetExchageRates(t *testing.T) {
t.Parallel()
env := NewIntegrationTestEnv(t)
defer CloseIntegrationTestEnv(env, nil)

newKey, err := PrivateKeyGenerateEd25519()
require.NoError(t, err)

newBalance := NewHbar(2)

resp, err := NewAccountCreateTransaction().
SetKey(newKey.PublicKey()).
SetInitialBalance(newBalance).
Execute(env.Client)
require.NoError(t, err)

receipt, err := resp.SetValidateStatus(true).GetReceipt(env.Client)
require.NoError(t, err)

assert.NotNil(t, receipt.ExchangeRate.expirationTime)
assert.NotNil(t, receipt.NextExchangeRate.expirationTime)
}
122 changes: 110 additions & 12 deletions transaction_receipt_query_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,13 @@ func TestUnitTransactionReceiptToJson(t *testing.T) {
Seconds: 1694689200,
},
},
NextRate: &services.ExchangeRate{
HbarEquiv: 50000,
CentEquiv: 154271,
ExpirationTime: &services.TimestampSeconds{
Seconds: 1694689200,
},
},
},
},
ChildTransactionReceipts: []*services.TransactionReceipt{
Expand Down Expand Up @@ -349,8 +356,8 @@ func TestUnitTransactionReceiptToJson(t *testing.T) {
TopicSequenceNumber: 10,
TopicRunningHash: []byte{10},
ExchangeRate: &services.ExchangeRateSet{
CurrentRate: &services.ExchangeRate{
HbarEquiv: 30000,
NextRate: &services.ExchangeRate{
HbarEquiv: 50000,
CentEquiv: 154271,
ExpirationTime: &services.TimestampSeconds{
Seconds: 1694689200,
Expand All @@ -373,18 +380,109 @@ func TestUnitTransactionReceiptToJson(t *testing.T) {
require.NoError(t, err)
receipt, err := tx.SetValidateStatus(true).GetReceipt(client)
require.NoError(t, err)
receiptBytes := receipt.ToBytes()
receipt, err = TransactionReceiptFromBytes(receiptBytes)
require.NoError(t, err)
jsonBytes, err := receipt.MarshalJSON()
require.NoError(t, err)
expected := `{"accountId":"0.0.123","children":[{"accountId":"0.0.123","children":[],"contractId":"0.0.456","duplicates":[],"exchangeRate":
{"hbars":30000,"cents":154271,"expirationTime":"2023-09-14T11:00:00.000Z"},"fileId":"0.0.789","nodeId":0,"scheduleId":"0.0.321",
"scheduledTransactionId":"[email protected]","serialNumbers":[1,2,3],"status":"SUCCESS","tokenId":"0.0.987","topicId":"0.0.654",
"topicRunningHash":"0a","topicRunningHashVersion":0,"topicSequenceNumber":10,"totalSupply":0}],"contractId":"0.0.456",
"duplicates":[{"accountId":"0.0.123","children":[],"contractId":"0.0.456","duplicates":[],"exchangeRate":{"hbars":30000,"cents":154271,
"expirationTime":"2023-09-14T11:00:00.000Z"},"fileId":"0.0.789","nodeId":0,"scheduleId":"0.0.321","scheduledTransactionId":"[email protected]",
"serialNumbers":[1,2,3],"status":"SUCCESS","tokenId":"0.0.987","topicId":"0.0.654","topicRunningHash":"0a","topicRunningHashVersion":0,
"topicSequenceNumber":10,"totalSupply":0}],"exchangeRate":{"hbars":30000,"cents":154271,"expirationTime":"2023-09-14T11:00:00.000Z"},
"fileId":"0.0.789","nodeId":1,"scheduleId":"0.0.321","scheduledTransactionId":"[email protected]","serialNumbers":[1,2,3],"status":"SUCCESS",
"tokenId":"0.0.987","topicId":"0.0.654","topicRunningHash":"0a","topicRunningHashVersion":0,"topicSequenceNumber":10,"totalSupply":0}`
expected := `
{
"accountId":"0.0.123",
"children":[
{
"accountId":"0.0.123",
"children":[
],
"contractId":"0.0.456",
"duplicates":[
],
"exchangeRate":{
"hbars":30000,
"cents":154271,
"expirationTime":"2023-09-14T11:00:00.000Z"
},
"fileId":"0.0.789",
"nodeId":0,
"scheduleId":"0.0.321",
"scheduledTransactionId":"[email protected]",
"serialNumbers":[
1,
2,
3
],
"status":"SUCCESS",
"tokenId":"0.0.987",
"topicId":"0.0.654",
"topicRunningHash":"0a",
"topicRunningHashVersion":0,
"topicSequenceNumber":10,
"totalSupply":0
}
],
"contractId":"0.0.456",
"duplicates":[
{
"accountId":"0.0.123",
"children":[
],
"contractId":"0.0.456",
"duplicates":[
],
"fileId":"0.0.789",
"nextExchangeRate":{
"cents":154271,
"expirationTime":"2023-09-14T11:00:00.000Z",
"hbars":50000
},
"nodeId":0,
"scheduleId":"0.0.321",
"scheduledTransactionId":"[email protected]",
"serialNumbers":[
1,
2,
3
],
"status":"SUCCESS",
"tokenId":"0.0.987",
"topicId":"0.0.654",
"topicRunningHash":"0a",
"topicRunningHashVersion":0,
"topicSequenceNumber":10,
"totalSupply":0
}
],
"exchangeRate":{
"hbars":30000,
"cents":154271,
"expirationTime":"2023-09-14T11:00:00.000Z"
},
"fileId":"0.0.789",
"nextExchangeRate":{
"cents":154271,
"expirationTime":"2023-09-14T11:00:00.000Z",
"hbars":50000
},
"nodeId":1,
"scheduleId":"0.0.321",
"scheduledTransactionId":"[email protected]",
"serialNumbers":[
1,
2,
3
],
"status":"SUCCESS",
"tokenId":"0.0.987",
"topicId":"0.0.654",
"topicRunningHash":"0a",
"topicRunningHashVersion":0,
"topicSequenceNumber":10,
"totalSupply":0
}
`

assert.JSONEqf(t, expected, string(jsonBytes), "json should be equal")

Expand Down
16 changes: 9 additions & 7 deletions transaction_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

jsoniter "github.com/json-iterator/go"
"google.golang.org/protobuf/types/known/wrapperspb"

protobuf "google.golang.org/protobuf/proto"

Expand All @@ -23,12 +22,12 @@ type TransactionRecord struct {
TransactionHash []byte
ConsensusTimestamp time.Time
TransactionID TransactionID
ScheduleRef ScheduleID
TransactionMemo string
TransactionFee Hbar
Transfers []Transfer
TokenTransfers map[TokenID][]TokenTransfer
NftTransfers map[TokenID][]_TokenNftTransfer
ExpectedDecimals map[TokenID]uint32
CallResult *ContractFunctionResult
CallResultIsCreate bool
AssessedCustomFees []AssessedCustomFee
Expand Down Expand Up @@ -102,12 +101,12 @@ func (record TransactionRecord) MarshalJSON() ([]byte, error) {

m["transactionHash"] = hex.EncodeToString(record.TransactionHash)
m["transactionId"] = record.TransactionID.String()
m["scheduleRef"] = record.ScheduleRef.String()
m["transactionMemo"] = record.TransactionMemo
m["transactionFee"] = fmt.Sprint(record.TransactionFee.AsTinybar())
m["transfers"] = transfersJSON
m["tokenTransfers"] = tokenTransfersMap
m["nftTransfers"] = tokenTransfersNftMap
m["expectedDecimals"] = record.ExpectedDecimals
m["callResultIsCreate"] = record.CallResultIsCreate

type AssessedCustomFeeJSON struct {
Expand Down Expand Up @@ -344,6 +343,11 @@ func _TransactionRecordFromProtobuf(protoResponse *services.TransactionGetRecord
transactionID = _TransactionIDFromProtobuf(pb.TransactionID)
}

var scheduleRef ScheduleID
if pb.ScheduleRef != nil {
scheduleRef = *_ScheduleIDFromProtobuf(pb.ScheduleRef)
}

var pendingAirdropRecords []PendingAirdropRecord
for _, pendingAirdropRecord := range pb.NewPendingAirdrops {
pendingAirdropRecords = append(pendingAirdropRecords, _PendingAirdropRecordFromProtobuf(pendingAirdropRecord))
Expand All @@ -354,6 +358,7 @@ func _TransactionRecordFromProtobuf(protoResponse *services.TransactionGetRecord
TransactionHash: pb.TransactionHash,
ConsensusTimestamp: _TimeFromProtobuf(pb.ConsensusTimestamp),
TransactionID: transactionID,
ScheduleRef: scheduleRef,
TransactionMemo: pb.Memo,
TransactionFee: HbarFromTinybar(int64(pb.TransactionFee)),
Transfers: accountTransfers,
Expand Down Expand Up @@ -421,10 +426,6 @@ func (record TransactionRecord) _ToProtobuf() (*services.TransactionGetRecordRes
Transfers: tokenTemp,
}

if decimal, ok := record.ExpectedDecimals[tokenID]; ok {
bod.ExpectedDecimals = &wrapperspb.UInt32Value{Value: decimal}
}

tokenTransfers = append(tokenTransfers, bod)
}

Expand Down Expand Up @@ -472,6 +473,7 @@ func (record TransactionRecord) _ToProtobuf() (*services.TransactionGetRecordRes
Nanos: int32(record.ConsensusTimestamp.Nanosecond()),
},
TransactionID: record.TransactionID._ToProtobuf(),
ScheduleRef: record.ScheduleRef._ToProtobuf(),
Memo: record.TransactionMemo,
TransactionFee: uint64(record.TransactionFee.AsTinybar()),
TransferList: &transferList,
Expand Down
40 changes: 40 additions & 0 deletions transaction_record_query_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,43 @@ func DisabledTestIntegrationTokenNftTransferRecordQuery(t *testing.T) { // nolin
_, err = resp.SetValidateStatus(true).GetReceipt(env.Client)
require.NoError(t, err)
}

func TestIntegrationTransactionRecordQueryGetScheduleRef(t *testing.T) {
env := NewIntegrationTestEnv(t)
defer CloseIntegrationTestEnv(env, nil)

key, err := GeneratePrivateKey()
require.NoError(t, err)

createResponse, err := NewAccountCreateTransaction().
SetKey(key.PublicKey()).
SetInitialBalance(NewHbar(2)).
Execute(env.Client)
require.NoError(t, err)

transactionReceipt, err := createResponse.GetReceipt(env.Client)
require.NoError(t, err)

accountId := *transactionReceipt.AccountID

// Create the transaction
transaction := NewTransferTransaction().
AddHbarTransfer(accountId, NewHbar(1).Negated()).
AddHbarTransfer(env.Client.GetOperatorAccountID(), NewHbar(1)).
SetMaxTransactionFee(NewHbar(10))

scheduled, err := transaction.Schedule()
require.NoError(t, err)

// Schedule the transaction
resp, err := scheduled.
Execute(env.Client)
require.NoError(t, err)

record, err := resp.SetValidateStatus(true).GetRecord(env.Client)
require.NoError(t, err)

// Get the schedule reference
scheduleRef := record.ScheduleRef
require.NotNil(t, scheduleRef)
}
2 changes: 1 addition & 1 deletion transaction_record_query_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ func TestUnitTransactionRecordQueryMarshalJSON(t *testing.T) {
"duplicates":[],
"ethereumHash":"01020304",
"evmAddress":"deadbeef",
"expectedDecimals":null,
"nftTransfers":{"0.0.123":[{"sender":"0.0.1246","recipient":"0.0.1246","isApproved":true,"serial":123}]},
"paidStakingRewards":[
{"accountId":"0.0.1157","amount":"-1041694270","isApproved":false},
Expand Down Expand Up @@ -373,6 +372,7 @@ func TestUnitTransactionRecordQueryMarshalJSON(t *testing.T) {
"topicSequenceNumber":0,
"totalSupply":0
},
"scheduleRef":"0.0.0",
"tokenTransfers":{"0.0.123":{"0.0.1246":"789"}},
"transactionFee":"41694270",
"transactionHash":"cac44f2db045ba441f3fbc295217f2eb0f956293d28b3401578f6160e66f4e47ea87952d91c4b1cb5bda6447823b979a",
Expand Down

0 comments on commit 4193992

Please sign in to comment.