github.com/stellar/stellar-etl@v1.0.1-0.20240312145900-4874b6bf2b89/internal/transform/transaction_test.go (about) 1 package transform 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/guregu/null" 9 "github.com/lib/pq" 10 "github.com/stretchr/testify/assert" 11 12 "github.com/stellar/go/ingest" 13 "github.com/stellar/go/xdr" 14 ) 15 16 func TestTransformTransaction(t *testing.T) { 17 type inputStruct struct { 18 transaction ingest.LedgerTransaction 19 historyHeader xdr.LedgerHeaderHistoryEntry 20 } 21 type transformTest struct { 22 input inputStruct 23 wantOutput TransactionOutput 24 wantErr error 25 } 26 genericInput := inputStruct{genericLedgerTransaction, genericLedgerHeaderHistoryEntry} 27 negativeSeqInput := genericInput 28 negativeSeqEnvelope := genericBumpOperationEnvelopeForTransaction 29 negativeSeqEnvelope.Tx.SeqNum = xdr.SequenceNumber(-1) 30 negativeSeqInput.transaction.Envelope.V1 = &negativeSeqEnvelope 31 32 badTimeboundInput := genericInput 33 badTimeboundEnvelope := genericBumpOperationEnvelopeForTransaction 34 badTimeboundEnvelope.Tx.Cond.Type = xdr.PreconditionTypePrecondTime 35 badTimeboundEnvelope.Tx.Cond.TimeBounds = &xdr.TimeBounds{ 36 MinTime: 1594586912, 37 MaxTime: 100, 38 } 39 badTimeboundInput.transaction.Envelope.V1 = &badTimeboundEnvelope 40 41 badFeeChargedInput := genericInput 42 badFeeChargedInput.transaction.Result.Result.FeeCharged = -1 43 44 hardCodedTransaction, hardCodedLedgerHeader, err := makeTransactionTestInput() 45 assert.NoError(t, err) 46 hardCodedOutput, err := makeTransactionTestOutput() 47 assert.NoError(t, err) 48 49 tests := []transformTest{ 50 transformTest{ 51 negativeSeqInput, 52 TransactionOutput{}, 53 fmt.Errorf("The account's sequence number (-1) is negative for ledger 0; transaction 1 (transaction id=4096)"), 54 }, 55 { 56 badFeeChargedInput, 57 TransactionOutput{}, 58 fmt.Errorf("The fee charged (-1) is negative for ledger 0; transaction 1 (transaction id=4096)"), 59 }, 60 { 61 badTimeboundInput, 62 TransactionOutput{}, 63 fmt.Errorf("The max time is earlier than the min time (100 < 1594586912) for ledger 0; transaction 1 (transaction id=4096)"), 64 }, 65 } 66 67 for i := range hardCodedTransaction { 68 tests = append(tests, transformTest{ 69 input: inputStruct{hardCodedTransaction[i], hardCodedLedgerHeader[i]}, 70 wantOutput: hardCodedOutput[i], 71 wantErr: nil, 72 }) 73 } 74 75 for _, test := range tests { 76 actualOutput, actualError := TransformTransaction(test.input.transaction, test.input.historyHeader) 77 assert.Equal(t, test.wantErr, actualError) 78 assert.Equal(t, test.wantOutput, actualOutput) 79 } 80 } 81 82 func makeTransactionTestOutput() (output []TransactionOutput, err error) { 83 correctTime, err := time.Parse("2006-1-2 15:04:05 MST", "2020-07-09 05:28:42 UTC") 84 output = []TransactionOutput{ 85 TransactionOutput{ 86 TxEnvelope: "AAAAAgAAAACI4aa0pXFSj6qfJuIObLw/5zyugLRGYwxb7wFSr3B9eAABX5ABjydzAABBtwAAAAEAAAAAAAAAAAAAAABfBqt0AAAAAQAAABdITDVhQ2dvelFISVc3c1NjNVhkY2ZtUgAAAAABAAAAAQAAAAAcR0GXGO76pFs4y38vJVAanjnLg4emNun7zAx0pHcDGAAAAAIAAAAAAAAAAAAAAAAAAAAAAQIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", 87 TxResult: "AAAAAAAAASz/////AAAAAQAAAAAAAAAAAAAAAAAAAAA=", 88 TxMeta: "AAAAAQAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAFAQIDBAUGBwgJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVU1NEAAAAAGtY3WxokwttAx3Fu/riPvoew/C7WMK8jZONR8Hfs75zAAAAHgAAAAAAAYagAAAAAAAAA+gAAAAAAAAB9AAAAAAAAAAZAAAAAAAAAAEAAAAAAAAABQECAwQFBgcICQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVNTRAAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAB4AAAAAAAGKiAAAAAAAAARMAAAAAAAAAfYAAAAAAAAAGgAAAAAAAAACAAAAAwAAAAAAAAAFAQIDBAUGBwgJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVU1NEAAAAAGtY3WxokwttAx3Fu/riPvoew/C7WMK8jZONR8Hfs75zAAAAHgAAAAAAAYagAAAAAAAAA+gAAAAAAAAB9AAAAAAAAAAZAAAAAAAAAAEAAAAAAAAABQECAwQFBgcICQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVNTRAAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAB4AAAAAAAGKiAAAAAAAAARMAAAAAAAAAfYAAAAAAAAAGgAAAAAAAAAA", 89 TxFeeMeta: "AAAAAA==", 90 TransactionHash: "a87fef5eeb260269c380f2de456aad72b59bb315aaac777860456e09dac0bafb", 91 LedgerSequence: 30521816, 92 TransactionID: 131090201534533632, 93 Account: testAccount1Address, 94 AccountSequence: 112351890582290871, 95 MaxFee: 90000, 96 FeeCharged: 300, 97 OperationCount: 1, 98 CreatedAt: correctTime, 99 MemoType: "MemoTypeMemoText", 100 Memo: "HL5aCgozQHIW7sSc5XdcfmR", 101 TimeBounds: "[0,1594272628)", 102 Successful: false, 103 ClosedAt: time.Date(2020, time.July, 9, 5, 28, 42, 0, time.UTC), 104 ResourceFee: 0, 105 SorobanResourcesInstructions: 0, 106 SorobanResourcesReadBytes: 0, 107 SorobanResourcesWriteBytes: 0, 108 TransactionResultCode: "TransactionResultCodeTxFailed", 109 }, 110 TransactionOutput{ 111 TxEnvelope: "AAAABQAAAABnzACGTDuJFoxqr+C8NHCe0CHFBXLi+YhhNCIILCIpcgAAAAAAABwgAAAAAgAAAACI4aa0pXFSj6qfJuIObLw/5zyugLRGYwxb7wFSr3B9eAAAAAACFPY2AAAAfQAAAAEAAAAAAAAAAAAAAABfBqt0AAAAAQAAABdITDVhQ2dvelFISVc3c1NjNVhkY2ZtUgAAAAABAAAAAQAAAAAcR0GXGO76pFs4y38vJVAanjnLg4emNun7zAx0pHcDGAAAAAIAAAAAAAAAAAAAAAAAAAAAAQIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", 112 TxResult: "AAAAAAAAASwAAAABqH/vXusmAmnDgPLeRWqtcrWbsxWqrHd4YEVuCdrAuvsAAAAAAAAAZAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=", 113 TxMeta: "AAAAAQAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAFAQIDBAUGBwgJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVU1NEAAAAAGtY3WxokwttAx3Fu/riPvoew/C7WMK8jZONR8Hfs75zAAAAHgAAAAAAAYagAAAAAAAAA+gAAAAAAAAB9AAAAAAAAAAZAAAAAAAAAAEAAAAAAAAABQECAwQFBgcICQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVNTRAAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAB4AAAAAAAGKiAAAAAAAAARMAAAAAAAAAfYAAAAAAAAAGgAAAAAAAAACAAAAAwAAAAAAAAAFAQIDBAUGBwgJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVU1NEAAAAAGtY3WxokwttAx3Fu/riPvoew/C7WMK8jZONR8Hfs75zAAAAHgAAAAAAAYagAAAAAAAAA+gAAAAAAAAB9AAAAAAAAAAZAAAAAAAAAAEAAAAAAAAABQECAwQFBgcICQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVNTRAAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAB4AAAAAAAGKiAAAAAAAAARMAAAAAAAAAfYAAAAAAAAAGgAAAAAAAAAA", 114 TxFeeMeta: "AAAAAA==", 115 TransactionHash: "a87fef5eeb260269c380f2de456aad72b59bb315aaac777860456e09dac0bafb", 116 LedgerSequence: 30521817, 117 TransactionID: 131090205829500928, 118 Account: testAccount1Address, 119 AccountSequence: 150015399398735997, 120 MaxFee: 0, 121 FeeCharged: 300, 122 OperationCount: 1, 123 CreatedAt: correctTime, 124 MemoType: "MemoTypeMemoText", 125 Memo: "HL5aCgozQHIW7sSc5XdcfmR", 126 TimeBounds: "[0,1594272628)", 127 Successful: true, 128 InnerTransactionHash: "a87fef5eeb260269c380f2de456aad72b59bb315aaac777860456e09dac0bafb", 129 FeeAccount: testAccount3Address, 130 NewMaxFee: 7200, 131 ClosedAt: time.Date(2020, time.July, 9, 5, 28, 42, 0, time.UTC), 132 ResourceFee: 0, 133 SorobanResourcesInstructions: 0, 134 SorobanResourcesReadBytes: 0, 135 SorobanResourcesWriteBytes: 0, 136 TransactionResultCode: "TransactionResultCodeTxFeeBumpInnerSuccess", //inner fee bump success 137 }, 138 TransactionOutput{ 139 TxEnvelope: "AAAAAgAAAAAcR0GXGO76pFs4y38vJVAanjnLg4emNun7zAx0pHcDGAAAAGQBpLyvsiV6gwAAAAIAAAABAAAAAAAAAAAAAAAAXwardAAAAAEAAAAFAAAACgAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABdITDVhQ2dvelFISVc3c1NjNVhkY2ZtUgAAAAABAAAAAQAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAAIAAAAAAAAAAAAAAAAAAAAAAQIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", 140 TxResult: "AAAAAAAAAGT////5AAAAAA==", 141 TxMeta: "AAAAAQAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAFAQIDBAUGBwgJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVU1NEAAAAAGtY3WxokwttAx3Fu/riPvoew/C7WMK8jZONR8Hfs75zAAAAHgAAAAAAAYagAAAAAAAAA+gAAAAAAAAB9AAAAAAAAAAZAAAAAAAAAAEAAAAAAAAABQECAwQFBgcICQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVNTRAAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAB4AAAAAAAGKiAAAAAAAAARMAAAAAAAAAfYAAAAAAAAAGgAAAAAAAAACAAAAAwAAAAAAAAAFAQIDBAUGBwgJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVU1NEAAAAAGtY3WxokwttAx3Fu/riPvoew/C7WMK8jZONR8Hfs75zAAAAHgAAAAAAAYagAAAAAAAAA+gAAAAAAAAB9AAAAAAAAAAZAAAAAAAAAAEAAAAAAAAABQECAwQFBgcICQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVNTRAAAAABrWN1saJMLbQMdxbv64j76HsPwu1jCvI2TjUfB37O+cwAAAB4AAAAAAAGKiAAAAAAAAARMAAAAAAAAAfYAAAAAAAAAGgAAAAAAAAAA", 142 TxFeeMeta: "AAAAAA==", 143 TransactionHash: "a87fef5eeb260269c380f2de456aad72b59bb315aaac777860456e09dac0bafb", 144 LedgerSequence: 30521818, 145 TransactionID: 131090210124468224, 146 Account: testAccount2Address, 147 AccountSequence: 118426953012574851, 148 MaxFee: 100, 149 FeeCharged: 100, 150 OperationCount: 1, 151 CreatedAt: correctTime, 152 MemoType: "MemoTypeMemoText", 153 Memo: "HL5aCgozQHIW7sSc5XdcfmR", 154 TimeBounds: "[0,1594272628)", 155 Successful: false, 156 LedgerBounds: "[5,10)", 157 ExtraSigners: pq.StringArray{"GABQEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7QL"}, 158 MinAccountSequenceAge: null.IntFrom(0), 159 MinAccountSequenceLedgerGap: null.IntFrom(0), 160 ClosedAt: time.Date(2020, time.July, 9, 5, 28, 42, 0, time.UTC), 161 ResourceFee: 0, 162 SorobanResourcesInstructions: 0, 163 SorobanResourcesReadBytes: 0, 164 SorobanResourcesWriteBytes: 0, 165 TransactionResultCode: "TransactionResultCodeTxInsufficientBalance", 166 }, 167 } 168 return 169 } 170 func makeTransactionTestInput() (transaction []ingest.LedgerTransaction, historyHeader []xdr.LedgerHeaderHistoryEntry, err error) { 171 hardCodedMemoText := "HL5aCgozQHIW7sSc5XdcfmR" 172 hardCodedTransactionHash := xdr.Hash([32]byte{0xa8, 0x7f, 0xef, 0x5e, 0xeb, 0x26, 0x2, 0x69, 0xc3, 0x80, 0xf2, 0xde, 0x45, 0x6a, 0xad, 0x72, 0xb5, 0x9b, 0xb3, 0x15, 0xaa, 0xac, 0x77, 0x78, 0x60, 0x45, 0x6e, 0x9, 0xda, 0xc0, 0xba, 0xfb}) 173 genericResultResults := &[]xdr.OperationResult{ 174 xdr.OperationResult{ 175 Tr: &xdr.OperationResultTr{ 176 Type: xdr.OperationTypeCreateAccount, 177 CreateAccountResult: &xdr.CreateAccountResult{ 178 Code: 0, 179 }, 180 }, 181 }, 182 } 183 hardCodedMeta := xdr.TransactionMeta{ 184 V: 1, 185 V1: genericTxMeta, 186 } 187 188 source := xdr.MuxedAccount{ 189 Type: xdr.CryptoKeyTypeKeyTypeEd25519, 190 Ed25519: &xdr.Uint256{3, 2, 1}, 191 } 192 destination := xdr.MuxedAccount{ 193 Type: xdr.CryptoKeyTypeKeyTypeEd25519, 194 Ed25519: &xdr.Uint256{1, 2, 3}, 195 } 196 signerKey := xdr.SignerKey{ 197 Type: xdr.SignerKeyTypeSignerKeyTypeEd25519, 198 Ed25519: source.Ed25519, 199 } 200 transaction = []ingest.LedgerTransaction{ 201 ingest.LedgerTransaction{ 202 Index: 1, 203 UnsafeMeta: hardCodedMeta, 204 Envelope: xdr.TransactionEnvelope{ 205 Type: xdr.EnvelopeTypeEnvelopeTypeTx, 206 V1: &xdr.TransactionV1Envelope{ 207 Tx: xdr.Transaction{ 208 SourceAccount: testAccount1, 209 SeqNum: 112351890582290871, 210 Memo: xdr.Memo{ 211 Type: xdr.MemoTypeMemoText, 212 Text: &hardCodedMemoText, 213 }, 214 Fee: 90000, 215 Cond: xdr.Preconditions{ 216 Type: xdr.PreconditionTypePrecondTime, 217 TimeBounds: &xdr.TimeBounds{ 218 MinTime: 0, 219 MaxTime: 1594272628, 220 }, 221 }, 222 Operations: []xdr.Operation{ 223 xdr.Operation{ 224 SourceAccount: &testAccount2, 225 Body: xdr.OperationBody{ 226 Type: xdr.OperationTypePathPaymentStrictReceive, 227 PathPaymentStrictReceiveOp: &xdr.PathPaymentStrictReceiveOp{ 228 Destination: destination, 229 }, 230 }, 231 }, 232 }, 233 }, 234 }, 235 }, 236 Result: xdr.TransactionResultPair{ 237 TransactionHash: hardCodedTransactionHash, 238 Result: xdr.TransactionResult{ 239 FeeCharged: 300, 240 Result: xdr.TransactionResultResult{ 241 Code: xdr.TransactionResultCodeTxFailed, 242 Results: genericResultResults, 243 }, 244 }, 245 }, 246 }, 247 ingest.LedgerTransaction{ 248 Index: 1, 249 UnsafeMeta: hardCodedMeta, 250 Envelope: xdr.TransactionEnvelope{ 251 Type: xdr.EnvelopeTypeEnvelopeTypeTxFeeBump, 252 FeeBump: &xdr.FeeBumpTransactionEnvelope{ 253 Tx: xdr.FeeBumpTransaction{ 254 FeeSource: testAccount3, 255 Fee: 7200, 256 InnerTx: xdr.FeeBumpTransactionInnerTx{ 257 Type: xdr.EnvelopeTypeEnvelopeTypeTx, 258 V1: &xdr.TransactionV1Envelope{ 259 Tx: xdr.Transaction{ 260 SourceAccount: testAccount1, 261 SeqNum: 150015399398735997, 262 Memo: xdr.Memo{ 263 Type: xdr.MemoTypeMemoText, 264 Text: &hardCodedMemoText, 265 }, 266 Cond: xdr.Preconditions{ 267 Type: xdr.PreconditionTypePrecondTime, 268 TimeBounds: &xdr.TimeBounds{ 269 MinTime: 0, 270 MaxTime: 1594272628, 271 }, 272 }, 273 Operations: []xdr.Operation{ 274 xdr.Operation{ 275 SourceAccount: &testAccount2, 276 Body: xdr.OperationBody{ 277 Type: xdr.OperationTypePathPaymentStrictReceive, 278 PathPaymentStrictReceiveOp: &xdr.PathPaymentStrictReceiveOp{ 279 Destination: destination, 280 }, 281 }, 282 }, 283 }, 284 }, 285 }, 286 }, 287 }, 288 }, 289 }, 290 Result: xdr.TransactionResultPair{ 291 TransactionHash: hardCodedTransactionHash, 292 Result: xdr.TransactionResult{ 293 FeeCharged: 300, 294 Result: xdr.TransactionResultResult{ 295 Code: xdr.TransactionResultCodeTxFeeBumpInnerSuccess, 296 InnerResultPair: &xdr.InnerTransactionResultPair{ 297 TransactionHash: hardCodedTransactionHash, 298 Result: xdr.InnerTransactionResult{ 299 FeeCharged: 100, 300 Result: xdr.InnerTransactionResultResult{ 301 Code: xdr.TransactionResultCodeTxSuccess, 302 Results: &[]xdr.OperationResult{ 303 xdr.OperationResult{ 304 Tr: &xdr.OperationResultTr{ 305 CreateAccountResult: &xdr.CreateAccountResult{}, 306 }, 307 }, 308 }, 309 }, 310 }, 311 }, 312 Results: &[]xdr.OperationResult{ 313 xdr.OperationResult{}, 314 }, 315 }, 316 }, 317 }, 318 }, 319 ingest.LedgerTransaction{ 320 Index: 1, 321 UnsafeMeta: hardCodedMeta, 322 Envelope: xdr.TransactionEnvelope{ 323 Type: xdr.EnvelopeTypeEnvelopeTypeTx, 324 V1: &xdr.TransactionV1Envelope{ 325 Tx: xdr.Transaction{ 326 SourceAccount: testAccount2, 327 SeqNum: 118426953012574851, 328 Memo: xdr.Memo{ 329 Type: xdr.MemoTypeMemoText, 330 Text: &hardCodedMemoText, 331 }, 332 Fee: 100, 333 Cond: xdr.Preconditions{ 334 Type: xdr.PreconditionTypePrecondV2, 335 V2: &xdr.PreconditionsV2{ 336 TimeBounds: &xdr.TimeBounds{ 337 MinTime: 0, 338 MaxTime: 1594272628, 339 }, 340 LedgerBounds: &xdr.LedgerBounds{ 341 MinLedger: 5, 342 MaxLedger: 10, 343 }, 344 ExtraSigners: []xdr.SignerKey{signerKey}, 345 }, 346 }, 347 Operations: []xdr.Operation{ 348 xdr.Operation{ 349 SourceAccount: &testAccount4, 350 Body: xdr.OperationBody{ 351 Type: xdr.OperationTypePathPaymentStrictReceive, 352 PathPaymentStrictReceiveOp: &xdr.PathPaymentStrictReceiveOp{ 353 Destination: destination, 354 }, 355 }, 356 }, 357 }, 358 }, 359 }, 360 }, 361 Result: xdr.TransactionResultPair{ 362 TransactionHash: hardCodedTransactionHash, 363 Result: xdr.TransactionResult{ 364 FeeCharged: 100, 365 Result: xdr.TransactionResultResult{ 366 Code: xdr.TransactionResultCodeTxInsufficientBalance, 367 Results: genericResultResults, 368 }, 369 }, 370 }, 371 }, 372 } 373 historyHeader = []xdr.LedgerHeaderHistoryEntry{ 374 xdr.LedgerHeaderHistoryEntry{ 375 Header: xdr.LedgerHeader{ 376 LedgerSeq: 30521816, 377 ScpValue: xdr.StellarValue{CloseTime: 1594272522}, 378 }, 379 }, 380 xdr.LedgerHeaderHistoryEntry{ 381 Header: xdr.LedgerHeader{ 382 LedgerSeq: 30521817, 383 ScpValue: xdr.StellarValue{CloseTime: 1594272522}, 384 }, 385 }, 386 xdr.LedgerHeaderHistoryEntry{ 387 Header: xdr.LedgerHeader{ 388 LedgerSeq: 30521818, 389 ScpValue: xdr.StellarValue{CloseTime: 1594272522}, 390 }, 391 }, 392 } 393 return 394 }