Skip to content

Commit

Permalink
setup bulla swap (#65)
Browse files Browse the repository at this point in the history
* setup bulla swap mappings

* fix tests

* addressed comments

* add OrderCreated test

* OrderExecuted test
  • Loading branch information
solidoracle authored Nov 1, 2024
1 parent beab830 commit 0e1110d
Show file tree
Hide file tree
Showing 11 changed files with 869 additions and 12 deletions.
501 changes: 501 additions & 0 deletions bulla-contracts/abis/BullaSwap.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion bulla-contracts/config/sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"frendLend": { "address": "0x3E058834CE20A54F0755889c008D3fF62D33cE85", "startBlock": 5096555 },
"instantPayment": { "address": "0x1cD1A83C2965CB7aD55d60551877Eb390e9C3d7A", "startBlock": 5096555 },
"bullaFactoring": { "address": "0x0000000000000000000000000000000000000000", "startBlock": 6631476 },
"bullaFactoringv2": { "address": "0xDF0fCe31285dcAB9124bF763AB9E5466723BeF35", "startBlock": 6812207 }
"bullaFactoringv2": { "address": "0xDF0fCe31285dcAB9124bF763AB9E5466723BeF35", "startBlock": 6812207 },
"bullaSwap": { "address": "0xdf30BE5964a7E26b49551a430e85B51148A7b95E", "startBlock": 6982025 }
}
2 changes: 1 addition & 1 deletion bulla-contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"scripts": {
"codegen": "yarn prep:sepolia && graph codegen",
"build": "yarn prep:sepolia && graph codegen && graph build",
"test": "yarn && yarn prep:goerli && graph test -v 0.2.2",
"test": "rm -rf tests/.bin && yarn && yarn prep:goerli && graph test -v 0.2.2",
"coverage": "yarn prep:goerli && graph test -- -c",
"prep:mainnet": "mustache config/mainnet.json template.yaml > subgraph.yaml",
"prep:goerli": "mustache config/goerli.json template.yaml > subgraph.yaml",
Expand Down
37 changes: 37 additions & 0 deletions bulla-contracts/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,42 @@ type InvoiceReconciledEvent implements IEventLog & IPoolTransaction @entity {
claim: Claim!
}

type OrderERC20 @entity {
id: ID! # orderId
orderId: BigInt!
expiry: BigInt!
signerWallet: Bytes! #address
signerToken: Token! #address
signerAmount: BigInt!
senderWallet: Bytes! #address
senderToken: Token! #address
senderAmount: BigInt!
}

type OrderCreatedEvent implements IEventLog @entity {
id: ID!
order: OrderERC20!
sender: Bytes! #address
signerWallet: Bytes! #address
eventName: String!
blockNumber: BigInt!
transactionHash: Bytes!
logIndex: BigInt!
timestamp: BigInt!
}

type OrderExecutedEvent implements IEventLog @entity {
id: ID!
order: OrderERC20!
sender: Bytes! #address
signerWallet: Bytes! #address
eventName: String!
blockNumber: BigInt!
transactionHash: Bytes!
logIndex: BigInt!
timestamp: BigInt!
}

type LoanOfferedEvent implements IEventLog @entity {
id: ID!
loanId: String!
Expand Down Expand Up @@ -448,6 +484,7 @@ type User @entity {
financeEvents: [IEventLog!]!
frendLendEvents: [IEventLog!]!
factoringEvents: [IEventLog!]!
swapEvents: [IEventLog!]!
}

type PoolPnl @entity {
Expand Down
17 changes: 17 additions & 0 deletions bulla-contracts/src/functions/BullaSwap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { BigInt, ethereum } from "@graphprotocol/graph-ts";
import { OrderCreated, OrderExecuted } from "../../generated/BullaSwap/BullaSwap";
import { OrderCreatedEvent, OrderExecutedEvent } from "../../generated/schema";

export const getOrderCreatedEventId = (orderId: BigInt, event: ethereum.Event): string =>
"OrderCreated-" + orderId.toString() + "-" + event.transaction.hash.toHexString() + "-" + event.logIndex.toString();

export const createOrderCreatedEvent = (orderId: BigInt, event: OrderCreated): OrderCreatedEvent => {
return new OrderCreatedEvent(getOrderCreatedEventId(orderId, event));
};

export const getOrderExecutedEventId = (orderId: BigInt, event: ethereum.Event): string =>
"OrderExecuted-" + orderId.toString() + "-" + event.transaction.hash.toHexString() + "-" + event.logIndex.toString();

export const createOrderExecutedEvent = (orderId: BigInt, event: OrderExecuted): OrderExecutedEvent => {
return new OrderExecutedEvent(getOrderExecutedEventId(orderId, event));
};
21 changes: 12 additions & 9 deletions bulla-contracts/src/mappings/BullaFactoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,18 +255,21 @@ export function handleInvoiceUnfactoredV2(event: InvoiceUnfactored): void {
const targetFees = getTargetFeesAndTaxes(event.address, "v2", ev.invoiceId);
const approvedInvoice = BullaFactoringv2.bind(event.address).approvedInvoices(ev.invoiceId);

const trueProcotolFee = targetFees[1] // targetProcotolFee
.times(ev.interestToCharge)
.div(targetFees[0]); // targetInterest
const trueProcotolFee = targetFees[0].isZero()
? BigInt.fromI32(0)
: targetFees[1] // targetProcotolFee
.times(ev.interestToCharge)
.div(targetFees[0]); // targetInterest

const trueTax = calculateTax(event.address, "v2", ev.interestToCharge);

const actualDays = (event.block.timestamp
.minus(approvedInvoice.getFundedTimestamp()))
.div(BigInt.fromI32(3600 * 24));
const actualDays = event.block.timestamp.minus(approvedInvoice.getFundedTimestamp()).div(BigInt.fromI32(3600 * 24));

const adminFee =
actualDays.times(BigInt.fromI32(approvedInvoice.getAdminFeeBps())).times(approvedInvoice.getTrueFaceValue()).div(BigInt.fromI32(365)).div(BigInt.fromI32(10_000));
const adminFee = actualDays
.times(BigInt.fromI32(approvedInvoice.getAdminFeeBps()))
.times(approvedInvoice.getTrueFaceValue())
.div(BigInt.fromI32(365))
.div(BigInt.fromI32(10_000));

InvoiceUnfactoredEvent.invoiceId = underlyingClaim.id;
InvoiceUnfactoredEvent.originalCreditor = ev.originalCreditor;
Expand Down Expand Up @@ -602,7 +605,7 @@ export function handleActivePaidInvoicesReconciled(event: ActivePaidInvoicesReco
originalCreditor.save();
pnlTotal = pnlTotal.plus(trueNetInterest);
}

const pool_pnl = getOrCreatePoolProfitAndLoss(event, pnlTotal);
const price_per_share = getOrCreatePricePerShare(event, version);
const historical_factoring_statistics = getOrCreateHistoricalFactoringStatistics(event, version);
Expand Down
82 changes: 82 additions & 0 deletions bulla-contracts/src/mappings/BullaSwap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { OrderCreated, OrderExecuted } from "../../generated/BullaSwap/BullaSwap";
import { OrderERC20 } from "../../generated/schema";
import { createOrderCreatedEvent, createOrderExecutedEvent } from "../functions/BullaSwap";
import { getOrCreateToken, getOrCreateUser } from "../functions/common";

export function handleOrderCreated(event: OrderCreated): void {
const ev = event.params;
const orderId = ev.orderId;

// Create the order entity
const order = new OrderERC20(orderId.toString());
order.orderId = orderId;
order.expiry = ev.order.expiry;
order.signerWallet = ev.order.signerWallet;
order.signerToken = getOrCreateToken(ev.order.signerToken).id;
order.signerAmount = ev.order.signerAmount;
order.senderWallet = ev.order.senderWallet;
order.senderToken = getOrCreateToken(ev.order.senderToken).id;
order.senderAmount = ev.order.senderAmount;
order.save();

// Create the event entity
const orderCreatedEvent = createOrderCreatedEvent(orderId, event);
orderCreatedEvent.order = order.id;
orderCreatedEvent.sender = ev.sender;
orderCreatedEvent.signerWallet = ev.order.signerWallet;
orderCreatedEvent.eventName = "OrderCreated";
orderCreatedEvent.blockNumber = event.block.number;
orderCreatedEvent.transactionHash = event.transaction.hash;
orderCreatedEvent.logIndex = event.logIndex;
orderCreatedEvent.timestamp = event.block.timestamp;

// Update user entities
const sender = getOrCreateUser(ev.sender);
sender.swapEvents = sender.swapEvents ? sender.swapEvents.concat([orderCreatedEvent.id]) : [orderCreatedEvent.id];
sender.save();

const signer = getOrCreateUser(ev.signerWallet);
signer.swapEvents = signer.swapEvents ? signer.swapEvents.concat([orderCreatedEvent.id]) : [orderCreatedEvent.id];
signer.save();

orderCreatedEvent.save();
}

export function handleOrderExecuted(event: OrderExecuted): void {
const ev = event.params;
const orderId = ev.orderId;

// Create the order entity
const order = new OrderERC20(orderId.toString());
order.orderId = orderId;
order.expiry = ev.order.expiry;
order.signerWallet = ev.order.signerWallet;
order.signerToken = getOrCreateToken(ev.order.signerToken).id;
order.signerAmount = ev.order.signerAmount;
order.senderWallet = ev.order.senderWallet;
order.senderToken = getOrCreateToken(ev.order.senderToken).id;
order.senderAmount = ev.order.senderAmount;
order.save();

// Create the event entity
const orderExecutedEvent = createOrderExecutedEvent(orderId, event);
orderExecutedEvent.order = order.id;
orderExecutedEvent.sender = ev.sender;
orderExecutedEvent.signerWallet = ev.order.signerWallet;
orderExecutedEvent.eventName = "OrderExecuted";
orderExecutedEvent.blockNumber = event.block.number;
orderExecutedEvent.transactionHash = event.transaction.hash;
orderExecutedEvent.logIndex = event.logIndex;
orderExecutedEvent.timestamp = event.block.timestamp;

// Update user entities
const sender = getOrCreateUser(ev.sender);
sender.swapEvents = sender.swapEvents ? sender.swapEvents.concat([orderExecutedEvent.id]) : [orderExecutedEvent.id];
sender.save();

const recipient = getOrCreateUser(ev.recipient);
recipient.swapEvents = recipient.swapEvents ? recipient.swapEvents.concat([orderExecutedEvent.id]) : [orderExecutedEvent.id];
recipient.save();

orderExecutedEvent.save();
}
24 changes: 23 additions & 1 deletion bulla-contracts/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,26 @@ dataSources:
handler: handleSharesRedeemedWithAttachmentV2
- event: InvoiceImpaired(indexed uint256,uint256,uint256)
handler: handleInvoiceImpairedV2
file: ./src/mappings/BullaFactoring.ts
file: ./src/mappings/BullaFactoring.ts
- kind: ethereum/contract
name: BullaSwap
network: {{ network }}
source:
address: "{{ bullaSwap.address }}"
startBlock: {{ bullaSwap.startBlock }}
abi: BullaSwap
mapping:
kind: ethereum/events
apiVersion: {{ apiVersion }}
language: wasm/assemblyscript
entities:
- BullaSwap
abis:
- name: BullaSwap
file: ./abis/BullaSwap.json
eventHandlers:
- event: OrderCreated(indexed uint256,indexed address,indexed address,(uint256,uint256,address,address,uint256,address,address,uint256))
handler: handleOrderCreated
- event: OrderExecuted(indexed uint256,indexed address,indexed address,(uint256,uint256,address,address,uint256,address,address,uint256))
handler: handleOrderExecuted
file: ./src/mappings/BullaSwap.ts
87 changes: 87 additions & 0 deletions bulla-contracts/tests/BullaSwap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { BigInt, log } from "@graphprotocol/graph-ts";
import { assert, test } from "matchstick-as/assembly/index";

import { handleOrderCreated, handleOrderExecuted } from "../src/mappings/BullaSwap";
import { ADDRESS_1, ADDRESS_2, ADDRESS_3, ADDRESS_4, afterEach, setupContracts } from "./helpers";
import { newOrderCreatedEvent, newOrderExecutedEvent } from "./functions/BullaSwap.testtools";
import { User } from "../generated/schema";
import { getOrderCreatedEventId, getOrderExecutedEventId } from "../src/functions/BullaSwap";

test("it handles OrderCreated event", () => {
const orderId = BigInt.fromI32(3);
const expiry = BigInt.fromI32(100);
const signerWallet = ADDRESS_1;
const signerToken = ADDRESS_2;
const signerAmount = BigInt.fromI32(10000);
const senderWallet = ADDRESS_3;
const senderToken = ADDRESS_4;
const senderAmount = BigInt.fromI32(10000);

setupContracts();
const signerUser = new User(signerWallet.toHexString());
signerUser.swapEvents = [];
signerUser.save();

const senderUser = new User(senderWallet.toHexString());
senderUser.swapEvents = [];
senderUser.save();

const timestamp = BigInt.fromI32(100);
const blockNum = BigInt.fromI32(100);

const orderCreatedEvent = newOrderCreatedEvent(orderId, signerWallet, signerToken, signerAmount, senderWallet, senderToken, senderAmount, expiry);
orderCreatedEvent.block.timestamp = timestamp;
orderCreatedEvent.block.number = blockNum;

handleOrderCreated(orderCreatedEvent);

const orderCreatedEventId = getOrderCreatedEventId(orderId, orderCreatedEvent);
assert.fieldEquals("OrderCreatedEvent", orderCreatedEventId, "signerWallet", signerWallet.toHexString());
assert.fieldEquals("OrderCreatedEvent", orderCreatedEventId, "sender", senderWallet.toHexString());
assert.fieldEquals("OrderERC20", orderId.toString(), "orderId", orderId.toString());

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

afterEach();
});

test("it handles OrderExecuted event", () => {
const orderId = BigInt.fromI32(3);
const expiry = BigInt.fromI32(100);
const signerWallet = ADDRESS_1;
const signerToken = ADDRESS_2;
const signerAmount = BigInt.fromI32(10000);
const senderWallet = ADDRESS_3;
const senderToken = ADDRESS_4;
const senderAmount = BigInt.fromI32(10000);

setupContracts();
const signerUser = new User(signerWallet.toHexString());
signerUser.swapEvents = [];
signerUser.save();

const senderUser = new User(senderWallet.toHexString());
senderUser.swapEvents = [];
senderUser.save();

const timestamp = BigInt.fromI32(100);
const blockNum = BigInt.fromI32(100);

const orderExecutedEvent = newOrderExecutedEvent(orderId, signerWallet, signerToken, signerAmount, senderWallet, senderToken, senderAmount, expiry);
orderExecutedEvent.block.timestamp = timestamp;
orderExecutedEvent.block.number = blockNum;

handleOrderExecuted(orderExecutedEvent);

const orderExecutedEventId = getOrderExecutedEventId(orderId, orderExecutedEvent);
assert.fieldEquals("OrderExecutedEvent", orderExecutedEventId, "signerWallet", signerWallet.toHexString());
assert.fieldEquals("OrderExecutedEvent", orderExecutedEventId, "sender", senderWallet.toHexString());
assert.fieldEquals("OrderERC20", orderId.toString(), "orderId", orderId.toString());

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

afterEach();
});

// exporting for test coverage
export { handleOrderCreated, handleOrderExecuted };
Loading

0 comments on commit 0e1110d

Please sign in to comment.