diff --git a/.changeset/nervous-guests-sort.md b/.changeset/nervous-guests-sort.md new file mode 100644 index 00000000000..2293d71186f --- /dev/null +++ b/.changeset/nervous-guests-sort.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/service-utils": patch +--- + +fix checkout service name diff --git a/.changeset/rude-candles-stare.md b/.changeset/rude-candles-stare.md new file mode 100644 index 00000000000..81c16e020cc --- /dev/null +++ b/.changeset/rude-candles-stare.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/react-native": patch +--- + +Correctly pass sdkOptions down diff --git a/.changeset/two-geckos-refuse.md b/.changeset/two-geckos-refuse.md new file mode 100644 index 00000000000..78cb426ee42 --- /dev/null +++ b/.changeset/two-geckos-refuse.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/react-native": patch +--- + +Update WalletConnectUI to use new arch diff --git a/.changeset/unlucky-horses-sort.md b/.changeset/unlucky-horses-sort.md new file mode 100644 index 00000000000..145b2c261b9 --- /dev/null +++ b/.changeset/unlucky-horses-sort.md @@ -0,0 +1,6 @@ +--- +"eslint-config-thirdweb": patch +"@thirdweb-dev/react": patch +--- + +Enforce react-hooks/exhaustive-deps lint rule diff --git a/.github/workflows/snippets.yml b/.github/workflows/snippets.yml new file mode 100644 index 00000000000..787ba7b7941 --- /dev/null +++ b/.github/workflows/snippets.yml @@ -0,0 +1,43 @@ +# On the Version Packages branch created by github-actions[bot] +# Run `pnpm build`, `pnpm generate-docs` and `pnpm generate-snippets` to generate JSON files in the snippets folder +# Commit the generated JSON files to the Version Packages branch + +name: Commit code snippets + +on: + push: + branches: + - changeset-release/main + +jobs: + typedoc: + if: github.actor == 'github-actions[bot]' + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - name: Checkout branch + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install + uses: ./.github/composite-actions/install + + - name: build + run: pnpm build + + - name: generate-docs + run: pnpm generate-docs + + - name: generate-snippets + run: pnpm generate-snippets + + - name: Commit changes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add -A + git commit -m "snippets: update JSON files [skip ci]" + git push + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/typedoc.yml b/.github/workflows/typedoc.yml new file mode 100644 index 00000000000..03247134326 --- /dev/null +++ b/.github/workflows/typedoc.yml @@ -0,0 +1,37 @@ +# On the Version Packages branch created by github-actions[bot] +# Run `pnpm typedoc` to generate the JSON files +# Commit the generated JSON files to the Version Packages branch + +name: Commit Typedoc JSON files + +on: + push: + branches: + - changeset-release/main + +jobs: + typedoc: + if: github.actor == 'github-actions[bot]' + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - name: Checkout branch + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install + uses: ./.github/composite-actions/install + + - name: Typedoc + run: pnpm typedoc + + - name: Commit changes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add -A + git commit -m "typedoc: update JSON files [skip ci]" + git push + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3ed551fbaf5..828b274f586 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,4 @@ playwright-report/ .env/ # Artifacts -packages/cli/artifacts/ - -typedoc \ No newline at end of file +packages/cli/artifacts/ \ No newline at end of file diff --git a/package.json b/package.json index 4fcf4bde244..c44e97fa76f 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "e2e": "turbo run e2e", "build": "turbo run build --filter=./packages/*", "typedoc": "turbo run typedoc", + "generate-docs": "turbo run generate-docs", + "generate-snippets": "node ./scripts/generate-snippets/index.mjs", "build:release": "turbo run build --force --filter=./packages/*", "dev": "turbo run dev --no-cache --parallel --continue", "fix:repo": "manypkg fix", diff --git a/packages/eslint-config-thirdweb/index.js b/packages/eslint-config-thirdweb/index.js index 09ad1ef0f70..99e6d227c74 100644 --- a/packages/eslint-config-thirdweb/index.js +++ b/packages/eslint-config-thirdweb/index.js @@ -50,5 +50,8 @@ module.exports = { ], }, ], + + // react + "react-hooks/exhaustive-deps": "error", }, }; diff --git a/packages/react-core/package.json b/packages/react-core/package.json index c2f61d4c724..dac2dea53cd 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -48,7 +48,7 @@ "lint": "eslint src/ && bunx publint --strict --level warning", "fix": "eslint src/ --fix", "clean": "rm -rf dist/", - "generate-docs": "pnpm generate-docs:evm && pnpm generate-snippets", + "generate-docs": "mkdir -p etc && pnpm generate-docs:evm && pnpm generate-snippets", "generate-docs:evm": "api-extractor run --local --config ./config/api-extractor-evm.json && api-documenter markdown -i ./temp -o ./docs/evm && rm -rf ./temp-evm && mv ./temp ./temp-evm", "generate-snippets": "node ./scripts/generate-snippets-evm.mjs && node ./scripts/generate-feature-snippets-evm.mjs", "build": "tsc && preconstruct build", diff --git a/packages/react-core/scripts/typedoc.mjs b/packages/react-core/scripts/typedoc.mjs index b5a69338813..5b83b44fc63 100644 --- a/packages/react-core/scripts/typedoc.mjs +++ b/packages/react-core/scripts/typedoc.mjs @@ -10,5 +10,4 @@ typedoc({ "**/packages/wallets/**", "**/packages/chains/**", ], - output: "both", // TODO: change this to 'json' when old portal is fully migrated to new portal }); diff --git a/packages/react-native/scripts/typedoc.mjs b/packages/react-native/scripts/typedoc.mjs index 890df41aa34..df1b5840f67 100644 --- a/packages/react-native/scripts/typedoc.mjs +++ b/packages/react-native/scripts/typedoc.mjs @@ -9,5 +9,4 @@ typedoc({ "**/packages/react-core/**", "**/packages/chains/**", ], - output: "both", // TODO: change this to 'json' when old portal is fully migrated to new portal }); diff --git a/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWallet.tsx b/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWallet.tsx index 729bf63e718..2ed8ce53f7c 100644 --- a/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWallet.tsx +++ b/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWallet.tsx @@ -191,7 +191,6 @@ export function ChooseWallet({ onChooseWallet(emailWallet, data); }} walletConfig={emailWallet} - // TEMPORARY BUILD FIX connect={(options: any) => connect(emailWallet, options)} connectedWallet={activeWallet} connectedWalletAddress={address} diff --git a/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWalletContent.tsx b/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWalletContent.tsx index 7e75e552dfc..8cfae745ab4 100644 --- a/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWalletContent.tsx +++ b/packages/react-native/src/evm/components/ConnectWalletFlow/ChooseWallet/ChooseWalletContent.tsx @@ -60,7 +60,6 @@ export const ChooseWalletContent = ({ onChooseWallet(item, data); }} walletConfig={item} - // TEMPORARY BUILD FIX connect={(options: any) => connect(item, options)} connectedWallet={activeWallet} connectedWalletAddress={address} diff --git a/packages/react-native/src/evm/index.ts b/packages/react-native/src/evm/index.ts index f359098275a..26473e1c22e 100644 --- a/packages/react-native/src/evm/index.ts +++ b/packages/react-native/src/evm/index.ts @@ -44,7 +44,7 @@ export { type ActionFn, } from "./components/Web3Button"; -export { WalletConnectUI } from "./wallets/wallets/wallet-connect/WalletConnectUI"; +export { WalletConnectUI } from "./wallets/wallets/wallet-connect/wallet-connect"; // utilities export * from "./utils/uri"; diff --git a/packages/react-native/src/evm/providers/thirdweb-provider.tsx b/packages/react-native/src/evm/providers/thirdweb-provider.tsx index eeabb195492..d635f5d335a 100644 --- a/packages/react-native/src/evm/providers/thirdweb-provider.tsx +++ b/packages/react-native/src/evm/providers/thirdweb-provider.tsx @@ -183,7 +183,7 @@ export const ThirdwebProvider = ( } createWalletStorage={createWalletStorage} clientId={clientId} - {...sdkOptions} + sdkOptions={sdkOptions} {...restProps} > diff --git a/packages/react-native/src/evm/wallets/wallets/wallet-connect/WalletConnectUI.tsx b/packages/react-native/src/evm/wallets/wallets/wallet-connect/WalletConnectInnerUI.tsx similarity index 99% rename from packages/react-native/src/evm/wallets/wallets/wallet-connect/WalletConnectUI.tsx rename to packages/react-native/src/evm/wallets/wallets/wallet-connect/WalletConnectInnerUI.tsx index 4f3914bfbdb..daa01c94deb 100644 --- a/packages/react-native/src/evm/wallets/wallets/wallet-connect/WalletConnectUI.tsx +++ b/packages/react-native/src/evm/wallets/wallets/wallet-connect/WalletConnectInnerUI.tsx @@ -33,7 +33,7 @@ type WCWallet = { const DEVICE_WIDTH = Dimensions.get("window").width; const MODAL_HEIGHT = Dimensions.get("window").height * 0.5; -export function WalletConnectUI({ +export function WalletConnectInnerUI({ connected, projectId, goBack, diff --git a/packages/react-native/src/evm/wallets/wallets/wallet-connect/wallet-connect.tsx b/packages/react-native/src/evm/wallets/wallets/wallet-connect/wallet-connect.tsx index 2c30c39dd6c..c357cc6fb50 100644 --- a/packages/react-native/src/evm/wallets/wallets/wallet-connect/wallet-connect.tsx +++ b/packages/react-native/src/evm/wallets/wallets/wallet-connect/wallet-connect.tsx @@ -1,6 +1,16 @@ -import { WalletConfig, WalletOptions } from "@thirdweb-dev/react-core"; +import { + WalletConfig, + WalletOptions, + useAddress, + useConnect, + useConnectionStatus, + useCreateWalletInstance, + useSetConnectedWallet, + useSetConnectionStatus, + useWallet, +} from "@thirdweb-dev/react-core"; import { WalletConnect } from "./WalletConnect"; -import { WalletConnectUI } from "./WalletConnectUI"; +import { WalletConnectInnerUI } from "./WalletConnectInnerUI"; import { TW_WC_PROJECT_ID } from "../../../constants/walletConnect"; import { walletIds } from "@thirdweb-dev/wallets"; @@ -39,8 +49,65 @@ export const walletConnect = ( projectId, }), connectUI(props) { - return ; + return ; }, recommended: config?.recommended, }; }; + +export type WalletConnectUIProps = { + /** + * temporarily hide the ConnectModal + * This is useful when you want to open another modal and do not want to show the ConnectModal in the background + */ + hide: () => void; + + /** + * when the wallet is connected, call this function to indicate that the wallet is connected and it is safe to close the Modal + */ + connected: () => void; + + /** + * go back to the wallet selector screen in connect wallet modal + */ + goBack: () => void; + + /** + * `WalletConfig` object of the wallet + */ + walletConfig: WalletConfig; + + /** + * Array of supported wallets including this wallet. + */ + supportedWallets: WalletConfig[]; + + projectId: string; + + isVisible?: boolean; +}; + +export const WalletConnectUI = (props: WalletConnectUIProps) => { + const connect = useConnect(); + const connectionStatus = useConnectionStatus(); + const createWalletInstance = useCreateWalletInstance(); + const setConnectionStatus = useSetConnectionStatus(); + const setConnectedWallet = useSetConnectedWallet(); + const connectedWallet = useWallet(); + const address = useAddress(); + + return ( + connect(props.walletConfig, connectProps)} + connectionStatus={connectionStatus} + createWalletInstance={() => createWalletInstance(props.walletConfig)} + connectedWallet={connectedWallet as WalletConnect} + connectedWalletAddress={address} + /> + ); +}; diff --git a/packages/react/package.json b/packages/react/package.json index 95395a858c0..5a6ce96508b 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -63,7 +63,7 @@ "lint": "eslint src/ && bunx publint --strict --level warning", "fix": "eslint src/ --fix", "clean": "rm -rf dist/", - "generate-docs": "pnpm generate-docs:evm && pnpm generate-snippets", + "generate-docs": "mkdir -p etc && pnpm generate-docs:evm && pnpm generate-snippets", "generate-docs:evm": "api-extractor run --local --config ./config/api-extractor-evm.json && api-documenter markdown -i ./temp -o ./docs/evm && rm -rf ./temp-evm && mv ./temp ./temp-evm", "generate-snippets": "node ./scripts/generate-snippets-evm.mjs && node ./scripts/generate-feature-snippets-evm.mjs", "build": "tsc && preconstruct build", diff --git a/packages/react/scripts/typedoc.mjs b/packages/react/scripts/typedoc.mjs index 858debbc0bb..9942e3cace7 100644 --- a/packages/react/scripts/typedoc.mjs +++ b/packages/react/scripts/typedoc.mjs @@ -11,5 +11,4 @@ typedoc({ "**/packages/react-core/**", "**/packages/chains/**", ], - output: "both", // TODO: change this to 'json' when old portal is fully migrated to new portal }); diff --git a/packages/react/src/payments/components/CheckoutWithCard.tsx b/packages/react/src/payments/components/CheckoutWithCard.tsx index 9436a5bcd03..3e96c67e2c7 100644 --- a/packages/react/src/payments/components/CheckoutWithCard.tsx +++ b/packages/react/src/payments/components/CheckoutWithCard.tsx @@ -97,7 +97,20 @@ export const CheckoutWithCard = ({ options, configs, }); - }, [CheckoutWithCardIframeContainerRef.current]); + }, [ + appNameToUse, + clientId, + configs, + locale, + onBeforeModalOpen, + onCardDetailLoad, + onError, + onPaymentSuccess, + onPriceUpdate, + onReview, + options, + sdkClientSecret, + ]); return ( <> diff --git a/packages/react/src/payments/components/PaperCheckout.tsx b/packages/react/src/payments/components/PaperCheckout.tsx index d3d8a47e18d..61aae4eed35 100644 --- a/packages/react/src/payments/components/PaperCheckout.tsx +++ b/packages/react/src/payments/components/PaperCheckout.tsx @@ -141,7 +141,7 @@ export const PaperCheckout = ({ return () => { window.removeEventListener("message", handleMessage); }; - }, []); + }, [onCloseCheckout, onPaymentSuccess, onTransferSuccess]); // Build iframe URL with query params. const checkoutUrl = new URL(`/checkout/${checkoutId}`, PAPER_APP_URL); diff --git a/packages/react/src/payments/components/VerifyOwnershipWithPaper.tsx b/packages/react/src/payments/components/VerifyOwnershipWithPaper.tsx index c62aaa5c9d0..49282d7b505 100644 --- a/packages/react/src/payments/components/VerifyOwnershipWithPaper.tsx +++ b/packages/react/src/payments/components/VerifyOwnershipWithPaper.tsx @@ -84,7 +84,7 @@ export const VerifyOwnershipWithPaper: React.FC< return () => { window.removeEventListener("message", handleMessage); }; - }, []); + }, [onError, onSuccess, onWindowClose]); const url = new URL("/sdk/v1/login-with-paper", PAPER_APP_URL); url.searchParams.append("chainName", chainNameToUse); diff --git a/packages/react/src/payments/components/common/Modal.tsx b/packages/react/src/payments/components/common/Modal.tsx index 2596a0d0ef2..48957758149 100644 --- a/packages/react/src/payments/components/common/Modal.tsx +++ b/packages/react/src/payments/components/common/Modal.tsx @@ -36,7 +36,7 @@ export const Modal: React.FC<{ return () => { document.removeEventListener("keydown", keyDownHandler); }; - }, []); + }, [escapeToClose, onClose]); const additionalDialogClasses = isFullScreen ? "" : dialogContainedClasses; const dialogPanelBg = isFullScreen ? "transparent" : bgColor; diff --git a/packages/sdk/package.json b/packages/sdk/package.json index eb5e65fda4e..95c59498902 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -64,7 +64,7 @@ "lint": "eslint src/", "fix": "eslint src/ --fix", "clean": "rm -rf dist/", - "generate-docs": "pnpm generate-docs:evm && pnpm generate-snippets", + "generate-docs": "mkdir -p etc && pnpm generate-docs:evm && pnpm generate-snippets", "generate-docs:evm": "api-extractor run --local --config ./config/api-extractor-evm.json && api-documenter markdown -i ./temp -o ./docs/evm && rm -rf ./temp-evm && mv ./temp ./temp-evm", "generate-snippets": "node ./scripts/generate-snippets.mjs && node ./scripts/generate-feature-snippets-evm.mjs", "build": "tsc && preconstruct build", diff --git a/packages/sdk/scripts/typedoc.mjs b/packages/sdk/scripts/typedoc.mjs index bbf546317f9..a91b62212b5 100644 --- a/packages/sdk/scripts/typedoc.mjs +++ b/packages/sdk/scripts/typedoc.mjs @@ -6,5 +6,4 @@ import { typedoc } from "typedoc-gen"; typedoc({ entryPoints: ["src/index.ts"], exclude: ["**/packages/storage/**", "**/packages/chains/**"], - output: "both", // TODO: change this to 'json' when old portal is fully migrated to new portal }); diff --git a/packages/service-utils/src/core/services.ts b/packages/service-utils/src/core/services.ts index 4d5fcbe4e67..ef8e6c29509 100644 --- a/packages/service-utils/src/core/services.ts +++ b/packages/service-utils/src/core/services.ts @@ -44,7 +44,7 @@ export const SERVICE_DEFINITIONS = { // all actions allowed actions: [], }, - payments: { + checkout: { name: "checkout", title: "Checkouts", description: "Payments for easy web3 onboarding", diff --git a/packages/storage/package.json b/packages/storage/package.json index ce1c0617639..8773c989760 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -18,7 +18,6 @@ "format": "prettier --write 'src/**/*'", "lint": "eslint src/ && bunx publint --strict --level warning", "fix": "eslint src/ --fix", - "generate-docs": "api-extractor run --local && api-documenter markdown -i ./temp -o ./docs", "clean": "rm -rf dist/", "build": "tsc && preconstruct build", "test:all": "NODE_ENV=test SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --parallel './test/**/*.test.ts'", diff --git a/packages/storage/scripts/typedoc.mjs b/packages/storage/scripts/typedoc.mjs index e96c9913808..04ce9faa80a 100644 --- a/packages/storage/scripts/typedoc.mjs +++ b/packages/storage/scripts/typedoc.mjs @@ -4,5 +4,4 @@ import { typedoc } from "typedoc-gen"; typedoc({ entryPoints: ["src/index.ts"], exclude: [], - output: "both", // TODO: change this to 'json' when old portal is fully migrated to new portal }); diff --git a/packages/typedoc-gen/src/index.ts b/packages/typedoc-gen/src/index.ts index 23293abc624..0cd56be710b 100644 --- a/packages/typedoc-gen/src/index.ts +++ b/packages/typedoc-gen/src/index.ts @@ -1,7 +1,4 @@ import TypeDoc from "typedoc"; -import fs from "fs/promises"; -import { existsSync } from "fs"; -import path from "path"; /** * @@ -10,7 +7,6 @@ import path from "path"; export async function typedoc(options: { entryPoints: string[]; exclude: string[]; - output: "json" | "html" | "both"; }) { const outFile = "typedoc/documentation.json"; @@ -25,19 +21,5 @@ export async function typedoc(options: { throw new Error("Failed to create project"); } - if (options.output === "html" || options.output === "both") { - const docsFolder = path.resolve(process.cwd(), "typedoc/docs"); - - if (existsSync(docsFolder)) { - await fs.rm(docsFolder, { - recursive: true, - }); - } - - await app.generateDocs(project, "typedoc/docs"); - } - - if (options.output === "json" || options.output === "both") { - await app.generateJson(project, outFile); - } + await app.generateJson(project, outFile); } diff --git a/packages/wallets/scripts/typedoc.mjs b/packages/wallets/scripts/typedoc.mjs index 7d1d4f24cf4..b0ab82cfd45 100644 --- a/packages/wallets/scripts/typedoc.mjs +++ b/packages/wallets/scripts/typedoc.mjs @@ -13,5 +13,4 @@ typedoc({ "src/evm/wallets/local-wallet-node.ts", ], exclude: [], - output: "both", // TODO: change this to 'json' when old portal is fully migrated to new portal }); diff --git a/packages/wallets/tsconfig.json b/packages/wallets/tsconfig.json index cc61a04a066..5aee1e9ce9f 100644 --- a/packages/wallets/tsconfig.json +++ b/packages/wallets/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "@thirdweb-dev/tsconfig/sdk.json", "include": ["src", "types", "test"], - "exclude": ["dist", "build", "node_modules", "**/*.test.ts"], + "exclude": ["dist", "build", "node_modules"], "compilerOptions": { "noUncheckedIndexedAccess": true } diff --git a/scripts/generate-snippets/index.mjs b/scripts/generate-snippets/index.mjs new file mode 100644 index 00000000000..e9e31b7699f --- /dev/null +++ b/scripts/generate-snippets/index.mjs @@ -0,0 +1,303 @@ +// @ts-check +import fs from "fs"; +import createCSharpSnippet from "./utils/create-csharp-snippet.mjs"; +import createReactSnippet from "./utils/create-react-snippet-from-mapping.mjs"; +// Note: these JSON files are only available after running the `pnpm generate-docs` in root +import typescriptSnippets from "../../packages/sdk/docs/evm/snippets.json" assert { type: "json" }; +import reactWebSnippets from "../../packages/react/docs/evm/snippets.json" assert { type: "json" }; +import reactCoreSnippets from "../../packages/react-core/docs/evm/snippets.json" assert { type: "json" }; +import typescriptFeatureSnippets from "../../packages/sdk/docs/evm/feature_snippets.json" assert { type: "json" }; +import reactFeatureSnippets from "../../packages/react/docs/evm/feature_snippets.json" assert { type: "json" }; +import reactCoreFeatureSnippets from "../../packages/react-core/docs/evm/feature_snippets.json" assert { type: "json" }; + +// Maybe feature_snippets_sdk.json and feature_snippets_sdk.json is not being used anywhere +// TODO: if that's the case - stop generating them here + +const CLASSES = [ + "ThirdwebSDK", + "NFTCollection", + "Edition", + "TokenDrop", + "Token", + "NFTDrop", + "EditionDrop", + "Marketplace", + "MarketplaceDirect", + "MarketplaceAuction", + "Split", + "Pack", + "Vote", + "Multiwrap", + "ContractDeployer", + "ContractEvents", + "DelayedReveal", + "GasCostEstimator", + "RemoteStorage", + "ContractInterceptor", + "ContractMetadata", + "ContractRoles", + "SignatureDrop", + "SmartContract", + "WalletAuthenticator", + "UserWallet", +]; + +/** + * @typedef {{ + * name: string; + * summary: string; + * remarks: string; + * examples: { + * javascript: string; + * python: string; + * go: string; + * react: string; + * unity: string; + * }, + * reference: { + * javascript: string; + * python: string; + * go: string; + * react: string; + * } + * }} SnippetInfo + */ + +async function main() { + const typescript = typescriptSnippets; + const react = { + ...reactWebSnippets, + ...reactCoreSnippets, + }; + + const [python, go] = await Promise.all([ + getPythonSnippetsJSON(), + getGoSnippetsJSON(), + ]); + + const snippets = CLASSES.reduce((acc, contractName) => { + const data = { + name: contractName, + summary: "", + examples: {}, + methods: /** @type {SnippetInfo[]} */ ([]), + properties: /** @type {SnippetInfo[]} */ ([]), + reference: {}, + }; + + // Get snippets from every SDK + const tsExample = Object.values(typescript).find( + (snippet) => snippet.name.toLowerCase() === contractName.toLowerCase(), + ); + const reactExample = Object.values(react).find((snippet) => + snippet.name.toLowerCase().includes(contractName.toLowerCase()), + ); + const pythonExample = Object.values(python).find((snippet) => + snippet.name.toLowerCase().includes(contractName.toLowerCase()), + ); + const goExample = Object.values(go).find((snippet) => + snippet.name.toLowerCase().includes(contractName.toLowerCase()), + ); + + // Get contract summary from typescript docs + data.summary = tsExample?.summary || ""; + + // Get snippets for methods + data.methods = + tsExample?.methods?.map((method) => ({ + name: method.name, + summary: method.summary, + remarks: method.remarks, + examples: { + javascript: + tsExample?.methods?.find( + (m) => m.name.toLowerCase() === method.name.toLowerCase(), + )?.examples?.javascript || "", + python: + pythonExample?.methods?.find( + (m) => + m.name.replaceAll("_", "").toLowerCase() === + method.name.toLowerCase(), + )?.example || "", + go: + goExample?.methods?.find( + (m) => m.name.toLowerCase() === method.name.toLowerCase(), + )?.example || "", + react: + createReactSnippet(contractName, method.name).example || + (function gen() { + const ts = + tsExample?.methods?.find( + (m) => m.name.toLowerCase() === method.name.toLowerCase(), + )?.examples?.javascript || ""; + + if (ts.includes("sdk")) { + return `const sdk = useSDK();\n\n${ts}`; + } else { + return ts; + } + })(), + unity: createCSharpSnippet(contractName, method.name), + }, + reference: { + javascript: + tsExample?.methods + ?.find((m) => m.name.toLowerCase() === method.name.toLowerCase()) + ?.reference?.toLowerCase() || "", + python: + pythonExample?.methods?.find( + (m) => + m.name.replaceAll("_", "").toLowerCase() === + method.name.toLowerCase(), + )?.reference || "", + go: + goExample?.methods?.find( + (m) => m.name.toLowerCase() === method.name.toLowerCase(), + )?.reference || "", + react: + createReactSnippet(contractName, method.name).reference || + tsExample?.methods + ?.find((m) => m.name.toLowerCase() === method.name.toLowerCase()) + ?.reference?.toLowerCase() || + "", + }, + })) || []; + + // Get snippets for properties + data.properties = + tsExample?.properties?.map((property) => ({ + name: property.name, + summary: property.summary, + remarks: property.remarks, + examples: { + javascript: + tsExample?.properties?.find( + (p) => p.name.toLowerCase() === property.name.toLowerCase(), + )?.examples?.javascript || "", + python: + pythonExample?.properties?.find( + (p) => + p.name.replaceAll("_", "").toLowerCase() === + property.name.toLowerCase(), + )?.example || "", + go: + goExample?.properties?.find( + (p) => p.name.toLowerCase() === property.name.toLowerCase(), + )?.example || "", + react: + createReactSnippet(contractName, property.name).example || + (function gen() { + const ts = + tsExample?.properties?.find( + (p) => p.name.toLowerCase() === property.name.toLowerCase(), + )?.examples?.javascript || ""; + + if (ts.includes("sdk")) { + return `const sdk = useSDK();\n\n${ts}`; + } else { + return ts; + } + })(), + unity: createCSharpSnippet(contractName, property.name), + }, + reference: { + javascript: + tsExample?.properties + ?.find( + (p) => p.name.toLowerCase() === property.name.toLowerCase(), + ) + ?.reference?.toLowerCase() || "", + python: + pythonExample?.properties?.find( + (p) => + p.name.replaceALl("_", "").toLowerCase() === + property.name.toLowerCase(), + )?.reference || "", + go: + goExample?.properties?.find( + (p) => p.name.toLowerCase() === property.name.toLowerCase(), + )?.reference || "", + react: + createReactSnippet(contractName, property.name).reference || + tsExample?.properties + ?.find( + (p) => p.name.toLowerCase() === property.name.toLowerCase(), + ) + ?.reference?.toLowerCase() || + "", + }, + })) || []; + + // Add reference for typescript contract interface + if (tsExample?.reference) { + data.reference.typescript = tsExample.reference; + } + + // Add reference for python contract interface + if (pythonExample?.reference) { + data.reference.python = pythonExample.reference; + } + + // Add reference for go contract interface + if (goExample?.reference) { + data.reference.go = goExample.reference; + } + + // Add setup examples for each SDK + data.examples = { + ...(tsExample?.examples || {}), + ...(reactExample?.examples?.javascript + ? { react: reactExample.examples.javascript } + : {}), + ...(pythonExample?.example ? { python: pythonExample.example } : {}), + ...(goExample?.example ? { go: goExample.example } : {}), + }; + + acc[contractName] = data; + + return acc; + }, {}); + + // snippets.json + fs.writeFileSync( + `${process.cwd()}/snippets/snippets.json`, + JSON.stringify(snippets, null, 2), + ); + + // feature_snippets_sdk + fs.writeFileSync( + `${process.cwd()}/snippets/feature_snippets_sdk.json`, + JSON.stringify(typescriptFeatureSnippets, null, 2), + ); + + // feature_snippets_react + fs.writeFileSync( + `${process.cwd()}/snippets/feature_snippets_react.json`, + JSON.stringify( + { + ...reactFeatureSnippets, + ...reactCoreFeatureSnippets, + }, + null, + 2, + ), + ); +} + +async function getPythonSnippetsJSON() { + const res = await fetch( + "https://raw.githubusercontent.com/thirdweb-dev/python-sdk/main/docs/docs/snippets.json", + ); + const data = await res.json(); + return data; +} + +async function getGoSnippetsJSON() { + const res = await fetch( + "https://raw.githubusercontent.com/thirdweb-dev/go-sdk/main/docs/snippets.json", + ); + const data = await res.json(); + return data; +} + +main(); diff --git a/scripts/generate-snippets/utils/create-csharp-snippet.mjs b/scripts/generate-snippets/utils/create-csharp-snippet.mjs new file mode 100644 index 00000000000..a446f3de1b9 --- /dev/null +++ b/scripts/generate-snippets/utils/create-csharp-snippet.mjs @@ -0,0 +1,366 @@ +const mapping = { + ThirdwebSDK: { + fromPrivateKey: + "Unity does not support instantiating the SDK from a private key. Instantiate the SDK in read-only mode and then connect the user's Wallet.", + fromSigner: + "Unity does not support instantiating the SDK from a signer. Instantiate the SDK in read-only mode and then connect the user's Wallet.", + fromWallet: + "Unity does not support instantiating the SDK from a Wallet. Instantiate the SDK in read-only mode and then connect the user's Wallet.", + getBalance: "CurrencyValue balance = await sdk.Wallet.GetBalance();", + getContract: `// Ensure your sdk is initialized to the same network as the contract +Contract contract = sdk.GetContract(""); + +// For marketplaces and packs: +Marketplace marketplace = contract.marketplace; +Pack pack = contract.pack;`, + getContractFromAbi: `Contract contract = sdk.GetContract("", "");`, + }, + NFTCollection: { + burn: 'var tokenId = "0";\nvar result = await contract.ERC721.Burn(tokenId);', + mintBatchTo: undefined, + mintTo: + '// Address of the wallet you want to mint the NFT to\nvar walletAddress = "{{wallet_address}}";\n\n// Custom metadata of the NFT, note that you can fully customize this metadata with other properties.\nvar metadata = new NFTMetadata() {\n name = "Cool NFT",\n description = "This is a cool NFT",\n image = "" \n};\n\nvar tx = await contract.ERC721.MintTo(walletAddress, metadata);', + balanceOf: + 'var walletAddress = "{{wallet_address}}";\nvar balance = await contract.ERC721.BalanceOf(walletAddress);\nDebug.Log(balance);', + get: 'var tokenId = "0";\nvar nft = await contract.ERC721.Get(tokenId);', + getAll: "var nfts = await contract.ERC721.GetAll();\nDebug.Log(nfts);", + getOwned: + '// Address of the Wallet to get the NFTs of\nvar address = "{{wallet_address}}";\nvar nfts = await contract.ERC721.GetOwned(address);\nDebug.Log(nfts);', + transfer: + 'var walletAddress = "{{wallet_address}}";\nvar tokenId = "0";\nawait contract.ERC721.Transfer(walletAddress, tokenId);', + }, + Edition: { + burn: 'var tokenId = "0";\nint amount = 1;\nvar result = await contract.ERC1155.Burn(tokenId, amount);', + getAll: "var nfts = await contract.ERC1155.GetAll();", + getOwned: + '// Address of the Wallet to get the NFTs of\nvar address = "{{wallet_address}}";\nvar nfts = await contract.ERC1155.GetOwned(address);', + mintBatchTo: undefined, + mintTo: + '// Address of the wallet you want to mint the NFT to\r\nvar toAddress = "{{wallet_address}}";\r\n// Custom metadata of the NFT, note that you can fully customize this metadata with other properties.\r\nvar metadata =\r\n new NFTMetadata()\r\n {\r\n name = "Cool NFT",\r\n description = "This is a cool NFT",\r\n image = ""\r\n };\r\nvar metadataWithSupply =\r\n new NFTMetadataWithSupply() { metadata = metadata, supply = 1 };\r\nvar tx = await contract.ERC1155.MintTo(toAddress, metadataWithSupply);', + airdrop: undefined, + balanceOf: + '// Address of the Wallet to check NFT balance\nvar walletAddress = "{{wallet_address}}";\nvar tokenId = "0"; // Id of the NFT to check\nvar balance = await contract.ERC1155.BalanceOf(walletAddress, tokenId);', + get: 'var nft = await contract.ERC1155.Get("0");', + transfer: + '// Address of the Wallet you want to send the NFT to\nvar toAddress = "{{wallet_address}}";\nvar tokenId = "0"; // The token ID of the NFT you want to send\nvar amount = 3; // How many copies of the NFTs to transfer\nawait contract.ERC1155.Transfer(toAddress, tokenId, amount);', + }, + TokenDrop: { + burnFrom: undefined, + burnTokens: + '// The amount of this token you want to burn\nvar amount = "1.2";\n\nawait contract.ERC20.Burn(amount);', + claimTo: + 'var address = "{{wallet_address}}"; // address of the wallet you want to claim the NFTs\nvar quantity = 1; // how many tokens you want to claim\n\nvar tx = await contract.ERC20.ClaimTo(address, quantity);\nvar receipt = tx.receipt; // the transaction receipt', + allowance: + '// Address of the Wallet to check token allowance\nvar spenderAddress = "0x...";\nvar allowance = await contract.ERC20.Allowance(spenderAddress);', + allowanceOf: + '// Address of the Wallet who owns the funds\nvar owner = "{{wallet_address}}";\n// Address of the Wallet to check token allowance\nvar spender = "0x...";\nvar allowance = await contract.ERC20.AllowanceOf(owner, spender);', + balance: "var balance = await contract.ERC20.Balance();", + balanceOf: + '// Address of the Wallet to check token balance\nvar walletAddress = "{{wallet_address}}";\nvar balance = await contract.ERC20.BalanceOf(walletAddress);', + get: "var token = await contract.ERC20.Get();", + setAllowance: + '// Address of the Wallet to allow transfers from\nvar spenderAddress = "0x...";\n// The number of tokens to give as allowance\nvar amount = "100";\nawait contract.ERC20.SetAllowance(spenderAddress, amount);', + totalSupply: "var balance = await contract.ERC20.TotalSupply();", + transfer: + '// Address of the Wallet you want to send the tokens to\nvar toAddress = "0x...";\n// The amount of tokens you want to send\nvar amount = "0.1";\nawait contract.ERC20.Transfer(toAddress, amount);', + transferBatch: undefined, + transferFrom: undefined, + }, + Token: { + burn: '// The amount of this token you want to burn\nvar amount = "1.2";\n\nawait contract.ERC20.Burn(amount);', + burnFrom: undefined, + mintBatchTo: undefined, + mintTo: + 'var toAddress = "{{wallet_address}}"; // Address of the Wallet you want to mint the tokens to\nvar amount = "1.5"; // The amount of this token you want to mint\n\nawait contract.ERC20.MintTo(toAddress, amount);', + allowance: + '// Address of the Wallet to check token allowance\nvar spenderAddress = "0x...";\nvar allowance = await contract.ERC20.Allowance(spenderAddress);', + allowanceOf: + '// Address of the Wallet who owns the funds\nvar owner = "{{wallet_address}}";\n// Address of the Wallet to check token allowance\nvar spender = "0x...";\nvar allowance = await contract.ERC20.AllowanceOf(owner, spender);', + balance: "var balance = await contract.ERC20.Balance();", + balanceOf: + '// Address of the Wallet to check token balance\nvar walletAddress = "{{wallet_address}}";\nvar balance = await contract.ERC20.BalanceOf(walletAddress);', + get: "var token = await contract.ERC20.Get();", + setAllowance: + '// Address of the Wallet to allow transfers from\nvar spenderAddress = "0x...";\n// The number of tokens to give as allowance\nvar amount = "100";\nawait contract.ERC20.SetAllowance(spenderAddress, amount);', + totalSupply: "var balance = await contract.ERC20.TotalSupply();", + transfer: + '// Address of the Wallet you want to send the tokens to\nvar toAddress = "0x...";\n// The amount of tokens you want to send\nvar amount = "0.1";\nawait contract.ERC20.Transfer(toAddress, amount);', + transferBatch: undefined, + transferFrom: undefined, + }, + NFTDrop: { + balanceOf: + 'var walletAddress = "{{wallet_address}}";\nvar balance = await contract.ERC721.BalanceOf(walletAddress);\nDebug.Log(balance);', + burn: 'var tokenId = "0";\nvar result = await contract.ERC721.Burn(tokenId);', + claimTo: + 'var address = "{{wallet_address}}"; // address of the wallet you want to claim the NFTs\nvar quantity = 1; // how many unique NFTs you want to claim\n\nvar tx = await contract.ERC721.ClaimTo(address, quantity);', + createBatch: undefined, + get: 'var tokenId = "0";\nvar nft = await contract.ERC721.Get(tokenId);', + getAllClaimed: undefined, + getAllUnclaimed: undefined, + totalClaimedSupply: + "var claimedNFTCount = await contract.ERC721.TotalClaimedSupply();", + totalUnclaimedSupply: + "var unclaimedNFTCount = await contract.ERC721.TotalUnclaimedSupply();", + transfer: + 'var walletAddress = "{{wallet_address}}";\nvar tokenId = "0";\nawait contract.ERC721.Transfer(walletAddress, tokenId);', + getAll: "var nfts = await contract.ERC721.GetAll();\nDebug.Log(nfts);", + getOwned: + '// Address of the Wallet to get the NFTs of\nvar address = "{{wallet_address}}";\nvar nfts = await contract.ERC721.GetOwned(address);\nDebug.Log(nfts);', + }, + EditionDrop: { + burnTokens: + 'var tokenId = "0";\nint amount = 1;\nvar result = await contract.ERC1155.Burn(tokenId, amount);', + claimTo: + 'var address = "{{wallet_address}}"; // address of the wallet you want to claim the NFTs\nvar quantity = 1; // how many unique NFTs you want to claim\n\nvar tx = await contract.ERC1155.ClaimTo(address, quantity);', + createBatch: undefined, + getAll: "var nfts = await contract.ERC1155.GetAll();", + getOwned: + '// Address of the Wallet to get the NFTs of\nvar address = "{{wallet_address}}";\nvar nfts = await contract.ERC1155.GetOwned(address);', + airdrop: undefined, + balanceOf: + '// Address of the Wallet to check NFT balance\nvar walletAddress = "{{wallet_address}}";\nvar tokenId = "0"; // Id of the NFT to check\nvar balance = await contract.ERC1155.BalanceOf(walletAddress, tokenId);', + get: 'var nft = await contract.ERC1155.Get("0");', + transfer: + '// Address of the Wallet you want to send the NFT to\nvar toAddress = "{{wallet_address}}";\nvar tokenId = "0"; // The token ID of the NFT you want to send\nvar amount = 3; // How many copies of the NFTs to transfer\nawait contract.ERC1155.Transfer(toAddress, tokenId, amount);', + }, + Marketplace: { + buyoutListing: + '// The listing ID of the asset you want to buy\nvar listingId = "0";\n// Quantity of the asset you want to buy\nvar quantityDesired = 1;\n\nawait contract.BuyoutListing(listingId, quantityDesired);', + getActiveListings: "var listings = await contract.GetActiveListings();", + getAllListings: "var listings = await contract.GetAllListings();", + getListing: + 'var listingId = "0";\nvar listing = await contract.GetListing(listingId);', + getOffers: + 'string listingId = "0";\r\nawait contract.GetOffers(listingId);', + makeOffer: + '// The listing ID of the asset you want to offer on\nvar listingId = "0";\n// The price you are willing to offer per token\nvar pricePerToken = 0.5;\n// The quantity of tokens you want to receive for this offer\nvar quantity = 1;\n\nawait contract.MakeOffer(\n listingId,\n pricePerToken,\n quantity,\n);', + setBidBufferBps: undefined, + setTimeBufferInSeconds: undefined, + }, + MarketplaceDirect: { + acceptOffer: undefined, + buyoutListing: + '// The listing ID of the asset you want to buy\r\nvar listingId = "0";\r\n// Quantity of the asset you want to buy\r\nvar quantityDesired = 1;\r\nawait contract.BuyListing(listingId, quantityDesired);', + cancelListing: + 'string listingId = "0";\r\nawait contract.direct.CancelListing(listingId);', + createListing: + 'await contract\r\n .direct\r\n .CreateListing(new NewDirectListing()\r\n {\r\n assetContractAddress = "0x...",\r\n buyoutPricePerToken = "1",\r\n currencyContractAddress = "0x...",\r\n listingDurationInSeconds = 3600,\r\n quantity = 1,\r\n reservePricePerToken = "0",\r\n startTimestamp = 0,\r\n tokenId = "1",\r\n type = "direct"\r\n });', + makeOffer: + 'string listingId = "0";\r\nstring price = "0.1";\r\nint quantity = 1;\r\nawait contract.MakeOffer(listingId, price, quantity);', + }, + MarketplaceAuction: { + buyoutListing: + '// The listing ID of the asset you want to buy\r\nvar listingId = "0";\r\n// Quantity of the asset you want to buy\r\nvar quantityDesired = 1;\r\nawait contract.BuyListing(listingId, quantityDesired);', + cancelListing: + 'string listingId = "0";\r\nawait contract.auction.CancelListing(listingId);', + closeListing: + 'string listingId = "0";\r\nawait contract.auction.ExecuteSale(listingId);', + createListing: + 'await contract\r\n .direct\r\n .CreateListing(new NewDirectListing()\r\n {\r\n assetContractAddress = "0x...",\r\n buyoutPricePerToken = "1",\r\n currencyContractAddress = "0x...",\r\n listingDurationInSeconds = 3600,\r\n quantity = 1,\r\n reservePricePerToken = "0",\r\n startTimestamp = 0,\r\n tokenId = "1",\r\n type = "auction"\r\n });', + executeSale: + 'string listingId = "0";\r\nawait contract.auction.ExecuteSale(listingId);', + getWinner: + 'string listingId = "0";\r\nawait contract.auction.GetWinner(listingId);', + getWinningBid: + 'string listingId = "0";\r\nawait contract.auction.GetWinningBid(listingId);', + makeBid: + 'string listingId = "0";\r\nstring price = "0.1";\r\nint quantity = 1;\r\nawait contract.MakeOffer(listingId, price, quantity);', + }, + Split: { + balanceOf: + "// Split is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + balanceOfToken: + "// Split is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + distribute: + "// Split is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + distributeToken: + "// Split is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + getAllRecipients: + "// Split is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + withdraw: + "// Split is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + }, + Pack: { + addPackContents: + '// Pack token ID\r\nstring packId = "0";\r\n\r\nawait contract\r\n .AddPackContents(packId,\r\n new PackRewards()\r\n {\r\n erc1155Rewards =\r\n new List {\r\n new ERC1155Reward()\r\n {\r\n contractAddress = "0x...",\r\n tokenId = "0",\r\n quantityPerReward = "1"\r\n }\r\n },\r\n erc721Rewards =\r\n new List {\r\n new ERC721Reward()\r\n { contractAddress = "0x...", tokenId = "0" }\r\n },\r\n erc20Rewards =\r\n new List {\r\n new ERC20Reward()\r\n { contractAddress = "0x...", quantityPerReward = "1" }\r\n }\r\n });', + create: + 'await contract\r\n .Create(new NewPackInput()\r\n {\r\n packMetadata =\r\n new NFTMetadata()\r\n {\r\n name = "My Pack",\r\n description = "My Pack Description",\r\n image = "https://myimage.com",\r\n external_url = "https://myimage.com"\r\n },\r\n erc1155Rewards =\r\n new List {\r\n new ERC1155Contents()\r\n {\r\n contractAddress = "0x...",\r\n tokenId = "0",\r\n quantityPerReward = "1"\r\n }\r\n },\r\n erc721Rewards =\r\n new List {\r\n new ERC721Contents()\r\n {\r\n contractAddress = "0x...",\r\n tokenId = "0"\r\n }\r\n },\r\n erc20Rewards =\r\n new List {\r\n new ERC20Contents()\r\n {\r\n contractAddress = "0x...",\r\n quantityPerReward = "1",\r\n totalRewards = "1"\r\n }\r\n }\r\n });', + createTo: + '// The address to check the funds of\r\nvar address = "{{wallet_address}}";\r\nawait contract\r\n .CreateTo(address,\r\n new NewPackInput()\r\n {\r\n packMetadata =\r\n new NFTMetadata()\r\n {\r\n name = "My Pack",\r\n description = "My Pack Description",\r\n image = "https://myimage.com",\r\n external_url = "https://myimage.com"\r\n },\r\n erc1155Rewards =\r\n new List {\r\n new ERC1155Contents()\r\n {\r\n contractAddress = "0x...",\r\n tokenId = "0",\r\n quantityPerReward = "1"\r\n }\r\n },\r\n erc721Rewards =\r\n new List {\r\n new ERC721Contents()\r\n {\r\n contractAddress = "0x...",\r\n tokenId = "0"\r\n }\r\n },\r\n erc20Rewards =\r\n new List {\r\n new ERC20Contents()\r\n {\r\n contractAddress = "0x...",\r\n quantityPerReward = "1",\r\n totalRewards = "1"\r\n }\r\n }\r\n });', + get: 'var tokenId = "0";\nvar pack = await contract.Get(tokenId);', + getAll: "var packs = await contract.GetAll();", + getOwned: + '// Address of the Wallet to get the packs of\nvar address = "{{wallet_address}}";\nvar packs = await contract.GetOwned(address);', + getPackContents: + 'var packId = "0";\nvar contents = await contract.GetPackContents(packId);\nDebug.Log(contents.erc20Rewards);\nDebug.Log(contents.erc721Rewards);\nDebug.Log(contents.erc1155Rewards);', + open: 'var tokenId = "0";\nvar amount = "1";\nvar tx = await contract.Open(tokenId, amount);', + airdrop: undefined, + balanceOf: + '// Address of the Wallet to check NFT balance\nvar walletAddress = "{{wallet_address}}";\nvar tokenId = "0"; // Id of the NFT to check\nvar balance = await contract.BalanceOf(walletAddress, tokenId);', + transfer: + '// Address of the Wallet you want to send the NFT to\nvar toAddress = "{{wallet_address}}";\nvar tokenId = "0"; // The token ID of the NFT you want to send\nvar amount = 3; // How many copies of the NFTs to transfer\nawait contract.Transfer(toAddress, tokenId, amount);', + }, + Vote: { + canExecute: + "// Vote is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + execute: + "// Vote is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + getAll: + "// Vote is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + hasVoted: + "// Vote is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + propose: + "// Vote is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + vote: "// Vote is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + }, + Multiwrap: { + getWrappedContents: + "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + unwrap: + "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + wrap: "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + balanceOf: + "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + get: "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + getAll: + "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + getOwned: + "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + transfer: + "// Multiwrap is not yet supported in Unity. You can still use the contract.Read and contract.Write functions to call functions directly.", + }, + ContractDeployer: { + deployEdition: + 'await sdk\r\n .deployer\r\n .DeployEdition(new NFTContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deployEditionDrop: + 'await sdk\r\n .deployer\r\n .DeployEditionDrop(new NFTContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deployMarketplace: + 'await sdk\r\n .deployer\r\n .DeployMarketplace(new MarketplaceContractDeployMetadata()\r\n { name = "My Collection" });', + deployMultiwrap: undefined, + deployNFTCollection: + 'await sdk\r\n .deployer\r\n .DeployNFTCollection(new NFTContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deployNFTDrop: + 'await sdk\r\n .deployer\r\n .DeployNFTDrop(new NFTContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deployPack: + 'await sdk\r\n .deployer\r\n .DeployPack(new NFTContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deploySignatureDrop: + 'await sdk\r\n .deployer\r\n .DeploySignatureDrop(new NFTContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deploySplit: undefined, + deployToken: + 'await sdk\r\n .deployer\r\n .DeployToken(new TokenContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deployTokenDrop: + 'await sdk\r\n .deployer\r\n .DeployTokenDrop(new TokenContractDeployMetadata()\r\n { name = "My Collection", primary_sale_recipient = "0x..." });', + deployVote: undefined, + }, + ContractEvents: { + addEventListener: undefined, + addTransactionListener: undefined, + getAllEvents: undefined, + getEvents: undefined, + listenToAllEvents: undefined, + removeAllListeners: undefined, + + removeEventListener: undefined, + removeTransactionListener: undefined, + }, + DelayedReveal: { + createDelayedRevealBatch: undefined, + getBatchesToReveal: undefined, + reveal: undefined, + }, + GasCostEstimator: { + currentGasPriceInGwei: undefined, + gasCostOf: undefined, + gasLimitOf: undefined, + }, + ContractInterceptor: { + overrideNextTransaction: undefined, + }, + ContractMetadata: { + get: undefined, + set: undefined, + update: undefined, + }, + ContractRoles: { + get: undefined, + getAll: undefined, + grant: undefined, + revoke: undefined, + setAll: undefined, + }, + SignatureDrop: { + burn: 'var tokenId = "0";\nvar result = await contract.ERC721.Burn(tokenId);', + claimTo: + 'var address = "{{wallet_address}}"; // address of the wallet you want to claim the NFTs\nvar quantity = 1; // how many unique NFTs you want to claim\n\nvar tx = await contract.ERC721.ClaimTo(address, quantity);', + createBatch: undefined, + getAllClaimed: undefined, + getAllUnclaimed: undefined, + totalClaimedSupply: + "var claimedNFTCount = await contract.ERC721.TotalClaimedSupply();", + totalUnclaimedSupply: + "var unclaimedNFTCount = await contract.ERC721.TotalUnclaimedSupply();", + balanceOf: + 'var walletAddress = "{{wallet_address}}";\nvar balance = await contract.ERC721.BalanceOf(walletAddress);\nDebug.Log(balance);', + get: 'var tokenId = "0";\nvar nft = await contract.ERC721.Get(tokenId);', + getAll: "var nfts = await contract.ERC721.GetAll();\nDebug.Log(nfts);", + getOwned: + '// Address of the Wallet to get the NFTs of\nvar address = "{{wallet_address}}";\nvar nfts = await contract.ERC721.GetOwned(address);\nDebug.Log(nfts);', + transfer: + 'var walletAddress = "{{wallet_address}}";\nvar tokenId = "0";\nawait contract.ERC721.Transfer(walletAddress, tokenId);', + signature: + 'var meta = new NFTMetadata()\n{\n name = "Unity NFT",\n description = "Minted From Unity (signature)",\n image = "ipfs://QmbpciV7R5SSPb6aT9kEBAxoYoXBUsStJkMpxzymV4ZcVc"\n};\nstring connectedAddress = await sdk.wallet.GetAddress();\nvar payload = new ERC721MintPayload(connectedAddress, meta);\nvar signature = await contract.ERC721.signature.Generate(payload); // typically generated on the backend \n// Provide the signature you generated above to the Mint function:\nvar result = await contract.ERC721.signature.Mint(signature);', + }, + SmartContract: { + call: '// Write operations\nawait contract.Write("functionName", "arg1", "arg2", "arg3");\n\n// Read operations (place expected return type between <>)\nvar result = await contract.Read("functionName", "arg1", "arg2", "arg3");', + }, + WalletAuthenticator: { + Authenticate: 'await sdk.wallet.Authenticate("example.org")', + GenerateAuthToken: + "// Generating an authentication token is a server-side admin operation.\n For this reason, it is not available in the Unity SDK.", + login: "// Login is not available in the Unity SDK.", + verify: + "// Generating an authentication token is a server-side admin operation.\n For this reason, it is not available in the Unity SDK.", + }, + UserWallet: { + balance: "await sdk.wallet.GetBalance();", + getAddress: "await sdk.wallet.GetAddress();", + recoverAddress: 'await sdk.wallet.RecoverAddress("message", "signature");', + sign: 'await sdk.wallet.Sign("message");', + transfer: 'await sdk.wallet.Transfer("to", "amount", "currencyAddress");', + }, + ContractMetadata: { + get: undefined, + set: undefined, + update: undefined, + }, + PlatformFee: { + get: undefined, + }, + PrimarySale: { + getRecipient: undefined, + setRecipient: undefined, + }, + Permissions: { + get: undefined, + getAll: undefined, + grant: undefined, + revoke: undefined, + setAll: undefined, + }, + Royalty: { + getDefaultRoyaltyInfo: undefined, + getTokenRoyaltyInfo: undefined, + setDefaultRoyaltyInfo: undefined, + setTokenRoyaltyInfo: undefined, + }, +}; + +/** + * Take in a TypeScript SDK class name and method name and return a C# snippet + * @param {string} className + * @param {string} methodName + */ +export default function createCSharpSnippet(className, methodName) { + return mapping?.[className]?.[methodName]; +} diff --git a/scripts/generate-snippets/utils/create-react-snippet-from-mapping.mjs b/scripts/generate-snippets/utils/create-react-snippet-from-mapping.mjs new file mode 100644 index 00000000000..a37336a188a --- /dev/null +++ b/scripts/generate-snippets/utils/create-react-snippet-from-mapping.mjs @@ -0,0 +1,321 @@ +// Read in the react snippets +import reactSnippets from "../../../packages/react/docs/evm/snippets.json" assert { type: "json" }; +import reactCoreSnippets from "../../../packages/react-core/docs/evm/snippets.json" assert { type: "json" }; + +// Takes in a two keys and returns the react snippet defined here for that value +// TODO: This logic **Probably** doesn't belong here. +// We should add some way of mapping this in the react SDK itself +// that way it is more maintainable. + +const reactMapping = { + NFTCollection: { + mainHook: "useNFTCollection", + subHooks: { + // methods + burn: "", + getAll: "useNFTs", + mintBatchTo: "", + mintTo: "useMintNFT", + balanceOf: "useNFTBalance", + get: "useNFT", + getOwned: "useOwnedNFTs", + transfer: "", + // properties + royalties: "", + signature: "", + }, + }, + Edition: { + mainHook: "useEdition", + subHooks: { + // methods + burn: "", + getAll: "useNFTs", + getOwned: "useOwnedNFTs", + mintBatchTo: "", + mintTo: "useMintNFT", + airdrop: "", + balanceOf: "useNFTBalance", + get: "useNFT", + transfer: "", + // properties + royalties: "", + signature: "", + }, + }, + TokenDrop: { + mainHook: "useTokenDrop", + subHooks: { + // methods + burn: "", + claimTo: "", + allowance: "", + allowanceOf: "", + balance: "", + balanceOf: "useTokenBalance", + get: "", + setAllowance: "", + totalSupply: "", + transfer: "", + transferBatch: "", + transferFrom: "", + // properties + claimConditions: "", + }, + }, + Token: { + mainHook: "useToken", + subHooks: { + // methods + burn: "", + burnFrom: "", + mintBatchTo: "", + mintTo: "", + allowance: "", + allowanceOf: "", + balance: "", + balanceOf: "useTokenBalance", + get: "", + setAllowance: "", + totalSupply: "", + transfer: "", + transferBatch: "", + transferFrom: "", + // properties + signature: "", + }, + }, + NFTDrop: { + mainHook: "useNFTDrop", + subHooks: { + // methods + burn: "", + claimTo: "useClaimNFT", + createBatch: "", + getAll: "useNFTs", + getAllClaimed: "useClaimedNFTs", + getAllUnclaimed: "useUnclaimedNFTs", + getOwned: "useOwnedNFTs", + totalClaimedSupply: "useClaimedNFTSupply", + totalUnclaimedSupply: "useUnclaimedNFTSupply", + balanceOf: "useNFTBalance", + get: "useNFT", + transfer: "", + // properties + claimConditions: "", + revealer: "", + royalties: "", + }, + }, + EditionDrop: { + mainHook: "useEditionDrop", + subHooks: { + // methods + burn: "", + claimTo: "useClaimNFT", + createBatch: "", + getAll: "useNFTs", + getOwned: "", + airdrop: "", + balanceOf: "useNFTBalance", + get: "", + transfer: "", + // properties + claimConditions: "", + royalties: "", + }, + }, + Marketplace: { + mainHook: "useMarketplace", + subHooks: { + // methods + buyoutListing: "", + getActiveListings: "useActiveListings", + getAllListings: "useListings", + getListing: "useListing", + setBidBufferBps: "", + setTimeBufferInsSeconds: "", + // properties + auction: "", + direct: "", + }, + }, + MarketplaceDirect: { + mainHook: "useMarketplace", + subHooks: { + // methods + acceptOffer: "", + buyoutListing: "useBuyNow", + cancelListing: "", + createListing: "", + makeOffer: "", + }, + }, + MarketplaceAuction: { + mainHook: "useMarketplace", + subHooks: { + // methods + buyoutListing: "", + cancelListing: "", + closeListing: "", + createListing: "", + getWinner: "", + getWinningBid: "useWinningBid", + makeBid: "useMakeBid", + }, + }, + Split: { + mainHook: "useSplit", + subHooks: { + // methods + balanceOf: "", + balanceOfToken: "", + distribute: "", + distributeToken: "", + getAllRecipients: "", + withdraw: "", + }, + }, + Pack: { + mainHook: "usePack", + subHooks: { + // methods + createTo: "", + getAll: "useNFTs", + getOwned: "useOwnedNFTs", + getPackContents: "", + open: "", + airdrop: "", + balanceOf: "useNFTBalance", + get: "useNFT", + transfer: "", + // properties + royalties: "", + }, + }, + Vote: { + mainHook: "useVote", + subHooks: { + // methods + canExecute: "", + execute: "", + getAll: "", + hasVoted: "", + propose: "", + vote: "", + }, + }, + Multiwrap: { + mainHook: "useMultiwrap", + subHooks: { + // methods + getAll: "useNFTs", + getWrappedContents: "", + unwrap: "", + wrap: "", + balanceOf: "useNFTBalance", + get: "useNFT", + transfer: "", + }, + }, + SignatureDrop: { + mainHook: "useSignatureDrop", + subHooks: { + // methods + claimTo: "useClaimNFT", + createBatch: "", + getAll: "useNFTs", + getAllClaimed: "useClaimedNFTs", + getAllUnclaimed: "useUnclaimedNFTs", + getOwned: "useOwnedNFTs", + totalClaimedSupply: "useClaimedNFTSupply", + totalUnclaimedSupply: "useUnclaimedNFTSupply", + balanceOf: "useNFTBalance", + get: "useNFT", + transfer: "", + // properties + claimConditions: "", + revealer: "", + royalties: "", + signature: "", + }, + }, + ContractEvents: { + mainHook: "useAllContractEvents", + subHooks: { + // methods + addEventListener: "useContractEvents", + removeEventListener: "", + addTransactionListener: "", + getAllEvents: "useAllContractEvents", + getEvents: "useContractEvents", + listenToAllEvents: "useAllContractEvents", + removeAllListeners: "", + removeEventListener: "", + removeTransactionListener: "", + }, + }, + ContractMetadata: { + mainHook: "useContractMetadata", + subHooks: { + // methods + get: "useContractMetadata", + set: "", + update: "", + }, + }, + ContractRoles: { + mainHook: "useRoleMembers", + subHooks: { + // methods + get: "useRoleMembers", + getAll: "useAllRoleMembers", + grant: "useGrantRole", + revoke: "useRevokeRole", + setAll: "useSetAllRoleMembers", + }, + }, + SmartContract: { + mainHook: "useContract", + subHooks: { + // methods + call: "useContractWrite", + }, + }, + UserWallet: { + mainHook: "useContract", + subHooks: { + // methods + getAddress: "useAddress", + }, + }, + ThirdwebSDK: { + mainHook: "useContract", + subHooks: { + // methods + getContract: "useContract", + call: "useContractWrite", + }, + }, + SmartContract: { + mainHook: "useContract", + subHooks: { + // methods + call: "useContractWrite", + }, + }, +}; + +export default function createReactSnippet(contractName, methodName) { + const mainHookName = reactMapping[contractName]?.mainHook; + const reactSubhookName = reactMapping[contractName]?.subHooks[methodName]; + + const snippets = { ...reactSnippets, ...reactCoreSnippets }; + const reactObject = snippets?.[mainHookName]; + + const reactSubhooks = reactObject?.subhooks; + + const reactSnippet = reactSubhooks?.find((s) => s.name === reactSubhookName); + + return reactSnippet ? reactSnippet : {}; +} diff --git a/snippets/readme.md b/snippets/readme.md new file mode 100644 index 00000000000..503d6e1c856 --- /dev/null +++ b/snippets/readme.md @@ -0,0 +1,9 @@ +# Snippets + +This folder contains the following files: + +- snippets.json +- feature_snippets_react.json +- feature_snippets_sdk.json + +These are generated in the "Version Packages" PR diff --git a/turbo.json b/turbo.json index cde4acd4f96..fbd8dc31315 100644 --- a/turbo.json +++ b/turbo.json @@ -9,6 +9,10 @@ "outputs": ["typedoc/**"], "dependsOn": ["^build"] }, + "generate-docs": { + "outputs": ["docs/**"], + "dependsOn": ["^build"] + }, "@thirdweb-dev/chains#build": { "outputs": ["dist/**", "chains/**"], "dependsOn": ["^build"],