Skip to content

Commit

Permalink
ALL-3061 Added IPFS get method (#1000)
Browse files Browse the repository at this point in the history
Co-authored-by: Oleksandr Loiko <[email protected]>
  • Loading branch information
alexloiko and Oleksandr Loiko authored Oct 23, 2023
1 parent 9706f40 commit c5590f5
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [4.1.14] - 2023.10.23
### Added
- Added IPFS get file data method

## [4.1.13] - 2023.10.20
### Changed
- Fixed CONTRACT_ADDRESS_LOG_EVENT data in getAll() Notification method
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ Explore the world of fungible tokens, manage their properties, and track your as
| [Get metadata of a fungible token](https://docs.tatum.io/docs/fungible-tokens/get-metadata-of-a-fungible-token) |
| [Create a fungible token](https://docs.tatum.io/docs/fungible-tokens/create-a-fungible-token) |

### πŸ“ IPFS

Enables you as a developer to use IPFS to store and retrieve your media.

| Documentation |
|--------------------------------------------------------------------|
| [Upload file to IPFS](https://docs.tatum.io/docs/ipfs/upload-file) |


### β›½ Fee Estimation

Stay updated with real-time fee insights and ensure smooth transactions without overpaying.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tatumio/tatum",
"version": "4.1.13",
"version": "4.1.14",
"description": "Tatum JS SDK",
"author": "Tatum",
"repository": "https://github.com/tatumio/tatum-js",
Expand Down
1 change: 1 addition & 0 deletions src/connector/connector.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface GetUrl<PARAMS = DefaultParamsType> {
path?: string
basePath?: string
params?: PARAMS
isDownload?: boolean
}

export interface SdkRequest<PARAMS = DefaultParamsType, BODY = DefaultBodyType> extends GetUrl<PARAMS> {
Expand Down
37 changes: 26 additions & 11 deletions src/connector/tatum.connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,24 @@ export class TatumConnector {
constructor(private readonly id: string) {}

public async get<RESPONSE, PARAMS extends DefaultParamsType = DefaultParamsType>(request: GetUrl<PARAMS>) {
return this.request<RESPONSE, PARAMS>({ ...request, method: 'GET' })
return this.request<RESPONSE, PARAMS>({ ...request, method: 'GET' }) as Promise<RESPONSE>
}

public async rpcCall<RESPONSE>(url: string, body: JsonRpcCall | JsonRpcCall[]) {
return this.request<RESPONSE>({ body, method: 'POST' }, 0, url)
return this.request<RESPONSE>({ body, method: 'POST' }, 0, url) as Promise<RESPONSE>
}

public async post<RESPONSE, BODY extends DefaultBodyType = DefaultBodyType>(
request: SdkRequest<DefaultParamsType, BODY>,
) {
return this.request<RESPONSE, DefaultParamsType, BODY>({ ...request, method: 'POST' })
return this.request<RESPONSE, DefaultParamsType, BODY>({
...request,
method: 'POST',
}) as Promise<RESPONSE>
}

public async delete<RESPONSE>(request: GetUrl) {
return this.request<RESPONSE>({ ...request, method: 'DELETE' })
return this.request<RESPONSE>({ ...request, method: 'DELETE' }) as Promise<RESPONSE>
}

public async uploadFile<RESPONSE>(request: FileUploadRequest) {
Expand All @@ -37,18 +40,24 @@ export class TatumConnector {
return this.request<RESPONSE>(
{ ...request, method: 'POST', body: formData, basePath: Constant.TATUM_API_URL.V3 },
0,
)
) as Promise<RESPONSE>
}

public async getFile<RESPONSE, PARAMS extends DefaultParamsType = DefaultParamsType>(
request: GetUrl<PARAMS>,
) {
return this.request<RESPONSE, PARAMS>({ ...request, method: 'GET', isDownload: true }) as Promise<Blob>
}

private async request<
RESPONSE,
PARAMS extends DefaultParamsType = DefaultParamsType,
BODY extends DefaultBodyType = DefaultBodyType,
>(
{ path, params, body, method, basePath }: SdkRequest<PARAMS, BODY>,
{ path, params, body, method, basePath, isDownload }: SdkRequest<PARAMS, BODY>,
retry = 0,
externalUrl?: string,
): Promise<RESPONSE> {
): Promise<RESPONSE | Blob | undefined> {
const url = externalUrl || this.getUrl({ path, params, basePath })
const isUpload = body && body instanceof FormData
const headers = isUpload ? Utils.getBasicHeaders(this.id) : Utils.getHeaders(this.id)
Expand All @@ -71,7 +80,7 @@ export class TatumConnector {
try {
const res = await fetch(url, request)
const end = Date.now() - start
const responseBody = await res.clone().text()
const responseBody = isDownload ? `Binary data` : await res.clone().text()

// Structure your log entry here
Utils.log({
Expand All @@ -93,15 +102,21 @@ export class TatumConnector {
})

if (res.ok) {
return responseBody ? await res.json() : undefined
if (!responseBody) {
return undefined
}
if (isDownload) {
return await res.blob()
}
return await res.json()
}

// Retry only in case of 5xx error
if (res.status >= 500 && res.status < 600) {
return await this.retry(url, request, res, retry)
}

return await Promise.reject(responseBody)
throw responseBody
} catch (error) {
const end = Date.now() - start
Utils.log({
Expand Down Expand Up @@ -151,7 +166,7 @@ export class TatumConnector {
request: RequestInit,
response: Response,
retry: number,
): Promise<RESPONSE> {
): Promise<RESPONSE | Blob | undefined> {
const { retryDelay, retryCount } = Container.of(this.id).get(CONFIG)
if (!retryCount) {
Utils.log({
Expand Down
7 changes: 7 additions & 0 deletions src/service/ipfs/ipfs.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ export interface UploadFile {
*/
file: BlobPart
}

export interface GetFile {
/**
* File id to be retrieved
*/
id: string
}
16 changes: 15 additions & 1 deletion src/service/ipfs/ipfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Container, Service } from 'typedi'
import { TatumConnector } from '../../connector/tatum.connector'
import { CONFIG, ErrorUtils, ResponseDto } from '../../util'
import { TatumConfig } from '../tatum'
import { UploadFile } from './ipfs.dto'
import { GetFile, UploadFile } from './ipfs.dto'

@Service({
factory: (data: { id: string }) => {
Expand Down Expand Up @@ -32,4 +32,18 @@ export class Ipfs {
}),
)
}

/**
* Get file binary data from the IPFS storage.
* @param body Body of the request with file to be uploaded.
* @returns Blob IPFS file binary data.
* @returns ResponseDto<null> is error occurred.
*/
async getFile(body: GetFile): Promise<Blob | ResponseDto<null>> {
return ErrorUtils.tryFailBlob(() =>
this.connector.getFile<Blob>({
path: `ipfs/${body.id}`,
}),
)
}
}
11 changes: 11 additions & 0 deletions src/util/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ export const ErrorUtils = {
}
}
},
tryFailBlob: async (f: (() => Promise<Blob>) | (() => Blob)): Promise<Blob | ResponseDto<null>> => {
try {
return await f()
} catch (e) {
return {
data: null,
status: Status.ERROR,
error: ErrorUtils.toErrorWithMessage(e),
}
}
},
formatErrorMsg: (message: string) => {
return message.replace('attr.', '')
},
Expand Down

0 comments on commit c5590f5

Please sign in to comment.