Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gnosis.pm/safe-react-gateway-sdk",
"version": "3.4.7",
"version": "3.5.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
Expand Down
39 changes: 23 additions & 16 deletions src/endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import { fetchData, insertParams, stringifyQuery } from './utils'
import type { paths } from './types/api'
import type { GetEndpoint, paths, PostEndpoint, Primitive } from './types/api'

type Primitive = string | number | boolean | null
function makeUrl(
baseUrl: string,
path: string,
pathParams?: Record<string, Primitive>,
query?: Record<string, Primitive>,
): string {
const pathname = insertParams(path, pathParams)
const search = stringifyQuery(query)
return `${baseUrl}${pathname}${search}`
}

interface Params {
path?: { [key: string]: Primitive }
query?: { [key: string]: Primitive }
body?: unknown
export function postEndpoint<T extends keyof paths>(
baseUrl: string,
path: T,
params?: paths[T] extends PostEndpoint ? paths[T]['post']['parameters'] : never,
): Promise<paths[T] extends PostEndpoint ? paths[T]['post']['responses'][200]['schema'] : never> {
const url = makeUrl(baseUrl, path as string, params?.path, params?.query)
return fetchData(url, params?.body)
}

export function callEndpoint<T extends keyof paths>(
export function getEndpoint<T extends keyof paths>(
baseUrl: string,
path: T,
parameters?: paths[T]['get']['parameters'],
params?: paths[T] extends GetEndpoint ? paths[T]['get']['parameters'] : never,
rawUrl?: string,
): Promise<paths[T]['get']['responses'][200]['schema']> {
): Promise<paths[T] extends GetEndpoint ? paths[T]['get']['responses'][200]['schema'] : never> {
if (rawUrl) {
return fetchData(rawUrl)
}

const params = parameters as Params
const pathname = insertParams(path, params?.path)
const search = stringifyQuery(params?.query)
const url = `${baseUrl}${pathname}${search}`

return fetchData(url, params?.body)
const url = makeUrl(baseUrl, path as string, params?.path, params?.query)
return fetchData(url)
}
46 changes: 23 additions & 23 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { callEndpoint } from './endpoint'
import { getEndpoint, postEndpoint } from './endpoint'
import type { operations } from './types/api'
import type {
SafeTransactionEstimation,
Expand Down Expand Up @@ -48,7 +48,7 @@ export const setBaseUrl = (url: string): void => {
* Get basic information about a Safe. E.g. owners, modules, version etc
*/
export function getSafeInfo(chainId: string, address: string): Promise<SafeInfo> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{address}', { path: { chainId, address } })
return getEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{address}', { path: { chainId, address } })
}

/**
Expand All @@ -60,7 +60,7 @@ export function getIncomingTransfers(
query?: operations['incoming_transfers']['parameters']['query'],
pageUrl?: string,
): Promise<SafeIncomingTransfersResponse> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v1/chains/{chainId}/safes/{address}/incoming-transfers/',
{
Expand All @@ -80,7 +80,7 @@ export function getModuleTransactions(
query?: operations['module_transactions']['parameters']['query'],
pageUrl?: string,
): Promise<SafeModuleTransactionsResponse> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v1/chains/{chainId}/safes/{address}/module-transactions/',
{
Expand All @@ -100,7 +100,7 @@ export function getMultisigTransactions(
query?: operations['multisig_transactions']['parameters']['query'],
pageUrl?: string,
): Promise<SafeMultisigTransactionsResponse> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v1/chains/{chainId}/safes/{address}/multisig-transactions/',
{
Expand All @@ -120,7 +120,7 @@ export function getBalances(
currency = 'usd',
query: operations['safes_balances_list']['parameters']['query'] = {},
): Promise<SafeBalanceResponse> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{address}/balances/{currency}', {
return getEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{address}/balances/{currency}', {
path: { chainId, address, currency },
query,
})
Expand All @@ -130,14 +130,14 @@ export function getBalances(
* Get a list of supported fiat currencies (e.g. USD, EUR etc)
*/
export function getFiatCurrencies(): Promise<FiatCurrencies> {
return callEndpoint(baseUrl, '/v1/balances/supported-fiat-codes')
return getEndpoint(baseUrl, '/v1/balances/supported-fiat-codes')
}

/**
* Get the addresses of all Safes belonging to an owner
*/
export function getOwnedSafes(chainId: string, address: string): Promise<OwnedSafes> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/owners/{address}/safes', { path: { chainId, address } })
return getEndpoint(baseUrl, '/v1/chains/{chainId}/owners/{address}/safes', { path: { chainId, address } })
}

/**
Expand All @@ -148,7 +148,7 @@ export function getCollectibles(
address: string,
query: operations['safes_collectibles_list']['parameters']['query'] = {},
): Promise<SafeCollectibleResponse[]> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{address}/collectibles', {
return getEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{address}/collectibles', {
path: { chainId, address },
query,
})
Expand All @@ -163,7 +163,7 @@ export function getCollectiblesPage(
query: operations['safes_collectibles_list_paginated']['parameters']['query'] = {},
pageUrl?: string,
): Promise<SafeCollectiblesPage> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v2/chains/{chainId}/safes/{address}/collectibles',
{ path: { chainId, address }, query },
Expand All @@ -179,7 +179,7 @@ export function getTransactionHistory(
address: string,
pageUrl?: string,
): Promise<TransactionListPage> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v1/chains/{chainId}/safes/{safe_address}/transactions/history',
{ path: { chainId, safe_address: address }, query: {} },
Expand All @@ -196,7 +196,7 @@ export function getTransactionQueue(
pageUrl?: string,
trusted?: boolean,
): Promise<TransactionListPage> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v1/chains/{chainId}/safes/{safe_address}/transactions/queued',
{ path: { chainId, safe_address: address }, query: { trusted } },
Expand All @@ -208,7 +208,7 @@ export function getTransactionQueue(
* Get the details of an individual transaction by its id
*/
export function getTransactionDetails(chainId: string, transactionId: string): Promise<TransactionDetails> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/transactions/{transactionId}', {
return getEndpoint(baseUrl, '/v1/chains/{chainId}/transactions/{transactionId}', {
path: { chainId, transactionId },
})
}
Expand All @@ -221,7 +221,7 @@ export function postSafeGasEstimation(
address: string,
body: operations['post_safe_gas_estimation']['parameters']['body'],
): Promise<SafeTransactionEstimation> {
return callEndpoint(baseUrl, '/v2/chains/{chainId}/safes/{safe_address}/multisig-transactions/estimations', {
return postEndpoint(baseUrl, '/v2/chains/{chainId}/safes/{safe_address}/multisig-transactions/estimations', {
path: { chainId, safe_address: address },
body,
})
Expand All @@ -235,7 +235,7 @@ export function proposeTransaction(
address: string,
body: operations['propose_transaction']['parameters']['body'],
): Promise<TransactionDetails> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/transactions/{safe_address}/propose', {
return postEndpoint(baseUrl, '/v1/chains/{chainId}/transactions/{safe_address}/propose', {
path: { chainId, safe_address: address },
body,
})
Expand All @@ -245,7 +245,7 @@ export function proposeTransaction(
* Returns all defined chain configs
*/
export function getChainsConfig(query?: operations['chains_list']['parameters']['query']): Promise<ChainListResponse> {
return callEndpoint(baseUrl, '/v1/chains', {
return getEndpoint(baseUrl, '/v1/chains', {
query,
})
}
Expand All @@ -254,7 +254,7 @@ export function getChainsConfig(query?: operations['chains_list']['parameters'][
* Returns a chain config
*/
export function getChainConfig(chainId: string): Promise<ChainInfo> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}', {
return getEndpoint(baseUrl, '/v1/chains/{chainId}', {
path: { chainId: chainId },
})
}
Expand All @@ -266,7 +266,7 @@ export function getSafeApps(
chainId: string,
query: operations['safe_apps_read']['parameters']['query'] = {},
): Promise<SafeAppsResponse> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/safe-apps', {
return getEndpoint(baseUrl, '/v1/chains/{chainId}/safe-apps', {
path: { chainId: chainId },
query,
})
Expand All @@ -276,7 +276,7 @@ export function getSafeApps(
* Returns list of Master Copies
*/
export function getMasterCopies(chainId: string): Promise<MasterCopyReponse> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/about/master-copies', {
return getEndpoint(baseUrl, '/v1/chains/{chainId}/about/master-copies', {
path: { chainId: chainId },
})
}
Expand All @@ -288,7 +288,7 @@ export function getDecodedData(
chainId: string,
encodedData: operations['data_decoder']['parameters']['body']['data'],
): Promise<DecodedDataResponse> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/data-decoder', {
return postEndpoint(baseUrl, '/v1/chains/{chainId}/data-decoder', {
path: { chainId: chainId },
body: { data: encodedData },
})
Expand All @@ -298,7 +298,7 @@ export function getDecodedData(
* Returns list of `SafeMessage`s
*/
export function getSafeMessages(chainId: string, address: string, pageUrl?: string): Promise<SafeMessageListPage> {
return callEndpoint(
return getEndpoint(
baseUrl,
'/v1/chains/{chainId}/safes/{safe_address}/messages',
{ path: { chainId, safe_address: address }, query: {} },
Expand All @@ -314,7 +314,7 @@ export function proposeSafeMessage(
address: string,
body: operations['propose_safe_message']['parameters']['body'],
): Promise<void> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{safe_address}/messages', {
return postEndpoint(baseUrl, '/v1/chains/{chainId}/safes/{safe_address}/messages', {
path: { chainId, safe_address: address },
body,
})
Expand All @@ -328,7 +328,7 @@ export function confirmSafeMessage(
messageHash: string,
body: operations['confirm_safe_message']['parameters']['body'],
): Promise<void> {
return callEndpoint(baseUrl, '/v1/chains/{chainId}/messages/{message_hash}/signatures', {
return postEndpoint(baseUrl, '/v1/chains/{chainId}/messages/{message_hash}/signatures', {
path: { chainId, message_hash: messageHash },
body,
})
Expand Down
71 changes: 50 additions & 21 deletions src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,49 @@ import type { ChainListResponse, ChainInfo } from './chains'
import type { SafeAppsResponse } from './safe-apps'
import type { DecodedDataRequest, DecodedDataResponse } from './decoded-data'
import type { MasterCopyReponse } from './master-copies'
import type { ConfirmSafeMessageRequest, ProposeSafeMessageRequest } from './safe-messages'
import type { ConfirmSafeMessageRequest, ProposeSafeMessageRequest, SafeMessageListPage } from './safe-messages'

export interface paths {
export type Primitive = string | number | boolean | null

interface GetParams {
path?: { [key: string]: Primitive }
query?: { [key: string]: Primitive }
}

interface PostParams extends GetParams {
body: string | Record<string, unknown>
}

interface Responses {
200: { schema: unknown }
[key: number]: { schema: unknown } | unknown
}

interface Endpoint {
parameters: {
path: Record<string, Primitive>
} | null
}

export interface GetEndpoint extends Endpoint {
get: {
parameters: GetParams | null
responses: Responses
}
}

export interface PostEndpoint extends Endpoint {
post: {
parameters: PostParams | null
responses: Responses
}
}

interface PathRegistry {
[key: string]: GetEndpoint | PostEndpoint | (GetEndpoint & PostEndpoint)
}

export interface paths extends PathRegistry {
'/v1/chains/{chainId}/safes/{address}': {
/** Get status of the safe */
get: operations['safes_read']
Expand Down Expand Up @@ -125,8 +165,7 @@ export interface paths {
}
}
'/v2/chains/{chainId}/safes/{safe_address}/multisig-transactions/estimations': {
/** This is actually supposed to be POST but it breaks our type paradise */
get: operations['post_safe_gas_estimation']
post: operations['post_safe_gas_estimation']
parameters: {
path: {
chainId: string
Expand All @@ -135,8 +174,7 @@ export interface paths {
}
}
'/v1/chains/{chainId}/transactions/{safe_address}/propose': {
/** This is actually supposed to be POST but it breaks our type paradise */
get: operations['propose_transaction']
post: operations['propose_transaction']
parameters: {
path: {
chainId: string
Expand All @@ -155,13 +193,7 @@ export interface paths {
}
'/v1/chains': {
get: operations['chains_list']
parameters: {
query: {
ordering?: string
limit?: number
offset?: number
}
}
parameters: null
}
'/v1/chains/{chainId}': {
get: operations['chains_read']
Expand All @@ -188,18 +220,16 @@ export interface paths {
}
}
'/v1/chains/{chainId}/data-decoder': {
get: operations['data_decoder']
post: operations['data_decoder']
parameters: {
path: {
chainId: string
}
}
}
'/v1/chains/{chainId}/safes/{safe_address}/messages': {
get:
| operations['get_safe_messages']
/** This is actually supposed to be POST but it breaks our type paradise */
| operations['propose_safe_message']
get: operations['get_safe_messages']
post: operations['propose_safe_message']
parameters: {
path: {
chainId: string
Expand All @@ -208,8 +238,7 @@ export interface paths {
}
}
'/v1/chains/{chainId}/messages/{message_hash}/signatures': {
/** This is actually supposed to be POST but it breaks our type paradise */
get: operations['confirm_safe_message']
post: operations['confirm_safe_message']
parameters: {
path: {
chainId: string
Expand Down Expand Up @@ -578,7 +607,7 @@ export interface operations {
}
responses: {
200: {
schema: SignedMessageListPage
schema: SafeMessageListPage
}
}
}
Expand Down
Loading