github.com/stellar/stellar-etl@v1.0.1-0.20240312145900-4874b6bf2b89/internal/transform/trustline.go (about) 1 package transform 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 7 "github.com/guregu/null" 8 "github.com/pkg/errors" 9 10 "github.com/stellar/stellar-etl/internal/utils" 11 12 "github.com/stellar/go/ingest" 13 "github.com/stellar/go/xdr" 14 ) 15 16 // TransformTrustline converts a trustline from the history archive ingestion system into a form suitable for BigQuery 17 func TransformTrustline(ledgerChange ingest.Change, header xdr.LedgerHeaderHistoryEntry) (TrustlineOutput, error) { 18 ledgerEntry, changeType, outputDeleted, err := utils.ExtractEntryFromChange(ledgerChange) 19 if err != nil { 20 return TrustlineOutput{}, err 21 } 22 23 trustEntry, ok := ledgerEntry.Data.GetTrustLine() 24 if !ok { 25 return TrustlineOutput{}, fmt.Errorf("Could not extract trustline data from ledger entry; actual type is %s", ledgerEntry.Data.Type) 26 } 27 28 outputAccountID, err := trustEntry.AccountId.GetAddress() 29 if err != nil { 30 return TrustlineOutput{}, err 31 } 32 33 var assetType, outputAssetCode, outputAssetIssuer, poolID string 34 35 asset := trustEntry.Asset 36 37 outputLedgerKey, err := trustLineEntryToLedgerKeyString(trustEntry) 38 if err != nil { 39 return TrustlineOutput{}, errors.Wrap(err, fmt.Sprintf("could not create ledger key string for trustline with account %s and asset %s", outputAccountID, asset.ToAsset().StringCanonical())) 40 } 41 42 if asset.Type == xdr.AssetTypeAssetTypePoolShare { 43 poolID = PoolIDToString(trustEntry.Asset.MustLiquidityPoolId()) 44 } else { 45 if err = asset.Extract(&assetType, &outputAssetCode, &outputAssetIssuer); err != nil { 46 return TrustlineOutput{}, errors.Wrap(err, fmt.Sprintf("could not parse asset for trustline with account %s", outputAccountID)) 47 } 48 } 49 50 outputAssetID := FarmHashAsset(outputAssetCode, outputAssetIssuer, asset.Type.String()) 51 52 liabilities := trustEntry.Liabilities() 53 54 closedAt, err := utils.TimePointToUTCTimeStamp(header.Header.ScpValue.CloseTime) 55 if err != nil { 56 return TrustlineOutput{}, err 57 } 58 59 ledgerSequence := header.Header.LedgerSeq 60 61 transformedTrustline := TrustlineOutput{ 62 LedgerKey: outputLedgerKey, 63 AccountID: outputAccountID, 64 AssetType: int32(asset.Type), 65 AssetCode: outputAssetCode, 66 AssetIssuer: outputAssetIssuer, 67 AssetID: outputAssetID, 68 Balance: utils.ConvertStroopValueToReal(trustEntry.Balance), 69 TrustlineLimit: int64(trustEntry.Limit), 70 LiquidityPoolID: poolID, 71 BuyingLiabilities: utils.ConvertStroopValueToReal(liabilities.Buying), 72 SellingLiabilities: utils.ConvertStroopValueToReal(liabilities.Selling), 73 Flags: uint32(trustEntry.Flags), 74 LastModifiedLedger: uint32(ledgerEntry.LastModifiedLedgerSeq), 75 LedgerEntryChange: uint32(changeType), 76 Sponsor: ledgerEntrySponsorToNullString(ledgerEntry), 77 Deleted: outputDeleted, 78 ClosedAt: closedAt, 79 LedgerSequence: uint32(ledgerSequence), 80 } 81 82 return transformedTrustline, nil 83 } 84 85 func trustLineEntryToLedgerKeyString(trustLine xdr.TrustLineEntry) (string, error) { 86 ledgerKey := &xdr.LedgerKey{} 87 err := ledgerKey.SetTrustline(trustLine.AccountId, trustLine.Asset) 88 if err != nil { 89 return "", fmt.Errorf("Error running ledgerKey.SetTrustline when calculating ledger key") 90 } 91 92 key, err := ledgerKey.MarshalBinary() 93 if err != nil { 94 return "", fmt.Errorf("Error running MarshalBinaryCompress when calculating ledger key") 95 } 96 97 return base64.StdEncoding.EncodeToString(key), nil 98 99 } 100 101 func ledgerEntrySponsorToNullString(entry xdr.LedgerEntry) null.String { 102 sponsoringID := entry.SponsoringID() 103 104 var sponsor null.String 105 if sponsoringID != nil { 106 sponsor.SetValid((*sponsoringID).Address()) 107 } 108 109 return sponsor 110 }