Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump up version to [email protected] #259

Merged
merged 11 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/react-sdk/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,18 @@ module.exports = {
tsconfigRootDir: __dirname,
},
extends: ["@story-protocol/eslint-config"],
overrides: [
{
files: ["test/**/*.test.ts"],
rules: {
"@typescript-eslint/no-unsafe-assignment": "off",
},
},
{
files: ["generator/**/*.js"],
rules: {
"@typescript-eslint/no-var-requires": "off",
},
},
],
};
27 changes: 23 additions & 4 deletions packages/react-sdk/generator/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const ejs = require("ejs");
const fs = require("fs");
const path = require("path");
const { exec } = require("child_process");

const ejs = require("ejs");
const ts = require("typescript");
const cliProgress = require("cli-progress");
const { exec } = require("child_process");

const resourcesFolder = path.resolve(__dirname, "../../core-sdk/src/resources");
const resourceTemplate = require("./templates/resource");
const indexTemplate = require("./templates/index");
Expand All @@ -26,6 +28,10 @@ const isPrimitiveType = (type) => {
const isViemType = (type) => {
return ["Hex", "Address"].includes(type);
};

const isEnclosedInCurlyBraces = (type) => {
return type.slice(0, 1) === "{" && type.slice(-1) === "}";
};
const visit = (file) => {
let program = ts.createProgram([file], { allowJs: true });
const sourceFile = program.getSourceFile(file);
Expand All @@ -44,6 +50,9 @@ const visit = (file) => {
ts.isIdentifier(member.name)
) {
const requests = [];
const isAsync = member.modifiers?.some(
(modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword
);
program.getTypeChecker().getSignatureFromDeclaration(member);
member.parameters.forEach((parameter) => {
requests.push({
Expand All @@ -58,12 +67,14 @@ const visit = (file) => {
?.getText()
.replace("Promise<", "")
.replace(">", ""),
isAsync,
comments:
ts
.getLeadingCommentRanges(sourceFile.text, member.pos)
?.map((range) =>
sourceFile.text.substring(range.pos, range.end).trim()
) || [],
defaultValues: undefined, // Get default value,
};
publicMethods.push(method);
}
Expand All @@ -72,6 +83,7 @@ const visit = (file) => {
});
return publicMethods;
};

let fileNames = [];
let exportTypes = [];
const files = fs.readdirSync(resourcesFolder);
Expand All @@ -85,6 +97,9 @@ files.forEach((file, index) => {
fileNames.push(fileName);
const methods = visit(path.resolve(resourcesFolder, file));
const methodNames = methods.map((method) => method.name);
const asyncMethods = methods
.filter((method) => method.isAsync)
.map((method) => method.name);
const types = methods.reduce(
(acc, curr) =>
acc.concat(
Expand All @@ -98,14 +113,15 @@ files.forEach((file, index) => {
types
.filter((type) => !isPrimitiveType(type))
.filter((type) => !isViemType(type))
.filter((type) => !isEnclosedInCurlyBraces(type))
),
];
exportTypes.push(...filteredTypes);
sources.push(
ejs.render(resourceTemplate.startTemplate, {
types: [filteredTypes],
name: fileName,
methodNames,
methodNames: asyncMethods,
viemTypes: [...new Set(types.filter((type) => isViemType(type)))],
})
);
Expand All @@ -119,7 +135,10 @@ files.forEach((file, index) => {

sources = sources.concat(
methodTemplates,
ejs.render(resourceTemplate.endTemplate, { methodNames, name: fileName })
ejs.render(resourceTemplate.endTemplate, {
methodNames,
name: fileName,
})
);
fs.writeFileSync(`src/resources/use${fileName}.ts`, sources.join("\n"));
});
Expand Down
5 changes: 5 additions & 0 deletions packages/react-sdk/generator/templates/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ const indexTemplate = `
export { StoryProvider } from "./StoryProtocolContext";
export { getPermissionSignature, AccessPermission, PIL_TYPE, } from "@story-protocol/core-sdk";
export type { PermissionSignatureRequest, StoryConfig, SupportedChainIds,
IpRelationship,
IpAttribute,
IpCreatorSocial,
IpMedia,
IPRobotTerms,
<%types.forEach((type,index)=>{%>
<%=type%><%=index === types.length - 1 ? '' : ','%>
<%})%>
Expand Down
29 changes: 11 additions & 18 deletions packages/react-sdk/generator/templates/resource.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
const methodTemplate = `<%=comments%>\nconst <%=method.name %> = async (<% method.requests.forEach((item, index)=> { %>
<%= item.name %>: <%= item.type %><%= index === method.requests.length - 1 ? '' : ',' %>
<% }); %>): Promise<<%- method.responseType %>> => {
try {
setLoadings((prev) => ({ ...prev, <%=method.name %>: true }));
setErrors((prev) => ({ ...prev, <%=method.name %>: null }));
const response = await client.<%= fileName%>.<%=method.name %>(<% method.requests.forEach((item,index)=>{%>
<%=item.name %><%=index === method.requests.length - 1 ? '' : ',' %>
<% })%>);
setLoadings((prev ) => ({ ...prev, <%=method.name %>: false }));
return response;
}catch(e){
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, <%=method.name %>: errorMessage }));
setLoadings((prev) => ({ ...prev, <%=method.name %>: false }));
throw new Error(errorMessage);
}
const methodTemplate = `<%=comments%><% if(method.isAsync){ %>
const <%=method.name %> = withLoadingErrorHandling<<%=method.requests[0].type%>,<%- method.responseType %>>('<%=method.name %>', client.<%= fileName%>.<%=method.name %>.bind(client.<%= fileName%>), setLoadings, setErrors);
<% } else { %>
const <%=method.name %> =(<% method.requests.forEach((item, index)=> { %>
<%= item.name||"request" %>: <%= item.type %><%= index === method.requests.length - 1 ? '' : ',' %>
<% }); %>): <%- method.responseType %>=> {
return client.<%= fileName%>.<%=method.name %>(<% method.requests.forEach((item,index)=>{%>
<%=item.name||"request" %><%=index === method.requests.length - 1 ? '' : ',' %>
<% })%>);
};
<% } %>
`;

const startTemplate = `import { <% types.forEach((type,index)=>{%>\n<%=type %><%= index===types.length-1?'':','%><%})%>
Expand All @@ -27,7 +20,7 @@ const startTemplate = `import { <% types.forEach((type,index)=>{%>\n<%=type %><%

import { useState } from "react";
import { useStoryContext } from "../StoryProtocolContext";
import { handleError } from "../util";
import { withLoadingErrorHandling } from "../withLoadingErrorHandling";
const use<%=name %> = () => {
const client = useStoryContext();
const [loadings,setLoadings] = useState<Record<string,boolean>>({<% methodNames.forEach((name,index)=>{%><%=name %>: false<%=index === methodNames.length - 1 ? '' : ',' %> <%})%>});
Expand Down
4 changes: 2 additions & 2 deletions packages/react-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@story-protocol/react-sdk",
"version": "0.0.1",
"version": "0.0.2",
"description": "The Story Protocol React SDK",
"main": "dist/story-protocol-react-sdk.cjs.js",
"module": "dist/story-protocol-react-sdk.esm.js",
Expand Down Expand Up @@ -62,7 +62,7 @@
},
"license": "MIT",
"dependencies": {
"@story-protocol/core-sdk": "1.0.0-rc.15",
"@story-protocol/core-sdk": "1.0.0-rc.22",
"react": "^18.3.1",
"viem": "^2.8.12"
},
Expand Down
10 changes: 7 additions & 3 deletions packages/react-sdk/src/StoryProtocolContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext, ReactNode } from "react";
import { createContext, useContext, ReactNode, useState } from "react";
import { StoryClient, StoryConfig } from "@story-protocol/core-sdk";

type Props = {
Expand All @@ -9,9 +9,13 @@ type Props = {
const StoryContext = createContext<StoryClient>({} as StoryClient);

const StoryProvider = ({ config, children }: Props) => {
const client = StoryClient.newClient(config);
const [client, setClient] = useState<StoryClient>();

if (!client) {
setClient(StoryClient.newClient(config));
}
return (
<StoryContext.Provider value={client}>{children}</StoryContext.Provider>
<StoryContext.Provider value={client!}>{children}</StoryContext.Provider>
);
};
const useStoryContext = (): StoryClient => {
Expand Down
12 changes: 11 additions & 1 deletion packages/react-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export type {
PermissionSignatureRequest,
StoryConfig,
SupportedChainIds,
IpRelationship,
IpAttribute,
IpCreatorSocial,
IpMedia,
IPRobotTerms,
RaiseDisputeRequest,
RaiseDisputeResponse,
CancelDisputeRequest,
Expand All @@ -18,7 +23,11 @@ export type {
IPAccountExecuteResponse,
IPAccountExecuteWithSigRequest,
IPAccountExecuteWithSigResponse,
IpAccountImplStateResponse,
IpAccountStateResponse,
GenerateCreatorMetadataParam,
IpCreator,
GenerateIpMetadataParam,
IpMetadata,
RegisterRequest,
RegisterIpResponse,
RegisterDerivativeRequest,
Expand All @@ -31,6 +40,7 @@ export type {
RegisterIpAndAttachPilTermsResponse,
RegisterIpAndMakeDerivativeRequest,
RegisterIpAndMakeDerivativeResponse,
MintAndRegisterIpAndMakeDerivativeRequest,
RegisterNonComSocialRemixingPILRequest,
RegisterPILResponse,
RegisterCommercialUsePILRequest,
Expand Down
81 changes: 31 additions & 50 deletions packages/react-sdk/src/resources/useDispute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { useState } from "react";

import { useStoryContext } from "../StoryProtocolContext";
import { handleError } from "../util";
import { withLoadingErrorHandling } from "../withLoadingErrorHandling";

const useDispute = () => {
const client = useStoryContext();
Expand All @@ -32,86 +32,67 @@ const useDispute = () => {
* @param request.linkToDisputeEvidence - The link to the dispute evidence.
* @param request.targetTag - The target tag of the dispute.
* @param request.calldata - Optional calldata to initialize the policy.
* @param request.txOptions - Optional transaction options.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to a RaiseDisputeResponse containing the transaction hash.
* @throws `NotRegisteredIpId` if targetIpId is not registered in the IPA Registry.
* @throws `NotWhitelistedDisputeTag` if targetTag is not whitelisted.
* @throws `ZeroLinkToDisputeEvidence` if linkToDisputeEvidence is empty
* @calls raiseDispute(address _targetIpId, string memory _linkToDisputeEvidence, bytes32 _targetTag, bytes calldata _data) external nonReentrant returns (uint256) {
* @emits DisputeRaised (disputeId_, targetIpId, msg.sender, arbitrationPolicy, linkToDisputeEvidence, targetTag, calldata);
*/
const raiseDispute = async (
request: RaiseDisputeRequest
): Promise<RaiseDisputeResponse> => {
try {
setLoadings((prev) => ({ ...prev, raiseDispute: true }));
setErrors((prev) => ({ ...prev, raiseDispute: null }));
const response = await client.dispute.raiseDispute(request);
setLoadings((prev) => ({ ...prev, raiseDispute: false }));
return response;
} catch (e) {
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, raiseDispute: errorMessage }));
setLoadings((prev) => ({ ...prev, raiseDispute: false }));
throw new Error(errorMessage);
}
};
const raiseDispute = withLoadingErrorHandling<
RaiseDisputeRequest,
RaiseDisputeResponse
>(
"raiseDispute",
client.dispute.raiseDispute.bind(client.dispute),
setLoadings,
setErrors
);

/**
* Cancels an ongoing dispute
* @param request - The request object containing details to cancel the dispute.
* @param request.disputeId The ID of the dispute to be cancelled.
* @param request.calldata Optional additional data used in the cancellation process.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to a CancelDisputeResponse containing the transaction hash.
* @throws NotInDisputeState, if the currentTag of the Dispute is not being disputed
* @throws NotDisputeInitiator, if the transaction executor is not the one that initiated the dispute
* @throws error if the Dispute&#39;s ArbitrationPolicy contract is not valid
* @calls cancelDispute(uint256 _disputeId, bytes calldata _data) external nonReentrant {
* @emits DisputeCancelled (_disputeId, _data);
*/
const cancelDispute = async (
request: CancelDisputeRequest
): Promise<CancelDisputeResponse> => {
try {
setLoadings((prev) => ({ ...prev, cancelDispute: true }));
setErrors((prev) => ({ ...prev, cancelDispute: null }));
const response = await client.dispute.cancelDispute(request);
setLoadings((prev) => ({ ...prev, cancelDispute: false }));
return response;
} catch (e) {
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, cancelDispute: errorMessage }));
setLoadings((prev) => ({ ...prev, cancelDispute: false }));
throw new Error(errorMessage);
}
};
const cancelDispute = withLoadingErrorHandling<
CancelDisputeRequest,
CancelDisputeResponse
>(
"cancelDispute",
client.dispute.cancelDispute.bind(client.dispute),
setLoadings,
setErrors
);

/**
* Resolves a dispute after it has been judged
* @param request - The request object containing details to resolve the dispute.
* @param request.disputeId The ID of the dispute to be resolved.
* @param request.data The data to resolve the dispute.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to a ResolveDisputeResponse.
* @throws NotAbleToResolve, if currentTag is still in dispute (i.e still needs a judgement to be set)
* @throws NotDisputeInitiator, if the transaction executor is not the one that initiated the dispute
* @emits DisputeResolved (_disputeId)
*/
const resolveDispute = async (
request: ResolveDisputeRequest
): Promise<ResolveDisputeResponse> => {
try {
setLoadings((prev) => ({ ...prev, resolveDispute: true }));
setErrors((prev) => ({ ...prev, resolveDispute: null }));
const response = await client.dispute.resolveDispute(request);
setLoadings((prev) => ({ ...prev, resolveDispute: false }));
return response;
} catch (e) {
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, resolveDispute: errorMessage }));
setLoadings((prev) => ({ ...prev, resolveDispute: false }));
throw new Error(errorMessage);
}
};
const resolveDispute = withLoadingErrorHandling<
ResolveDisputeRequest,
ResolveDisputeResponse
>(
"resolveDispute",
client.dispute.resolveDispute.bind(client.dispute),
setLoadings,
setErrors
);

return {
loadings,
Expand Down
Loading