Compare commits

..
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
cbf5508bd5 Version Packages (#449)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-12-07 14:21:51 +13:00
Joaquim VergesandGitHub 3731459d33 [SDK] Less strict prebuilt checks to support OSRF variants (#451) 2022-12-07 13:08:12 +13:00
Adam MajmudarandGitHub 64f24f1bb1 CLI auto-updates on every run (#441) 2022-12-06 02:40:31 +00:00
Joaquim VergesandGitHub cac6c30bca [SDK] Fix setting allowance or approvals gaslessly (#450) 2022-12-06 11:49:04 +13:00
Adam MajmudarandGitHub e7740a59db Detect if forge isn't installed and display error (#447) 2022-12-05 16:54:13 -05:00
Jonas DanielsandGitHub 7a37e564fd [SDK, React] - useContract fail fast (#448) 2022-12-05 21:41:58 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
e173636f4b Version Packages (#446)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-12-04 11:34:00 +13:00
Joaquim VergesandGitHub 8c6cdaa288 [SDK] Fix creating listings with a magic.link wallet (#443) 2022-12-03 21:58:44 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
ad9b3febff Version Packages (#445)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-12-04 07:49:38 +13:00
Adam MajmudarandGitHub 94f49b1294 Move framework check back to template (#444) 2022-12-03 18:40:46 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
517e2a75e3 Version Packages (#442)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-12-02 16:26:33 -08:00
Jonas DanielsandGitHub 72692689e9 initialize pay package (#433) 2022-12-02 22:52:04 +00:00
Jonas DanielsandGitHub efc56fa580 [SDK] - improved batch provider (#440) 2022-12-02 22:39:11 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
564b17e760 Version Packages (#419)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-12-03 11:25:35 +13:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b4507db963 Bump decode-uri-component from 0.2.0 to 0.2.2 (#439)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-02 14:10:31 -08:00
Joaquim VergesandGitHub f451da6395 [SDK] Fix SigMint detection for OSRF NFT Collection contracts (#438) 2022-12-03 11:00:21 +13:00
Jonas DanielsandGitHub ee47840767 fix #429 (#436) 2022-12-02 10:47:46 -08:00
Adam MajmudarandGitHub bef97f72f4 [CLI] Make solc default backup compilation (#435) 2022-12-02 17:11:20 +00:00
Adam MajmudarandGitHub 3e87dd3ccb [CLI] display file names when there are duplicate contract names (#432) 2022-12-02 03:21:40 +00:00
Joaquim VergesandGitHub def42511ff [SOL] Remove workaround for getLargestAccount (#434) 2022-12-02 02:42:26 +00:00
Adam MajmudarandGitHub c42545a647 [CLI] fix CLI on paths with spaces for windows (#431) 2022-12-01 19:03:54 -05:00
Adam MajmudarandGitHub 6e20d1f21a [CLI] allow adding contracts to existing projects (#428) 2022-12-01 20:31:06 +00:00
Joaquim VergesandGitHub e684d7e1ca [CLI] Fix metadata upload with special characters (#430) 2022-12-01 20:14:27 +00:00
Adam MajmudarandGitHub f545a67e9f [Auth] include credentials when requesting user (#425) 2022-12-01 18:17:31 +00:00
Jake LooandGitHub 034a257442 [SDK] Support more types of Minimal Proxy (#429) 2022-12-01 20:30:09 +13:00
1bfb91dbf3 [SDK] Improve error parsing for other wallets (#424)
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-30 18:02:21 -08:00
Jonas DanielsandGitHub 5d95cbcdb2 fix turbo (#427) 2022-12-01 00:52:06 +00:00
Jonas DanielsandGitHub 639e535ed5 init unity-js-bridge package (#420) 2022-11-30 22:36:16 +00:00
af3acc6b10 [SDK] Add support for AWS KMS (#416)
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-28 20:34:24 -08:00
Joaquim VergesandGitHub eca47763cd [SDK] increase gas limit for opening packs (#418) 2022-11-29 03:30:15 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
37b5bec897 Version Packages (#417)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-28 18:23:23 -08:00
Nacho IacovinoandGitHub 48d91e4431 [CLI] Fix mappings for prebuilts (#415) 2022-11-28 18:13:00 -08:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
a20be881e3 Version Packages (#406)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-29 12:09:38 +13:00
Joaquim VergesandGitHub 47f8945325 [SDK] improve error parsing (#414) 2022-11-29 11:45:33 +13:00
Furqan RydhanandGitHub 1b0bf99da7 Improvements to the App Deploy Flow (#413) 2022-11-28 14:23:44 -08:00
f03be398e0 [SDK] Update signTypedData domain to match contract (#412)
Co-authored-by: Joaquim Verges <[email protected]>
2022-11-28 03:00:50 +00:00
27996cb4bc [CLI] - feat: add solana support to cli (#403)
Co-authored-by: Jarrod Watts <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-24 01:01:00 +00:00
2eaa67acbe [CLI+SDK] app-uri (#283)
Co-authored-by: Furqan Rydhan <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-23 09:17:29 +00:00
Jonas Daniels aafd7968df bring the registry-url back apparently it was important 2022-11-23 01:05:43 -08:00
Jonas DanielsandGitHub 48797c7cf0 [SDK] - add gasless feature detection (#408) 2022-11-23 00:53:59 -08:00
Jonas DanielsandGitHub 4edcb37100 update prettier & format (#407) 2022-11-23 06:41:39 +00:00
83dcaf7058 Expose sdk.fromWallet and wallet classes (#402)
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-22 18:15:28 -05:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
b4e005be7f Version Packages (#401)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-22 14:31:57 -08:00
Nacho IacovinoandGitHub ccb7db4873 [Solana + React] Update hooks for creators/royalties (#405) 2022-11-22 19:22:51 +00:00
Jonas DanielsandGitHub 9151aa7dc8 [SDK] - expose getDefaultTrustedForwarders helper fn (#404) 2022-11-22 03:35:01 +00:00
5a01c537e3 [DO NOT MERGE] Update to Metaplex v0.17 (#305)
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-21 16:14:39 -08:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f09c153ff7 Version Packages (#391)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-21 15:22:56 -08:00
Nacho IacovinoandGitHub 15431621fd [React] Remove console.log (#400) 2022-11-21 20:03:32 +00:00
Jonas DanielsandGitHub 887af24450 [SDK] - fix error handling for nullish error values (#399) 2022-11-21 18:52:02 +00:00
Jonas DanielsandGitHub 15514f190a [SDK] - add default value option to constructorParams schema (#398) 2022-11-21 18:28:18 +00:00
Adam MajmudarandGitHub 72589ec234 Call user callback in getUser (#397) 2022-11-21 17:46:18 +00:00
Jonas DanielsandGitHub f8bceec10c fix solana claim condition native token (#395) 2022-11-19 05:36:42 +00:00
Adam MajmudarandGitHub 7c0744a006 Add support for total supply and pagination on get all (#388) 2022-11-18 02:21:32 +00:00
Nacho IacovinoandGitHub 846022e2cf [React] Fix unlimited price (#392) 2022-11-17 22:25:25 +00:00
Joaquim VergesandGitHub 96bd92e724 [SDK] Expose getAllDetectedFeatures(ABI) helper function (#390) 2022-11-17 14:07:37 -08:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c2b6d977ed Version Packages (#383)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-16 14:02:50 -08:00
7cb8e59be4 [SDK] Add new Drop contract implementation addresses (#364)
Co-authored-by: Jonas Daniels <[email protected]>
Co-authored-by: Adam Majmudar <[email protected]>
2022-11-16 21:52:01 +00:00
Adam MajmudarandGitHub 04a47e8971 Add retroactive creator and royalty update option (#385) 2022-11-16 21:37:45 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8a6a97a3e9 Bump loader-utils from 2.0.3 to 2.0.4 (#384)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 19:51:40 +00:00
Jonas DanielsandGitHub 612bcdd16f [REACT] - update gnosis connector (#386) 2022-11-16 19:34:27 +00:00
Jonas DanielsandGitHub 0ed77d2c9e [SDK] - add constructorParams to schema for better release -> deploy (#382) 2022-11-15 20:47:54 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7129aef6e1 Version Packages (#370)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-11 08:51:19 -08:00
Joaquim VergesandGitHub f50b74819d [SDK] make isConnected sync, remove useless fn (#381) 2022-11-11 06:14:24 +00:00
Joaquim VergesandGitHub 3eba69afd7 [SDK] expose signer's chain id via sdk.wallet (#380) 2022-11-11 00:42:05 +00:00
Jarrod WattsandGitHub 98c2253e8f [SDK] Docs - Add await before sdk.getContract snippets (#379) 2022-11-10 16:08:31 -08:00
32d91ef709 [REACT] Fix Border Radius for Safari (#378)
Co-authored-by: Jarrod Watts <[email protected]>
2022-11-10 09:53:17 -08:00
Adam MajmudarandGitHub b79dc18f7a Add event filtering on topics (#377) 2022-11-09 11:51:13 -05:00
Adam MajmudarandGitHub 4af785c37c Add TokensClaimed event to tiered-drop (#376) 2022-11-08 20:34:45 +00:00
Adam MajmudarandGitHub 6f818f393e Updated tiered-drop contract (#373) 2022-11-03 17:03:00 -07:00
Adam MajmudarandGitHub 97ed4779a9 Update nft drop claimTo documentation (#372) 2022-11-03 22:42:42 +00:00
Nacho IacovinoandGitHub 2d3fca5237 [React] Add useClaimerProofs hook (#369) 2022-11-03 01:17:15 +01:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7016019f2a Version Packages (#366)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-02 15:16:25 -07:00
Joaquim VergesandGitHub 4e7b293c54 [SDK] Fix handling of old allowlist proof format (#368) 2022-11-02 14:11:13 -07:00
Jonas DanielsandGitHub c9c0e4ff39 [SDK] - make EVM side react native compatible (#365) 2022-11-02 05:38:56 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
06c24c153a Version Packages (#361)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-01 16:13:47 -07:00
aa6d9ed75d [SDK] Support new Drop claim conditions mechanics (#333)
Co-authored-by: adam-maj <[email protected]>
Co-authored-by: Adam Majmudar <[email protected]>
2022-11-01 23:07:10 +00:00
Joaquim VergesandGitHub 42a606588d [SDK] Fix fetching NFTs with numbers as ids (#362) 2022-11-01 22:01:01 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
2820761003 Version Packages (#360)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-01 13:49:34 -07:00
Adam MajmudarandGitHub 5200d5d7e7 Add support for TieredDrop in extensions (#329) 2022-11-01 13:48:48 -07:00
Joaquim VergesandGitHub e731c1a7c3 [SDK] Allow fetching claimerProofs from any claim condition (#359) 2022-10-31 23:26:27 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
2e8d3fd6e7 Version Packages (#358)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-28 18:14:35 -07:00
Nacho IacovinoandGitHub cc4613b5fd [React] Add Pack and Multiwrap as NFTContract types (#356) 2022-10-29 01:28:40 +02:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
78566babaa Version Packages (#354)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-28 10:29:57 -07:00
Joaquim VergesandGitHub 65fc7ba6ff [SDK] Expose claimCondtions.getClaimerProofs(address) (#357) 2022-10-28 10:25:36 -07:00
Nacho IacovinoandGitHub 1c24c3c3c4 [Multi] Add useUpdateCreator hook, fix CreatorInput schema (#353) 2022-10-26 18:19:32 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
408c5a81fa Version Packages (#347)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-26 08:38:25 -07:00
Joaquim VergesandGitHub 352291791e [SDK, React] expose marketplace.auction.executeSale (#352) 2022-10-26 00:19:01 +00:00
Jonas DanielsandGitHub aabbb149e8 [React] - fix wallet connection during hot reload (#351) 2022-10-25 22:48:39 +00:00
Jonas DanielsandGitHub d59450f814 do not release e2e tests (#350) 2022-10-25 20:29:22 +00:00
7d9a4c6abc Update name of useRoyalty, and update (#348)
Co-authored-by: Jonas Daniels <[email protected]>
2022-10-25 19:56:09 +00:00
Jonas DanielsandGitHub 99806e595d [VARIOUS] - exclude sizes of test files etc (#349) 2022-10-25 18:39:30 +00:00
Nacho IacovinoandGitHub 21c21c1adf resolveReleasesFromAddress -> resolveContractUriFromAddress (#344) 2022-10-24 23:43:43 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4b10719047 Version Packages (#345)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-24 16:18:44 -07:00
Joaquim VergesandGitHub 989cf7347c [React, SDK] Small fixes for useOffers and makeOffers (#346) 2022-10-24 23:09:32 +00:00
Joaquim VergesandGitHub 72227b2e16 [SDK, React] Expose new useOffers and useMakeOffer hooks (#343) 2022-10-24 15:28:34 -07:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
ed6c54f20d Version Packages (#336)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-21 13:26:24 -07:00
Joaquim VergesandGitHub 26116a6f63 [SDK] Update to new univeral RPC endpoint (#342) 2022-10-21 13:21:11 -07:00
Jonas DanielsandGitHub f11a2719ff [workflow] github hosted runners (#340) 2022-10-20 22:02:58 -07:00
Jonas DanielsandGitHub ef27aad0aa [Various, React] - add initial e2e testing setup (#327) 2022-10-21 04:19:04 +00:00
Nacho IacovinoandGitHub b03a902145 [React] Docs update (#339) 2022-10-20 20:17:01 -07:00
Adam MajmudarandGitHub 340605b507 Clean native token address in changeset (#337) 2022-10-20 23:57:55 +00:00
Adam MajmudarandGitHub 15f8006e1f Export smart contract (#335) 2022-10-20 23:46:02 +00:00
Adam MajmudarandGitHub 811c5a1166 Update code snippets for signature minting (#334) 2022-10-20 23:29:07 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c41a80d86d Version Packages (#331)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-20 15:35:12 -07:00
Joaquim VergesandGitHub ad851f7b4d [SDK] Fix for finding addresses in legacy merkle tree format (#332) 2022-10-20 21:35:52 +00:00
Joaquim VergesandGitHub 6218c88584 [SDK] Fix for deploy byte parameters (#330) 2022-10-20 04:47:55 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c9b564feaf Version Packages (#323)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-19 21:19:06 -07:00
Adam MajmudarandGitHub 87fd6ab14e Update storage download on fail (#324) 2022-10-19 12:44:36 -07:00
Joaquim VergesandGitHub df74340fa5 [SDK] Import cbor-x fully for es builds (#328) 2022-10-19 17:46:54 +00:00
Joaquim VergesandGitHub a57b4f01f3 [SDK] Implement sharded merkle trees for lightweight allowlist checks (#321) 2022-10-19 16:54:09 +00:00
Jonas DanielsandGitHub 126752d7d0 [Various] - clean up extraneous dependencies (#326) 2022-10-18 23:56:04 -07:00
89ff921a7d Fix vite (#315)
Co-authored-by: Jonas Daniels <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2022-10-18 15:23:57 -07:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
9124b3180c Version Packages (#308)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-18 15:02:14 -07:00
Adam MajmudarandGitHub f41a443c57 Add update creators and update royalty (#320) 2022-10-18 21:50:47 +00:00
Joaquim VergesandGitHub b7cd744cd0 [SDK] Sign multiple solana claims at once (#322) 2022-10-18 21:35:03 +00:00
bb1b4e6ac3 [React] Add useMinimumNextBid hook (#318)
Co-authored-by: Jonas Daniels <[email protected]>
2022-10-18 11:57:26 -07:00
2f8ec89c4c [SDK, React] Expose total claimed/unclaimed supply for erc721 contracts (#319)
Co-authored-by: Nacho Iacovino <[email protected]>
2022-10-17 18:17:54 -07:00
Joaquim VergesandGitHub 6ae52664e5 [React] Fix passing wrong RPC url to UserWallet when using an external signer (#316) 2022-10-17 22:26:15 +00:00
Adam MajmudarandGitHub 4f867e15ed Fix supply in nft.get() (#317) 2022-10-17 19:17:43 +00:00
cc8f983615 fix typo (#314)
Co-authored-by: Joaquim Verges <[email protected]>
2022-10-16 22:27:40 +00:00
Joaquim VergesandGitHub f45ef62128 [SDK] return fallback metadata when tokenId is not found on nft contract (#313) 2022-10-16 15:15:26 -07:00
9727502eb3 Add useMintNFTSupply hook (#310)
Co-authored-by: Jonas Daniels <[email protected]>
2022-10-14 13:32:43 -07:00
Adam MajmudarandGitHub b6eec6146c [Solana] Add quantity to mint additional supply (#312) 2022-10-14 19:23:07 +00:00
88daa3c5cb [SDK] Check for undefined ABI (#309)
Co-authored-by: Joaquim Verges <[email protected]>
2022-10-14 03:37:40 +00:00
Adam MajmudarandGitHub 53c6507669 Add deploy event listener (#306) 2022-10-13 21:28:24 +00:00
YashandGitHub 782b58d3f6 [SDK] Fix multicall txns in a gasless setup (#307) 2022-10-13 11:57:02 -07:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
e17e41f4d1 Version Packages (#304)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-12 15:22:33 -07:00
Joaquim VergesandGitHub 712b11a43e [SDK] Fix not getting real owner of Solana NFTs (#303) 2022-10-12 22:12:53 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
306debb029 Version Packages (#302)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-12 10:57:32 -07:00
Joaquim VergesandGitHub 86f0ceff46 [React] Remove useAddress hook for now (#301) 2022-10-12 17:54:14 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7f0d1ec947 Version Packages (#300)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-12 10:23:15 -07:00
Joaquim VergesandGitHub b1218cbd7d [React] Recreate SDK on wallet changes to propagate to useAddress and other hooks (#299) 2022-10-12 10:12:21 -07:00
Joaquim Verges 97ef35ce0f [SDK] docstrings for claim conditions 2022-10-12 08:48:58 -07:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
1f46f270cd Version Packages (#267)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-12 00:36:55 -07:00
Jonas DanielsandGitHub e8c25ed0f2 [React] - fix getBalance (#298) 2022-10-12 05:28:15 +00:00
Jonas DanielsandGitHub 78d6d3c159 [SDK] - fix solana getAddress (#297) 2022-10-12 04:49:39 +00:00
Joaquim Verges c72d92956a update generate snippets scripts 2022-10-11 21:28:39 -07:00
Jonas DanielsandGitHub cf88795376 [SDK, React] - useBalance hook (#296) 2022-10-12 04:15:06 +00:00
Jonas DanielsandGitHub 47287fb189 [Various] - fix lint (#295) 2022-10-11 21:02:38 -07:00
Joaquim Verges 3763326c25 [React] Fix docstrings 2022-10-11 20:32:10 -07:00
Joaquim Verges 894eb27dfa [SDK] Fix docstrings 2022-10-11 20:21:11 -07:00
Joaquim VergesandGitHub 8b3b97c8f7 [SDK] Fix getAllClaimed for Solana NFT drops (#293) 2022-10-12 00:31:19 +00:00
Jonas DanielsandGitHub 89d87a5eb3 [SDK] - fix batch upload for lazy mint (#294) 2022-10-12 00:18:15 +00:00
Jonas DanielsandGitHub 492a818079 [SOL] - expose useAddress() (#292) 2022-10-11 21:10:43 +00:00
Jonas DanielsandGitHub 86f608390a [React] - expose .program on useProgram() (#291) 2022-10-11 21:00:56 +00:00
Jonas DanielsandGitHub 8096c78b46 [SDK, React] - claim changes (#290) 2022-10-11 20:48:51 +00:00
Nacho IacovinoandGitHub 521a49c6ec [Solana] Standarize use claim (#289) 2022-10-11 10:50:35 -07:00
Joaquim VergesandGitHub 25a4773bba [SDK] Add pagination to getAll() for solana nft collections (#286) 2022-10-11 05:16:20 +00:00
18381fac73 Fix errorneous ERC20 Allowance check (#280)
Co-authored-by: Joaquim Verges <[email protected]>
2022-10-10 21:56:16 +00:00
Joaquim VergesandGitHub 89b5c6fe07 [SDK] Make solana drop creation and register transactions sequential (#285) 2022-10-10 14:43:09 -07:00
Joaquim VergesandGitHub 4dccccc6fa [SDK] Solana docs update (#284) 2022-10-10 12:44:55 -07:00
Jarrod WattsandGitHub de15e4212f [REACT] - Update Broken Links to Portal in README (#281) 2022-10-10 00:54:37 +00:00
Jarrod WattsandGitHub 1f41adbd2c [REACT] - Fix useActiveClaimCondition invariant failing for token ID 0 (#282) 2022-10-10 11:13:00 +11:00
Furqan RydhanandGitHub 1918495f2e Command Updates (detect -> build) + helper text (#279) 2022-10-09 16:21:07 -07:00
24514a6e9f Fr/command updates (#276)
Co-authored-by: Joaquim Verges <[email protected]>
2022-10-08 03:29:20 +00:00
Adam MajmudarandGitHub ad06c5b289 Add auth support to react and auth packages (#274) 2022-10-07 21:20:36 +00:00
Adam MajmudarandGitHub 9de3f8c8e9 Add support for recursive folder upload (#277) 2022-10-07 19:09:40 +00:00
Joaquim VergesandGitHub b1fa17158d [SDK] Expose maxClaimable and disallow claiming drops by default (#273) 2022-10-07 02:16:52 +00:00
Nacho IacovinoandGitHub 2bdf1984cb [Solana] Add claim conditions hooks (#272) 2022-10-07 02:36:20 +02:00
Adam MajmudarandGitHub df048af605 Add support for auth to Solana (#271) 2022-10-06 17:05:18 -07:00
Joaquim VergesandGitHub 41507d32a7 [SDK] Solana Program Registry Integration (#270) 2022-10-06 16:21:17 -07:00
Jonas DanielsandGitHub b2cadf164c [SDK, React] - remove deprecated chains (#269) 2022-10-06 00:20:53 -07:00
Adam MajmudarandGitHub 57b9c671aa [CLI] Update storage upload CLI (#268) 2022-10-05 15:29:16 -07:00
Adam MajmudarandGitHub 3b7d10ed93 [React] Add hook to create a storage upload component (#266) 2022-10-05 15:08:43 -07:00
Jonas DanielsandGitHub d6bb61b7fa [SDK] - align getProgram & make chainId getter available on EVM contracts (#263) 2022-10-05 20:06:34 +00:00
408 changed files with 28222 additions and 8063 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"ignore": ["e2e-cra-5", "e2e-next-12", "e2e-vite-3"],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"updateInternalDependents": "always",
"onlyUpdatePeerDependentsWhenOutOfRange": true
+1 -1
View File
@@ -9,7 +9,7 @@ runs:
with:
node-version: 16
registry-url: "https://registry.npmjs.org"
# cache: "yarn"
cache: "yarn"
- name: Install dependencies
shell: bash
+1 -2
View File
@@ -14,8 +14,7 @@ jobs:
build:
name: Build and Test
# timeout-minutes: 15
# try out buildjet to speed up build and test
runs-on: buildjet-32vcpu-ubuntu-2204
runs-on: ubuntu-latest-32
# To use Remote Caching, uncomment the next lines and follow the steps below.
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
+1 -8
View File
@@ -13,8 +13,7 @@ concurrency:
jobs:
integration-tests:
timeout-minutes: 60
# try out buildjet to speed up build and test
runs-on: buildjet-32vcpu-ubuntu-2204
runs-on: ubuntu-latest-32
steps:
- uses: actions/checkout@v3
@@ -28,9 +27,3 @@ jobs:
run: yarn e2e
env:
NODE_OPTIONS: "--max_old_space_size=4096"
- uses: actions/upload-artifact@v2
if: always()
with:
name: playwright-report
path: packages/react/playwright-report/
retention-days: 30
+1 -2
View File
@@ -40,8 +40,7 @@ jobs:
comment_body: ${{ github.event.comment.body }}
deploy:
# try out buildjet to speed up build and test
runs-on: buildjet-32vcpu-ubuntu-2204
runs-on: ubuntu-latest-32
needs: deploy-check
if: needs.deploy-check.outputs.triggered == 'true'
steps:
+1 -2
View File
@@ -14,8 +14,7 @@ concurrency:
jobs:
release:
name: Release
# try out buildjet to speed up build and test
runs-on: buildjet-32vcpu-ubuntu-2204
runs-on: ubuntu-latest-32
steps:
- name: Checkout branch
uses: actions/checkout@v3
+3 -2
View File
@@ -4,8 +4,7 @@ on: [pull_request]
jobs:
build:
# try out buildjet to speed up build and test
runs-on: buildjet-32vcpu-ubuntu-2204
runs-on: ubuntu-latest-32
steps:
- uses: actions/checkout@v3
@@ -16,3 +15,5 @@ jobs:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
strip-hash: "\\-(\\w{8})(?:\\.esm|\\.cjs)"
minimum-change-threshold: 100
# exclude source maps, node modules and any test related files
exclude: "{**/*.map,**/node_modules/**,**/test/**}"
+6 -1
View File
@@ -12,4 +12,9 @@ server/dist
public/dist
.turbo
./packages/contracts-js/abis
.idea/
.idea/
.yalc/
yalc.lock
build/
playwright-report/
.vscode/
-1
View File
@@ -1,4 +1,3 @@
lib
node_modules
dist
contracts-js
-1
View File
@@ -28,7 +28,6 @@
| [/storage](./packages/storage) | Best in class decentralized storage SDK for Browser and Node | <a href="https://www.npmjs.com/package/@thirdweb-dev/storage"><img src="https://img.shields.io/npm/v/@thirdweb-dev/storage?color=red&label=npm&logo=npm" alt="npm version"/></a> |
| [/cli](./packages/cli) | Publish and deploy smart contracts without dealing with private keys | <a href="https://www.npmjs.com/package/thirdweb"><img src="https://img.shields.io/npm/v/thirdweb?color=red&label=npm&logo=npm" alt="npm version"/></a> |
## Documentation
Visit [https://portal.thirdweb.com/](https://portal.thirdweb.com/) to view the full documentation.
+5 -9
View File
@@ -8,14 +8,15 @@
"private": true,
"workspaces": {
"packages": [
"packages/*"
"packages/*",
"test/**/*"
]
},
"scripts": {
"test": "turbo run test test:evm test:solana",
"e2e": "turbo run e2e",
"build": "turbo run build",
"build:release": "turbo run build --force",
"build": "turbo run build --filter=./packages/*",
"build:release": "turbo run build --force --filter=./packages/*",
"dev": "turbo run dev --no-cache --parallel --continue",
"fix:repo": "manypkg fix",
"lint": "turbo run lint",
@@ -27,12 +28,7 @@
"release": "node ./scripts/pre-release.mjs && changeset publish",
"version-packages:nightly": "changeset version --snapshot nightly",
"release:nightly": "node ./scripts/pre-release.mjs && changeset publish --tag nightly",
"push": "turbo run push"
},
"preconstruct": {
"packages": [
"packages/*"
]
"push": "turbo run push --filter=./packages/*"
},
"packageManager": "[email protected]",
"dependencies": {
+64
View File
@@ -1,5 +1,69 @@
# @thirdweb-dev/auth
## 2.0.37
## 2.0.36
## 2.0.35
## 2.0.34
### Patch Changes
- [#425](https://github.com/thirdweb-dev/js/pull/425) [`f545a67`](https://github.com/thirdweb-dev/js/commit/f545a67e9fb597d27bb39ca515d24d306fbb121a) Thanks [@adam-maj](https://github.com/adam-maj)! - Add sameSite none and include credentials
## 2.0.33
## 2.0.32
## 2.0.31
### Patch Changes
- [#397](https://github.com/thirdweb-dev/js/pull/397) [`72589ec`](https://github.com/thirdweb-dev/js/commit/72589ec234d86939b67b0ca8b3b789f2e9c54cc2) Thanks [@adam-maj](https://github.com/adam-maj)! - Call user callback in getUser
## 2.0.30
## 2.0.29
## 2.0.28
## 2.0.27
## 2.0.26
## 2.0.25
## 2.0.24
## 2.0.23
## 2.0.22
## 2.0.21
### Patch Changes
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - enable e2e testing
## 2.0.20
## 2.0.19
## 2.0.18
## 2.0.17
## 2.0.16
## 2.0.15
## 2.0.14
### Patch Changes
- [#274](https://github.com/thirdweb-dev/js/pull/274) [`ad06c5b`](https://github.com/thirdweb-dev/js/commit/ad06c5b28902422f9b416d65255c64c937a5e046) Thanks [@adam-maj](https://github.com/adam-maj)! - Add solana auth support and plugins for react and auth package
## 2.0.13
## 2.0.12
+4
View File
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-auth-next-evm.cjs.js",
"module": "dist/thirdweb-dev-auth-next-evm.esm.js"
}
+4
View File
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-auth-next-solana.cjs.js",
"module": "dist/thirdweb-dev-auth-next-solana.esm.js"
}
+12 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "2.0.13",
"version": "2.0.37",
"exports": {
"./next": {
"module": "./next/dist/thirdweb-dev-auth-next.esm.js",
@@ -10,10 +10,18 @@
"module": "./express/dist/thirdweb-dev-auth-express.esm.js",
"default": "./express/dist/thirdweb-dev-auth-express.cjs.js"
},
"./next/evm": {
"module": "./next/evm/dist/thirdweb-dev-auth-next-evm.esm.js",
"default": "./next/evm/dist/thirdweb-dev-auth-next-evm.cjs.js"
},
"./next-auth": {
"module": "./next-auth/dist/thirdweb-dev-auth-next-auth.esm.js",
"default": "./next-auth/dist/thirdweb-dev-auth-next-auth.cjs.js"
},
"./next/solana": {
"module": "./next/solana/dist/thirdweb-dev-auth-next-solana.esm.js",
"default": "./next/solana/dist/thirdweb-dev-auth-next-solana.cjs.js"
},
"./package.json": "./package.json"
},
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/auth",
@@ -35,6 +43,8 @@
"preconstruct": {
"entrypoints": [
"next/index.ts",
"next/evm/index.ts",
"next/solana/index.ts",
"express/index.ts",
"next-auth/index.ts"
],
@@ -63,7 +73,7 @@
"eslint-plugin-inclusive-language": "^2.2.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"ethers": "^5.7.1",
"ethers": "^5.7.2",
"express": "^4.18.1",
"next": "^12.2.0",
"next-auth": "^4.10.3",
+68
View File
@@ -0,0 +1,68 @@
import loginHandler from "./routes/login";
import logoutHandler from "./routes/logout";
import userHandler from "./routes/user";
import {
ThirdwebAuthConfig,
ThirdwebAuthRoute,
ThirdwebAuthUser,
} from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import cookieParser from "cookie-parser";
import { Express, NextFunction, Request, Response } from "express";
export * from "./types";
export function getUser(req: Request): ThirdwebAuthUser | null {
return req.user;
}
export function ThirdwebAuth(app: Express, cfg: ThirdwebAuthConfig) {
const ctx = {
...cfg,
sdk: ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet"),
};
const authUrl = cfg.authUrl?.replace(/\/$/, "") || "/auth";
app.use(cookieParser());
app.use(async (req: Request, _: Response, next: NextFunction) => {
const { sdk, domain } = ctx;
let user = null;
const token = req.cookies.thirdweb_auth_token;
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
if (ctx.callbacks?.user) {
user = await ctx.callbacks.user(address);
}
user = { ...user, address };
} catch {
// No-op
}
}
req.user = user as ThirdwebAuthUser | null;
next();
});
app.get(`${authUrl}/:route`, (req: Request, res: Response) => {
const action = req.params.route as ThirdwebAuthRoute;
switch (action) {
case "login":
return loginHandler(req, res, ctx);
case "user":
return userHandler(req, res);
case "logout":
return logoutHandler(req, res);
default:
return res.status(400).json({
message: "Invalid route for authentication.",
});
}
});
}
@@ -43,7 +43,7 @@ export default async function handler(
path: "/",
httpOnly: true,
secure: true,
sameSite: "strict",
sameSite: "none",
}),
);
+1 -68
View File
@@ -1,68 +1 @@
import loginHandler from "./routes/login";
import logoutHandler from "./routes/logout";
import userHandler from "./routes/user";
import {
ThirdwebAuthConfig,
ThirdwebAuthRoute,
ThirdwebAuthUser,
} from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import cookieParser from "cookie-parser";
import { Express, NextFunction, Request, Response } from "express";
export * from "./types";
export function getUser(req: Request): ThirdwebAuthUser | null {
return req.user;
}
export function ThirdwebAuth(app: Express, cfg: ThirdwebAuthConfig) {
const ctx = {
...cfg,
sdk: ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet"),
};
const authUrl = cfg.authUrl?.replace(/\/$/, "") || "/auth";
app.use(cookieParser());
app.use(async (req: Request, _: Response, next: NextFunction) => {
const { sdk, domain } = ctx;
let user = null;
const token = req.cookies.thirdweb_auth_token;
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
if (ctx.callbacks?.user) {
user = await ctx.callbacks.user(address);
}
user = { ...user, address };
} catch {
// No-op
}
}
req.user = user as ThirdwebAuthUser | null;
next();
});
app.get(`${authUrl}/:route`, (req: Request, res: Response) => {
const action = req.params.route as ThirdwebAuthRoute;
switch (action) {
case "login":
return loginHandler(req, res, ctx);
case "user":
return userHandler(req, res);
case "logout":
return logoutHandler(req, res);
default:
return res.status(400).json({
message: "Invalid route for authentication.",
});
}
});
}
export * from "./evm";
+145
View File
@@ -0,0 +1,145 @@
import { ThirdwebNextAuthConfig } from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { serialize } from "cookie";
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next";
import NextAuth, {
NextAuthOptions,
Session,
unstable_getServerSession,
} from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export function ThirdwebNextAuth(cfg: ThirdwebNextAuthConfig) {
const sdk = ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet");
function ThirdwebProvider(res: GetServerSidePropsContext["res"]) {
return CredentialsProvider({
name: "ThirdwebAuth",
credentials: {
payload: {
label: "Payload",
type: "text",
placeholder: "",
},
},
async authorize({ payload }: any) {
try {
const parsed = JSON.parse(payload);
const token = await sdk.auth.generateAuthToken(cfg.domain, parsed);
const address = await sdk.auth.authenticate(cfg.domain, token);
// Securely set httpOnly cookie on request to prevent XSS on frontend
// And set path to / to enable thirdweb_auth_token usage on all endpoints
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", token, {
path: "/",
httpOnly: true,
secure: true,
sameSite: "none",
}),
);
return { id: address, address };
} catch (err) {
return null;
}
},
});
}
function nextOptions(
req: GetServerSidePropsContext["req"],
res: GetServerSidePropsContext["res"],
): NextAuthOptions {
async function session({
session: _session,
}: {
session: Session;
}): Promise<Session> {
const token = req.cookies.thirdweb_auth_token || "";
try {
const address = await sdk.auth.authenticate(cfg.domain, token);
_session.user = { ..._session.user, address } as Session["user"];
return _session;
} catch {
return _session;
}
}
function signOut() {
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", "", {
path: "/",
expires: new Date(Date.now() + 5 * 1000),
}),
);
}
const providers: NextAuthOptions["providers"] = [
...cfg.nextOptions.providers,
ThirdwebProvider(res),
];
const configSession = cfg.nextOptions.callbacks?.session;
const callbacks: NextAuthOptions["callbacks"] = {
...cfg.nextOptions.callbacks,
session: configSession
? async (params) => {
params.session = await session(params);
return configSession(params);
}
: session,
};
const configSignOut = cfg.nextOptions.events?.signOut;
const events: NextAuthOptions["events"] = {
...cfg.nextOptions.events,
signOut: configSignOut
? async (params) => {
signOut();
return configSignOut(params);
}
: signOut,
};
return {
...cfg.nextOptions,
providers,
callbacks,
events,
};
}
async function getUser(
...args:
| [NextApiRequest, NextApiResponse]
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]]
) {
return unstable_getServerSession(
args[0],
args[1],
nextOptions(args[0], args[1]),
);
}
function NextAuthHandler(...args: [] | [NextApiRequest, NextApiResponse]) {
if (args.length === 0) {
return (req: NextApiRequest, res: NextApiResponse) => {
return NextAuth(req, res, nextOptions(req, res));
};
}
return NextAuth(args[0], args[1], nextOptions(args[0], args[1]));
}
return {
NextAuthHandler,
getUser,
};
}
+1 -145
View File
@@ -1,145 +1 @@
import { ThirdwebNextAuthConfig } from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { serialize } from "cookie";
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next";
import NextAuth, {
NextAuthOptions,
Session,
unstable_getServerSession,
} from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export function ThirdwebNextAuth(cfg: ThirdwebNextAuthConfig) {
const sdk = ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet");
function ThirdwebProvider(res: GetServerSidePropsContext["res"]) {
return CredentialsProvider({
name: "ThirdwebAuth",
credentials: {
payload: {
label: "Payload",
type: "text",
placeholder: "",
},
},
async authorize({ payload }: any) {
try {
const parsed = JSON.parse(payload);
const token = await sdk.auth.generateAuthToken(cfg.domain, parsed);
const address = await sdk.auth.authenticate(cfg.domain, token);
// Securely set httpOnly cookie on request to prevent XSS on frontend
// And set path to / to enable thirdweb_auth_token usage on all endpoints
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", token, {
path: "/",
httpOnly: true,
secure: true,
sameSite: "strict",
}),
);
return { address };
} catch (err) {
return null;
}
},
});
}
function nextOptions(
req: GetServerSidePropsContext["req"],
res: GetServerSidePropsContext["res"],
): NextAuthOptions {
async function session({
session: _session,
}: {
session: Session;
}): Promise<Session> {
const token = req.cookies.thirdweb_auth_token || "";
try {
const address = await sdk.auth.authenticate(cfg.domain, token);
_session.user = { ..._session.user, address } as Session["user"];
return _session;
} catch {
return _session;
}
}
function signOut() {
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", "", {
path: "/",
expires: new Date(Date.now() + 5 * 1000),
}),
);
}
const providers: NextAuthOptions["providers"] = [
...cfg.nextOptions.providers,
ThirdwebProvider(res),
];
const configSession = cfg.nextOptions.callbacks?.session;
const callbacks: NextAuthOptions["callbacks"] = {
...cfg.nextOptions.callbacks,
session: configSession
? async (params) => {
params.session = await session(params);
return configSession(params);
}
: session,
};
const configSignOut = cfg.nextOptions.events?.signOut;
const events: NextAuthOptions["events"] = {
...cfg.nextOptions.events,
signOut: configSignOut
? async (params) => {
signOut();
return configSignOut(params);
}
: signOut,
};
return {
...cfg.nextOptions,
providers,
callbacks,
events,
};
}
async function getUser(
...args:
| [NextApiRequest, NextApiResponse]
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]]
) {
return unstable_getServerSession(
args[0],
args[1],
nextOptions(args[0], args[1]),
);
}
function NextAuthHandler(...args: [] | [NextApiRequest, NextApiResponse]) {
if (args.length === 0) {
return (req: NextApiRequest, res: NextApiResponse) => {
return NextAuth(req, res, nextOptions(req, res));
};
}
return NextAuth(args[0], args[1], nextOptions(args[0], args[1]));
}
return {
NextAuthHandler,
getUser,
};
}
export * from "./evm";
+89
View File
@@ -0,0 +1,89 @@
import loginHandler from "./routes/login";
import logoutHandler from "./routes/logout";
import userHandler from "./routes/user";
import {
ThirdwebAuthConfig,
ThirdwebAuthContext,
ThirdwebAuthRoute,
ThirdwebAuthUser,
} from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { NextRequest } from "next/server";
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next/types";
export * from "./types";
async function ThirdwebAuthRouter(
req: NextApiRequest,
res: NextApiResponse,
ctx: ThirdwebAuthContext,
) {
// Catch-all route must be named with [...thirdweb]
const { thirdweb } = req.query;
const action = thirdweb?.[0] as ThirdwebAuthRoute;
switch (action) {
case "login":
return await loginHandler(req, res, ctx);
case "user":
return await userHandler(req, res, ctx);
case "logout":
return await logoutHandler(req, res);
default:
return res.status(400).json({
message: "Invalid route for authentication.",
});
}
}
export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
const ctx = {
...cfg,
sdk: ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet"),
};
function ThirdwebAuthHandler(
...args: [] | [NextApiRequest, NextApiResponse]
) {
if (args.length === 0) {
return async (req: NextApiRequest, res: NextApiResponse) =>
await ThirdwebAuthRouter(req, res, ctx);
}
return ThirdwebAuthRouter(args[0], args[1], ctx);
}
async function getUser(
req: GetServerSidePropsContext["req"] | NextRequest | NextApiRequest,
) {
const { sdk, domain } = ctx;
let user: ThirdwebAuthUser | null = null;
const token =
typeof req.cookies.get === "function"
? (req.cookies as any).get("thirdweb_auth_token")
: (req.cookies as any).thirdweb_auth_token;
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
let data = {};
if (ctx.callbacks?.user) {
data = await ctx.callbacks.user(address);
}
user = { ...data, address };
} catch {
// No-op
}
}
return user;
}
return { ThirdwebAuthHandler, getUser };
}
@@ -47,7 +47,7 @@ export default async function handler(
path: "/",
httpOnly: true,
secure: true,
sameSite: "strict",
sameSite: "none",
}),
);
+1 -83
View File
@@ -1,83 +1 @@
import loginHandler from "./routes/login";
import logoutHandler from "./routes/logout";
import userHandler from "./routes/user";
import {
ThirdwebAuthConfig,
ThirdwebAuthContext,
ThirdwebAuthRoute,
ThirdwebAuthUser,
} from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { NextRequest } from "next/server";
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next/types";
export * from "./types";
async function ThirdwebAuthRouter(
req: NextApiRequest,
res: NextApiResponse,
ctx: ThirdwebAuthContext,
) {
// Catch-all route must be named with [...thirdweb]
const { thirdweb } = req.query;
const action = thirdweb?.[0] as ThirdwebAuthRoute;
switch (action) {
case "login":
return await loginHandler(req, res, ctx);
case "user":
return await userHandler(req, res, ctx);
case "logout":
return await logoutHandler(req, res);
default:
return res.status(400).json({
message: "Invalid route for authentication.",
});
}
}
export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
const ctx = {
...cfg,
sdk: ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet"),
};
function ThirdwebAuthHandler(
...args: [] | [NextApiRequest, NextApiResponse]
) {
if (args.length === 0) {
return async (req: NextApiRequest, res: NextApiResponse) =>
await ThirdwebAuthRouter(req, res, ctx);
}
return ThirdwebAuthRouter(args[0], args[1], ctx);
}
async function getUser(
req: GetServerSidePropsContext["req"] | NextRequest | NextApiRequest,
) {
const { sdk, domain } = ctx;
let user: ThirdwebAuthUser | null = null;
const token =
typeof req.cookies.get === "function"
? (req.cookies as any).get("thirdweb_auth_token")
: (req.cookies as any).thirdweb_auth_token;
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
user = { address };
} catch {
// No-op
}
}
return user;
}
return { ThirdwebAuthHandler, getUser };
}
export * from "./evm";
+89
View File
@@ -0,0 +1,89 @@
import loginHandler from "./routes/login";
import logoutHandler from "./routes/logout";
import userHandler from "./routes/user";
import {
ThirdwebAuthConfig,
ThirdwebAuthContext,
ThirdwebAuthRoute,
ThirdwebAuthUser,
} from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk/solana";
import { NextRequest } from "next/server";
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next/types";
export * from "./types";
async function ThirdwebAuthRouter(
req: NextApiRequest,
res: NextApiResponse,
ctx: ThirdwebAuthContext,
) {
// Catch-all route must be named with [...thirdweb]
const { thirdweb } = req.query;
const action = thirdweb?.[0] as ThirdwebAuthRoute;
switch (action) {
case "login":
return await loginHandler(req, res, ctx);
case "user":
return await userHandler(req, res, ctx);
case "logout":
return await logoutHandler(req, res);
default:
return res.status(400).json({
message: "Invalid route for authentication.",
});
}
}
export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
const ctx = {
...cfg,
sdk: ThirdwebSDK.fromPrivateKey("mainnet-beta", cfg.privateKey),
};
function ThirdwebAuthHandler(
...args: [] | [NextApiRequest, NextApiResponse]
) {
if (args.length === 0) {
return async (req: NextApiRequest, res: NextApiResponse) =>
await ThirdwebAuthRouter(req, res, ctx);
}
return ThirdwebAuthRouter(args[0], args[1], ctx);
}
async function getUser(
req: GetServerSidePropsContext["req"] | NextRequest | NextApiRequest,
) {
const { sdk, domain } = ctx;
let user: ThirdwebAuthUser | null = null;
const token =
typeof req.cookies.get === "function"
? (req.cookies as any).get("thirdweb_auth_token")
: (req.cookies as any).thirdweb_auth_token;
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
let data = {};
if (ctx.callbacks?.user) {
data = await ctx.callbacks.user(address);
}
user = { ...data, address };
} catch {
// No-op
}
}
return user;
}
return { ThirdwebAuthHandler, getUser };
}
@@ -0,0 +1,60 @@
import { ThirdwebAuthContext } from "../types";
import { LoginPayload } from "@thirdweb-dev/sdk";
import { serialize } from "cookie";
import { NextApiRequest, NextApiResponse } from "next";
function redirectWithError(
req: NextApiRequest,
res: NextApiResponse,
error: string,
) {
const encodedError = encodeURIComponent(error);
const url = new URL(req.headers.referer as string);
url.searchParams.set("error", encodedError);
return res.redirect(url.toString());
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
ctx: ThirdwebAuthContext,
) {
if (req.method !== "GET") {
return redirectWithError(req, res, "INVALID_METHOD");
}
const { sdk, domain } = ctx;
// Get signed login payload from the frontend
const payload = JSON.parse(atob(req.query.payload as string)) as LoginPayload;
if (!payload) {
redirectWithError(req, res, "MISSING_LOGIN_PAYLOAD");
}
let token;
try {
// Generate an access token with the SDK using the signed payload
token = await sdk.auth.generateAuthToken(domain, payload);
} catch {
return redirectWithError(req, res, "INVALID_LOGIN_PAYLOAD");
}
// Securely set httpOnly cookie on request to prevent XSS on frontend
// And set path to / to enable thirdweb_auth_token usage on all endpoints
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", token, {
path: "/",
httpOnly: true,
secure: true,
sameSite: "none",
}),
);
if (ctx.callbacks?.login) {
const address = sdk.auth.verify(domain, payload);
await ctx.callbacks.login(address);
}
return res.status(301).redirect(req.query.redirect as string);
}
@@ -0,0 +1,24 @@
import { serialize } from "cookie";
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method !== "GET") {
return res.status(400).json({
error: "Invalid method. Only GET supported.",
});
}
// Set the access token to 'none' and expire in 5 seconds
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", "", {
path: "/",
expires: new Date(Date.now() + 5 * 1000),
}),
);
return res.status(301).redirect(req.headers.referer as string);
}
@@ -0,0 +1,34 @@
import { ThirdwebAuthContext, ThirdwebAuthUser } from "../types";
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
ctx: ThirdwebAuthContext,
) {
if (req.method !== "GET") {
return res.status(400).json({
error: "Invalid method. Only GET supported.",
});
}
const { sdk, domain } = ctx;
let user = null;
const token = req.cookies.thirdweb_auth_token;
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
if (ctx.callbacks?.user) {
user = await ctx.callbacks.user(address);
}
user = { ...user, address };
} catch {
// No-op
}
}
return res.status(200).json(user as ThirdwebAuthUser | null);
}
@@ -0,0 +1,34 @@
import { ThirdwebSDK } from "@thirdweb-dev/sdk/solana";
export type ThirdwebAuthRoute = "login" | "logout" | "user";
export type ThirdwebAuthConfig = {
privateKey: string;
domain: string;
callbacks?: {
login?: (address: string) => Promise<void> | void;
user?: (
address: string,
) =>
| Promise<Omit<ThirdwebAuthUser, "address">>
| Omit<ThirdwebAuthUser, "address">;
};
};
export type ThirdwebAuthContext = {
sdk: ThirdwebSDK;
domain: string;
callbacks?: {
login?: (address: string) => Promise<void> | void;
user?: (
address: string,
) =>
| Promise<Omit<ThirdwebAuthUser, "address">>
| Omit<ThirdwebAuthUser, "address">;
};
};
export type ThirdwebAuthUser = {
address: string;
[key: string]: any;
};
+216
View File
@@ -1,5 +1,221 @@
# thirdweb
## 0.9.6
### Patch Changes
- [#441](https://github.com/thirdweb-dev/js/pull/441) [`64f24f1`](https://github.com/thirdweb-dev/js/commit/64f24f1bb167c3d0cb3beca51fd300eaec21cc27) Thanks [@adam-maj](https://github.com/adam-maj)! - CLI autoupdates on run
- [#447](https://github.com/thirdweb-dev/js/pull/447) [`e7740a5`](https://github.com/thirdweb-dev/js/commit/e7740a59db022a3396194ac66cd195d8ae754d57) Thanks [@adam-maj](https://github.com/adam-maj)! - Detect whether forge is installed
- Updated dependencies [[`3731459`](https://github.com/thirdweb-dev/js/commit/3731459d33f1ded7ebb69124809449b901b3ad3d), [`cac6c30`](https://github.com/thirdweb-dev/js/commit/cac6c30bca5e17df81d746ef81316af47d5e252e), [`7a37e56`](https://github.com/thirdweb-dev/js/commit/7a37e564fd5d5a9df84c8da44ecaf6c42f67a0e2)]:
- @thirdweb-dev/sdk@3.6.7
## 0.9.5
### Patch Changes
- Updated dependencies [[`8c6cdaa`](https://github.com/thirdweb-dev/js/commit/8c6cdaa2887fb2cc40d3ee6991233d195d103805)]:
- @thirdweb-dev/sdk@3.6.6
## 0.9.4
### Patch Changes
- [#444](https://github.com/thirdweb-dev/js/pull/444) [`94f49b1`](https://github.com/thirdweb-dev/js/commit/94f49b1294bc0208171b16ed413cbb44644af017) Thanks [@adam-maj](https://github.com/adam-maj)! - Add changeset
## 0.9.3
### Patch Changes
- Updated dependencies [[`efc56fa`](https://github.com/thirdweb-dev/js/commit/efc56fa5802490ac8ef50037658d046afd89e9a1)]:
- @thirdweb-dev/sdk@3.6.5
## 0.9.2
### Patch Changes
- [#430](https://github.com/thirdweb-dev/js/pull/430) [`e684d7e`](https://github.com/thirdweb-dev/js/commit/e684d7e1ca16f633bce8698529d16bf60c264aa4) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix uploading contracts with special characters in the comments
- [#435](https://github.com/thirdweb-dev/js/pull/435) [`bef97f7`](https://github.com/thirdweb-dev/js/commit/bef97f72f4860596b7b70b05e67fcadf2c9a012e) Thanks [@adam-maj](https://github.com/adam-maj)! - Make solc default backup compilation
- [#432](https://github.com/thirdweb-dev/js/pull/432) [`3e87dd3`](https://github.com/thirdweb-dev/js/commit/3e87dd3ccb04a2b73437357c939a251e83b783b2) Thanks [@adam-maj](https://github.com/adam-maj)! - Display file name on duplicate contract names
- [#431](https://github.com/thirdweb-dev/js/pull/431) [`c42545a`](https://github.com/thirdweb-dev/js/commit/c42545a64725492136025fa1dcdb4d46ba674a30) Thanks [@adam-maj](https://github.com/adam-maj)! - Add changeset
- [#428](https://github.com/thirdweb-dev/js/pull/428) [`6e20d1f`](https://github.com/thirdweb-dev/js/commit/6e20d1f21a622f102e94b956f700d0871c0dc779) Thanks [@adam-maj](https://github.com/adam-maj)! - Update CLI to enable create contract inside contracts project
- Updated dependencies [[`f451da6`](https://github.com/thirdweb-dev/js/commit/f451da6395689a5f89800ee63f34b6175b61f703), [`af3acc6`](https://github.com/thirdweb-dev/js/commit/af3acc6b10751b840e56aef6400da5eea6040df2), [`1bfb91d`](https://github.com/thirdweb-dev/js/commit/1bfb91dbf3a39160c987a425813ac5dbb84703ad), [`ee47840`](https://github.com/thirdweb-dev/js/commit/ee478407673b0416e0c1cfe2be11bd6963395348), [`def4251`](https://github.com/thirdweb-dev/js/commit/def42511ff5a20d83f9094164dafb87e412571b5), [`034a257`](https://github.com/thirdweb-dev/js/commit/034a257442314c67729f7bafcbe3740cff33fa32), [`eca4776`](https://github.com/thirdweb-dev/js/commit/eca47763cd89cc3b7aa57b542971837987540b55), [`639e535`](https://github.com/thirdweb-dev/js/commit/639e535ed55280ad9d081001aab3f5af72bb3e45)]:
- @thirdweb-dev/sdk@3.6.4
## 0.9.1
### Patch Changes
- [#415](https://github.com/thirdweb-dev/js/pull/415) [`48d91e4`](https://github.com/thirdweb-dev/js/commit/48d91e4431a3740d0f98f730ed5abf5b287f92c1) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix mappings for prebuilts redirect on deploy
## 0.9.0
### Minor Changes
- [#403](https://github.com/thirdweb-dev/js/pull/403) [`27996cb`](https://github.com/thirdweb-dev/js/commit/27996cb4bc6f054f45b0a66b0a3aca732e0ef610) Thanks [@avneesh0612](https://github.com/avneesh0612)! - Add CLI Support for solana with --solana flag on create command
- [#283](https://github.com/thirdweb-dev/js/pull/283) [`2eaa67a`](https://github.com/thirdweb-dev/js/commit/2eaa67acbe21464e7715d0b696afdc024460a44d) Thanks [@adam-maj](https://github.com/adam-maj)! - add capability to deploy apps
### Patch Changes
- [#413](https://github.com/thirdweb-dev/js/pull/413) [`1b0bf99`](https://github.com/thirdweb-dev/js/commit/1b0bf99da796df88ff307dd004cdaf239fb2b1ba) Thanks [@furqanrydhan](https://github.com/furqanrydhan)! - small interface tweaks
- Updated dependencies [[`48797c7`](https://github.com/thirdweb-dev/js/commit/48797c7cf0695965e33eb6bf602be4652f7085a8), [`83dcaf7`](https://github.com/thirdweb-dev/js/commit/83dcaf70584af8c5cdf0427f9fc1ba82d89f0887), [`f03be39`](https://github.com/thirdweb-dev/js/commit/f03be398e0d7b75c9c5b4fb643f35903e89a17e7), [`2eaa67a`](https://github.com/thirdweb-dev/js/commit/2eaa67acbe21464e7715d0b696afdc024460a44d), [`47f8945`](https://github.com/thirdweb-dev/js/commit/47f8945325447874b1ace0359919c1d54fd55436)]:
- @thirdweb-dev/sdk@3.6.3
## 0.8.18
### Patch Changes
- Updated dependencies [[`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715), [`9151aa7`](https://github.com/thirdweb-dev/js/commit/9151aa7dc80754a7aa4fd3f6ce0207bccbb6451f), [`5a01c53`](https://github.com/thirdweb-dev/js/commit/5a01c537e30bd7ef562aad1012413990de6faedf)]:
- @thirdweb-dev/sdk@3.6.2
## 0.8.17
### Patch Changes
- Updated dependencies [[`15514f1`](https://github.com/thirdweb-dev/js/commit/15514f190a844d809ae5b1edb580aab46a682485), [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510), [`f8bceec`](https://github.com/thirdweb-dev/js/commit/f8bceec10c60b30dc3d6f45926e2a9e018202578), [`887af24`](https://github.com/thirdweb-dev/js/commit/887af24450e316c2ea390cd49c0563cebe793c0f), [`96bd92e`](https://github.com/thirdweb-dev/js/commit/96bd92e724ec7d880d23348071b26ab8c21dd868)]:
- @thirdweb-dev/sdk@3.6.1
## 0.8.16
### Patch Changes
- Updated dependencies [[`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1), [`0ed77d2`](https://github.com/thirdweb-dev/js/commit/0ed77d2c9e7526444ef660aab82a950865234aa6), [`04a47e8`](https://github.com/thirdweb-dev/js/commit/04a47e8971d28da2532ebd9db824eeb459c17bd4)]:
- @thirdweb-dev/sdk@3.6.0
## 0.8.15
### Patch Changes
- Updated dependencies [[`3eba69a`](https://github.com/thirdweb-dev/js/commit/3eba69afd78b7aa472a9c00c9d4220bb69ad1d3e), [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855), [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd), [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0)]:
- @thirdweb-dev/sdk@3.5.2
## 0.8.14
### Patch Changes
- Updated dependencies [[`4e7b293`](https://github.com/thirdweb-dev/js/commit/4e7b293c543244de79c150ca8c37d941221fc9a3), [`c9c0e4f`](https://github.com/thirdweb-dev/js/commit/c9c0e4ff39b054af746f3aec75fcbd0a3ef7239d)]:
- @thirdweb-dev/sdk@3.5.1
## 0.8.13
### Patch Changes
- Updated dependencies [[`5200d5d`](https://github.com/thirdweb-dev/js/commit/5200d5d7e730da58bd4d3e7c222e3c661265f913), [`42a6065`](https://github.com/thirdweb-dev/js/commit/42a606588dfed03c67c57357dd0ee1ad19fad6ea)]:
- @thirdweb-dev/sdk@3.5.0
## 0.8.12
### Patch Changes
- Updated dependencies [[`e731c1a`](https://github.com/thirdweb-dev/js/commit/e731c1a7c341e6f2b9cc42c88d5c1b036dcf4a7c)]:
- @thirdweb-dev/sdk@3.4.5
## 0.8.11
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@3.4.4
## 0.8.10
### Patch Changes
- Updated dependencies [[`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5), [`65fc7ba`](https://github.com/thirdweb-dev/js/commit/65fc7ba6fff093a971b53cb0979c39768e090ba1)]:
- @thirdweb-dev/sdk@3.4.3
## 0.8.9
### Patch Changes
- Updated dependencies [[`21c21c1`](https://github.com/thirdweb-dev/js/commit/21c21c1adfd09b60ad563bfd4c308597140de33c), [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60)]:
- @thirdweb-dev/sdk@3.4.2
## 0.8.8
### Patch Changes
- Updated dependencies [[`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2)]:
- @thirdweb-dev/sdk@3.4.1
## 0.8.7
### Patch Changes
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - enable e2e testing
- Updated dependencies [[`340605b`](https://github.com/thirdweb-dev/js/commit/340605b507f384fbd2999b9c16542af3c53e84a9), [`26116a6`](https://github.com/thirdweb-dev/js/commit/26116a6f637ee845f7bd17f20ffe17caf184658e), [`15f8006`](https://github.com/thirdweb-dev/js/commit/15f8006e1fb22333b7ee239b45e7b1b12d6dccc8), [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5)]:
- @thirdweb-dev/sdk@3.4.0
## 0.8.6
### Patch Changes
- Updated dependencies [[`ad851f7`](https://github.com/thirdweb-dev/js/commit/ad851f7b4d6abb5ab9364ef3dec229f913e18ce5), [`6218c88`](https://github.com/thirdweb-dev/js/commit/6218c885842e6b4e44ec38ec92a9211e56c49bf4)]:
- @thirdweb-dev/sdk@3.3.1
## 0.8.5
### Patch Changes
- [#326](https://github.com/thirdweb-dev/js/pull/326) [`126752d`](https://github.com/thirdweb-dev/js/commit/126752d7d02c9a808a63fb9e67a9df6658b5682b) Thanks [@jnsdls](https://github.com/jnsdls)! - remove tons of unused dependencies, use SDK function for extracting ipfs has from bytecode
- Updated dependencies [[`126752d`](https://github.com/thirdweb-dev/js/commit/126752d7d02c9a808a63fb9e67a9df6658b5682b), [`df74340`](https://github.com/thirdweb-dev/js/commit/df74340fa51323304c32419761d6f18628b060fa), [`89ff921`](https://github.com/thirdweb-dev/js/commit/89ff921a7d9f0e42b4e6707c8b56d0aab95c1aa0), [`a57b4f0`](https://github.com/thirdweb-dev/js/commit/a57b4f01f3a49590b897101f2730582e4124a554)]:
- @thirdweb-dev/sdk@3.3.0
## 0.8.4
### Patch Changes
- Updated dependencies [[`4f867e1`](https://github.com/thirdweb-dev/js/commit/4f867e15edbe5757afbf54cab207458711a8986c), [`b6eec61`](https://github.com/thirdweb-dev/js/commit/b6eec6146c23b66a3681bbb48b173b9019254214), [`9727502`](https://github.com/thirdweb-dev/js/commit/9727502eb30ac139382b7c7c8e8fc0967cbfbcf1), [`782b58d`](https://github.com/thirdweb-dev/js/commit/782b58d3f6a3b49ff9b3d837551db5161f96171a), [`f41a443`](https://github.com/thirdweb-dev/js/commit/f41a443c5785240197607b5bf93ff18a1c8e8307), [`f45ef62`](https://github.com/thirdweb-dev/js/commit/f45ef62128cfefe06275a38440c90d45e9f3cef7), [`2f8ec89`](https://github.com/thirdweb-dev/js/commit/2f8ec89c4c83ae577092c840c198e6fcfb114e69), [`b7cd744`](https://github.com/thirdweb-dev/js/commit/b7cd744cd0482a6c3fe5ae0c858f20cd380d4114), [`53c6507`](https://github.com/thirdweb-dev/js/commit/53c65076696a43bd9a7e58a7493d4e65c172900f)]:
- @thirdweb-dev/sdk@3.2.6
## 0.8.3
### Patch Changes
- Updated dependencies [[`712b11a`](https://github.com/thirdweb-dev/js/commit/712b11a43e389ae10b7f09648779a69c05b2c913)]:
- @thirdweb-dev/sdk@3.2.5
## 0.8.2
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@3.2.4
## 0.8.1
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@3.2.3
## 0.8.0
### Minor Changes
- [#276](https://github.com/thirdweb-dev/js/pull/276) [`24514a6`](https://github.com/thirdweb-dev/js/commit/24514a6e9fc1316622c1494e5be225e53f88d26e) Thanks [@furqanrydhan](https://github.com/furqanrydhan)! - build is now default compile command, reorganized the help list
- [#279](https://github.com/thirdweb-dev/js/pull/279) [`1918495`](https://github.com/thirdweb-dev/js/commit/1918495f2ee7f50d94083d9577dab0bf1c828c94) Thanks [@furqanrydhan](https://github.com/furqanrydhan)! - Updating command list order, helper text and changed detect -> build
### Patch Changes
- [#277](https://github.com/thirdweb-dev/js/pull/277) [`9de3f8c`](https://github.com/thirdweb-dev/js/commit/9de3f8c8e954733bfc3eb6e8e0e786ff5b296f0c) Thanks [@adam-maj](https://github.com/adam-maj)! - Add recursive folder upload support
- [#268](https://github.com/thirdweb-dev/js/pull/268) [`57b9c67`](https://github.com/thirdweb-dev/js/commit/57b9c671aaf7fce0076dd332c171ba6944752e7a) Thanks [@adam-maj](https://github.com/adam-maj)! - Update storage upload cLI
- Updated dependencies [[`521a49c`](https://github.com/thirdweb-dev/js/commit/521a49c6ec6a73068adcfbc1d94d2f3f17afae86), [`8b3b97c`](https://github.com/thirdweb-dev/js/commit/8b3b97c8f7b3710ce62ed86cfeb4f6de3c23d559), [`25a4773`](https://github.com/thirdweb-dev/js/commit/25a4773bba406f4e270ac86e68c5266d24c08330), [`b2cadf1`](https://github.com/thirdweb-dev/js/commit/b2cadf164cfe9fb27081df7530356baf70ec2b3a), [`d6bb61b`](https://github.com/thirdweb-dev/js/commit/d6bb61b7fac759fff7d6293edd46f693f5a7889c), [`78d6d3c`](https://github.com/thirdweb-dev/js/commit/78d6d3c15968a449924b3f24354e151a90e4b20d), [`89d87a5`](https://github.com/thirdweb-dev/js/commit/89d87a5eb31e78e68e097718e9ae6e4c4d101868), [`41507d3`](https://github.com/thirdweb-dev/js/commit/41507d32a78c556f50c88de81c4d6109b1783c78), [`8096c78`](https://github.com/thirdweb-dev/js/commit/8096c78b466a7f5f9c2aac6e2c56a06f9d3a25d6), [`b1fa171`](https://github.com/thirdweb-dev/js/commit/b1fa17158dcac00265bc8f4d64f1f9708482cdb5), [`18381fa`](https://github.com/thirdweb-dev/js/commit/18381fac73741826934212ac6441842ed42a64a0), [`df048af`](https://github.com/thirdweb-dev/js/commit/df048af605f449279b01d7352b604e7856ac223c), [`d6bb61b`](https://github.com/thirdweb-dev/js/commit/d6bb61b7fac759fff7d6293edd46f693f5a7889c), [`cf88795`](https://github.com/thirdweb-dev/js/commit/cf88795376d3110f9d3aa839928d22276904b15a), [`89b5c6f`](https://github.com/thirdweb-dev/js/commit/89b5c6fe079e4df2cf12cb557aa9784f88c5d159)]:
- @thirdweb-dev/sdk@3.2.2
## 0.7.24
### Patch Changes
+3 -1
View File
@@ -1,6 +1,8 @@
export const CREATE_MESSAGES = {
typeOfProject: "What type of project do you want to create?",
projectName: "What is your project named?",
contractName: "What will be the name of your new smart contract?",
chain: "Which blockchain do you want to use?",
framework: "What framework do you want to use?",
language: "What language do you want to use?",
contract: "What type of contract do you want to start from?",
@@ -9,5 +11,5 @@ export const CREATE_MESSAGES = {
export const ERROR_MESSAGES = {
noConfiguration:
"Failed to find a supported project configuration file in current directory",
"No contract project configuration file found in current directory",
};
+3 -1
View File
@@ -2,7 +2,7 @@ import { CREATE_MESSAGES } from "../constants/constants";
import { prepareEnvironment } from "@gmrchk/cli-testing-library";
// this creates an app, can take some time that's fine
jest.setTimeout(120_000);
jest.setTimeout(150_000);
describe("npx thirdweb create", () => {
it("should create app (CRA) successfully", async () => {
@@ -16,6 +16,8 @@ describe("npx thirdweb create", () => {
await pressKey("enter");
await waitForText(CREATE_MESSAGES.projectName);
await pressKey("enter");
await waitForText(CREATE_MESSAGES.chain);
await pressKey("enter");
await waitForText(CREATE_MESSAGES.framework);
// select CRA
await pressKey("arrowDown");
+3 -3
View File
@@ -15,8 +15,8 @@ describe("npx thirdweb deploy", () => {
`${path}/BasicContract.sol`,
);
const { waitForText, waitForFinish, getExitCode, writeText, getStdout } =
await spawn("node", "./dist/cli/index.js deploy");
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
await spawn("node", "./dist/cli/index.js deploy --contract");
expect(await exists("BasicContract.sol")).toEqual(true);
@@ -26,7 +26,7 @@ describe("npx thirdweb deploy", () => {
// wait for program to finish
await waitForFinish();
expect(getStdout().at(-1)).toContain(
expect(getStderr().at(-1)).toContain(
"https://thirdweb.com/contracts/deploy/",
);
+4
View File
@@ -19,6 +19,10 @@ describe("npx thirdweb detect", () => {
await create.waitForText(CREATE_MESSAGES.framework);
// select hardhat
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contractName);
// set contract name
await create.writeText("Contract");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contract);
// select ERC721
await create.pressKey("arrowDown");
+2 -2
View File
@@ -15,7 +15,7 @@ describe("npx thirdweb release", () => {
`${path}/BasicContract.sol`,
);
const { waitForText, waitForFinish, getExitCode, writeText, getStdout } =
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
await spawn("node", "./dist/cli/index.js release");
expect(await exists("BasicContract.sol")).toEqual(true);
@@ -26,7 +26,7 @@ describe("npx thirdweb release", () => {
// wait for program to finish
await waitForFinish();
expect(getStdout().at(-1)).toContain(
expect(getStderr().at(-1)).toContain(
"https://thirdweb.com/contracts/release/",
);
+6 -12
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.7.24",
"version": "0.9.6",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -10,7 +10,7 @@
},
"devDependencies": {
"@gmrchk/cli-testing-library": "^0.1.2",
"@types/async-retry": "1.3.0",
"@types/async-retry": "^1.3.0",
"@types/cross-spawn": "^6.0.2",
"@types/inquirer": "^8.2.1",
"@types/jest": "^29.0.0",
@@ -31,24 +31,18 @@
"dependencies": {
"@thirdweb-dev/sdk": "*",
"async-retry": "^1.3.3",
"cbor": "^8.1.0",
"commander": "^9.1.0",
"cpy": "^9.0.1",
"detect-package-manager": "^2.0.1",
"enquirer": "^2.3.6",
"ethers": "^5.7.0",
"form-data": "^4.0.0",
"ethers": "^5.7.2",
"got": "11.8.5",
"inquirer": "^8.2.3",
"ipfs-unixfs": "^6.0.7",
"ipld-dag-pb": "^0.22.3",
"multihashes": "^4.0.3",
"open": "^8.4.0",
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
"solc": "0.8.13",
"solc": "0.8.17",
"tar": "^6.1.11",
"tslog": "^3.3.3",
"update-check": "^1.5.4",
"update-notifier": "^6.0.2",
"validate-npm-package-name": "^4.0.0",
"yaml": "^2.1.1"
@@ -80,4 +74,4 @@
"sourcemap": true,
"clean": true
}
}
}
+275 -116
View File
@@ -1,39 +1,38 @@
#!/usr/bin/env node
import { installGithubAction } from "../common/ci-installer";
import { detectExtensions } from "../common/feature-detector";
import { processProject } from "../common/processor";
import { cliVersion, pkg } from "../constants/urls";
import { info, logger } from "../core/helpers/logger";
import { info, logger, spinner } from "../core/helpers/logger";
import { twCreate } from "../create/command";
import generateDashboardUrl from "../helpers/generate-dashboard-url";
import { deploy } from "../deploy";
import { findPackageInstallation } from "../helpers/detect-local-packages";
import { upload } from "../storage/command";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import chalk from "chalk";
import { exec, spawn } from "child_process";
import { Command } from "commander";
import open from "open";
import prompts from "prompts";
const main = async () => {
// eslint-disable-next-line turbo/no-undeclared-env-vars
const skipIntro = process.env.THIRDWEB_CLI_SKIP_INTRO === "true";
const program = new Command();
//yes this has to look like this, eliminates whitespace
console.info(`
$$\\ $$\\ $$\\ $$\\ $$\\
$$ | $$ | \\__| $$ | $$ |
$$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$$$$\\
\\_$$ _| $$ __$$\\ $$ |$$ __$$\\ $$ __$$ |$$ | $$ | $$ |$$ __$$\\ $$ __$$\\
$$ | $$ | $$ |$$ |$$ | \\__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ |
$$ |$$\\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ |
\\$$$$ |$$ | $$ |$$ |$$ | \\$$$$$$$ |\\$$$$$\\$$$$ |\\$$$$$$$\\ $$$$$$$ |
\\____/ \\__| \\__|\\__|\\__| \\_______| \\_____\\____/ \\_______|\\_______/ `);
console.info(`\n 💎 thirdweb-cli v${cliVersion} 💎\n`);
import("update-notifier").then(({ default: updateNotifier }) => {
updateNotifier({
pkg,
shouldNotifyInNpmScript: true,
// check every time while we're still building the CLI
updateCheckInterval: 0,
}).notify();
});
// yes this has to look like this, eliminates whitespace
if (!skipIntro) {
console.info(`
$$\\ $$\\ $$\\ $$\\ $$\\
$$ | $$ | \\__| $$ | $$ |
$$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$$$$\\
\\_$$ _| $$ __$$\\ $$ |$$ __$$\\ $$ __$$ |$$ | $$ | $$ |$$ __$$\\ $$ __$$\\
$$ | $$ | $$ |$$ |$$ | \\__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ |
$$ |$$\\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ |
\\$$$$ |$$ | $$ |$$ |$$ | \\$$$$$$$ |\\$$$$$\\$$$$ |\\$$$$$$$\\ $$$$$$$ |
\\____/ \\__| \\__|\\__|\\__| \\_______| \\_____\\____/ \\_______|\\_______/ `);
console.info(`\n 💎 thirdweb-cli v${cliVersion} 💎\n`);
}
program
.name("thirdweb-cli")
@@ -41,101 +40,45 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
.version(cliVersion, "-v, --version");
program
.command("create")
.command("create [projectType] [projectPath]")
.description(
"Create a thirdweb app from any of our official templates. Checkout some examples you can use here: https://github.com/thirdweb-example/",
"Create a web3 app from any of our official templates: https://github.com/thirdweb-example/",
)
.option("--app", `Create a thirdweb app.`)
.option("--contract", `Create a thirdweb contracts project.`)
.option("--ts, --typescript", `Initialize as a TypeScript project.`)
.option("--js, --javascript", `Initialize as a JavaScript project.`)
.option("--forge", `Initialize as a Forge project.`)
.option("--hardhat", `Initialize as a Hardhat project.`)
.option("--cra", `Initialize as a Create React App project.`)
.option("--next", `Initialize as a Next.js project.`)
.option("--vite", `Initialize as a Vite project.`)
.option("--app", "Create a web3 app.")
.option("--contract", "Create a web3 contract project")
.option("--ts, --typescript", "Initialize as a TypeScript project.")
.option("--js, --javascript", "Initialize as a JavaScript project.")
.option("--forge", "Initialize as a Forge project.")
.option("--hardhat", "Initialize as a Hardhat project.")
.option("--cra", "Initialize as a Create React App project.")
.option("--next", "Initialize as a Next.js project.")
.option("--vite", "Initialize as a Vite project.")
.option(
"--use-npm",
`Explicitly tell the CLI to bootstrap the app using npm`,
"Explicitly tell the CLI to bootstrap the app using npm",
)
.option(
"--use-pnpm",
`Explicitly tell the CLI to bootstrap the app using pnpm`,
"Explicitly tell the CLI to bootstrap the app using pnpm",
)
.option("--framework [name]", `The preferred framework.`)
.option("--framework [name]", "The preferred framework.")
.option("--solana", "Initialize as a Solana project.")
.option("--evm", "Initialize as an Ethereum project.")
.option(
"-t, --template [name]",
`A template to start your project from. You can use an template repository name from the official thirdweb-example org.`,
)
.action(async (options) => {
await twCreate(options);
});
program
.command("deploy")
.description(
"Deploy contracts through your thirdweb dashboard, without dealing with private keys.",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.option(
"-n, --name [name]",
"Name of the pre-built or released contract (such as nft-drop)",
"A template to start your project from. You can use an template repository name from the official thirdweb-example org.",
)
.option(
"-cv, --contract-version [version]",
"Version of the released contract",
"-c, --contract-name [name]",
"Name of the new smart contract to create",
)
.action(async (options) => {
if (options.name) {
const url = generateDashboardUrl(options.name, options.contractVersion);
if (!url) {
logger.error(
chalk.red(
`Could not find a contract named ${options.name} ${
options.contractVersion || ""
}`,
),
);
return;
}
info(`Open this link to deploy your contract:`);
logger.info(chalk.blueBright(url));
open(url.toString());
return;
}
const url = await processProject(options, "deploy");
info(`Open this link to deploy your contracts:`);
logger.info(chalk.blueBright(url.toString()));
open(url.toString());
.action(async (type, path, options) => {
await twCreate(type, path, options);
});
program
.command("release")
.description(
"Release contracts, making them available for others to deploy and unlocking SDKs, Dashboards and Analytics.",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.action(async (options) => {
const url = await processProject(options, "release");
info(`Open this link to release your contracts:`);
logger.info(chalk.blueBright(url.toString()));
open(url.toString());
});
program
.command("detect")
.description(
"Compile contracts and detect implemented thirdweb contract extensions",
)
.command("build")
.description("Compile contract and detect thirdweb contract extensions")
.option("-p, --path <project-path>", "path to project", ".")
.option("-d, --debug", "show debug logs")
.option("-a, --all", "run detection on all contracts")
@@ -144,29 +87,245 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
});
program
.command("upload")
.description("Upload any file or directory using decentralized storage")
.argument("<upload-path>", "path to file or directory to upload")
.action(async (path) => {
const storage = new ThirdwebStorage();
const uri = await upload(storage, path);
info(`Files stored at the following IPFS URI:`);
logger.info(chalk.blueBright(uri.toString()));
const url = storage.resolveScheme(uri);
info(`Open this link to view your upload:`);
logger.info(chalk.blueBright(url.toString()));
.command("deploy")
.description("Deploy your (or team) contracts securely to blockchains")
.option("-p, --path <project-path>", "path to project", ".")
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.option(
"--dist-path [distPath]",
"Path to the dist folder where the HTML based App is",
)
.option(
"-n, --name [name]",
"Name of the pre-built or released contract (such as nft-drop)",
)
.option(
"-f, --file [name]",
"Filter for contract files that contain this file name",
)
.option(
"-cn, --contract-name [name]",
"Filter for contracts that contain this contract name",
)
.option(
"-cv, --contract-version [version]",
"Version of the released contract",
)
.option("--app", "Deploy a web app to decentralized storage")
.option("--contract", "Deploy a smart contract to blockchains")
.action(async (options) => {
const url = await deploy(options);
if (url) {
open(url);
}
});
program
.command("install-ci")
.command("release")
.description(
"(alpha) Set up continuous integration for your contracts. This adds a github action to deploy the project on pull requests and pushes to branches. Publishes on push the the main branch.",
"Release your protocol so other devs can deploy them and unlock SDKs, Dashboards and Analytics",
)
.option("-p, --path <project-path>", "path to project", ".")
.option(
"-f, --file [name]",
"Filter for contract files that contain the file name",
)
.option(
"-cn, --contract-name [name]",
"Filter for contracts that contain this contract name",
)
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.action(async (options) => {
await installGithubAction(options);
const url = await processProject(options, "release");
info(
`Open this link to release your contracts: ${chalk.blueBright(
url.toString(),
)}`,
);
open(url.toString());
});
program
.command("upload")
.description("Upload any file or directory to decentralized storage (IPFS)")
.argument("[upload]", "path to file or directory to upload")
.action(async (path) => {
const storage = new ThirdwebStorage();
try {
const uri = await upload(storage, path);
info(
`Files stored at the following IPFS URI: ${chalk.blueBright(
uri.toString(),
)}`,
);
const url = storage.resolveScheme(uri);
info(
`Open this link to view your upload: ${chalk.blueBright(
url.toString(),
)}`,
);
} catch (err: any) {
if (
err.toString() === "No files detected in specified directory" ||
err.toString() === "Invalid path provided" ||
err.toString() === "No path provided"
) {
logger.error(
chalk.redBright(
"Please specify a valid file or directory to upload",
),
);
} else {
logger.error(chalk.redBright("Failed to upload files"), err);
}
}
});
program
.command("detect")
.description(
"(deprecated) Compile contracts and detect implemented thirdweb contract extensions",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("-d, --debug", "show debug logs")
.option("-a, --all", "run detection on all contracts")
.action(async (options) => {
await detectExtensions(options);
});
if (!skipIntro) {
const versionSpinner = spinner("Checking for updates...");
await import("update-notifier").then(
async ({ default: updateNotifier }) => {
const notifier = updateNotifier({
pkg,
shouldNotifyInNpmScript: true,
// check every time while we're still building the CLI
updateCheckInterval: 0,
});
const versionInfo = await notifier.fetchInfo();
versionSpinner.stop();
if (versionInfo.type !== "latest") {
const res = await prompts({
type: "toggle",
name: "upgrade",
message: `A new version of the CLI is available. Would you like to upgrade?`,
initial: true,
active: "yes",
inactive: "no",
});
if (res.upgrade) {
const updateSpinner = spinner(
`Upgrading CLI to version ${versionInfo.latest}...`,
);
const clonedEnvironment = { ...process.env };
clonedEnvironment.THIRDWEB_CLI_SKIP_INTRO = "true";
const installation = await findPackageInstallation();
// If the package isn't installed anywhere, just defer to npx thirdweb@latest
if (!installation) {
updateSpinner.succeed(
`Now using CLI version ${versionInfo.latest}. Continuing execution...`,
);
await new Promise((done, failed) => {
const shell = spawn(
`npx --yes thirdweb@latest ${process.argv
.slice(2)
.join(" ")}`,
[],
{ stdio: "inherit", shell: true, env: clonedEnvironment },
);
shell.on("close", (code) => {
if (code === 0) {
done("");
} else {
failed();
}
});
});
return process.exit(0);
}
// Otherwise, get the correct command based on package manager and local vs. global
let command = "";
switch (installation.packageManager) {
case "npm":
command = installation.isGlobal
? `npm install -g thirdweb`
: `npm install thirdweb`;
break;
case "yarn":
command = installation.isGlobal
? `yarn global add thirdweb`
: `yarn add thirdweb`;
break;
case "pnpm":
command = installation.isGlobal
? `pnpm add -g thirdweb@latest`
: `pnpm add thirdweb@latest`;
break;
default:
console.error(
`Could not detect package manager in use, aborting automatic upgrade.\nIf you want to upgrade the CLI, please do it manually with your package manager.`,
);
process.exit(1);
}
await new Promise((done, failed) => {
exec(command, (err, stdout, stderr) => {
if (err) {
failed(err);
return;
}
done({ stdout, stderr });
});
});
updateSpinner.succeed(
`Successfully upgraded CLI to version ${versionInfo.latest}. Continuing execution...`,
);
// If the package is installed globally with yarn or pnpm, then npx won't recognize it
// So we need to make sure to run the command directly
const executionCommand =
!installation.isGlobal || installation.packageManager === "npm"
? `npx thirdweb`
: `thirdweb`;
await new Promise((done, failed) => {
const shell = spawn(
`${executionCommand} ${process.argv.slice(2).join(" ")}`,
[],
{ stdio: "inherit", shell: true, env: clonedEnvironment },
);
shell.on("close", (code) => {
if (code === 0) {
done("");
} else {
failed();
}
});
});
process.exit(0);
}
}
},
);
}
await program.parseAsync();
};
+43 -6
View File
@@ -76,7 +76,7 @@ export async function processProject(
}
}
let compiledResult;
let compiledResult: { contracts: ContractPayload[] };
const compileLoader = spinner("Compiling project...");
try {
compiledResult = await build(projectPath, projectType);
@@ -106,10 +106,47 @@ export async function processProject(
if (options.ci) {
selectedContracts = compiledResult.contracts;
} else {
const choices = compiledResult.contracts.map((c) => ({
name: c.name,
value: c,
}));
const filtered = compiledResult.contracts
.filter((c) => {
if (typeof options.file === "string" && options.file.length > 0) {
return c.fileName.includes(options.file);
}
return true;
})
.filter((c) => {
if (
typeof options.contractName === "string" &&
options.contractName.length > 0
) {
return c.name.includes(options.contractName);
}
return true;
});
if (filtered.length === 0) {
logger.error(`No contracts found matching the specified filters.`);
process.exit(1);
}
const choices = filtered.map((c) => {
if (
compiledResult.contracts.filter(
(other: ContractPayload) => other.name === c.name,
).length > 1
) {
return {
name: `${c.name} - ${chalk.gray(c.fileName)}`,
value: c,
};
}
return {
name: c.name,
value: c,
};
});
const prompt = createContractsPrompt(
choices,
`Choose which contract(s) to ${command}`,
@@ -164,7 +201,7 @@ export async function processProject(
const metadataURIs = await Promise.all(
selectedContracts.map(async (c) => {
logger.debug(`Uploading ${c.name}...`);
return await storage.upload(JSON.parse(c.metadata), {
return await storage.upload(JSON.parse(JSON.stringify(c.metadata)), {
uploadWithoutDirectory: true,
});
}),
+1
View File
@@ -55,6 +55,7 @@ export class BrownieBuilder extends BaseBuilder {
metadata: {},
bytecode,
sources: [], // TODO
fileName: "", // TODO
name: contractName,
});
break;
@@ -1,7 +1,7 @@
import { extractIPFSHashFromBytecode } from "../helpers/ipfs";
import { logger } from "../helpers/logger";
import { CompileOptions, IBuilder } from "../interfaces/Builder";
import { ContractPayload } from "../interfaces/ContractPayload";
import { extractIPFSHashFromBytecode } from "@thirdweb-dev/sdk/evm";
export abstract class BaseBuilder implements IBuilder {
abstract compile(
+20
View File
@@ -1,9 +1,11 @@
import { findFiles } from "../../common/file-helper";
import { hasForge } from "../../create/helpers/has-forge";
import { execute } from "../helpers/exec";
import { logger } from "../helpers/logger";
import { CompileOptions } from "../interfaces/Builder";
import { ContractPayload } from "../interfaces/ContractPayload";
import { BaseBuilder } from "./builder-base";
import chalk from "chalk";
import { existsSync, readFileSync } from "fs";
import { basename, join } from "path";
@@ -11,6 +13,18 @@ export class FoundryBuilder extends BaseBuilder {
public async compile(options: CompileOptions): Promise<{
contracts: ContractPayload[];
}> {
const isInstalled = await hasForge();
if (!isInstalled) {
console.error(
`\n${chalk.redBright(
`error`,
)} You don't have forge installed on this machine!\n\nYou can install forge by following these instructions:\n${chalk.blueBright(
`https://book.getfoundry.sh/getting-started/installation`,
)}\n`,
);
process.exit(1);
}
await execute("forge clean", options.projectPath);
await execute("forge build --extra-output metadata", options.projectPath);
@@ -88,6 +102,11 @@ export class FoundryBuilder extends BaseBuilder {
})
.filter((path) => path !== undefined) as string[];
const fileNames = Object.keys(
parsedMetadata?.settings?.compilationTarget || {},
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (
this.shouldProcessContract(
contractInfo.abi,
@@ -99,6 +118,7 @@ export class FoundryBuilder extends BaseBuilder {
name: contractName,
metadata,
bytecode,
fileName,
sources,
});
}
+7 -1
View File
@@ -25,7 +25,7 @@ export class HardhatBuilder extends BaseBuilder {
//the hardhat extractor **logs out** the runtime config of hardhat, we take that stdout and parse it
const stringifiedConfig = (
await execute(
`npx hardhat run ${configExtractorScriptPath} --no-compile`,
`npx hardhat run "${configExtractorScriptPath}" --no-compile`,
options.projectPath,
)
).stdout;
@@ -123,11 +123,17 @@ export class HardhatBuilder extends BaseBuilder {
})
.filter((path) => path !== undefined) as string[];
const fileNames = Object.keys(
meta?.settings?.compilationTarget || {},
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (this.shouldProcessContract(abi, deployedBytecode, contractName)) {
contracts.push({
metadata,
bytecode,
name: contractName,
fileName,
sources,
});
}
+6
View File
@@ -140,11 +140,17 @@ export class SolcBuilder extends BaseBuilder {
})
.filter((path) => path !== undefined) as string[];
const fileNames = Object.keys(
parsedMetadata?.settings?.compilationTarget || {},
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (this.shouldProcessContract(abi, deployedBytecode, contractName)) {
contracts.push({
metadata,
bytecode,
name: contractName,
fileName,
sources: _sources,
});
}
+7
View File
@@ -72,11 +72,18 @@ export class TruffleBuilder extends BaseBuilder {
return undefined;
})
.filter((path) => path !== undefined) as string[];
const fileNames = Object.keys(
parsedMetadata?.settings?.compilationTarget || {},
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (this.shouldProcessContract(abi, deployedBytecode, contractName)) {
contracts.push({
metadata,
bytecode,
name: contractName,
fileName,
sources,
});
}
@@ -36,6 +36,7 @@ export default async function detect(
name: "continue",
message:
"Do you want to continue and compile this project with solc instead?",
initial: true,
});
const shouldCompile = await prompt.run();
if (!shouldCompile) {
+11
View File
@@ -0,0 +1,11 @@
import { ProjectType } from "../types/ProjectType";
import { Detector } from "./detector";
import { existsSync } from "fs";
export default class NPMDetector implements Detector {
public projectType: ProjectType = "npm";
public matches(path: string): boolean {
return existsSync(path + "/package-lock.json");
}
}
+14
View File
@@ -0,0 +1,14 @@
import { ProjectType } from "../types/ProjectType";
import { Detector } from "./detector";
import { existsSync } from "fs";
export default class ViteDetector implements Detector {
public projectType: ProjectType = "vite";
public matches(path: string): boolean {
return (
existsSync(path + "/vite.config.js") ||
existsSync(path + "/vite.config.ts")
);
}
}
+11
View File
@@ -0,0 +1,11 @@
import { ProjectType } from "../types/ProjectType";
import { Detector } from "./detector";
import { existsSync } from "fs";
export default class YarnDetector implements Detector {
public projectType: ProjectType = "yarn";
public matches(path: string): boolean {
return existsSync(path + "/yarn.lock");
}
}
-66
View File
@@ -1,66 +0,0 @@
import { decodeFirstSync } from "cbor";
import { UnixFS } from "ipfs-unixfs";
import { DAGNode } from "ipld-dag-pb";
import { toB58String } from "multihashes";
/**
* Derives IPFS hash of string
* @param {String} str
* @return {String} IPFS hash (ex: "Qm")
*/
export async function getIPFSHash(str: string) {
const file = new UnixFS({
type: "file",
data: Buffer.from(str),
});
const node = new DAGNode(file.marshal());
const metadataLink = await node.toDAGLink();
return toB58String(metadataLink.Hash.multihash);
}
/**
* Extract the IPFS hash from the given bytecode
* @param bytecode
* @returns
*/
export function extractIPFSHashFromBytecode(
bytecode: string,
): string | undefined {
const numericBytecode = hexToBytes(bytecode);
const cborLength: number =
numericBytecode[numericBytecode.length - 2] * 0x100 +
numericBytecode[numericBytecode.length - 1];
const bytecodeBuffer = Buffer.from(
numericBytecode.slice(numericBytecode.length - 2 - cborLength, -2),
);
const cborData = decodeFirstSync(bytecodeBuffer);
if (cborData["ipfs"]) {
const uri = toB58String(cborData["ipfs"]);
return uri;
}
return undefined;
}
function hexToBytes(hex: string | number) {
hex = hex.toString(16);
if (!hex.startsWith("0x")) {
hex = `0x${hex}`;
}
if (!isHexStrict(hex)) {
throw new Error('Given value "' + hex + '" is not a valid hex string.');
}
hex = hex.replace(/^0x/i, "");
for (var bytes = [], c = 0; c < hex.length; c += 2) {
bytes.push(parseInt(hex.slice(c, c + 2), 16));
}
return bytes;
}
function isHexStrict(hex: string | number) {
return (
(typeof hex === "string" || typeof hex === "number") &&
/^(-)?0x[0-9a-f]*$/i.test(hex.toString())
);
}
@@ -17,6 +17,11 @@ export interface ContractPayload {
*/
metadata: any;
/**
* The file name of the original compiled file
*/
fileName: string;
/**
* The source file paths
*/
@@ -4,4 +4,10 @@ export type ProjectType =
| "hardhat"
| "truffle"
| "solc"
| "vite"
| "next"
| "cra"
| "spa-webapp"
| "yarn"
| "npm"
| "none";
+265 -134
View File
@@ -2,60 +2,82 @@
/* eslint-disable import/no-extraneous-dependencies */
import { CREATE_MESSAGES } from "../../constants/constants";
import detect from "../core/detection/detect";
import { DownloadError, createApp } from "./helpers/create-app";
import { createContract } from "./helpers/create-contract";
import { createContractProject } from "./helpers/create-contract";
import { getPkgManager } from "./helpers/get-pkg-manager";
import { validateNpmName } from "./helpers/validate-pkg";
import chalk from "chalk";
import fs from "fs";
import path from "path";
import prompts from "prompts";
let projectType: string = "";
let contractName: string = "";
let projectPath: string = "";
let projectType: string = "";
let framework: string = "";
let language: string = "";
let baseContract: string = "";
let chain: string = "";
/* let createType: string = "app"; */
export async function twCreate(options: any) {
if (typeof projectPath === "string") {
projectPath = projectPath.trim();
export async function twCreate(
pType: string,
pPath: string = "",
options: any,
) {
if (typeof pPath === "string") {
projectPath = pPath;
}
if (options.app) {
if (typeof options.contractName === "string") {
contractName = options.contractName;
}
if (pType === "app" || options.app) {
projectType = "app";
}
if (options.contract) {
} else if (pType === "contract" || options.contract) {
projectType = "contract";
}
if (options.typescript) {
language = "typescript";
if (projectType === "app") {
if (options.typescript) {
language = "typescript";
}
if (options.javascript) {
language = "javascript";
}
if (options.next) {
framework = "next";
}
if (options.cra) {
framework = "cra";
}
if (options.vite) {
framework = "vite";
}
if (options.solana) {
chain = "solana";
}
if (options.evm) {
chain = "evm";
}
}
if (options.javascript) {
language = "javascript";
}
if (projectType === "contract") {
if (options.forge) {
framework = "forge";
}
if (options.next) {
framework = "next";
}
if (options.cra) {
framework = "cra";
}
if (options.vite) {
framework = "vite";
}
if (options.forge) {
framework = "forge";
}
if (options.hardhat) {
framework = "hardhat";
if (options.hardhat) {
framework = "hardhat";
}
}
if (options.framework) {
@@ -76,103 +98,216 @@ export async function twCreate(options: any) {
if (typeof res.projectType === "string") {
projectType = res.projectType.trim();
}
} else if (!projectType && options.template) {
} else if (!projectType || options.template) {
// If no project type is specified, but a template is, we assume the user wants to create an app.
// We do this so old users can still use the --template flag to create an app.
projectType = "app";
}
if (!projectPath) {
const defaultName =
projectType === "contract" ? "thirdweb-contracts" : "thirdweb-app";
const res = await prompts({
type: "text",
name: "path",
message: CREATE_MESSAGES.projectName,
initial: options.template || defaultName,
format: (name: string) => name.toLowerCase(),
validate: (name: string) => {
const validation = validateNpmName(
path.basename(path.resolve(name.toLowerCase())),
);
if (validation.valid) {
return true;
}
return "Invalid project name: " + validation.problems?.[0];
},
});
if (typeof res.path === "string") {
projectPath = res.path.trim();
}
}
if (!projectPath) {
console.log(
"\nPlease specify the project directory:\n" +
` ${chalk.cyan("npx thirdweb create")} ${chalk.green(
"<project-directory>",
)}\n` +
"For example:\n" +
` ${chalk.cyan("npx thirdweb create")} ${chalk.green(
"my-thirdweb-app",
)}\n\n` +
`Run ${chalk.cyan("npx thirdweb --help")} to see all options.`,
);
process.exit(1);
}
if (!options.template) {
if (projectType === "app" && !framework) {
const res = await prompts({
type: "select",
name: "framework",
message: CREATE_MESSAGES.framework,
choices: [
{ title: "Next.js", value: "next" },
{ title: "Create React App", value: "cra" },
{ title: "Vite", value: "vite" },
],
});
if (typeof res.framework === "string") {
framework = res.framework.trim();
}
}
if (projectType === "app" && !language) {
const res = await prompts({
type: "select",
name: "language",
message: CREATE_MESSAGES.language,
choices: [
{ title: "JavaScript", value: "javascript" },
{ title: "TypeScript", value: "typescript" },
],
});
if (typeof res.language === "string") {
language = res.language.trim();
}
}
// Whether to only create a new contract without the project
let onlyContract = false;
if (projectType === "contract") {
const resolvedProjectPath = path.resolve(projectPath);
const contractProjectType = await detect(resolvedProjectPath, {});
if (
projectType === "contract" &&
framework !== "forge" &&
framework !== "hardhat"
contractProjectType === "foundry" &&
fs.existsSync(path.join(resolvedProjectPath, "src"))
) {
onlyContract = true;
projectPath = path.join(projectPath, "src");
} else if (contractProjectType === "hardhat") {
if (fs.existsSync(path.join(resolvedProjectPath, "contracts"))) {
onlyContract = true;
projectPath = path.join(projectPath, "contracts");
} else {
// If there's no expected contracts folder, check for a directory that has .sol files
const directories = fs
.readdirSync(resolvedProjectPath)
.filter((file) =>
fs.lstatSync(path.join(resolvedProjectPath, file)).isDirectory(),
);
for (const directory of directories) {
const files = fs.readdirSync(path.join(projectPath, directory));
if (files.some((file) => file.endsWith(".sol"))) {
onlyContract = true;
projectPath = path.join(projectPath, directory);
break;
}
}
}
}
}
if (!onlyContract) {
if (!projectPath) {
const defaultName =
projectType === "contract" ? "thirdweb-contracts" : "thirdweb-app";
const res = await prompts({
type: "select",
name: "framework",
message: CREATE_MESSAGES.framework,
choices: [
{ title: "Hardhat", value: "hardhat" },
{ title: "Forge", value: "forge" },
],
type: "text",
name: "path",
message: CREATE_MESSAGES.projectName,
initial: options.template || defaultName,
format: (name: string) => name.toLowerCase(),
validate: (name: string) => {
const validation = validateNpmName(
path.basename(path.resolve(name.toLowerCase())),
);
if (validation.valid) {
return true;
}
return "Invalid project name: " + validation.problems?.[0];
},
});
if (typeof res.framework === "string") {
framework = res.framework.trim();
if (typeof res.path === "string") {
projectPath = path.join(projectPath, res.path.trim());
}
}
if (!projectPath) {
console.log(
"\nPlease specify the project directory:\n" +
` ${chalk.cyan("npx thirdweb create")} ${chalk.green(
"<project-directory>",
)}\n` +
"For example:\n" +
` ${chalk.cyan("npx thirdweb create")} ${chalk.green(
"my-thirdweb-app",
)}\n\n` +
`Run ${chalk.cyan("npx thirdweb --help")} to see all options.`,
);
process.exit(1);
}
if (!options.template) {
if (projectType === "app" && !chain) {
const res = await prompts({
type: "select",
name: "chain",
message: CREATE_MESSAGES.chain,
choices: [
{ title: "EVM", value: "evm" },
{ title: "Solana", value: "solana" },
],
});
if (res.chain === "solana") {
chain = "solana";
} else {
chain = "evm";
}
}
if (projectType === "app" && !framework) {
const res = await prompts({
type: "select",
name: "framework",
message: CREATE_MESSAGES.framework,
choices:
// Solana doesn't support Vite just yet:
chain === "solana"
? [
{ title: "Next.js", value: "next" },
{ title: "Create React App", value: "cra" },
// { title: "Vite", value: "vite" },
]
: [
{ title: "Next.js", value: "next" },
{ title: "Create React App", value: "cra" },
{ title: "Vite", value: "vite" },
],
});
if (typeof res.framework === "string") {
framework = res.framework.trim();
}
}
if (projectType === "app" && !language) {
const res = await prompts({
type: "select",
name: "language",
message: CREATE_MESSAGES.language,
choices: [
{ title: "JavaScript", value: "javascript" },
{ title: "TypeScript", value: "typescript" },
],
});
if (typeof res.language === "string") {
language = res.language.trim();
}
}
if (
projectType === "contract" &&
framework !== "forge" &&
framework !== "hardhat"
) {
const res = await prompts({
type: "select",
name: "framework",
message: CREATE_MESSAGES.framework,
choices: [
{ title: "Hardhat", value: "hardhat" },
{ title: "Forge", value: "forge" },
],
});
if (typeof res.framework === "string") {
framework = res.framework.trim();
}
}
if (!framework) {
console.log("Please specify a framework");
process.exit(1);
}
if (!language) {
// Default = JavaScript
language = "javascript";
}
}
}
if (projectType === "contract") {
// Select contract name
if (!contractName) {
const defaultName = "MyContract";
const res = await prompts({
type: "text",
name: "path",
message: CREATE_MESSAGES.contractName,
initial: defaultName,
validate: (name: string) => {
const isValid = /(^[a-z0-9A-Z]+$)|(^[a-z0-9A-Z]+\.sol$)/.test(name);
if (isValid) {
return true;
}
return `Invalid contract name 'contractName' (only alphanumeric characters allowed)`;
},
});
if (typeof res.path === "string") {
contractName = res.path.trim();
}
if (!contractName) {
console.log(
"\nPlease specify the contract name:\n" +
` ${chalk.cyan(
"npx thirdweb create --contract --name",
)} ${chalk.green("<contract-name>")}\n` +
"For example:\n" +
` ${chalk.cyan(
"npx thirdweb create --contract --name",
)} ${chalk.green("MyContract")}\n\n` +
`Run ${chalk.cyan("npx thirdweb --help")} to see all options.`,
);
process.exit(1);
}
}
@@ -184,7 +319,9 @@ export async function twCreate(options: any) {
name: "standard",
message: CREATE_MESSAGES.contract,
choices: [
{ title: "Empty Contract", value: "none" },
...(!onlyContract
? [{ title: "Empty Contract", value: "none" }]
: []),
{ title: "ERC721", value: "erc721" },
{ title: "ERC20", value: "erc20" },
{ title: "ERC1155", value: "erc1155" },
@@ -238,20 +375,11 @@ export async function twCreate(options: any) {
}
}
}
if (!framework) {
console.log("Please specify a framework");
process.exit(1);
}
if (!language) {
// Default = JavaScript
language = "javascript";
}
}
const resolvedProjectPath = path.resolve(projectPath);
const projectName = path.basename(resolvedProjectPath);
// Resolve project path
projectPath = path.resolve(projectPath);
const projectName = path.basename(projectPath);
const { valid, problems } = validateNpmName(projectName);
if (!valid) {
@@ -283,18 +411,21 @@ export async function twCreate(options: any) {
try {
if (projectType === "app") {
await createApp({
appPath: resolvedProjectPath,
appPath: projectPath,
packageManager,
framework,
language,
template,
chain,
});
} else {
await createContract({
contractPath: resolvedProjectPath,
await createContractProject({
contractPath: projectPath,
packageManager,
framework,
contractName,
baseContract,
onlyContract,
});
}
} catch (reason) {
@@ -22,12 +22,14 @@ export async function createApp({
framework,
language,
template,
chain,
}: {
appPath: string;
packageManager: PackageManager;
framework?: string;
language?: string;
template?: string;
chain?: string;
}): Promise<void> {
let frameworkPath = "";
@@ -43,7 +45,9 @@ export async function createApp({
process.exit(1);
}
} else if (framework) {
frameworkPath = `${framework}-${language || "javascript"}-starter`;
frameworkPath = `${framework}-${language || "javascript"}-${
chain === "solana" ? "solana-" : ""
}starter`;
const found = await hasTemplate(frameworkPath);
if (!found) {
@@ -2,6 +2,7 @@ import { hasBaseContract, readBaseContract } from "./base-contracts";
import { DownloadError } from "./create-app";
import { PackageManager } from "./get-pkg-manager";
import { tryGitInit } from "./git";
import { hasForge } from "./has-forge";
import { install } from "./install";
import { isFolderEmpty } from "./is-folder-empty";
import { getOnline } from "./is-online";
@@ -11,22 +12,28 @@ import { submodules } from "./submodules";
import { downloadAndExtractRepo } from "./templates";
import retry from "async-retry";
import chalk from "chalk";
import fs from "fs";
import { writeFile } from "fs/promises";
import path from "path";
interface ICreateContract {
interface ICreateContractProject {
contractPath: string;
packageManager: PackageManager;
contractName: string;
framework?: string;
baseContract?: string;
onlyContract: boolean;
}
export async function createContract({
export async function createContractProject({
contractPath,
packageManager,
framework,
contractName,
baseContract,
}: ICreateContract) {
onlyContract,
}: ICreateContractProject) {
// Check that the selected base contract is valid
if (baseContract) {
const found = hasBaseContract(baseContract);
@@ -40,8 +47,8 @@ export async function createContract({
}
}
// Check that we have write permission for the specified directory
const root = path.resolve(contractPath);
if (!(await isWriteable(path.dirname(root)))) {
console.error(
"The application path is not writable, please check folder permissions and try again.",
@@ -52,117 +59,179 @@ export async function createContract({
process.exit(1);
}
const projectName = path.basename(root);
await makeDir(root);
if (!isFolderEmpty(root, projectName)) {
// Check that the contract name is valid
if (!/(^[a-z0-9A-Z]+$)|(^[a-z0-9A-Z]+\.sol$)/.test(contractName)) {
console.error(
`Contract name ${chalk.red(
`"${contractName}"`,
)} is not valid (only alphanumeric characters are allowed).`,
);
process.exit(1);
}
// Clean the contract name
contractName = contractName.replace(/\.sol$/, "") + ".sol";
const useYarn = packageManager === "yarn";
const isOnline = !useYarn || (await getOnline());
const originalDirectory = process.cwd();
console.log(
`Creating a new thirdweb contracts project in ${chalk.green(root)}.`,
);
console.log();
process.chdir(root);
function isErrorLike(err: unknown): err is { message: string } {
return (
typeof err === "object" &&
err !== null &&
typeof (err as { message?: unknown }).message === "string"
);
}
try {
console.log(`Downloading files. This might take a moment.`);
let starter = "";
if (framework === "hardhat") {
starter = "hardhat-javascript-starter";
} else if (framework === "forge") {
starter = "forge-starter";
} else {
console.error("Please provide a valid contracts framework.");
if (onlyContract) {
// If we are already in a contracts project, just create a new contract
if (fs.existsSync(path.join(root, contractName))) {
console.error(
`A contract with the name ${chalk.red(
`"${contractName}"`,
)} already exists in specified directory.`,
);
process.exit(1);
}
await retry(
() => downloadAndExtractRepo(root, { name: starter, filePath: "" }),
{
retries: 3,
},
);
// Modify the /contracts/MyContract.sol contents to match the base contract
if (baseContract && baseContract.length > 0) {
const baseContractText = readBaseContract(baseContract);
// Set the contents of the Contract.sol file to the base contract
let contractFile = "";
if (framework === "hardhat") {
contractFile = path.join(root, "contracts", "Contract.sol");
}
if (framework === "forge") {
contractFile = path.join(root, "src", "Contract.sol");
}
contractFile = path.join(root, contractName);
// Write the base contract to the MyContract.sol file
await writeFile(contractFile, baseContractText);
console.log(
`${chalk.green("Success!")} Created ${contractName} at ${contractPath}`,
);
}
} catch (reason) {
throw new DownloadError(
isErrorLike(reason) ? reason.message : String(reason),
);
}
console.log("Installing packages. This might take a couple of minutes.");
console.log();
await install(root, null, { packageManager, isOnline });
console.log();
if (tryGitInit(root)) {
console.log("Initialized a git repository.");
console.log();
}
if (framework === "forge") {
await submodules();
}
let cdpath: string;
if (path.join(originalDirectory, projectName) === contractPath) {
cdpath = projectName;
} else {
cdpath = contractPath;
}
// Otherwise, create a new contracts project
const projectName = path.basename(root);
console.log(
`${chalk.green("Success!")} Created ${projectName} at ${contractPath}`,
);
console.log();
console.log("Inside that directory, you can run several commands:");
console.log();
console.log(chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} build`));
console.log(
" Compiles your contracts and detects thirdweb extensions implemented on them.",
);
console.log();
console.log(chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} deploy`));
console.log(" Deploys your contracts with the thirdweb deploy flow.");
console.log();
console.log(
chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} release`),
);
console.log(" Releases your contracts with the thirdweb release flow.");
console.log();
console.log("We suggest that you begin by typing:");
console.log();
console.log(chalk.cyan(" cd"), cdpath);
console.log();
await makeDir(root);
if (!isFolderEmpty(root, projectName)) {
process.exit(1);
}
const isOnline = !useYarn || (await getOnline());
const originalDirectory = process.cwd();
console.log(
`Creating a new thirdweb contracts project in ${chalk.green(root)}.`,
);
console.log();
process.chdir(root);
function isErrorLike(err: unknown): err is { message: string } {
return (
typeof err === "object" &&
err !== null &&
typeof (err as { message?: unknown }).message === "string"
);
}
try {
console.log(`Downloading files. This might take a moment.`);
let starter = "";
if (framework === "hardhat") {
starter = "hardhat-javascript-starter";
} else if (framework === "forge") {
starter = "forge-starter";
} else {
console.error("Please provide a valid contracts framework.");
process.exit(1);
}
await retry(
() => downloadAndExtractRepo(root, { name: starter, filePath: "" }),
{
retries: 3,
},
);
// Add in a new contracts file with specific base contract
if (baseContract && baseContract.length > 0) {
const baseContractText = readBaseContract(baseContract);
// Set the filename of the new file and delete the dummy Contract.sol file
let contractFile = "";
if (framework === "hardhat") {
fs.unlinkSync(path.join(root, "contracts", "Contract.sol"));
contractFile = path.join(root, "contracts", contractName);
}
if (framework === "forge") {
fs.unlinkSync(path.join(root, "src", "Contract.sol"));
contractFile = path.join(root, "src", contractName);
}
// Write the base contract to the new file
await writeFile(contractFile, baseContractText);
}
} catch (reason) {
throw new DownloadError(
isErrorLike(reason) ? reason.message : String(reason),
);
}
console.log("Installing packages. This might take a couple of minutes.");
console.log();
await install(root, null, { packageManager, isOnline });
console.log();
if (tryGitInit(root)) {
console.log("Initialized a git repository.");
console.log();
}
if (framework === "forge") {
await submodules();
}
let cdpath: string;
if (path.join(originalDirectory, projectName) === contractPath) {
cdpath = projectName;
} else {
cdpath = contractPath;
}
console.log(
`${chalk.green("Success!")} Created ${projectName} at ${contractPath}`,
);
console.log();
console.log("Inside that directory, you can run several commands:");
console.log();
console.log(
chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} build`),
);
console.log(
" Compiles your contracts and detects thirdweb extensions implemented on them.",
);
console.log();
console.log(
chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} deploy`),
);
console.log(" Deploys your contracts with the thirdweb deploy flow.");
console.log();
console.log(
chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} release`),
);
console.log(" Releases your contracts with the thirdweb release flow.");
console.log();
console.log("We suggest that you begin by typing:");
console.log();
console.log(chalk.cyan(" cd"), cdpath);
console.log();
if (framework === "forge") {
const isInstalled = await hasForge();
if (!isInstalled) {
console.log(
`\n${chalk.yellowBright(
`warning`,
)} You don't have forge installed on this machine, and will need it to run this project! \n\nYou can install forge by following these instructions:\n${chalk.blueBright(
`https://book.getfoundry.sh/getting-started/installation`,
)}\n`,
);
}
}
}
}
@@ -0,0 +1,14 @@
import { exec } from "child_process";
export async function hasForge() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return await new Promise((resolve, reject) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
exec("forge --version", (error, stdout, stderr) => {
if (error) {
resolve(false);
}
resolve(true);
});
});
}
+16 -1
View File
@@ -1,11 +1,26 @@
import spawn from "cross-spawn";
export async function runCommand(command: string, args: string[]) {
export async function runCommand(
command: string,
args: string[],
logging: boolean = false,
) {
return new Promise<void>((resolve, reject) => {
/**
* Spawn the installation process.
*/
const child = spawn(command, args);
child.stdout?.on("data", (data) => {
if (logging) {
console.log(data.toString());
}
});
child.stderr?.on("error", (err) => {
if (logging) {
console.error(err);
}
});
child.on("close", (code) => {
if (code !== 0) {
reject({ command: `${command}` });
+43
View File
@@ -0,0 +1,43 @@
import NPMDetector from "../core/detection/npm";
import ViteDetector from "../core/detection/vite";
import YarnDetector from "../core/detection/yarn";
import { runCommand } from "../create/helpers/run-command";
import { upload } from "../storage/command";
import { DEFAULT_IPFS_GATEWAY } from "@thirdweb-dev/sdk";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
export async function deployApp(distPath = "dist", projectPath = ".") {
const storage = new ThirdwebStorage();
const supportedFrameworks = [new ViteDetector()];
const possibleProjects = supportedFrameworks
.filter((detector) => detector.matches(projectPath))
.map((detector) => detector.projectType);
const hasYarn = new YarnDetector().matches(".");
const hasNPM = new NPMDetector().matches(".");
if (possibleProjects.length === 0) {
throw new Error("No supported project detected");
}
try {
if (hasYarn) {
await runCommand("yarn", ["build"]);
} else if (hasNPM) {
await runCommand("npm", ["build"]);
}
} catch (err) {
console.error("Can't build project");
return Promise.reject("Can't build project");
}
try {
let url = await upload(storage, distPath);
url = url.replace("ipfs://", DEFAULT_IPFS_GATEWAY);
return `${url}/index.html`;
} catch (err) {
console.error("Can't upload project");
return Promise.reject("Can't upload project");
}
}
+54
View File
@@ -0,0 +1,54 @@
import { processProject } from "../common/processor";
import { info, logger } from "../core/helpers/logger";
import generateDashboardUrl from "../helpers/generate-dashboard-url";
import { deployApp } from "./app";
import chalk from "chalk";
type DeployOptions = {
name: string;
contractVersion: string;
app: boolean;
path?: string;
distPath?: string;
};
export async function deploy(options: DeployOptions) {
if (options.name) {
const url = generateDashboardUrl(options.name, options.contractVersion);
if (!url) {
logger.error(
chalk.red(
`Could not find a contract named ${options.name} ${
options.contractVersion || ""
}`,
),
);
return;
}
info(`Open this link to deploy your contract: ${chalk.blueBright(url)}`);
return url.toString();
}
if (options.app) {
try {
let url = await deployApp(options.distPath, options.path);
info(`Here is the link to your app: ${chalk.blueBright(url.toString())}`);
return url.toString();
} catch (err) {
logger.error("Failed to deploy app, No compatible project found", err);
return Promise.reject(
"failed to deploy app, no compatible project found",
);
}
}
const url = await processProject(options, "deploy");
info(
`Open this link to deploy your contracts: ${chalk.blueBright(
url.toString(),
)}`,
);
return url.toString();
}
@@ -0,0 +1,103 @@
import { exec } from "child_process";
type PackageManager = "npm" | "yarn" | "pnpm";
interface Installation {
packageManager: PackageManager;
isGlobal: boolean;
}
export async function findPackageInstallation(): Promise<
Installation | undefined
> {
const isLocal = await isInstalledLocally();
if (isLocal) {
const packageManager = await import("detect-package-manager").then(
({ detect }) => {
return detect();
},
);
return { packageManager, isGlobal: false };
}
const isGlobalNpm = await isInstalledGloballyWithNpm();
if (isGlobalNpm) {
return { packageManager: "npm", isGlobal: true };
}
const isGlobalYarn = await isInstalledGloballyWithYarn();
if (isGlobalYarn) {
return { packageManager: "yarn", isGlobal: true };
}
const isGlobalPnpm = await isInstalledGloballyWithPnpm();
if (isGlobalPnpm) {
return { packageManager: "pnpm", isGlobal: true };
}
return undefined;
}
// For LOCAL packages, npm ls picks up things installed by yarn and pnpm too
async function isInstalledLocally(): Promise<boolean> {
const packages = await detectPackages("npm ls --depth=0");
return containsThirdweb(packages || []);
}
// But for GLOBAL packages, we need to use a separate command for each one
async function isInstalledGloballyWithNpm(): Promise<boolean> {
const packages = await detectPackages("npm ls -g --depth=0");
return containsThirdweb(packages || []);
}
async function isInstalledGloballyWithYarn(): Promise<boolean> {
const packages = await detectPackages("yarn --cwd `yarn global dir` list");
return containsThirdweb(packages || []);
}
async function isInstalledGloballyWithPnpm(): Promise<boolean> {
const packages: string[] = await new Promise((resolve) => {
exec(`pnpm list -g --depth=0`, (err, stdout) => {
var pkgs: string[] = [];
pkgs = stdout.split("dependencies:")[1]?.trim().split("\n") || [];
pkgs = pkgs.map((pkg) => pkg.replace(" ", "@"));
resolve(pkgs);
});
});
return containsThirdweb(packages || []);
}
function containsThirdweb(packages: string[]) {
return packages.some((pkg) => pkg.match(/^thirdweb/));
}
async function detectPackages(cmd: string): Promise<string[]> {
return new Promise((resolve) => {
exec(cmd, (err, stdout) => {
var packages: string[] = [];
packages = stdout.split("\n");
// We're one short on '-' to support both yarn and npm
packages = packages.filter(function (item) {
if (item.match(/^├─.+/g) !== null) {
return true;
}
if (item.match(/^└─.+/g) !== null) {
return true;
}
return undefined;
});
packages = packages
.map(function (item) {
if (item.match(/^├─.+/g) !== null) {
return item.replace(/(^├──\s|^├─\s)/g, "");
}
if (item.match(/^└─.+/g) !== null) {
return item.replace(/(^└──\s|^├─\s)/g, "");
}
})
.filter((item) => !!item) as string[];
resolve(packages);
});
});
}
@@ -13,18 +13,18 @@ export default function generateDashboardUrl(
// Pre-built contract
else {
const mapping = {
"signature-drop": "drop/signature-drop",
"nft-drop": "drop/nft-drop",
"edition-drop": "drop/edition-drop",
"nft-collection": "token/nft-collection",
edition: "token/edition",
"token-drop": "drop/token-drop",
token: "token/token",
marketplace: "marketplace/marketplace",
split: "governance/split",
vote: "governance/vote",
pack: "token/pack",
multiwrap: "token/multiwrap",
"signature-drop": "SignatureDrop",
"nft-drop": "DropERC721",
"edition-drop": "DropERC1155",
"nft-collection": "TokenERC721",
edition: "TokenERC1155",
"token-drop": "DropERC20",
token: "TokenERC20",
marketplace: "Marketplace",
split: "Split",
vote: "VoteERC20",
pack: "Pack",
multiwrap: "Multiwrap",
};
const foundMapping = mapping[name as keyof typeof mapping];
@@ -33,6 +33,6 @@ export default function generateDashboardUrl(
return undefined;
}
return `https://thirdweb.com/contracts/new/pre-built/${foundMapping}`;
return `https://thirdweb.com/thirdweb.eth/${foundMapping}`;
}
}
+37 -28
View File
@@ -1,40 +1,51 @@
import { logger } from "../core/helpers/logger";
import { spinner } from "../core/helpers/logger";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import chalk from "chalk";
import { BufferOrStringWithName, ThirdwebStorage } from "@thirdweb-dev/storage";
import fs from "fs";
import path from "path";
function recurseFiles(
uploadPath: string,
basePath: string,
): BufferOrStringWithName[] {
const files = [];
const fileType = fs.lstatSync(uploadPath);
if (fileType.isFile()) {
const fileName = path.relative(basePath, uploadPath);
const fileData = fs.readFileSync(uploadPath);
files.push({ name: fileName, data: fileData });
} else if (fileType.isDirectory()) {
const paths = fs.readdirSync(uploadPath);
paths.forEach((subPath) => {
const fullSubPath = path.join(uploadPath, subPath);
const subFiles = recurseFiles(fullSubPath, basePath);
subFiles.forEach((file) => files.push(file));
});
}
return files;
}
export async function upload(
storage: ThirdwebStorage,
uploadPath: string,
): Promise<string> {
if (!uploadPath) {
return Promise.reject("No path provided");
}
const pathExists = fs.existsSync(uploadPath);
if (!pathExists) {
logger.error(
`Invalid path ${chalk.blueBright(
uploadPath,
)} provided. Please provide a valid path to a file or directory to upload."`,
);
process.exit(1);
return Promise.reject("Invalid path provided");
}
let uri = "";
const fileType = fs.lstatSync(uploadPath);
if (fileType.isDirectory()) {
const subPaths = fs.readdirSync(uploadPath);
const filePaths = subPaths
.map((subPath) => path.join(uploadPath, subPath))
.filter((subPath) => fs.lstatSync(subPath).isFile());
const files = filePaths.map((filePath) => fs.readFileSync(filePath));
const files = recurseFiles(uploadPath, uploadPath);
if (files.length === 0) {
logger.error(
`No files detected in specified directory ${chalk.blueBright(
uploadPath,
)} to upload.`,
);
process.exit(1);
return Promise.reject("No files detected in specified directory");
}
const spin = spinner(
@@ -44,19 +55,17 @@ export async function upload(
spin.succeed("Successfully uploaded directory to IPFS");
uri = uris[0].substring(0, uris[0].lastIndexOf("/"));
} else if (fileType.isFile()) {
const file = fs.readFileSync(uploadPath);
const fileName = path.parse(uploadPath).base;
const fileData = fs.readFileSync(uploadPath);
const file = { name: fileName, data: fileData };
const spin = spinner(
"Uploading file to IPFS. This may take a while depending on file sizes.",
);
uri = await storage.upload(file);
uri = await storage.upload(file, { uploadWithoutDirectory: true });
spin.succeed("Succesfully uploaded file to IPFS.");
} else {
logger.error(
`Path ${chalk.blueBright(
uploadPath,
)} does not point to a valid file or directory. Please provide a valid path to a file or directory to upload`,
);
process.exit(1);
return Promise.reject("Invalid path provided");
}
return uri;
+20
View File
@@ -1,5 +1,25 @@
# @thirdweb-dev/contracts-js
## 1.2.2
### Patch Changes
- [#438](https://github.com/thirdweb-dev/js/pull/438) [`f451da6`](https://github.com/thirdweb-dev/js/commit/f451da6395689a5f89800ee63f34b6175b61f703) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix SigMint detection for OSRF NFT Collection contracts
## 1.2.1
### Patch Changes
- [#376](https://github.com/thirdweb-dev/js/pull/376) [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop with tokens claimed
- [#373](https://github.com/thirdweb-dev/js/pull/373) [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop contract version
## 1.2.0
### Minor Changes
- [#333](https://github.com/thirdweb-dev/js/pull/333) [`aa6d9ed`](https://github.com/thirdweb-dev/js/commit/aa6d9ed75d126d7a0cca9fb8fc389ff94e9d1e14) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Update to contracts package v3.2.0
## 1.1.9
### Patch Changes
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.cjs.js",
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.esm.js"
}
+3 -3
View File
@@ -1,19 +1,19 @@
{
"name": "@thirdweb-dev/contracts-js",
"version": "1.1.9",
"version": "1.2.2",
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
"module": "dist/thirdweb-dev-contracts-js.esm.js",
"license": "Apache-2.0",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
"dependencies": {
"@thirdweb-dev/contracts": "3.1.8-0"
"@thirdweb-dev/contracts": "3.2.8-0"
},
"devDependencies": {
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@preconstruct/cli": "^2.2.1",
"@typechain/ethers-v5": "10.0.0",
"ethers": "^5.7.0",
"ethers": "^5.7.2",
"typechain": "^8.1.0",
"typescript": "^4.7.4"
},
+2 -1
View File
@@ -11,7 +11,8 @@ module.exports = {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-parameter-properties": "error",
"@typescript-eslint/no-unused-vars": "warn",
// making this an error going forward
"@typescript-eslint/no-unused-vars": "error",
// import rules
"import/first": "error",
+1 -1
View File
@@ -6,7 +6,7 @@
"dependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"eslint-config-next": "^12.0.8",
"eslint-config-next": "12.3.1",
"eslint-config-prettier": "^8.3.0",
"eslint-config-turbo": "latest",
"eslint-plugin-react": "^7.28.0"
+6
View File
@@ -0,0 +1,6 @@
{
"presets": [
"@babel/preset-typescript",
["@babel/preset-env", { "targets": "defaults, not ie 11" }]
]
}
+4
View File
@@ -0,0 +1,4 @@
# folders
dist/
# files
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ["thirdweb"],
};
+7
View File
@@ -0,0 +1,7 @@
# @thirdweb-dev/pay
## 0.1.0
### Minor Changes
- [#433](https://github.com/thirdweb-dev/js/pull/433) [`7269268`](https://github.com/thirdweb-dev/js/commit/72692689e9adb41e92038765fd01a36c2b7457e1) Thanks [@jnsdls](https://github.com/jnsdls)! - Initialize Pay Package
+16
View File
@@ -0,0 +1,16 @@
<p align="center">
<br />
<a href="https://thirdweb.com"><img src="https://github.com/thirdweb-dev/js/blob/main/packages/sdk/logo.svg?raw=true" width="200" alt=""/></a>
<br />
</p>
<h1 align="center">thirdweb wallets</h1>
<p align="center">
<!-- <a href="https://www.npmjs.com/package/@thirdweb-dev/sdk"><img src="https://img.shields.io/npm/v/@thirdweb-dev/sdk?color=red&label=npm&logo=npm" alt="npm version"/></a> -->
<!-- <a href="https://github.com/thirdweb-dev/js/actions/workflows/CI.yml"><img alt="Build Status" src="https://github.com/thirdweb-dev/js/actions/workflows/CI.yml/badge.svg"/></a> -->
<!-- <a href="https://discord.gg/thirdweb"><img alt="Join our Discord!" src="https://img.shields.io/discord/834227967404146718.svg?color=7289da&label=discord&logo=discord&style=flat"/></a> -->
</p>
<!-- <p align="center"><strong>Best in class Web3 SDK for Browser, Node and Mobile apps</strong></p> -->
<br />
### todo
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-pay-integrations-coinbase.cjs.js",
"module": "dist/thirdweb-dev-pay-integrations-coinbase.esm.js"
}
+53
View File
@@ -0,0 +1,53 @@
{
"name": "@thirdweb-dev/pay",
"version": "0.1.0",
"main": "dist/thirdweb-dev-pay.cjs.js",
"module": "dist/thirdweb-dev-pay.esm.js",
"exports": {
".": {
"module": "./dist/thirdweb-dev-pay.esm.js",
"default": "./dist/thirdweb-dev-pay.cjs.js"
},
"./integrations/coinbase": {
"module": "./integrations/coinbase/dist/thirdweb-dev-pay-integrations-coinbase.esm.js",
"default": "./integrations/coinbase/dist/thirdweb-dev-pay-integrations-coinbase.cjs.js"
},
"./package.json": "./package.json"
},
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/pay",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/thirdweb-dev/js/issues"
},
"author": "thirdweb eng <[email protected]>",
"files": [
"dist/",
"integrations/"
],
"preconstruct": {
"entrypoints": [
"index.ts",
"integrations/**"
],
"___experimentalFlags_WILL_CHANGE_IN_PATCH": {
"exports": true
},
"exports": true
},
"sideEffects": false,
"dependencies": {
"@coinbase/cbpay-js": "^1.6.0"
},
"devDependencies": {
"@preconstruct/cli": "^2.2.1",
"typescript": "^4.7.4"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
"lint": "eslint src/",
"fix": "eslint src/ --fix",
"clean": "rm -rf dist/",
"build": "tsc && preconstruct build",
"push": "yalc push"
}
}
+1
View File
@@ -0,0 +1 @@
export * from "./integrations/coinbase";
@@ -0,0 +1,62 @@
import { initOnRamp, InitOnRampParams } from "@coinbase/cbpay-js";
interface CoinbasePayOptions extends Pick<InitOnRampParams, "appId"> {}
const CHAIN_ID_MAP = {
[-1]: "solana",
1: "ethereum",
69: "optimism",
137: "polygon",
} as const;
export type FundWalletOptions = {
address: string;
chainId: keyof typeof CHAIN_ID_MAP;
assets?: string[];
};
export class CoinbasePayIntegration {
#appId: string;
constructor(options: CoinbasePayOptions) {
this.#appId = options.appId;
}
async fundWallet(opts: FundWalletOptions): Promise<void> {
const { address, chainId, assets } = opts;
return new Promise((res, rej) => {
initOnRamp(
{
appId: this.#appId,
widgetParameters: {
destinationWallets: [
{
address,
assets,
supportedNetworks: [CHAIN_ID_MAP[chainId]],
},
],
},
experienceLoggedIn: "embedded",
experienceLoggedOut: "popup",
closeOnExit: true,
onSuccess: () => {
res();
},
onExit(error) {
if (error) {
return rej(error);
}
return res();
},
},
(err, instance) => {
if (err || !instance) {
return rej(err);
}
instance.open();
},
);
});
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"extends": "@thirdweb-dev/tsconfig/sdk.json",
"include": ["src", "types"],
"exclude": ["dist", "build", "node_modules"]
}
+192
View File
@@ -1,5 +1,197 @@
# @thirdweb-dev/react
## 3.6.7
### Patch Changes
- [#448](https://github.com/thirdweb-dev/js/pull/448) [`7a37e56`](https://github.com/thirdweb-dev/js/commit/7a37e564fd5d5a9df84c8da44ecaf6c42f67a0e2) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - allow `useContract` to fail faster to enable the import case
## 3.6.6
### Patch Changes
- [#443](https://github.com/thirdweb-dev/js/pull/443) [`8c6cdaa`](https://github.com/thirdweb-dev/js/commit/8c6cdaa2887fb2cc40d3ee6991233d195d103805) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix magic link connector not connecting to the right chain
## 3.6.5
## 3.6.4
### Patch Changes
- [#425](https://github.com/thirdweb-dev/js/pull/425) [`f545a67`](https://github.com/thirdweb-dev/js/commit/f545a67e9fb597d27bb39ca515d24d306fbb121a) Thanks [@adam-maj](https://github.com/adam-maj)! - Add sameSite none and include credentials
- [#420](https://github.com/thirdweb-dev/js/pull/420) [`639e535`](https://github.com/thirdweb-dev/js/commit/639e535ed55280ad9d081001aab3f5af72bb3e45) Thanks [@jnsdls](https://github.com/jnsdls)! - update deps
## 3.6.3
## 3.6.2
### Patch Changes
- [#405](https://github.com/thirdweb-dev/js/pull/405) [`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add updateAll param to creators and royalty update hooks for Solana
## 3.6.1
### Patch Changes
- [#392](https://github.com/thirdweb-dev/js/pull/392) [`846022e`](https://github.com/thirdweb-dev/js/commit/846022e2cfb12b846aae029b85899fb72fd2c9ad) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix unlimited price for useActiveClaimConditionForWallet
- [#388](https://github.com/thirdweb-dev/js/pull/388) [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510) Thanks [@adam-maj](https://github.com/adam-maj)! - Add support for total supply and pagination on get all
## 3.6.0
### Patch Changes
- [#386](https://github.com/thirdweb-dev/js/pull/386) [`612bcdd`](https://github.com/thirdweb-dev/js/commit/612bcdd16fc242d8b04bc70d609e44b0df47ed3f) Thanks [@jnsdls](https://github.com/jnsdls)! - [Gnosis Connector] - switch to safe.global hostname & add support for bsc and optimism chains
- [#364](https://github.com/thirdweb-dev/js/pull/364) [`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Add experimental `useActiveClaimConditionForWallet()` hook
## 3.5.2
### Patch Changes
- [#369](https://github.com/thirdweb-dev/js/pull/369) [`2d3fca5`](https://github.com/thirdweb-dev/js/commit/2d3fca52373046c88392139922e9c9da79f9a2d4) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useClaimerProofs hook
- [#378](https://github.com/thirdweb-dev/js/pull/378) [`32d91ef`](https://github.com/thirdweb-dev/js/commit/32d91ef709c8fb92a903e52c65b27538a80ea4eb) Thanks [@mykcryptodev](https://github.com/mykcryptodev)! - round borders for buttons and menus on safari
- [#377](https://github.com/thirdweb-dev/js/pull/377) [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0) Thanks [@adam-maj](https://github.com/adam-maj)! - Add event filters
## 3.5.1
## 3.5.0
## 3.4.5
## 3.4.4
### Patch Changes
- [#356](https://github.com/thirdweb-dev/js/pull/356) [`cc4613b`](https://github.com/thirdweb-dev/js/commit/cc4613b5fd69840f4f9cfd0ac1c4e6743e62fe52) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add Pack and Multiwrap as NFTContract types
## 3.4.3
### Patch Changes
- [#353](https://github.com/thirdweb-dev/js/pull/353) [`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useUpdateCreators hook, fix CreatorInput schema
## 3.4.2
### Patch Changes
- [#348](https://github.com/thirdweb-dev/js/pull/348) [`7d9a4c6`](https://github.com/thirdweb-dev/js/commit/7d9a4c6abcad1b4f43e431ce7b0b38db9016ea9a) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - [SOL] - add `useUpdateRoyaltySettings()` hook
[SOL] - change `useRoyalty()` hook -> `useRoyaltySettings()` for consistency
- [#352](https://github.com/thirdweb-dev/js/pull/352) [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - expose useExecuteAuctionSale and useAcceptDirectListingOffer
- [#351](https://github.com/thirdweb-dev/js/pull/351) [`aabbb14`](https://github.com/thirdweb-dev/js/commit/aabbb149e81d6824015a4797b2b6c929ca359545) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - fix wallet connection during dev (hot reload)
## 3.4.1
### Patch Changes
- [#343](https://github.com/thirdweb-dev/js/pull/343) [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose new useOffers and useMakeOffer hooks
## 3.4.0
### Minor Changes
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - Gnosis Safe and Magic Link connectors are no longer included in the default export. They are now available as named exports instead.
## Gnosis Safe
### Connector
```diff
- import { GnosisSafeConnector } from "@thirdweb-dev/react";
+ import { GnosisSafeConnector } from "@thirdweb-dev/react/evm/connectors/gnosis-safe";
```
### Hook
```diff
- import { useGnosis } from "@thirdweb-dev/react";
+ import { useGnosis } from "@thirdweb-dev/react/evm/connectors/gnosis-safe";
```
## Magic Link
### Connector
```diff
- import { MagicLink } from "@thirdweb-dev/react";
+ import { MagicConnector } from "@thirdweb-dev/react/evm/connectors/magic";
```
### Hook
```diff
- import { useMagic } from "@thirdweb-dev/react";
+ import { useMagic } from "@thirdweb-dev/react/evm/connectors/magic";
```
### Patch Changes
- [#339](https://github.com/thirdweb-dev/js/pull/339) [`b03a902`](https://github.com/thirdweb-dev/js/commit/b03a9021451b79f802f682f66e5ae8e9355d7e6f) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix docs for some functions
## 3.3.1
## 3.3.0
## 3.2.6
### Patch Changes
- [#316](https://github.com/thirdweb-dev/js/pull/316) [`6ae5266`](https://github.com/thirdweb-dev/js/commit/6ae52664e5865564cd4fc2e00e3120675b9e0ca3) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix SIWE when using an external signer
- [#310](https://github.com/thirdweb-dev/js/pull/310) [`9727502`](https://github.com/thirdweb-dev/js/commit/9727502eb30ac139382b7c7c8e8fc0967cbfbcf1) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - [SOL] - add useMintNFTSupply hook in react and accomodate inputs for it in SDK
- [#319](https://github.com/thirdweb-dev/js/pull/319) [`2f8ec89`](https://github.com/thirdweb-dev/js/commit/2f8ec89c4c83ae577092c840c198e6fcfb114e69) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose total claimed and unclaimed supply for erc721 drop contracts
- [#318](https://github.com/thirdweb-dev/js/pull/318) [`bb1b4e6`](https://github.com/thirdweb-dev/js/commit/bb1b4e6ac39d98cc68b8e31e659cd68be3a5b967) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useMinimumNextBid hook and change invariant for other marketplace hooks
## 3.2.5
## 3.2.4
### Patch Changes
- [#301](https://github.com/thirdweb-dev/js/pull/301) [`86f0cef`](https://github.com/thirdweb-dev/js/commit/86f0ceff46f72df8ebd81f843e3c66a245f23992) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Remove useAddress hook for now
## 3.2.3
### Patch Changes
- [#299](https://github.com/thirdweb-dev/js/pull/299) [`b1218cb`](https://github.com/thirdweb-dev/js/commit/b1218cbd7d97ca7949d94a7e4ab93fef4ffbacd5) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Recreate SDK on wallet changes for hook propagation
## 3.2.2
### Patch Changes
- [#289](https://github.com/thirdweb-dev/js/pull/289) [`521a49c`](https://github.com/thirdweb-dev/js/commit/521a49c6ec6a73068adcfbc1d94d2f3f17afae86) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Standarize useClaimNFT to evm
- [#274](https://github.com/thirdweb-dev/js/pull/274) [`ad06c5b`](https://github.com/thirdweb-dev/js/commit/ad06c5b28902422f9b416d65255c64c937a5e046) Thanks [@adam-maj](https://github.com/adam-maj)! - Add solana auth support and plugins for react and auth package
- [#269](https://github.com/thirdweb-dev/js/pull/269) [`b2cadf1`](https://github.com/thirdweb-dev/js/commit/b2cadf164cfe9fb27081df7530356baf70ec2b3a) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - remove deprecated chains from support
- [#272](https://github.com/thirdweb-dev/js/pull/272) [`2bdf198`](https://github.com/thirdweb-dev/js/commit/2bdf1984cb97121c447cffd27aa6a5f4f92679b3) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add claim conditions hook for Solana
- [#291](https://github.com/thirdweb-dev/js/pull/291) [`86f6083`](https://github.com/thirdweb-dev/js/commit/86f608390a7848cda82c0f7e8913ca60f7d3901f) Thanks [@jnsdls](https://github.com/jnsdls)! - [SOL] - expose `.program` on `useProgram()` return type to mirror `.contract` on EVM
- [#292](https://github.com/thirdweb-dev/js/pull/292) [`492a818`](https://github.com/thirdweb-dev/js/commit/492a818079aff67c7f88bc43666c87c3714cc957) Thanks [@jnsdls](https://github.com/jnsdls)! - [SOL] expose `useAddress()` hook that returns the connected wallet address in base58
- [#290](https://github.com/thirdweb-dev/js/pull/290) [`8096c78`](https://github.com/thirdweb-dev/js/commit/8096c78b466a7f5f9c2aac6e2c56a06f9d3a25d6) Thanks [@jnsdls](https://github.com/jnsdls)! - [SOL] - `useClaimNFT()` allow claiming to connected wallet without passing address explicitly
[EVM] - `useClaimNFT()` allow claiming to connected wallet without passing address explicitly
- [#298](https://github.com/thirdweb-dev/js/pull/298) [`e8c25ed`](https://github.com/thirdweb-dev/js/commit/e8c25ed0f28d566203d70bf59a8908e59216334a) Thanks [@jnsdls](https://github.com/jnsdls)! - [SOL] - fix useBalance
- [#263](https://github.com/thirdweb-dev/js/pull/263) [`d6bb61b`](https://github.com/thirdweb-dev/js/commit/d6bb61b7fac759fff7d6293edd46f693f5a7889c) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - add chainId getter on contracts
- [#266](https://github.com/thirdweb-dev/js/pull/266) [`3b7d10e`](https://github.com/thirdweb-dev/js/commit/3b7d10ed93d8e3b698e9f905c93ba79863b35325) Thanks [@adam-maj](https://github.com/adam-maj)! - Add storage hooks to react
- [#282](https://github.com/thirdweb-dev/js/pull/282) [`1f41adb`](https://github.com/thirdweb-dev/js/commit/1f41adbd2ccfbc367757620e0842ef32bc783a08) Thanks [@jarrodwatts](https://github.com/jarrodwatts)! - Fix useActiveClaimCondition invariant failing for token ID 0
- [#296](https://github.com/thirdweb-dev/js/pull/296) [`cf88795`](https://github.com/thirdweb-dev/js/commit/cf88795376d3110f9d3aa839928d22276904b15a) Thanks [@jnsdls](https://github.com/jnsdls)! - [SOL] - add `useBalance` hook
## 3.2.1
### Patch Changes
+2 -2
View File
@@ -26,11 +26,11 @@ The `useContractCall` hook to call a smart contract function has been renamed to
### Prebuilt Contract Hooks
Hooks to connect to prebuilt contracts such as `useNFTDrop` and `useMarketplace` are now deprecated in favour of using the generic `useContract` hook:
Hooks to connect to prebuilt contracts such as `useNFTDrop` and `useMarketplace` are now deprecated in favour of using the generic `useContract` hook followed by the contract type:
```diff
- const contract = useNFTDrop("0x...")
+ const { contract } = useContract("0x...")
+ const { contract } = useContract("0x...", "nft-drop")
```
You can currently still continue to use the prebuilt hooks, however they provide a warning in the console informing you of their deprecation. We will likely remove these hooks in a future version of the SDK.
+6 -6
View File
@@ -71,7 +71,7 @@ Below are examples of where to set this up in your application:
### Connect to a User's Wallet
Now the provider is set up, we can use all of the hooks and UI components available in the SDK, such as the [ConnectWallet](https://portal.thirdweb.com/sdk/ui-components/connectwalletbutton) component.
Now the provider is set up, we can use all of the hooks and UI components available in the SDK, such as the [ConnectWallet](https://portal.thirdweb.com/ui-components/connectwalletbutton) component.
Once the user has connected their wallet, all the calls we make to interact with contracts using the SDK will be on behalf of the user.
@@ -143,7 +143,7 @@ Each [extension](https://portal.thirdweb.com/extensions) you implement in your s
These hooks make it easy to interact with your smart contracts by implementing the complex logic for you under the hood.
For example, if your smart contract implements [ERC721Supply](https://portal.thirdweb.com/extensions/erc721supply#unlocked-features), you unlock the ability to [view all NFTs](https://portal.thirdweb.com/sdk/interacting-with-contracts/erc721supply#get-all-minted-nfts) on that contract using the SDK; which fetches all of your NFT metadata and the current owner of each NFT in parallel. In the React SDK, that is available using `useNFTs`:
For example, if your smart contract implements [ERC721Supply](https://portal.thirdweb.com/contractkit/interfaces/erc721supply#unlocked-features), you unlock the ability to [view all NFTs](https://portal.thirdweb.com/sdk/interacting-with-contracts/erc721supply#get-all-minted-nfts) on that contract using the SDK; which fetches all of your NFT metadata and the current owner of each NFT in parallel. In the React SDK, that is available using `useNFTs`:
```jsx
import { useContract, useNFTs } from "@thirdweb-dev/react";
@@ -154,7 +154,7 @@ export default function Home() {
}
```
If we want to mint an NFT and our contract implements [ERC721Mintable](https://portal.thirdweb.com/extensions/erc721mintable#unlocked-features), we can use the [`useMintNFT`](https://portal.thirdweb.com/sdk/interacting-with-contracts/erc721mintable) hook to mint an NFT from the connected wallet; handling all of the logic of uploading and pinning the metadata to IPFS for us behind the scenes.
If we want to mint an NFT and our contract implements [ERC721Mintable](https://portal.thirdweb.com/contractkit/interfaces/erc721mintable#unlocked-features), we can use the [`useMintNFT`](https://portal.thirdweb.com/sdk/interacting-with-contracts/erc721mintable) hook to mint an NFT from the connected wallet; handling all of the logic of uploading and pinning the metadata to IPFS for us behind the scenes.
```jsx
import { useContract, useNFTs, useMintNFT } from "@thirdweb-dev/react";
@@ -172,7 +172,7 @@ export default function Home() {
The SDK provides many UI components to help you build your application.
For example, we can render each of the NFTs using the [`NFT Media Renderer`](https://portal.thirdweb.com/sdk/ui-components/nft-renderer)
For example, we can render each of the NFTs using the [`NFT Media Renderer`](https://portal.thirdweb.com/ui-components/nft-renderer)
component, making use of the loading state from `useNFTs`:
```jsx title="pages/index.jsx"
@@ -191,7 +191,7 @@ export default function Home() {
<div>
{nfts.map((nft) => (
<ThirdwebNftMedia
key={nft.tokenId}
key={nft.metadata.id}
metadata={nft.metadata}
height={200}
/>
@@ -203,7 +203,7 @@ export default function Home() {
}
```
The [`Web3Button`](https://portal.thirdweb.com/sdk/ui-components/web3button) component ensures the user has connected their wallet and is currently configured to the same network as your smart contract before calling the function. It also has access to the `contract` directly, allowing you to perform any action on your smart contract when the button is clicked.
The [`Web3Button`](https://portal.thirdweb.com/ui-components/web3button) component ensures the user has connected their wallet and is currently configured to the same network as your smart contract before calling the function. It also has access to the `contract` directly, allowing you to perform any action on your smart contract when the button is clicked.
For example, we can mint an NFT like so:
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-react-evm-connectors-gnosis-safe.cjs.js",
"module": "dist/thirdweb-dev-react-evm-connectors-gnosis-safe.esm.js"
}
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-react-evm-connectors-magic.cjs.js",
"module": "dist/thirdweb-dev-react-evm-connectors-magic.esm.js"
}
+21 -19
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.2.1",
"version": "3.6.7",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -20,6 +20,14 @@
"module": "./solana/dist/thirdweb-dev-react-solana.esm.js",
"default": "./solana/dist/thirdweb-dev-react-solana.cjs.js"
},
"./evm/connectors/magic": {
"module": "./evm/connectors/magic/dist/thirdweb-dev-react-evm-connectors-magic.esm.js",
"default": "./evm/connectors/magic/dist/thirdweb-dev-react-evm-connectors-magic.cjs.js"
},
"./evm/connectors/gnosis-safe": {
"module": "./evm/connectors/gnosis-safe/dist/thirdweb-dev-react-evm-connectors-gnosis-safe.esm.js",
"default": "./evm/connectors/gnosis-safe/dist/thirdweb-dev-react-evm-connectors-gnosis-safe.cjs.js"
},
"./package.json": "./package.json"
},
"files": [
@@ -31,7 +39,8 @@
"entrypoints": [
"index.ts",
"solana/index.ts",
"evm/index.ts"
"evm/index.ts",
"evm/connectors/**.ts"
],
"___experimentalFlags_WILL_CHANGE_IN_PATCH": {
"exports": true
@@ -49,13 +58,11 @@
"generate-docs:solana": "api-extractor run --local --config ./config/api-extractor-solana.json && api-documenter markdown -i ./temp -o ./docs/solana && rm -rf ./temp-solana && mv ./temp ./temp-solana",
"generate-snippets": "node ./scripts/generate-snippets-evm.mjs && node ./scripts/generate-snippets-solana.mjs && node ./scripts/generate-feature-snippets-evm.mjs",
"build": "tsc && preconstruct build",
"e2e": "yarn test-ct",
"test-ct": "playwright test -c playwright-ct.config.ts",
"push": "yalc push"
},
"sideEffects:": false,
"devDependencies": {
"@babel/core": "^7.18.10",
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.18.10",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
@@ -63,15 +70,12 @@
"@microsoft/api-documenter": "^7.19.4",
"@microsoft/api-extractor": "^7.29.2",
"@microsoft/tsdoc": "^0.14.1",
"@playwright/experimental-ct-react": "1.25.1",
"@playwright/test": "1.25.1",
"@preconstruct/cli": "^2.2.1",
"@solana/wallet-adapter-base": "^0.9.17",
"@solana/wallet-adapter-react": "^0.15.19",
"@solana/wallet-adapter-wallets": "^0.19.0",
"@solana/web3.js": "^1.63.0",
"@solana/web3.js": "^1.62.0",
"@thirdweb-dev/sdk": "*",
"@thirdweb-dev/solana": "*",
"@types/color": "^3.0.3",
"@types/mime": "^3.0.1",
"@types/react": "^18.0.5",
@@ -84,7 +88,7 @@
"eslint-plugin-inclusive-language": "^2.2.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"ethers": "^5.7.1",
"ethers": "^5.7.2",
"prettier": "^2.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -93,13 +97,14 @@
"dependencies": {
"@emotion/react": "^11.10.0",
"@emotion/styled": "^11.10.0",
"@gnosis.pm/safe-core-sdk": "2.1.0",
"@gnosis.pm/safe-ethers-adapters": "0.1.0-alpha.9",
"@gnosis.pm/safe-ethers-lib": "1.1.0",
"@gnosis.pm/safe-core-sdk": "^3.1.1",
"@gnosis.pm/safe-ethers-adapters": "0.1.0-alpha.11",
"@gnosis.pm/safe-ethers-lib": "^1.6.1",
"@react-icons/all-files": "^4.1.0",
"@solana/wallet-adapter-phantom": "^0.9.17",
"@tanstack/react-query": "^4.0.10",
"@zag-js/menu": "0.1.14",
"@zag-js/react": "0.1.16",
"@zag-js/menu": "^0.1.16",
"@zag-js/react": "^0.1.18",
"buffer": "^6.0.3",
"color": "^4.2.3",
"copy-to-clipboard": "^3.3.2",
@@ -114,7 +119,7 @@
"@solana/wallet-adapter-base": "^0.9.17",
"@solana/wallet-adapter-react": "^0.15.19",
"@solana/wallet-adapter-wallets": "^0.19.0",
"@solana/web3.js": "^1.63.0",
"@solana/web3.js": "^1.62.0",
"@thirdweb-dev/sdk": "*",
"ethers": ">=5.5.1",
"react": ">=18.0.0",
@@ -136,9 +141,6 @@
},
"@solana/web3.js": {
"optional": true
},
"@thirdweb-dev/solana": {
"optional": true
}
}
}
-57
View File
@@ -1,57 +0,0 @@
import type { PlaywrightTestConfig } from "@playwright/experimental-ct-react";
import { devices } from "@playwright/experimental-ct-react";
/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: "./",
/* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
snapshotDir: "./__snapshots__",
/* Maximum time one test can run for. */
timeout: 10 * 1000,
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
// workers: process.env.CI ? 1 : undefined,
// we can use parallel tests because we have more cores now
workers: undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
/* Port to use for Playwright component endpoint. */
ctPort: 3100,
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
},
},
{
name: "firefox",
use: {
...devices["Desktop Firefox"],
},
},
{
name: "webkit",
use: {
...devices["Desktop Safari"],
},
},
],
};
export default config;
-4
View File
@@ -1,4 +0,0 @@
// Import styles, initialize component theme here.
// import '../src/common.css';
export {};
@@ -70,7 +70,7 @@ function parseExampleTag(docComment) {
return examples;
}
const baseDocUrl = "https://portal.thirdweb.com/react/react.";
const baseDocUrl = "https://portal.thirdweb.com/react/solana/react.";
const extractReferenceLink = (m, kind, contractName) => {
if (kind === "Property") {
@@ -1,6 +1,6 @@
import { RequiredParam } from "../types/shared";
import { QueryKey } from "@tanstack/react-query";
import type { ChainId } from "@thirdweb-dev/sdk";
import { RequiredParam } from "./required-param";
import type { QueryKey } from "@tanstack/react-query";
import type { ValidContractInstance } from "@thirdweb-dev/sdk";
import type {
Network,
NFTCollection,
@@ -13,7 +13,7 @@ const TW_QUERY_KEY_PREFIX = "__tw__";
// marker to make sure the query will not get stored in local storage by a query persister
const NEVER_PERSIST_QUERY_POSTFIX = { persist: false } as const;
function ensureTWPrefix<TKey extends QueryKey>(key: TKey) {
export function ensureTWPrefix<TKey extends QueryKey>(key: TKey) {
if (key[0] === TW_QUERY_KEY_PREFIX) {
return key as unknown as Readonly<[typeof TW_QUERY_KEY_PREFIX, ...TKey]>;
}
@@ -37,11 +37,23 @@ export function createEVMQueryKey<TKey extends QueryKey>(key: TKey) {
}
export function createEVMQueryKeyWithChain<TKey extends QueryKey>(
key: TKey,
chainId: RequiredParam<ChainId>,
chainId: RequiredParam<number>,
) {
return ensureTWPrefix([chainId, ...key] as const);
}
export function createEVMContractQueryKey<TKey extends QueryKey>(
contract: RequiredParam<ValidContractInstance>,
key: TKey = [] as unknown as TKey,
) {
const chainId = contract?.chainId;
const address = contract?.getAddress();
return createEVMQueryKeyWithChain(
["contract", address, ...key] as const,
chainId,
);
}
// SOL
export function createSOLQueryKey<TKey extends QueryKey>(key: TKey) {
@@ -0,0 +1,15 @@
import invariant from "tiny-invariant";
/**
* Makes a parameter required to be passed, but still allowes it to be null or undefined.
*
* @beta
*/
export type RequiredParam<T> = T | null | undefined;
export function requiredParamInvariant<TValue>(
condition: RequiredParam<TValue>,
message?: string,
): asserts condition {
invariant(condition !== null || condition !== undefined, message);
}
-6
View File
@@ -1,6 +0,0 @@
/**
* Makes a parameter required to be passed, but still allowes it to be null or undefined.
*
* @beta
*/
export type RequiredParam<T> = T | null | undefined;
@@ -1,15 +0,0 @@
import { ConnectWallet } from ".";
import { ThirdwebProvider } from "../../providers/full";
import { test, expect } from "@playwright/experimental-ct-react";
test.use({ viewport: { width: 500, height: 500 } });
test("should render the connect wallet button", async ({ mount }) => {
const component = await mount(
<ThirdwebProvider desiredChainId={1}>
<ConnectWallet />
</ThirdwebProvider>,
);
await expect(component).toContainText("Connect Wallet");
});
@@ -14,19 +14,19 @@ export const SupportedNetworkSelect: React.FC<SupportedNetworkSelectProps> = ({
const deprecatedNetworks = useMemo(() => {
return SUPPORTED_CHAIN_IDS.map((supportedChain) => {
return getChainFromChainId(supportedChain);
}).filter((n) => !!n.deprecated);
});
}, []);
const testnets = useMemo(() => {
return SUPPORTED_CHAIN_IDS.map((supportedChain) => {
return getChainFromChainId(supportedChain);
}).filter((n) => n.testnet && !n.deprecated);
});
}, []);
const mainnets = useMemo(() => {
return SUPPORTED_CHAIN_IDS.map((supportedChain) => {
return getChainFromChainId(supportedChain);
}).filter((n) => !n.testnet && !n.deprecated);
});
}, []);
return (
<Select {...selectProps}>
@@ -76,10 +76,8 @@ const chainIdToCurrencyMap: Record<
> = {
[ChainId.Mainnet]: "ethereum",
[ChainId.Goerli]: "ethereum",
[ChainId.Rinkeby]: "ethereum",
[ChainId.Arbitrum]: "arbitrum",
[ChainId.ArbitrumRinkeby]: "arbitrum",
[ChainId.ArbitrumGoerli]: "arbitrum",
[ChainId.Avalanche]: "avalanche",
@@ -89,7 +87,6 @@ const chainIdToCurrencyMap: Record<
[ChainId.FantomTestnet]: "fantom",
[ChainId.Optimism]: "optimism",
[ChainId.OptimismKovan]: "optimism",
[ChainId.OptimismGoerli]: "optimism",
[ChainId.Polygon]: "polygon",
@@ -147,7 +144,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
},
connect,
] = useConnect();
const disconnect = useDisconnect({ reconnectAfterGnosis: false });
const disconnect = useDisconnect({ reconnectPrevious: false });
const supportedConnectors = connectors.filter((c) =>
SUPPORTED_CONNECTORS.includes(c.id as typeof SUPPORTED_CONNECTORS[number]),
@@ -13,12 +13,14 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
}
/**
* This component can be used to render NFTs from the thirdweb SDK.
* Props: {@link ThirdwebNftMediaProps}
*
* @example
* ```jsx
* import { ThirdwebNftMedia, useNFTCollection, useNFT } from "@thirdweb-dev/react";
* import { ThirdwebNftMedia, useContract, useNFT } from "@thirdweb-dev/react";
* export default function NFTCollectionRender() {
* const contract = useNFTCollection(<your-contract-address>);
* const { contract } = useContract(<your-contract-address>);
* const { data: nft, isLoading } = useNFT(contract, 0);
*
* return (
@@ -32,11 +34,6 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
* );
* }
* ```
*
* Use this to get the primary sales recipient of your {@link SmartContract}
* @param contract - an instance of a {@link SmartContract}
* @returns the wallet address of the primary sales recipient
* @beta
*/
export const ThirdwebNftMedia = React.forwardRef<
HTMLMediaElement,
@@ -1,16 +0,0 @@
import { Web3Button } from ".";
import { ThirdwebProvider } from "../../providers/full";
import { test, expect } from "@playwright/experimental-ct-react";
test.use({ viewport: { width: 500, height: 500 } });
test("should render the connect wallet button", async ({ mount }) => {
const component = await mount(
<ThirdwebProvider desiredChainId={1}>
<Web3Button contractAddress="0x123" action={() => undefined}>
Do the thing
</Web3Button>
</ThirdwebProvider>,
);
await expect(component).toContainText("Connect Wallet");
});

Some files were not shown because too many files have changed in this diff Show More