Skip to content

Commit

Permalink
Bump up version to [email protected] (#259) (#260)
Browse files Browse the repository at this point in the history
* Update ipAsset type

* Update react-sdk script

* Turn off no-unsafe-assignment in test

* Add env into turbo.json

* Fix integration tests

* Refactor code by wrapper of withLoadingErrorHandling

* Optimize generate story client

* Update exporting types

* Skip generater template file

* Bump up version to [email protected]

* Remove test command to skip tests
  • Loading branch information
bonnie57 authored Sep 19, 2024
1 parent 00d1f3a commit 7a2f298
Show file tree
Hide file tree
Showing 26 changed files with 6,627 additions and 8,384 deletions.
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

0 comments on commit 7a2f298

Please sign in to comment.