Skip to content

refactor(dapi-client)!: expose Uint8Array instead of Buffer in public API#3675

Closed
PastaPastaPasta wants to merge 2 commits into
dashpay:v3.1-devfrom
PastaPastaPasta:claude/esm-2-uint8array
Closed

refactor(dapi-client)!: expose Uint8Array instead of Buffer in public API#3675
PastaPastaPasta wants to merge 2 commits into
dashpay:v3.1-devfrom
PastaPastaPasta:claude/esm-2-uint8array

Conversation

@PastaPastaPasta
Copy link
Copy Markdown
Member

Summary

Replaces Buffer with Uint8Array across @dashevo/dapi-client's public API. Adds a small lib/utils/bytes.js helper for hex/base64/concat operations. Package stays CJS — that conversion happens in PR 3.

This is PR 2 of 5 in the stacked series. Depends on #3674.

Why

Removes Buffer from the dapi-client surface so consumers don't need a Buffer polyfill in browser bundles. Buffer is Node-specific; Uint8Array works everywhere.

What changes

dapi-client lib/

  • New lib/utils/bytes.js: hexToBytes, bytesToHex, base64ToBytes, bytesToBase64, concatBytes, bytesEqual (CJS exports).
  • All Buffer.* call sites converted per the translation table in the commit message.
  • Two production exceptions where Buffer is retained:
    • BlockHeadersReadernew BlockHeader(Buffer.from(header)) because dashcore-lib's BufferReader needs .readInt32LE.
    • GetIdentitiesContractKeysResponseIdentifier.from(Buffer.from(entry.getIdentityId())) because wasm-dpp's Identifier explicitly requires Node Buffer.

createGrpcTransportError

Restored dual-format handling that Buffer.from(x, 'base64') provided implicitly: typeof x === 'string' ? base64ToBytes(x) : new Uint8Array(x) for the three metadata-bin fields (grpc-js sends raw bytes; grpc-web sends base64 strings).

Tests

Spec files that construct expected protobuf requests now wrap .toBuffer() with new Uint8Array(...) to match production's normalization. Sinon's calledOnceWithExactly is strict about Buffer-vs-Uint8Array distinction.

Test plan

  • yarn workspace @dashevo/dapi-client run test:unit315 passing
  • yarn workspace @dashevo/wallet-lib run test:unit377 passing (no regression)
  • yarn workspace dash run test:unit60 passing (no regression)

Downstream consumers (wallet-lib, js-dash-sdk) exercise dapi-client mostly through mocks, so they didn't need updates here.

Breaking changes

Public response objects now expose Uint8Array instead of Buffer. Consumer code patterns that need updating:

Before After
response.field.toString('hex') bytesToHex(response.field)
response.field.toString('base64') bytesToBase64(response.field)
Buffer.isBuffer(response.field) response.field instanceof Uint8Array
response.field.slice(a, b) response.field.subarray(a, b)

In Node, Buffer extends Uint8Array, so anything that just reads bytes (passes to crypto, writes to a stream, length checks, indexed access) continues to work identically.

Stack

  • PR 1 — Cleanup (merged dependency)
  • ➡️ PR 2 — Buffer → Uint8Array (this PR)
  • PR 3 — dapi-client → ESM (dual-format CJS+ESM)
  • PR 4 — wallet-lib → ESM
  • PR 5 — js-dash-sdk + platform-test-suite → ESM

…ton/fetch/promisify shims

Non-breaking cleanup pass; package stays CJS, no public API changes, no consumer changes required.

dapi-client: replace winston with a minimal console-backed logger that preserves the same API (.error/.warn/.info/.verbose/.debug/.silly/.getForId). Drop node-fetch and the lib/test/bootstrap setimmediate shim — Node 18+ has both globally. Drop the https.Agent self-signed-TLS branch from requestJsonRpc (was Node-only; consumers wanting this must configure NODE_TLS_REJECT_UNAUTHORIZED at the app layer). Inline lodash/sample in ListDAPIAddressProvider. Add engines.node >=18.18. Remove dependencies: winston, node-fetch, lodash, bs58 (unused), node-inspect-extracted (unused). Remove devDeps: setimmediate.

dapi-grpc: inline the promisify shim in core/v0/web/CorePromiseClient.js and platform/v0/web/PlatformPromiseClient.js so the browser bundle no longer requires Node's util module. Both files document the shim so a future codegen regen does not silently reintroduce require('util').
… API

Adds lib/utils/bytes.js helper (hexToBytes/bytesToHex/base64ToBytes/bytesToBase64/concatBytes/bytesEqual) and converts all Buffer.* call sites in dapi-client lib/ to Uint8Array, with corresponding test updates. Package stays CJS.

Production exceptions where Buffer is retained: BlockHeadersReader passes Buffer to dashcore-lib's BlockHeader (its BufferReader needs .readInt32LE), and GetIdentitiesContractKeysResponse passes Buffer to wasm-dpp's Identifier.from (it explicitly requires Node Buffer).

createGrpcTransportError now handles both raw bytes (grpc-js path) and base64 strings (grpc-web path) for drive-error-data-bin, stack-bin, and dash-serialized-consensus-error-bin metadata fields, restoring the dual-format behavior that Buffer.from(x, 'base64') used to provide implicitly.

Test updates: spec files that construct expected protobuf requests now wrap .toBuffer() with new Uint8Array(...) to match production's normalization (sinon calledOnceWithExactly distinguishes Buffer from plain Uint8Array).

Breaking change for direct consumers: response object byte fields are now Uint8Array. Callers that do response.field.toString('hex') will fail — use bytesToHex(response.field) from lib/utils/bytes instead. Buffer.isBuffer(response.field) now returns false; use response.field instanceof Uint8Array.

Test results: dapi-client 315/315, wallet-lib 377/377, js-dash-sdk 60/60 — downstream consumers continue passing without modification (they exercise dapi-client mostly via mocks).
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

Warning

Rate limit exceeded

@PastaPastaPasta has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 2 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c03988a3-02b5-4568-b2b0-b31ff738d279

📥 Commits

Reviewing files that changed from the base of the PR and between 6a3b904 and 0b8c68e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (75)
  • .pnp.cjs
  • packages/dapi-grpc/clients/core/v0/web/CorePromiseClient.js
  • packages/dapi-grpc/clients/platform/v0/web/PlatformPromiseClient.js
  • packages/js-dapi-client/lib/SimplifiedMasternodeListProvider/SimplifiedMasternodeListProvider.js
  • packages/js-dapi-client/lib/dapiAddressProvider/ListDAPIAddressProvider.js
  • packages/js-dapi-client/lib/index.js
  • packages/js-dapi-client/lib/logger/index.js
  • packages/js-dapi-client/lib/methods/core/getBlockByHashFactory.js
  • packages/js-dapi-client/lib/methods/core/getBlockByHeightFactory.js
  • packages/js-dapi-client/lib/methods/core/getBlockchainStatusFactory.js
  • packages/js-dapi-client/lib/methods/core/getMasternodeStatusFactory.js
  • packages/js-dapi-client/lib/methods/core/getTransaction/GetTransactionResponse.js
  • packages/js-dapi-client/lib/methods/core/subscribeToBlockHeadersWithChainLocksFactory.js
  • packages/js-dapi-client/lib/methods/core/subscribeToTransactionsWithProofsFactory.js
  • packages/js-dapi-client/lib/methods/platform/getDataContract/GetDataContractResponse.js
  • packages/js-dapi-client/lib/methods/platform/getDataContract/getDataContractFactory.js
  • packages/js-dapi-client/lib/methods/platform/getDataContractHistory/getDataContractHistoryFactory.js
  • packages/js-dapi-client/lib/methods/platform/getDocuments/GetDocumentsResponse.js
  • packages/js-dapi-client/lib/methods/platform/getDocuments/getDocumentsFactory.js
  • packages/js-dapi-client/lib/methods/platform/getIdentitiesContractKeys/GetIdentitiesContractKeysResponse.js
  • packages/js-dapi-client/lib/methods/platform/getIdentitiesContractKeys/getIdentitiesContractKeysFactory.js
  • packages/js-dapi-client/lib/methods/platform/getIdentity/GetIdentityResponse.js
  • packages/js-dapi-client/lib/methods/platform/getIdentity/getIdentityFactory.js
  • packages/js-dapi-client/lib/methods/platform/getIdentityBalance/getIdentityBalanceFactory.js
  • packages/js-dapi-client/lib/methods/platform/getIdentityByPublicKeyHash/GetIdentityByPublicKeyHashResponse.js
  • packages/js-dapi-client/lib/methods/platform/getIdentityContractNonce/getIdentityContractNonceFactory.js
  • packages/js-dapi-client/lib/methods/platform/getIdentityKeys/getIdentityKeysFactory.js
  • packages/js-dapi-client/lib/methods/platform/getIdentityNonce/getIdentityNonceFactory.js
  • packages/js-dapi-client/lib/methods/platform/getProtocolVersionUpgradeVoteStatus/GetProtocolVersionUpgradeVoteStatusResponse.js
  • packages/js-dapi-client/lib/methods/platform/getProtocolVersionUpgradeVoteStatus/getProtocolVersionUpgradeVoteStatusFactory.js
  • packages/js-dapi-client/lib/methods/platform/getStatus/GetStatusResponse.js
  • packages/js-dapi-client/lib/methods/platform/response/Proof.js
  • packages/js-dapi-client/lib/methods/platform/waitForStateTransitionResult/WaitForStateTransitionResultResponse.js
  • packages/js-dapi-client/lib/test/bootstrap.js
  • packages/js-dapi-client/lib/test/fixtures/getProofFixture.js
  • packages/js-dapi-client/lib/test/fixtures/getStatusFixture.js
  • packages/js-dapi-client/lib/test/mocks/mockHeadersChain.js
  • packages/js-dapi-client/lib/transport/GrpcTransport/createGrpcTransportError.js
  • packages/js-dapi-client/lib/transport/JsonRpcTransport/requestJsonRpc.js
  • packages/js-dapi-client/lib/utils/bytes.js
  • packages/js-dapi-client/package.json
  • packages/js-dapi-client/polyfills/fetch-polyfill.js
  • packages/js-dapi-client/test/integration/methods/core/CoreMethodsFacade.spec.js
  • packages/js-dapi-client/test/integration/methods/platform/PlatformMethodsFacade.spec.js
  • packages/js-dapi-client/test/unit/methods/core/broadcastTransactionFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/getBlockByHashFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/getBlockByHeightFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/getBlockchainStatusFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/getMasternodeStatusFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/getTransaction/GetTransactionResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/core/getTransaction/getTransactionFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/subscribeToBlockHeadersWithChainLocksFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/core/subscribeToTransactionsWithProofsFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getDataContract/GetDataContractResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getDataContract/getDataContractFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/getDataContractHistoryFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getDocuments/GetDocumentsResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getDocuments/getDocumentsFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentitiesContractKeys/getIdentitiesContractKeysFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentity/GetIdentityResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentity/getIdentityFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityBalance/getIdentityBalanceFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityByPublicKeyHash/GetIdentityByPublicKeyHashResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityByPublicKeyHash/getIdentityByPublicKeyHashFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityContractNonce/GetIdentityContractNonce.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityContractNonce/getIdentityContractNonceFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityKeys/GetIdentityKeys.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityKeys/getIdentityKeysFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityNonce/GetIdentityNonce.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getIdentityNonce/getIdentityNonceFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getProtocolVersionUpgradeVoteStatus/GetProtocolVersionUpgradeVoteStatusResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getProtocolVersionUpgradeVoteStatus/getProtocolVersionUpgradeVoteStatusFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getStatus/GetStatusResponse.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/getStatus/getStatusFactory.spec.js
  • packages/js-dapi-client/test/unit/methods/platform/waitForStateTransitionResult/waitForStateTransitionResultFactory.spec.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@PastaPastaPasta
Copy link
Copy Markdown
Member Author

Closing — reopening as upstream→upstream so CI runs against secrets/runners. New PR link will be added shortly.

@PastaPastaPasta
Copy link
Copy Markdown
Member Author

Reopened as #3680 (upstream→upstream so CI runs against repo secrets/runners).

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.

1 participant