deploy.js script

This commit is contained in:
EmberSpirit007 2025-01-23 19:32:49 +01:00
parent 5824bf0091
commit 9d84ef3951
27 changed files with 162 additions and 6654 deletions

View file

@ -25,14 +25,6 @@ for stats
burnedLastWeek
burnedLastDay
burnNextHourProjected
totalTaxPaid
taxPaidLastWeek
taxPaidLastDay
taxNextHourProjected
totalUbiClaimed
ubiClaimedLastWeek
ubiClaimedLastDay
ubiNextHourProjected
}
}
```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,86 @@
const fs = require('fs');
const { exec } = require("child_process");
const readline = require("readline");
// Netzwerkspezifische Informationen
const networks = {
'base-sepolia': {
NETWORK: 'base-sepolia',
CONTRACT_ADDRESS_HARB: '0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8',
CONTRACT_ADDRESS_STAKE: '0xe28020BCdEeAf2779dd47c670A8eFC2973316EE2',
START_BLOCK: 20940337,
SUBGRAPH_NAME: "harb-base-sepolia"
},
'sepolia': {
NETWORK: 'sepolia',
CONTRACT_ADDRESS_HARB: '0x087F256D11fe533b0c7d372e44Ee0F9e47C89dF9',
CONTRACT_ADDRESS_STAKE: '0xCd21a41a137BCAf8743E47D048F57D92398f7Da9',
START_BLOCK: 6746241,
SUBGRAPH_NAME: "harb"
},
};
// Netzwerk über Kommandozeilenargument auswählen
const args = process.argv.slice(2);
if (args.length === 0) {
console.error('Kein Netzwerk angegeben, z. B.: node deploy.js sepolia');
process.exit(1);
}
const selectedNetwork = networks[args[0]];
if (!selectedNetwork) {
console.error(`Kein gülitges Netzwerk angegeben: ${args[0]}. Verfügbare Netzwerke: ${Object.keys(networks).join(', ')}`);
process.exit(1);
}
// Template-Datei laden
const subgraphTemplate = fs.readFileSync('subgraph_template.yaml', 'utf-8');
// Platzhalter ersetzen
let subgraphConfig = subgraphTemplate.replace(/{{NETWORK}}/g, selectedNetwork.NETWORK);
subgraphConfig = subgraphConfig.replace(/{{CONTRACT_ADDRESS_STAKE}}/g, selectedNetwork.CONTRACT_ADDRESS_STAKE);
subgraphConfig = subgraphConfig.replace(/{{CONTRACT_ADDRESS_HARB}}/g, selectedNetwork.CONTRACT_ADDRESS_HARB);
subgraphConfig = subgraphConfig.replace(/{{START_BLOCK}}/g, selectedNetwork.START_BLOCK);
// Neue Datei generieren
fs.writeFileSync('subgraph.yaml', subgraphConfig);
console.log(`subgraph.yaml für das Netzwerk ${selectedNetwork.NETWORK} wurde erfolgreich generiert.`);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Which version label to use1? (e.g. "v0.0.1"): ', (versionLabel) => {
if (!versionLabel) {
console.error("Kein Versionslabel angegeben. Abbruch.");
rl.close();
process.exit(1);
}
const serverAdress = "https://api.studio.thegraph.com/deploy/";
console.log(`Starte Deployment mit Versionslabel "${versionLabel}"...`);
// Spawn-Prozess starten
// const deployProcess = spawn("graph", ["deploy", "--node", serverAdress, selectedNetwork.SUBGRAPH_NAME]);
const command = `graph deploy --node ${serverAdress} ${selectedNetwork.SUBGRAPH_NAME} --version-label ${versionLabel}`;
console.log(`Auszuführender Befehl: ${command}`);
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Fehler: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
}
console.log(`stdout: ${stdout}`);
});
});

View file

@ -20,15 +20,6 @@ type Stats @entity {
burnedLastDay: BigInt!
burnNextHourProjected: BigInt!
totalTaxPaid: BigInt!
taxPaidLastWeek: BigInt!
taxPaidLastDay: BigInt!
taxNextHourProjected: BigInt!
totalUbiClaimed: BigInt!
ubiClaimedLastWeek: BigInt!
ubiClaimedLastDay: BigInt!
ubiNextHourProjected: BigInt!
}
enum PositionStatus {

View file

@ -30,17 +30,7 @@ function getOrCreateStats(): Stats {
stats.burnedLastDay = BigInt.zero();
stats.burnNextHourProjected = BigInt.zero();
// Tax paid
stats.totalTaxPaid = BigInt.zero();
stats.taxPaidLastWeek = BigInt.zero();
stats.taxPaidLastDay = BigInt.zero();
stats.taxNextHourProjected = BigInt.zero();
// UBI claimed
stats.totalUbiClaimed = BigInt.zero();
stats.ubiClaimedLastWeek = BigInt.zero();
stats.ubiClaimedLastDay = BigInt.zero();
stats.ubiNextHourProjected = BigInt.zero();
stats.ringBuffer = new Array<BigInt>(168 * 4).fill(BigInt.zero());
stats.ringBufferPointer = 0;
@ -61,8 +51,6 @@ export function handleTransfer(event: TransferEvent): void {
const harberg = Harb.bind(event.address);
if (event.params.from == TAX_POOL_ADDR) {
// Update total UBI claimed
stats.totalUbiClaimed = stats.totalUbiClaimed.plus(event.params.value);
// Add the UBI amount to the current hour's total in the ring buffer
let ubiBufferIndex = (stats.ringBufferPointer * 4) + 0; // UBI is at index 0
@ -89,8 +77,6 @@ export function handleTransfer(event: TransferEvent): void {
stats.harbTotalSupply = stats.harbTotalSupply.minus(event.params.value);
} else if (event.params.to == TAX_POOL_ADDR) {
// Tax paid event
stats.totalTaxPaid = stats.totalTaxPaid.plus(event.params.value);
// Add the burned amount to the current hour's total in the ring buffer
let taxBufferIndex = (stats.ringBufferPointer * 4) + 3; // tax paid is at index 3
@ -134,41 +120,29 @@ export function handleBlock(block: ethereum.Block): void {
let mintedLastWeek = BigInt.zero();
let burnedLastWeek = BigInt.zero();
let taxPaidLastWeek = BigInt.zero();
let ubiClaimedLastWeek = BigInt.zero();
let mintedLastDay = BigInt.zero();
let burnedLastDay = BigInt.zero();
let taxPaidLastDay = BigInt.zero();
let ubiClaimedLastDay = BigInt.zero();
for (let i = 0; i < 168; i++) {
let index = ((stats.ringBufferPointer - i + 168) % 168) * 4;
ubiClaimedLastWeek = ubiClaimedLastWeek.plus(ringBuffer[index]);
mintedLastWeek = mintedLastWeek.plus(ringBuffer[index + 1]);
burnedLastWeek = burnedLastWeek.plus(ringBuffer[index + 2]);
taxPaidLastWeek = taxPaidLastWeek.plus(ringBuffer[index + 3]);
if (i < 24) {
ubiClaimedLastDay = ubiClaimedLastDay.plus(ringBuffer[index]);
mintedLastDay = mintedLastDay.plus(ringBuffer[index + 1]);
burnedLastDay = burnedLastDay.plus(ringBuffer[index + 2]);
taxPaidLastDay = taxPaidLastDay.plus(ringBuffer[index + 3]);
}
}
stats.mintedLastWeek = mintedLastWeek;
stats.burnedLastWeek = burnedLastWeek;
stats.taxPaidLastWeek = taxPaidLastWeek;
stats.ubiClaimedLastWeek = ubiClaimedLastWeek;
stats.mintedLastDay = mintedLastDay;
stats.burnedLastDay = burnedLastDay;
stats.taxPaidLastDay = taxPaidLastDay;
stats.ubiClaimedLastDay = ubiClaimedLastDay;
// Update the ring buffer in the stats entity
stats.ringBuffer = ringBuffer;
@ -198,14 +172,10 @@ export function handleBlock(block: ethereum.Block): void {
let medium = previousHourTotal.plus(projectedTotal).div(BigInt.fromI32(2));
if (i == 0) {
stats.ubiNextHourProjected = (medium > BigInt.zero()) ? medium : stats.ubiClaimedLastWeek.div(BigInt.fromI32(7));
} else if (i == 1) {
if (i == 1) {
stats.mintNextHourProjected = (medium > BigInt.zero()) ? medium : stats.mintedLastWeek.div(BigInt.fromI32(7));
} else if (i == 2) {
stats.burnNextHourProjected = (medium > BigInt.zero()) ? medium : stats.burnedLastWeek.div(BigInt.fromI32(7));
} else if (i == 3) {
stats.taxNextHourProjected = (medium > BigInt.zero()) ? medium : stats.taxPaidLastWeek.div(BigInt.fromI32(7));
}
}

View file

@ -22,7 +22,7 @@ export function handlePositionCreated(event: PositionCreatedEvent): void {
position.creationTime = event.block.timestamp.toI32();
position.lastTaxTime = event.block.timestamp.toI32();
position.taxRate = BigDecimal.fromString(taxRates[event.params.taxRate.toI32()]);
position.harbDeposit = event.params.harbergDeposit;
position.harbDeposit = event.params.harbDeposit;
position.status = "Active";
position.snatched = 0;
position.payout = BigInt.fromString("0");
@ -44,7 +44,7 @@ export function handlePositionRemoved(event: PositionRemovedEvent): void {
position.status = "Closed";
let harb = Harb.bind(getSubgraphConfig().harbergAddress);
position.totalSupplyEnd = harb.totalSupply();
position.payout = position.payout.plus(event.params.harbergPayout);
position.payout = position.payout.plus(event.params.harbPayout);
position.save();
}
let stake = Stake.bind(event.address);
@ -59,10 +59,10 @@ export function handlePositionShrunk(event: PositionShrunkEvent): void {
let position = Position.load(Bytes.fromI32(event.params.positionId.toI32()));
if (position != null) {
position.share = event.params.newShares.toBigDecimal().div(totalSupply);
position.harbDeposit = position.harbDeposit.minus(event.params.harbergPayout);
position.harbDeposit = position.harbDeposit.minus(event.params.harbPayout);
position.snatched = position.snatched++;
position.payout = position.payout.plus(event.params.harbergPayout);
position.payout = position.payout.plus(event.params.harbPayout);
position.save();
}
}

View file

@ -8,9 +8,9 @@ dataSources:
name: Harb
network: base-sepolia
source:
address: "0x54838DC097E7fC4736B801bF1c1FCf1597348265"
address: "0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8"
abi: Harb
startBlock: 15399960
startBlock: 20940337
mapping:
kind: ethereum/events
apiVersion: 0.0.7
@ -31,9 +31,9 @@ dataSources:
name: Stake
network: base-sepolia
source:
address: "0xd7728173F73C748944d29EA77b56f09b8FEc8F33"
address: "0xe28020BCdEeAf2779dd47c670A8eFC2973316EE2"
abi: Stake
startBlock: 15399960
startBlock: 20940337
mapping:
kind: ethereum/events
apiVersion: 0.0.7

View file

@ -6,11 +6,11 @@ schema:
dataSources:
- kind: ethereum
name: Harb
network: sepolia
network: {{NETWORK}}
source:
address: "0x087F256D11fe533b0c7d372e44Ee0F9e47C89dF9"
address: "{{CONTRACT_ADDRESS_HARB}}"
abi: Harb
startBlock: 6152180
startBlock: {{START_BLOCK}}
mapping:
kind: ethereum/events
apiVersion: 0.0.7
@ -24,18 +24,16 @@ dataSources:
eventHandlers:
- event: Transfer(indexed address,indexed address,uint256)
handler: handleTransfer
- event: UbiClaimed(indexed address,uint256)
handler: handleUbiClaimed
blockHandlers:
- handler: handleBlock
file: ./src/harb.ts
- kind: ethereum
name: Stake
network: sepolia
network: {{NETWORK}}
source:
address: "0xCd21a41a137BCAf8743E47D048F57D92398f7Da9"
address: "{{CONTRACT_ADDRESS_STAKE}}"
abi: Stake
startBlock: 6182180
startBlock: {{START_BLOCK}}
mapping:
kind: ethereum/events
apiVersion: 0.0.7

View file

@ -0,0 +1,59 @@
specVersion: 0.0.4
repository: http://gitea.loseyourip.com:4000/dark-meme-society/harb.git
description: Harberger Tax Token
schema:
file: ./schema.graphql
dataSources:
- kind: ethereum
name: Harb
network: base-sepolia
source:
address: "0x54838DC097E7fC4736B801bF1c1FCf1597348265"
abi: Harb
startBlock: 15399960
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
entities:
- Stats
- UbiClaim
abis:
- name: Harb
file: ./abis/Harb.json
eventHandlers:
- event: Transfer(indexed address,indexed address,uint256)
handler: handleTransfer
blockHandlers:
- handler: handleBlock
file: ./src/harb.ts
- kind: ethereum
name: Stake
network: base-sepolia
source:
address: "0xd7728173F73C748944d29EA77b56f09b8FEc8F33"
abi: Stake
startBlock: 15399960
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
entities:
- Position
abis:
- name: Stake
file: ./abis/Stake.json
- name: Harb
file: ./abis/Harb.json
eventHandlers:
- event: PositionCreated(indexed uint256,indexed address,uint256,uint256,uint32)
handler: handlePositionCreated
- event: PositionRemoved(indexed uint256,indexed address,uint256)
handler: handlePositionRemoved
- event: PositionShrunk(indexed uint256,indexed address,uint256,uint256)
handler: handlePositionShrunk
- event: PositionTaxPaid(indexed uint256,indexed address,uint256,uint256,uint256)
handler: handleTaxPaid
- event: PositionRateHiked(indexed uint256,indexed address,uint256)
handler: handlePositionRateHiked
file: ./src/stake.ts

View file

@ -1,4 +0,0 @@
build/
node_modules/
generated/
yarn.lock

View file

@ -1,9 +0,0 @@
## deployment
```
yarn codegen
yarn build
yarn deploy
```

View file

@ -1 +0,0 @@
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"},{"internalType":"address","name":"_harb","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int24","name":"tickLower","type":"int24"},{"indexed":true,"internalType":"int24","name":"tickUpper","type":"int24"},{"indexed":false,"internalType":"uint128","name":"liquidity","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"IncreaseLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int24","name":"tickLower","type":"int24"},{"indexed":true,"internalType":"int24","name":"tickUpper","type":"int24"},{"indexed":false,"internalType":"uint128","name":"liquidity","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"ethReceived","type":"uint256"}],"name":"PositionLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount0Owed","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount1Owed","type":"uint256"}],"name":"UniCallback","type":"event"},{"inputs":[],"name":"liquidityPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outstanding","outputs":[{"internalType":"uint256","name":"_outstanding","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum BaseLineLP.Stage","name":"","type":"uint8"}],"name":"positions","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"feeDestination_","type":"address"}],"name":"setFeeDestination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shift","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slide","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spendingLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum BaseLineLP.Stage","name":"s","type":"uint8"}],"name":"tokensIn","outputs":[{"internalType":"uint256","name":"_ethInPosition","type":"uint256"},{"internalType":"uint256","name":"_harbInPosition","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Owed","type":"uint256"},{"internalType":"uint256","name":"amount1Owed","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"uniswapV3MintCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,12 +0,0 @@
{
"sepolia": {
"Harb": {
"address": "0x7517db0f2b24223f2f0e3567149ca180e204da8a",
"startBlock": 5909060
},
"Stake": {
"address": "0x00b4d656b8182d0c2f4841b7a6f1429b94f73a66",
"startBlock": 5909060
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,23 +0,0 @@
{
"name": "harb",
"license": "UNLICENSED",
"scripts": {
"codegen": "graph codegen",
"build": "graph build",
"deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ harb",
"create-local": "graph create --node http://localhost:8020/ harb",
"remove-local": "graph remove --node http://localhost:8020/ harb",
"deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 harb",
"test": "graph test"
},
"dependencies": {
"@graphprotocol/graph-cli": "0.69.0",
"@graphprotocol/graph-ts": "0.34.0",
"assemblyscript": "0.27.25"
},
"devDependencies": {
"@types/node": "^20.11.30",
"matchstick-as": "0.5.0",
"typescript": "^5.4.3"
}
}

View file

@ -1,59 +0,0 @@
# scalar Bytes
# scalar BigInt
# scalar BigDecimal
type Stats @entity {
id: Bytes!
outstandingSupply: BigInt! # uint256
activeSupply: BigInt! # uint256
ringBuffer: [BigInt!]! # Ring buffer to store daily totals
ringBufferPointer: Int! # Pointer to the current day in the ring buffer
lastUpdatedHour: Int! # The last updated day boundary (timestamp in days)
totalMinted: BigInt!
mintedLastWeek: BigInt!
mintedLastDay: BigInt!
mintNextHourProjected: BigInt!
totalBurned: BigInt!
burnedLastWeek: BigInt!
burnedLastDay: BigInt!
burnNextHourProjected: BigInt!
totalTaxPaid: BigInt!
taxPaidLastWeek: BigInt!
taxPaidLastDay: BigInt!
taxNextHourProjected: BigInt!
totalUbiClaimed: BigInt!
ubiClaimedLastWeek: BigInt!
ubiClaimedLastDay: BigInt!
ubiNextHourProjected: BigInt!
}
enum PositionStatus {
Active
Closed
}
type Position @entity {
id: Bytes!
owner: Bytes! # address
share: BigDecimal!
# harb at start
# current harb value
creationTime: Int!
lastTaxTime: Int
taxRate: BigDecimal!
taxPaid: BigInt!
harbDeposit: BigInt!
snatched: Int!
totalSupplyInit: BigInt!
totalSupplyEnd: BigInt
status: PositionStatus!
payout: BigInt!
}
# type Query {
# stats: [Stats!]
# positions: [Position!]
#}

View file

@ -1,222 +0,0 @@
import {
Approval as ApprovalEvent,
EIP712DomainChanged as EIP712DomainChangedEvent,
Transfer as TransferEvent,
UbiClaimed as UbiClaimedEvent
} from "../generated/Harb/Harb";
import { BigInt, Bytes, ethereum, Address, log } from "@graphprotocol/graph-ts";
import { Stats } from "../generated/schema"
// Helper function to get or create Stats entity
function getOrCreateStats(): Stats {
let stats = Stats.load(Bytes.fromHexString("0x01") as Bytes);
if (stats == null) {
stats = new Stats(Bytes.fromHexString("0x01") as Bytes);
stats.outstandingSupply = BigInt.zero();
stats.activeSupply = BigInt.zero();
// Minted
stats.totalMinted = BigInt.zero();
stats.mintedLastWeek = BigInt.zero();
stats.mintedLastDay = BigInt.zero();
stats.mintNextHourProjected = BigInt.zero();
// Burned
stats.totalBurned = BigInt.zero();
stats.burnedLastWeek = BigInt.zero();
stats.burnedLastDay = BigInt.zero();
stats.burnNextHourProjected = BigInt.zero();
// Tax paid
stats.totalTaxPaid = BigInt.zero();
stats.taxPaidLastWeek = BigInt.zero();
stats.taxPaidLastDay = BigInt.zero();
stats.taxNextHourProjected = BigInt.zero();
// UBI claimed
stats.totalUbiClaimed = BigInt.zero();
stats.ubiClaimedLastWeek = BigInt.zero();
stats.ubiClaimedLastDay = BigInt.zero();
stats.ubiNextHourProjected = BigInt.zero();
stats.ringBuffer = new Array<BigInt>(168 * 4).fill(BigInt.zero());
stats.ringBufferPointer = 0;
stats.lastUpdatedHour = 0;
}
return stats;
}
export function handleUbiClaimed(event: UbiClaimedEvent): void {
let stats = getOrCreateStats();
// Get a copy of the ring buffer
let ringBuffer = stats.ringBuffer;
// Update total UBI claimed
stats.totalUbiClaimed = stats.totalUbiClaimed.plus(event.params.ubiAmount);
// Add the UBI amount to the current hour's total in the ring buffer
let ubiBufferIndex = (stats.ringBufferPointer * 4) + 0; // UBI is at index 0
ringBuffer[ubiBufferIndex] = ringBuffer[ubiBufferIndex].plus(event.params.ubiAmount);
// Update the ring buffer in the stats entity
stats.ringBuffer = ringBuffer;
// Save the updated Stats entity
stats.save();
}
export function handleTransfer(event: TransferEvent): void {
let ZERO_ADDRESS = Address.fromString("0x0000000000000000000000000000000000000000");
let TAX_POOL_ADDR = Address.fromString("0x0000000000000000000000000000000000000002");
let stats = getOrCreateStats();
// Get a copy of the ring buffer
let ringBuffer = stats.ringBuffer;
// Determine if it's a mint or burn event
if (event.params.from == ZERO_ADDRESS) {
// Mint event
stats.totalMinted = stats.totalMinted.plus(event.params.value);
// Add the minted amount to the current hour's total in the ring buffer
let mintBufferIndex = (stats.ringBufferPointer * 4) + 1; // Minted tokens are at index 1
ringBuffer[mintBufferIndex] = ringBuffer[mintBufferIndex].plus(event.params.value);
} else if (event.params.to == ZERO_ADDRESS) {
// Burn event
stats.totalBurned = stats.totalBurned.plus(event.params.value);
// Add the burned amount to the current hour's total in the ring buffer
let burnBufferIndex = (stats.ringBufferPointer * 4) + 2; // Burned tokens are at index 2
ringBuffer[burnBufferIndex] = ringBuffer[burnBufferIndex].plus(event.params.value);
} else if (event.params.to == TAX_POOL_ADDR) {
// Tax paid event
stats.totalTaxPaid = stats.totalTaxPaid.plus(event.params.value);
// Add the burned amount to the current hour's total in the ring buffer
let taxBufferIndex = (stats.ringBufferPointer * 4) + 3; // tax paid is at index 3
ringBuffer[taxBufferIndex] = ringBuffer[taxBufferIndex].plus(event.params.value);
}
// Update the ring buffer in the stats entity
stats.ringBuffer = ringBuffer;
// Save the updated Stats entity
stats.save();
}
// Block handler to aggregate stats
export function handleBlock(block: ethereum.Block): void {
// Update Stats entity
let stats = getOrCreateStats();
// Get a copy of the ring buffer
let ringBuffer = stats.ringBuffer;
// Calculate the current hour
let currentHour = block.timestamp.toI32() / 3600;
// Check if we've moved to a new hour
if (currentHour > stats.lastUpdatedHour) {
// Move the ring buffer pointer forward
stats.ringBufferPointer = (stats.ringBufferPointer + 1) % 168;
// Reset the new current hour in the ring buffer
let baseIndex = stats.ringBufferPointer * 4;
ringBuffer[baseIndex] = BigInt.zero(); // UBI claimed
ringBuffer[baseIndex + 1] = BigInt.zero(); // Minted tokens
ringBuffer[baseIndex + 2] = BigInt.zero(); // Burned tokens
// Update the last updated hour
stats.lastUpdatedHour = currentHour;
// Recalculate the sum of the last 7 days and 24 hours
let mintedLastWeek = BigInt.zero();
let burnedLastWeek = BigInt.zero();
let taxPaidLastWeek = BigInt.zero();
let ubiClaimedLastWeek = BigInt.zero();
let mintedLastDay = BigInt.zero();
let burnedLastDay = BigInt.zero();
let taxPaidLastDay = BigInt.zero();
let ubiClaimedLastDay = BigInt.zero();
for (let i = 0; i < 168; i++) {
let index = ((stats.ringBufferPointer - i + 168) % 168) * 4;
ubiClaimedLastWeek = ubiClaimedLastWeek.plus(ringBuffer[index]);
mintedLastWeek = mintedLastWeek.plus(ringBuffer[index + 1]);
burnedLastWeek = burnedLastWeek.plus(ringBuffer[index + 2]);
taxPaidLastWeek = taxPaidLastWeek.plus(ringBuffer[index + 3]);
if (i < 24) {
ubiClaimedLastDay = ubiClaimedLastDay.plus(ringBuffer[index]);
mintedLastDay = mintedLastDay.plus(ringBuffer[index + 1]);
burnedLastDay = burnedLastDay.plus(ringBuffer[index + 2]);
taxPaidLastDay = taxPaidLastDay.plus(ringBuffer[index + 3]);
}
}
stats.mintedLastWeek = mintedLastWeek;
stats.burnedLastWeek = burnedLastWeek;
stats.taxPaidLastWeek = taxPaidLastWeek;
stats.ubiClaimedLastWeek = ubiClaimedLastWeek;
stats.mintedLastDay = mintedLastDay;
stats.burnedLastDay = burnedLastDay;
stats.taxPaidLastDay = taxPaidLastDay;
stats.ubiClaimedLastDay = ubiClaimedLastDay;
// Update the ring buffer in the stats entity
stats.ringBuffer = ringBuffer;
} else {
// update projected stats with every block
// Calculate the elapsed time in the current hour
let currentTimestamp = block.timestamp.toI32();
let startOfHour = (currentTimestamp / 3600) * 3600;
let elapsedSeconds = currentTimestamp - startOfHour;
for (var i = 0; i <= 3; i++) {
let bufferIndex = (stats.ringBufferPointer * 4) + i;
// Project the current hour's total based on the average rate of burned tokens in the current hour
let projectedTotal = ringBuffer[bufferIndex].times(BigInt.fromI32(3600)).div(BigInt.fromI32(elapsedSeconds));
// Calculate the medium between the previous hour and the projection
let previousHourTotal = ringBuffer[((stats.ringBufferPointer - 1 + 168) % 168) * 4 + i];
log.info("projecting stats : {} projected total: {}. previous hour Total: {}. medium: {}", [
i.toString(),
projectedTotal.toString(),
previousHourTotal.toString(),
previousHourTotal.plus(projectedTotal).div(BigInt.fromI32(2)).toString(),
]);
let medium = previousHourTotal.plus(projectedTotal).div(BigInt.fromI32(2));
if (i == 0) {
stats.ubiNextHourProjected = (medium > BigInt.zero()) ? medium : stats.ubiClaimedLastWeek.div(BigInt.fromI32(7));
} else if (i == 1) {
stats.mintNextHourProjected = (medium > BigInt.zero()) ? medium : stats.mintedLastWeek.div(BigInt.fromI32(7));
} else if (i == 2) {
stats.burnNextHourProjected = (medium > BigInt.zero()) ? medium : stats.burnedLastWeek.div(BigInt.fromI32(7));
} else if (i == 3) {
stats.taxNextHourProjected = (medium > BigInt.zero()) ? medium : stats.taxPaidLastWeek.div(BigInt.fromI32(7));
}
}
}
// Save the updated Stats entity
stats.save();
}

View file

@ -1,11 +0,0 @@
query GetPositions {
positions {
id
owner
share
creationTime
lastTaxTime
taxRate
status
}
}

View file

@ -1,70 +0,0 @@
import {
PositionCreated as PositionCreatedEvent,
PositionRemoved as PositionRemovedEvent,
PositionTaxPaid as PositionTaxPaidEvent,
PositionShrunk as PositionShrunkEvent,
PositionRateHiked as PositionRateHikedEvent,
} from "../generated/Stake/Stake";
import { Harb } from "../generated/Harb/Harb";
import { BigDecimal, BigInt, Bytes } from "@graphprotocol/graph-ts";
import { Position } from "../generated/schema";
let decimals: BigDecimal = BigDecimal.fromString("1000000000000000000");
let totalSupply: BigDecimal = BigDecimal.fromString("10000000000000000000000000");
let taxRates: Array<string> = ["0.01", "0.03", "0.05", "0.08", "0.12", "0.18", "0.24", "0.30", "0.40", "0.50", "0.60", "0.80", "1", "1.3", "1.8", "2.5", "3.2", "4.2", "5.4", "7", "9.2", "12", "16", "20", "26", "34", "44", "57", "75", "97"];
export function handlePositionCreated(event: PositionCreatedEvent): void {
let position = new Position(Bytes.fromI32(event.params.positionId.toI32()));
position.owner = event.params.owner;
position.share = event.params.share.toBigDecimal().div(totalSupply);
position.creationTime = event.block.timestamp.toI32();
position.taxRate = event.params.taxRate.toBigDecimal().div(BigDecimal.fromString("100"));
position.harbDeposit = event.params.harbDeposit;
position.status = "Active";
position.snatched = 0;
position.payout = BigInt.fromString("0");
position.taxPaid = BigInt.fromString("0");
let harb = Harb.bind(event.address);
position.totalSupplyInit = harb.totalSupply();
position.save();
}
export function handlePositionRemoved(event: PositionRemovedEvent): void {
let position = Position.load(Bytes.fromI32(event.params.positionId.toI32()));
if (position != null) {
position.status = "Closed";
let harb = Harb.bind(event.address);
position.totalSupplyEnd = harb.totalSupply();
position.payout = position.payout.plus(event.params.harbPayout);
position.save();
}
}
export function handlePositionShrunk(event: PositionShrunkEvent): void {
let position = Position.load(Bytes.fromI32(event.params.positionId.toI32()));
if (position != null) {
position.share = event.params.newShares.toBigDecimal().div(totalSupply);
position.harbDeposit = position.harbDeposit.minus(event.params.harbPayout);
position.snatched = position.snatched++;
position.payout = position.payout.plus(event.params.harbPayout);
position.save();
}
}
export function handleTaxPaid(event: PositionTaxPaidEvent): void {
let position = Position.load(Bytes.fromI32(event.params.positionId.toI32()));
if (position != null) {
position.taxPaid = position.taxPaid.plus(event.params.taxPaid);
position.taxRate = event.params.taxRate.toBigDecimal().div(BigDecimal.fromString("100"));
position.save();
}
}
export function handlePositionRateHiked(event: PositionRateHikedEvent): void {
let position = Position.load(Bytes.fromI32(event.params.positionId.toI32()));
if (position != null) {
position.taxRate = BigDecimal.fromString(taxRates[event.params.newTaxRate.toI32()]);
position.save();
}
}

View file

@ -1,55 +0,0 @@
import { newMockEvent } from "matchstick-as"
import { ethereum, Address, BigInt } from "@graphprotocol/graph-ts"
import { Approval, EIP712DomainChanged, Transfer } from "../generated/Harb/Harb"
export function createApprovalEvent(
owner: Address,
spender: Address,
value: BigInt
): Approval {
let approvalEvent = changetype<Approval>(newMockEvent())
approvalEvent.parameters = new Array()
approvalEvent.parameters.push(
new ethereum.EventParam("owner", ethereum.Value.fromAddress(owner))
)
approvalEvent.parameters.push(
new ethereum.EventParam("spender", ethereum.Value.fromAddress(spender))
)
approvalEvent.parameters.push(
new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value))
)
return approvalEvent
}
export function createEIP712DomainChangedEvent(): EIP712DomainChanged {
let eip712DomainChangedEvent = changetype<EIP712DomainChanged>(newMockEvent())
eip712DomainChangedEvent.parameters = new Array()
return eip712DomainChangedEvent
}
export function createTransferEvent(
from: Address,
to: Address,
value: BigInt
): Transfer {
let transferEvent = changetype<Transfer>(newMockEvent())
transferEvent.parameters = new Array()
transferEvent.parameters.push(
new ethereum.EventParam("from", ethereum.Value.fromAddress(from))
)
transferEvent.parameters.push(
new ethereum.EventParam("to", ethereum.Value.fromAddress(to))
)
transferEvent.parameters.push(
new ethereum.EventParam("value", ethereum.Value.fromUnsignedBigInt(value))
)
return transferEvent
}

View file

@ -1,62 +0,0 @@
import {
assert,
describe,
test,
clearStore,
beforeAll,
afterAll
} from "matchstick-as/assembly/index"
import { Address, BigInt } from "@graphprotocol/graph-ts"
import { Approval } from "../generated/schema"
import { Approval as ApprovalEvent } from "../generated/Harb/Harb"
import { handleApproval } from "../src/harb"
import { createApprovalEvent } from "./harb-utils"
// Tests structure (matchstick-as >=0.5.0)
// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0
describe("Describe entity assertions", () => {
beforeAll(() => {
let owner = Address.fromString("0x0000000000000000000000000000000000000001")
let spender = Address.fromString(
"0x0000000000000000000000000000000000000001"
)
let value = BigInt.fromI32(234)
let newApprovalEvent = createApprovalEvent(owner, spender, value)
handleApproval(newApprovalEvent)
})
afterAll(() => {
clearStore()
})
// For more test scenarios, see:
// https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test
test("Approval created and stored", () => {
assert.entityCount("Approval", 1)
// 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function
assert.fieldEquals(
"Approval",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"owner",
"0x0000000000000000000000000000000000000001"
)
assert.fieldEquals(
"Approval",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"spender",
"0x0000000000000000000000000000000000000001"
)
assert.fieldEquals(
"Approval",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"value",
"234"
)
// More assert options:
// https://thegraph.com/docs/en/developer/matchstick/#asserts
})
})

View file

@ -1,70 +0,0 @@
import { newMockEvent } from "matchstick-as"
import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts"
import { PositionCreated, PositionRemoved } from "../generated/Stake/Stake"
export function createPositionCreatedEvent(
positionId: BigInt,
owner: Address,
share: BigInt,
creationTime: BigInt,
taxRate: BigInt
): PositionCreated {
let positionCreatedEvent = changetype<PositionCreated>(newMockEvent())
positionCreatedEvent.parameters = new Array()
positionCreatedEvent.parameters.push(
new ethereum.EventParam(
"positionId",
ethereum.Value.fromUnsignedBigInt(positionId)
)
)
positionCreatedEvent.parameters.push(
new ethereum.EventParam("owner", ethereum.Value.fromAddress(owner))
)
positionCreatedEvent.parameters.push(
new ethereum.EventParam("share", ethereum.Value.fromUnsignedBigInt(share))
)
positionCreatedEvent.parameters.push(
new ethereum.EventParam(
"creationTime",
ethereum.Value.fromUnsignedBigInt(creationTime)
)
)
positionCreatedEvent.parameters.push(
new ethereum.EventParam(
"taxRate",
ethereum.Value.fromUnsignedBigInt(taxRate)
)
)
return positionCreatedEvent
}
export function createPositionRemovedEvent(
positionId: BigInt,
share: BigInt,
lastTaxTime: BigInt
): PositionRemoved {
let positionRemovedEvent = changetype<PositionRemoved>(newMockEvent())
positionRemovedEvent.parameters = new Array()
positionRemovedEvent.parameters.push(
new ethereum.EventParam(
"positionId",
ethereum.Value.fromUnsignedBigInt(positionId)
)
)
positionRemovedEvent.parameters.push(
new ethereum.EventParam("share", ethereum.Value.fromUnsignedBigInt(share))
)
positionRemovedEvent.parameters.push(
new ethereum.EventParam(
"lastTaxTime",
ethereum.Value.fromUnsignedBigInt(lastTaxTime)
)
)
return positionRemovedEvent
}

View file

@ -1,80 +0,0 @@
import {
assert,
describe,
test,
clearStore,
beforeAll,
afterAll
} from "matchstick-as/assembly/index"
import { BigInt, Address } from "@graphprotocol/graph-ts"
import { PositionCreated } from "../generated/schema"
import { PositionCreated as PositionCreatedEvent } from "../generated/Stake/Stake"
import { handlePositionCreated } from "../src/stake"
import { createPositionCreatedEvent } from "./stake-utils"
// Tests structure (matchstick-as >=0.5.0)
// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0
describe("Describe entity assertions", () => {
beforeAll(() => {
let positionId = BigInt.fromI32(234)
let owner = Address.fromString("0x0000000000000000000000000000000000000001")
let share = BigInt.fromI32(234)
let creationTime = BigInt.fromI32(234)
let taxRate = BigInt.fromI32(234)
let newPositionCreatedEvent = createPositionCreatedEvent(
positionId,
owner,
share,
creationTime,
taxRate
)
handlePositionCreated(newPositionCreatedEvent)
})
afterAll(() => {
clearStore()
})
// For more test scenarios, see:
// https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test
test("PositionCreated created and stored", () => {
assert.entityCount("PositionCreated", 1)
// 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function
assert.fieldEquals(
"PositionCreated",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"positionId",
"234"
)
assert.fieldEquals(
"PositionCreated",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"owner",
"0x0000000000000000000000000000000000000001"
)
assert.fieldEquals(
"PositionCreated",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"share",
"234"
)
assert.fieldEquals(
"PositionCreated",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"creationTime",
"234"
)
assert.fieldEquals(
"PositionCreated",
"0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
"taxRate",
"234"
)
// More assert options:
// https://thegraph.com/docs/en/developer/matchstick/#asserts
})
})

View file

@ -1,4 +0,0 @@
{
"extends": "@graphprotocol/graph-ts/types/tsconfig.base.json",
"include": ["src", "tests"]
}