diff --git a/v2/api-validator/src/client/generated/ApiClient.ts b/v2/api-validator/src/client/generated/ApiClient.ts index 46977e62..7cffe349 100644 --- a/v2/api-validator/src/client/generated/ApiClient.ts +++ b/v2/api-validator/src/client/generated/ApiClient.ts @@ -41,7 +41,7 @@ export class ApiClient { constructor(config?: Partial, HttpRequest: HttpRequestConstructor = AxiosHttpRequest) { this.request = new HttpRequest({ BASE: config?.BASE ?? 'http://0.0.0.0:8000', - VERSION: config?.VERSION ?? '0.5.0', + VERSION: config?.VERSION ?? '0.5.1', WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false, CREDENTIALS: config?.CREDENTIALS ?? 'include', TOKEN: config?.TOKEN, diff --git a/v2/api-validator/src/client/generated/core/OpenAPI.ts b/v2/api-validator/src/client/generated/core/OpenAPI.ts index e5aa249b..ea0df4ba 100644 --- a/v2/api-validator/src/client/generated/core/OpenAPI.ts +++ b/v2/api-validator/src/client/generated/core/OpenAPI.ts @@ -21,7 +21,7 @@ export type OpenAPIConfig = { export const OpenAPI: OpenAPIConfig = { BASE: 'http://0.0.0.0:8000', - VERSION: '0.5.0', + VERSION: '0.5.1', WITH_CREDENTIALS: false, CREDENTIALS: 'include', TOKEN: undefined, diff --git a/v2/api-validator/src/client/generated/models/PublicBlockchainTransaction.ts b/v2/api-validator/src/client/generated/models/PublicBlockchainTransaction.ts index a919cc77..d18ffae1 100644 --- a/v2/api-validator/src/client/generated/models/PublicBlockchainTransaction.ts +++ b/v2/api-validator/src/client/generated/models/PublicBlockchainTransaction.ts @@ -5,7 +5,13 @@ import type { PublicBlockchainTransactionDestination } from './PublicBlockchainTransactionDestination'; +/** + * Blockchain transaction details. When the withdrawal or deposit has succeeded, `blockchainTxId` (transaction hash) is required and must be non-empty, although it is indicated as optional in the schema. + */ export type PublicBlockchainTransaction = (PublicBlockchainTransactionDestination & { + /** + * Transaction hash on the blockchain. Required (non-empty) when the transaction has succeeded. + */ blockchainTxId?: string; }); diff --git a/v2/api-validator/src/client/generated/services/TransfersBlockchainService.ts b/v2/api-validator/src/client/generated/services/TransfersBlockchainService.ts index 16f9f29a..6878b8e0 100644 --- a/v2/api-validator/src/client/generated/services/TransfersBlockchainService.ts +++ b/v2/api-validator/src/client/generated/services/TransfersBlockchainService.ts @@ -16,7 +16,7 @@ export class TransfersBlockchainService { /** * Get list of withdrawals over public blockchains sorted by creation time - * Retrieves a paginated list of withdrawal transactions sent over public blockchains. Includes cryptocurrency transfers to external blockchain addresses, sorted by creation time. + * Retrieves a paginated list of withdrawal transactions sent over public blockchains. Includes cryptocurrency transfers to external blockchain addresses, sorted by creation time. On success (status succeeded), the destination `blockchainTxId` (transaction hash) is required and must be non-empty. * * @returns any List of withdrawals. * @throws ApiError @@ -99,7 +99,8 @@ export class TransfersBlockchainService { /** * Create new withdrawal over public blockchain - * Should reject any non blockchain withdrawal request. + * Should reject any non blockchain withdrawal request. In the response, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the destination is required and must be non-empty. + * * @returns BlockchainWithdrawal New withdrawal has been successfully created. * @throws ApiError */ diff --git a/v2/api-validator/src/client/generated/services/TransfersFiatService.ts b/v2/api-validator/src/client/generated/services/TransfersFiatService.ts index 41c6048a..2193a88d 100644 --- a/v2/api-validator/src/client/generated/services/TransfersFiatService.ts +++ b/v2/api-validator/src/client/generated/services/TransfersFiatService.ts @@ -17,6 +17,7 @@ export class TransfersFiatService { /** * Get list of fiat withdrawals sorted by creation time * Retrieves a paginated list of fiat currency withdrawal transactions. Includes traditional banking transfers and wire transfers, sorted by creation time. + * The `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is optional in the schema. * * @returns any List of withdrawals. * @throws ApiError @@ -99,7 +100,8 @@ export class TransfersFiatService { /** * Create new fiat withdrawal - * Should reject any non fiat withdrawal request. + * Should reject any non fiat withdrawal request. In the response, `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction reaches a finalized state (succeeded or failed), although optional in the schema. + * * @returns FiatWithdrawal New withdrawal has been successfully created. * @throws ApiError */ diff --git a/v2/api-validator/src/client/generated/services/TransfersPeerAccountsService.ts b/v2/api-validator/src/client/generated/services/TransfersPeerAccountsService.ts index 1cb109c1..0ff90629 100644 --- a/v2/api-validator/src/client/generated/services/TransfersPeerAccountsService.ts +++ b/v2/api-validator/src/client/generated/services/TransfersPeerAccountsService.ts @@ -15,6 +15,7 @@ export class TransfersPeerAccountsService { /** * Get list of withdrawals to peer accounts, sorted by creation time * Retrieves a paginated list of withdrawal transactions sent to peer accounts. Includes transfers to other accounts within the same provider ecosystem, sorted by creation time. + * The `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is optional in the schema. * * @returns any List of withdrawals. * @throws ApiError @@ -97,7 +98,8 @@ export class TransfersPeerAccountsService { /** * Create new withdrawal to a peer account - * Should reject any non peer acount withdrawal request. + * Should reject any non peer acount withdrawal request. In the response, `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction reaches a finalized state (succeeded or failed), although optional in the schema. + * * @returns PeerAccountWithdrawal New withdrawal has been successfully created. * @throws ApiError */ diff --git a/v2/api-validator/src/client/generated/services/TransfersService.ts b/v2/api-validator/src/client/generated/services/TransfersService.ts index a33c0f44..4e4fc9b1 100644 --- a/v2/api-validator/src/client/generated/services/TransfersService.ts +++ b/v2/api-validator/src/client/generated/services/TransfersService.ts @@ -15,6 +15,8 @@ export class TransfersService { /** * Get list of withdrawals sorted by creation time * Retrieves a paginated list of all withdrawal transactions for the specified account. Withdrawals are sorted by creation time and include all types of withdrawal operations. + * If a withdrawal is in a terminal state (succeeded or failed), and it has an optional destination.referenceId property (not all transfer methods have this property), then this property MUST contain a valid value, despite it being defined as optional in the schema. + * Blockchain withdrawals in status succeeded, MUST contain destination.blockchainTxId property with a valid value (e.g., transaction hash), despite it being defined as optional in the schema. * * @returns any List of withdrawals. * @throws ApiError @@ -98,6 +100,7 @@ export class TransfersService { /** * Get withdrawal details * Retrieves detailed information about a specific withdrawal transaction, including status, amounts, fees, destination details, and processing information. + * For Peer, Fiat and other transfer methods that define a `referenceId` on the destination, this property is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is currently indicated as optional in the schema. For blockchain withdrawals, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the destination is required and must be non-empty. * * @returns Withdrawal Withdrawals details. * @throws ApiError @@ -159,6 +162,7 @@ export class TransfersService { /** * Get list of deposits sorted by creation time in a descending order * Retrieves a paginated list of all deposit transactions for the specified account. Deposits are sorted by creation time in descending order and include all types of deposit operations. + * For Peer, Fiat and other transfer methods that define a `referenceId` on the source, this property is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is currently indicated as optional in the schema. For deposits with a blockchain source, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the source is required and must be non-empty. * * @returns any Deposits details. * @throws ApiError @@ -236,6 +240,7 @@ export class TransfersService { /** * Get deposit details * Retrieves detailed information about a specific deposit transaction, including status, amounts, source details, confirmation information, and processing details. + * For Peer, Fiat and other transfer methods that define a `referenceId` on the source, this property is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is currently indicated as optional in the schema. For deposits with a blockchain source, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the source is required and must be non-empty. * * @returns Deposit List of deposits. * @throws ApiError diff --git a/v2/api-validator/src/server/controllers/deposit-controller.ts b/v2/api-validator/src/server/controllers/deposit-controller.ts index 848ad7a6..df63670b 100644 --- a/v2/api-validator/src/server/controllers/deposit-controller.ts +++ b/v2/api-validator/src/server/controllers/deposit-controller.ts @@ -10,7 +10,9 @@ import { DepositAddressStatus, DepositCapability, DepositDestination, + DepositStatus, IbanCapability, + InternalTransferMethod, PublicBlockchainCapability, } from '../../client/generated'; import { Repository } from './repository'; @@ -73,6 +75,8 @@ export class DepositController { const knownAssetIds = AssetsController.getAllAdditionalAssets().map((a) => a.id); injectKnownAssetIdsToDeposits(knownAssetIds, this.depositRepository); + ensureReferenceIdForFinalizedDeposits(this.depositRepository); + ensureBlockchainTxIdForSucceededDeposits(this.depositRepository); injectKnownAssetIdsToDepositAddresses(knownAssetIds, this.depositAddressRepository); injectKnownAssetIdsToDepositCapabilities(knownAssetIds, this.depositCapabilitiesRepository); this.depositCapabilitiesRepository.removeDuplicatesBy((dc) => dc.deposit); @@ -216,6 +220,43 @@ function injectKnownAssetIdsToDeposits( } } +function ensureReferenceIdForFinalizedDeposits(depositRepository: Repository): void { + const finalized = [DepositStatus.SUCCEEDED, DepositStatus.FAILED]; + for (const { id } of depositRepository.list()) { + const deposit = depositRepository.find(id); + if (!deposit || !finalized.includes(deposit.status)) continue; + const tm = deposit.source.transferMethod; + if ( + tm === PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN || + tm === InternalTransferMethod.transferMethod.INTERNAL_TRANSFER + ) { + continue; + } + const source = deposit.source as { referenceId?: string }; + if (!source.referenceId || source.referenceId.trim() === '') { + source.referenceId = randomUUID(); + } + } +} + +function ensureBlockchainTxIdForSucceededDeposits(depositRepository: Repository): void { + for (const { id } of depositRepository.list()) { + const deposit = depositRepository.find(id); + if ( + !deposit || + deposit.status !== DepositStatus.SUCCEEDED || + deposit.source.transferMethod !== + PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN + ) { + continue; + } + const source = deposit.source as { blockchainTxId?: string }; + if (!source.blockchainTxId || source.blockchainTxId.trim() === '') { + source.blockchainTxId = '0x' + randomUUID().replace(/-/g, '').slice(0, 64); + } + } +} + function injectKnownAssetIdsToDepositAddresses( knownAssetIds: string[], depositAddressRepository: Repository diff --git a/v2/api-validator/src/server/controllers/withdrawal-controller.ts b/v2/api-validator/src/server/controllers/withdrawal-controller.ts index 479891ea..14ce1778 100644 --- a/v2/api-validator/src/server/controllers/withdrawal-controller.ts +++ b/v2/api-validator/src/server/controllers/withdrawal-controller.ts @@ -73,6 +73,8 @@ export class WithdrawalController { const knownAssetIds = AssetsController.getAllAdditionalAssets().map((a) => a.id); injectKnownAssetIdsToWithdrawals(knownAssetIds, this.withdrawalRepository); + ensureReferenceIdForFinalizedWithdrawals(this.withdrawalRepository); + ensureBlockchainTxIdForSucceededWithdrawals(this.withdrawalRepository); injectKnownAssetIdsToWithdrawalCapabilities(knownAssetIds, this.withdrawalCapabilityRepository); this.withdrawalCapabilityRepository.removeDuplicatesBy((dc) => { return { @@ -259,6 +261,47 @@ function injectKnownAssetIdsToWithdrawals( } } +function ensureReferenceIdForFinalizedWithdrawals( + withdrawalRepository: Repository +): void { + const finalized = [WithdrawalStatus.SUCCEEDED, WithdrawalStatus.FAILED]; + for (const { id } of withdrawalRepository.list()) { + const withdrawal = withdrawalRepository.find(id); + if (!withdrawal || !finalized.includes(withdrawal.status)) continue; + const tm = withdrawal.destination.transferMethod; + if ( + tm === PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN || + tm === InternalTransferMethod.transferMethod.INTERNAL_TRANSFER + ) { + continue; + } + const dest = withdrawal.destination as { referenceId?: string }; + if (!dest.referenceId || dest.referenceId.trim() === '') { + dest.referenceId = randomUUID(); + } + } +} + +function ensureBlockchainTxIdForSucceededWithdrawals( + withdrawalRepository: Repository +): void { + for (const { id } of withdrawalRepository.list()) { + const withdrawal = withdrawalRepository.find(id); + if ( + !withdrawal || + withdrawal.status !== WithdrawalStatus.SUCCEEDED || + withdrawal.destination.transferMethod !== + PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN + ) { + continue; + } + const dest = withdrawal.destination as { blockchainTxId?: string }; + if (!dest.blockchainTxId || dest.blockchainTxId.trim() === '') { + dest.blockchainTxId = '0x' + randomUUID().replace(/-/g, '').slice(0, 64); + } + } +} + function injectKnownAssetIdsToWithdrawalCapabilities( knownAssetIds: string[], withdrawalCapabilityRepository: Repository diff --git a/v2/api-validator/tests/server-tests/deposits.test.ts b/v2/api-validator/tests/server-tests/deposits.test.ts index 117ef58d..c08fb67f 100644 --- a/v2/api-validator/tests/server-tests/deposits.test.ts +++ b/v2/api-validator/tests/server-tests/deposits.test.ts @@ -13,6 +13,7 @@ import { DepositAddressCreationRequest, DepositAddressStatus, DepositCapability, + DepositStatus, IbanCapability, InternalTransferCapability, InternalTransferMethod, @@ -542,5 +543,47 @@ describe.skipIf(noTransfersCapability)('Deposits', () => { } } }); + + const isFinalizedDeposit = (d: Deposit) => + d.status === DepositStatus.SUCCEEDED || d.status === DepositStatus.FAILED; + + const depositSourceTransferMethodHasReferenceId = (transferMethod: string) => + transferMethod !== PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN && + transferMethod !== InternalTransferMethod.transferMethod.INTERNAL_TRANSFER; + + it('should return non-empty referenceId for finalized deposits (Get Deposits) when transfer method defines it', () => { + for (const deposits of accountDepositsMap.values()) { + for (const d of deposits.filter(isFinalizedDeposit)) { + if (!depositSourceTransferMethodHasReferenceId(d.source.transferMethod)) continue; + const source = d.source as { referenceId?: string }; + expect( + source.referenceId, + `Deposit ${d.id} (${d.source.transferMethod}) in finalized state must have non-empty referenceId` + ).toBeDefined(); + expect( + typeof source.referenceId === 'string' && source.referenceId.trim().length > 0, + `Deposit ${d.id} source referenceId must be non-empty` + ).toBe(true); + } + } + }); + + it('should return non-empty blockchainTxId for succeeded deposits with blockchain source (Get Deposits)', () => { + for (const deposits of accountDepositsMap.values()) { + for (const d of deposits.filter((x) => x.status === DepositStatus.SUCCEEDED)) { + if (d.source.transferMethod !== PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN) + continue; + const source = d.source as { blockchainTxId?: string }; + expect( + source.blockchainTxId, + `Succeeded deposit ${d.id} with blockchain source must have non-empty blockchainTxId (transaction hash)` + ).toBeDefined(); + expect( + typeof source.blockchainTxId === 'string' && source.blockchainTxId.trim().length > 0, + `Deposit ${d.id} source blockchainTxId must be non-empty` + ).toBe(true); + } + } + }); }); }); diff --git a/v2/api-validator/tests/server-tests/withdrawals.test.ts b/v2/api-validator/tests/server-tests/withdrawals.test.ts index b21f2322..0cc37c27 100644 --- a/v2/api-validator/tests/server-tests/withdrawals.test.ts +++ b/v2/api-validator/tests/server-tests/withdrawals.test.ts @@ -21,6 +21,7 @@ import { type TransferCapability, Withdrawal, WithdrawalCapability, + WithdrawalStatus, ParticipantRelationshipType, CountryAlpha2Code, ParticipantsIdentification, @@ -312,6 +313,98 @@ describe.skipIf(noTransfersCapability)('Withdrawals', () => { } } }); + + const isFinalizedWithdrawal = (w: Withdrawal) => + w.status === WithdrawalStatus.SUCCEEDED || w.status === WithdrawalStatus.FAILED; + + const transferMethodHasReferenceId = (transferMethod: string) => + transferMethod !== PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN && + transferMethod !== InternalTransferMethod.transferMethod.INTERNAL_TRANSFER; + + it('should return non-empty referenceId for finalized withdrawals (Get Withdrawals) when transfer method defines it', () => { + for (const withdrawals of accountWithdrawalsMap.values()) { + for (const w of withdrawals.filter(isFinalizedWithdrawal)) { + if (!transferMethodHasReferenceId(w.destination.transferMethod)) continue; + const destination = w.destination as { referenceId?: string }; + expect( + destination.referenceId, + `Withdrawal ${w.id} (${w.destination.transferMethod}) in finalized state must have non-empty referenceId` + ).toBeDefined(); + expect( + typeof destination.referenceId === 'string' && destination.referenceId.trim().length > 0, + `Withdrawal ${w.id} referenceId must be non-empty` + ).toBe(true); + } + } + }); + + it('should return non-empty referenceId for finalized fiat withdrawals (Get Fiat Withdrawals)', () => { + for (const withdrawals of accountFiatWithdrawalsMap.values()) { + for (const w of withdrawals.filter(isFinalizedWithdrawal)) { + const destination = w.destination as { referenceId?: string }; + expect( + destination.referenceId, + `Fiat withdrawal ${w.id} in finalized state must have non-empty referenceId` + ).toBeDefined(); + expect( + typeof destination.referenceId === 'string' && destination.referenceId.trim().length > 0, + `Fiat withdrawal ${w.id} referenceId must be non-empty` + ).toBe(true); + } + } + }); + + it('should return non-empty referenceId for finalized peer account withdrawals (Get Peer Account Withdrawals)', () => { + for (const withdrawals of accountPeerAccountWithdrawalsMap.values()) { + for (const w of withdrawals.filter(isFinalizedWithdrawal)) { + const destination = w.destination as { referenceId?: string }; + expect( + destination.referenceId, + `Peer account withdrawal ${w.id} in finalized state must have non-empty referenceId` + ).toBeDefined(); + expect( + typeof destination.referenceId === 'string' && destination.referenceId.trim().length > 0, + `Peer account withdrawal ${w.id} referenceId must be non-empty` + ).toBe(true); + } + } + }); + + it('should return non-empty blockchainTxId for succeeded blockchain withdrawals (Get Withdrawals)', () => { + for (const withdrawals of accountWithdrawalsMap.values()) { + for (const w of withdrawals.filter((x) => x.status === WithdrawalStatus.SUCCEEDED)) { + if (w.destination.transferMethod !== PublicBlockchainCapability.transferMethod.PUBLIC_BLOCKCHAIN) + continue; + const destination = w.destination as { blockchainTxId?: string }; + expect( + destination.blockchainTxId, + `Succeeded blockchain withdrawal ${w.id} must have non-empty blockchainTxId (transaction hash)` + ).toBeDefined(); + expect( + typeof destination.blockchainTxId === 'string' && + destination.blockchainTxId.trim().length > 0, + `Blockchain withdrawal ${w.id} blockchainTxId must be non-empty` + ).toBe(true); + } + } + }); + + it('should return non-empty blockchainTxId for succeeded blockchain withdrawals (Get Blockchain Withdrawals)', () => { + for (const withdrawals of accountBlockchainWithdrawalsMap.values()) { + for (const w of withdrawals.filter((x) => x.status === WithdrawalStatus.SUCCEEDED)) { + const destination = w.destination as { blockchainTxId?: string }; + expect( + destination.blockchainTxId, + `Succeeded blockchain withdrawal ${w.id} must have non-empty blockchainTxId (transaction hash)` + ).toBeDefined(); + expect( + typeof destination.blockchainTxId === 'string' && + destination.blockchainTxId.trim().length > 0, + `Blockchain withdrawal ${w.id} blockchainTxId must be non-empty` + ).toBe(true); + } + } + }); }); describe('Create withdrawal', () => { diff --git a/v2/openapi/README.md b/v2/openapi/README.md index 5da20732..1e8964be 100644 --- a/v2/openapi/README.md +++ b/v2/openapi/README.md @@ -370,6 +370,15 @@ There are four objects, extending one another, that define the IBAN transfer met reference ID property to help correlate a withdrawal to a specific transaction on the transaction recipient side. + For Peer, Fiat and other transfer methods that define a `referenceId` on the destination + (withdrawals) or source (deposits), this property is expected to become **mandatory (non-empty)** + when the transaction is in a finalized state (succeeded or failed), although it is currently + indicated as optional in the schema. The same expectation applies to GET and POST transfer + endpoints that return withdrawal or deposit payloads. + + For blockchain withdrawals and for deposits with a blockchain source, when the transaction + has **succeeded**, `blockchainTxId` (transaction hash) is required and must be non-empty. + ![IBAN objects hierarchy](doc-assets/network-link-iban.png "IBAN objects hierarchy") When a client retrieves a withdrawal details, an `IbanTransfer` object is returned in the diff --git a/v2/openapi/fb-provider-api.yaml b/v2/openapi/fb-provider-api.yaml index 5f1b0e71..8ea9118f 100644 --- a/v2/openapi/fb-provider-api.yaml +++ b/v2/openapi/fb-provider-api.yaml @@ -4,7 +4,7 @@ servers: url: http://0.0.0.0:8000 info: title: 'Fireblocks Provider Connectivity API v2' - version: 0.5.0 + version: 0.5.1 x-logo: url: 'doc-assets/fireblocks-logo-lockup-network-navy.png' altText: 'Fireblocks logo' diff --git a/v2/openapi/fb-provider-transfer-api.yaml b/v2/openapi/fb-provider-transfer-api.yaml index bb686e83..47b46265 100644 --- a/v2/openapi/fb-provider-transfer-api.yaml +++ b/v2/openapi/fb-provider-transfer-api.yaml @@ -244,6 +244,14 @@ paths: description: > Retrieves a paginated list of all withdrawal transactions for the specified account. Withdrawals are sorted by creation time and include all types of withdrawal operations. + + If a withdrawal is in a terminal state (succeeded or failed), and it has an optional + destination.referenceId property (not all transfer methods have this property), then this + property MUST contain a valid value, despite it being defined as optional in the schema. + + Blockchain withdrawals in status succeeded, MUST contain destination.blockchainTxId property + with a valid value (e.g., transaction hash), despite it being defined as optional in the + schema. tags: [ transfers ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -274,6 +282,11 @@ paths: description: > Retrieves detailed information about a specific withdrawal transaction, including status, amounts, fees, destination details, and processing information. + + For Peer, Fiat and other transfer methods that define a `referenceId` on the destination, + this property is expected to become mandatory (non-empty) when the transaction is in a + finalized state (succeeded or failed), although it is currently indicated as optional in the schema. + For blockchain withdrawals, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the destination is required and must be non-empty. tags: [ transfers ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -305,6 +318,7 @@ paths: description: > Retrieves a paginated list of withdrawal transactions sent over public blockchains. Includes cryptocurrency transfers to external blockchain addresses, sorted by creation time. + On success (status succeeded), the destination `blockchainTxId` (transaction hash) is required and must be non-empty. tags: [ transfersBlockchain ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -340,7 +354,9 @@ paths: post: operationId: createBlockchainWithdrawal summary: Create new withdrawal over public blockchain - description: Should reject any non blockchain withdrawal request. + description: > + Should reject any non blockchain withdrawal request. + In the response, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the destination is required and must be non-empty. tags: [ transfersBlockchain ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -378,6 +394,9 @@ paths: description: > Retrieves a paginated list of fiat currency withdrawal transactions. Includes traditional banking transfers and wire transfers, sorted by creation time. + + The `referenceId` on the destination is expected to become mandatory (non-empty) when the + transaction is in a finalized state (succeeded or failed), although it is optional in the schema. tags: [ transfersFiat ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -413,7 +432,10 @@ paths: post: operationId: createFiatWithdrawal summary: Create new fiat withdrawal - description: Should reject any non fiat withdrawal request. + description: > + Should reject any non fiat withdrawal request. + In the response, `referenceId` on the destination is expected to become mandatory (non-empty) + when the transaction reaches a finalized state (succeeded or failed), although optional in the schema. tags: [ transfersFiat ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -451,6 +473,9 @@ paths: description: > Retrieves a paginated list of withdrawal transactions sent to peer accounts. Includes transfers to other accounts within the same provider ecosystem, sorted by creation time. + + The `referenceId` on the destination is expected to become mandatory (non-empty) when the + transaction is in a finalized state (succeeded or failed), although it is optional in the schema. tags: [ transfersPeerAccounts ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -487,7 +512,10 @@ paths: post: operationId: createPeerAccountWithdrawal summary: Create new withdrawal to a peer account - description: Should reject any non peer acount withdrawal request. + description: > + Should reject any non peer acount withdrawal request. + In the response, `referenceId` on the destination is expected to become mandatory (non-empty) + when the transaction reaches a finalized state (succeeded or failed), although optional in the schema. tags: [ transfersPeerAccounts ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -600,6 +628,11 @@ paths: description: > Retrieves a paginated list of all deposit transactions for the specified account. Deposits are sorted by creation time in descending order and include all types of deposit operations. + + For Peer, Fiat and other transfer methods that define a `referenceId` on the source, + this property is expected to become mandatory (non-empty) when the transaction is in a + finalized state (succeeded or failed), although it is currently indicated as optional in the schema. + For deposits with a blockchain source, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the source is required and must be non-empty. tags: [ transfers ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -639,6 +672,11 @@ paths: description: > Retrieves detailed information about a specific deposit transaction, including status, amounts, source details, confirmation information, and processing details. + + For Peer, Fiat and other transfer methods that define a `referenceId` on the source, + this property is expected to become mandatory (non-empty) when the transaction is in a + finalized state (succeeded or failed), although it is currently indicated as optional in the schema. + For deposits with a blockchain source, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the source is required and must be non-empty. tags: [ transfers ] parameters: - $ref: '#/x-header-params/X-FBAPI-KEY' @@ -1603,12 +1641,17 @@ components: PublicBlockchainTransaction: type: object + description: >- + Blockchain transaction details. When the withdrawal or deposit has succeeded, + `blockchainTxId` (transaction hash) is required and must be non-empty, although + it is indicated as optional in the schema. allOf: - $ref: '#/components/schemas/PublicBlockchainTransactionDestination' - type: object properties: blockchainTxId: type: string + description: Transaction hash on the blockchain. Required (non-empty) when the transaction has succeeded. PeerAccountTransferCapability: type: object diff --git a/v2/openapi/fb-unified-openapi.yaml b/v2/openapi/fb-unified-openapi.yaml index 4679ae14..877d5ad7 100644 --- a/v2/openapi/fb-unified-openapi.yaml +++ b/v2/openapi/fb-unified-openapi.yaml @@ -4,7 +4,7 @@ servers: url: http://0.0.0.0:8000 info: title: Fireblocks Provider Connectivity API v2 - version: 0.5.0 + version: 0.5.1 x-logo: url: doc-assets/fireblocks-logo-lockup-network-navy.png altText: Fireblocks logo @@ -14,7 +14,8 @@ info: license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html - description: Placeholder for automatic documentation injection from README.md + description: + $ref: README.md tags: - name: capabilities description: Server capabilities discovery operations. @@ -781,6 +782,8 @@ paths: summary: Get list of withdrawals sorted by creation time description: | Retrieves a paginated list of all withdrawal transactions for the specified account. Withdrawals are sorted by creation time and include all types of withdrawal operations. + If a withdrawal is in a terminal state (succeeded or failed), and it has an optional destination.referenceId property (not all transfer methods have this property), then this property MUST contain a valid value, despite it being defined as optional in the schema. + Blockchain withdrawals in status succeeded, MUST contain destination.blockchainTxId property with a valid value (e.g., transaction hash), despite it being defined as optional in the schema. tags: - transfers parameters: @@ -810,6 +813,7 @@ paths: summary: Get withdrawal details description: | Retrieves detailed information about a specific withdrawal transaction, including status, amounts, fees, destination details, and processing information. + For Peer, Fiat and other transfer methods that define a `referenceId` on the destination, this property is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is currently indicated as optional in the schema. For blockchain withdrawals, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the destination is required and must be non-empty. tags: - transfers parameters: @@ -839,7 +843,7 @@ paths: operationId: getBlockchainWithdrawals summary: Get list of withdrawals over public blockchains sorted by creation time description: | - Retrieves a paginated list of withdrawal transactions sent over public blockchains. Includes cryptocurrency transfers to external blockchain addresses, sorted by creation time. + Retrieves a paginated list of withdrawal transactions sent over public blockchains. Includes cryptocurrency transfers to external blockchain addresses, sorted by creation time. On success (status succeeded), the destination `blockchainTxId` (transaction hash) is required and must be non-empty. tags: - transfersBlockchain parameters: @@ -877,7 +881,8 @@ paths: post: operationId: createBlockchainWithdrawal summary: Create new withdrawal over public blockchain - description: Should reject any non blockchain withdrawal request. + description: | + Should reject any non blockchain withdrawal request. In the response, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the destination is required and must be non-empty. tags: - transfersBlockchain parameters: @@ -914,6 +919,7 @@ paths: summary: Get list of fiat withdrawals sorted by creation time description: | Retrieves a paginated list of fiat currency withdrawal transactions. Includes traditional banking transfers and wire transfers, sorted by creation time. + The `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is optional in the schema. tags: - transfersFiat parameters: @@ -951,7 +957,8 @@ paths: post: operationId: createFiatWithdrawal summary: Create new fiat withdrawal - description: Should reject any non fiat withdrawal request. + description: | + Should reject any non fiat withdrawal request. In the response, `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction reaches a finalized state (succeeded or failed), although optional in the schema. tags: - transfersFiat parameters: @@ -988,6 +995,7 @@ paths: summary: Get list of withdrawals to peer accounts, sorted by creation time description: | Retrieves a paginated list of withdrawal transactions sent to peer accounts. Includes transfers to other accounts within the same provider ecosystem, sorted by creation time. + The `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is optional in the schema. tags: - transfersPeerAccounts parameters: @@ -1025,7 +1033,8 @@ paths: post: operationId: createPeerAccountWithdrawal summary: Create new withdrawal to a peer account - description: Should reject any non peer acount withdrawal request. + description: | + Should reject any non peer acount withdrawal request. In the response, `referenceId` on the destination is expected to become mandatory (non-empty) when the transaction reaches a finalized state (succeeded or failed), although optional in the schema. tags: - transfersPeerAccounts parameters: @@ -1136,6 +1145,7 @@ paths: summary: Get list of deposits sorted by creation time in a descending order description: | Retrieves a paginated list of all deposit transactions for the specified account. Deposits are sorted by creation time in descending order and include all types of deposit operations. + For Peer, Fiat and other transfer methods that define a `referenceId` on the source, this property is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is currently indicated as optional in the schema. For deposits with a blockchain source, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the source is required and must be non-empty. tags: - transfers parameters: @@ -1175,6 +1185,7 @@ paths: summary: Get deposit details description: | Retrieves detailed information about a specific deposit transaction, including status, amounts, source details, confirmation information, and processing details. + For Peer, Fiat and other transfer methods that define a `referenceId` on the source, this property is expected to become mandatory (non-empty) when the transaction is in a finalized state (succeeded or failed), although it is currently indicated as optional in the schema. For deposits with a blockchain source, when the transaction has succeeded, `blockchainTxId` (transaction hash) on the source is required and must be non-empty. tags: - transfers parameters: @@ -4307,12 +4318,14 @@ components: $ref: '#/components/schemas/PositiveAmount' PublicBlockchainTransaction: type: object + description: Blockchain transaction details. When the withdrawal or deposit has succeeded, `blockchainTxId` (transaction hash) is required and must be non-empty, although it is indicated as optional in the schema. allOf: - $ref: '#/components/schemas/PublicBlockchainTransactionDestination' - type: object properties: blockchainTxId: type: string + description: Transaction hash on the blockchain. Required (non-empty) when the transaction has succeeded. PeerAccountTransferCapability: type: object required: