github.com/stellar/stellar-etl@v1.0.1-0.20240312145900-4874b6bf2b89/internal/transform/trade_test.go (about)

     1  package transform
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/guregu/null"
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"github.com/stellar/stellar-etl/internal/utils"
    12  
    13  	"github.com/stellar/go/ingest"
    14  	"github.com/stellar/go/xdr"
    15  )
    16  
    17  func TestTransformTrade(t *testing.T) {
    18  	type tradeInput struct {
    19  		index       int32
    20  		transaction ingest.LedgerTransaction
    21  		closeTime   time.Time
    22  	}
    23  	type transformTest struct {
    24  		input      tradeInput
    25  		wantOutput []TradeOutput
    26  		wantErr    error
    27  	}
    28  
    29  	hardCodedInputTransaction := makeTradeTestInput()
    30  	hardCodedOutputArray := makeTradeTestOutput()
    31  
    32  	genericInput := tradeInput{
    33  		index:       0,
    34  		transaction: genericLedgerTransaction,
    35  		closeTime:   genericCloseTime,
    36  	}
    37  
    38  	wrongTypeInput := genericInput
    39  	wrongTypeInput.transaction = ingest.LedgerTransaction{
    40  		Index: 1,
    41  		Envelope: xdr.TransactionEnvelope{
    42  			Type: xdr.EnvelopeTypeEnvelopeTypeTx,
    43  			V1: &xdr.TransactionV1Envelope{
    44  				Tx: xdr.Transaction{
    45  					SourceAccount: genericSourceAccount,
    46  					Memo:          xdr.Memo{},
    47  					Operations: []xdr.Operation{
    48  						genericBumpOperation,
    49  					},
    50  				},
    51  			},
    52  		},
    53  		Result: utils.CreateSampleResultMeta(true, 1).Result,
    54  	}
    55  
    56  	resultOutOfRangeInput := genericInput
    57  	resultOutOfRangeEnvelope := genericManageBuyOfferEnvelope
    58  	resultOutOfRangeInput.transaction.Envelope.V1 = &resultOutOfRangeEnvelope
    59  	resultOutOfRangeInput.transaction.Result = wrapOperationsResultsSlice([]xdr.OperationResult{}, true)
    60  
    61  	failedTxInput := genericInput
    62  	failedTxInput.transaction.Result = wrapOperationsResultsSlice([]xdr.OperationResult{}, false)
    63  
    64  	noTrInput := genericInput
    65  	noTrEnvelope := genericManageBuyOfferEnvelope
    66  	noTrInput.transaction.Envelope.V1 = &noTrEnvelope
    67  	noTrInput.transaction.Result = wrapOperationsResultsSlice([]xdr.OperationResult{
    68  		xdr.OperationResult{Tr: nil},
    69  	}, true)
    70  
    71  	failedResultInput := genericInput
    72  	failedResultEnvelope := genericManageBuyOfferEnvelope
    73  	failedResultInput.transaction.Envelope.V1 = &failedResultEnvelope
    74  	failedResultInput.transaction.Result = wrapOperationsResultsSlice([]xdr.OperationResult{
    75  		xdr.OperationResult{
    76  			Tr: &xdr.OperationResultTr{
    77  				Type: xdr.OperationTypeManageBuyOffer,
    78  				ManageBuyOfferResult: &xdr.ManageBuyOfferResult{
    79  					Code: xdr.ManageBuyOfferResultCodeManageBuyOfferMalformed,
    80  				},
    81  			}},
    82  	}, true)
    83  
    84  	negBaseAmountInput := genericInput
    85  	negBaseAmountEnvelope := genericManageBuyOfferEnvelope
    86  	negBaseAmountInput.transaction.Envelope.V1 = &negBaseAmountEnvelope
    87  	negBaseAmountInput.transaction.Result = wrapOperationsResultsSlice([]xdr.OperationResult{
    88  		xdr.OperationResult{
    89  			Tr: &xdr.OperationResultTr{
    90  				Type: xdr.OperationTypeManageBuyOffer,
    91  				ManageBuyOfferResult: &xdr.ManageBuyOfferResult{
    92  					Code: xdr.ManageBuyOfferResultCodeManageBuyOfferSuccess,
    93  					Success: &xdr.ManageOfferSuccessResult{
    94  						OffersClaimed: []xdr.ClaimAtom{
    95  							xdr.ClaimAtom{
    96  								Type: xdr.ClaimAtomTypeClaimAtomTypeOrderBook,
    97  								OrderBook: &xdr.ClaimOfferAtom{
    98  									SellerId:   genericAccountID,
    99  									AmountSold: -1,
   100  								},
   101  							},
   102  						},
   103  					},
   104  				},
   105  			}},
   106  	}, true)
   107  
   108  	negCounterAmountInput := genericInput
   109  	negCounterAmountEnvelope := genericManageBuyOfferEnvelope
   110  	negCounterAmountInput.transaction.Envelope.V1 = &negCounterAmountEnvelope
   111  	negCounterAmountInput.transaction.Result = wrapOperationsResultsSlice([]xdr.OperationResult{
   112  		xdr.OperationResult{
   113  			Tr: &xdr.OperationResultTr{
   114  				Type: xdr.OperationTypeManageBuyOffer,
   115  				ManageBuyOfferResult: &xdr.ManageBuyOfferResult{
   116  					Code: xdr.ManageBuyOfferResultCodeManageBuyOfferSuccess,
   117  					Success: &xdr.ManageOfferSuccessResult{
   118  						OffersClaimed: []xdr.ClaimAtom{
   119  							xdr.ClaimAtom{
   120  								Type: xdr.ClaimAtomTypeClaimAtomTypeOrderBook,
   121  								OrderBook: &xdr.ClaimOfferAtom{
   122  									SellerId:     genericAccountID,
   123  									AmountBought: -2,
   124  								},
   125  							},
   126  						},
   127  					},
   128  				},
   129  			}},
   130  	}, true)
   131  
   132  	tests := []transformTest{
   133  		{
   134  			wrongTypeInput,
   135  			[]TradeOutput{}, fmt.Errorf("Operation of type OperationTypeBumpSequence at index 0 does not result in trades"),
   136  		},
   137  		{
   138  			resultOutOfRangeInput,
   139  			[]TradeOutput{}, fmt.Errorf("Operation index of 0 is out of bounds in result slice (len = 0)"),
   140  		},
   141  		{
   142  			failedTxInput,
   143  			[]TradeOutput{}, fmt.Errorf("Transaction failed; no trades"),
   144  		},
   145  		{
   146  			noTrInput,
   147  			[]TradeOutput{}, fmt.Errorf("Could not get result Tr for operation at index 0"),
   148  		},
   149  		{
   150  			failedResultInput,
   151  			[]TradeOutput{}, fmt.Errorf("Could not get ManageOfferSuccess for operation at index 0"),
   152  		},
   153  		{
   154  			negBaseAmountInput,
   155  			[]TradeOutput{}, fmt.Errorf("Amount sold is negative (-1) for operation at index 0"),
   156  		},
   157  		{
   158  			negCounterAmountInput,
   159  			[]TradeOutput{}, fmt.Errorf("Amount bought is negative (-2) for operation at index 0"),
   160  		},
   161  	}
   162  
   163  	for i := range hardCodedInputTransaction.Envelope.Operations() {
   164  		tests = append(tests, transformTest{
   165  			input:      tradeInput{index: int32(i), transaction: hardCodedInputTransaction, closeTime: genericCloseTime},
   166  			wantOutput: hardCodedOutputArray[i],
   167  			wantErr:    nil,
   168  		})
   169  	}
   170  
   171  	for _, test := range tests {
   172  		actualOutput, actualError := TransformTrade(test.input.index, 100, test.input.transaction, test.input.closeTime)
   173  		assert.Equal(t, test.wantErr, actualError)
   174  		assert.Equal(t, test.wantOutput, actualOutput)
   175  	}
   176  }
   177  
   178  func wrapOperationsResultsSlice(results []xdr.OperationResult, successful bool) xdr.TransactionResultPair {
   179  	resultCode := xdr.TransactionResultCodeTxFailed
   180  	if successful {
   181  		resultCode = xdr.TransactionResultCodeTxSuccess
   182  	}
   183  	return xdr.TransactionResultPair{
   184  		Result: xdr.TransactionResult{
   185  			Result: xdr.TransactionResultResult{
   186  				Code:    resultCode,
   187  				Results: &results,
   188  			},
   189  		},
   190  	}
   191  }
   192  
   193  func makeTradeTestInput() (inputTransaction ingest.LedgerTransaction) {
   194  	inputTransaction = genericLedgerTransaction
   195  	inputEnvelope := genericBumpOperationEnvelope
   196  
   197  	inputEnvelope.Tx.SourceAccount = testAccount3
   198  	offerOne := xdr.ClaimAtom{
   199  		Type: xdr.ClaimAtomTypeClaimAtomTypeOrderBook,
   200  		OrderBook: &xdr.ClaimOfferAtom{
   201  			SellerId:     testAccount1ID,
   202  			OfferId:      97684906,
   203  			AssetSold:    ethAsset,
   204  			AssetBought:  usdtAsset,
   205  			AmountSold:   13300347,
   206  			AmountBought: 12634,
   207  		},
   208  	}
   209  	offerTwo := xdr.ClaimAtom{
   210  		Type: xdr.ClaimAtomTypeClaimAtomTypeOrderBook,
   211  		OrderBook: &xdr.ClaimOfferAtom{
   212  			SellerId:     testAccount3ID,
   213  			OfferId:      86106895,
   214  			AssetSold:    usdtAsset,
   215  			AssetBought:  nativeAsset,
   216  			AmountSold:   500,
   217  			AmountBought: 20,
   218  		},
   219  	}
   220  	lPOne := xdr.ClaimAtom{
   221  		Type: xdr.ClaimAtomTypeClaimAtomTypeLiquidityPool,
   222  		LiquidityPool: &xdr.ClaimLiquidityAtom{
   223  			LiquidityPoolId: xdr.PoolId{4, 5, 6},
   224  			AssetSold:       xdr.MustNewCreditAsset("WER", testAccount4Address),
   225  			AmountSold:      123,
   226  			AssetBought:     xdr.MustNewCreditAsset("NIJ", testAccount1Address),
   227  			AmountBought:    456,
   228  		},
   229  	}
   230  
   231  	lPTwo := xdr.ClaimAtom{
   232  		Type: xdr.ClaimAtomTypeClaimAtomTypeLiquidityPool,
   233  		LiquidityPool: &xdr.ClaimLiquidityAtom{
   234  			LiquidityPoolId: xdr.PoolId{1, 2, 3, 4, 5, 6},
   235  			AssetSold:       xdr.MustNewCreditAsset("HAH", testAccount1Address),
   236  			AmountSold:      1,
   237  			AssetBought:     xdr.MustNewCreditAsset("WHO", testAccount4Address),
   238  			AmountBought:    1,
   239  		},
   240  	}
   241  
   242  	inputOperations := []xdr.Operation{
   243  
   244  		xdr.Operation{
   245  			SourceAccount: nil,
   246  			Body: xdr.OperationBody{
   247  				Type:              xdr.OperationTypeManageSellOffer,
   248  				ManageSellOfferOp: &xdr.ManageSellOfferOp{},
   249  			},
   250  		},
   251  
   252  		xdr.Operation{
   253  			SourceAccount: nil,
   254  			Body: xdr.OperationBody{
   255  				Type:             xdr.OperationTypeManageBuyOffer,
   256  				ManageBuyOfferOp: &xdr.ManageBuyOfferOp{},
   257  			},
   258  		},
   259  		xdr.Operation{
   260  			SourceAccount: nil,
   261  			Body: xdr.OperationBody{
   262  				Type: xdr.OperationTypePathPaymentStrictSend,
   263  				PathPaymentStrictSendOp: &xdr.PathPaymentStrictSendOp{
   264  					Destination: testAccount1,
   265  				},
   266  			},
   267  		},
   268  		xdr.Operation{
   269  			SourceAccount: &testAccount3,
   270  			Body: xdr.OperationBody{
   271  				Type: xdr.OperationTypePathPaymentStrictReceive,
   272  				PathPaymentStrictReceiveOp: &xdr.PathPaymentStrictReceiveOp{
   273  					Destination: testAccount1,
   274  				},
   275  			},
   276  		},
   277  		xdr.Operation{
   278  			SourceAccount: &testAccount3,
   279  			Body: xdr.OperationBody{
   280  				Type:                    xdr.OperationTypePathPaymentStrictSend,
   281  				PathPaymentStrictSendOp: &xdr.PathPaymentStrictSendOp{},
   282  			},
   283  		},
   284  		xdr.Operation{
   285  			SourceAccount: &testAccount3,
   286  			Body: xdr.OperationBody{
   287  				Type:                       xdr.OperationTypePathPaymentStrictReceive,
   288  				PathPaymentStrictReceiveOp: &xdr.PathPaymentStrictReceiveOp{},
   289  			},
   290  		},
   291  		xdr.Operation{
   292  			SourceAccount: nil,
   293  			Body: xdr.OperationBody{
   294  				Type:                     xdr.OperationTypeCreatePassiveSellOffer,
   295  				CreatePassiveSellOfferOp: &xdr.CreatePassiveSellOfferOp{},
   296  			},
   297  		},
   298  	}
   299  	inputEnvelope.Tx.Operations = inputOperations
   300  	results := []xdr.OperationResult{
   301  		xdr.OperationResult{
   302  			Code: xdr.OperationResultCodeOpInner,
   303  			Tr: &xdr.OperationResultTr{
   304  				Type: xdr.OperationTypeManageSellOffer,
   305  				ManageSellOfferResult: &xdr.ManageSellOfferResult{
   306  					Code: xdr.ManageSellOfferResultCodeManageSellOfferSuccess,
   307  					Success: &xdr.ManageOfferSuccessResult{
   308  						OffersClaimed: []xdr.ClaimAtom{
   309  							offerOne,
   310  						},
   311  					},
   312  				},
   313  			},
   314  		},
   315  
   316  		xdr.OperationResult{
   317  			Tr: &xdr.OperationResultTr{
   318  				Type: xdr.OperationTypeManageBuyOffer,
   319  				ManageBuyOfferResult: &xdr.ManageBuyOfferResult{
   320  					Code: xdr.ManageBuyOfferResultCodeManageBuyOfferSuccess,
   321  					Success: &xdr.ManageOfferSuccessResult{
   322  						OffersClaimed: []xdr.ClaimAtom{
   323  							offerTwo,
   324  						},
   325  					},
   326  				},
   327  			},
   328  		},
   329  		xdr.OperationResult{
   330  			Code: xdr.OperationResultCodeOpInner,
   331  			Tr: &xdr.OperationResultTr{
   332  				Type: xdr.OperationTypePathPaymentStrictSend,
   333  				PathPaymentStrictSendResult: &xdr.PathPaymentStrictSendResult{
   334  					Code: xdr.PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess,
   335  					Success: &xdr.PathPaymentStrictSendResultSuccess{
   336  						Offers: []xdr.ClaimAtom{
   337  							offerOne, offerTwo,
   338  						},
   339  					},
   340  				},
   341  			},
   342  		},
   343  		xdr.OperationResult{
   344  			Code: xdr.OperationResultCodeOpInner,
   345  			Tr: &xdr.OperationResultTr{
   346  				Type: xdr.OperationTypePathPaymentStrictReceive,
   347  				PathPaymentStrictReceiveResult: &xdr.PathPaymentStrictReceiveResult{
   348  					Code: xdr.PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess,
   349  					Success: &xdr.PathPaymentStrictReceiveResultSuccess{
   350  						Offers: []xdr.ClaimAtom{
   351  							offerTwo, offerOne,
   352  						},
   353  					},
   354  				},
   355  			},
   356  		},
   357  		xdr.OperationResult{
   358  			Tr: &xdr.OperationResultTr{
   359  				Type: xdr.OperationTypePathPaymentStrictSend,
   360  				PathPaymentStrictSendResult: &xdr.PathPaymentStrictSendResult{
   361  					Code: xdr.PathPaymentStrictSendResultCodePathPaymentStrictSendSuccess,
   362  					Success: &xdr.PathPaymentStrictSendResultSuccess{
   363  						Offers: []xdr.ClaimAtom{
   364  							lPOne,
   365  						},
   366  					},
   367  				},
   368  			},
   369  		},
   370  		xdr.OperationResult{
   371  			Tr: &xdr.OperationResultTr{
   372  				Type: xdr.OperationTypePathPaymentStrictReceive,
   373  				PathPaymentStrictReceiveResult: &xdr.PathPaymentStrictReceiveResult{
   374  					Code: xdr.PathPaymentStrictReceiveResultCodePathPaymentStrictReceiveSuccess,
   375  					Success: &xdr.PathPaymentStrictReceiveResultSuccess{
   376  						Offers: []xdr.ClaimAtom{
   377  							lPTwo,
   378  						},
   379  					},
   380  				},
   381  			},
   382  		},
   383  		xdr.OperationResult{
   384  			Tr: &xdr.OperationResultTr{
   385  				Type: xdr.OperationTypeCreatePassiveSellOffer,
   386  				CreatePassiveSellOfferResult: &xdr.ManageSellOfferResult{
   387  					Code: xdr.ManageSellOfferResultCodeManageSellOfferSuccess,
   388  					Success: &xdr.ManageOfferSuccessResult{
   389  						OffersClaimed: []xdr.ClaimAtom{},
   390  					},
   391  				},
   392  			},
   393  		},
   394  	}
   395  
   396  	unsafeMeta := xdr.TransactionMetaV1{
   397  		Operations: []xdr.OperationMeta{
   398  			xdr.OperationMeta{
   399  				Changes: xdr.LedgerEntryChanges{
   400  					xdr.LedgerEntryChange{
   401  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   402  						State: &xdr.LedgerEntry{
   403  							Data: xdr.LedgerEntryData{
   404  								Type: xdr.LedgerEntryTypeOffer,
   405  								Offer: &xdr.OfferEntry{
   406  									SellerId: testAccount1ID,
   407  									OfferId:  97684906,
   408  									Price: xdr.Price{
   409  										N: 12634,
   410  										D: 13300347,
   411  									},
   412  								},
   413  							},
   414  						},
   415  					},
   416  					xdr.LedgerEntryChange{
   417  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   418  						Updated: &xdr.LedgerEntry{
   419  							Data: xdr.LedgerEntryData{
   420  								Type: xdr.LedgerEntryTypeOffer,
   421  								Offer: &xdr.OfferEntry{
   422  									SellerId: testAccount1ID,
   423  									OfferId:  97684906,
   424  									Price: xdr.Price{
   425  										N: 2,
   426  										D: 4,
   427  									},
   428  								},
   429  							},
   430  						},
   431  					},
   432  				},
   433  			},
   434  			xdr.OperationMeta{
   435  				Changes: xdr.LedgerEntryChanges{
   436  					xdr.LedgerEntryChange{
   437  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   438  						State: &xdr.LedgerEntry{
   439  							Data: xdr.LedgerEntryData{
   440  								Type: xdr.LedgerEntryTypeOffer,
   441  								Offer: &xdr.OfferEntry{
   442  									SellerId: testAccount3ID,
   443  									OfferId:  86106895,
   444  									Price: xdr.Price{
   445  										N: 25,
   446  										D: 1,
   447  									},
   448  								},
   449  							},
   450  						},
   451  					},
   452  					xdr.LedgerEntryChange{
   453  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   454  						Updated: &xdr.LedgerEntry{
   455  							Data: xdr.LedgerEntryData{
   456  								Type: xdr.LedgerEntryTypeOffer,
   457  								Offer: &xdr.OfferEntry{
   458  									SellerId: testAccount3ID,
   459  									OfferId:  86106895,
   460  									Price: xdr.Price{
   461  										N: 1111,
   462  										D: 12,
   463  									},
   464  								},
   465  							},
   466  						},
   467  					},
   468  				},
   469  			},
   470  			xdr.OperationMeta{
   471  				Changes: xdr.LedgerEntryChanges{
   472  					xdr.LedgerEntryChange{
   473  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   474  						State: &xdr.LedgerEntry{
   475  							Data: xdr.LedgerEntryData{
   476  								Type: xdr.LedgerEntryTypeOffer,
   477  								Offer: &xdr.OfferEntry{
   478  									SellerId: testAccount1ID,
   479  									OfferId:  97684906,
   480  									Price: xdr.Price{
   481  										N: 12634,
   482  										D: 13300347,
   483  									},
   484  								},
   485  							},
   486  						},
   487  					},
   488  					xdr.LedgerEntryChange{
   489  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   490  						Updated: &xdr.LedgerEntry{
   491  							Data: xdr.LedgerEntryData{
   492  								Type: xdr.LedgerEntryTypeOffer,
   493  								Offer: &xdr.OfferEntry{
   494  									SellerId: testAccount1ID,
   495  									OfferId:  97684906,
   496  									Price: xdr.Price{
   497  										N: 1111,
   498  										D: 12,
   499  									},
   500  								},
   501  							},
   502  						},
   503  					},
   504  					xdr.LedgerEntryChange{
   505  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   506  						State: &xdr.LedgerEntry{
   507  							Data: xdr.LedgerEntryData{
   508  								Type: xdr.LedgerEntryTypeOffer,
   509  								Offer: &xdr.OfferEntry{
   510  									SellerId: testAccount3ID,
   511  									OfferId:  86106895,
   512  									Price: xdr.Price{
   513  										N: 20,
   514  										D: 500,
   515  									},
   516  								},
   517  							},
   518  						},
   519  					},
   520  					xdr.LedgerEntryChange{
   521  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   522  						Updated: &xdr.LedgerEntry{
   523  							Data: xdr.LedgerEntryData{
   524  								Type: xdr.LedgerEntryTypeOffer,
   525  								Offer: &xdr.OfferEntry{
   526  									SellerId: testAccount3ID,
   527  									OfferId:  86106895,
   528  									Price: xdr.Price{
   529  										N: 1111,
   530  										D: 12,
   531  									},
   532  								},
   533  							},
   534  						},
   535  					},
   536  				},
   537  			},
   538  			xdr.OperationMeta{
   539  				Changes: xdr.LedgerEntryChanges{
   540  					xdr.LedgerEntryChange{
   541  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   542  						State: &xdr.LedgerEntry{
   543  							Data: xdr.LedgerEntryData{
   544  								Type: xdr.LedgerEntryTypeOffer,
   545  								Offer: &xdr.OfferEntry{
   546  									SellerId: testAccount3ID,
   547  									OfferId:  86106895,
   548  									Price: xdr.Price{
   549  										N: 20,
   550  										D: 500,
   551  									},
   552  								},
   553  							},
   554  						},
   555  					},
   556  					xdr.LedgerEntryChange{
   557  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   558  						Updated: &xdr.LedgerEntry{
   559  							Data: xdr.LedgerEntryData{
   560  								Type: xdr.LedgerEntryTypeOffer,
   561  								Offer: &xdr.OfferEntry{
   562  									SellerId: testAccount1ID,
   563  									OfferId:  97684906,
   564  									Price: xdr.Price{
   565  										N: 12634,
   566  										D: 13300347,
   567  									},
   568  								},
   569  							},
   570  						},
   571  					},
   572  					xdr.LedgerEntryChange{
   573  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   574  						State: &xdr.LedgerEntry{
   575  							Data: xdr.LedgerEntryData{
   576  								Type: xdr.LedgerEntryTypeOffer,
   577  								Offer: &xdr.OfferEntry{
   578  									SellerId: testAccount1ID,
   579  									OfferId:  97684906,
   580  									Price: xdr.Price{
   581  										N: 12634,
   582  										D: 13300347,
   583  									},
   584  								},
   585  							},
   586  						},
   587  					},
   588  					xdr.LedgerEntryChange{
   589  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   590  						Updated: &xdr.LedgerEntry{
   591  							Data: xdr.LedgerEntryData{
   592  								Type: xdr.LedgerEntryTypeOffer,
   593  								Offer: &xdr.OfferEntry{
   594  									SellerId: testAccount1ID,
   595  									Price: xdr.Price{
   596  										N: 12634,
   597  										D: 1330,
   598  									},
   599  								},
   600  							},
   601  						},
   602  					},
   603  				},
   604  			},
   605  			xdr.OperationMeta{
   606  				Changes: xdr.LedgerEntryChanges{
   607  					xdr.LedgerEntryChange{
   608  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   609  						State: &xdr.LedgerEntry{
   610  							Data: xdr.LedgerEntryData{
   611  								Type: xdr.LedgerEntryTypeLiquidityPool,
   612  								LiquidityPool: &xdr.LiquidityPoolEntry{
   613  									LiquidityPoolId: xdr.PoolId{4, 5, 6},
   614  									Body: xdr.LiquidityPoolEntryBody{
   615  										Type: xdr.LiquidityPoolTypeLiquidityPoolConstantProduct,
   616  										ConstantProduct: &xdr.LiquidityPoolEntryConstantProduct{
   617  											Params: xdr.LiquidityPoolConstantProductParameters{
   618  												AssetA: xdr.MustNewCreditAsset("NIJ", testAccount1Address),
   619  												AssetB: xdr.MustNewCreditAsset("WER", testAccount4Address),
   620  												Fee:    xdr.LiquidityPoolFeeV18,
   621  											},
   622  											ReserveA:                 400,
   623  											ReserveB:                 800,
   624  											TotalPoolShares:          40,
   625  											PoolSharesTrustLineCount: 50,
   626  										},
   627  									},
   628  								},
   629  							},
   630  						},
   631  					},
   632  					xdr.LedgerEntryChange{
   633  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   634  						Updated: &xdr.LedgerEntry{
   635  							Data: xdr.LedgerEntryData{
   636  								Type: xdr.LedgerEntryTypeLiquidityPool,
   637  								LiquidityPool: &xdr.LiquidityPoolEntry{
   638  									LiquidityPoolId: xdr.PoolId{4, 5, 6},
   639  									Body: xdr.LiquidityPoolEntryBody{
   640  										Type: xdr.LiquidityPoolTypeLiquidityPoolConstantProduct,
   641  										ConstantProduct: &xdr.LiquidityPoolEntryConstantProduct{
   642  											Params: xdr.LiquidityPoolConstantProductParameters{
   643  												AssetA: xdr.MustNewCreditAsset("NIJ", testAccount1Address),
   644  												AssetB: xdr.MustNewCreditAsset("WER", testAccount4Address),
   645  												Fee:    xdr.LiquidityPoolFeeV18,
   646  											},
   647  											ReserveA:                 500,
   648  											ReserveB:                 750,
   649  											TotalPoolShares:          40,
   650  											PoolSharesTrustLineCount: 50,
   651  										},
   652  									},
   653  								},
   654  							},
   655  						},
   656  					},
   657  				},
   658  			},
   659  			xdr.OperationMeta{
   660  				Changes: xdr.LedgerEntryChanges{
   661  					xdr.LedgerEntryChange{
   662  						Type: xdr.LedgerEntryChangeTypeLedgerEntryState,
   663  						State: &xdr.LedgerEntry{
   664  							Data: xdr.LedgerEntryData{
   665  								Type: xdr.LedgerEntryTypeLiquidityPool,
   666  								LiquidityPool: &xdr.LiquidityPoolEntry{
   667  									LiquidityPoolId: xdr.PoolId{1, 2, 3, 4, 5, 6},
   668  									Body: xdr.LiquidityPoolEntryBody{
   669  										Type: xdr.LiquidityPoolTypeLiquidityPoolConstantProduct,
   670  										ConstantProduct: &xdr.LiquidityPoolEntryConstantProduct{
   671  											Params: xdr.LiquidityPoolConstantProductParameters{
   672  												AssetA: xdr.MustNewCreditAsset("HAH", testAccount4Address),
   673  												AssetB: xdr.MustNewCreditAsset("WHO", testAccount1Address),
   674  												Fee:    xdr.LiquidityPoolFeeV18,
   675  											},
   676  											ReserveA:                 100000,
   677  											ReserveB:                 10000,
   678  											TotalPoolShares:          40,
   679  											PoolSharesTrustLineCount: 50,
   680  										},
   681  									},
   682  								},
   683  							},
   684  						},
   685  					},
   686  					xdr.LedgerEntryChange{
   687  						Type: xdr.LedgerEntryChangeTypeLedgerEntryUpdated,
   688  						Updated: &xdr.LedgerEntry{
   689  							Data: xdr.LedgerEntryData{
   690  								Type: xdr.LedgerEntryTypeLiquidityPool,
   691  								LiquidityPool: &xdr.LiquidityPoolEntry{
   692  									LiquidityPoolId: xdr.PoolId{4, 5, 6},
   693  									Body: xdr.LiquidityPoolEntryBody{
   694  										Type: xdr.LiquidityPoolTypeLiquidityPoolConstantProduct,
   695  										ConstantProduct: &xdr.LiquidityPoolEntryConstantProduct{
   696  											Params: xdr.LiquidityPoolConstantProductParameters{
   697  												AssetA: xdr.MustNewCreditAsset("HAH", testAccount4Address),
   698  												AssetB: xdr.MustNewCreditAsset("WHO", testAccount1Address),
   699  												Fee:    xdr.LiquidityPoolFeeV18,
   700  											},
   701  											ReserveA:                 999999,
   702  											ReserveB:                 10001,
   703  											TotalPoolShares:          40,
   704  											PoolSharesTrustLineCount: 50,
   705  										},
   706  									},
   707  								},
   708  							},
   709  						},
   710  					},
   711  				},
   712  			},
   713  			xdr.OperationMeta{},
   714  		}}
   715  
   716  	inputTransaction.Result.Result.Result.Results = &results
   717  	inputTransaction.Envelope.V1 = &inputEnvelope
   718  	inputTransaction.UnsafeMeta.V1 = &unsafeMeta
   719  	return
   720  }
   721  
   722  func makeTradeTestOutput() [][]TradeOutput {
   723  	offerOneOutput := TradeOutput{
   724  		Order:                 0,
   725  		LedgerClosedAt:        genericCloseTime,
   726  		SellingAccountAddress: testAccount1Address,
   727  		SellingAssetCode:      "ETH",
   728  		SellingAssetIssuer:    testAccount3Address,
   729  		SellingAssetType:      "credit_alphanum4",
   730  		SellingAssetID:        4476940172956910889,
   731  		SellingAmount:         13300347 * 0.0000001,
   732  		BuyingAccountAddress:  testAccount3Address,
   733  		BuyingAssetCode:       "USDT",
   734  		BuyingAssetIssuer:     testAccount4Address,
   735  		BuyingAssetType:       "credit_alphanum4",
   736  		BuyingAssetID:         -8205667356306085451,
   737  		BuyingAmount:          12634 * 0.0000001,
   738  		PriceN:                12634,
   739  		PriceD:                13300347,
   740  		SellingOfferID:        null.IntFrom(97684906),
   741  		BuyingOfferID:         null.IntFrom(4611686018427388005),
   742  		HistoryOperationID:    101,
   743  		TradeType:             1,
   744  	}
   745  	offerTwoOutput := TradeOutput{
   746  		Order:                 0,
   747  		LedgerClosedAt:        genericCloseTime,
   748  		SellingAccountAddress: testAccount3Address,
   749  		SellingAssetCode:      "USDT",
   750  		SellingAssetIssuer:    testAccount4Address,
   751  		SellingAssetType:      "credit_alphanum4",
   752  		SellingAssetID:        -8205667356306085451,
   753  		SellingAmount:         500 * 0.0000001,
   754  		BuyingAccountAddress:  testAccount3Address,
   755  		BuyingAssetCode:       "",
   756  		BuyingAssetIssuer:     "",
   757  		BuyingAssetType:       "native",
   758  		BuyingAssetID:         -5706705804583548011,
   759  		BuyingAmount:          20 * 0.0000001,
   760  		PriceN:                25,
   761  		PriceD:                1,
   762  		SellingOfferID:        null.IntFrom(86106895),
   763  		BuyingOfferID:         null.IntFrom(4611686018427388005),
   764  		HistoryOperationID:    101,
   765  		TradeType:             1,
   766  	}
   767  
   768  	lPOneOutput := TradeOutput{
   769  		Order:                  0,
   770  		LedgerClosedAt:         genericCloseTime,
   771  		SellingAssetCode:       "WER",
   772  		SellingAssetIssuer:     testAccount4Address,
   773  		SellingAssetType:       "credit_alphanum4",
   774  		SellingAssetID:         -7615773297180926952,
   775  		SellingAmount:          123 * 0.0000001,
   776  		BuyingAccountAddress:   testAccount3Address,
   777  		BuyingAssetCode:        "NIJ",
   778  		BuyingAssetIssuer:      testAccount1Address,
   779  		BuyingAssetType:        "credit_alphanum4",
   780  		BuyingAssetID:          -8061435944444096568,
   781  		BuyingAmount:           456 * 0.0000001,
   782  		PriceN:                 456,
   783  		PriceD:                 123,
   784  		BuyingOfferID:          null.IntFrom(4611686018427388005),
   785  		SellingLiquidityPoolID: null.StringFrom("0405060000000000000000000000000000000000000000000000000000000000"),
   786  		LiquidityPoolFee:       null.IntFrom(30),
   787  		HistoryOperationID:     101,
   788  		TradeType:              2,
   789  		RoundingSlippage:       null.IntFrom(0),
   790  		SellerIsExact:          null.BoolFrom(false),
   791  	}
   792  
   793  	lPTwoOutput := TradeOutput{
   794  		Order:                  0,
   795  		LedgerClosedAt:         genericCloseTime,
   796  		SellingAssetCode:       "HAH",
   797  		SellingAssetIssuer:     testAccount1Address,
   798  		SellingAssetType:       "credit_alphanum4",
   799  		SellingAssetID:         -6231594281606355691,
   800  		SellingAmount:          1 * 0.0000001,
   801  		BuyingAccountAddress:   testAccount3Address,
   802  		BuyingAssetCode:        "WHO",
   803  		BuyingAssetIssuer:      testAccount4Address,
   804  		BuyingAssetType:        "credit_alphanum4",
   805  		BuyingAssetID:          -680582465233747022,
   806  		BuyingAmount:           1 * 0.0000001,
   807  		PriceN:                 1,
   808  		PriceD:                 1,
   809  		BuyingOfferID:          null.IntFrom(4611686018427388005),
   810  		SellingLiquidityPoolID: null.StringFrom("0102030405060000000000000000000000000000000000000000000000000000"),
   811  		LiquidityPoolFee:       null.IntFrom(30),
   812  		HistoryOperationID:     101,
   813  		TradeType:              2,
   814  		RoundingSlippage:       null.IntFrom(100),
   815  		SellerIsExact:          null.BoolFrom(true),
   816  	}
   817  
   818  	onePriceIsAmount := offerOneOutput
   819  	onePriceIsAmount.PriceN = 12634
   820  	onePriceIsAmount.PriceD = 13300347
   821  	onePriceIsAmount.SellerIsExact = null.BoolFrom(false)
   822  
   823  	offerOneOutputSecondPlace := onePriceIsAmount
   824  	offerOneOutputSecondPlace.Order = 1
   825  	offerOneOutputSecondPlace.SellerIsExact = null.BoolFrom(true)
   826  
   827  	twoPriceIsAmount := offerTwoOutput
   828  	twoPriceIsAmount.PriceN = int64(twoPriceIsAmount.BuyingAmount * 10000000)
   829  	twoPriceIsAmount.PriceD = int64(twoPriceIsAmount.SellingAmount * 10000000)
   830  	twoPriceIsAmount.SellerIsExact = null.BoolFrom(true)
   831  
   832  	offerTwoOutputSecondPlace := twoPriceIsAmount
   833  	offerTwoOutputSecondPlace.Order = 1
   834  	offerTwoOutputSecondPlace.SellerIsExact = null.BoolFrom(false)
   835  
   836  	output := [][]TradeOutput{
   837  		[]TradeOutput{offerOneOutput},
   838  		[]TradeOutput{offerTwoOutput},
   839  		[]TradeOutput{onePriceIsAmount, offerTwoOutputSecondPlace},
   840  		[]TradeOutput{twoPriceIsAmount, offerOneOutputSecondPlace},
   841  		[]TradeOutput{lPOneOutput},
   842  		[]TradeOutput{lPTwoOutput},
   843  		[]TradeOutput{},
   844  	}
   845  	return output
   846  }