import { DataResponse } from './response/payload/common/data.response'; import { AddressResponse } from './response/payload/address/address.response'; import { PaginatedDataResponse } from './response/payload/common/paginated-data.response'; import { AccountResponse } from './response/payload/account/account.response'; import { PaginateQuery } from './request/query/paginate.query'; import { RequestMakerInterface } from './request/maker/request-maker.interface'; import { ExchangeRateResponse } from './response/payload/exchange-rate/exchange-rate.response'; import { PaginatedTransactionResponse } from './response/payload/transaction/paginated-transaction.response'; import { TransactionResponse } from './response/payload/transaction/transaction.response'; import { PayloadPreconditionFailedException } from './request/maker/exception/payload-precondition-failed.exception'; import { PaginatedPaymentMethodResponse } from './response/payload/payment/paginated-payment-method.response'; import { PaymentMethodResponse } from './response/payload/payment/payment-method.response'; import { FiatCurrenciesResponse } from './response/payload/fiat-currencies/fiat-currencies.response'; import { TimeResponse } from './response/payload/time/time.response'; import { PriceResponse } from './response/payload/price/price.response'; import { validateCurrencyPair } from './request/validator/currency-pair.validator'; import { PaginatedBuyResponse } from './response/payload/buy/paginated-buy.response'; import { BuyResponse } from './response/payload/buy/buy.response'; import { PaginatedSellResponse } from './response/payload/sell/paginated-sell.response'; import { SellResponse } from './response/payload/sell/sell.response'; import { CryptoCurrenciesResponse } from './response/payload/crypto-currencies/crypto-currencies.response'; export class CoinbaseClient { private requestMaker: RequestMakerInterface; constructor(requestMaker: RequestMakerInterface) { this.requestMaker = requestMaker; } /** * Get current exchange rates. Default base currency is USD but it can be defined as any supported currency (see Currencies endpoint). * Returned rates will define the exchange rate for one unit of the base currency. * * Permissions * This endpoint does not require any permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-exchange-rates#get-exchange-rates */ async getExchangeRates( currency: string, ): Promise> { return this.requestMaker.read>( `/v2/exchange-rates?currency=${currency}`, ); } /** * List a current user's accounts to which the authentication method has access to. * * Permissions * This endpoint requires the "wallet:accounts:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#list-accounts */ async listAccounts( paginateQuery?: PaginateQuery, ): Promise> { return this.requestMaker.read< Promise> >(`/v2/accounts`, paginateQuery); } /** * Show (or get) a current user's account. To access the primary account for a given currency, a currency string (e.g., BTC or ETH) can be used instead of the account ID in the URL. * * Permissions * This endpoint requires the "wallet:accounts:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#show-an-account */ async showAccount(accountId: string): Promise> { return this.requestMaker.read>>( `/v2/accounts/${accountId}`, ); } /** * Modify a user's account. * * Permissions * This endpoint requires the "wallet:accounts:update" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#update-account */ async updateAccount( accountId: string, name: string, ): Promise> { return this.requestMaker.update>>( `/v2/accounts/${accountId}`, { name: name }, ); } /** * Remove a user's account. You cannot remove: * * - Primary accounts * - Accounts with non-zero balance * - Fiat accounts * - Vaults with a pending withdrawal * * Permissions * This endpoint requires the "wallet:accounts:delete" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-accounts#delete-account */ async deleteAccount(accountId: string): Promise { return this.requestMaker.delete(`/v2/accounts/${accountId}`); } /** * Creates a new address for an account. Addresses can be created for wallet account types. * * Permissions * This endpoint requires the "wallet:addresses:create" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-addresses#create-address */ async createAddress( accountId: string, name?: string, ): Promise> { return this.requestMaker.create>>( `/v2/accounts/${accountId}/addresses`, name ? { name: name } : null, ); } /** * Get a single address for an account. A regular cryptocurrency address can be used in place of address_id but the address must be associated with the correct account. * * Permissions * This endpoint requires the "wallet:addresses:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-addresses#show-address */ async showAddress( accountId: string, addressId: string, ): Promise> { return this.requestMaker.read>>( `/v2/accounts/${accountId}/addresses/${addressId}`, ); } /** * List transactions that have been sent to a specific address. A regular cryptocurrency address can be used in place of address_id but the address must be associated with the correct account. * * Permissions * This endpoint requires the "wallet:transactions:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-transactions#list-transactions **/ async listTransactions( accountId: string, paginateQuery?: PaginateQuery, ): Promise> { return this.requestMaker.read< Promise> >(`/v2/accounts/${accountId}/transactions`, paginateQuery); } /** * Get a single address for an account. A regular cryptocurrency address can be used in place of address_id but the address must be associated with the correct account. * * Permissions * This endpoint requires the "wallet:addresses:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-transactions#show-a-transaction */ async showTransaction( accountId: string, transactionId: string, ): Promise> { return this.requestMaker.read>>( `/v2/accounts/${accountId}/transactions/${transactionId}`, ); } /** * Send funds to a network address for any Coinbase supported asset, or email address of the recipient. No transaction fees are required for off-blockchain cryptocurrency transactions. * * Coinbase recommends that you always supply a unique idem field for each transaction. * * Permissions * This endpoint requires the "wallet:transactions:send" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-transactions#send-money */ async sendMoney( accountId: string, to: string, amount: string, currency: string, options?: { idem?: string; toFinancialInstitution?: boolean; financialInstitutionWebsite?: string; memo?: string; description?: string; skipNotifications?: boolean; destinationTag?: string; }, ): Promise> { if ( options && options.toFinancialInstitution && !options.financialInstitutionWebsite ) { throw new PayloadPreconditionFailedException( 'financialInstitutionWebsite is required when toFinancialInstitution is true', ); } const payload = { type: 'send', to: to, amount: amount, currency: currency, }; if (options && options.idem) { payload['idem'] = options.idem; } if (options && options.destinationTag) { payload['destination_tag'] = options.destinationTag; } if (options && options.description) { payload['description'] = options.description; } if (options && options.skipNotifications) { payload['skip_notifications'] = options.skipNotifications; } if (options && options.memo) { payload['memo'] = options.memo; } if (options && options.toFinancialInstitution) { payload['to_financial_institution'] = options.toFinancialInstitution; payload['financial_institution_website'] = options.financialInstitutionWebsite; } return this.requestMaker.create>>( `/v2/accounts/${accountId}/transactions`, payload, ); } /** * Transfer any Coinbase supported digital asset between two of a single user's accounts. The following transfers are allowed: * * Permissions * This endpoint requires the "wallet:transactions:transfer" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-transactions#transfer-money-between-accounts */ async transferMoney( accountId: string, to: string, amount: string, currency: string, description?: string, ): Promise> { const payload = { type: 'transfer', to: to, amount: amount, currency: currency, }; if (description) { payload['description'] = description; } return this.requestMaker.create>>( `/v2/accounts/${accountId}/transactions`, payload, ); } /** * Lists the current user's payment methods. * * Permissions * This endpoint requires the "wallet:payment-methods:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-payment-methods#list-payment-methods */ async listPaymentMethods( paginateQuery?: PaginateQuery, ): Promise> { return this.requestMaker.read< Promise> >(`/v2/payment-methods`, paginateQuery); } /** * Get a single payment method (of the current user) by payment method ID. * * Permissions * This endpoint requires the "wallet:payment-methods:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-payment-methods#show-a-payment-method */ async showPaymentMethod( paymentMethodId: string, ): Promise> { return this.requestMaker.read>>( `/v2/payment-methods/${paymentMethodId}`, ); } /** * Lists known fiat currencies. Currency codes conform to the ISO 4217 standard where possible. Currencies with no representation in ISO 4217 may use a custom code. * * Permissions * This endpoint does not require any permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-currencies#get-fiat-currencies */ async getFiatCurrencies(): Promise> { return this.requestMaker.read< Promise> >(`/v2/currencies`); } /** * Lists known cryptocurrencies. * * Permissions * This endpoint does not require any permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-currencies#get-cryptocurrencies */ async getCryptoCurrencies(): Promise< DataResponse > { return this.requestMaker.read< Promise> >(`/v2/currencies/crypto`); } /** * Get the API server time. * * Permissions * This endpoint does not require any permission. */ async getCurrentTime(): Promise> { return this.requestMaker.read>>( `/v2/time`, ); } /** * Get the total price to buy one bitcoin or ether. * * Note that exchange rates fluctuates so the price is only correct for seconds at the time. This buy price includes standard Coinbase fee (1%) but excludes any other fees including bank fees. * If you need more accurate price estimate for a specific payment method or amount, see buy bitcoin endpoint and quote: true option. * * Permissions * This endpoint does not require any permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-buy-price */ async getBuyPrice( currencyPair: string, ): Promise> { validateCurrencyPair(currencyPair); return this.requestMaker.read>>( `/v2/prices/${currencyPair}/buy`, ); } /** * Get the total price to sell one bitcoin or ether. * * Note that exchange rates fluctuates so the price is only correct for seconds at the time. This sell price includes standard Coinbase fee (1%) but excludes any other fees including bank fees. * If you need more accurate price estimate for a specific payment method or amount, see sell bitcoin endpoint and quote: true option. * * Permissions * This endpoint does not require any permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-sell-price */ async getSellPrice( currencyPair: string, ): Promise> { validateCurrencyPair(currencyPair); return this.requestMaker.read>>( `/v2/prices/${currencyPair}/sell`, ); } /** * Get the current market price for bitcoin. This is usually somewhere in between the buy and sell price. * * Note that exchange rates fluctuates so the price is only correct for seconds at the time. * * You can also get historic prices with date parameter. * * Permissions * This endpoint does not require any permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices#get-spot-price */ async getSpotPrice( currencyPair: string, date?: Date, ): Promise> { validateCurrencyPair(currencyPair); let url = `/v2/prices/${currencyPair}/spot`; if (date) { url += `?date=${date.toISOString()}`; } return this.requestMaker.read>>(url); } /** * Lists buys for an account. * * Permissions * This endpoint requires the "wallet:buys:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#list-buys */ async listBuys( paginateQuery?: PaginateQuery, ): Promise> { return this.requestMaker.read< Promise> >(`/v2/buys`, paginateQuery); } /** * Show an individual buy. * * Permissions * This endpoint requires the "wallet:buys:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#show-a-buy */ async showBuy(buyId: string): Promise> { return this.requestMaker.read>>( `/v2/buys/${buyId}`, ); } /** * Buys a user-defined amount of any Coinbase supported asset. * * Permissions * This endpoint requires the "wallet:buys:create" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#place-buy-order */ async placeBuy( amount: string, currency: string, paymentMethodId: string, options?: { commit?: boolean; quote?: string; agree_btc_amount_varies?: boolean; }, ): Promise> { const payload = { amount: amount, currency: currency, payment_method: paymentMethodId, }; if (options && options.commit) { payload['commit'] = options.commit; } if (options && options.quote) { payload['quote'] = options.quote; } if (options && options.agree_btc_amount_varies) { payload['agree_btc_amount_varies'] = options.agree_btc_amount_varies; } return this.requestMaker.create>>( `/v2/buys`, payload, ); } /** * Completes a buy that is created in commit: false state. * * If the exchange rate has changed since the buy was created, this call will fail with the error “The exchange rate updated while you were waiting. The new total is shown below”. * * The buy's total will also be updated. You can repeat the /commit call to accept the new values and start the buy at the new rates. * * Permissions * This endpoint requires the "wallet:buys:create" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-buys#commit-a-buy */ async commitBuy(buyId: string): Promise> { return this.requestMaker.update>>( `/v2/buys/${buyId}/commit`, {}, ); } /** * Lists sells for an account. * * Permissions * This endpoint requires the "wallet:sells:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-sells#list-sells */ async listSells( paginateQuery?: PaginateQuery, ): Promise> { return this.requestMaker.read< Promise> >(`/v2/sells`, paginateQuery); } /** * Show an individual sell. * * Permissions * This endpoint requires the "wallet:sells:read" permission. * * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-sells#show-a-sell */ async showSell(sellId: string): Promise> { return this.requestMaker.read>>( `/v2/sells/${sellId}`, ); } }