Skip to content

fix(sdk-coin-icp): parse certificate to detect canister rejections on withdrawal#9344

Open
bitgo-ai-agent-dev[bot] wants to merge 1 commit into
masterfrom
spt-114-icp-withdrawal-fix
Open

fix(sdk-coin-icp): parse certificate to detect canister rejections on withdrawal#9344
bitgo-ai-agent-dev[bot] wants to merge 1 commit into
masterfrom
spt-114-icp-withdrawal-fix

Conversation

@bitgo-ai-agent-dev

@bitgo-ai-agent-dev bitgo-ai-agent-dev Bot commented Jul 24, 2026

Copy link
Copy Markdown

What

  • Add ICP labeled hash tree traversal to Utils (lookupPathInTree, extractRequestStatusFromCertificate) to decode the certificate returned by the ICP v3 /call endpoint
  • Update broadcastTransaction in icp.ts to inspect the certificate's request_status subtree after receiving status: 'replied' — throws with the canister's reject_message if the inner status is rejected
  • Add IcpCertificate, IcpHashTree types and REQUEST_STATUS_REPLIED / REQUEST_STATUS_REJECTED constants to iface.ts
  • Replace the test broadcast response fixture with a minimal success response; rename the original rejected-certificate fixture to PublicNodeApiBroadcastResponseRejected
  • Add a new test asserting that canister rejections (e.g. insufficient funds) are surfaced as errors

Why

  • The ICP HTTP API v3 returns HTTP 200 with outer status: 'replied' even when the canister rejects the call (e.g. insufficient funds). The actual outcome is encoded inside a CBOR certificate in the response body.
  • Previously, broadcastTransaction only checked the outer status and treated every replied response as a success. This caused ICP withdrawals rejected by the ledger to be silently reported as successful by the BitGo SDK, which is the root cause of the reported API failure (COINS-1257).

Test plan

  • test/unit/transactionBuilder/transactionRecover.ts — all 94 tests pass including new case
  • should fail to recover if canister rejects the transaction (e.g. insufficient funds) — verifies the rejected certificate fixture now throws

Ticket: COINS-1257

@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the spt-114-icp-withdrawal-fix branch from 2d414a4 to eb0c4ad Compare July 24, 2026 00:37
@linear-code

linear-code Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

COINS-1257

The ICP /api/v3/canister/call endpoint returns HTTP 200 with
outer status='replied' even when the canister rejects the
transaction (e.g. insufficient funds). The rejection details
are encoded in the certificate's request_status subtree.

Previously, broadcastTransaction only checked the outer status
field and treated any 'replied' response as a success. This
caused silent failures: withdrawals that were rejected by the
ICP ledger (e.g. due to insufficient balance) were reported as
successful by the SDK.

This fix adds ICP labeled hash tree traversal to
extract the actual request status from the certificate. When
the certificate contains request_status.status='rejected', the
broadcast now throws with the canister's reject_message,
surfacing the real failure to callers.

Changes:
- Add IcpCertificate, IcpHashTree types and REQUEST_STATUS_*
  constants to iface.ts
- Add lookupPathInTree, extractRequestStatusFromCertificate,
  and helper tree-traversal methods to Utils class
- Update broadcastTransaction to decode the certificate and
  throw on canister rejection
- Replace the test broadcast response fixture with a minimal
  success response; rename the original rejected fixture to
  PublicNodeApiBroadcastResponseRejected
- Add test case that verifies canister rejections are surfaced

Ticket: COINS-1257
Session-Id: c40a0622-f3d1-48cc-82a2-5d3debf68691
Task-Id: b2e68cd6-bb53-4c2c-b0b6-f8c4e7f3d652
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the spt-114-icp-withdrawal-fix branch from eb0c4ad to 3716514 Compare July 24, 2026 16:06
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot marked this pull request as ready for review July 24, 2026 16:06
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot requested review from a team as code owners July 24, 2026 16:06
@ralph-bitgo
ralph-bitgo Bot force-pushed the spt-114-icp-withdrawal-fix branch from 3716514 to 65f87fa Compare July 24, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants