Skip to content

Commit

Permalink
[sdk-core][sdk-redux] add GDA pool subgraph entity queries (#1840)
Browse files Browse the repository at this point in the history
* add gda pool subgraph entity queries

* improve infinity paging api

* add some robustness to transaction serialization

* reduce tx tracking timeout from 10 mins to 3 mins

* remove unnecessary toLowerCase

* changeset

* [SUBGRAPH] [BUG] PoolMember not getting updated when the member units change (#1877)

* add a test starter

* add the test

* fixes

* improve test

* update dev container for matchstick compatibility

* implement the fix

* clean-up

* add elaborate test for pool  total amount received

* fix test issue

* add even more comments

* fix test name

* ignore test

---------

Co-authored-by: 0xdavinchee <[email protected]>

* [SUBGRAPH] approval mapping (#1878)

* approval mapping

* missing addresses

* missing addresses cont.

* no-op, trigger build

* fix tests

---------

Co-authored-by: Kaspar Kallas <[email protected]>

* [subgraph] Fix Correctness of GDA Entities (#1890)



---------

Co-authored-by: 0xdavinchee <[email protected]>

* add getTotalAmountReceivedByPoolMember to sdk-core (#1902)

* update entities based on new subgraph

* map name, isnfttransfer, isnftapproval

* fix merge issue

* remove unnecessary files

* update gitignore

---------

Co-authored-by: 0xdavinchee <[email protected]>
  • Loading branch information
kasparkallas and 0xdavinchee authored Mar 26, 2024
1 parent 24a549c commit d58178f
Show file tree
Hide file tree
Showing 26 changed files with 810 additions and 428 deletions.
8 changes: 8 additions & 0 deletions packages/sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Added

- Added `getTotalAmountReceivedByMember`

### Changed

- Map the name from subgraph to an unknown event, instead of "\_Unknown".
- Don't lock metadata version to a specific version, use semver (^).
- Allow infinite pagination with 'skip: 0' value (previously had to be undefined)
- Add subgraphs queries for Pools, PoolMembers and PoolDistributors
- Map `isNFTApproval` and `isNFTTransfer` onto events

## [0.6.12] - 2023-10-23

Expand Down
26 changes: 26 additions & 0 deletions packages/sdk-core/src/SuperfluidPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
GetClaimableParams,
GetDisconnectedBalanceParams,
GetMemberFlowRateParams,
GetTotalAmountReceivedByMemberParams,
GetUnitsParams,
SuperfluidPoolDecreaseAllowanceParams,
SuperfluidPoolIncreaseAllowanceParams,
Expand Down Expand Up @@ -236,6 +237,31 @@ export default class SuperfluidPoolClass {
}
};

/**
* Retrieves the flow rate for a specific member.
* @param member The member's address.
* @param providerOrSigner A provider or signer object
* @returns The total amount received by the member.
*/
getTotalAmountReceivedByMember = async (
params: GetTotalAmountReceivedByMemberParams
): Promise<string> => {
try {
return (
await this.contract
.connect(params.providerOrSigner)
.getTotalAmountReceivedByMember(params.member)
).toString();
} catch (err) {
throw new SFError({
type: "SUPERFLUID_POOL_READ",
message:
"There was an error getting the total amount received by member.",
cause: err,
});
}
};

/**
* Retrieves the claimable amount for a specific member and time.
* @param member The member's address.
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk-core/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export interface TransferEvent extends EventBase {
to: string;
value: string;
token: string;
isNFTTransfer: boolean;
}

export interface AgreementClassRegisteredEvent extends EventBase {
Expand Down Expand Up @@ -468,6 +469,7 @@ export interface MemberUnitsUpdatedEvent extends EventBase {
}
export interface ApprovalEvent extends EventBase {
name: "ApprovalEvent";
isNFTApproval: boolean;
}
export interface ApprovalForAllEvent extends EventBase {
name: "ApprovalForAllEvent";
Expand Down
5 changes: 4 additions & 1 deletion packages/sdk-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ export * from "./subgraph/entities/streamPeriod/streamPeriod";
export * from "./subgraph/entities/token/token";
export * from "./subgraph/entities/tokenStatistic/tokenStatistic";
export * from "./subgraph/entities/tokenStatisticLog/tokenStatisticLog";
export * from "./subgraph/entities/flowOperator/flowOperators";
export * from "./subgraph/entities/flowOperator/flowOperator";
export * from "./subgraph/entities/pool/pool";
export * from "./subgraph/entities/poolMember/poolMember";
export * from "./subgraph/entities/poolDistributor/poolDistributor";

export * from "./subgraph/events/events";
export * from "./subgraph/events/flowUpdatedEvent";
Expand Down
5 changes: 5 additions & 0 deletions packages/sdk-core/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,11 @@ export interface GetMemberFlowRateParams {
readonly providerOrSigner: ethers.providers.Provider | ethers.Signer;
}

export interface GetTotalAmountReceivedByMemberParams {
readonly member: string;
readonly providerOrSigner: ethers.providers.Provider | ethers.Signer;
}

export interface ClaimAllForMemberParams {
readonly member: string;
readonly signer: ethers.Signer;
Expand Down
5 changes: 2 additions & 3 deletions packages/sdk-core/src/mapGetAllEventsQueryEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ export const mapGetAllEventsQueryEvents = (
to: x.to.id,
token: x.token,
value: x.value,
isNFTTransfer: x.isNFTTransfer,
});
case "TrustedForwarderChangedEvent":
return typeGuard<events.TrustedForwarderChangedEvent>({
Expand Down Expand Up @@ -760,6 +761,7 @@ export const mapGetAllEventsQueryEvents = (
order: Number(x.order),
timestamp: Number(x.timestamp),
logIndex: Number(x.logIndex),
isNFTApproval: x.isNFTApproval,
});
case "ApprovalForAllEvent":
return typeGuard<events.ApprovalForAllEvent>({
Expand All @@ -786,9 +788,6 @@ export const mapGetAllEventsQueryEvents = (
default:
// eslint-disable-next-line no-case-declarations
const eventBase = x as events.EventBase;
console.warn(
`An unknown event [${eventBase.name}] was detected which couldn't be properly mapped. Please update to the latest version of @superfluid-finance/sdk-core.`
);
return typeGuard<events.UnknownEvent>({
// force casted as empty string for the type system
name: eventBase.name as "",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk-core/src/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export function isLastIdPaging(paging?: Paging): paging is LastIdPaging {
export function isAllPaging(paging?: Paging): paging is AllPaging {
return (
paging !== undefined &&
paging.skip === undefined &&
!paging.skip &&
paging.lastId === undefined &&
paging.take === Infinity
);
Expand Down
122 changes: 122 additions & 0 deletions packages/sdk-core/src/subgraph/entities/pool/pool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import {
Address,
BigNumber,
BlockNumber,
Timestamp,
} from "../../mappedSubgraphTypes";
import { Pool_Filter, Pool_OrderBy } from "../../schema.generated";
import {
RelevantAddressesIntermediate,
SubgraphListQuery,
SubgraphQueryHandler,
} from "../../subgraphQueryHandler";

import {
GetPoolQuery,
PoolsDocument,
PoolsQuery,
PoolsQueryVariables,
} from "./pools.generated";

export type PoolListQuery = SubgraphListQuery<Pool_Filter, Pool_OrderBy>;

export interface Pool {
id: Address;
createdAtTimestamp: Timestamp;
createdAtBlockNumber: BlockNumber;
updatedAtTimestamp: Timestamp;
updatedAtBlockNumber: BlockNumber;
totalAmountInstantlyDistributedUntilUpdatedAt: BigNumber;
totalAmountFlowedDistributedUntilUpdatedAt: BigNumber;
totalAmountDistributedUntilUpdatedAt: BigNumber;
totalFlowAdjustmentAmountDistributedUntilUpdatedAt: BigNumber;
totalUnits: BigNumber;
totalConnectedUnits: BigNumber;
totalDisconnectedUnits: BigNumber;
perUnitSettledValue: BigNumber;
perUnitFlowRate: BigNumber;
/**
* A member is any account which has more than 0 units in the pool.
*/
totalMembers: number;
/**
* A connected member is any account which has more than 0 units in the pool and is connected.
*/
totalConnectedMembers: number;
/**
* A disconnected member is any account which has more than 0 units in the pool and is not connected.
*/
totalDisconnectedMembers: number;
adjustmentFlowRate: BigNumber;
flowRate: BigNumber;
totalBuffer: BigNumber;
token: Address;
admin: Address;
}

export type SubgraphPool = NonNullable<Required<GetPoolQuery>["pool"]>;

export const mapSubgraphGDAPool = (x: SubgraphPool): Pool => {
const mappedPool = {
...x,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
totalAmountInstantlyDistributedUntilUpdatedAt:
x.totalAmountInstantlyDistributedUntilUpdatedAt,
totalAmountFlowedDistributedUntilUpdatedAt:
x.totalAmountFlowedDistributedUntilUpdatedAt,
totalAmountDistributedUntilUpdatedAt:
x.totalAmountDistributedUntilUpdatedAt,
admin: x.admin.id,
token: x.token.id,
};

return mappedPool;
};

export class PoolQueryHandler extends SubgraphQueryHandler<
Pool,
PoolListQuery,
PoolsQuery,
PoolsQueryVariables
> {
getAddressFieldKeysFromFilter = (): {
accountKeys: (keyof Pool_Filter)[];
tokenKeys: (keyof Pool_Filter)[];
} => ({
accountKeys: ["admin", "id"],
tokenKeys: ["token"],
});

getRelevantAddressesFromResultCore = (
result: Pool
): RelevantAddressesIntermediate => ({
tokens: [result.token],
accounts: [result.admin, result.id],
});

mapFromSubgraphResponse = (response: PoolsQuery): Pool[] =>
response.pools.map((x) => ({
...x,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
totalAmountInstantlyDistributedUntilUpdatedAt:
x.totalAmountInstantlyDistributedUntilUpdatedAt,
totalAmountFlowedDistributedUntilUpdatedAt:
x.totalAmountFlowedDistributedUntilUpdatedAt,
totalAmountDistributedUntilUpdatedAt:
x.totalAmountDistributedUntilUpdatedAt,
totalFlowAdjustmentAmountDistributedUntilUpdatedAt:
x.totalFlowAdjustmentAmountDistributedUntilUpdatedAt,
perUnitFlowRate: x.perUnitFlowRate,
perUnitSettledValue: x.perUnitSettledValue,
admin: x.admin.id,
token: x.token.id,
}));

requestDocument = PoolsDocument;
}
54 changes: 54 additions & 0 deletions packages/sdk-core/src/subgraph/entities/pool/pools.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
query getPool($id: ID!) {
pool(id: $id) {
...PoolPart
}
}

query pools(
$first: Int = 10
$orderBy: Pool_orderBy = id
$orderDirection: OrderDirection = asc
$skip: Int = 0
$where: Pool_filter = {}
$block: Block_height
) {
pools(
first: $first
orderBy: $orderBy
orderDirection: $orderDirection
skip: $skip
where: $where
block: $block
) {
...PoolPart
}
}

fragment PoolPart on Pool {
id
createdAtTimestamp
createdAtBlockNumber
updatedAtTimestamp
updatedAtBlockNumber
admin {
id
}
token {
id
}
totalMembers
totalUnits
totalConnectedMembers
totalConnectedUnits
totalDisconnectedMembers
totalDisconnectedUnits
totalAmountInstantlyDistributedUntilUpdatedAt
flowRate
perUnitSettledValue
perUnitFlowRate
totalBuffer
totalAmountFlowedDistributedUntilUpdatedAt
totalAmountDistributedUntilUpdatedAt
adjustmentFlowRate
totalFlowAdjustmentAmountDistributedUntilUpdatedAt
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {
Address,
BigNumber,
BlockNumber,
SubgraphId,
Timestamp,
} from "../../mappedSubgraphTypes";
import {
PoolDistributor_Filter,
PoolDistributor_OrderBy,
} from "../../schema.generated";
import {
RelevantAddressesIntermediate,
SubgraphListQuery,
SubgraphQueryHandler,
} from "../../subgraphQueryHandler";

import {
PoolDistributorsDocument,
PoolDistributorsQuery,
PoolDistributorsQueryVariables,
} from "./poolDistributors.generated";

export interface PoolDistributor {
id: SubgraphId;
createdAtTimestamp: Timestamp;
createdAtBlockNumber: BlockNumber;
updatedAtTimestamp: Timestamp;
updatedAtBlockNumber: BlockNumber;
totalBuffer: BigNumber;
totalAmountInstantlyDistributedUntilUpdatedAt: BigNumber;
totalAmountFlowedDistributedUntilUpdatedAt: BigNumber;
totalAmountDistributedUntilUpdatedAt: BigNumber;
flowRate: BigNumber;
account: Address;
pool: Address;
token: Address;
}

export type PoolDistributorsListQuery = SubgraphListQuery<
PoolDistributor_Filter,
PoolDistributor_OrderBy
>;

export class PoolDistributorQueryHandler extends SubgraphQueryHandler<
PoolDistributor,
PoolDistributorsListQuery,
PoolDistributorsQuery,
PoolDistributorsQueryVariables
> {
getAddressFieldKeysFromFilter = (): {
accountKeys: (keyof PoolDistributor_Filter)[];
tokenKeys: (keyof PoolDistributor_Filter)[];
} => ({
accountKeys: ["account", "pool"],
tokenKeys: [],
});

getRelevantAddressesFromResultCore = (
result: PoolDistributor
): RelevantAddressesIntermediate => ({
tokens: [result.token],
accounts: [result.account, result.pool],
});

mapFromSubgraphResponse = (
response: PoolDistributorsQuery
): PoolDistributor[] =>
response.poolDistributors.map((x) => ({
...x,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
pool: x.pool.id,
token: x.pool.token.id,
account: x.account.id,
}));

requestDocument = PoolDistributorsDocument;
}
Loading

0 comments on commit d58178f

Please sign in to comment.