Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cmd/export_transactions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ func TestExportTransactions(t *testing.T) {
Golden: "ledger_fee_bump.golden",
WantErr: nil,
},
{
Name: "10 ledgers with classic and soroban txn",
Args: []string{"export_transactions", "-s", "61477814", "-e", "61477824", "-o", GotTestDir(t, "classic_soroban_txs.txt")},
Golden: "classic_soroban_txs.golden",
WantErr: nil,
},
}

for _, test := range tests {
Expand Down
7 changes: 5 additions & 2 deletions internal/transform/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,13 @@ func TransformTransaction(transaction ingest.LedgerTransaction, lhe xdr.LedgerHe
}
}

// For P23 onwards, transaction meta v3 will be empty
// For P23 onwards, transaction meta v3 will be empty.
// In P23+, the fee refund balance change moved from TxChangesAfter to
// PostTxApplyFeeChanges on the LedgerTransaction, so we need to include both.
metav4, ok := transaction.UnsafeMeta.GetV4()
if ok {
accountBalanceStart, accountBalanceEnd := getAccountBalanceFromLedgerEntryChanges(metav4.TxChangesAfter, feeAccountAddress)
feeChanges := append(metav4.TxChangesAfter, transaction.PostTxApplyFeeChanges...)
accountBalanceStart, accountBalanceEnd := getAccountBalanceFromLedgerEntryChanges(feeChanges, feeAccountAddress)
outputResourceFeeRefund = accountBalanceEnd - accountBalanceStart
if metav4.SorobanMeta != nil {
extV1, ok := metav4.SorobanMeta.Ext.GetV1()
Expand Down
213 changes: 209 additions & 4 deletions internal/transform/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ func TestTransformTransaction(t *testing.T) {
})
}

for _, test := range tests {
actualOutput, actualError := TransformTransaction(test.input.transaction, test.input.historyHeader)
assert.Equal(t, test.wantErr, actualError)
assert.Equal(t, test.wantOutput, actualOutput)
for i, test := range tests {
t.Run(fmt.Sprintf("case_%d", i), func(t *testing.T) {
actualOutput, actualError := TransformTransaction(test.input.transaction, test.input.historyHeader)
assert.Equal(t, test.wantErr, actualError)
assert.Equal(t, test.wantOutput, actualOutput)
})
}
}

Expand Down Expand Up @@ -173,6 +175,46 @@ func makeTransactionTestOutput() (output []TransactionOutput, err error) {
TransactionResultCode: "TransactionResultCodeTxInsufficientBalance",
TxSigners: []string{"GD2GXC24XWOM6T2UHABEMSYW5UZGJ4U7WEN7AQT2WYW32TQFP4ND3M7O4VGCBTT2BWNILFEVDX5DBBBMK2RTQIBMJNL6F62MAQ53NBAIXUDA"},
},
// Test case 4: Fee-bump Soroban tx with V4 meta and PostTxApplyFeeChanges (P23+)
// Based on real mainnet tx 5c4f80c4...094116 (ledger 61396807, protocol 25)
// Fee breakdown: 20,230 non-refundable + 7,298 refundable + 300 inclusion = 27,828 charged
// Resource fee refund: 10,705 (38,533 initial - 27,828 charged)
{
TxEnvelope: "AAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJaFAAAAAgAAAACI4aa0pXFSj6qfJuIObLw/5zyugLRGYwxb7wFSr3B9eAAAlb0BjydzAABBtwAAAAEAAAAAAAAAAAAAAABfBqt0AAAAAQAAABdITDVhQ2dvelFISVc3c1NjNVhkY2ZtUgAAAAABAAAAAQAAAAAcR0GXGO76pFs4y38vJVAanjnLg4emNun7zAx0pHcDGAAAAAIAAAAAAAAAAAAAAAAAAAAAAQIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVZAAAAAAAAAAAAAAABY0KvjwAAAED0a4tcvZzPT1Q4AkZLFu0yZPKfsRvwQnq2Lb1OBX8aPbPu5UwgznoNmoWUlR36MIQsVqM4ICxLV+L7TAQ7toQI",
TxResult: "AAAAAAAAbLQAAAABqH/vXusmAmnDgPLeRWqtcrWbsxWqrHd4YEVuCdrAuvsAAAAAAAAAZAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
TxMeta: "AAAABAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAABPBgAAAAAAAByCAAAAAAAAHG4AAAAAAAAAAAAAAAA=",
TxFeeMeta: "AAAAAgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7L0HFQ2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7L0G72xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
TransactionHash: "a87fef5eeb260269c380f2de456aad72b59bb315aaac777860456e09dac0bafb",
LedgerSequence: 61396807,
TransactionID: 263697278143827968,
Account: testAccount1Address,
AccountSequence: 112351890582290871,
MaxFee: 38333,
FeeCharged: 27828,
OperationCount: 1,
CreatedAt: correctTime,
MemoType: "MemoTypeMemoText",
Memo: "HL5aCgozQHIW7sSc5XdcfmR",
TimeBounds: "[0,1594272628)",
Successful: true,
ClosedAt: time.Date(2020, time.July, 9, 5, 28, 42, 0, time.UTC),
FeeAccount: testAccount5Address,
InnerTransactionHash: "a87fef5eeb260269c380f2de456aad72b59bb315aaac777860456e09dac0bafb",
NewMaxFee: 38533,
ResourceFee: 38233,
SorobanResourcesInstructions: 0,
SorobanResourcesReadBytes: 0,
SorobanResourcesDiskReadBytes: 0,
SorobanResourcesWriteBytes: 0,
TransactionResultCode: "TransactionResultCodeTxFeeBumpInnerSuccess",
InclusionFeeBid: 300,
InclusionFeeCharged: 300,
ResourceFeeRefund: 10705,
TotalNonRefundableResourceFeeCharged: 20230,
TotalRefundableResourceFeeCharged: 7298,
RentFeeCharged: 7278,
TxSigners: []string{"GD2GXC24XWOM6T2UHABEMSYW5UZGJ4U7WEN7AQT2WYW32TQFP4ND3M7O4VGCBTT2BWNILFEVDX5DBBBMK2RTQIBMJNL6F62MAQ53NBAIXUDA"},
},
}
return
}
Expand Down Expand Up @@ -426,6 +468,162 @@ func makeTransactionTestInput() (transaction []ingest.LedgerTransaction, history
},
},
},
// Test case 4: Fee-bump Soroban tx with V4 meta and PostTxApplyFeeChanges (P23+)
// Based on real mainnet tx 5c4f80c4...094116 (ledger 61396807, protocol 25)
{
Index: 1,
UnsafeMeta: xdr.TransactionMeta{
V: 4,
V4: &xdr.TransactionMetaV4{
TxChangesBefore: xdr.LedgerEntryChanges{},
Operations: []xdr.OperationMetaV2{{}},
TxChangesAfter: xdr.LedgerEntryChanges{},
SorobanMeta: &xdr.SorobanTransactionMetaV2{
Ext: xdr.SorobanTransactionMetaExt{
V: 1,
V1: &xdr.SorobanTransactionMetaExtV1{
TotalNonRefundableResourceFeeCharged: 20230,
TotalRefundableResourceFeeCharged: 7298,
RentFeeCharged: 7278,
},
},
},
},
},
Envelope: xdr.TransactionEnvelope{
Type: xdr.EnvelopeTypeEnvelopeTypeTxFeeBump,
FeeBump: &xdr.FeeBumpTransactionEnvelope{
Tx: xdr.FeeBumpTransaction{
FeeSource: testAccount5,
Fee: 38533,
InnerTx: xdr.FeeBumpTransactionInnerTx{
Type: xdr.EnvelopeTypeEnvelopeTypeTx,
V1: &xdr.TransactionV1Envelope{
Tx: xdr.Transaction{
SourceAccount: testAccount1,
SeqNum: 112351890582290871,
Memo: xdr.Memo{
Type: xdr.MemoTypeMemoText,
Text: &hardCodedMemoText,
},
Fee: 38333,
Cond: xdr.Preconditions{
Type: xdr.PreconditionTypePrecondTime,
TimeBounds: &xdr.TimeBounds{
MinTime: 0,
MaxTime: 1594272628,
},
},
Operations: []xdr.Operation{
{
SourceAccount: &testAccount2,
Body: xdr.OperationBody{
Type: xdr.OperationTypePathPaymentStrictReceive,
PathPaymentStrictReceiveOp: &xdr.PathPaymentStrictReceiveOp{
Destination: destination,
},
},
},
},
Ext: xdr.TransactionExt{
V: 1,
SorobanData: &xdr.SorobanTransactionData{
ResourceFee: 38233,
},
},
},
},
},
},
Signatures: []xdr.DecoratedSignature{
{
Hint: xdr.SignatureHint{99, 66, 175, 143},
Signature: xdr.Signature{244, 107, 139, 92, 189, 156, 207, 79, 84, 56, 2, 70, 75, 22, 237, 50, 100, 242, 159, 177, 27, 240, 66, 122, 182, 45, 189, 78, 5, 127, 26, 61, 179, 238, 229, 76, 32, 206, 122, 13, 154, 133, 148, 149, 29, 250, 48, 132, 44, 86, 163, 56, 32, 44, 75, 87, 226, 251, 76, 4, 59, 182, 132, 8},
},
},
},
},
Result: xdr.TransactionResultPair{
TransactionHash: hardCodedTransactionHash,
Result: xdr.TransactionResult{
FeeCharged: 27828,
Result: xdr.TransactionResultResult{
Code: xdr.TransactionResultCodeTxFeeBumpInnerSuccess,
InnerResultPair: &xdr.InnerTransactionResultPair{
TransactionHash: hardCodedTransactionHash,
Result: xdr.InnerTransactionResult{
FeeCharged: 100,
Result: xdr.InnerTransactionResultResult{
Code: xdr.TransactionResultCodeTxSuccess,
Results: &[]xdr.OperationResult{
{
Tr: &xdr.OperationResultTr{
CreateAccountResult: &xdr.CreateAccountResult{},
},
},
},
},
},
},
Results: &[]xdr.OperationResult{{}},
},
},
},
// FeeChanges: fee account balance 4,067,134,559,286 -> 4,067,134,520,753 (deducted 38,533)
FeeChanges: xdr.LedgerEntryChanges{
{
Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
State: &xdr.LedgerEntry{
Data: xdr.LedgerEntryData{
Type: xdr.LedgerEntryTypeAccount,
Account: &xdr.AccountEntry{
AccountId: testAccount5ID,
Balance: 4067134559286,
},
},
},
},
{
Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
Updated: &xdr.LedgerEntry{
Data: xdr.LedgerEntryData{
Type: xdr.LedgerEntryTypeAccount,
Account: &xdr.AccountEntry{
AccountId: testAccount5ID,
Balance: 4067134520753,
},
},
},
},
},
// PostTxApplyFeeChanges: fee account balance 4,067,134,520,753 -> 4,067,134,531,458 (refund 10,705)
PostTxApplyFeeChanges: xdr.LedgerEntryChanges{
{
Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
State: &xdr.LedgerEntry{
Data: xdr.LedgerEntryData{
Type: xdr.LedgerEntryTypeAccount,
Account: &xdr.AccountEntry{
AccountId: testAccount5ID,
Balance: 4067134520753,
},
},
},
},
{
Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
Updated: &xdr.LedgerEntry{
Data: xdr.LedgerEntryData{
Type: xdr.LedgerEntryTypeAccount,
Account: &xdr.AccountEntry{
AccountId: testAccount5ID,
Balance: 4067134531458,
},
},
},
},
},
},
}
historyHeader = []xdr.LedgerHeaderHistoryEntry{
{
Expand All @@ -446,6 +644,13 @@ func makeTransactionTestInput() (transaction []ingest.LedgerTransaction, history
ScpValue: xdr.StellarValue{CloseTime: 1594272522},
},
},
{
Header: xdr.LedgerHeader{
LedgerSeq: 61396807,
LedgerVersion: 25,
ScpValue: xdr.StellarValue{CloseTime: 1594272522},
},
},
}
return
}
Loading