-
Notifications
You must be signed in to change notification settings - Fork 58
add sdk storage interface #394
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left an initial batch of reviews
constructor( | ||
gatewayUrl: string = DEFAULT_IPFS_GATEWAY, | ||
uploader: IStorageUpload = new IpfsUploader(), | ||
) { | ||
this.gatewayUrl = `${gatewayUrl.replace(/\/$/, "")}/`; | ||
this.uploader = uploader; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if we could not have 2 params here, can the gatewayUrl be part of the IpfsUploader()
interface and then we just pass that in here by itself? this api just doesn't feel clean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are separate concerns though - the uploader is just for uploading files, whereas the gateway is for file download - these are two separate things may want to specify (ie I want filebase upload + pinata gateway download) - it doesn't seem right for gateway to be on the uploader considering its used in the main IpfsStorage interface.
Also fwiw, this is an internal interface - the public storage interface is now different (src/core/classes/storage.ts
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so nice to have upload progress now 🔥 xhr FTW
src/core/classes/storage.ts
Outdated
return this.storage.get(hash); | ||
} | ||
|
||
public async upload(data: FileOrBuffer[] | JsonObject[]): Promise<string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm can this be (FileOrBuffer | JsonObject)[] | (FileOrBuffer | JsonObject)
so i can pass a single thing if i want to?
also the return type should give me both the base uri and the individual uris i think right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a couple of nits - let's merge an iterate
src/constants/urls.ts
Outdated
/** | ||
* @internal | ||
*/ | ||
export const TW_FILEBASE_SERVER_URL = "http://localhost:3002"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this used for?
src/core/classes/storage.ts
Outdated
*/ | ||
public async upload( | ||
data: FileOrBuffer[] | JsonObject[] | FileOrBuffer | JsonObject, | ||
): Promise<string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would still be nice to also return the individual uris here, or at least something like the total number of files uploaded?
This pull request introduces 1 alert when merging 27fa534 into 79d199d - view on LGTM.com new alerts:
|
src/core/classes/ipfs-storage.ts
Outdated
/** | ||
* IPFS Storage implementation, accepts custom IPFS gateways | ||
* @public | ||
*/ | ||
export class IpfsStorage implements IStorage { | ||
private gatewayUrl: string; | ||
private failedUrls: string[] = []; | ||
public uploader: IStorageUpload; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't need to be public right?
src/core/interfaces/IStorage.ts
Outdated
* @returns - The one time use token that can be passed to the Pinata API. | ||
*/ | ||
getUploadToken(contractAddress: string): Promise<string>; | ||
uploader: IStorageUpload; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also doesn't need to be in the interface, it's an implementation detail
src/core/storage/ipfs-uploader.ts
Outdated
|
||
data.append("pinataMetadata", JSON.stringify(metadata)); | ||
|
||
if (typeof window === "undefined") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
man i would reaaaaally love this for the thirdweb CLI - what would it take to make it happen?
This pull request introduces 1 alert when merging a122f98 into 79d199d - view on LGTM.com new alerts:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like there was a bad merge in the ThirdwebSDK constructor!
src/core/sdk.ts
Outdated
this.storage = storage; | ||
this.deployer = new ContractDeployer(rpc, options, storage); | ||
this.wallet = new UserWallet(rpc, options); | ||
super(network, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happened to my getProviderForNetwork
here?
package.json
Outdated
@@ -91,6 +92,7 @@ | |||
"form-data": "^4.0.0", | |||
"keccak256": "^1.0.6", | |||
"merkletreejs": "^0.2.24", | |||
"request": "^2.88.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're not using this are we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bunch of minor things + still an issue in ThirdwebSDK
post merge
package.json
Outdated
@@ -52,6 +52,7 @@ | |||
"@types/lodash.isequal": "^4.5.5", | |||
"@types/mocha": "^9.1.1", | |||
"@types/node": "^17.0.0", | |||
"@types/request": "^2.48.8", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adam-maj what about this one? don't see it being used either?
src/core/classes/storage.ts
Outdated
} | ||
|
||
/** | ||
* Upload any data to an IPFS directory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add here that we handle pinning for you?
src/core/classes/storage.ts
Outdated
* fs.readFileSync("file2.png"), | ||
* fs.readFileSync("file3.png"), | ||
* ] | ||
* const uri = await sdk.storage.upload(files); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be interesting to also show an example of uploading a single json object and maybe passing the upload progress option (with a disclaimer) to show the different capabilities.
Would also add a comment on what the expected response looks like : ipfs://hash/0, ipfs://hash/1...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also add an example uploading just regular JSON, and one example with a progress upload callback?
src/core/storage/ipfs-uploader.ts
Outdated
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
globalThis.FormData = require("form-data"); | ||
} | ||
export class IpfsUploader implements IStorageUpload { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets mark this class as @internal for now. It's not added to the index.ts of the folder is it?
src/core/classes/storage.ts
Outdated
import { UploadProgressEvent } from "../../types/events"; | ||
import { IStorage } from "../interfaces/IStorage"; | ||
|
||
interface StorageUpload { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one can be exported though - add it to the index.ts of the folder, and add a top level doc with @public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, should this interface be moved to IStorageUpload
? also feels like it could be a type instead of an interface, but nbd
src/core/interfaces/IStorage.ts
Outdated
/** | ||
* @internal | ||
*/ | ||
export interface UploadBatchResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the difference between this interface and StorageUpload
defined above? looks the same?
fileNames: string[]; | ||
} | ||
|
||
export interface IStorageUpload { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be @internal
src/core/sdk.ts
Outdated
@@ -133,16 +134,22 @@ export class ThirdwebSDK extends RPCConnectionHandler { | |||
*/ | |||
public wallet: UserWallet; | |||
|
|||
/** | |||
* Upload and download files from IPFS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add 'or from your own storage service'
src/core/sdk.ts
Outdated
this.storageHandler = storage; | ||
this.storage = new Storage(storage); | ||
this.deployer = new ContractDeployer(network, options, storage); | ||
this.wallet = new UserWallet(network, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adam-maj careful here - you're passingnetwork
instead of the transformed provider rpc
(should prob be renamed)
this will def break things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm good catch - typing doesn't throw here understandably (maybe because of overlapping types?)
@@ -0,0 +1,11 @@ | |||
export interface UploadProgressEvent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make sure this gets exported properly (add to types/index.ts)
src/core/classes/storage.ts
Outdated
*/ | ||
uris: string[]; | ||
} | ||
export class Storage { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adam-maj you're still not exporting this class for docs, needs to be declared in core/classes/index.ts
- also add a top level class documentation 🙏
src/core/classes/storage.ts
Outdated
* fs.readFileSync("file2.png"), | ||
* fs.readFileSync("file3.png"), | ||
* ] | ||
* const uri = await sdk.storage.upload(files); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also add an example uploading just regular JSON, and one example with a progress upload callback?
src/core/interfaces/IStorage.ts
Outdated
options?: { | ||
onProgress: (event: UploadProgressEvent) => void; | ||
}, | ||
): Promise<StorageUpload>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i actually kinda liked that the type has Result
in it, like StorageUploadResult
, but nbd
* director and the URIs of the uploaded files. | ||
* @public | ||
*/ | ||
export type StorageUpload = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make sure this is exported in docs (add to core/interfaces/index.ts
)
No description provided.