From 8d4405884eeae35c49c91025d4f82a9c505e3ee3 Mon Sep 17 00:00:00 2001 From: ioay Date: Tue, 26 Mar 2024 20:43:27 +0100 Subject: [PATCH 01/28] Subgraph: Exposing data to populate Activity Details for stake operation --- subgraph/README.md | 19 +- subgraph/abis/AcreBitcoinDepositor.json | 557 +----------------- subgraph/schema.graphql | 128 ++-- subgraph/src/acre-bitcoin-depositor.ts | 206 +------ subgraph/src/utils.ts | 23 + subgraph/subgraph.yaml | 35 +- .../tests/acre-bitcoin-depositor-utils.ts | 319 +--------- subgraph/tests/acre-bitcoin-depositor.test.ts | 189 ++++-- 8 files changed, 275 insertions(+), 1201 deletions(-) create mode 100644 subgraph/src/utils.ts diff --git a/subgraph/README.md b/subgraph/README.md index 2136be36d..bf6e72f27 100644 --- a/subgraph/README.md +++ b/subgraph/README.md @@ -38,19 +38,24 @@ EVM-compatible JSON-RPC API. You can use Thesis private RPC from Alchemy or create a private one [here](https://www.alchemy.com/overviews/private-rpc-endpoint). -1. Set the API key in the `docker-compose.yaml` file. +1. Install Docker on your local machine: + - Mac: https://docs.docker.com/desktop/install/mac-install/ + - Windows: https://docs.docker.com/desktop/install/windows-install/ + - Linux: https://docs.docker.com/desktop/install/linux-install/ + +2. Set the API key in the `docker-compose.yaml` file. ``` ethereum: "sepolia:https://eth-sepolia.g.alchemy.com/v2/" ``` -2. Run a local Graph Node: +3. Run a local Graph Node: ``` docker-compose up ``` -3. Allocate the subgraph name in the local Graph Node: +4. Allocate the subgraph name in the local Graph Node: ``` pnpm create-local @@ -58,8 +63,14 @@ create a private one Note: use it only if your subgraph is not created in the local Graph node. -4. Deploy the subgraph to your local Graph Node: +5. Deploy the subgraph to your local Graph Node: ``` pnpm deploy-local ``` + +6. Create Subgraph queries and preview of the entities: + + ``` + http://localhost:8000/subgraphs/name/acre-subgraph + ``` diff --git a/subgraph/abis/AcreBitcoinDepositor.json b/subgraph/abis/AcreBitcoinDepositor.json index 4c9d39adf..df4025ed4 100644 --- a/subgraph/abis/AcreBitcoinDepositor.json +++ b/subgraph/abis/AcreBitcoinDepositor.json @@ -1,106 +1,4 @@ [ - { - "inputs": [ - { "internalType": "address", "name": "bridge", "type": "address" }, - { "internalType": "address", "name": "tbtcVault", "type": "address" }, - { "internalType": "address", "name": "_tbtcToken", "type": "address" }, - { "internalType": "address", "name": "_stbtc", "type": "address" } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { "internalType": "address", "name": "target", "type": "address" } - ], - "name": "AddressEmptyCode", - "type": "error" - }, - { - "inputs": [ - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "AddressInsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "BridgingCompletionAlreadyNotified", - "type": "error" - }, - { - "inputs": [], - "name": "BridgingFinalizationAlreadyCalled", - "type": "error" - }, - { "inputs": [], "name": "BridgingNotCompleted", "type": "error" }, - { "inputs": [], "name": "CallerNotStaker", "type": "error" }, - { - "inputs": [ - { "internalType": "uint256", "name": "depositorFee", "type": "uint256" }, - { "internalType": "uint256", "name": "bridgedAmount", "type": "uint256" } - ], - "name": "DepositorFeeExceedsBridgedAmount", - "type": "error" - }, - { "inputs": [], "name": "FailedInnerCall", "type": "error" }, - { - "inputs": [ - { "internalType": "uint256", "name": "amountToStake", "type": "uint256" }, - { "internalType": "uint256", "name": "currentBalance", "type": "uint256" } - ], - "name": "InsufficientTbtcBalance", - "type": "error" - }, - { - "inputs": [ - { "internalType": "address", "name": "owner", "type": "address" } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { "internalType": "address", "name": "account", "type": "address" } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [ - { "internalType": "uint8", "name": "bits", "type": "uint8" }, - { "internalType": "uint256", "name": "value", "type": "uint256" } - ], - "name": "SafeCastOverflowedUintDowncast", - "type": "error" - }, - { - "inputs": [ - { "internalType": "address", "name": "token", "type": "address" } - ], - "name": "SafeERC20FailedOperation", - "type": "error" - }, - { "inputs": [], "name": "StakeRequestNotQueued", "type": "error" }, - { "inputs": [], "name": "StakerIsZeroAddress", "type": "error" }, - { "inputs": [], "name": "StbtcZeroAddress", "type": "error" }, - { "inputs": [], "name": "TbtcTokenZeroAddress", "type": "error" }, - { - "inputs": [ - { - "internalType": "enum AcreBitcoinDepositor.StakeRequestState", - "name": "currentState", - "type": "uint8" - }, - { - "internalType": "enum AcreBitcoinDepositor.StakeRequestState", - "name": "expectedState", - "type": "uint8" - } - ], - "name": "UnexpectedStakeRequestState", - "type": "error" - }, { "anonymous": false, "inputs": [ @@ -116,132 +14,6 @@ "name": "caller", "type": "address" }, - { - "indexed": true, - "internalType": "uint16", - "name": "referral", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "bridgedAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "depositorFee", - "type": "uint256" - } - ], - "name": "BridgingCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tbtcAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "finalizedAt", - "type": "uint32" - } - ], - "name": "DepositFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "initializedAt", - "type": "uint32" - } - ], - "name": "DepositInitialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "depositorFeeDivisor", - "type": "uint64" - } - ], - "name": "DepositorFeeDivisorUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, { "indexed": true, "internalType": "address", @@ -251,338 +23,11 @@ { "indexed": false, "internalType": "uint256", - "name": "amountToStake", - "type": "uint256" - } - ], - "name": "StakeRequestCancelledFromQueue", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stakedAmount", - "type": "uint256" - } - ], - "name": "StakeRequestFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stakedAmount", + "name": "initialAmount", "type": "uint256" } ], - "name": "StakeRequestFinalizedFromQueue", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "staker", - "type": "address" - } - ], "name": "StakeRequestInitialized", "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "queuedAmount", - "type": "uint256" - } - ], - "name": "StakeRequestQueued", - "type": "event" - }, - { - "inputs": [], - "name": "SATOSHI_MULTIPLIER", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { "internalType": "contract IBridge", "name": "", "type": "address" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "depositKey", "type": "uint256" } - ], - "name": "cancelQueuedStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bytes32", "name": "extraData", "type": "bytes32" } - ], - "name": "decodeExtraData", - "outputs": [ - { "internalType": "address", "name": "staker", "type": "address" }, - { "internalType": "uint16", "name": "referral", "type": "uint16" } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "depositorFeeDivisor", - "outputs": [{ "internalType": "uint64", "name": "", "type": "uint64" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "staker", "type": "address" }, - { "internalType": "uint16", "name": "referral", "type": "uint16" } - ], - "name": "encodeExtraData", - "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "depositKey", "type": "uint256" } - ], - "name": "finalizeQueuedStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "depositKey", "type": "uint256" } - ], - "name": "finalizeStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { "internalType": "bytes4", "name": "version", "type": "bytes4" }, - { "internalType": "bytes", "name": "inputVector", "type": "bytes" }, - { "internalType": "bytes", "name": "outputVector", "type": "bytes" }, - { "internalType": "bytes4", "name": "locktime", "type": "bytes4" } - ], - "internalType": "struct IBridgeTypes.BitcoinTxInfo", - "name": "fundingTx", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fundingOutputIndex", - "type": "uint32" - }, - { - "internalType": "bytes8", - "name": "blindingFactor", - "type": "bytes8" - }, - { - "internalType": "bytes20", - "name": "walletPubKeyHash", - "type": "bytes20" - }, - { - "internalType": "bytes20", - "name": "refundPubKeyHash", - "type": "bytes20" - }, - { - "internalType": "bytes4", - "name": "refundLocktime", - "type": "bytes4" - }, - { "internalType": "address", "name": "vault", "type": "address" } - ], - "internalType": "struct IBridgeTypes.DepositRevealInfo", - "name": "reveal", - "type": "tuple" - }, - { "internalType": "address", "name": "staker", "type": "address" }, - { "internalType": "uint16", "name": "referral", "type": "uint16" } - ], - "name": "initializeStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "uint256", "name": "depositKey", "type": "uint256" } - ], - "name": "queueStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "name": "stakeRequests", - "outputs": [ - { - "internalType": "enum AcreBitcoinDepositor.StakeRequestState", - "name": "state", - "type": "uint8" - }, - { "internalType": "address", "name": "staker", "type": "address" }, - { "internalType": "uint88", "name": "queuedAmount", "type": "uint88" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "stbtc", - "outputs": [ - { "internalType": "contract stBTC", "name": "", "type": "address" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tbtcToken", - "outputs": [ - { "internalType": "contract IERC20", "name": "", "type": "address" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tbtcVault", - "outputs": [ - { "internalType": "contract ITBTCVault", "name": "", "type": "address" } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "newOwner", "type": "address" } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newDepositorFeeDivisor", - "type": "uint64" - } - ], - "name": "updateDepositorFeeDivisor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" } ] diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index fa33c0551..b96178d80 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -1,106 +1,62 @@ -type BridgingCompleted @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - caller: Bytes! # address - referral: Int! # uint16 - bridgedAmount: BigInt! # uint256 - depositorFee: BigInt! # uint256 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +enum ChainType { + Bitcoin + Ethereum } -type DepositFinalized @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - tbtcAmount: BigInt! # uint256 - finalizedAt: BigInt! # uint32 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! -} - -type DepositInitialized @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - initializedAt: BigInt! # uint32 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! -} - -type DepositorFeeDivisorUpdated @entity(immutable: true) { - id: Bytes! - depositorFeeDivisor: BigInt! # uint64 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! -} - -type OwnershipTransferStarted @entity(immutable: true) { - id: Bytes! - previousOwner: Bytes! # address - newOwner: Bytes! # address - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +enum LogType { + Initialized + Finalized + Queued + FinalizedFromQueue + CancelledFromQueue } -type OwnershipTransferred @entity(immutable: true) { - id: Bytes! - previousOwner: Bytes! # address - newOwner: Bytes! # address - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +interface ActivityData { + id: ID! + staker: Staker + logs: [LogData!] } -type StakeRequestCancelledFromQueue @entity(immutable: true) { - id: Bytes! +type StakeRequestInitialized @entity { + id: ID! depositKey: BigInt! # uint256 + caller: Bytes! # address staker: Bytes! # address - amountToStake: BigInt! # uint256 blockNumber: BigInt! blockTimestamp: BigInt! transactionHash: Bytes! } -type StakeRequestFinalized @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - caller: Bytes! # address - stakedAmount: BigInt! # uint256 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +type Staker @entity { + # Id is the ethereum address of the account. + id: ID! + activities: [ActivityData!] @derivedFrom(field: "staker") } -type StakeRequestFinalizedFromQueue @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - caller: Bytes! # address - stakedAmount: BigInt! # uint256 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +type Stake implements ActivityData @entity { + id: ID! + staker: Staker + logs: [LogData!] @derivedFrom(field: "activity") + initialDepositAmountSatoshi: BigInt! + amountToStakeStBtc: BigInt! + shareStBtc: BigInt! } -type StakeRequestInitialized @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - caller: Bytes! # address - staker: Bytes! # address - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +type Unstake implements ActivityData @entity { + id: ID! + staker: Staker + logs: [LogData!] @derivedFrom(field: "activity") + initialDepositAmountSatoshi: BigInt! + amountToStakeStBtc: BigInt! + shareStBtc: BigInt! } -type StakeRequestQueued @entity(immutable: true) { - id: Bytes! - depositKey: BigInt! # uint256 - caller: Bytes! # address - queuedAmount: BigInt! # uint256 - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! +type LogData @entity { + # Id is the transaction hash + id: ID! + timestamp: BigInt! + activity: ActivityData + chain: ChainType! + type: LogType + amount: BigInt! } diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts index c7d87d32d..61be4d8f3 100644 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ b/subgraph/src/acre-bitcoin-depositor.ts @@ -1,180 +1,39 @@ -import { - BridgingCompleted as BridgingCompletedEvent, - DepositFinalized as DepositFinalizedEvent, - DepositInitialized as DepositInitializedEvent, - DepositorFeeDivisorUpdated as DepositorFeeDivisorUpdatedEvent, - OwnershipTransferStarted as OwnershipTransferStartedEvent, - OwnershipTransferred as OwnershipTransferredEvent, - StakeRequestCancelledFromQueue as StakeRequestCancelledFromQueueEvent, - StakeRequestFinalized as StakeRequestFinalizedEvent, - StakeRequestFinalizedFromQueue as StakeRequestFinalizedFromQueueEvent, - StakeRequestInitialized as StakeRequestInitializedEvent, - StakeRequestQueued as StakeRequestQueuedEvent, -} from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" -import { - BridgingCompleted, - DepositFinalized, - DepositInitialized, - DepositorFeeDivisorUpdated, - OwnershipTransferStarted, - OwnershipTransferred, - StakeRequestCancelledFromQueue, - StakeRequestFinalized, - StakeRequestFinalizedFromQueue, - StakeRequestInitialized, - StakeRequestQueued, -} from "../generated/schema" +import { StakeRequestInitialized as StakeRequestInitializedEvent } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" +import { Stake, StakeRequestInitialized } from "../generated/schema" +import { getOrCreateStaker, getOrCreateLog } from "./utils" -export function handleBridgingCompleted(event: BridgingCompletedEvent): void { - const entity = new BridgingCompleted( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.depositKey = event.params.depositKey - entity.caller = event.params.caller - entity.referral = event.params.referral - entity.bridgedAmount = event.params.bridgedAmount - entity.depositorFee = event.params.depositorFee - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleDepositFinalized(event: DepositFinalizedEvent): void { - const entity = new DepositFinalized( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.depositKey = event.params.depositKey - entity.tbtcAmount = event.params.tbtcAmount - entity.finalizedAt = event.params.finalizedAt - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleDepositInitialized(event: DepositInitializedEvent): void { - const entity = new DepositInitialized( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.depositKey = event.params.depositKey - entity.initializedAt = event.params.initializedAt - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleDepositorFeeDivisorUpdated( - event: DepositorFeeDivisorUpdatedEvent, -): void { - const entity = new DepositorFeeDivisorUpdated( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.depositorFeeDivisor = event.params.depositorFeeDivisor - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleOwnershipTransferStarted( - event: OwnershipTransferStartedEvent, -): void { - const entity = new OwnershipTransferStarted( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.previousOwner = event.params.previousOwner - entity.newOwner = event.params.newOwner - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleOwnershipTransferred( - event: OwnershipTransferredEvent, -): void { - const entity = new OwnershipTransferred( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.previousOwner = event.params.previousOwner - entity.newOwner = event.params.newOwner - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleStakeRequestCancelledFromQueue( - event: StakeRequestCancelledFromQueueEvent, +// eslint-disable-next-line import/prefer-default-export +export function handleStakeRequestInitialized( + event: StakeRequestInitializedEvent, ): void { - const entity = new StakeRequestCancelledFromQueue( - event.transaction.hash.concatI32(event.logIndex.toI32()), + const entity = new StakeRequestInitialized( + event.transaction.hash.toHexString(), ) - entity.depositKey = event.params.depositKey - entity.staker = event.params.staker - entity.amountToStake = event.params.amountToStake - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash + const stakeEntity = new Stake(event.transaction.hash.toHexString()) - entity.save() -} + const stakerEntity = getOrCreateStaker(event.params.staker) + stakerEntity.save() -export function handleStakeRequestFinalized( - event: StakeRequestFinalizedEvent, -): void { - const entity = new StakeRequestFinalized( - event.transaction.hash.concatI32(event.logIndex.toI32()), + const logDataBtc = getOrCreateLog( + `${event.transaction.hash.toHexString()}btc`, ) - entity.depositKey = event.params.depositKey - entity.caller = event.params.caller - entity.stakedAmount = event.params.stakedAmount - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} - -export function handleStakeRequestFinalizedFromQueue( - event: StakeRequestFinalizedFromQueueEvent, -): void { - const entity = new StakeRequestFinalizedFromQueue( - event.transaction.hash.concatI32(event.logIndex.toI32()), + const logDataEth = getOrCreateLog( + `${event.transaction.hash.toHexString()}eth`, ) - entity.depositKey = event.params.depositKey - entity.caller = event.params.caller - entity.stakedAmount = event.params.stakedAmount - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash + logDataBtc.activity = stakeEntity.id + logDataBtc.timestamp = event.block.timestamp + logDataBtc.chain = "Bitcoin" + logDataBtc.amount = event.params.initialAmount + logDataBtc.save() - entity.save() -} + logDataEth.activity = stakeEntity.id + logDataEth.timestamp = event.block.timestamp + logDataEth.chain = "Ethereum" + logDataEth.amount = event.params.initialAmount + logDataEth.save() -export function handleStakeRequestInitialized( - event: StakeRequestInitializedEvent, -): void { - const entity = new StakeRequestInitialized( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) entity.depositKey = event.params.depositKey entity.caller = event.params.caller entity.staker = event.params.staker @@ -185,18 +44,3 @@ export function handleStakeRequestInitialized( entity.save() } - -export function handleStakeRequestQueued(event: StakeRequestQueuedEvent): void { - const entity = new StakeRequestQueued( - event.transaction.hash.concatI32(event.logIndex.toI32()), - ) - entity.depositKey = event.params.depositKey - entity.caller = event.params.caller - entity.queuedAmount = event.params.queuedAmount - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} diff --git a/subgraph/src/utils.ts b/subgraph/src/utils.ts new file mode 100644 index 000000000..fe77a3cae --- /dev/null +++ b/subgraph/src/utils.ts @@ -0,0 +1,23 @@ +import { Address } from "@graphprotocol/graph-ts" +import { Staker, LogData } from "../generated/schema" + +export function getOrCreateStaker(stakerId: Address): Staker { + const stakerHexString = stakerId.toHexString() + let staker = Staker.load(stakerHexString) + + if (!staker) { + staker = new Staker(stakerHexString) + } + + return staker +} + +export function getOrCreateLog(logId: string): LogData { + let log = LogData.load(logId) + + if (!log) { + log = new LogData(logId) + } + + return log +} diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index be92baecd..b6b81f1a3 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -1,6 +1,4 @@ specVersion: 0.0.5 -indexerHints: - prune: auto schema: file: ./schema.graphql dataSources: @@ -16,41 +14,12 @@ dataSources: apiVersion: 0.0.7 language: wasm/assemblyscript entities: - - BridgingCompleted - - DepositFinalized - - DepositInitialized - - DepositorFeeDivisorUpdated - - OwnershipTransferStarted - - OwnershipTransferred - - StakeRequestCancelledFromQueue - - StakeRequestFinalized - - StakeRequestFinalizedFromQueue - StakeRequestInitialized - - StakeRequestQueued abis: - name: AcreBitcoinDepositor file: ./abis/AcreBitcoinDepositor.json eventHandlers: - - event: BridgingCompleted(indexed uint256,indexed address,indexed uint16,uint256,uint256) - handler: handleBridgingCompleted - - event: DepositFinalized(indexed uint256,uint256,uint32) - handler: handleDepositFinalized - - event: DepositInitialized(indexed uint256,uint32) - handler: handleDepositInitialized - - event: DepositorFeeDivisorUpdated(uint64) - handler: handleDepositorFeeDivisorUpdated - - event: OwnershipTransferStarted(indexed address,indexed address) - handler: handleOwnershipTransferStarted - - event: OwnershipTransferred(indexed address,indexed address) - handler: handleOwnershipTransferred - - event: StakeRequestCancelledFromQueue(indexed uint256,indexed address,uint256) - handler: handleStakeRequestCancelledFromQueue - - event: StakeRequestFinalized(indexed uint256,indexed address,uint256) - handler: handleStakeRequestFinalized - - event: StakeRequestFinalizedFromQueue(indexed uint256,indexed address,uint256) - handler: handleStakeRequestFinalizedFromQueue - - event: StakeRequestInitialized(indexed uint256,indexed address,indexed address) + - event: StakeRequestInitialized(indexed uint256,indexed address,indexed address,uint256) handler: handleStakeRequestInitialized - - event: StakeRequestQueued(indexed uint256,indexed address,uint256) - handler: handleStakeRequestQueued + receipt: true file: ./src/acre-bitcoin-depositor.ts diff --git a/subgraph/tests/acre-bitcoin-depositor-utils.ts b/subgraph/tests/acre-bitcoin-depositor-utils.ts index 6cf8ff247..b0b027998 100644 --- a/subgraph/tests/acre-bitcoin-depositor-utils.ts +++ b/subgraph/tests/acre-bitcoin-depositor-utils.ts @@ -1,315 +1,42 @@ -import { newMockEvent } from "matchstick-as" import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts" -import { - BridgingCompleted, - DepositFinalized, - DepositInitialized, - DepositorFeeDivisorUpdated, - OwnershipTransferStarted, - OwnershipTransferred, - StakeRequestCancelledFromQueue, - StakeRequestFinalized, - StakeRequestFinalizedFromQueue, - StakeRequestInitialized, - StakeRequestQueued, -} from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" - -export function createBridgingCompletedEvent( - depositKey: BigInt, - caller: Address, - referral: i32, - bridgedAmount: BigInt, - depositorFee: BigInt, -): BridgingCompleted { - const bridgingCompletedEvent = changetype(newMockEvent()) - - bridgingCompletedEvent.parameters = [] - - bridgingCompletedEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - bridgingCompletedEvent.parameters.push( - new ethereum.EventParam("caller", ethereum.Value.fromAddress(caller)), - ) - bridgingCompletedEvent.parameters.push( - new ethereum.EventParam( - "referral", - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(referral)), - ), - ) - bridgingCompletedEvent.parameters.push( - new ethereum.EventParam( - "bridgedAmount", - ethereum.Value.fromUnsignedBigInt(bridgedAmount), - ), - ) - bridgingCompletedEvent.parameters.push( - new ethereum.EventParam( - "depositorFee", - ethereum.Value.fromUnsignedBigInt(depositorFee), - ), - ) - - return bridgingCompletedEvent -} - -export function createDepositFinalizedEvent( - depositKey: BigInt, - tbtcAmount: BigInt, - finalizedAt: BigInt, -): DepositFinalized { - const depositFinalizedEvent = changetype(newMockEvent()) - - depositFinalizedEvent.parameters = [] - - depositFinalizedEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - depositFinalizedEvent.parameters.push( - new ethereum.EventParam( - "tbtcAmount", - ethereum.Value.fromUnsignedBigInt(tbtcAmount), - ), - ) - depositFinalizedEvent.parameters.push( - new ethereum.EventParam( - "finalizedAt", - ethereum.Value.fromUnsignedBigInt(finalizedAt), - ), - ) - - return depositFinalizedEvent -} - -export function createDepositInitializedEvent( - depositKey: BigInt, - initializedAt: BigInt, -): DepositInitialized { - const depositInitializedEvent = changetype(newMockEvent()) - - depositInitializedEvent.parameters = [] - - depositInitializedEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - depositInitializedEvent.parameters.push( - new ethereum.EventParam( - "initializedAt", - ethereum.Value.fromUnsignedBigInt(initializedAt), - ), - ) - - return depositInitializedEvent -} - -export function createDepositorFeeDivisorUpdatedEvent( - depositorFeeDivisor: BigInt, -): DepositorFeeDivisorUpdated { - const depositorFeeDivisorUpdatedEvent = - changetype(newMockEvent()) - - depositorFeeDivisorUpdatedEvent.parameters = [] - - depositorFeeDivisorUpdatedEvent.parameters.push( - new ethereum.EventParam( - "depositorFeeDivisor", - ethereum.Value.fromUnsignedBigInt(depositorFeeDivisor), - ), - ) - - return depositorFeeDivisorUpdatedEvent -} - -export function createOwnershipTransferStartedEvent( - previousOwner: Address, - newOwner: Address, -): OwnershipTransferStarted { - const ownershipTransferStartedEvent = - changetype(newMockEvent()) - - ownershipTransferStartedEvent.parameters = [] - - ownershipTransferStartedEvent.parameters.push( - new ethereum.EventParam( - "previousOwner", - ethereum.Value.fromAddress(previousOwner), - ), - ) - ownershipTransferStartedEvent.parameters.push( - new ethereum.EventParam("newOwner", ethereum.Value.fromAddress(newOwner)), - ) - - return ownershipTransferStartedEvent -} - -export function createOwnershipTransferredEvent( - previousOwner: Address, - newOwner: Address, -): OwnershipTransferred { - const ownershipTransferredEvent = - changetype(newMockEvent()) - - ownershipTransferredEvent.parameters = [] - - ownershipTransferredEvent.parameters.push( - new ethereum.EventParam( - "previousOwner", - ethereum.Value.fromAddress(previousOwner), - ), - ) - ownershipTransferredEvent.parameters.push( - new ethereum.EventParam("newOwner", ethereum.Value.fromAddress(newOwner)), - ) - - return ownershipTransferredEvent -} - -export function createStakeRequestCancelledFromQueueEvent( - depositKey: BigInt, - staker: Address, - amountToStake: BigInt, -): StakeRequestCancelledFromQueue { - const stakeRequestCancelledFromQueueEvent = - changetype(newMockEvent()) - - stakeRequestCancelledFromQueueEvent.parameters = [] - - stakeRequestCancelledFromQueueEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - stakeRequestCancelledFromQueueEvent.parameters.push( - new ethereum.EventParam("staker", ethereum.Value.fromAddress(staker)), - ) - stakeRequestCancelledFromQueueEvent.parameters.push( - new ethereum.EventParam( - "amountToStake", - ethereum.Value.fromUnsignedBigInt(amountToStake), - ), - ) - - return stakeRequestCancelledFromQueueEvent -} - -export function createStakeRequestFinalizedEvent( - depositKey: BigInt, - caller: Address, - stakedAmount: BigInt, -): StakeRequestFinalized { - const stakeRequestFinalizedEvent = - changetype(newMockEvent()) - - stakeRequestFinalizedEvent.parameters = [] - - stakeRequestFinalizedEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - stakeRequestFinalizedEvent.parameters.push( - new ethereum.EventParam("caller", ethereum.Value.fromAddress(caller)), - ) - stakeRequestFinalizedEvent.parameters.push( - new ethereum.EventParam( - "stakedAmount", - ethereum.Value.fromUnsignedBigInt(stakedAmount), - ), - ) - - return stakeRequestFinalizedEvent -} - -export function createStakeRequestFinalizedFromQueueEvent( - depositKey: BigInt, - caller: Address, - stakedAmount: BigInt, -): StakeRequestFinalizedFromQueue { - const stakeRequestFinalizedFromQueueEvent = - changetype(newMockEvent()) - - stakeRequestFinalizedFromQueueEvent.parameters = [] - - stakeRequestFinalizedFromQueueEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - stakeRequestFinalizedFromQueueEvent.parameters.push( - new ethereum.EventParam("caller", ethereum.Value.fromAddress(caller)), - ) - stakeRequestFinalizedFromQueueEvent.parameters.push( - new ethereum.EventParam( - "stakedAmount", - ethereum.Value.fromUnsignedBigInt(stakedAmount), - ), - ) - - return stakeRequestFinalizedFromQueueEvent -} +import { newMockEvent } from "matchstick-as/assembly/defaults" +import { StakeRequestInitialized } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" +// eslint-disable-next-line import/prefer-default-export export function createStakeRequestInitializedEvent( depositKey: BigInt, caller: Address, staker: Address, + initialAmount: BigInt, ): StakeRequestInitialized { const stakeRequestInitializedEvent = changetype(newMockEvent()) stakeRequestInitializedEvent.parameters = [] - stakeRequestInitializedEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - stakeRequestInitializedEvent.parameters.push( - new ethereum.EventParam("caller", ethereum.Value.fromAddress(caller)), + const depositKeyParam = new ethereum.EventParam( + "depositKey", + ethereum.Value.fromUnsignedBigInt(depositKey), ) - stakeRequestInitializedEvent.parameters.push( - new ethereum.EventParam("staker", ethereum.Value.fromAddress(staker)), + const callerParam = new ethereum.EventParam( + "caller", + ethereum.Value.fromAddress(caller), ) - return stakeRequestInitializedEvent -} - -export function createStakeRequestQueuedEvent( - depositKey: BigInt, - caller: Address, - queuedAmount: BigInt, -): StakeRequestQueued { - const stakeRequestQueuedEvent = changetype(newMockEvent()) - - stakeRequestQueuedEvent.parameters = [] - - stakeRequestQueuedEvent.parameters.push( - new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ), - ) - stakeRequestQueuedEvent.parameters.push( - new ethereum.EventParam("caller", ethereum.Value.fromAddress(caller)), + const stakerParam = new ethereum.EventParam( + "staker", + ethereum.Value.fromAddress(staker), ) - stakeRequestQueuedEvent.parameters.push( - new ethereum.EventParam( - "queuedAmount", - ethereum.Value.fromUnsignedBigInt(queuedAmount), - ), + + const initialAmountParam = new ethereum.EventParam( + "initialAmount", + ethereum.Value.fromUnsignedBigInt(initialAmount), ) - return stakeRequestQueuedEvent + stakeRequestInitializedEvent.parameters.push(depositKeyParam) + stakeRequestInitializedEvent.parameters.push(callerParam) + stakeRequestInitializedEvent.parameters.push(stakerParam) + stakeRequestInitializedEvent.parameters.push(initialAmountParam) + + return stakeRequestInitializedEvent } diff --git a/subgraph/tests/acre-bitcoin-depositor.test.ts b/subgraph/tests/acre-bitcoin-depositor.test.ts index 9f036d495..9476ac9b1 100644 --- a/subgraph/tests/acre-bitcoin-depositor.test.ts +++ b/subgraph/tests/acre-bitcoin-depositor.test.ts @@ -1,80 +1,179 @@ +// acre-bitcoin-depositor.test.ts + import { assert, describe, test, clearStore, - beforeAll, - afterAll, -} from "matchstick-as" + afterEach, +} from "matchstick-as/assembly/index" import { BigInt, Address } from "@graphprotocol/graph-ts" -import { handleBridgingCompleted } from "../src/acre-bitcoin-depositor" -import { createBridgingCompletedEvent } from "./acre-bitcoin-depositor-utils" +import { createStakeRequestInitializedEvent } from "./acre-bitcoin-depositor-utils" +import { handleStakeRequestInitialized } from "../src/acre-bitcoin-depositor" -// Tests structure (matchstick-as >=0.5.0) -// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 +describe("createStakeRequestInitialized event", () => { + afterEach(() => { + clearStore() + }) + + test("StakeRequestInitialized entity does not exist in the store", () => { + assert.notInStore("StakeRequestInitialized", "") + }) + + test("Staker entity does not exist in the store", () => { + assert.notInStore("Stake", "") + }) + + test("LogData entity does not exist in the store", () => { + assert.notInStore("LogData", "") + }) -describe("Describe entity assertions", () => { - beforeAll(() => { + test("should create StakeRequestInitialized entity", () => { const depositKey = BigInt.fromI32(234) const caller = Address.fromString( "0x0000000000000000000000000000000000000001", ) - const referral = 123 - const bridgedAmount = BigInt.fromI32(234) - const depositorFee = BigInt.fromI32(234) - const newBridgingCompletedEvent = createBridgingCompletedEvent( + const staker = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const initialAmount = BigInt.fromI32(234) + + const event = createStakeRequestInitializedEvent( depositKey, caller, - referral, - bridgedAmount, - depositorFee, + staker, + initialAmount, ) - handleBridgingCompleted(newBridgingCompletedEvent) - }) + handleStakeRequestInitialized(event) - afterAll(() => { - clearStore() + assert.entityCount("StakeRequestInitialized", 1) }) - // For more test scenarios, see: - // https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test + test("StakeRequestInitialized entity has proper fields", () => { + const depositKey = BigInt.fromI32(234) + const caller = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const staker = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const initialAmount = BigInt.fromI32(10000) + + const event = createStakeRequestInitializedEvent( + depositKey, + caller, + staker, + initialAmount, + ) + + handleStakeRequestInitialized(event) - test("BridgingCompleted created and stored", () => { - assert.entityCount("BridgingCompleted", 1) + const txId = event.transaction.hash.toHexString() - // 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function assert.fieldEquals( - "BridgingCompleted", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", + "StakeRequestInitialized", + txId, "depositKey", - "234", + depositKey.toString(), + ) + + assert.fieldEquals( + "StakeRequestInitialized", + txId, + "staker", + staker.toHexString(), ) + assert.fieldEquals( - "BridgingCompleted", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", + "StakeRequestInitialized", + txId, "caller", + caller.toHexString(), + ) + }) + + test("should create Staker entity", () => { + const depositKey = BigInt.fromI32(234) + const caller = Address.fromString( "0x0000000000000000000000000000000000000001", ) - assert.fieldEquals( - "BridgingCompleted", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", - "referral", - "123", + const staker = Address.fromString( + "0x0000000000000000000000000000000000000001", ) + const initialAmount = BigInt.fromI32(234) + + const event = createStakeRequestInitializedEvent( + depositKey, + caller, + staker, + initialAmount, + ) + handleStakeRequestInitialized(event) + + assert.entityCount("Staker", 1) + }) + + test("should create LogData entities", () => { + const depositKey = BigInt.fromI32(234) + const caller = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const staker = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const initialAmount = BigInt.fromI32(234) + + const event = createStakeRequestInitializedEvent( + depositKey, + caller, + staker, + initialAmount, + ) + handleStakeRequestInitialized(event) + + assert.entityCount("LogData", 2) + }) + + test("LogData entity has proper fields", () => { + const depositKey = BigInt.fromI32(234) + const caller = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const staker = Address.fromString( + "0x0000000000000000000000000000000000000001", + ) + const initialAmount = BigInt.fromI32(10000) + + const event = createStakeRequestInitializedEvent( + depositKey, + caller, + staker, + initialAmount, + ) + + handleStakeRequestInitialized(event) + + const txBtcId = `${event.transaction.hash.toHexString()}btc` + const txEthId = `${event.transaction.hash.toHexString()}eth` + assert.fieldEquals( - "BridgingCompleted", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", - "bridgedAmount", - "234", + "LogData", + txBtcId, + "timestamp", + event.block.timestamp.toString(), ) + assert.fieldEquals( - "BridgingCompleted", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a01000000", - "depositorFee", - "234", + "LogData", + txEthId, + "timestamp", + event.block.timestamp.toString(), ) - // More assert options: - // https://thegraph.com/docs/en/developer/matchstick/#asserts + assert.fieldEquals("LogData", txBtcId, "chain", "Bitcoin") + assert.fieldEquals("LogData", txEthId, "chain", "Ethereum") + + assert.fieldEquals("LogData", txBtcId, "amount", initialAmount.toString()) + assert.fieldEquals("LogData", txEthId, "amount", initialAmount.toString()) }) }) From 742d770ea7ed1965564e186c20c3684e67c0aa26 Mon Sep 17 00:00:00 2001 From: ioay Date: Tue, 16 Apr 2024 23:30:43 +0200 Subject: [PATCH 02/28] Update subgraph specVersion to 1.0.0 --- subgraph/subgraph.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index b6b81f1a3..40a0e9eb1 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -1,4 +1,6 @@ -specVersion: 0.0.5 +specVersion: 1.0.0 +indexerHints: + prune: auto schema: file: ./schema.graphql dataSources: From 7a58df6ce89963ce3bcfacf331592538b4006b2e Mon Sep 17 00:00:00 2001 From: ioay Date: Tue, 16 Apr 2024 23:52:50 +0200 Subject: [PATCH 03/28] Updated logData id param --- subgraph/src/acre-bitcoin-depositor.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts index 61be4d8f3..1f4fddcb8 100644 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ b/subgraph/src/acre-bitcoin-depositor.ts @@ -9,11 +9,8 @@ export function handleStakeRequestInitialized( const entity = new StakeRequestInitialized( event.transaction.hash.toHexString(), ) - const stakeEntity = new Stake(event.transaction.hash.toHexString()) - const stakerEntity = getOrCreateStaker(event.params.staker) - stakerEntity.save() const logDataBtc = getOrCreateLog( `${event.transaction.hash.toHexString()}btc`, @@ -26,13 +23,11 @@ export function handleStakeRequestInitialized( logDataBtc.timestamp = event.block.timestamp logDataBtc.chain = "Bitcoin" logDataBtc.amount = event.params.initialAmount - logDataBtc.save() logDataEth.activity = stakeEntity.id logDataEth.timestamp = event.block.timestamp logDataEth.chain = "Ethereum" logDataEth.amount = event.params.initialAmount - logDataEth.save() entity.depositKey = event.params.depositKey entity.caller = event.params.caller @@ -42,5 +37,8 @@ export function handleStakeRequestInitialized( entity.blockTimestamp = event.block.timestamp entity.transactionHash = event.transaction.hash + stakerEntity.save() + logDataBtc.save() + logDataEth.save() entity.save() } From c779aabb637576d335c43997f38805bfde5a1607 Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 17 Apr 2024 11:32:26 +0200 Subject: [PATCH 04/28] Removed StakeRequestInitialized entity --- subgraph/schema.graphql | 10 ---------- subgraph/src/acre-bitcoin-depositor.ts | 16 ++-------------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index b96178d80..b2c40c781 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -17,16 +17,6 @@ interface ActivityData { logs: [LogData!] } -type StakeRequestInitialized @entity { - id: ID! - depositKey: BigInt! # uint256 - caller: Bytes! # address - staker: Bytes! # address - blockNumber: BigInt! - blockTimestamp: BigInt! - transactionHash: Bytes! -} - type Staker @entity { # Id is the ethereum address of the account. id: ID! diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts index 1f4fddcb8..53aff5030 100644 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ b/subgraph/src/acre-bitcoin-depositor.ts @@ -1,16 +1,13 @@ import { StakeRequestInitialized as StakeRequestInitializedEvent } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" -import { Stake, StakeRequestInitialized } from "../generated/schema" +import { Stake } from "../generated/schema" import { getOrCreateStaker, getOrCreateLog } from "./utils" // eslint-disable-next-line import/prefer-default-export export function handleStakeRequestInitialized( event: StakeRequestInitializedEvent, ): void { - const entity = new StakeRequestInitialized( - event.transaction.hash.toHexString(), - ) - const stakeEntity = new Stake(event.transaction.hash.toHexString()) const stakerEntity = getOrCreateStaker(event.params.staker) + const stakeEntity = new Stake(event.transaction.hash.toHexString()) const logDataBtc = getOrCreateLog( `${event.transaction.hash.toHexString()}btc`, @@ -29,16 +26,7 @@ export function handleStakeRequestInitialized( logDataEth.chain = "Ethereum" logDataEth.amount = event.params.initialAmount - entity.depositKey = event.params.depositKey - entity.caller = event.params.caller - entity.staker = event.params.staker - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - stakerEntity.save() logDataBtc.save() logDataEth.save() - entity.save() } From 175c0ae81a8e52d6f775821d711d6e74da648390 Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 17 Apr 2024 11:38:32 +0200 Subject: [PATCH 05/28] Added comment to timestamp prop --- subgraph/src/acre-bitcoin-depositor.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts index 53aff5030..0cc6d8df0 100644 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ b/subgraph/src/acre-bitcoin-depositor.ts @@ -17,6 +17,11 @@ export function handleStakeRequestInitialized( ) logDataBtc.activity = stakeEntity.id + + // This timestamp may be different than the actual time + // when the BTC transaction took place: + // It indicates when Ethereum received event about this BTC deposit, + // not when the BTC transaction happened. logDataBtc.timestamp = event.block.timestamp logDataBtc.chain = "Bitcoin" logDataBtc.amount = event.params.initialAmount From fb4daa7bb57eedb28ad78307d914afc22a6c8085 Mon Sep 17 00:00:00 2001 From: ioay Date: Thu, 18 Apr 2024 10:10:00 +0200 Subject: [PATCH 06/28] Unit tests updated, schema adjustments --- subgraph/schema.graphql | 12 +- subgraph/src/acre-bitcoin-depositor.ts | 6 +- subgraph/src/utils.ts | 13 +- subgraph/tests/acre-bitcoin-depositor.test.ts | 143 ++---------------- 4 files changed, 36 insertions(+), 138 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index b2c40c781..63df972c4 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -11,9 +11,9 @@ enum LogType { CancelledFromQueue } -interface ActivityData { +interface ActivityData @key(fields: "id") { id: ID! - staker: Staker + staker: Staker! logs: [LogData!] } @@ -23,18 +23,18 @@ type Staker @entity { activities: [ActivityData!] @derivedFrom(field: "staker") } -type Stake implements ActivityData @entity { +type Stake implements ActivityData @entity{ id: ID! - staker: Staker + staker: Staker! logs: [LogData!] @derivedFrom(field: "activity") initialDepositAmountSatoshi: BigInt! amountToStakeStBtc: BigInt! shareStBtc: BigInt! } -type Unstake implements ActivityData @entity { +type Unstake implements ActivityData @entity{ id: ID! - staker: Staker + staker: Staker! logs: [LogData!] @derivedFrom(field: "activity") initialDepositAmountSatoshi: BigInt! amountToStakeStBtc: BigInt! diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts index 0cc6d8df0..bcfe97ae3 100644 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ b/subgraph/src/acre-bitcoin-depositor.ts @@ -1,13 +1,12 @@ import { StakeRequestInitialized as StakeRequestInitializedEvent } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" -import { Stake } from "../generated/schema" -import { getOrCreateStaker, getOrCreateLog } from "./utils" +import { getOrCreateStaker, getOrCreateStake, getOrCreateLog } from "./utils" // eslint-disable-next-line import/prefer-default-export export function handleStakeRequestInitialized( event: StakeRequestInitializedEvent, ): void { const stakerEntity = getOrCreateStaker(event.params.staker) - const stakeEntity = new Stake(event.transaction.hash.toHexString()) + const stakeEntity = getOrCreateStake(event.transaction.hash.toHexString()) const logDataBtc = getOrCreateLog( `${event.transaction.hash.toHexString()}btc`, @@ -32,6 +31,7 @@ export function handleStakeRequestInitialized( logDataEth.amount = event.params.initialAmount stakerEntity.save() + // stakeEntity.save() logDataBtc.save() logDataEth.save() } diff --git a/subgraph/src/utils.ts b/subgraph/src/utils.ts index fe77a3cae..c2440e666 100644 --- a/subgraph/src/utils.ts +++ b/subgraph/src/utils.ts @@ -1,5 +1,5 @@ import { Address } from "@graphprotocol/graph-ts" -import { Staker, LogData } from "../generated/schema" +import { Staker, LogData, Stake } from "../generated/schema" export function getOrCreateStaker(stakerId: Address): Staker { const stakerHexString = stakerId.toHexString() @@ -12,6 +12,17 @@ export function getOrCreateStaker(stakerId: Address): Staker { return staker } +export function getOrCreateStake(transactionId: string): Stake { + // const stakeHexString = transactionHash.toHexString() + let stake = Stake.load(transactionId) + + if (!stake) { + stake = new Stake(transactionId) + } + + return stake +} + export function getOrCreateLog(logId: string): LogData { let log = LogData.load(logId) diff --git a/subgraph/tests/acre-bitcoin-depositor.test.ts b/subgraph/tests/acre-bitcoin-depositor.test.ts index 9476ac9b1..9b3938d4b 100644 --- a/subgraph/tests/acre-bitcoin-depositor.test.ts +++ b/subgraph/tests/acre-bitcoin-depositor.test.ts @@ -1,158 +1,45 @@ -// acre-bitcoin-depositor.test.ts - import { assert, describe, test, clearStore, afterEach, + beforeEach, } from "matchstick-as/assembly/index" import { BigInt, Address } from "@graphprotocol/graph-ts" import { createStakeRequestInitializedEvent } from "./acre-bitcoin-depositor-utils" import { handleStakeRequestInitialized } from "../src/acre-bitcoin-depositor" -describe("createStakeRequestInitialized event", () => { - afterEach(() => { - clearStore() - }) - - test("StakeRequestInitialized entity does not exist in the store", () => { - assert.notInStore("StakeRequestInitialized", "") - }) - - test("Staker entity does not exist in the store", () => { - assert.notInStore("Stake", "") - }) +const depositKey = BigInt.fromI32(234) +const caller = Address.fromString("0x0000000000000000000000000000000000000001") +const staker = Address.fromString("0x0000000000000000000000000000000000000001") +const initialAmount = BigInt.fromI32(234) - test("LogData entity does not exist in the store", () => { - assert.notInStore("LogData", "") - }) +const event = createStakeRequestInitializedEvent( + depositKey, + caller, + staker, + initialAmount, +) - test("should create StakeRequestInitialized entity", () => { - const depositKey = BigInt.fromI32(234) - const caller = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const staker = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const initialAmount = BigInt.fromI32(234) - - const event = createStakeRequestInitializedEvent( - depositKey, - caller, - staker, - initialAmount, - ) +describe("createStakeRequestInitialized event", () => { + beforeEach(() => { handleStakeRequestInitialized(event) - - assert.entityCount("StakeRequestInitialized", 1) }) - test("StakeRequestInitialized entity has proper fields", () => { - const depositKey = BigInt.fromI32(234) - const caller = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const staker = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const initialAmount = BigInt.fromI32(10000) - - const event = createStakeRequestInitializedEvent( - depositKey, - caller, - staker, - initialAmount, - ) - - handleStakeRequestInitialized(event) - - const txId = event.transaction.hash.toHexString() - - assert.fieldEquals( - "StakeRequestInitialized", - txId, - "depositKey", - depositKey.toString(), - ) - - assert.fieldEquals( - "StakeRequestInitialized", - txId, - "staker", - staker.toHexString(), - ) - - assert.fieldEquals( - "StakeRequestInitialized", - txId, - "caller", - caller.toHexString(), - ) + afterEach(() => { + clearStore() }) test("should create Staker entity", () => { - const depositKey = BigInt.fromI32(234) - const caller = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const staker = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const initialAmount = BigInt.fromI32(234) - - const event = createStakeRequestInitializedEvent( - depositKey, - caller, - staker, - initialAmount, - ) - handleStakeRequestInitialized(event) - assert.entityCount("Staker", 1) }) test("should create LogData entities", () => { - const depositKey = BigInt.fromI32(234) - const caller = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const staker = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const initialAmount = BigInt.fromI32(234) - - const event = createStakeRequestInitializedEvent( - depositKey, - caller, - staker, - initialAmount, - ) - handleStakeRequestInitialized(event) - assert.entityCount("LogData", 2) }) test("LogData entity has proper fields", () => { - const depositKey = BigInt.fromI32(234) - const caller = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const staker = Address.fromString( - "0x0000000000000000000000000000000000000001", - ) - const initialAmount = BigInt.fromI32(10000) - - const event = createStakeRequestInitializedEvent( - depositKey, - caller, - staker, - initialAmount, - ) - - handleStakeRequestInitialized(event) - const txBtcId = `${event.transaction.hash.toHexString()}btc` const txEthId = `${event.transaction.hash.toHexString()}eth` From e5be694b0645fec75a0c75cb55eae0ecc132ac3a Mon Sep 17 00:00:00 2001 From: ioay Date: Thu, 18 Apr 2024 11:53:48 +0200 Subject: [PATCH 07/28] Update reflects the latest contract to Sepolia: Staker -> DepositPwner --- subgraph/abis/AcreBitcoinDepositor.json | 4 +- subgraph/schema.graphql | 20 +++---- subgraph/src/acre-bitcoin-depositor.ts | 21 +++++--- subgraph/src/utils.ts | 14 ++--- subgraph/subgraph.yaml | 13 +++-- .../tests/acre-bitcoin-depositor-utils.ts | 29 +++++------ subgraph/tests/acre-bitcoin-depositor.test.ts | 52 ++++++++++++++++--- 7 files changed, 98 insertions(+), 55 deletions(-) diff --git a/subgraph/abis/AcreBitcoinDepositor.json b/subgraph/abis/AcreBitcoinDepositor.json index df4025ed4..41a640c8f 100644 --- a/subgraph/abis/AcreBitcoinDepositor.json +++ b/subgraph/abis/AcreBitcoinDepositor.json @@ -17,7 +17,7 @@ { "indexed": true, "internalType": "address", - "name": "staker", + "name": "depositOwner", "type": "address" }, { @@ -27,7 +27,7 @@ "type": "uint256" } ], - "name": "StakeRequestInitialized", + "name": "DepositInitialized", "type": "event" } ] diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 63df972c4..a2395d769 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -13,36 +13,36 @@ enum LogType { interface ActivityData @key(fields: "id") { id: ID! - staker: Staker! + depositOwner: DepositOwner! logs: [LogData!] } -type Staker @entity { +type DepositOwner @entity { # Id is the ethereum address of the account. id: ID! - activities: [ActivityData!] @derivedFrom(field: "staker") + activities: [ActivityData!] @derivedFrom(field: "depositOwner") } type Stake implements ActivityData @entity{ id: ID! - staker: Staker! + depositOwner: DepositOwner! logs: [LogData!] @derivedFrom(field: "activity") initialDepositAmountSatoshi: BigInt! - amountToStakeStBtc: BigInt! - shareStBtc: BigInt! + amountToStakeStBtc: BigInt + shareStBtc: BigInt } type Unstake implements ActivityData @entity{ id: ID! - staker: Staker! + depositOwner: DepositOwner! logs: [LogData!] @derivedFrom(field: "activity") initialDepositAmountSatoshi: BigInt! - amountToStakeStBtc: BigInt! - shareStBtc: BigInt! + amountToStakeStBtc: BigInt + shareStBtc: BigInt } type LogData @entity { - # Id is the transaction hash + # Id is the transaction hash. id: ID! timestamp: BigInt! activity: ActivityData diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts index bcfe97ae3..f3140e5d9 100644 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ b/subgraph/src/acre-bitcoin-depositor.ts @@ -1,13 +1,18 @@ -import { StakeRequestInitialized as StakeRequestInitializedEvent } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" -import { getOrCreateStaker, getOrCreateStake, getOrCreateLog } from "./utils" +import { DepositInitialized as DepositInitializedEvent } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" +import { + getOrCreateDepositOwner, + getOrCreateStake, + getOrCreateLog, +} from "./utils" // eslint-disable-next-line import/prefer-default-export -export function handleStakeRequestInitialized( - event: StakeRequestInitializedEvent, -): void { - const stakerEntity = getOrCreateStaker(event.params.staker) +export function handleDepositInitialized(event: DepositInitializedEvent): void { + const depositOwnerEntity = getOrCreateDepositOwner(event.params.depositOwner) const stakeEntity = getOrCreateStake(event.transaction.hash.toHexString()) + stakeEntity.depositOwner = depositOwnerEntity.id + stakeEntity.initialDepositAmountSatoshi = event.params.initialAmount + const logDataBtc = getOrCreateLog( `${event.transaction.hash.toHexString()}btc`, ) @@ -30,8 +35,8 @@ export function handleStakeRequestInitialized( logDataEth.chain = "Ethereum" logDataEth.amount = event.params.initialAmount - stakerEntity.save() - // stakeEntity.save() + depositOwnerEntity.save() + stakeEntity.save() logDataBtc.save() logDataEth.save() } diff --git a/subgraph/src/utils.ts b/subgraph/src/utils.ts index c2440e666..299e93b0b 100644 --- a/subgraph/src/utils.ts +++ b/subgraph/src/utils.ts @@ -1,15 +1,15 @@ import { Address } from "@graphprotocol/graph-ts" -import { Staker, LogData, Stake } from "../generated/schema" +import { DepositOwner, LogData, Stake } from "../generated/schema" -export function getOrCreateStaker(stakerId: Address): Staker { - const stakerHexString = stakerId.toHexString() - let staker = Staker.load(stakerHexString) +export function getOrCreateDepositOwner(depositOwnerId: Address): DepositOwner { + const depositOwnerHexString = depositOwnerId.toHexString() + let depositOwner = DepositOwner.load(depositOwnerHexString) - if (!staker) { - staker = new Staker(stakerHexString) + if (!depositOwner) { + depositOwner = new DepositOwner(depositOwnerHexString) } - return staker + return depositOwner } export function getOrCreateStake(transactionId: string): Stake { diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 40a0e9eb1..1bf2b1c05 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -8,20 +8,23 @@ dataSources: name: AcreBitcoinDepositor network: sepolia source: - address: "0x37E34EbC743FFAf96b56b3f62854bb7E733a4B50" + address: "0x2F86FE8C5683372Db667E6f6d88dcB6d55a81286" abi: AcreBitcoinDepositor - startBlock: 5394071 + startBlock: 5675744 mapping: kind: ethereum/events apiVersion: 0.0.7 language: wasm/assemblyscript entities: - - StakeRequestInitialized + - DepositOwner + - Stake + - Unstake + - LogData abis: - name: AcreBitcoinDepositor file: ./abis/AcreBitcoinDepositor.json eventHandlers: - - event: StakeRequestInitialized(indexed uint256,indexed address,indexed address,uint256) - handler: handleStakeRequestInitialized + - event: DepositInitialized(indexed uint256,indexed address,indexed address,uint256) + handler: handleDepositInitialized receipt: true file: ./src/acre-bitcoin-depositor.ts diff --git a/subgraph/tests/acre-bitcoin-depositor-utils.ts b/subgraph/tests/acre-bitcoin-depositor-utils.ts index b0b027998..7143e8c95 100644 --- a/subgraph/tests/acre-bitcoin-depositor-utils.ts +++ b/subgraph/tests/acre-bitcoin-depositor-utils.ts @@ -1,18 +1,17 @@ import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts" import { newMockEvent } from "matchstick-as/assembly/defaults" -import { StakeRequestInitialized } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" +import { DepositInitialized } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" // eslint-disable-next-line import/prefer-default-export -export function createStakeRequestInitializedEvent( +export function createDepositInitializedEvent( depositKey: BigInt, caller: Address, - staker: Address, + depositOwner: Address, initialAmount: BigInt, -): StakeRequestInitialized { - const stakeRequestInitializedEvent = - changetype(newMockEvent()) +): DepositInitialized { + const depositInitializedEvent = changetype(newMockEvent()) - stakeRequestInitializedEvent.parameters = [] + depositInitializedEvent.parameters = [] const depositKeyParam = new ethereum.EventParam( "depositKey", @@ -23,9 +22,9 @@ export function createStakeRequestInitializedEvent( ethereum.Value.fromAddress(caller), ) - const stakerParam = new ethereum.EventParam( - "staker", - ethereum.Value.fromAddress(staker), + const depositOwnerParam = new ethereum.EventParam( + "depositOwner", + ethereum.Value.fromAddress(depositOwner), ) const initialAmountParam = new ethereum.EventParam( @@ -33,10 +32,10 @@ export function createStakeRequestInitializedEvent( ethereum.Value.fromUnsignedBigInt(initialAmount), ) - stakeRequestInitializedEvent.parameters.push(depositKeyParam) - stakeRequestInitializedEvent.parameters.push(callerParam) - stakeRequestInitializedEvent.parameters.push(stakerParam) - stakeRequestInitializedEvent.parameters.push(initialAmountParam) + depositInitializedEvent.parameters.push(depositKeyParam) + depositInitializedEvent.parameters.push(callerParam) + depositInitializedEvent.parameters.push(depositOwnerParam) + depositInitializedEvent.parameters.push(initialAmountParam) - return stakeRequestInitializedEvent + return depositInitializedEvent } diff --git a/subgraph/tests/acre-bitcoin-depositor.test.ts b/subgraph/tests/acre-bitcoin-depositor.test.ts index 9b3938d4b..4f1248ea1 100644 --- a/subgraph/tests/acre-bitcoin-depositor.test.ts +++ b/subgraph/tests/acre-bitcoin-depositor.test.ts @@ -7,42 +7,78 @@ import { beforeEach, } from "matchstick-as/assembly/index" import { BigInt, Address } from "@graphprotocol/graph-ts" -import { createStakeRequestInitializedEvent } from "./acre-bitcoin-depositor-utils" -import { handleStakeRequestInitialized } from "../src/acre-bitcoin-depositor" +import { createDepositInitializedEvent } from "./acre-bitcoin-depositor-utils" +import { handleDepositInitialized } from "../src/acre-bitcoin-depositor" const depositKey = BigInt.fromI32(234) const caller = Address.fromString("0x0000000000000000000000000000000000000001") -const staker = Address.fromString("0x0000000000000000000000000000000000000001") +const depositOwner = Address.fromString( + "0x0000000000000000000000000000000000000001", +) const initialAmount = BigInt.fromI32(234) -const event = createStakeRequestInitializedEvent( +const event = createDepositInitializedEvent( depositKey, caller, - staker, + depositOwner, initialAmount, ) describe("createStakeRequestInitialized event", () => { beforeEach(() => { - handleStakeRequestInitialized(event) + handleDepositInitialized(event) }) afterEach(() => { clearStore() }) - test("should create Staker entity", () => { - assert.entityCount("Staker", 1) + test("should create DepositOwner entity", () => { + assert.entityCount("DepositOwner", 1) + }) + + test("should create Stake entity", () => { + assert.entityCount("Stake", 1) }) test("should create LogData entities", () => { assert.entityCount("LogData", 2) }) + test("Stake entity has proper fields", () => { + assert.fieldEquals( + "Stake", + event.transaction.hash.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Stake", + event.transaction.hash.toHexString(), + "initialDepositAmountSatoshi", + event.params.initialAmount.toString(), + ) + }) + test("LogData entity has proper fields", () => { const txBtcId = `${event.transaction.hash.toHexString()}btc` const txEthId = `${event.transaction.hash.toHexString()}eth` + assert.fieldEquals( + "LogData", + txBtcId, + "activity", + event.transaction.hash.toHexString(), + ) + + assert.fieldEquals( + "LogData", + txEthId, + "activity", + event.transaction.hash.toHexString(), + ) + assert.fieldEquals( "LogData", txBtcId, From 7c3399966bda9f05a92cb3f712f1576b433b2773 Mon Sep 17 00:00:00 2001 From: ioay Date: Sun, 21 Apr 2024 23:31:10 +0200 Subject: [PATCH 08/28] Added handleDepositFinalized event, renamed acre-bitcoin depositor to bitcoin-depositor, added deploy information to readme.md --- subgraph/.prettierrc.js | 2 +- subgraph/README.md | 30 ++- subgraph/abis/AcreBitcoinDepositor.json | 33 --- subgraph/abis/BitcoinDepositor.json | 82 +++++++ subgraph/networks.json | 2 +- subgraph/schema.graphql | 12 +- subgraph/src/acre-bitcoin-depositor.ts | 42 ---- subgraph/src/bitcoin-depositor.ts | 85 ++++++++ subgraph/src/utils.ts | 13 +- subgraph/subgraph.yaml | 16 +- .../tests/acre-bitcoin-depositor-utils.ts | 41 ---- subgraph/tests/acre-bitcoin-depositor.test.ts | 102 --------- subgraph/tests/bitcoin-depositor-utils.ts | 101 +++++++++ subgraph/tests/bitcoin-depositor.test.ts | 205 ++++++++++++++++++ 14 files changed, 524 insertions(+), 242 deletions(-) delete mode 100644 subgraph/abis/AcreBitcoinDepositor.json create mode 100644 subgraph/abis/BitcoinDepositor.json delete mode 100644 subgraph/src/acre-bitcoin-depositor.ts create mode 100644 subgraph/src/bitcoin-depositor.ts delete mode 100644 subgraph/tests/acre-bitcoin-depositor-utils.ts delete mode 100644 subgraph/tests/acre-bitcoin-depositor.test.ts create mode 100644 subgraph/tests/bitcoin-depositor-utils.ts create mode 100644 subgraph/tests/bitcoin-depositor.test.ts diff --git a/subgraph/.prettierrc.js b/subgraph/.prettierrc.js index 15dafbe4b..6d44c572e 100644 --- a/subgraph/.prettierrc.js +++ b/subgraph/.prettierrc.js @@ -1,3 +1,3 @@ module.exports = { - ...require("../.prettierrc.js"), + ...require("../.prettierrc.js"), } diff --git a/subgraph/README.md b/subgraph/README.md index bf6e72f27..09a2ce5ed 100644 --- a/subgraph/README.md +++ b/subgraph/README.md @@ -38,7 +38,8 @@ EVM-compatible JSON-RPC API. You can use Thesis private RPC from Alchemy or create a private one [here](https://www.alchemy.com/overviews/private-rpc-endpoint). -1. Install Docker on your local machine: +1. Install Docker on your local machine: + - Mac: https://docs.docker.com/desktop/install/mac-install/ - Windows: https://docs.docker.com/desktop/install/windows-install/ - Linux: https://docs.docker.com/desktop/install/linux-install/ @@ -74,3 +75,30 @@ Note: use it only if your subgraph is not created in the local Graph node. ``` http://localhost:8000/subgraphs/name/acre-subgraph ``` + +### Deploy the subgraph to Subgraph Studio + +1. Once your subgraph has been created in Subgraph Studio you can initialize the subgraph code using this command: + + ``` + graph init --studio + ``` + + The value can be found on your subgraph details page in Subgraph Studio + (https://thegraph.com/docs/en/deploying/deploying-a-subgraph-to-studio/#create-your-subgraph-in-subgraph-studio) + +2. Before being able to deploy your subgraph to Subgraph Studio, you need to login into your account within the CLI. + + ``` + graph auth --studio + ``` + + The can be found on your "My Subgraphs" page or your subgraph details page. + +3. Deploying a Subgraph to Subgraph Studio + + ``` + graph deploy --studio + ``` + + After running this command, the CLI will ask for a version label, you can name it however you want, you can use labels such as 0.1 and 0.2 or use letters as well such as uniswap-v2-0.1. diff --git a/subgraph/abis/AcreBitcoinDepositor.json b/subgraph/abis/AcreBitcoinDepositor.json deleted file mode 100644 index 41a640c8f..000000000 --- a/subgraph/abis/AcreBitcoinDepositor.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "depositKey", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "depositOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialAmount", - "type": "uint256" - } - ], - "name": "DepositInitialized", - "type": "event" - } -] diff --git a/subgraph/abis/BitcoinDepositor.json b/subgraph/abis/BitcoinDepositor.json new file mode 100644 index 000000000..3c4462015 --- /dev/null +++ b/subgraph/abis/BitcoinDepositor.json @@ -0,0 +1,82 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "depositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint16", + "name": "referral", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "bridgedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "depositorFee", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "depositOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialAmount", + "type": "uint256" + } + ], + "name": "DepositInitialized", + "type": "event" + } +] diff --git a/subgraph/networks.json b/subgraph/networks.json index 04789726a..3f3a9403c 100644 --- a/subgraph/networks.json +++ b/subgraph/networks.json @@ -1,6 +1,6 @@ { "sepolia": { - "AcreBitcoinDepositor": { + "BitcoinDepositor": { "address": "0x37E34EbC743FFAf96b56b3f62854bb7E733a4B50", "startBlock": 5394071 } diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index a2395d769..ee6e77851 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -4,11 +4,9 @@ enum ChainType { } enum LogType { + Unknown Initialized Finalized - Queued - FinalizedFromQueue - CancelledFromQueue } interface ActivityData @key(fields: "id") { @@ -23,21 +21,21 @@ type DepositOwner @entity { activities: [ActivityData!] @derivedFrom(field: "depositOwner") } -type Stake implements ActivityData @entity{ +type Deposit implements ActivityData @entity { id: ID! depositOwner: DepositOwner! logs: [LogData!] @derivedFrom(field: "activity") initialDepositAmountSatoshi: BigInt! - amountToStakeStBtc: BigInt + amountToDepositStBtc: BigInt shareStBtc: BigInt } -type Unstake implements ActivityData @entity{ +type Withdraw implements ActivityData @entity { id: ID! depositOwner: DepositOwner! logs: [LogData!] @derivedFrom(field: "activity") initialDepositAmountSatoshi: BigInt! - amountToStakeStBtc: BigInt + amountToDepositStBtc: BigInt shareStBtc: BigInt } diff --git a/subgraph/src/acre-bitcoin-depositor.ts b/subgraph/src/acre-bitcoin-depositor.ts deleted file mode 100644 index f3140e5d9..000000000 --- a/subgraph/src/acre-bitcoin-depositor.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { DepositInitialized as DepositInitializedEvent } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" -import { - getOrCreateDepositOwner, - getOrCreateStake, - getOrCreateLog, -} from "./utils" - -// eslint-disable-next-line import/prefer-default-export -export function handleDepositInitialized(event: DepositInitializedEvent): void { - const depositOwnerEntity = getOrCreateDepositOwner(event.params.depositOwner) - const stakeEntity = getOrCreateStake(event.transaction.hash.toHexString()) - - stakeEntity.depositOwner = depositOwnerEntity.id - stakeEntity.initialDepositAmountSatoshi = event.params.initialAmount - - const logDataBtc = getOrCreateLog( - `${event.transaction.hash.toHexString()}btc`, - ) - const logDataEth = getOrCreateLog( - `${event.transaction.hash.toHexString()}eth`, - ) - - logDataBtc.activity = stakeEntity.id - - // This timestamp may be different than the actual time - // when the BTC transaction took place: - // It indicates when Ethereum received event about this BTC deposit, - // not when the BTC transaction happened. - logDataBtc.timestamp = event.block.timestamp - logDataBtc.chain = "Bitcoin" - logDataBtc.amount = event.params.initialAmount - - logDataEth.activity = stakeEntity.id - logDataEth.timestamp = event.block.timestamp - logDataEth.chain = "Ethereum" - logDataEth.amount = event.params.initialAmount - - depositOwnerEntity.save() - stakeEntity.save() - logDataBtc.save() - logDataEth.save() -} diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts new file mode 100644 index 000000000..0616be07a --- /dev/null +++ b/subgraph/src/bitcoin-depositor.ts @@ -0,0 +1,85 @@ +import { + DepositInitialized as DepositInitializedEvent, + DepositFinalized as DepositFinalizedEvent, +} from "../generated/BitcoinDepositor/BitcoinDepositor" +import { + getOrCreateDepositOwner, + getOrCreateDeposit, + getOrCreateLog, +} from "./utils" + +// eslint-disable-next-line import/prefer-default-export +export function handleDepositInitialized(event: DepositInitializedEvent): void { + const depositOwnerEntity = getOrCreateDepositOwner(event.params.depositOwner) + const depositEntity = getOrCreateDeposit( + event.params.depositKey.toHexString(), + ) + + depositEntity.depositOwner = depositOwnerEntity.id + depositEntity.initialDepositAmountSatoshi = event.params.initialAmount + + const logDataBtc = getOrCreateLog( + `${event.transaction.hash.toHexString()}btc`, + ) + const logDataEth = getOrCreateLog( + `${event.transaction.hash.toHexString()}eth`, + ) + + logDataBtc.activity = depositEntity.id + + // This timestamp may be different than the actual time + // when the BTC transaction took place: + // It indicates when Ethereum received event about this BTC deposit, + // not when the BTC transaction happened. + logDataBtc.timestamp = event.block.timestamp + logDataBtc.chain = "Bitcoin" + logDataBtc.amount = event.params.initialAmount + + logDataEth.activity = depositEntity.id + logDataEth.timestamp = event.block.timestamp + logDataEth.chain = "Ethereum" + logDataEth.amount = event.params.initialAmount + + depositOwnerEntity.save() + depositEntity.save() + logDataBtc.save() + logDataEth.save() +} + +export function handleDepositFinalized(event: DepositFinalizedEvent): void { + const depositOwnerEntity = getOrCreateDepositOwner(event.params.depositOwner) + const depositEntity = getOrCreateDeposit( + event.params.depositKey.toHexString(), + ) + + depositEntity.depositOwner = depositOwnerEntity.id + depositEntity.initialDepositAmountSatoshi = event.params.initialAmount + depositEntity.amountToDepositStBtc = event.params.bridgedAmount + + const logDataBtc = getOrCreateLog( + `${event.transaction.hash.toHexString()}btc`, + ) + const logDataEth = getOrCreateLog( + `${event.transaction.hash.toHexString()}eth`, + ) + + logDataBtc.activity = depositEntity.id + + // This timestamp may be different than the actual time + // when the BTC transaction took place: + // It indicates when Ethereum received event about this BTC deposit, + // not when the BTC transaction happened. + logDataBtc.timestamp = event.block.timestamp + logDataBtc.chain = "Bitcoin" + logDataBtc.amount = event.params.initialAmount + + logDataEth.activity = depositEntity.id + logDataEth.timestamp = event.block.timestamp + logDataEth.chain = "Ethereum" + logDataEth.amount = event.params.initialAmount + + depositOwnerEntity.save() + depositEntity.save() + logDataBtc.save() + logDataEth.save() +} diff --git a/subgraph/src/utils.ts b/subgraph/src/utils.ts index 299e93b0b..5d4c786fb 100644 --- a/subgraph/src/utils.ts +++ b/subgraph/src/utils.ts @@ -1,5 +1,5 @@ import { Address } from "@graphprotocol/graph-ts" -import { DepositOwner, LogData, Stake } from "../generated/schema" +import { DepositOwner, LogData, Deposit } from "../generated/schema" export function getOrCreateDepositOwner(depositOwnerId: Address): DepositOwner { const depositOwnerHexString = depositOwnerId.toHexString() @@ -12,15 +12,14 @@ export function getOrCreateDepositOwner(depositOwnerId: Address): DepositOwner { return depositOwner } -export function getOrCreateStake(transactionId: string): Stake { - // const stakeHexString = transactionHash.toHexString() - let stake = Stake.load(transactionId) +export function getOrCreateDeposit(transactionId: string): Deposit { + let deposit = Deposit.load(transactionId) - if (!stake) { - stake = new Stake(transactionId) + if (!deposit) { + deposit = new Deposit(transactionId) } - return stake + return deposit } export function getOrCreateLog(logId: string): LogData { diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 1bf2b1c05..fbde95930 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -5,11 +5,11 @@ schema: file: ./schema.graphql dataSources: - kind: ethereum - name: AcreBitcoinDepositor + name: BitcoinDepositor network: sepolia source: address: "0x2F86FE8C5683372Db667E6f6d88dcB6d55a81286" - abi: AcreBitcoinDepositor + abi: BitcoinDepositor startBlock: 5675744 mapping: kind: ethereum/events @@ -17,14 +17,16 @@ dataSources: language: wasm/assemblyscript entities: - DepositOwner - - Stake - - Unstake + - Deposit + - Withdraw - LogData abis: - - name: AcreBitcoinDepositor - file: ./abis/AcreBitcoinDepositor.json + - name: BitcoinDepositor + file: ./abis/BitcoinDepositor.json eventHandlers: - event: DepositInitialized(indexed uint256,indexed address,indexed address,uint256) handler: handleDepositInitialized receipt: true - file: ./src/acre-bitcoin-depositor.ts + - event: DepositFinalized(indexed uint256,indexed address,indexed address,indexed uint16,uint256,uint256,uint256) + handler: handleDepositFinalized + file: ./src/bitcoin-depositor.ts diff --git a/subgraph/tests/acre-bitcoin-depositor-utils.ts b/subgraph/tests/acre-bitcoin-depositor-utils.ts deleted file mode 100644 index 7143e8c95..000000000 --- a/subgraph/tests/acre-bitcoin-depositor-utils.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts" -import { newMockEvent } from "matchstick-as/assembly/defaults" -import { DepositInitialized } from "../generated/AcreBitcoinDepositor/AcreBitcoinDepositor" - -// eslint-disable-next-line import/prefer-default-export -export function createDepositInitializedEvent( - depositKey: BigInt, - caller: Address, - depositOwner: Address, - initialAmount: BigInt, -): DepositInitialized { - const depositInitializedEvent = changetype(newMockEvent()) - - depositInitializedEvent.parameters = [] - - const depositKeyParam = new ethereum.EventParam( - "depositKey", - ethereum.Value.fromUnsignedBigInt(depositKey), - ) - const callerParam = new ethereum.EventParam( - "caller", - ethereum.Value.fromAddress(caller), - ) - - const depositOwnerParam = new ethereum.EventParam( - "depositOwner", - ethereum.Value.fromAddress(depositOwner), - ) - - const initialAmountParam = new ethereum.EventParam( - "initialAmount", - ethereum.Value.fromUnsignedBigInt(initialAmount), - ) - - depositInitializedEvent.parameters.push(depositKeyParam) - depositInitializedEvent.parameters.push(callerParam) - depositInitializedEvent.parameters.push(depositOwnerParam) - depositInitializedEvent.parameters.push(initialAmountParam) - - return depositInitializedEvent -} diff --git a/subgraph/tests/acre-bitcoin-depositor.test.ts b/subgraph/tests/acre-bitcoin-depositor.test.ts deleted file mode 100644 index 4f1248ea1..000000000 --- a/subgraph/tests/acre-bitcoin-depositor.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - assert, - describe, - test, - clearStore, - afterEach, - beforeEach, -} from "matchstick-as/assembly/index" -import { BigInt, Address } from "@graphprotocol/graph-ts" -import { createDepositInitializedEvent } from "./acre-bitcoin-depositor-utils" -import { handleDepositInitialized } from "../src/acre-bitcoin-depositor" - -const depositKey = BigInt.fromI32(234) -const caller = Address.fromString("0x0000000000000000000000000000000000000001") -const depositOwner = Address.fromString( - "0x0000000000000000000000000000000000000001", -) -const initialAmount = BigInt.fromI32(234) - -const event = createDepositInitializedEvent( - depositKey, - caller, - depositOwner, - initialAmount, -) - -describe("createStakeRequestInitialized event", () => { - beforeEach(() => { - handleDepositInitialized(event) - }) - - afterEach(() => { - clearStore() - }) - - test("should create DepositOwner entity", () => { - assert.entityCount("DepositOwner", 1) - }) - - test("should create Stake entity", () => { - assert.entityCount("Stake", 1) - }) - - test("should create LogData entities", () => { - assert.entityCount("LogData", 2) - }) - - test("Stake entity has proper fields", () => { - assert.fieldEquals( - "Stake", - event.transaction.hash.toHexString(), - "depositOwner", - depositOwner.toHexString(), - ) - - assert.fieldEquals( - "Stake", - event.transaction.hash.toHexString(), - "initialDepositAmountSatoshi", - event.params.initialAmount.toString(), - ) - }) - - test("LogData entity has proper fields", () => { - const txBtcId = `${event.transaction.hash.toHexString()}btc` - const txEthId = `${event.transaction.hash.toHexString()}eth` - - assert.fieldEquals( - "LogData", - txBtcId, - "activity", - event.transaction.hash.toHexString(), - ) - - assert.fieldEquals( - "LogData", - txEthId, - "activity", - event.transaction.hash.toHexString(), - ) - - assert.fieldEquals( - "LogData", - txBtcId, - "timestamp", - event.block.timestamp.toString(), - ) - - assert.fieldEquals( - "LogData", - txEthId, - "timestamp", - event.block.timestamp.toString(), - ) - - assert.fieldEquals("LogData", txBtcId, "chain", "Bitcoin") - assert.fieldEquals("LogData", txEthId, "chain", "Ethereum") - - assert.fieldEquals("LogData", txBtcId, "amount", initialAmount.toString()) - assert.fieldEquals("LogData", txEthId, "amount", initialAmount.toString()) - }) -}) diff --git a/subgraph/tests/bitcoin-depositor-utils.ts b/subgraph/tests/bitcoin-depositor-utils.ts new file mode 100644 index 000000000..aba46e8fb --- /dev/null +++ b/subgraph/tests/bitcoin-depositor-utils.ts @@ -0,0 +1,101 @@ +import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts" +import { newMockEvent } from "matchstick-as/assembly/defaults" +import { + DepositInitialized, + DepositFinalized, +} from "../generated/BitcoinDepositor/BitcoinDepositor" + +export function createDepositInitializedEvent( + depositKey: BigInt, + caller: Address, + depositOwner: Address, + initialAmount: BigInt, +): DepositInitialized { + const depositInitializedEvent = changetype(newMockEvent()) + + depositInitializedEvent.parameters = [] + + const depositKeyParam = new ethereum.EventParam( + "depositKey", + ethereum.Value.fromUnsignedBigInt(depositKey), + ) + const callerParam = new ethereum.EventParam( + "caller", + ethereum.Value.fromAddress(caller), + ) + + const depositOwnerParam = new ethereum.EventParam( + "depositOwner", + ethereum.Value.fromAddress(depositOwner), + ) + + const initialAmountParam = new ethereum.EventParam( + "initialAmount", + ethereum.Value.fromUnsignedBigInt(initialAmount), + ) + + depositInitializedEvent.parameters.push(depositKeyParam) + depositInitializedEvent.parameters.push(callerParam) + depositInitializedEvent.parameters.push(depositOwnerParam) + depositInitializedEvent.parameters.push(initialAmountParam) + + return depositInitializedEvent +} + +export function createDepositFinalizedEvent( + depositKey: BigInt, + caller: Address, + depositOwner: Address, + referral: BigInt, + initialAmount: BigInt, + bridgedAmount: BigInt, + depositorFee: BigInt, +): DepositFinalized { + const depositFinalizedEvent = changetype(newMockEvent()) + + depositFinalizedEvent.parameters = [] + + const depositKeyParam = new ethereum.EventParam( + "depositKey", + ethereum.Value.fromUnsignedBigInt(depositKey), + ) + const callerParam = new ethereum.EventParam( + "caller", + ethereum.Value.fromAddress(caller), + ) + + const depositOwnerParam = new ethereum.EventParam( + "depositOwner", + ethereum.Value.fromAddress(depositOwner), + ) + + const referralParam = new ethereum.EventParam( + "referral", + ethereum.Value.fromUnsignedBigInt(referral), + ) + + const initialAmountParam = new ethereum.EventParam( + "initialAmount", + ethereum.Value.fromUnsignedBigInt(initialAmount), + ) + + const bridgedAmountParam = new ethereum.EventParam( + "bridgedAmount", + ethereum.Value.fromUnsignedBigInt(bridgedAmount), + ) + + const depositorFeeParam = new ethereum.EventParam( + "depositorFee", + ethereum.Value.fromUnsignedBigInt(depositorFee), + ) + + depositFinalizedEvent.parameters.push(depositKeyParam) + depositFinalizedEvent.parameters.push(callerParam) + depositFinalizedEvent.parameters.push(depositOwnerParam) + depositFinalizedEvent.parameters.push(referralParam) + depositFinalizedEvent.parameters.push(initialAmountParam) + depositFinalizedEvent.parameters.push(bridgedAmountParam) + depositFinalizedEvent.parameters.push(depositorFeeParam) + + return depositFinalizedEvent +} diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts new file mode 100644 index 000000000..57450af2b --- /dev/null +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -0,0 +1,205 @@ +import { + assert, + describe, + test, + clearStore, + afterEach, + beforeEach, +} from "matchstick-as/assembly/index" +import { BigInt, Address } from "@graphprotocol/graph-ts" +import { + createDepositInitializedEvent, + createDepositFinalizedEvent, +} from "./bitcoin-depositor-utils" +import { + handleDepositFinalized, + handleDepositInitialized, +} from "../src/bitcoin-depositor" + +const depositKey = BigInt.fromI32(234) +const caller = Address.fromString("0x0000000000000000000000000000000000000001") +const depositOwner = Address.fromString( + "0x0000000000000000000000000000000000000001", +) +const referral = BigInt.fromI32(234) +const initialAmount = BigInt.fromI32(234) +const bridgedAmount = BigInt.fromI32(234) +const depositorFee = BigInt.fromI32(234) + +const depositInitializedEvent = createDepositInitializedEvent( + depositKey, + caller, + depositOwner, + initialAmount, +) + +const depositFinalizedEvent = createDepositFinalizedEvent( + depositKey, + caller, + depositOwner, + referral, + initialAmount, + bridgedAmount, + depositorFee, +) + +describe("createDepositInitializedEvent event", () => { + beforeEach(() => { + handleDepositInitialized(depositInitializedEvent) + }) + + afterEach(() => { + clearStore() + }) + + test("should create DepositOwner entity", () => { + assert.entityCount("DepositOwner", 1) + }) + + test("should create Deposit entity", () => { + assert.entityCount("Deposit", 1) + }) + + test("should create LogData entities", () => { + assert.entityCount("LogData", 2) + }) + + test("Deposit entity has proper fields", () => { + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "initialDepositAmountSatoshi", + depositInitializedEvent.params.initialAmount.toString(), + ) + }) + + test("LogData entity has proper fields", () => { + const txBtcId = `${depositInitializedEvent.transaction.hash.toHexString()}btc` + const txEthId = `${depositInitializedEvent.transaction.hash.toHexString()}eth` + + assert.fieldEquals( + "LogData", + txBtcId, + "activity", + depositInitializedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "LogData", + txEthId, + "activity", + depositInitializedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "LogData", + txBtcId, + "timestamp", + depositInitializedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals( + "LogData", + txEthId, + "timestamp", + depositInitializedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals("LogData", txBtcId, "chain", "Bitcoin") + assert.fieldEquals("LogData", txEthId, "chain", "Ethereum") + + assert.fieldEquals("LogData", txBtcId, "amount", initialAmount.toString()) + assert.fieldEquals("LogData", txEthId, "amount", initialAmount.toString()) + }) +}) + +describe("createDepositFinalizedEvent event", () => { + beforeEach(() => { + handleDepositFinalized(depositFinalizedEvent) + }) + + afterEach(() => { + clearStore() + }) + + test("should create DepositOwner entity", () => { + assert.entityCount("DepositOwner", 1) + }) + + test("should create Deposit entity", () => { + assert.entityCount("Deposit", 1) + }) + + test("should create LogData entities", () => { + assert.entityCount("LogData", 2) + }) + + test("Deposit entity has proper fields", () => { + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "initialDepositAmountSatoshi", + depositFinalizedEvent.params.initialAmount.toString(), + ) + }) + + test("LogData entity has proper fields", () => { + const txBtcId = `${depositFinalizedEvent.transaction.hash.toHexString()}btc` + const txEthId = `${depositFinalizedEvent.transaction.hash.toHexString()}eth` + + assert.fieldEquals( + "LogData", + txBtcId, + "activity", + depositFinalizedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "LogData", + txEthId, + "activity", + depositFinalizedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "LogData", + txBtcId, + "timestamp", + depositFinalizedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals( + "LogData", + txEthId, + "timestamp", + depositFinalizedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals("LogData", txBtcId, "chain", "Bitcoin") + assert.fieldEquals("LogData", txEthId, "chain", "Ethereum") + + assert.fieldEquals("LogData", txBtcId, "amount", initialAmount.toString()) + assert.fieldEquals("LogData", txEthId, "amount", initialAmount.toString()) + }) +}) From 64c7a32bb37d067cf563ae69f9972cba20f6524d Mon Sep 17 00:00:00 2001 From: ioay Date: Mon, 22 Apr 2024 17:45:13 +0200 Subject: [PATCH 09/28] LogData -> Event entity, simplified event entity, adjusted tests --- subgraph/README.md | 22 +++++- subgraph/abis/BitcoinDepositor.json | 6 -- subgraph/schema.graphql | 38 +++++----- subgraph/src/bitcoin-depositor.ts | 67 ++++-------------- subgraph/src/utils.ts | 12 ++-- subgraph/subgraph.yaml | 2 +- subgraph/tests/bitcoin-depositor-utils.ts | 7 -- subgraph/tests/bitcoin-depositor.test.ts | 86 ++++++++++------------- 8 files changed, 96 insertions(+), 144 deletions(-) diff --git a/subgraph/README.md b/subgraph/README.md index 09a2ce5ed..6e768a028 100644 --- a/subgraph/README.md +++ b/subgraph/README.md @@ -78,7 +78,17 @@ Note: use it only if your subgraph is not created in the local Graph node. ### Deploy the subgraph to Subgraph Studio -1. Once your subgraph has been created in Subgraph Studio you can initialize the subgraph code using this command: +1. You need to connect wallet to use Subgraph Studio [Metamask, WalletConnect, Coinbase Wallet or Safe]. + + ``` + https://thegraph.com/studio/ + ``` + +2. We're going to create a Subgraph. To do that you need to click Create a Subgraph button in My Dashboard of Subgraph Studio. + +3. In the next step you'll need to add name of Subgraph and choose indexed blockchain from the list. + +4. Once your subgraph has been created in Subgraph Studio you can initialize the subgraph code using this command: ``` graph init --studio @@ -87,7 +97,7 @@ Note: use it only if your subgraph is not created in the local Graph node. The value can be found on your subgraph details page in Subgraph Studio (https://thegraph.com/docs/en/deploying/deploying-a-subgraph-to-studio/#create-your-subgraph-in-subgraph-studio) -2. Before being able to deploy your subgraph to Subgraph Studio, you need to login into your account within the CLI. +5. Before being able to deploy your subgraph to Subgraph Studio, you need to login into your account within the CLI. ``` graph auth --studio @@ -95,10 +105,16 @@ Note: use it only if your subgraph is not created in the local Graph node. The can be found on your "My Subgraphs" page or your subgraph details page. -3. Deploying a Subgraph to Subgraph Studio +6. Deploying a Subgraph to Subgraph Studio ``` graph deploy --studio ``` After running this command, the CLI will ask for a version label, you can name it however you want, you can use labels such as 0.1 and 0.2 or use letters as well such as uniswap-v2-0.1. + +7. More information about deploying your subgraph to Subgraph Studio: + + ``` + https://thegraph.com/docs/en/deploying/subgraph-studio/ + ``` diff --git a/subgraph/abis/BitcoinDepositor.json b/subgraph/abis/BitcoinDepositor.json index 3c4462015..29b1c8055 100644 --- a/subgraph/abis/BitcoinDepositor.json +++ b/subgraph/abis/BitcoinDepositor.json @@ -14,12 +14,6 @@ "name": "caller", "type": "address" }, - { - "indexed": true, - "internalType": "address", - "name": "depositOwner", - "type": "address" - }, { "indexed": true, "internalType": "uint16", diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index ee6e77851..d2d30b397 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -1,9 +1,4 @@ -enum ChainType { - Bitcoin - Ethereum -} - -enum LogType { +enum EventType { Unknown Initialized Finalized @@ -12,7 +7,8 @@ enum LogType { interface ActivityData @key(fields: "id") { id: ID! depositOwner: DepositOwner! - logs: [LogData!] + events: [Event!] + txBtcId: String } type DepositOwner @entity { @@ -24,27 +20,33 @@ type DepositOwner @entity { type Deposit implements ActivityData @entity { id: ID! depositOwner: DepositOwner! - logs: [LogData!] @derivedFrom(field: "activity") - initialDepositAmountSatoshi: BigInt! - amountToDepositStBtc: BigInt - shareStBtc: BigInt + events: [Event!] @derivedFrom(field: "activity") + initialDepositAmount: BigInt! + amountToDeposit: BigInt + bridgedAmount: BigInt + depositorFee: BigInt + referral: BigInt + txBtcId: String + # TODO: add these fields when event & contract be ready + # entryFee (amountToDeposit - depositedAmount) + # depositedAmount: assets from deposit event (stbtc contract) + # shares: shares from deposit event(stbtc contract) } type Withdraw implements ActivityData @entity { id: ID! depositOwner: DepositOwner! - logs: [LogData!] @derivedFrom(field: "activity") - initialDepositAmountSatoshi: BigInt! - amountToDepositStBtc: BigInt - shareStBtc: BigInt + events: [Event!] @derivedFrom(field: "activity") + initialDepositAmount: BigInt! + amountToDeposit: BigInt + txBtcId: String } -type LogData @entity { +type Event @entity { # Id is the transaction hash. id: ID! timestamp: BigInt! activity: ActivityData - chain: ChainType! - type: LogType + type: EventType amount: BigInt! } diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 0616be07a..2f7dba30c 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -5,10 +5,9 @@ import { import { getOrCreateDepositOwner, getOrCreateDeposit, - getOrCreateLog, + getOrCreateEvent, } from "./utils" -// eslint-disable-next-line import/prefer-default-export export function handleDepositInitialized(event: DepositInitializedEvent): void { const depositOwnerEntity = getOrCreateDepositOwner(event.params.depositOwner) const depositEntity = getOrCreateDeposit( @@ -16,70 +15,32 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { ) depositEntity.depositOwner = depositOwnerEntity.id - depositEntity.initialDepositAmountSatoshi = event.params.initialAmount + depositEntity.initialDepositAmount = event.params.initialAmount - const logDataBtc = getOrCreateLog( - `${event.transaction.hash.toHexString()}btc`, - ) - const logDataEth = getOrCreateLog( - `${event.transaction.hash.toHexString()}eth`, - ) - - logDataBtc.activity = depositEntity.id + const eventEntity = getOrCreateEvent(event.transaction.hash.toHexString()) - // This timestamp may be different than the actual time - // when the BTC transaction took place: - // It indicates when Ethereum received event about this BTC deposit, - // not when the BTC transaction happened. - logDataBtc.timestamp = event.block.timestamp - logDataBtc.chain = "Bitcoin" - logDataBtc.amount = event.params.initialAmount - - logDataEth.activity = depositEntity.id - logDataEth.timestamp = event.block.timestamp - logDataEth.chain = "Ethereum" - logDataEth.amount = event.params.initialAmount + eventEntity.activity = depositEntity.id + eventEntity.timestamp = event.block.timestamp + eventEntity.amount = event.params.initialAmount depositOwnerEntity.save() depositEntity.save() - logDataBtc.save() - logDataEth.save() + eventEntity.save() } export function handleDepositFinalized(event: DepositFinalizedEvent): void { - const depositOwnerEntity = getOrCreateDepositOwner(event.params.depositOwner) const depositEntity = getOrCreateDeposit( event.params.depositKey.toHexString(), ) - depositEntity.depositOwner = depositOwnerEntity.id - depositEntity.initialDepositAmountSatoshi = event.params.initialAmount - depositEntity.amountToDepositStBtc = event.params.bridgedAmount - - const logDataBtc = getOrCreateLog( - `${event.transaction.hash.toHexString()}btc`, - ) - const logDataEth = getOrCreateLog( - `${event.transaction.hash.toHexString()}eth`, - ) - - logDataBtc.activity = depositEntity.id - - // This timestamp may be different than the actual time - // when the BTC transaction took place: - // It indicates when Ethereum received event about this BTC deposit, - // not when the BTC transaction happened. - logDataBtc.timestamp = event.block.timestamp - logDataBtc.chain = "Bitcoin" - logDataBtc.amount = event.params.initialAmount + depositEntity.initialDepositAmount = event.params.initialAmount + depositEntity.amountToDeposit = event.params.bridgedAmount - logDataEth.activity = depositEntity.id - logDataEth.timestamp = event.block.timestamp - logDataEth.chain = "Ethereum" - logDataEth.amount = event.params.initialAmount + const eventEntity = getOrCreateEvent(event.transaction.hash.toHexString()) + eventEntity.activity = depositEntity.id + eventEntity.timestamp = event.block.timestamp + eventEntity.amount = event.params.initialAmount - depositOwnerEntity.save() depositEntity.save() - logDataBtc.save() - logDataEth.save() + eventEntity.save() } diff --git a/subgraph/src/utils.ts b/subgraph/src/utils.ts index 5d4c786fb..1b1d8f430 100644 --- a/subgraph/src/utils.ts +++ b/subgraph/src/utils.ts @@ -1,5 +1,5 @@ import { Address } from "@graphprotocol/graph-ts" -import { DepositOwner, LogData, Deposit } from "../generated/schema" +import { DepositOwner, Deposit, Event } from "../generated/schema" export function getOrCreateDepositOwner(depositOwnerId: Address): DepositOwner { const depositOwnerHexString = depositOwnerId.toHexString() @@ -22,12 +22,12 @@ export function getOrCreateDeposit(transactionId: string): Deposit { return deposit } -export function getOrCreateLog(logId: string): LogData { - let log = LogData.load(logId) +export function getOrCreateEvent(eventId: string): Event { + let event = Event.load(eventId) - if (!log) { - log = new LogData(logId) + if (!event) { + event = new Event(eventId) } - return log + return event } diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index fbde95930..871010ca6 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -27,6 +27,6 @@ dataSources: - event: DepositInitialized(indexed uint256,indexed address,indexed address,uint256) handler: handleDepositInitialized receipt: true - - event: DepositFinalized(indexed uint256,indexed address,indexed address,indexed uint16,uint256,uint256,uint256) + - event: DepositFinalized(indexed uint256,indexed address,indexed uint16,uint256,uint256,uint256) handler: handleDepositFinalized file: ./src/bitcoin-depositor.ts diff --git a/subgraph/tests/bitcoin-depositor-utils.ts b/subgraph/tests/bitcoin-depositor-utils.ts index aba46e8fb..7d3eb01be 100644 --- a/subgraph/tests/bitcoin-depositor-utils.ts +++ b/subgraph/tests/bitcoin-depositor-utils.ts @@ -45,7 +45,6 @@ export function createDepositInitializedEvent( export function createDepositFinalizedEvent( depositKey: BigInt, caller: Address, - depositOwner: Address, referral: BigInt, initialAmount: BigInt, bridgedAmount: BigInt, @@ -64,11 +63,6 @@ export function createDepositFinalizedEvent( ethereum.Value.fromAddress(caller), ) - const depositOwnerParam = new ethereum.EventParam( - "depositOwner", - ethereum.Value.fromAddress(depositOwner), - ) - const referralParam = new ethereum.EventParam( "referral", ethereum.Value.fromUnsignedBigInt(referral), @@ -91,7 +85,6 @@ export function createDepositFinalizedEvent( depositFinalizedEvent.parameters.push(depositKeyParam) depositFinalizedEvent.parameters.push(callerParam) - depositFinalizedEvent.parameters.push(depositOwnerParam) depositFinalizedEvent.parameters.push(referralParam) depositFinalizedEvent.parameters.push(initialAmountParam) depositFinalizedEvent.parameters.push(bridgedAmountParam) diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 57450af2b..84c2f11b1 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -3,8 +3,8 @@ import { describe, test, clearStore, - afterEach, - beforeEach, + beforeAll, + afterAll, } from "matchstick-as/assembly/index" import { BigInt, Address } from "@graphprotocol/graph-ts" import { @@ -36,7 +36,6 @@ const depositInitializedEvent = createDepositInitializedEvent( const depositFinalizedEvent = createDepositFinalizedEvent( depositKey, caller, - depositOwner, referral, initialAmount, bridgedAmount, @@ -44,11 +43,11 @@ const depositFinalizedEvent = createDepositFinalizedEvent( ) describe("createDepositInitializedEvent event", () => { - beforeEach(() => { + beforeAll(() => { handleDepositInitialized(depositInitializedEvent) }) - afterEach(() => { + afterAll(() => { clearStore() }) @@ -60,8 +59,8 @@ describe("createDepositInitializedEvent event", () => { assert.entityCount("Deposit", 1) }) - test("should create LogData entities", () => { - assert.entityCount("LogData", 2) + test("should create Event entity", () => { + assert.entityCount("Event", 1) }) test("Deposit entity has proper fields", () => { @@ -82,70 +81,62 @@ describe("createDepositInitializedEvent event", () => { assert.fieldEquals( "Deposit", depositInitializedEvent.params.depositKey.toHexString(), - "initialDepositAmountSatoshi", + "initialDepositAmount", depositInitializedEvent.params.initialAmount.toString(), ) }) - test("LogData entity has proper fields", () => { - const txBtcId = `${depositInitializedEvent.transaction.hash.toHexString()}btc` - const txEthId = `${depositInitializedEvent.transaction.hash.toHexString()}eth` + test("Event entity has proper fields", () => { + const txId = depositInitializedEvent.transaction.hash.toHexString() assert.fieldEquals( - "LogData", - txBtcId, + "Event", + txId, "activity", depositInitializedEvent.params.depositKey.toHexString(), ) assert.fieldEquals( - "LogData", - txEthId, + "Event", + txId, "activity", depositInitializedEvent.params.depositKey.toHexString(), ) assert.fieldEquals( - "LogData", - txBtcId, + "Event", + txId, "timestamp", depositInitializedEvent.block.timestamp.toString(), ) assert.fieldEquals( - "LogData", - txEthId, + "Event", + txId, "timestamp", depositInitializedEvent.block.timestamp.toString(), ) - assert.fieldEquals("LogData", txBtcId, "chain", "Bitcoin") - assert.fieldEquals("LogData", txEthId, "chain", "Ethereum") - - assert.fieldEquals("LogData", txBtcId, "amount", initialAmount.toString()) - assert.fieldEquals("LogData", txEthId, "amount", initialAmount.toString()) + assert.fieldEquals("Event", txId, "amount", initialAmount.toString()) }) }) describe("createDepositFinalizedEvent event", () => { - beforeEach(() => { + beforeAll(() => { + handleDepositInitialized(depositInitializedEvent) handleDepositFinalized(depositFinalizedEvent) }) - afterEach(() => { + afterAll(() => { clearStore() }) - test("should create DepositOwner entity", () => { - assert.entityCount("DepositOwner", 1) - }) - - test("should create Deposit entity", () => { + test("should load Deposit entity", () => { assert.entityCount("Deposit", 1) }) - test("should create LogData entities", () => { - assert.entityCount("LogData", 2) + test("should create Event entity", () => { + assert.entityCount("Event", 1) }) test("Deposit entity has proper fields", () => { @@ -159,47 +150,42 @@ describe("createDepositFinalizedEvent event", () => { assert.fieldEquals( "Deposit", depositFinalizedEvent.params.depositKey.toHexString(), - "initialDepositAmountSatoshi", + "initialDepositAmount", depositFinalizedEvent.params.initialAmount.toString(), ) }) - test("LogData entity has proper fields", () => { - const txBtcId = `${depositFinalizedEvent.transaction.hash.toHexString()}btc` - const txEthId = `${depositFinalizedEvent.transaction.hash.toHexString()}eth` + test("Event entity has proper fields", () => { + const txId = depositFinalizedEvent.transaction.hash.toHexString() assert.fieldEquals( - "LogData", - txBtcId, + "Event", + txId, "activity", depositFinalizedEvent.params.depositKey.toHexString(), ) assert.fieldEquals( - "LogData", - txEthId, + "Event", + txId, "activity", depositFinalizedEvent.params.depositKey.toHexString(), ) assert.fieldEquals( - "LogData", - txBtcId, + "Event", + txId, "timestamp", depositFinalizedEvent.block.timestamp.toString(), ) assert.fieldEquals( - "LogData", - txEthId, + "Event", + txId, "timestamp", depositFinalizedEvent.block.timestamp.toString(), ) - assert.fieldEquals("LogData", txBtcId, "chain", "Bitcoin") - assert.fieldEquals("LogData", txEthId, "chain", "Ethereum") - - assert.fieldEquals("LogData", txBtcId, "amount", initialAmount.toString()) - assert.fieldEquals("LogData", txEthId, "amount", initialAmount.toString()) + assert.fieldEquals("Event", txId, "amount", initialAmount.toString()) }) }) From 6d0bd0cbfe2046017adb536bc318e7de7b708a79 Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 09:14:20 +0200 Subject: [PATCH 10/28] Renamed txBtcId schema field to bitcoinTransactionId --- subgraph/schema.graphql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index d2d30b397..ab8f2c027 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -8,7 +8,7 @@ interface ActivityData @key(fields: "id") { id: ID! depositOwner: DepositOwner! events: [Event!] - txBtcId: String + bitcoinTransactionId: String } type DepositOwner @entity { @@ -26,7 +26,7 @@ type Deposit implements ActivityData @entity { bridgedAmount: BigInt depositorFee: BigInt referral: BigInt - txBtcId: String + bitcoinTransactionId: String # TODO: add these fields when event & contract be ready # entryFee (amountToDeposit - depositedAmount) # depositedAmount: assets from deposit event (stbtc contract) @@ -39,7 +39,7 @@ type Withdraw implements ActivityData @entity { events: [Event!] @derivedFrom(field: "activity") initialDepositAmount: BigInt! amountToDeposit: BigInt - txBtcId: String + bitcoinTransactionId: String } type Event @entity { From 9ecd67d35d3f737b73e3afd32911643f4201b9fe Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 09:24:09 +0200 Subject: [PATCH 11/28] Subgraph: tests for bitcoin-depositor adjusted --- subgraph/tests/bitcoin-depositor.test.ts | 43 +++--------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 84c2f11b1..d211fabfb 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -42,7 +42,7 @@ const depositFinalizedEvent = createDepositFinalizedEvent( depositorFee, ) -describe("createDepositInitializedEvent event", () => { +describe("handleDepositInitialized", () => { beforeAll(() => { handleDepositInitialized(depositInitializedEvent) }) @@ -71,13 +71,6 @@ describe("createDepositInitializedEvent event", () => { depositOwner.toHexString(), ) - assert.fieldEquals( - "Deposit", - depositInitializedEvent.params.depositKey.toHexString(), - "depositOwner", - depositOwner.toHexString(), - ) - assert.fieldEquals( "Deposit", depositInitializedEvent.params.depositKey.toHexString(), @@ -96,20 +89,6 @@ describe("createDepositInitializedEvent event", () => { depositInitializedEvent.params.depositKey.toHexString(), ) - assert.fieldEquals( - "Event", - txId, - "activity", - depositInitializedEvent.params.depositKey.toHexString(), - ) - - assert.fieldEquals( - "Event", - txId, - "timestamp", - depositInitializedEvent.block.timestamp.toString(), - ) - assert.fieldEquals( "Event", txId, @@ -121,7 +100,7 @@ describe("createDepositInitializedEvent event", () => { }) }) -describe("createDepositFinalizedEvent event", () => { +describe("handleDepositFinalized", () => { beforeAll(() => { handleDepositInitialized(depositInitializedEvent) handleDepositFinalized(depositFinalizedEvent) @@ -131,11 +110,11 @@ describe("createDepositFinalizedEvent event", () => { clearStore() }) - test("should load Deposit entity", () => { + test("Deposit entity should exist", () => { assert.entityCount("Deposit", 1) }) - test("should create Event entity", () => { + test("Event entity should exist", () => { assert.entityCount("Event", 1) }) @@ -165,20 +144,6 @@ describe("createDepositFinalizedEvent event", () => { depositFinalizedEvent.params.depositKey.toHexString(), ) - assert.fieldEquals( - "Event", - txId, - "activity", - depositFinalizedEvent.params.depositKey.toHexString(), - ) - - assert.fieldEquals( - "Event", - txId, - "timestamp", - depositFinalizedEvent.block.timestamp.toString(), - ) - assert.fieldEquals( "Event", txId, From 3ba10f1d99830dd87693cad02af06dcfc69ef72e Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 09:43:30 +0200 Subject: [PATCH 12/28] Removed Unkown eventType --- subgraph/schema.graphql | 1 - 1 file changed, 1 deletion(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index ab8f2c027..55a3dae85 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -1,5 +1,4 @@ enum EventType { - Unknown Initialized Finalized } From f812f51ffac1b91a90d56e319525e017d13bb146 Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 11:07:06 +0200 Subject: [PATCH 13/28] Error handling in case of no deposit entity for handleDepositFinalized --- subgraph/src/bitcoin-depositor.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 2f7dba30c..455e66fa1 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -2,6 +2,7 @@ import { DepositInitialized as DepositInitializedEvent, DepositFinalized as DepositFinalizedEvent, } from "../generated/BitcoinDepositor/BitcoinDepositor" +import { Deposit } from "../generated/schema" import { getOrCreateDepositOwner, getOrCreateDeposit, @@ -29,9 +30,11 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { } export function handleDepositFinalized(event: DepositFinalizedEvent): void { - const depositEntity = getOrCreateDeposit( - event.params.depositKey.toHexString(), - ) + const depositEntity = Deposit.load(event.params.depositKey.toHexString()) + + if (!depositEntity) { + throw new Error("Deposit entity does not exist") + } depositEntity.initialDepositAmount = event.params.initialAmount depositEntity.amountToDeposit = event.params.bridgedAmount From 93ca0d1691c2d9b62ca902e0f6417b45bda34298 Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 11:13:21 +0200 Subject: [PATCH 14/28] Make type for EventyEntity required --- subgraph/schema.graphql | 2 +- subgraph/src/bitcoin-depositor.ts | 2 ++ subgraph/tests/bitcoin-depositor.test.ts | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 55a3dae85..0b3f318e3 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -46,6 +46,6 @@ type Event @entity { id: ID! timestamp: BigInt! activity: ActivityData - type: EventType + type: EventType! amount: BigInt! } diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 455e66fa1..c88e29058 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -23,6 +23,7 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { eventEntity.activity = depositEntity.id eventEntity.timestamp = event.block.timestamp eventEntity.amount = event.params.initialAmount + eventEntity.type = "Initialized" depositOwnerEntity.save() depositEntity.save() @@ -43,6 +44,7 @@ export function handleDepositFinalized(event: DepositFinalizedEvent): void { eventEntity.activity = depositEntity.id eventEntity.timestamp = event.block.timestamp eventEntity.amount = event.params.initialAmount + eventEntity.type = "Finalized" depositEntity.save() eventEntity.save() diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index d211fabfb..30d5b8aa4 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -97,6 +97,7 @@ describe("handleDepositInitialized", () => { ) assert.fieldEquals("Event", txId, "amount", initialAmount.toString()) + assert.fieldEquals("Event", txId, "type", "Initialized") }) }) @@ -152,5 +153,6 @@ describe("handleDepositFinalized", () => { ) assert.fieldEquals("Event", txId, "amount", initialAmount.toString()) + assert.fieldEquals("Event", txId, "type", "Finalized") }) }) From 56633d0daf0202afac8eaaf9e68b86e3d09d6dac Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 11:34:32 +0200 Subject: [PATCH 15/28] Removed amount from Event entity, updated mapping entities in subgraph.yaml --- subgraph/schema.graphql | 1 - subgraph/src/bitcoin-depositor.ts | 3 +-- subgraph/subgraph.yaml | 2 +- subgraph/tests/bitcoin-depositor.test.ts | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 0b3f318e3..d6bde9e83 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -47,5 +47,4 @@ type Event @entity { timestamp: BigInt! activity: ActivityData type: EventType! - amount: BigInt! } diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index c88e29058..4d07ac838 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -22,7 +22,6 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { eventEntity.activity = depositEntity.id eventEntity.timestamp = event.block.timestamp - eventEntity.amount = event.params.initialAmount eventEntity.type = "Initialized" depositOwnerEntity.save() @@ -41,9 +40,9 @@ export function handleDepositFinalized(event: DepositFinalizedEvent): void { depositEntity.amountToDeposit = event.params.bridgedAmount const eventEntity = getOrCreateEvent(event.transaction.hash.toHexString()) + eventEntity.activity = depositEntity.id eventEntity.timestamp = event.block.timestamp - eventEntity.amount = event.params.initialAmount eventEntity.type = "Finalized" depositEntity.save() diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 871010ca6..18414c988 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -19,7 +19,7 @@ dataSources: - DepositOwner - Deposit - Withdraw - - LogData + - Event abis: - name: BitcoinDepositor file: ./abis/BitcoinDepositor.json diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 30d5b8aa4..56b81a2e4 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -96,7 +96,6 @@ describe("handleDepositInitialized", () => { depositInitializedEvent.block.timestamp.toString(), ) - assert.fieldEquals("Event", txId, "amount", initialAmount.toString()) assert.fieldEquals("Event", txId, "type", "Initialized") }) }) @@ -152,7 +151,6 @@ describe("handleDepositFinalized", () => { depositFinalizedEvent.block.timestamp.toString(), ) - assert.fieldEquals("Event", txId, "amount", initialAmount.toString()) assert.fieldEquals("Event", txId, "type", "Finalized") }) }) From a569f838a764064080f0f26fbf5a8ca3890a3a1e Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 11:42:34 +0200 Subject: [PATCH 16/28] Added TODO section to handleDepositInitialized --- subgraph/src/bitcoin-depositor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 4d07ac838..e69622101 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -15,6 +15,8 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { event.params.depositKey.toHexString(), ) + // TODO: get the bitcoin transaction hash from this Ethereum transaction + // by finding the DepositRevealed event in logs from the tBTC-v2 Bridge contract. depositEntity.depositOwner = depositOwnerEntity.id depositEntity.initialDepositAmount = event.params.initialAmount From 5fd53004c5ca213805440f87c08d0dfcc516d4d8 Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 12:15:23 +0200 Subject: [PATCH 17/28] Updated the order of fields in schema --- subgraph/schema.graphql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index d6bde9e83..4f179cb4c 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -21,9 +21,9 @@ type Deposit implements ActivityData @entity { depositOwner: DepositOwner! events: [Event!] @derivedFrom(field: "activity") initialDepositAmount: BigInt! - amountToDeposit: BigInt bridgedAmount: BigInt depositorFee: BigInt + amountToDeposit: BigInt referral: BigInt bitcoinTransactionId: String # TODO: add these fields when event & contract be ready @@ -36,8 +36,8 @@ type Withdraw implements ActivityData @entity { id: ID! depositOwner: DepositOwner! events: [Event!] @derivedFrom(field: "activity") - initialDepositAmount: BigInt! - amountToDeposit: BigInt + # TODO: amount field will be updated when working on withdraw + amount: BigInt bitcoinTransactionId: String } From 623a28ff075fc5b2a1089d0ce55ebc40034058ec Mon Sep 17 00:00:00 2001 From: ioay Date: Wed, 24 Apr 2024 15:00:47 +0200 Subject: [PATCH 18/28] Added bridgedAmount, depositorFee, amountToDeposit fields --- subgraph/schema.graphql | 4 ---- subgraph/src/bitcoin-depositor.ts | 14 ++++++++++++-- subgraph/tests/bitcoin-depositor.test.ts | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 4f179cb4c..c4e0d1cf6 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -26,10 +26,6 @@ type Deposit implements ActivityData @entity { amountToDeposit: BigInt referral: BigInt bitcoinTransactionId: String - # TODO: add these fields when event & contract be ready - # entryFee (amountToDeposit - depositedAmount) - # depositedAmount: assets from deposit event (stbtc contract) - # shares: shares from deposit event(stbtc contract) } type Withdraw implements ActivityData @entity { diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index e69622101..e31266ed6 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -1,3 +1,5 @@ +import { ethereum } from "@graphprotocol/graph-ts" + import { DepositInitialized as DepositInitializedEvent, DepositFinalized as DepositFinalizedEvent, @@ -38,8 +40,16 @@ export function handleDepositFinalized(event: DepositFinalizedEvent): void { throw new Error("Deposit entity does not exist") } - depositEntity.initialDepositAmount = event.params.initialAmount - depositEntity.amountToDeposit = event.params.bridgedAmount + depositEntity.bridgedAmount = event.params.bridgedAmount + depositEntity.depositorFee = event.params.depositorFee + depositEntity.amountToDeposit = event.params.bridgedAmount.minus( + event.params.depositorFee, + ) + if (event.params.referral) { + depositEntity.referral = ethereum.Value.fromI32( + event.params.referral, + ).toBigInt() + } const eventEntity = getOrCreateEvent(event.transaction.hash.toHexString()) diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 56b81a2e4..b5f1c703f 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -132,6 +132,29 @@ describe("handleDepositFinalized", () => { "initialDepositAmount", depositFinalizedEvent.params.initialAmount.toString(), ) + + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "bridgedAmount", + depositFinalizedEvent.params.bridgedAmount.toString(), + ) + + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "depositorFee", + depositFinalizedEvent.params.depositorFee.toString(), + ) + + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "amountToDeposit", + depositFinalizedEvent.params.bridgedAmount + .minus(depositFinalizedEvent.params.depositorFee) + .toString(), + ) }) test("Event entity has proper fields", () => { From 1b4812527e544cc5f99d30ecd10f001da7b3c21a Mon Sep 17 00:00:00 2001 From: ioay Date: Thu, 25 Apr 2024 23:18:51 +0200 Subject: [PATCH 19/28] Readme adjustment --- subgraph/README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/subgraph/README.md b/subgraph/README.md index 6e768a028..28d373e25 100644 --- a/subgraph/README.md +++ b/subgraph/README.md @@ -91,7 +91,7 @@ Note: use it only if your subgraph is not created in the local Graph node. 4. Once your subgraph has been created in Subgraph Studio you can initialize the subgraph code using this command: ``` - graph init --studio + graph init --studio ``` The value can be found on your subgraph details page in Subgraph Studio @@ -100,7 +100,7 @@ Note: use it only if your subgraph is not created in the local Graph node. 5. Before being able to deploy your subgraph to Subgraph Studio, you need to login into your account within the CLI. ``` - graph auth --studio + graph auth --studio ``` The can be found on your "My Subgraphs" page or your subgraph details page. @@ -113,8 +113,4 @@ Note: use it only if your subgraph is not created in the local Graph node. After running this command, the CLI will ask for a version label, you can name it however you want, you can use labels such as 0.1 and 0.2 or use letters as well such as uniswap-v2-0.1. -7. More information about deploying your subgraph to Subgraph Studio: - - ``` - https://thegraph.com/docs/en/deploying/subgraph-studio/ - ``` +7. More information about deploying your subgraph to Subgraph Studio: https://thegraph.com/docs/en/deploying/subgraph-studio/ From 3e9d122dc75a256a9fc03cb4c28537e27b89b910 Mon Sep 17 00:00:00 2001 From: ioay Date: Thu, 25 Apr 2024 23:21:38 +0200 Subject: [PATCH 20/28] Added suffix to event entity id depending on type --- subgraph/src/bitcoin-depositor.ts | 8 ++++++-- subgraph/tests/bitcoin-depositor.test.ts | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index e31266ed6..5b4c5bc83 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -22,7 +22,9 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { depositEntity.depositOwner = depositOwnerEntity.id depositEntity.initialDepositAmount = event.params.initialAmount - const eventEntity = getOrCreateEvent(event.transaction.hash.toHexString()) + const eventEntity = getOrCreateEvent( + `${event.transaction.hash.toHexString()}_DepositInitialized`, + ) eventEntity.activity = depositEntity.id eventEntity.timestamp = event.block.timestamp @@ -51,7 +53,9 @@ export function handleDepositFinalized(event: DepositFinalizedEvent): void { ).toBigInt() } - const eventEntity = getOrCreateEvent(event.transaction.hash.toHexString()) + const eventEntity = getOrCreateEvent( + `${event.transaction.hash.toHexString()}_DepositFinalized`, + ) eventEntity.activity = depositEntity.id eventEntity.timestamp = event.block.timestamp diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index b5f1c703f..362aac9cf 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -80,7 +80,7 @@ describe("handleDepositInitialized", () => { }) test("Event entity has proper fields", () => { - const txId = depositInitializedEvent.transaction.hash.toHexString() + const txId = `${depositInitializedEvent.transaction.hash.toHexString()}_DepositInitialized` assert.fieldEquals( "Event", @@ -158,7 +158,7 @@ describe("handleDepositFinalized", () => { }) test("Event entity has proper fields", () => { - const txId = depositFinalizedEvent.transaction.hash.toHexString() + const txId = `${depositInitializedEvent.transaction.hash.toHexString()}_DepositFinalized` assert.fieldEquals( "Event", From 6949cf2031dc4a26ab1b016ad0d9740af9999a90 Mon Sep 17 00:00:00 2001 From: ioay Date: Thu, 25 Apr 2024 23:22:19 +0200 Subject: [PATCH 21/28] getOrCreateDeposit utils: param renamed to depositKey --- subgraph/src/utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subgraph/src/utils.ts b/subgraph/src/utils.ts index 1b1d8f430..2f3264b20 100644 --- a/subgraph/src/utils.ts +++ b/subgraph/src/utils.ts @@ -12,11 +12,11 @@ export function getOrCreateDepositOwner(depositOwnerId: Address): DepositOwner { return depositOwner } -export function getOrCreateDeposit(transactionId: string): Deposit { - let deposit = Deposit.load(transactionId) +export function getOrCreateDeposit(depositKey: string): Deposit { + let deposit = Deposit.load(depositKey) if (!deposit) { - deposit = new Deposit(transactionId) + deposit = new Deposit(depositKey) } return deposit From b97b682b3d00c0f94200b322ed51b021d8d376e4 Mon Sep 17 00:00:00 2001 From: ioay Date: Thu, 25 Apr 2024 23:26:16 +0200 Subject: [PATCH 22/28] handleDepositFinalized - test update --- subgraph/tests/bitcoin-depositor.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 362aac9cf..6c187738c 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -115,7 +115,7 @@ describe("handleDepositFinalized", () => { }) test("Event entity should exist", () => { - assert.entityCount("Event", 1) + assert.entityCount("Event", 2) }) test("Deposit entity has proper fields", () => { From 8197d981251f5f8f880266d403505185296c5ee4 Mon Sep 17 00:00:00 2001 From: ioay Date: Sun, 28 Apr 2024 14:19:40 +0200 Subject: [PATCH 23/28] Changed referral type to Int --- subgraph/schema.graphql | 2 +- subgraph/src/bitcoin-depositor.ts | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index c4e0d1cf6..1a991e608 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -24,7 +24,7 @@ type Deposit implements ActivityData @entity { bridgedAmount: BigInt depositorFee: BigInt amountToDeposit: BigInt - referral: BigInt + referral: Int bitcoinTransactionId: String } diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 5b4c5bc83..676c887d9 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -1,5 +1,3 @@ -import { ethereum } from "@graphprotocol/graph-ts" - import { DepositInitialized as DepositInitializedEvent, DepositFinalized as DepositFinalizedEvent, @@ -47,11 +45,7 @@ export function handleDepositFinalized(event: DepositFinalizedEvent): void { depositEntity.amountToDeposit = event.params.bridgedAmount.minus( event.params.depositorFee, ) - if (event.params.referral) { - depositEntity.referral = ethereum.Value.fromI32( - event.params.referral, - ).toBigInt() - } + depositEntity.referral = event.params.referral const eventEntity = getOrCreateEvent( `${event.transaction.hash.toHexString()}_DepositFinalized`, From caf046236d1cc4d19b1c3e0b79d39a1abaf297cf Mon Sep 17 00:00:00 2001 From: ioay Date: Sun, 28 Apr 2024 14:25:42 +0200 Subject: [PATCH 24/28] Added receipt fot the DepositFinalized event --- subgraph/subgraph.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 18414c988..96ba12d8e 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -29,4 +29,5 @@ dataSources: receipt: true - event: DepositFinalized(indexed uint256,indexed address,indexed uint16,uint256,uint256,uint256) handler: handleDepositFinalized + receipt: true file: ./src/bitcoin-depositor.ts From ea18261607ce087fbfe5af77e1984b7732a800db Mon Sep 17 00:00:00 2001 From: ioay Date: Sun, 28 Apr 2024 15:33:17 +0200 Subject: [PATCH 25/28] Adjustment tests for initialize & finalized deposit events --- subgraph/src/bitcoin-depositor.ts | 38 +++++----- subgraph/tests/bitcoin-depositor.test.ts | 96 +++++++++++++++++++++++- 2 files changed, 112 insertions(+), 22 deletions(-) diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 676c887d9..230ee0ad4 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -36,25 +36,23 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { export function handleDepositFinalized(event: DepositFinalizedEvent): void { const depositEntity = Deposit.load(event.params.depositKey.toHexString()) - if (!depositEntity) { - throw new Error("Deposit entity does not exist") + if (depositEntity) { + depositEntity.bridgedAmount = event.params.bridgedAmount + depositEntity.depositorFee = event.params.depositorFee + depositEntity.amountToDeposit = event.params.bridgedAmount.minus( + event.params.depositorFee, + ) + depositEntity.referral = event.params.referral + + const eventEntity = getOrCreateEvent( + `${event.transaction.hash.toHexString()}_DepositFinalized`, + ) + + eventEntity.activity = depositEntity.id + eventEntity.timestamp = event.block.timestamp + eventEntity.type = "Finalized" + + depositEntity.save() + eventEntity.save() } - - depositEntity.bridgedAmount = event.params.bridgedAmount - depositEntity.depositorFee = event.params.depositorFee - depositEntity.amountToDeposit = event.params.bridgedAmount.minus( - event.params.depositorFee, - ) - depositEntity.referral = event.params.referral - - const eventEntity = getOrCreateEvent( - `${event.transaction.hash.toHexString()}_DepositFinalized`, - ) - - eventEntity.activity = depositEntity.id - eventEntity.timestamp = event.block.timestamp - eventEntity.type = "Finalized" - - depositEntity.save() - eventEntity.save() } diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 6c187738c..e637bd564 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -5,7 +5,10 @@ import { clearStore, beforeAll, afterAll, + beforeEach, + afterEach, } from "matchstick-as/assembly/index" + import { BigInt, Address } from "@graphprotocol/graph-ts" import { createDepositInitializedEvent, @@ -17,6 +20,7 @@ import { } from "../src/bitcoin-depositor" const depositKey = BigInt.fromI32(234) +const nextDepositKey = BigInt.fromI32(345) const caller = Address.fromString("0x0000000000000000000000000000000000000001") const depositOwner = Address.fromString( "0x0000000000000000000000000000000000000001", @@ -33,6 +37,13 @@ const depositInitializedEvent = createDepositInitializedEvent( initialAmount, ) +const nextDepositInitializedEvent = createDepositInitializedEvent( + nextDepositKey, + caller, + depositOwner, + initialAmount, +) + const depositFinalizedEvent = createDepositFinalizedEvent( depositKey, caller, @@ -100,16 +111,89 @@ describe("handleDepositInitialized", () => { }) }) -describe("handleDepositFinalized", () => { +describe("handleDepositInitialized if depositOwner already exists", () => { beforeAll(() => { handleDepositInitialized(depositInitializedEvent) - handleDepositFinalized(depositFinalizedEvent) + handleDepositInitialized(nextDepositInitializedEvent) }) afterAll(() => { clearStore() }) + test("should create DepositOwner entity", () => { + assert.entityCount("DepositOwner", 1) + }) + + test("should create Deposit entity", () => { + assert.entityCount("Deposit", 2) + }) + + test("should create Event entity", () => { + assert.entityCount("Event", 1) + }) + + test("Deposit entity has proper fields", () => { + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "initialDepositAmount", + depositInitializedEvent.params.initialAmount.toString(), + ) + + assert.fieldEquals( + "Deposit", + nextDepositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + nextDepositInitializedEvent.params.depositKey.toHexString(), + "initialDepositAmount", + nextDepositInitializedEvent.params.initialAmount.toString(), + ) + }) + + test("Event entity has proper fields", () => { + const nextTxId = `${nextDepositInitializedEvent.transaction.hash.toHexString()}_DepositInitialized` + + assert.fieldEquals( + "Event", + nextTxId, + "activity", + nextDepositInitializedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "Event", + nextTxId, + "timestamp", + nextDepositInitializedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals("Event", nextTxId, "type", "Initialized") + }) +}) + +describe("handleDepositFinalized", () => { + beforeEach(() => { + handleDepositInitialized(depositInitializedEvent) + handleDepositFinalized(depositFinalizedEvent) + }) + + afterEach(() => { + clearStore() + }) + test("Deposit entity should exist", () => { assert.entityCount("Deposit", 1) }) @@ -176,4 +260,12 @@ describe("handleDepositFinalized", () => { assert.fieldEquals("Event", txId, "type", "Finalized") }) + + test("doesn't create entities when depositEntity not exist", () => { + clearStore() + handleDepositFinalized(depositFinalizedEvent) + assert.entityCount("Deposit", 0) + assert.entityCount("DepositOwner", 0) + assert.entityCount("Event", 0) + }) }) From 1f5e9f16fef712ffa4835098cb403249c2c54ec6 Mon Sep 17 00:00:00 2001 From: ioay Date: Mon, 29 Apr 2024 09:30:57 +0200 Subject: [PATCH 26/28] Wrapped describe block in tests --- subgraph/tests/bitcoin-depositor.test.ts | 252 ++++++++++++----------- 1 file changed, 127 insertions(+), 125 deletions(-) diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index e637bd564..27fc3d388 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -54,133 +54,135 @@ const depositFinalizedEvent = createDepositFinalizedEvent( ) describe("handleDepositInitialized", () => { - beforeAll(() => { - handleDepositInitialized(depositInitializedEvent) - }) - - afterAll(() => { - clearStore() - }) - - test("should create DepositOwner entity", () => { - assert.entityCount("DepositOwner", 1) + describe("when the deposit owner doesn't exist yet", () => { + beforeAll(() => { + handleDepositInitialized(depositInitializedEvent) + }) + + afterAll(() => { + clearStore() + }) + + test("should create DepositOwner entity", () => { + assert.entityCount("DepositOwner", 1) + }) + + test("should create Deposit entity", () => { + assert.entityCount("Deposit", 1) + }) + + test("should create Event entity", () => { + assert.entityCount("Event", 1) + }) + + test("Deposit entity has proper fields", () => { + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "initialDepositAmount", + depositInitializedEvent.params.initialAmount.toString(), + ) + }) + + test("Event entity has proper fields", () => { + const txId = `${depositInitializedEvent.transaction.hash.toHexString()}_DepositInitialized` + + assert.fieldEquals( + "Event", + txId, + "activity", + depositInitializedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "Event", + txId, + "timestamp", + depositInitializedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals("Event", txId, "type", "Initialized") + }) }) - test("should create Deposit entity", () => { - assert.entityCount("Deposit", 1) - }) - - test("should create Event entity", () => { - assert.entityCount("Event", 1) - }) - - test("Deposit entity has proper fields", () => { - assert.fieldEquals( - "Deposit", - depositInitializedEvent.params.depositKey.toHexString(), - "depositOwner", - depositOwner.toHexString(), - ) - - assert.fieldEquals( - "Deposit", - depositInitializedEvent.params.depositKey.toHexString(), - "initialDepositAmount", - depositInitializedEvent.params.initialAmount.toString(), - ) - }) - - test("Event entity has proper fields", () => { - const txId = `${depositInitializedEvent.transaction.hash.toHexString()}_DepositInitialized` - - assert.fieldEquals( - "Event", - txId, - "activity", - depositInitializedEvent.params.depositKey.toHexString(), - ) - - assert.fieldEquals( - "Event", - txId, - "timestamp", - depositInitializedEvent.block.timestamp.toString(), - ) - - assert.fieldEquals("Event", txId, "type", "Initialized") - }) -}) - -describe("handleDepositInitialized if depositOwner already exists", () => { - beforeAll(() => { - handleDepositInitialized(depositInitializedEvent) - handleDepositInitialized(nextDepositInitializedEvent) - }) - - afterAll(() => { - clearStore() - }) - - test("should create DepositOwner entity", () => { - assert.entityCount("DepositOwner", 1) - }) - - test("should create Deposit entity", () => { - assert.entityCount("Deposit", 2) - }) - - test("should create Event entity", () => { - assert.entityCount("Event", 1) - }) - - test("Deposit entity has proper fields", () => { - assert.fieldEquals( - "Deposit", - depositInitializedEvent.params.depositKey.toHexString(), - "depositOwner", - depositOwner.toHexString(), - ) - - assert.fieldEquals( - "Deposit", - depositInitializedEvent.params.depositKey.toHexString(), - "initialDepositAmount", - depositInitializedEvent.params.initialAmount.toString(), - ) - - assert.fieldEquals( - "Deposit", - nextDepositInitializedEvent.params.depositKey.toHexString(), - "depositOwner", - depositOwner.toHexString(), - ) - - assert.fieldEquals( - "Deposit", - nextDepositInitializedEvent.params.depositKey.toHexString(), - "initialDepositAmount", - nextDepositInitializedEvent.params.initialAmount.toString(), - ) - }) - - test("Event entity has proper fields", () => { - const nextTxId = `${nextDepositInitializedEvent.transaction.hash.toHexString()}_DepositInitialized` - - assert.fieldEquals( - "Event", - nextTxId, - "activity", - nextDepositInitializedEvent.params.depositKey.toHexString(), - ) - - assert.fieldEquals( - "Event", - nextTxId, - "timestamp", - nextDepositInitializedEvent.block.timestamp.toString(), - ) - - assert.fieldEquals("Event", nextTxId, "type", "Initialized") + describe("when the deposit owner already exists", () => { + beforeAll(() => { + handleDepositInitialized(depositInitializedEvent) + handleDepositInitialized(nextDepositInitializedEvent) + }) + + afterAll(() => { + clearStore() + }) + + test("should create DepositOwner entity", () => { + assert.entityCount("DepositOwner", 1) + }) + + test("should create Deposit entity", () => { + assert.entityCount("Deposit", 2) + }) + + test("should create Event entity", () => { + assert.entityCount("Event", 1) + }) + + test("Deposit entity has proper fields", () => { + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + depositInitializedEvent.params.depositKey.toHexString(), + "initialDepositAmount", + depositInitializedEvent.params.initialAmount.toString(), + ) + + assert.fieldEquals( + "Deposit", + nextDepositInitializedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) + + assert.fieldEquals( + "Deposit", + nextDepositInitializedEvent.params.depositKey.toHexString(), + "initialDepositAmount", + nextDepositInitializedEvent.params.initialAmount.toString(), + ) + }) + + test("Event entity has proper fields", () => { + const nextTxId = `${nextDepositInitializedEvent.transaction.hash.toHexString()}_DepositInitialized` + + assert.fieldEquals( + "Event", + nextTxId, + "activity", + nextDepositInitializedEvent.params.depositKey.toHexString(), + ) + + assert.fieldEquals( + "Event", + nextTxId, + "timestamp", + nextDepositInitializedEvent.block.timestamp.toString(), + ) + + assert.fieldEquals("Event", nextTxId, "type", "Initialized") + }) }) }) From db323cc59912c29613fe89b19488405559f5f7fb Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Tue, 30 Apr 2024 12:07:08 +0200 Subject: [PATCH 27/28] Update `handleDepositFinalized` handler Throw an error when the Deposit entity deosn't exist. We throw an error just to improve readability of the code. This should never happen because the graph indexes events chronologically and the deposit can only be finalized once it has been initialized. This case is possible when we set the wrong `startBlock` in manifest but we always set the `startBlock` to block where a given contract was deployed. Cover this case in unit tests. --- subgraph/src/bitcoin-depositor.ts | 44 ++++--- subgraph/tests/bitcoin-depositor.test.ts | 140 ++++++++++++----------- 2 files changed, 98 insertions(+), 86 deletions(-) diff --git a/subgraph/src/bitcoin-depositor.ts b/subgraph/src/bitcoin-depositor.ts index 230ee0ad4..957af9a2e 100644 --- a/subgraph/src/bitcoin-depositor.ts +++ b/subgraph/src/bitcoin-depositor.ts @@ -15,8 +15,9 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { event.params.depositKey.toHexString(), ) - // TODO: get the bitcoin transaction hash from this Ethereum transaction - // by finding the DepositRevealed event in logs from the tBTC-v2 Bridge contract. + // TODO: Get the bitcoin transaction hash from this Ethereum transaction + // by finding the `DepositRevealed` event in logs from the tBTC-v2 Bridge + // contract. depositEntity.depositOwner = depositOwnerEntity.id depositEntity.initialDepositAmount = event.params.initialAmount @@ -36,23 +37,30 @@ export function handleDepositInitialized(event: DepositInitializedEvent): void { export function handleDepositFinalized(event: DepositFinalizedEvent): void { const depositEntity = Deposit.load(event.params.depositKey.toHexString()) - if (depositEntity) { - depositEntity.bridgedAmount = event.params.bridgedAmount - depositEntity.depositorFee = event.params.depositorFee - depositEntity.amountToDeposit = event.params.bridgedAmount.minus( - event.params.depositorFee, - ) - depositEntity.referral = event.params.referral + // We throw an error just to improve readability of the code. This should + // never happen because the graph indexes events chronologically and the + // deposit can only be finalized once it has been initialized. This case is + // possible when we set the wrong `startBlock` in manifest but we always set + // the `startBlock` to block where a given contract was deployed. + if (!depositEntity) { + throw new Error("Deposit entity does not exist") + } - const eventEntity = getOrCreateEvent( - `${event.transaction.hash.toHexString()}_DepositFinalized`, - ) + depositEntity.bridgedAmount = event.params.bridgedAmount + depositEntity.depositorFee = event.params.depositorFee + depositEntity.amountToDeposit = event.params.bridgedAmount.minus( + event.params.depositorFee, + ) + depositEntity.referral = event.params.referral - eventEntity.activity = depositEntity.id - eventEntity.timestamp = event.block.timestamp - eventEntity.type = "Finalized" + const eventEntity = getOrCreateEvent( + `${event.transaction.hash.toHexString()}_DepositFinalized`, + ) - depositEntity.save() - eventEntity.save() - } + eventEntity.activity = depositEntity.id + eventEntity.timestamp = event.block.timestamp + eventEntity.type = "Finalized" + + depositEntity.save() + eventEntity.save() } diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index 27fc3d388..a8dc5c0d1 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -187,87 +187,91 @@ describe("handleDepositInitialized", () => { }) describe("handleDepositFinalized", () => { - beforeEach(() => { - handleDepositInitialized(depositInitializedEvent) - handleDepositFinalized(depositFinalizedEvent) - }) + describe("when deposit entity already exist", () => { + beforeEach(() => { + handleDepositInitialized(depositInitializedEvent) + handleDepositFinalized(depositFinalizedEvent) + }) - afterEach(() => { - clearStore() - }) + afterEach(() => { + clearStore() + }) - test("Deposit entity should exist", () => { - assert.entityCount("Deposit", 1) - }) + test("Deposit entity should exist", () => { + assert.entityCount("Deposit", 1) + }) - test("Event entity should exist", () => { - assert.entityCount("Event", 2) - }) + test("Event entity should exist", () => { + assert.entityCount("Event", 2) + }) - test("Deposit entity has proper fields", () => { - assert.fieldEquals( - "Deposit", - depositFinalizedEvent.params.depositKey.toHexString(), - "depositOwner", - depositOwner.toHexString(), - ) + test("Deposit entity has proper fields", () => { + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "depositOwner", + depositOwner.toHexString(), + ) - assert.fieldEquals( - "Deposit", - depositFinalizedEvent.params.depositKey.toHexString(), - "initialDepositAmount", - depositFinalizedEvent.params.initialAmount.toString(), - ) + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "initialDepositAmount", + depositFinalizedEvent.params.initialAmount.toString(), + ) - assert.fieldEquals( - "Deposit", - depositFinalizedEvent.params.depositKey.toHexString(), - "bridgedAmount", - depositFinalizedEvent.params.bridgedAmount.toString(), - ) + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "bridgedAmount", + depositFinalizedEvent.params.bridgedAmount.toString(), + ) - assert.fieldEquals( - "Deposit", - depositFinalizedEvent.params.depositKey.toHexString(), - "depositorFee", - depositFinalizedEvent.params.depositorFee.toString(), - ) + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "depositorFee", + depositFinalizedEvent.params.depositorFee.toString(), + ) - assert.fieldEquals( - "Deposit", - depositFinalizedEvent.params.depositKey.toHexString(), - "amountToDeposit", - depositFinalizedEvent.params.bridgedAmount - .minus(depositFinalizedEvent.params.depositorFee) - .toString(), - ) - }) + assert.fieldEquals( + "Deposit", + depositFinalizedEvent.params.depositKey.toHexString(), + "amountToDeposit", + depositFinalizedEvent.params.bridgedAmount + .minus(depositFinalizedEvent.params.depositorFee) + .toString(), + ) + }) - test("Event entity has proper fields", () => { - const txId = `${depositInitializedEvent.transaction.hash.toHexString()}_DepositFinalized` + test("Event entity has proper fields", () => { + const txId = `${depositInitializedEvent.transaction.hash.toHexString()}_DepositFinalized` - assert.fieldEquals( - "Event", - txId, - "activity", - depositFinalizedEvent.params.depositKey.toHexString(), - ) + assert.fieldEquals( + "Event", + txId, + "activity", + depositFinalizedEvent.params.depositKey.toHexString(), + ) - assert.fieldEquals( - "Event", - txId, - "timestamp", - depositFinalizedEvent.block.timestamp.toString(), - ) + assert.fieldEquals( + "Event", + txId, + "timestamp", + depositFinalizedEvent.block.timestamp.toString(), + ) - assert.fieldEquals("Event", txId, "type", "Finalized") + assert.fieldEquals("Event", txId, "type", "Finalized") + }) }) - test("doesn't create entities when depositEntity not exist", () => { - clearStore() - handleDepositFinalized(depositFinalizedEvent) - assert.entityCount("Deposit", 0) - assert.entityCount("DepositOwner", 0) - assert.entityCount("Event", 0) + describe("when the Deposit entity does not exist", () => { + test( + "should throw an error", + () => { + handleDepositFinalized(depositFinalizedEvent) + }, + true, + ) }) }) From 7d076e40c746c823a6ba6f000a2c1a48b52f7d99 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Tue, 30 Apr 2024 12:20:20 +0200 Subject: [PATCH 28/28] Update the `referral` type in unit tests We changed the type of the `referral` field to `Int` in 8197d98 so just for consistency we update it in tests as well. --- subgraph/tests/bitcoin-depositor-utils.ts | 4 ++-- subgraph/tests/bitcoin-depositor.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subgraph/tests/bitcoin-depositor-utils.ts b/subgraph/tests/bitcoin-depositor-utils.ts index 7d3eb01be..cb809517c 100644 --- a/subgraph/tests/bitcoin-depositor-utils.ts +++ b/subgraph/tests/bitcoin-depositor-utils.ts @@ -45,7 +45,7 @@ export function createDepositInitializedEvent( export function createDepositFinalizedEvent( depositKey: BigInt, caller: Address, - referral: BigInt, + referral: i16, initialAmount: BigInt, bridgedAmount: BigInt, depositorFee: BigInt, @@ -65,7 +65,7 @@ export function createDepositFinalizedEvent( const referralParam = new ethereum.EventParam( "referral", - ethereum.Value.fromUnsignedBigInt(referral), + ethereum.Value.fromI32(referral), ) const initialAmountParam = new ethereum.EventParam( diff --git a/subgraph/tests/bitcoin-depositor.test.ts b/subgraph/tests/bitcoin-depositor.test.ts index a8dc5c0d1..b9ac5d333 100644 --- a/subgraph/tests/bitcoin-depositor.test.ts +++ b/subgraph/tests/bitcoin-depositor.test.ts @@ -25,7 +25,7 @@ const caller = Address.fromString("0x0000000000000000000000000000000000000001") const depositOwner = Address.fromString( "0x0000000000000000000000000000000000000001", ) -const referral = BigInt.fromI32(234) +const referral: i16 = 234 const initialAmount = BigInt.fromI32(234) const bridgedAmount = BigInt.fromI32(234) const depositorFee = BigInt.fromI32(234)