Conversation
There was a problem hiding this comment.
Hey - I've found 9 security issues, 5 other issues, and left some high level feedback:
Security issues:
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
- Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (link)
General comments:
- The
StreamingTestPagecomponent has grown very large (~800 lines) and mixes networking logic, state management, and complex UI in a single file; consider extracting sections (e.g., create/update/delete stream panels, pool section, SUP reserves section) into smaller presentational/components to improve readability and future maintenance. - In the React hooks (
useCreateStream,useUpdateStream,useDeleteStream,useConnectToPool, etc.) a new SDK instance is constructed for every mutation; if these hooks are used frequently, consider memoizing or centralizing SDK construction (e.g., via a context or a small factory) to avoid unnecessary re-instantiation.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `StreamingTestPage` component has grown very large (~800 lines) and mixes networking logic, state management, and complex UI in a single file; consider extracting sections (e.g., create/update/delete stream panels, pool section, SUP reserves section) into smaller presentational/components to improve readability and future maintenance.
- In the React hooks (`useCreateStream`, `useUpdateStream`, `useDeleteStream`, `useConnectToPool`, etc.) a new SDK instance is constructed for every mutation; if these hooks are used frequently, consider memoizing or centralizing SDK construction (e.g., via a context or a small factory) to avoid unnecessary re-instantiation.
## Individual Comments
### Comment 1
<location> `packages/streaming-sdk/src/constants.ts:42-43` </location>
<code_context>
+ [SupportedChains.BASE]: "https://base-mainnet.subgraph.x.superfluid.dev/",
+ [SupportedChains.BASE_SEPOLIA]:
+ "https://base-sepolia.subgraph.x.superfluid.dev/",
+ supReserve:
+ "https://thegraph.com/explorer/subgraphs/6dRuPxMvaJAp32hvcTsYbAya69A4t1KUHh2EnV3YQeXU",
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** SUP reserve subgraph URL points to the Graph Explorer page, not the API endpoint
Because this constant is used by `GraphQLClient` in `querySUPReserves`, requests will fail against the HTML Explorer page. Please update `SUBGRAPH_URLS.supReserve` to the underlying GraphQL API endpoint (e.g., `https://api.thegraph.com/subgraphs/...`) so `SubgraphClient` can query SUP reserve data correctly.
</issue_to_address>
### Comment 2
<location> `packages/streaming-sdk/src/streaming-sdk.ts:79-93` </location>
<code_context>
+ )
+ }
+
+ async updateStream(params: UpdateStreamParams): Promise<Hash> {
+ const { receiver, token, newFlowRate, userData = "0x", onHash } = params
+
+ const account = await this.getAccount()
+
+ return this.submitAndWait(
+ {
+ address: CFA_FORWARDER_ADDRESSES[this.chainId],
+ abi: cfaForwarderAbi,
+ functionName: "updateFlow",
+ args: [token, account, receiver, newFlowRate, userData],
+ },
+ onHash,
+ )
+ }
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Inconsistent validation of flow rates between createStream and updateStream
`createStream` validates that `flowRate` is positive, but `updateStream` passes `newFlowRate` through unvalidated. If the protocol requires positive flow rates for active streams, this mismatch could cause unexpected reverts or inconsistent behavior. Please either align the validation behavior in `updateStream` or document why zero/negative values are acceptable here.
```suggestion
async updateStream(params: UpdateStreamParams): Promise<Hash> {
const { receiver, token, newFlowRate, userData = "0x", onHash } = params
if (BigInt(newFlowRate) <= 0n) {
throw new Error("newFlowRate must be a positive non-zero value")
}
const account = await this.getAccount()
return this.submitAndWait(
{
address: CFA_FORWARDER_ADDRESSES[this.chainId],
abi: cfaForwarderAbi,
functionName: "updateFlow",
args: [token, account, receiver, newFlowRate, userData],
},
onHash,
)
}
```
</issue_to_address>
### Comment 3
<location> `packages/react-hooks/src/streaming/useGDAPools.ts:13-16` </location>
<code_context>
+/**
+ * Hook for fetching GDA distribution pools
+ */
+export function useGDAPools({
+ environment = "production",
+ enabled = true,
+}: UseGDAPoolsParams = {}) {
+ const publicClient = usePublicClient()
+
</code_context>
<issue_to_address>
**suggestion:** Environment parameter in GDA hooks is unused by the underlying SDK
`useGDAPools` and `usePoolMemberships` accept an `environment` parameter and include it in the query key, but never pass it into `GdaSDK` (which only receives `publicClient`, `walletClient?`, `chainId?`). This makes `environment` appear to affect the data source while having no real impact. Either propagate `environment` into the SDK so it influences the selected subgraph/contracts, or remove it from the hook signatures and query keys to avoid misleading callers.
Suggested implementation:
```typescript
export interface UseGDAPoolsParams {
enabled?: boolean
}
/**
* Hook for fetching GDA distribution pools
*/
```
```typescript
export function useGDAPools({
```
To fully implement the suggestion and avoid misleading callers, you should also:
1. Remove `environment` from the `UseGDAPoolsParams` type wherever it is imported/used (other files in the codebase).
2. Remove `environment` from the React Query key (or any other caching key) used inside `useGDAPools` so it no longer appears to affect the data source.
3. If there are other related hooks like `usePoolMemberships` that expose `environment` but don't pass it into `GdaSDK`, apply the same changes there: drop `environment` from the params interface, from the function signature, and from any query keys.
</issue_to_address>
### Comment 4
<location> `apps/demo-identity-app/src/components/StreamingTestPage.tsx:90-99` </location>
<code_context>
+
+ const chainId = publicClient?.chain?.id
+
+ const getG$Token = () => {
+ if (!chainId) return "0x"
+ try {
+ // Mapping for UI purposes
+ const addresses: any = {
+ production: {
+ 42220: "0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A", // Celo Mainnet
+ },
+ staging: {
+ 42220: "0x61FA0fB802fd8345C06da558240E0651886fec69", // Celo Staging
+ },
+ development: {
+ 44787: "0xFa51eFDc0910CCdA91732e6806912Fa12e2FD475", // Celo Alfajores
+ 42220: "0xFa51eFDc0910CCdA91732e6806912Fa12e2FD475", // Fallback for user case
+ }
+ }
+ return addresses[environment]?.[chainId] || addresses[environment]?.[42220] || "0x"
+ } catch (e) {
+ return "0x"
</code_context>
<issue_to_address>
**issue (bug_risk):** Fallback to "0x" as a token address can cause runtime failures in SDK calls
`getG$Token` returns the literal `"0x"` when `chainId` is missing or the mapping lookup fails, then casts it to `Address` and passes it into streaming hooks/SDK calls. This is an invalid address and will likely cause opaque transaction/subgraph failures. Prefer returning `null`/`undefined` and disabling the related actions with a clear UI message, or throwing early with a descriptive error when no mapping exists for the current chain/environment.
</issue_to_address>
### Comment 5
<location> `apps/demo-identity-app/src/components/StreamingTestPage.tsx:322` </location>
<code_context>
- </Text>
-
- {/* Disclaimer Section */}
- <YStack
- padding="$3"
- backgroundColor="#FFF8E1"
</code_context>
<issue_to_address>
**issue (complexity):** Consider extracting a reusable section card component and a shared mutation helper to reduce duplication and make this large page easier to read and maintain.
You can keep all functionality but cut a lot of cognitive load with two small abstractions that are local and low‑risk:
### 1. Extract a reusable `SectionCard` layout
You repeat the same “white card with padding/border/gap” pattern for most sections. Creating a tiny wrapper will shrink JSX and make the structure easier to scan:
```tsx
// locally in this file (top-level, above the component) or in a small ui file
const SectionCard: React.FC<React.PropsWithChildren<{ gap?: any; bg?: string }>> = ({
children,
gap = "$3",
bg = "white",
}) => (
<YStack
padding="$4"
backgroundColor={bg}
borderRadius="$4"
borderWidth={1}
borderColor="#E2E8F0"
gap={gap}
>
{children}
</YStack>
);
```
Then replace blocks like:
```tsx
<YStack
padding="$4"
backgroundColor="white"
borderRadius="$4"
borderWidth={1}
borderColor="#E2E8F0"
gap="$3"
>
{/* content */}
</YStack>
```
with:
```tsx
<SectionCard>
{/* content */}
</SectionCard>
```
For the docs card you can override `bg`:
```tsx
<SectionCard bg="#EBF8FF">
{/* Documentation Section content */}
</SectionCard>
```
This alone significantly shortens the file and makes sections visually obvious.
---
### 2. Factor out a shared mutation helper for repeated handlers
Your mutation handlers (`handleCreateStream`, `handleUpdateStream`, `handleDeleteStream`, pool connect/disconnect) repeat the same `try → mutate → onSuccess/onError → alert/log` structure. You can abstract that without changing behavior:
```tsx
// helper near the top of the file
type MutationFn<TArgs> = (
args: TArgs,
opts: {
onSuccess?: (hash: string) => void;
onError?: (error: any) => void;
},
) => void;
function runMutationWithAlerts<TArgs>(
mutate: MutationFn<TArgs>,
args: TArgs,
{
onSuccess,
successMessage,
}: { onSuccess?: (hash: string) => void; successMessage?: string } = {},
) {
try {
mutate(args, {
onSuccess: (hash) => {
if (successMessage) {
alert(`${successMessage} Transaction: ${hash}`);
}
onSuccess?.(hash);
},
onError: (error: any) => {
console.error(error);
alert(`Error: ${error.message}`);
},
});
} catch (error: any) {
console.error(error);
alert(`Error: ${error.message}`);
}
}
```
Then your handlers become much smaller and consistent:
```tsx
const handleCreateStream = () => {
if (!receiver || !amount) {
alert("Please fill in all fields");
return;
}
const flowRate = calculateFlowRate(parseEther(amount), timeUnit);
runMutationWithAlerts(
createStream,
{ receiver: receiver as Address, token: G$_TOKEN as Address, flowRate, environment },
{
onSuccess: (hash) => {
setLastTxHash(hash);
refetchStreams();
setReceiver("");
setAmount("10");
},
},
);
};
const handleUpdateStream = () => {
if (!updateReceiver || !updateAmount) {
alert("Please fill in all fields");
return;
}
const newFlowRate = calculateFlowRate(parseEther(updateAmount), timeUnit);
runMutationWithAlerts(
updateStream,
{
receiver: updateReceiver as Address,
token: G$_TOKEN as Address,
newFlowRate,
environment,
},
{
onSuccess: (hash) => {
setLastTxHash(hash);
refetchStreams();
},
},
);
};
```
`disconnectFromPool` can also use this helper:
```tsx
const handleDisconnectFromPool = () => {
if (!poolAddress) {
alert("Please enter pool address");
return;
}
runMutationWithAlerts(
disconnectFromPool,
{ poolAddress: poolAddress as Address },
{ successMessage: "Disconnected!" },
);
};
```
These two changes keep all behavior, avoid any structural redesign, but reduce duplication and make the component much easier to follow and extend.
</issue_to_address>
### Comment 6
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:112` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 7
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:125` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 8
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:138` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 9
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:150` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 10
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:167` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 11
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:182` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 12
<location> `packages/streaming-sdk/src/streaming-sdk.test.ts:269` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 13
<location> `packages/streaming-sdk/TESTING.md:105` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>
### Comment 14
<location> `packages/streaming-sdk/README.md:48` </location>
<code_context>
0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A
</code_context>
<issue_to_address>
**security (generic-api-key):** Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
*Source: gitleaks*
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| supReserve: | ||
| "https://thegraph.com/explorer/subgraphs/6dRuPxMvaJAp32hvcTsYbAya69A4t1KUHh2EnV3YQeXU", |
There was a problem hiding this comment.
issue (bug_risk): SUP reserve subgraph URL points to the Graph Explorer page, not the API endpoint
Because this constant is used by GraphQLClient in querySUPReserves, requests will fail against the HTML Explorer page. Please update SUBGRAPH_URLS.supReserve to the underlying GraphQL API endpoint (e.g., https://api.thegraph.com/subgraphs/...) so SubgraphClient can query SUP reserve data correctly.
| async updateStream(params: UpdateStreamParams): Promise<Hash> { | ||
| const { receiver, token, newFlowRate, userData = "0x", onHash } = params | ||
|
|
||
| const account = await this.getAccount() | ||
|
|
||
| return this.submitAndWait( | ||
| { | ||
| address: CFA_FORWARDER_ADDRESSES[this.chainId], | ||
| abi: cfaForwarderAbi, | ||
| functionName: "updateFlow", | ||
| args: [token, account, receiver, newFlowRate, userData], | ||
| }, | ||
| onHash, | ||
| ) | ||
| } |
There was a problem hiding this comment.
suggestion (bug_risk): Inconsistent validation of flow rates between createStream and updateStream
createStream validates that flowRate is positive, but updateStream passes newFlowRate through unvalidated. If the protocol requires positive flow rates for active streams, this mismatch could cause unexpected reverts or inconsistent behavior. Please either align the validation behavior in updateStream or document why zero/negative values are acceptable here.
| async updateStream(params: UpdateStreamParams): Promise<Hash> { | |
| const { receiver, token, newFlowRate, userData = "0x", onHash } = params | |
| const account = await this.getAccount() | |
| return this.submitAndWait( | |
| { | |
| address: CFA_FORWARDER_ADDRESSES[this.chainId], | |
| abi: cfaForwarderAbi, | |
| functionName: "updateFlow", | |
| args: [token, account, receiver, newFlowRate, userData], | |
| }, | |
| onHash, | |
| ) | |
| } | |
| async updateStream(params: UpdateStreamParams): Promise<Hash> { | |
| const { receiver, token, newFlowRate, userData = "0x", onHash } = params | |
| if (BigInt(newFlowRate) <= 0n) { | |
| throw new Error("newFlowRate must be a positive non-zero value") | |
| } | |
| const account = await this.getAccount() | |
| return this.submitAndWait( | |
| { | |
| address: CFA_FORWARDER_ADDRESSES[this.chainId], | |
| abi: cfaForwarderAbi, | |
| functionName: "updateFlow", | |
| args: [token, account, receiver, newFlowRate, userData], | |
| }, | |
| onHash, | |
| ) | |
| } |
| export function useGDAPools({ | ||
| environment = "production", | ||
| enabled = true, | ||
| }: UseGDAPoolsParams = {}) { |
There was a problem hiding this comment.
suggestion: Environment parameter in GDA hooks is unused by the underlying SDK
useGDAPools and usePoolMemberships accept an environment parameter and include it in the query key, but never pass it into GdaSDK (which only receives publicClient, walletClient?, chainId?). This makes environment appear to affect the data source while having no real impact. Either propagate environment into the SDK so it influences the selected subgraph/contracts, or remove it from the hook signatures and query keys to avoid misleading callers.
Suggested implementation:
export interface UseGDAPoolsParams {
enabled?: boolean
}
/**
* Hook for fetching GDA distribution pools
*/export function useGDAPools({To fully implement the suggestion and avoid misleading callers, you should also:
- Remove
environmentfrom theUseGDAPoolsParamstype wherever it is imported/used (other files in the codebase). - Remove
environmentfrom the React Query key (or any other caching key) used insideuseGDAPoolsso it no longer appears to affect the data source. - If there are other related hooks like
usePoolMembershipsthat exposeenvironmentbut don't pass it intoGdaSDK, apply the same changes there: dropenvironmentfrom the params interface, from the function signature, and from any query keys.
| const getG$Token = () => { | ||
| if (!chainId) return "0x" | ||
| try { | ||
| // Mapping for UI purposes | ||
| const addresses: any = { | ||
| production: { | ||
| 42220: "0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A", // Celo Mainnet | ||
| }, | ||
| staging: { | ||
| 42220: "0x61FA0fB802fd8345C06da558240E0651886fec69", // Celo Staging |
There was a problem hiding this comment.
issue (bug_risk): Fallback to "0x" as a token address can cause runtime failures in SDK calls
getG$Token returns the literal "0x" when chainId is missing or the mapping lookup fails, then casts it to Address and passes it into streaming hooks/SDK calls. This is an invalid address and will likely cause opaque transaction/subgraph failures. Prefer returning null/undefined and disabling the related actions with a clear UI message, or throwing early with a descriptive error when no mapping exists for the current chain/environment.
|
|
||
| {/* Transaction Alert */} | ||
| {lastTxHash && ( | ||
| <YStack |
There was a problem hiding this comment.
issue (complexity): Consider extracting a reusable section card component and a shared mutation helper to reduce duplication and make this large page easier to read and maintain.
You can keep all functionality but cut a lot of cognitive load with two small abstractions that are local and low‑risk:
1. Extract a reusable SectionCard layout
You repeat the same “white card with padding/border/gap” pattern for most sections. Creating a tiny wrapper will shrink JSX and make the structure easier to scan:
// locally in this file (top-level, above the component) or in a small ui file
const SectionCard: React.FC<React.PropsWithChildren<{ gap?: any; bg?: string }>> = ({
children,
gap = "$3",
bg = "white",
}) => (
<YStack
padding="$4"
backgroundColor={bg}
borderRadius="$4"
borderWidth={1}
borderColor="#E2E8F0"
gap={gap}
>
{children}
</YStack>
);Then replace blocks like:
<YStack
padding="$4"
backgroundColor="white"
borderRadius="$4"
borderWidth={1}
borderColor="#E2E8F0"
gap="$3"
>
{/* content */}
</YStack>with:
<SectionCard>
{/* content */}
</SectionCard>For the docs card you can override bg:
<SectionCard bg="#EBF8FF">
{/* Documentation Section content */}
</SectionCard>This alone significantly shortens the file and makes sections visually obvious.
2. Factor out a shared mutation helper for repeated handlers
Your mutation handlers (handleCreateStream, handleUpdateStream, handleDeleteStream, pool connect/disconnect) repeat the same try → mutate → onSuccess/onError → alert/log structure. You can abstract that without changing behavior:
// helper near the top of the file
type MutationFn<TArgs> = (
args: TArgs,
opts: {
onSuccess?: (hash: string) => void;
onError?: (error: any) => void;
},
) => void;
function runMutationWithAlerts<TArgs>(
mutate: MutationFn<TArgs>,
args: TArgs,
{
onSuccess,
successMessage,
}: { onSuccess?: (hash: string) => void; successMessage?: string } = {},
) {
try {
mutate(args, {
onSuccess: (hash) => {
if (successMessage) {
alert(`${successMessage} Transaction: ${hash}`);
}
onSuccess?.(hash);
},
onError: (error: any) => {
console.error(error);
alert(`Error: ${error.message}`);
},
});
} catch (error: any) {
console.error(error);
alert(`Error: ${error.message}`);
}
}Then your handlers become much smaller and consistent:
const handleCreateStream = () => {
if (!receiver || !amount) {
alert("Please fill in all fields");
return;
}
const flowRate = calculateFlowRate(parseEther(amount), timeUnit);
runMutationWithAlerts(
createStream,
{ receiver: receiver as Address, token: G$_TOKEN as Address, flowRate, environment },
{
onSuccess: (hash) => {
setLastTxHash(hash);
refetchStreams();
setReceiver("");
setAmount("10");
},
},
);
};
const handleUpdateStream = () => {
if (!updateReceiver || !updateAmount) {
alert("Please fill in all fields");
return;
}
const newFlowRate = calculateFlowRate(parseEther(updateAmount), timeUnit);
runMutationWithAlerts(
updateStream,
{
receiver: updateReceiver as Address,
token: G$_TOKEN as Address,
newFlowRate,
environment,
},
{
onSuccess: (hash) => {
setLastTxHash(hash);
refetchStreams();
},
},
);
};disconnectFromPool can also use this helper:
const handleDisconnectFromPool = () => {
if (!poolAddress) {
alert("Please enter pool address");
return;
}
runMutationWithAlerts(
disconnectFromPool,
{ poolAddress: poolAddress as Address },
{ successMessage: "Disconnected!" },
);
};These two changes keep all behavior, avoid any structural redesign, but reduce duplication and make the component much easier to follow and extend.
| sdk.updateStream({ | ||
| receiver: | ||
| "0x1234567890123456789012345678901234567890" as Address, | ||
| token: "0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A" as Address, |
There was a problem hiding this comment.
security (generic-api-key): Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
Source: gitleaks
| sdk.deleteStream({ | ||
| receiver: | ||
| "0x1234567890123456789012345678901234567890" as Address, | ||
| token: "0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A" as Address, |
There was a problem hiding this comment.
security (generic-api-key): Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
Source: gitleaks
|
|
||
| const mockQueryBalances = vi.fn().mockResolvedValue([ | ||
| { | ||
| token: "0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A", |
There was a problem hiding this comment.
security (generic-api-key): Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
Source: gitleaks
|
|
||
| const hash = await sdk.createStream({ | ||
| receiver: '0x...', | ||
| token: '0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A', // G$ on Celo |
There was a problem hiding this comment.
security (generic-api-key): Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
Source: gitleaks
| const flowRate = calculateFlowRate(parseEther('100'), 'month') | ||
| const hash = await streamingSDK.createStream({ | ||
| receiver: '0x...', | ||
| token: '0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A', // G$ on Celo |
There was a problem hiding this comment.
security (generic-api-key): Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
Source: gitleaks
|
Closing this PR with cleaner fixes |
Implemented the Superfluid Streaming SDK and its associated React Hooks, providing a complete library for managing G$ money streams and GDA distribution pools. It also includes an interactive test UI in the demo-identity-app for verification.
Key Features
Core SDK: Implementation of StreamingSDK and GdaSDK for stream CRUD operations and GDA pool management.
React Hooks: Wagmi-style hooks (useCreateStream, useStreamList, usePoolMemberships, etc.) for easy frontend integration.
Subgraph Integration: Optimized queries for historical balances, active flows, and SUP reserve holdings.
Test UI: A new "Streaming" tab in the demo app to interactively test all SDK features.
Documentation: Comprehensive guides for both core SDK usage and frontend testing.
Summary by Sourcery
Introduce a new streaming SDK and React hooks for managing Superfluid-based G$ money streams and GDA pools, and expose them via a demo app streaming test UI.
New Features:
Enhancements:
Build:
Documentation:
Tests:
Chores: