Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvoiceImpaired and pool profit array by timestamp #56

Merged
Show file tree
Hide file tree
Changes from 2 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
27 changes: 27 additions & 0 deletions bulla-contracts/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ type InvoiceUnfactoredEvent implements IEventLog & IPoolTransaction @entity {
claim: Claim!
}

type InvoiceImpairedEvent implements IEventLog & IPoolTransaction @entity {
id: ID!
invoiceId: String!
eventName: String!
fundedAmount: BigInt!
impairAmount: BigInt!
blockNumber: BigInt!
transactionHash: Bytes!
logIndex: BigInt!
timestamp: BigInt!
poolAddress: Bytes!
priceAfterTransaction: BigInt!
claim: Claim!
}

type DepositMadeEvent implements IEventLog & IPoolTransaction @entity {
id: ID!
depositor: Bytes! #address
Expand Down Expand Up @@ -428,6 +443,18 @@ type User @entity {
factoringEvents: [IEventLog!]!
}

type PoolPnl @entity {
id: ID!
address: Bytes! #address
pnlHistory: [PnlHistoryEntry!]!
}

type PnlHistoryEntry @entity {
id: ID!
pnl: BigInt!
timestamp: BigInt!
}

type FactoringPricePerShare @entity {
id: ID!
address: Bytes! # address
Expand Down
8 changes: 8 additions & 0 deletions bulla-contracts/src/functions/BullaFactoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BigInt, ethereum } from "@graphprotocol/graph-ts";
import {
DepositMadeEvent,
InvoiceFundedEvent,
InvoiceImpairedEvent,
InvoiceKickbackAmountSentEvent,
InvoicePaidEvent,
InvoiceUnfactoredEvent,
Expand All @@ -11,6 +12,7 @@ import {
Deposit,
DepositMadeWithAttachment,
InvoiceFunded,
InvoiceImpaired,
InvoiceKickbackAmountSent,
InvoicePaid,
InvoiceUnfactored,
Expand Down Expand Up @@ -56,3 +58,9 @@ export const getSharesRedeemedEventId = (event: ethereum.Event): string => {
};

export const createSharesRedeemedEvent = (event: Withdraw): SharesRedeemedEvent => new SharesRedeemedEvent(getSharesRedeemedEventId(event));

export const getInvoiceImpairedEventId = (underlyingClaimId: BigInt, event: ethereum.Event): string =>
"InvoiceImpaired-" + underlyingClaimId.toString() + "-" + event.transaction.hash.toHexString() + "-" + event.logIndex.toString();

export const createInvoiceImpairedEvent = (underlyingTokenId: BigInt, event: InvoiceImpaired): InvoiceImpairedEvent =>
new InvoiceImpairedEvent(getInvoiceImpairedEventId(underlyingTokenId, event));
36 changes: 35 additions & 1 deletion bulla-contracts/src/functions/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ import { ClaimCreatedClaimAttachmentStruct } from "../../generated/BullaClaimERC
import { ERC20 } from "../../generated/BullaClaimERC721/ERC20";
import { BullaManager as BullaManagerContract } from "../../generated/BullaManager/BullaManager";
import { LoanOfferedLoanOfferAttachmentStruct } from "../../generated/FrendLend/FrendLend";
import { BullaManager, Token, User, FactoringPricePerShare, PriceHistoryEntry, HistoricalFactoringStatistics, FactoringStatisticsEntry } from "../../generated/schema";
import {
BullaManager,
Token,
User,
FactoringPricePerShare,
PriceHistoryEntry,
HistoricalFactoringStatistics,
FactoringStatisticsEntry,
PoolPnl,
PnlHistoryEntry
} from "../../generated/schema";
import { BullaFactoring, DepositMadeWithAttachmentAttachmentStruct, SharesRedeemedWithAttachmentAttachmentStruct } from "../../generated/BullaFactoring/BullaFactoring";
import { BigInt } from "@graphprotocol/graph-ts";

Expand Down Expand Up @@ -188,3 +198,27 @@ export const getOrCreateHistoricalFactoringStatistics = (event: ethereum.Event):

return historicalFactoringStatistics;
};

export const getOrCreatePoolProfitAndLoss = (event: ethereum.Event, pnl: BigInt): PoolPnl => {
let poolPnl = PoolPnl.load(event.address.toHexString());

if (!poolPnl) {
poolPnl = new PoolPnl(event.address.toHexString());
poolPnl.address = event.address;
poolPnl.pnlHistory = [];
}

const pnlHistoryEntryId = poolPnl.id.concat("-").concat(event.block.timestamp.toString());
const pnlHistoryEntry = new PnlHistoryEntry(pnlHistoryEntryId);
pnlHistoryEntry.timestamp = event.block.timestamp;
pnlHistoryEntry.pnl = pnl;
pnlHistoryEntry.save();

let updatedHistory = poolPnl.pnlHistory;
updatedHistory.push(pnlHistoryEntry.id);
poolPnl.pnlHistory = updatedHistory;

poolPnl.save();

return poolPnl;
};
41 changes: 40 additions & 1 deletion bulla-contracts/src/mappings/BullaFactoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Deposit,
DepositMadeWithAttachment,
InvoiceFunded,
InvoiceImpaired,
InvoiceKickbackAmountSent,
InvoicePaid,
InvoicePaid__Params,
Expand All @@ -14,6 +15,7 @@ import { getClaim } from "../functions/BullaClaimERC721";
import {
createDepositMadeEvent,
createInvoiceFundedEvent,
createInvoiceImpairedEvent,
createInvoiceKickbackAmountSentEvent,
createInvoicePaidEvent,
createInvoiceUnfactoredEvent,
Expand All @@ -26,6 +28,7 @@ import {
getIPFSHash_redeemWithAttachment,
getLatestPrice,
getOrCreateHistoricalFactoringStatistics,
getOrCreatePoolProfitAndLoss,
getOrCreatePricePerShare,
getOrCreateUser
} from "../functions/common";
Expand Down Expand Up @@ -106,7 +109,6 @@ export function handleInvoicePaid(event: InvoicePaid): void {
const ev: InvoicePaid__Params = event.params;
const originatingClaimId = ev.invoiceId;

log.info("in handleInvoicePaid", []);
const underlyingClaim = getClaim(originatingClaimId.toString());
const InvoicePaidEvent = createInvoicePaidEvent(originatingClaimId, event);

Expand All @@ -121,6 +123,7 @@ export function handleInvoicePaid(event: InvoicePaid): void {
const price_per_share = getOrCreatePricePerShare(event);
const latestPrice = getLatestPrice(event);
const historical_factoring_statistics = getOrCreateHistoricalFactoringStatistics(event);
const pool_pnl = getOrCreatePoolProfitAndLoss(event, ev.trueInterest);

InvoicePaidEvent.eventName = "InvoicePaid";
InvoicePaidEvent.blockNumber = event.block.number;
Expand All @@ -137,6 +140,7 @@ export function handleInvoicePaid(event: InvoicePaid): void {
original_creditor.save();
price_per_share.save();
historical_factoring_statistics.save();
pool_pnl.save();
}

export function handleInvoiceUnfactored(event: InvoiceUnfactored): void {
Expand Down Expand Up @@ -258,3 +262,38 @@ export function handleSharesRedeemedWithAttachment(event: SharesRedeemedWithAtta

sharesRedeemedEvent.save();
}

export function handleInvoiceImpaired(event: InvoiceImpaired): void {
const ev = event.params;
const originatingClaimId = ev.invoiceId;

const underlyingClaim = getClaim(originatingClaimId.toString());

const InvoiceImpairedEvent = createInvoiceImpairedEvent(originatingClaimId, event);

InvoiceImpairedEvent.invoiceId = underlyingClaim.id;
const price_per_share = getOrCreatePricePerShare(event);
const latestPrice = getLatestPrice(event);
const historical_factoring_statistics = getOrCreateHistoricalFactoringStatistics(event);

InvoiceImpairedEvent.eventName = "InvoiceImpaired";
InvoiceImpairedEvent.blockNumber = event.block.number;
InvoiceImpairedEvent.transactionHash = event.transaction.hash;
InvoiceImpairedEvent.logIndex = event.logIndex;
InvoiceImpairedEvent.fundedAmount = ev.lossAmount;
InvoiceImpairedEvent.impairAmount = ev.gainAmount;
InvoiceImpairedEvent.timestamp = event.block.timestamp;
InvoiceImpairedEvent.poolAddress = event.address;
InvoiceImpairedEvent.priceAfterTransaction = latestPrice;
InvoiceImpairedEvent.claim = underlyingClaim.id;
const lossAccrued = ev.lossAmount
.minus(underlyingClaim.paidAmount)
.minus(ev.gainAmount)
.neg();
const pool_pnl = getOrCreatePoolProfitAndLoss(event, lossAccrued);

pool_pnl.save();
solidoracle marked this conversation as resolved.
Show resolved Hide resolved
InvoiceImpairedEvent.save();
price_per_share.save();
historical_factoring_statistics.save();
}
2 changes: 2 additions & 0 deletions bulla-contracts/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,6 @@ dataSources:
handler: handleSharesRedeemed
- event: SharesRedeemedWithAttachment(indexed address,uint256,uint256,(bytes32,uint8,uint8))
handler: handleSharesRedeemedWithAttachment
- event: InvoiceImpaired(indexed uint256,uint256,uint256)
handler: handleInvoiceImpaired
file: ./src/mappings/BullaFactoring.ts
39 changes: 39 additions & 0 deletions bulla-contracts/tests/BullaFactoring.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
handleDepositMade,
handleDepositMadeWithAttachment,
handleInvoiceFunded,
handleInvoiceImpaired,
handleInvoiceKickbackAmountSent,
handleInvoicePaid,
handleInvoiceUnfactored,
Expand All @@ -28,6 +29,7 @@ import {
newDepositMadeEvent,
newDepositMadeWithAttachmentEvent,
newInvoiceFundedEvent,
newInvoiceImpairedEvent,
newInvoiceKickbackAmountSentEvent,
newInvoicePaidEvent,
newInvoiceUnfactoredEvent,
Expand All @@ -37,6 +39,7 @@ import {
import {
getDepositMadeEventId,
getInvoiceFundedEventId,
getInvoiceImpairedEventId,
getInvoiceKickbackAmountSentEventId,
getInvoicePaidEventId,
getInvoiceUnfactoredEventId,
Expand All @@ -47,6 +50,8 @@ import {
FactoringPricePerShare,
FactoringStatisticsEntry,
HistoricalFactoringStatistics,
PnlHistoryEntry,
PoolPnl,
PriceHistoryEntry,
SharesRedeemedEvent
} from "../generated/schema";
Expand Down Expand Up @@ -258,6 +263,32 @@ test("it handles BullaFactoring events", () => {

log.info("✅ should attach IPFS hash to SharesRedeemed event", []);

const lossAmount = BigInt.fromI32(2000);
const gainAmount = BigInt.fromI32(50);

const invoiceImpairedEvent = newInvoiceImpairedEvent(claimId, lossAmount, gainAmount);
invoiceImpairedEvent.block.timestamp = timestamp;
invoiceImpairedEvent.block.number = blockNum;

handleInvoiceImpaired(invoiceImpairedEvent);

const invoiceImpairedEventId = getInvoiceImpairedEventId(claimId, invoiceImpairedEvent);
assert.fieldEquals("InvoiceImpairedEvent", invoiceImpairedEventId, "invoiceId", invoiceImpairedEvent.params.invoiceId.toString());
assert.fieldEquals("InvoiceImpairedEvent", invoiceImpairedEventId, "fundedAmount", invoiceImpairedEvent.params.lossAmount.toString());
assert.fieldEquals("InvoiceImpairedEvent", invoiceImpairedEventId, "impairAmount", invoiceImpairedEvent.params.gainAmount.toString());
assert.fieldEquals("InvoiceImpairedEvent", invoiceImpairedEventId, "poolAddress", MOCK_BULLA_FACTORING_ADDRESS.toHexString());
assert.fieldEquals("InvoiceImpairedEvent", invoiceImpairedEventId, "claim", claimId.toString());

let poolPnl = PoolPnl.load(MOCK_BULLA_FACTORING_ADDRESS.toHexString());
assert.assertNotNull(poolPnl);

const pnlHistoryEntryId = poolPnl!.pnlHistory[0];
const pnlHistoryEntry = PnlHistoryEntry.load(pnlHistoryEntryId);
assert.assertNotNull(pnlHistoryEntry);
assert.bigIntEquals(lossAmount.minus(gainAmount).neg(), pnlHistoryEntry!.pnl);

log.info("✅ should create a InvoiceImpaired event", []);

afterEach();
});

Expand Down Expand Up @@ -286,6 +317,14 @@ test("it handles InvoicePaid event", () => {

handleInvoicePaid(invoicePaidEvent);

let poolPnl = PoolPnl.load(MOCK_BULLA_FACTORING_ADDRESS.toHexString());
assert.assertNotNull(poolPnl);

const pnlHistoryEntryId = poolPnl!.pnlHistory[0];
const pnlHistoryEntry = PnlHistoryEntry.load(pnlHistoryEntryId);
assert.assertNotNull(pnlHistoryEntry);
assert.bigIntEquals(trueInterest, pnlHistoryEntry!.pnl);

const invoicePaidEventId = getInvoicePaidEventId(claimId, invoicePaidEvent);
assert.fieldEquals("InvoicePaidEvent", invoicePaidEventId, "invoiceId", invoicePaidEvent.params.invoiceId.toString());
assert.fieldEquals("InvoicePaidEvent", invoicePaidEventId, "fundedAmount", invoicePaidEvent.params.fundedAmountNet.toString());
Expand Down
23 changes: 23 additions & 0 deletions bulla-contracts/tests/functions/BullaFactoring.testtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DepositMade,
DepositMadeWithAttachment,
InvoiceFunded,
InvoiceImpaired,
InvoiceKickbackAmountSent,
InvoicePaid,
InvoiceUnfactored,
Expand Down Expand Up @@ -226,6 +227,28 @@ export function newSharesRedeemedWithAttachmentEvent(redeemer: Address, assets:
return sharesRedeemedWithAttachmentEvent;
}

export function newInvoiceImpairedEvent(originatingClaimId: BigInt, lossAmount: BigInt, gainAmount: BigInt): InvoiceImpaired {
const mockEvent = newMockEvent();
const invoiceImpairedEvent = new InvoiceImpaired(
mockEvent.address,
mockEvent.logIndex,
mockEvent.transactionLogIndex,
mockEvent.logType,
mockEvent.block,
mockEvent.transaction,
mockEvent.parameters,
mockEvent.receipt
);

invoiceImpairedEvent.address = MOCK_BULLA_FACTORING_ADDRESS;
invoiceImpairedEvent.parameters = new Array();
invoiceImpairedEvent.parameters.push(new ethereum.EventParam("invoiceId", ethereum.Value.fromUnsignedBigInt(originatingClaimId)));
invoiceImpairedEvent.parameters.push(new ethereum.EventParam("lossAmount", ethereum.Value.fromUnsignedBigInt(lossAmount)));
invoiceImpairedEvent.parameters.push(new ethereum.EventParam("gainAmount", ethereum.Value.fromUnsignedBigInt(gainAmount)));

return invoiceImpairedEvent;
}

function createMultihashTuple(): ethereum.Tuple {
const hash: Bytes = changetype<Bytes>(Bytes.fromHexString(MULTIHASH_BYTES));
const multihashArray: Array<ethereum.Value> = [
Expand Down
Loading