-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Modify calling signTypedData by wallet client * Upload pnpm-lock.yaml * Generator resource files * Generate index file * Add some config * Add comments for method * Fix react bundle issue * Update README.md * Update bundle config * Update core-sdk version in order to solve linking react-sdk * reset core-sdk version * Link core sdk * Modify core-sdk reference * Cancel fix code command * Set link-workspace-packages false * Modify pnpm-lock file * test * Rename StoryProtocolContext * Add comments about npmrc * Modify package.json * Add getPermissionSignature and export the related types * Update README.md
- Loading branch information
Showing
18 changed files
with
2,121 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Once core-react is published to npm, react-sdk can be updated to use it | ||
link-workspace-packages: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module.exports = { | ||
parserOptions: { | ||
project: "./tsconfig.json", | ||
tsconfigRootDir: __dirname, | ||
}, | ||
extends: ["@story-protocol/eslint-config"], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Story Protocol React SDK | ||
|
||
The react-sdk is a library that provides a set of hooks to interact with the SDK. It is designed to be used in a React application. | ||
|
||
## How to use Story Protocol SDK in Your Project | ||
|
||
### Generate React SDK | ||
|
||
1. Install the dependencies | ||
|
||
```bash | ||
pnpm install | ||
``` | ||
|
||
2. Update the `@story-protocol/core-sdk` package version in the `packages/react-sdk/package.json` file to the latest version. | ||
|
||
Important: Once publish core-sdk, you need to update the core-sdk version in the react-sdk package.json file. | ||
|
||
3. Generate the SDK | ||
|
||
```bash | ||
pnpm run generate | ||
``` | ||
|
||
This SDK is generated using the command `pnpm run generate`. The source code resides in the `packages/sdk` directory and the generated SDK can be found in the `packages/react-sdk` folder. | ||
|
||
### How to use Story Protocol React SDK in Your Project | ||
|
||
- Install Story Protocol React SDK | ||
|
||
```bash | ||
pnpm install @story-protocol/react-sdk | ||
``` | ||
|
||
- Import the provider in your React application | ||
|
||
```typescript | ||
import { StoryProvider } from "@story-protocol/react-sdk"; | ||
const client = StoryClient.newClient(config); | ||
<StoryProvider | ||
config={{ | ||
chainId: "sepolia", | ||
transport: http("RPC_URL"), | ||
wallet: walletClient, | ||
}} | ||
</StoryProvider> | ||
``` | ||
|
||
- Use the hooks in your component | ||
|
||
```typescript | ||
import { useIpAsset } from "@story-protocol/react-sdk"; | ||
const { data, error, loading, register } = useIpAsset(); | ||
register({ nftContract: "0x1234", tokenId: "1" }); | ||
``` | ||
|
||
### How To Build and Test Story Protocol React SDK for local testing | ||
|
||
- Install yalc | ||
|
||
```bash | ||
npm install -g yalc | ||
``` | ||
|
||
- For manual testing of the react-sdk, set up a separate web project. The guide below uses `yalc` to link the `react-sdk` locally, enabling its installation and import for testing. | ||
|
||
Under the `typescript-sdk/packages/react-sdk` directory: | ||
|
||
- Execute `npm run build` to build your latest code. | ||
- Run `yalc publish`. You should see a message like `@story-protocol/react-sdk@<version> published in store.` (Note: The version number may vary). | ||
- To set up your testing environment (e.g., a new Next.js project), use `yalc add @story-protocol/react-sdk@<version>` (ensure the version number is updated accordingly). | ||
|
||
- Run `pnpm install`. This installs `@story-protocol/react-sdk@<version>` with your local changes. | ||
|
||
### Steps to Refresh the Changes | ||
|
||
Under the `typescript-sdk/packages/react-sdk` directory: | ||
|
||
- Execute `npm run build` to build your latest code. | ||
- Run `yalc push`. | ||
|
||
In your testing environment: | ||
|
||
- Run `yalc update` to pull the latest changes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
const ejs = require("ejs"); | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const ts = require("typescript"); | ||
const resourcesFolder = path.resolve(__dirname, "../../core-sdk/src/resources"); | ||
const resourceTemplate = require("./templates/resource"); | ||
const indexTemplate = require("./templates/index"); | ||
|
||
console.log("🚀🚀 React SDK generator started!\n"); | ||
const isPrimitiveType = (type) => { | ||
return [ | ||
"string", | ||
"number", | ||
"boolean", | ||
"symbol", | ||
"undefined", | ||
"null", | ||
"bigint", | ||
"string|bigint|number", | ||
].includes(type); | ||
}; | ||
const isViemType = (type) => { | ||
return ["Hex", "Address"].includes(type); | ||
}; | ||
const visit = (file) => { | ||
let program = ts.createProgram([file], { allowJs: true }); | ||
const sourceFile = program.getSourceFile(file); | ||
ts.createProgram([sourceFile.fileName], {}).getTypeChecker(); | ||
const publicMethods = []; | ||
ts.forEachChild(sourceFile, (node) => { | ||
if (ts.isClassDeclaration(node)) { | ||
for (const member of node.members) { | ||
if ( | ||
ts.isMethodDeclaration(member) && | ||
(member.modifiers?.some( | ||
(m) => m.kind === ts.SyntaxKind.PublicKeyword | ||
) ?? | ||
true) && | ||
member.name && | ||
ts.isIdentifier(member.name) | ||
) { | ||
const requests = []; | ||
program.getTypeChecker().getSignatureFromDeclaration(member); | ||
member.parameters.forEach((parameter) => { | ||
requests.push({ | ||
name: parameter.name.escapedText, | ||
type: parameter.type.getText(), | ||
}); | ||
}); | ||
const method = { | ||
name: member.name.text, | ||
requests, | ||
responseType: member.type | ||
?.getText() | ||
.replace("Promise<", "") | ||
.replace(">", ""), | ||
comments: | ||
ts | ||
.getLeadingCommentRanges(sourceFile.text, member.pos) | ||
?.map((range) => | ||
sourceFile.text.substring(range.pos, range.end).trim() | ||
) || [], | ||
}; | ||
publicMethods.push(method); | ||
} | ||
} | ||
} | ||
}); | ||
return publicMethods; | ||
}; | ||
let fileNames = []; | ||
let exportTypes = []; | ||
fs.readdirSync(resourcesFolder).forEach((file) => { | ||
let sources = []; | ||
const fileName = | ||
file.replace(".ts", "").charAt(0).toUpperCase() + | ||
file.replace(".ts", "").slice(1); | ||
fileNames.push(fileName); | ||
const methods = visit(path.resolve(resourcesFolder, file)); | ||
const methodNames = methods.map((method) => method.name); | ||
const types = methods.reduce( | ||
(acc, curr) => | ||
acc.concat( | ||
curr.requests.map((item) => item.type), | ||
curr.responseType | ||
), | ||
[] | ||
); | ||
const filteredTypes = [ | ||
...new Set( | ||
types | ||
.filter((type) => !isPrimitiveType(type)) | ||
.filter((type) => !isViemType(type)) | ||
), | ||
]; | ||
exportTypes.push(...filteredTypes); | ||
sources.push( | ||
ejs.render(resourceTemplate.startTemplate, { | ||
types: [filteredTypes], | ||
name: fileName, | ||
methodNames, | ||
viemTypes: [...new Set(types.filter((type) => isViemType(type)))], | ||
}) | ||
); | ||
const methodTemplates = methods.map((method) => { | ||
return ejs.render(resourceTemplate.methodTemplate, { | ||
method: method, | ||
fileName: file.replace(".ts", ""), | ||
comments: method.comments, | ||
}); | ||
}); | ||
|
||
sources = sources.concat( | ||
methodTemplates, | ||
ejs.render(resourceTemplate.endTemplate, { methodNames, name: fileName }) | ||
); | ||
fs.writeFileSync(`src/resources/use${fileName}.ts`, sources.join("\n")); | ||
}); | ||
const indexSource = ejs.render(indexTemplate, { | ||
resources: fileNames, | ||
types: exportTypes, | ||
}); | ||
fs.writeFileSync("src/index.ts", indexSource); | ||
|
||
console.log("👍👍 React SDK templates generated successfully!"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const indexTemplate = ` | ||
export { StoryProvider } from "./StoryProtocolContext"; | ||
export { getPermissionSignature, AccessPermission, PIL_TYPE, } from "@story-protocol/core-sdk"; | ||
export type { PermissionSignatureRequest, StoryConfig, SupportedChainIds, | ||
<%types.forEach((type,index)=>{%> | ||
<%=type%><%=index === types.length - 1 ? '' : ','%> | ||
<%})%> | ||
} from "@story-protocol/core-sdk"; | ||
<% resources.forEach((resource) => {%> | ||
export { default as use<%=resource %> } from "./resources/use<%=resource %>"; | ||
<%})%> | ||
`; | ||
module.exports = indexTemplate; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
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){ | ||
if(e instanceof Error){ | ||
setErrors((prev) => ({ ...prev, <%=method.name %>: e.message })); | ||
setLoadings((prev) => ({ ...prev, <%=method.name %>: false })); | ||
} | ||
throw new Error(\`unhandled error type\`); | ||
} | ||
}; | ||
`; | ||
|
||
const startTemplate = `import { <% types.forEach((type,index)=>{%>\n<%=type %><%= index===types.length-1?'':','%><%})%> | ||
} from "@story-protocol/core-sdk"; | ||
<% if (viemTypes.length > 0) { %> | ||
import { <% viemTypes.forEach((type, index) => { %>\n<%= type %><%= index === viemTypes.length - 1 ? '' : ',' %><% }) %> | ||
} from "viem"; | ||
<% } %> | ||
import { useState } from "react"; | ||
import { useStoryContext } from "../StoryProtocolContext"; | ||
const use<%=name %> = () => { | ||
const client = useStoryContext(); | ||
const [loadings,setLoadings] = useState<Record<string,boolean>>({<% methodNames.forEach((name,index)=>{%><%=name %>: false<%=index === methodNames.length - 1 ? '' : ',' %> <%})%>}); | ||
const [errors,setErrors] = useState<Record<string,string|null>>({ <% methodNames.forEach((name,index)=>{%><%=name %>: null<%=index === methodNames.length - 1 ? '' : ',' %><%})%> }); | ||
`; | ||
|
||
const endTemplate = `return { | ||
loadings, | ||
errors, | ||
<% methodNames.forEach((name,index)=>{%><%=name %><%=index === methodNames.length - 1 ? '' : ',' %> | ||
<%})%> | ||
};}\nexport default use<%=name %>;`; | ||
|
||
module.exports = { startTemplate, endTemplate, methodTemplate }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
{ | ||
"name": "@story-protocol/react-sdk", | ||
"version": "1.0.0-rc.14", | ||
"description": "The Story Protocol React SDK", | ||
"main": "dist/story-protocol-react-sdk.cjs.js", | ||
"module": "dist/story-protocol-react-sdk.esm.js", | ||
"exports": { | ||
".": { | ||
"module": "./dist/story-protocol-react-sdk.esm.js", | ||
"default": "./dist/story-protocol-react-sdk.cjs.js" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"scripts": { | ||
"generate": "node ./generator/index.js && npm run fix", | ||
"build": "pnpm run fix && preconstruct build", | ||
"fix": "pnpm run format:fix && pnpm run lint:fix", | ||
"format": "prettier --check .", | ||
"format:fix": "prettier --write .", | ||
"lint:fix": "pnpm run lint --fix", | ||
"lint": "eslint ./src", | ||
"tsc": "tsc --noEmit" | ||
}, | ||
"sideEffects": false, | ||
"files": [ | ||
"dist/**/*" | ||
], | ||
"preconstruct": { | ||
"entrypoints": [ | ||
"index.ts" | ||
], | ||
"exports": true, | ||
"externals": [ | ||
"react", | ||
"@story-protocol/core-sdk" | ||
] | ||
}, | ||
"keywords": [ | ||
"story-protocol", | ||
"react", | ||
"sdk", | ||
"react hooks" | ||
], | ||
"babel": { | ||
"presets": [ | ||
"@babel/preset-env", | ||
"@babel/preset-typescript", | ||
[ | ||
"@babel/preset-react", | ||
{ | ||
"runtime": "automatic" | ||
} | ||
] | ||
] | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"@story-protocol/core-sdk": "1.0.0-rc.14", | ||
"react": "^18.3.1", | ||
"viem": "^2.8.12", | ||
"@types/react": "^18.3.3" | ||
}, | ||
"devDependencies": { | ||
"@babel/preset-env": "^7.22.20", | ||
"@babel/preset-react": "^7.24.7", | ||
"@babel/preset-typescript": "^7.23.0", | ||
"@preconstruct/cli": "^2.8.1", | ||
"@story-protocol/eslint-config": "workspace:*", | ||
"@story-protocol/prettier-config": "workspace:*", | ||
"@story-protocol/tsconfig": "workspace:*", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.4.5", | ||
"ejs": "^3.1.10" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { createContext, useContext, ReactNode } from "react"; | ||
import { StoryClient, StoryConfig } from "@story-protocol/core-sdk"; | ||
|
||
type Props = { | ||
config: StoryConfig; | ||
children: ReactNode; | ||
}; | ||
|
||
const StoryContext = createContext<StoryClient>({} as StoryClient); | ||
|
||
const StoryProvider = ({ config, children }: Props) => { | ||
const client = StoryClient.newClient(config); | ||
return ( | ||
<StoryContext.Provider value={client}>{children}</StoryContext.Provider> | ||
); | ||
}; | ||
const useStoryContext = (): StoryClient => { | ||
return useContext(StoryContext); | ||
}; | ||
export { useStoryContext, StoryProvider }; |
Oops, something went wrong.