From 7164e202e99fc31c1aa3351e8a31f8006493e759 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:00:22 +0000 Subject: [PATCH 01/31] chore: version packages --- .changeset/flat-teams-design.md | 5 ----- .changeset/fruity-clouds-serve.md | 5 ----- .changeset/heavy-eggs-sell.md | 5 ----- .changeset/hot-lions-bow.md | 5 ----- .changeset/quick-eyes-rest.md | 5 ----- .changeset/seven-hornets-shout.md | 5 ----- .changeset/soft-plums-say.md | 5 ----- .changeset/solid-rules-run.md | 5 ----- .changeset/some-bottles-sleep.md | 5 ----- .changeset/yellow-snails-divide.md | 5 ----- packages/api/CHANGELOG.md | 27 +++++++++++++++++++++++++++ packages/api/package.json | 2 +- 12 files changed, 28 insertions(+), 51 deletions(-) delete mode 100644 .changeset/flat-teams-design.md delete mode 100644 .changeset/fruity-clouds-serve.md delete mode 100644 .changeset/heavy-eggs-sell.md delete mode 100644 .changeset/hot-lions-bow.md delete mode 100644 .changeset/quick-eyes-rest.md delete mode 100644 .changeset/seven-hornets-shout.md delete mode 100644 .changeset/soft-plums-say.md delete mode 100644 .changeset/solid-rules-run.md delete mode 100644 .changeset/some-bottles-sleep.md delete mode 100644 .changeset/yellow-snails-divide.md diff --git a/.changeset/flat-teams-design.md b/.changeset/flat-teams-design.md deleted file mode 100644 index 9f31810d..00000000 --- a/.changeset/flat-teams-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@oaknetwork/api": patch ---- - -chore: enhance httpClient to include Oak-Version in headers#18 diff --git a/.changeset/fruity-clouds-serve.md b/.changeset/fruity-clouds-serve.md deleted file mode 100644 index 62d49605..00000000 --- a/.changeset/fruity-clouds-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@oaknetwork/api': minor ---- - -Add typed environment configuration and @SandboxOnly decorator diff --git a/.changeset/heavy-eggs-sell.md b/.changeset/heavy-eggs-sell.md deleted file mode 100644 index b58541e9..00000000 --- a/.changeset/heavy-eggs-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@oaknetwork/api': patch ---- - -Add TSDoc documentation to SDK public API diff --git a/.changeset/hot-lions-bow.md b/.changeset/hot-lions-bow.md deleted file mode 100644 index c552d50f..00000000 --- a/.changeset/hot-lions-bow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@oaknetwork/api': minor ---- - -Add integration tests for WebhookService covering CRUD operations, toggle, and notifications endpoints diff --git a/.changeset/quick-eyes-rest.md b/.changeset/quick-eyes-rest.md deleted file mode 100644 index 47c1aa71..00000000 --- a/.changeset/quick-eyes-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@oaknetwork/api': minor ---- - -Fix httpClient to return ApiError for non-JSON API error responses diff --git a/.changeset/seven-hornets-shout.md b/.changeset/seven-hornets-shout.md deleted file mode 100644 index 2fc0fb2e..00000000 --- a/.changeset/seven-hornets-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@oaknetwork/api": minor ---- - -added sync and balance API diff --git a/.changeset/soft-plums-say.md b/.changeset/soft-plums-say.md deleted file mode 100644 index 6f3a0641..00000000 --- a/.changeset/soft-plums-say.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@oaknetwork/api": major ---- - -Updated types of all request response diff --git a/.changeset/solid-rules-run.md b/.changeset/solid-rules-run.md deleted file mode 100644 index c7add307..00000000 --- a/.changeset/solid-rules-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@oaknetwork/api": major ---- - -updated customer test for US clients, added test for transfer diff --git a/.changeset/some-bottles-sleep.md b/.changeset/some-bottles-sleep.md deleted file mode 100644 index e616cd83..00000000 --- a/.changeset/some-bottles-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@oaknetwork/api': minor ---- - -Add Payment Method Service Integration Tests diff --git a/.changeset/yellow-snails-divide.md b/.changeset/yellow-snails-divide.md deleted file mode 100644 index 9d1ba669..00000000 --- a/.changeset/yellow-snails-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@oaknetwork/api": major ---- - -Refactor httpClient to return Result and centralize error handling (breaking change). diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index 95994936..adcec9a1 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -1,5 +1,32 @@ # @oaknetwork/api +## 1.0.0 + +### Major Changes + +### Major Changes + +- Updated types of all request response +- updated customer test for US clients, added test for transfer +- Refactor httpClient to return Result and centralize error handling (breaking change). + +### Minor Changes + +### Minor Changes + +- Add typed environment configuration and @SandboxOnly decorator +- Add integration tests for WebhookService covering CRUD operations, toggle, and notifications endpoints +- Fix httpClient to return ApiError for non-JSON API error responses +- added sync and balance API +- Add Payment Method Service Integration Tests + +### Patch Changes + +### Patch Changes + +- chore: enhance httpClient to include Oak-Version in headers#18 +- Add TSDoc documentation to SDK public API + ## 1.1.0 ### Minor Changes diff --git a/packages/api/package.json b/packages/api/package.json index 9e726bc0..5eeacd82 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@oaknetwork/api", - "version": "0.1.0", + "version": "1.0.0", "description": "TypeScript SDK for Crowdsplit API", "publishConfig": { "access": "public" From deea48512af42f823a08dbc97467a98f73e3aca1 Mon Sep 17 00:00:00 2001 From: lucas vinhas Date: Thu, 26 Feb 2026 11:35:17 -0300 Subject: [PATCH 02/31] chore: update CHANGELOG to reflect initial release of Oak SDK and remove outdated entries --- packages/api/CHANGELOG.md | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index adcec9a1..426d779e 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -4,44 +4,7 @@ ### Major Changes -### Major Changes - -- Updated types of all request response -- updated customer test for US clients, added test for transfer -- Refactor httpClient to return Result and centralize error handling (breaking change). - -### Minor Changes - -### Minor Changes - -- Add typed environment configuration and @SandboxOnly decorator -- Add integration tests for WebhookService covering CRUD operations, toggle, and notifications endpoints -- Fix httpClient to return ApiError for non-JSON API error responses -- added sync and balance API -- Add Payment Method Service Integration Tests - -### Patch Changes - -### Patch Changes - -- chore: enhance httpClient to include Oak-Version in headers#18 -- Add TSDoc documentation to SDK public API - -## 1.1.0 - -### Minor Changes - -### Minor Changes - -- testing changeset for releases - -## 1.0.0 - -### Major Changes - -### Major Changes - -- Adopt Result responses across API services and auth flows. +- Initial release of Oak SDK ## 0.1.0 From e7d46116fafa6f9815901158a09c11ebf689b562 Mon Sep 17 00:00:00 2001 From: lucas vinhas Date: Thu, 26 Feb 2026 11:40:03 -0300 Subject: [PATCH 03/31] chore: add initial changeset file for tracking updates --- .changeset/humble-tools-travel.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/humble-tools-travel.md diff --git a/.changeset/humble-tools-travel.md b/.changeset/humble-tools-travel.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/humble-tools-travel.md @@ -0,0 +1,2 @@ +--- +--- From 51d418961836f9aaf1fad8bd1fd65bf751ba41fc Mon Sep 17 00:00:00 2001 From: lucas vinhas Date: Thu, 26 Feb 2026 13:39:40 -0300 Subject: [PATCH 04/31] chore: bump version to 1.0.1 in package.json --- .changeset/many-laws-dance.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/many-laws-dance.md diff --git a/.changeset/many-laws-dance.md b/.changeset/many-laws-dance.md new file mode 100644 index 00000000..e214773b --- /dev/null +++ b/.changeset/many-laws-dance.md @@ -0,0 +1,5 @@ +--- +"@oaknetwork/api": minor +--- + +Initial release of SDK v1.0.1. From b38f1e45e212771d0c73a462c7dc5f5834f164a6 Mon Sep 17 00:00:00 2001 From: lucas vinhas Date: Thu, 26 Feb 2026 13:44:41 -0300 Subject: [PATCH 05/31] chore: update version type for @oaknetwork/api to patch in changeset --- .changeset/many-laws-dance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/many-laws-dance.md b/.changeset/many-laws-dance.md index e214773b..f468ddfc 100644 --- a/.changeset/many-laws-dance.md +++ b/.changeset/many-laws-dance.md @@ -1,5 +1,5 @@ --- -"@oaknetwork/api": minor +"@oaknetwork/api": patch --- Initial release of SDK v1.0.1. From 062f70770ca98631538bd1926b068d99c270cba5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:27:16 +0000 Subject: [PATCH 06/31] chore: version packages --- .changeset/humble-tools-travel.md | 2 -- .changeset/many-laws-dance.md | 5 ----- packages/api/CHANGELOG.md | 8 ++++++++ packages/api/package.json | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) delete mode 100644 .changeset/humble-tools-travel.md delete mode 100644 .changeset/many-laws-dance.md diff --git a/.changeset/humble-tools-travel.md b/.changeset/humble-tools-travel.md deleted file mode 100644 index a845151c..00000000 --- a/.changeset/humble-tools-travel.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/many-laws-dance.md b/.changeset/many-laws-dance.md deleted file mode 100644 index f468ddfc..00000000 --- a/.changeset/many-laws-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@oaknetwork/api": patch ---- - -Initial release of SDK v1.0.1. diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index 426d779e..0b1cd15f 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -1,5 +1,13 @@ # @oaknetwork/api +## 1.0.1 + +### Patch Changes + +### Patch Changes + +- Initial release of SDK v1.0.1. + ## 1.0.0 ### Major Changes diff --git a/packages/api/package.json b/packages/api/package.json index 5eeacd82..9f86af04 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@oaknetwork/api", - "version": "1.0.0", + "version": "1.0.1", "description": "TypeScript SDK for Crowdsplit API", "publishConfig": { "access": "public" From 841fca133c693bbff6aeef88dd2612a9636ee9d1 Mon Sep 17 00:00:00 2001 From: Rafa Gomes <565337+0xrafasec@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:58:01 -0300 Subject: [PATCH 07/31] Add MIT License to the project --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f27005d4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Oak Network + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 093c7f387b5a8aa699633707db25f6c6f4d024b3 Mon Sep 17 00:00:00 2001 From: Rafa Gomes <565337+0xrafasec@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:00:49 -0300 Subject: [PATCH 08/31] Update license section to link to LICENSE file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7871cfc0..a8095c18 100644 --- a/README.md +++ b/README.md @@ -589,7 +589,7 @@ Before submitting PR: ## 📄 License -MIT +[MIT LICENSE](LICENSE) --- From 751c0e2226eb28cfbe6e8390a7eb247ca701ae43 Mon Sep 17 00:00:00 2001 From: Rafa Gomes <565337+0xrafasec@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:07:42 -0300 Subject: [PATCH 09/31] Fix formatting by adding newline at end of file Add newline at the end of the dependabot.yml file --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..d698d8d0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + From 8556c3c6400ecc9bcbaa6f48c52e77baaf3a9488 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 12:17:32 -0300 Subject: [PATCH 10/31] fix(ci): update Codecov file path in workflow configuration --- .github/workflows/codecov.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 32161fbb..de9e7d21 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -30,6 +30,5 @@ jobs: uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - files: packages/api/coverage/lcov.info + files: api/coverage/lcov.info fail_ci_if_error: false - continue-on-error: true From d8b22bf3dab12b3ae0fd94e3173f8783a2128349 Mon Sep 17 00:00:00 2001 From: Rafa Gomes <565337+0xrafasec@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:18:27 -0300 Subject: [PATCH 11/31] Add SECURITY.md for vulnerability reporting and best practices Added a comprehensive security policy document outlining supported versions, vulnerability reporting procedures, security best practices, and disclosure policies for the Oak SDK. --- SECURITY.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..afe95113 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,92 @@ +# Security Policy + +## Supported Versions + +We actively maintain and provide security updates for the following versions of `@oaknetwork/api`: + +| Version | Supported | +| ------- | ------------------ | +| 1.x | ✅ Active support | + +## Reporting a Vulnerability + +**Please do not report security vulnerabilities through public GitHub issues.** + +If you discover a vulnerability in the Oak SDK, we ask that you follow responsible disclosure practices and report it privately so we can address it before any public disclosure. + +### How to Report + +- **Email**: [security@oaknetwork.org](mailto:security@oaknetwork.org) +- **General support**: [support@oaknetwork.org](mailto:support@oaknetwork.org) +- **GitHub Private Advisories**: [Report a vulnerability](https://github.com/oak-network/sdk/security/advisories/new) + +When reporting, please include as much detail as possible: + +- A clear description of the vulnerability +- Steps to reproduce the issue +- The potential impact and attack surface +- Any proof-of-concept code (if available) +- The SDK version(s) affected + +### What to Expect + +| Timeline | Action | +| -------- | ------ | +| **Within 48 hours** | Acknowledgment of your report | +| **Within 7 days** | Initial severity assessment and triage | +| **Within 30 days** | A patch or mitigation plan for confirmed vulnerabilities | +| **Within 90 days** | Public disclosure (coordinated with reporter) | + +We follow **coordinated vulnerability disclosure (CVD)** principles. We will keep you informed throughout the process and aim to resolve confirmed vulnerabilities within 30 days. For complex issues, we may request an extension and will communicate transparently about the timeline. + +## Scope + +The following are **in scope** for vulnerability reports: + +- Authentication and token management flaws (`OAuth 2.0` client credentials flow) +- Webhook signature verification bypass or timing-attack vulnerabilities +- Credential or secret exposure through SDK APIs +- Dependency vulnerabilities with direct security impact on SDK consumers +- Type-safety issues that could lead to injection or data leakage + +The following are **out of scope**: + +- Vulnerabilities in the Oak Network backend API itself (please contact Oak Network directly) +- Issues in third-party dependencies without a clear exploit path through this SDK +- Denial-of-service attacks that require significant resources or special access +- Social engineering attacks + +## Security Best Practices for SDK Consumers + +To use the Oak SDK securely in your applications: + +- **Never hardcode credentials** — store `clientId` and `clientSecret` in environment variables +- **Never commit `.env` files** — add them to `.gitignore` +- **Always verify webhook signatures** — use `verifyWebhookSignature()` or `parseWebhookPayload()` before processing any webhook event +- **Use separate credentials** for sandbox and production environments +- **Do not log or expose** `clientSecret` or access tokens in application logs +- **Keep the SDK updated** — subscribe to [GitHub releases](https://github.com/oak-network/sdk/releases) to stay informed about security patches + +## Security Features in This SDK + +- **OAuth 2.0 client credentials flow** with automatic token caching +- **`clientSecret` is not exposed** on the client config object (as of v0.2) +- **HMAC-SHA256 webhook signature verification** with timing-safe comparison to prevent timing attacks +- **Exponential backoff with jitter** on retries to mitigate thundering herd scenarios +- **Strict TypeScript types** with `unknown` for unvalidated external data + +## Disclosure Policy + +We are committed to working with security researchers and the community to ensure the safety of our SDK. Once a vulnerability is confirmed and a fix is available, we will: + +1. Release a patched version as soon as possible +2. Publish a [GitHub Security Advisory](https://github.com/oak-network/sdk/security/advisories) +3. Update the [CHANGELOG.md](./CHANGELOG.md) with details about the fix +4. Credit the reporter (unless they prefer to remain anonymous) + +We ask that reporters allow us up to **90 days** from initial report to public disclosure to give users time to update. + +## Contact + +For security-related inquiries, reach out to [security@oaknetwork.org](mailto:security@oaknetwork.org). +For general questions, visit [oaknetwork.org](https://oaknetwork.org) or open a [GitHub Discussion](https://github.com/oak-network/sdk/issues). From b40d789bc1984f27a722802e52899ffed30bce96 Mon Sep 17 00:00:00 2001 From: Rafa Gomes <565337+0xrafasec@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:21:13 -0300 Subject: [PATCH 12/31] Rename to Oak API SDK and add security section Updated project title and added security section. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a8095c18..1ee837a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Oak SDK Monorepo +# Oak API SDK > **Status**: Pre-launch development (Expected launch: March 2026) @@ -593,6 +593,10 @@ Before submitting PR: --- +## Security + +[SECURITY POLICIES](SECURITY.md) + ## 🔗 Links - [Oak Network Website](https://oaknetwork.org) From 12c25323ed6ccce3b57fe0ac2052be6395d89a2e Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 12:40:32 -0300 Subject: [PATCH 13/31] chore: add initial Codecov configuration file --- codecov.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..3e2c3a61 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,5 @@ +codecov: + branch: main + +fixes: + - "src/::packages/api/src/" From 539a755afb7ad68ad3fb8f708c955114ce44eb9a Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:09:38 -0300 Subject: [PATCH 14/31] fix(ci): correct Codecov file path in workflow configuration --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index de9e7d21..5e7299cc 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -30,5 +30,5 @@ jobs: uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - files: api/coverage/lcov.info + files: packages/api/coverage/lcov.info fail_ci_if_error: false From 488286525db0211a0c4475cbb4cfad1444557310 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:23:17 -0300 Subject: [PATCH 15/31] fix(ci): remove unnecessary colon from Codecov file path --- codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 3e2c3a61..c148ac4f 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,4 +2,4 @@ codecov: branch: main fixes: - - "src/::packages/api/src/" + - src/::packages/api/src/ From 1284e37d93cda0960d30271d4088cc00fdfde801 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:23:26 -0300 Subject: [PATCH 16/31] fix(ci): update CI workflow to include 'fix/codecov-badge' branch for push and pull request triggers --- .github/workflows/ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1edd7d42..01a19747 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,44 +2,44 @@ name: CI on: push: - branches: [main, develop] + branches: [main, develop, fix/codecov-badge] pull_request: - branches: [main, develop] + branches: [main, develop, fix/codecov-badge] jobs: build-and-test: runs-on: ubuntu-latest - + strategy: matrix: node-version: [18.x, 20.x, 24.x] - + steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - + - name: Setup pnpm uses: pnpm/action-setup@v4 with: run_install: false - + - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - cache: 'pnpm' - + cache: "pnpm" + - name: Install dependencies run: pnpm install --frozen-lockfile - name: Calculate next versions from changesets run: pnpm changeset:status - + - name: Build all packages run: pnpm -r --workspace-concurrency=Infinity --filter=!@oaknetwork/contracts build - + - name: Run tests with coverage (enforces 100% threshold) run: pnpm -r --workspace-concurrency=Infinity --filter=!@oaknetwork/contracts test --coverage env: @@ -47,7 +47,7 @@ jobs: CLIENT_ID: ${{ secrets.CLIENT_ID }} CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }} OAK_ENVIRONMENT: sandbox - + - name: Upload coverage reports uses: actions/upload-artifact@v4 if: always() @@ -56,6 +56,6 @@ jobs: path: | packages/*/coverage/ retention-days: 30 - + - name: Run lint run: pnpm -r --workspace-concurrency=Infinity --filter=!@oaknetwork/contracts lint From 8ea35a63c8a823dce5818026059f773170785cce Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:23:33 -0300 Subject: [PATCH 17/31] fix(ci): add checks for lcov.info file in Codecov workflow --- .github/workflows/codecov.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 5e7299cc..2e9d88b2 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -4,7 +4,7 @@ on: workflow_run: workflows: [CI] types: [completed] - branches: [main, develop] + branches: [main, develop, fix/codecov-badge] concurrency: group: codecov-${{ github.event.workflow_run.id }} @@ -26,9 +26,17 @@ jobs: run-id: ${{ github.event.workflow_run.id }} github-token: ${{ github.token }} + - name: Check lcov.info + run: | + echo "Checking where the file landed:" + ls -la + ls -la packages/api/coverage/ + echo "Reading the first 5 lines of code source mapped:" + grep "SF:" packages/api/coverage/lcov.info | head -n 5 + - name: Upload to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - files: packages/api/coverage/lcov.info + files: api/coverage/lcov.info fail_ci_if_error: false From 7691396c90f11ac2937162e6097609dd44d499ca Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:30:29 -0300 Subject: [PATCH 18/31] fix(ci): remove 'fix/codecov-badge' branch from Codecov workflow triggers --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 2e9d88b2..5e470c2b 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -4,7 +4,7 @@ on: workflow_run: workflows: [CI] types: [completed] - branches: [main, develop, fix/codecov-badge] + branches: [main, develop] concurrency: group: codecov-${{ github.event.workflow_run.id }} From a129b0f08d83cb829103649a59881963adcd7251 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:30:45 -0300 Subject: [PATCH 19/31] fix(ci): further refine CI workflow by removing 'fix/codecov-badge' branch from triggers --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01a19747..325ab01c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [main, develop, fix/codecov-badge] + branches: [main, develop] pull_request: - branches: [main, develop, fix/codecov-badge] + branches: [main, develop] jobs: build-and-test: From 6a6d2097881a3179cf5439605db5e9f52f802ddc Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:41:17 -0300 Subject: [PATCH 20/31] fix(ci): streamline Codecov workflow by correcting file paths for coverage checks --- .github/workflows/codecov.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 5e470c2b..7298f29d 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -29,10 +29,9 @@ jobs: - name: Check lcov.info run: | echo "Checking where the file landed:" - ls -la - ls -la packages/api/coverage/ + ls -la api/coverage/ echo "Reading the first 5 lines of code source mapped:" - grep "SF:" packages/api/coverage/lcov.info | head -n 5 + grep "SF:" api/coverage/lcov.info | head -n 5 - name: Upload to Codecov uses: codecov/codecov-action@v5 From 25d60e5ed5595043d0e237628661270d1be3f5f8 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:41:33 -0300 Subject: [PATCH 21/31] fix(ci): remove lcov.info checks from Codecov workflow to simplify configuration --- .github/workflows/codecov.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 7298f29d..de9e7d21 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -26,13 +26,6 @@ jobs: run-id: ${{ github.event.workflow_run.id }} github-token: ${{ github.token }} - - name: Check lcov.info - run: | - echo "Checking where the file landed:" - ls -la api/coverage/ - echo "Reading the first 5 lines of code source mapped:" - grep "SF:" api/coverage/lcov.info | head -n 5 - - name: Upload to Codecov uses: codecov/codecov-action@v5 with: From 348a1a5c3de82b3eaf5eadbc0b8ade00539f6a15 Mon Sep 17 00:00:00 2001 From: lucas vinhas Date: Fri, 27 Feb 2026 15:46:07 -0300 Subject: [PATCH 22/31] chore(ci): update npm version in release workflow to 11.11.0 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ce7b472c..a3bda145 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,7 @@ jobs: - name: Update npm for OIDC support if: steps.changesets.outputs.hasChangesets == 'false' run: | - npm install -g npm@10.9.2 + npm install -g npm@11.11.0 npm --version - name: Publish packages From b672f3ab0820c2419e4bb48b7cc124078ee3558e Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 15:50:58 -0300 Subject: [PATCH 23/31] docs: update CodeQL badge in README for consistency --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7871cfc0..60e940f7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > **Status**: Pre-launch development (Expected launch: March 2026) -[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/oak-network/sdk/badge)](https://scorecard.dev/viewer/?uri=github.com/oak-network/sdk) [![Codecov](https://codecov.io/github/oak-network/sdk/graph/badge.svg)](https://app.codecov.io/github/oak-network/sdk) [![CodeQL](https://img.shields.io/github/actions/workflow/status/oak-network/sdk/codeql.yml?label=CodeQL&logo=github)](https://github.com/oak-network/sdk/actions/workflows/codeql.yml) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/oak-network/sdk/badge)](https://scorecard.dev/viewer/?uri=github.com/oak-network/sdk) [![Codecov](https://codecov.io/github/oak-network/sdk/graph/badge.svg)](https://app.codecov.io/github/oak-network/sdk) [![CodeQL](https://github.com/oak-network/sdk/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/oak-network/sdk/actions/workflows/github-code-scanning/codeql) TypeScript SDK for the Oak Network Crowdsplit API. Build secure payment applications with type-safe interfaces, comprehensive error handling, and OAuth 2.0 authentication. @@ -437,9 +437,8 @@ const customerData: Customer.Request = { }; // Type-safe result handling -const result: Result = await crowdsplit.customers.create( - customerData, -); +const result: Result = + await crowdsplit.customers.create(customerData); if (result.ok) { const customer: Customer.Data = result.value.data; From 506b0e0e343eefbae46ac6f0da0299f29ff40817 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 16:04:14 -0300 Subject: [PATCH 24/31] fix(codecov): update path format in codecov.yml for consistency --- codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index c148ac4f..3e2c3a61 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,4 +2,4 @@ codecov: branch: main fixes: - - src/::packages/api/src/ + - "src/::packages/api/src/" From e903c31f1d67ead2a41f7c27f8a8f7e941997ffc Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 16:04:20 -0300 Subject: [PATCH 25/31] fix(ci): add checkout step to Codecov workflow for accurate coverage reporting --- .github/workflows/codecov.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index de9e7d21..1e114a4d 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -19,6 +19,11 @@ jobs: actions: read steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_sha }} + - name: Download coverage artifact uses: actions/download-artifact@v4 with: From c0a0d531a1366dcbb56bb05a3b8fd88bd37d667f Mon Sep 17 00:00:00 2001 From: fahmidareem3 Date: Sat, 28 Feb 2026 01:06:49 +0600 Subject: [PATCH 26/31] docs: update readme to follow the website doc --- README.md | 724 ++++++++++++++++++++++-------------------------------- 1 file changed, 295 insertions(+), 429 deletions(-) diff --git a/README.md b/README.md index 1ee837a8..ab15e5a3 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,36 @@ -# Oak API SDK - -> **Status**: Pre-launch development (Expected launch: March 2026) +# Oak Network SDK [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/oak-network/sdk/badge)](https://scorecard.dev/viewer/?uri=github.com/oak-network/sdk) [![Codecov](https://codecov.io/github/oak-network/sdk/graph/badge.svg)](https://app.codecov.io/github/oak-network/sdk) [![CodeQL](https://img.shields.io/github/actions/workflow/status/oak-network/sdk/codeql.yml?label=CodeQL&logo=github)](https://github.com/oak-network/sdk/actions/workflows/codeql.yml) -TypeScript SDK for the Oak Network Crowdsplit API. Build secure payment applications with type-safe interfaces, comprehensive error handling, and OAuth 2.0 authentication. +TypeScript SDK for the [Oak Network](https://www.oaknetwork.org/) payment API. Build secure payment applications with type-safe interfaces, a `Result` error handling pattern, automatic OAuth 2.0 authentication, and built-in retries. + +> **Full documentation** — [oaknetwork.org/docs/sdk/api-sdk/overview](https://www.oaknetwork.org/docs/sdk/api-sdk/overview) --- -## 📦 Packages +## Getting credentials + +To use the SDK you need a **Client ID** and **Client Secret**. Contact **[support@oaknetwork.org](mailto:support@oaknetwork.org)** to get your sandbox credentials. + +Create a `.env` file in your project root: + +```bash +CLIENT_ID=your-client-id +CLIENT_SECRET=your-client-secret +``` + +Install `dotenv` to load these automatically: `pnpm add dotenv`, then add `import 'dotenv/config'` at the top of your entry file. -- **[@oaknetwork/api](./packages/api)** - Core SDK for Crowdsplit API -- **@oaknetwork/contracts** - Smart contracts (placeholder, not in active development) +| Variable | Required | Description | +|---|---|---| +| `CLIENT_ID` | Yes | Your merchant client ID | +| `CLIENT_SECRET` | Yes | Your merchant client secret | + +> Use different credentials for sandbox and production. Never commit `.env` files or log secrets. --- -## 🚀 Quick Start +## Quick start ### Installation @@ -27,365 +42,358 @@ npm install @oaknetwork/api yarn add @oaknetwork/api ``` -### Basic Usage +**Requirements:** Node.js 18+, TypeScript 5.x recommended. + +### Basic usage ```typescript -import { createOakClient } from "@oaknetwork/api"; -import { Crowdsplit } from "@oaknetwork/api/products/crowdsplit"; +import 'dotenv/config'; +import { createOakClient, createCustomerService } from '@oaknetwork/api'; -// Create client const client = createOakClient({ - environment: "sandbox", // or "production" - clientId: process.env.OAK_CLIENT_ID, - clientSecret: process.env.OAK_CLIENT_SECRET, + environment: 'sandbox', + clientId: process.env.CLIENT_ID!, + clientSecret: process.env.CLIENT_SECRET!, }); -// Initialize Crowdsplit product -const crowdsplit = Crowdsplit(client); +const customers = createCustomerService(client); -// Create a customer -const customerResult = await crowdsplit.customers.create({ - email: "user@example.com", - first_name: "John", - last_name: "Doe", -}); +const result = await customers.list(); -if (customerResult.ok) { - console.log("Customer created:", customerResult.value.data.customer_id); +if (result.ok) { + console.log(result.value.data); } else { - console.error("Error:", customerResult.error.message); + console.error(result.error.message); } ``` +> See the full [Quickstart guide](https://www.oaknetwork.org/docs/sdk/api-sdk/quickstart) for a step-by-step walkthrough. + +--- + +## Services + +The SDK ships 10 service modules. Import the factory function for each service you need. + +| Service | Factory | What it does | +|---|---|---| +| [Customers](https://www.oaknetwork.org/docs/sdk/api-sdk/customers) | `createCustomerService(client)` | Create, get, list, update, sync, and check balances | +| [Payments](https://www.oaknetwork.org/docs/sdk/api-sdk/payments) | `createPaymentService(client)` | Create, confirm, cancel payments | +| [Payment Methods](https://www.oaknetwork.org/docs/sdk/api-sdk/payment-methods) | `createPaymentMethodService(client)` | Add, list, get, delete payment methods | +| [Webhooks](https://www.oaknetwork.org/docs/sdk/api-sdk/webhooks) | `createWebhookService(client)` | Register, manage, and monitor webhooks | +| [Transactions](https://www.oaknetwork.org/docs/sdk/api-sdk/transactions) | `createTransactionService(client)` | List, get, and settle transactions | +| [Transfers](https://www.oaknetwork.org/docs/sdk/api-sdk/transfers) | `createTransferService(client)` | Create provider transfers (Stripe, PagarMe, BRLA) | +| [Plans](https://www.oaknetwork.org/docs/sdk/api-sdk/plans) | `createPlanService(client)` | CRUD subscription plans | +| [Refunds](https://www.oaknetwork.org/docs/sdk/api-sdk/refunds) | `createRefundService(client)` | Refund a payment (full or partial) | +| [Buy](https://www.oaknetwork.org/docs/sdk/api-sdk/buy-and-sell) | `createBuyService(client)` | Crypto on-ramp via Bridge | +| [Sell](https://www.oaknetwork.org/docs/sdk/api-sdk/buy-and-sell) | `createSellService(client)` | Crypto off-ramp via Avenia | + --- -## 🔐 Authentication +## Usage examples -The SDK uses OAuth 2.0 client credentials flow with automatic token management. +### Customers ```typescript -// Tokens are automatically fetched and cached -const result = await crowdsplit.customers.list(); +import { createCustomerService } from '@oaknetwork/api'; -// Manual token operations (rarely needed) -const tokenResult = await client.getAccessToken(); -if (tokenResult.ok) { - console.log("Token:", tokenResult.value); -} -``` +const customers = createCustomerService(client); -**Security Best Practices:** +// Create +const result = await customers.create({ + email: 'user@example.com', + first_name: 'John', + last_name: 'Doe', + country_code: 'US', +}); -- ✅ Store credentials in environment variables -- ✅ Never commit `.env` files -- ✅ Use different credentials for sandbox and production -- ❌ Never log `clientSecret` or access tokens +// List +await customers.list({ limit: 10, offset: 0 }); ---- +// Get +await customers.get('customer_id'); -## 📡 Available Services +// Update +await customers.update('customer_id', { email: 'new@example.com' }); +``` -### Customers +### Providers ```typescript -// Create customer -await crowdsplit.customers.create({ - email: "user@example.com", - first_name: "John", - document_type: "personal_tax_id", - document_number: "123456789", -}); +import { createProviderService } from '@oaknetwork/api'; -// Get customer -await crowdsplit.customers.get("customer_id"); +const providers = createProviderService(client); -// List customers -await crowdsplit.customers.list({ limit: 10, offset: 0 }); +// Register as Stripe customer (buyer) +await providers.submitRegistration(customerId, { + provider: 'stripe', + target_role: 'customer', +}); -// Update customer -await crowdsplit.customers.update("customer_id", { - email: "newemail@example.com", +// Register as Stripe connected account (seller) +await providers.submitRegistration(customerId, { + provider: 'stripe', + target_role: 'connected_account', + provider_data: { + account_type: 'express', + transfers_requested: true, + card_payments_requested: true, + tax_reporting_us_1099_k_requested: false, + payouts_debit_negative_balances: false, + external_account_collection_requested: false, + }, }); + +// Check registration status +const status = await providers.getRegistrationStatus(customerId); ``` ### Payments ```typescript -// Create payment -await crowdsplit.payments.create({ - provider: "stripe", +import { createPaymentService } from '@oaknetwork/api'; + +const payments = createPaymentService(client); + +// Create and capture a payment +const result = await payments.create({ + provider: 'stripe', source: { - amount: 1000, // Amount in cents - currency: "usd", - customer: { id: "customer_id" }, - payment_method: { type: "card", id: "pm_123" }, - capture_method: "automatic", + amount: 5000, + currency: 'usd', + customer: { id: customerId }, + payment_method: { type: 'card', id: paymentMethodId }, + capture_method: 'automatic', }, confirm: true, }); -// Confirm payment -await crowdsplit.payments.confirm("payment_id"); - -// Cancel payment -await crowdsplit.payments.cancel("payment_id"); +// Confirm / cancel +await payments.confirm('payment_id'); +await payments.cancel('payment_id'); ``` -### Payment Methods +### Payment methods ```typescript -// Create payment method -await crowdsplit.paymentMethods.create("customer_id", { - type: "card", - provider: "stripe", - provider_data: { - token: "tok_visa", - }, -}); +import { createPaymentMethodService } from '@oaknetwork/api'; -// List customer payment methods -await crowdsplit.paymentMethods.list("customer_id"); - -// Delete payment method -await crowdsplit.paymentMethods.delete("customer_id", "pm_id"); -``` +const paymentMethods = createPaymentMethodService(client); -### Refunds +// Add a card +await paymentMethods.add(customerId, { + type: 'card', + provider: 'stripe', +}); -```typescript -// Create refund -await crowdsplit.refunds.create({ - transaction_id: "txn_123", - amount: 500, // Partial refund - reason: "customer_request", +// Add a bank account +await paymentMethods.add(customerId, { + type: 'bank', + provider: 'stripe', + currency: 'usd', + bank_name: 'Chase', + bank_account_number: '000123456789', + bank_routing_number: '021000021', + bank_account_type: 'checking', + bank_account_name: 'John Doe', }); + +// List / get / delete +await paymentMethods.list(customerId); +await paymentMethods.get(customerId, 'pm_id'); +await paymentMethods.delete(customerId, 'pm_id'); ``` ### Transfers ```typescript -// Create transfer -await crowdsplit.transfers.create({ - provider: "stripe", +import { createTransferService } from '@oaknetwork/api'; + +const transfers = createTransferService(client); + +await transfers.create({ + provider: 'stripe', source: { amount: 1000, - currency: "usd", - customer: { id: "customer_id" }, + currency: 'usd', + customer: { id: customerId }, }, destination: { - customer: { id: "customer_id" }, - payment_method: { id: "pm_123", type: "bank" }, + customer: { id: customerId }, + payment_method: { type: 'bank', id: bankPmId }, }, }); ``` -### Webhooks +### Refunds ```typescript -// Register webhook -await crowdsplit.webhooks.register({ - url: "https://your-app.com/webhooks/oak", - events: ["payment.created", "payment.succeeded"], -}); +import { createRefundService } from '@oaknetwork/api'; -// List webhooks -await crowdsplit.webhooks.list(); - -// Update webhook -await crowdsplit.webhooks.update("webhook_id", { - url: "https://your-app.com/webhooks/oak-v2", -}); +const refunds = createRefundService(client); -// Toggle webhook status -await crowdsplit.webhooks.toggleStatus("webhook_id", "inactive"); +// Full refund +await refunds.create(paymentId, {}); -// Delete webhook -await crowdsplit.webhooks.delete("webhook_id"); +// Partial refund +await refunds.create(paymentId, { amount: 500 }); ``` -### Providers +### Plans ```typescript -// List available providers -await crowdsplit.providers.list(); +import { createPlanService } from '@oaknetwork/api'; -// Get provider details -await crowdsplit.providers.get("stripe"); -``` - -### Plans +const plans = createPlanService(client); -```typescript -// List plans -await crowdsplit.plans.list(); +await plans.create({ + name: 'Pro Plan', + amount: 2999, + currency: 'USD', + interval: 'monthly', +}); -// Get plan details -await crowdsplit.plans.get("plan_id"); +await plans.list(); +await plans.get('plan_id'); ``` ### Transactions ```typescript -// List transactions -await crowdsplit.transactions.list({ - limit: 20, - offset: 0, -}); +import { createTransactionService } from '@oaknetwork/api'; -// Get transaction details -await crowdsplit.transactions.get("txn_id"); +const transactions = createTransactionService(client); + +await transactions.list({ limit: 20 }); +await transactions.get('txn_id'); ``` --- -## 🔔 Webhook Verification - -**New in v0.2.0**: Secure webhook signature verification using HMAC-SHA256 with timing-safe comparison. +## Webhooks -### Express.js Example +Register endpoints to receive real-time event notifications, and verify incoming payloads with HMAC-SHA256 signature verification. ```typescript -import express from "express"; -import { verifyWebhookSignature, parseWebhookPayload } from "@oaknetwork/api"; - -const app = express(); -app.use(express.json()); - -app.post("/webhooks/oak", async (req, res) => { - const signature = req.headers["x-oak-signature"] as string; - const payload = JSON.stringify(req.body); - - // Option 1: Verify signature only - const isValid = verifyWebhookSignature( - payload, - signature, - process.env.WEBHOOK_SECRET!, - ); - - if (!isValid) { - return res.status(401).send("Invalid signature"); - } - - const event = req.body; - console.log("Webhook event:", event.type); - - // Option 2: Verify and parse in one step (preferred) - const result = parseWebhookPayload<{ - type: string; - data: unknown; - }>(payload, signature, process.env.WEBHOOK_SECRET!); - - if (!result.ok) { - console.error("Webhook verification failed:", result.error.message); - return res.status(401).send(result.error.message); - } +import { + createWebhookService, + verifyWebhookSignature, + parseWebhookPayload, +} from '@oaknetwork/api'; + +const webhooks = createWebhookService(client); + +// Register +const wh = await webhooks.register({ + url: 'https://your-server.com/webhooks/oak', + description: 'Payment events', +}); - // Handle verified event - const verifiedEvent = result.value; - switch (verifiedEvent.type) { - case "payment.created": - // Handle payment created - break; - case "payment.succeeded": - // Handle payment succeeded - break; - default: - console.log("Unhandled event:", verifiedEvent.type); - } +if (wh.ok) { + console.log('Secret:', wh.value.data.secret); // store securely +} - res.sendStatus(200); -}); +// List / update / delete +await webhooks.list(); +await webhooks.update('webhook_id', { url: 'https://new-url.com/webhooks' }); +await webhooks.toggleStatus('webhook_id', 'inactive'); +await webhooks.delete('webhook_id'); ``` -### Next.js API Route Example +### Verify and parse incoming events ```typescript -import type { NextApiRequest, NextApiResponse } from "next"; -import { parseWebhookPayload } from "@oaknetwork/api"; - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - if (req.method !== "POST") { - return res.status(405).end(); - } +import { parseWebhookPayload } from '@oaknetwork/api'; +import express from 'express'; - const signature = req.headers["x-oak-signature"] as string; - const payload = JSON.stringify(req.body); +const app = express(); +app.post('/webhooks/oak', express.raw({ type: 'application/json' }), (req, res) => { const result = parseWebhookPayload( - payload, - signature, + req.body.toString(), + req.headers['x-oak-signature'] as string, process.env.WEBHOOK_SECRET!, ); if (!result.ok) { - return res.status(401).json({ error: result.error.message }); + return res.status(401).json({ error: 'Invalid signature' }); } - // Process verified webhook - const event = result.value; - console.log("Received:", event); + switch (result.value.event) { + case 'payment.succeeded': + break; + case 'payment.failed': + break; + case 'provider_registration.approved': + break; + } - res.status(200).json({ received: true }); -} + res.json({ received: true }); +}); ``` -**Security Notes:** - -- Always verify signatures before processing webhooks -- Use timing-safe comparison (built into SDK) -- Store webhook secret securely (environment variables) -- Never expose webhook endpoints without verification +> Full webhook reference — [oaknetwork.org/docs/sdk/api-sdk/webhooks](https://www.oaknetwork.org/docs/sdk/api-sdk/webhooks) --- -## 🎯 Error Handling +## Error handling -The SDK uses a `Result` type pattern for predictable error handling: +Every method returns `Result` — no uncaught exceptions. Check `result.ok` to branch on success or failure. ```typescript -const result = await crowdsplit.customers.create(customerData); +const result = await customers.create({ email: 'user@example.com', first_name: 'John' }); if (result.ok) { - // Success - result.value contains the response const customer = result.value.data; - console.log("Created:", customer.customer_id); + console.log('Created:', customer.id); } else { - // Error - result.error contains the OakError - console.error("Failed:", result.error.message); - console.error("Status:", result.error.statusCode); - console.error("Code:", result.error.code); + console.error('Failed:', result.error.message); + console.error('Status:', result.error.statusCode); + console.error('Code:', result.error.code); } ``` -### Error Types +| Error type | Description | +|---|---| +| `ApiError` | HTTP errors from the API (4xx, 5xx) | +| `NetworkError` | Network failures, timeouts | +| `ParseError` | Invalid JSON responses | +| `AbortError` | Request aborted | +| `EnvironmentViolationError` | Sandbox-only method called in production | -- `ApiError` - HTTP errors from the API (4xx, 5xx) -- `NetworkError` - Network failures, timeouts -- `ParseError` - Invalid JSON responses -- `AbortError` - Request aborted -- `OakError` - Base error class +> Full error handling guide — [oaknetwork.org/docs/sdk/api-sdk/error-handling](https://www.oaknetwork.org/docs/sdk/api-sdk/error-handling) --- -## ⚙️ Configuration +## Configuration + +### Environments -### Environment Options +| Environment | API Base URL | Description | +|---|---|---| +| `sandbox` | `https://api-stage.usecrowdpay.xyz` | Testing — all operations allowed | +| `production` | `https://app.usecrowdpay.xyz` | Live — test operations blocked | ```typescript -type OakEnvironment = "sandbox" | "production" | "custom"; +const client = createOakClient({ + environment: 'sandbox', + clientId: process.env.CLIENT_ID!, + clientSecret: process.env.CLIENT_SECRET!, -createOakClient({ - environment: "sandbox", // Use sandbox for testing - clientId: "your_client_id", - clientSecret: "your_client_secret", + // Optional: point to a custom API server + customUrl: 'https://my-dev-server.example.com', +}); +``` - // Optional: Custom URL for development - customUrl: "http://localhost:3000", +### Retry configuration - // Optional: Retry configuration +The SDK automatically retries failed requests with exponential backoff and jitter. + +```typescript +const client = createOakClient({ + environment: 'sandbox', + clientId: process.env.CLIENT_ID!, + clientSecret: process.env.CLIENT_SECRET!, retryOptions: { maxNumberOfRetries: 3, delay: 1000, @@ -395,237 +403,95 @@ createOakClient({ }); ``` -### Retry Configuration - -The SDK automatically retries failed requests with exponential backoff: - -- **Retry on**: 408, 429, 500, 502, 503, 504 -- **Max retries**: 3 (configurable) -- **Backoff**: Exponential with jitter to prevent thundering herd - -```typescript -retryOptions: { - maxNumberOfRetries: 3, // Number of retry attempts - delay: 1000, // Initial delay in ms - backoffFactor: 2, // Multiplier for each retry - maxDelay: 30000, // Maximum delay cap - retryOnStatus: [408, 429, 500, 502, 503, 504], - retryOnError: (error) => error.isNetworkError, -} -``` +Retried status codes: `408`, `429`, `500`, `502`, `503`, `504`. --- -## 📝 TypeScript Support +## TypeScript support -The SDK is written in TypeScript with full type definitions: +The SDK ships full type declarations. All service methods, request payloads, and responses are typed. ```typescript -import type { - Customer, - Payment, - PaymentMethod, - Transaction, - Transfer, - Result, -} from "@oaknetwork/api"; - -// Type-safe customer creation -const customerData: Customer.Request = { - email: "user@example.com", - first_name: "John", -}; - -// Type-safe result handling -const result: Result = await crowdsplit.customers.create( - customerData, -); - -if (result.ok) { - const customer: Customer.Data = result.value.data; -} +import type { Result } from '@oaknetwork/api'; ``` --- -## 🔄 Migration Guide (v0.1 → v0.2) +## Development -### Breaking Changes - -#### 1. `clientSecret` No Longer Exposed - -**Before (v0.1):** - -```typescript -console.log(client.config.clientSecret); // ✅ Works in v0.1 -``` - -**After (v0.2):** - -```typescript -console.log(client.config.clientSecret); // ❌ undefined in v0.2 -// Store separately if needed: -const secret = process.env.CLIENT_SECRET; -``` - -#### 2. `createAuthService()` Removed - -**Before (v0.1):** - -```typescript -import { createAuthService } from "@oaknetwork/api"; -const auth = createAuthService(client); -await auth.getAccessToken(); -``` - -**After (v0.2):** - -```typescript -// Use client directly -await client.getAccessToken(); -``` - -See [CHANGELOG.md](./CHANGELOG.md) for full migration guide. - ---- - -## 🛠️ Development - -### Package Manager +### Package manager This project uses **pnpm** exclusively: ```bash pnpm install # Install dependencies -pnpm build # Build all packages -pnpm test # Run tests -pnpm lint # Lint code +pnpm build # Build all packages +pnpm test # Run tests +pnpm lint # Lint code ``` -**DO NOT** use npm or yarn. The repository enforces pnpm >= 10.0.0. +**Do not** use npm or yarn. The repository enforces pnpm >= 10.0.0. -### Changesets Workflow - -We use Changesets to manage versions and changelogs: - -1. **After making changes**, run: - - ```bash - pnpm changeset - ``` - -2. **Select impact** (Major/Minor/Patch) for affected packages - -3. **Commit** the generated file in `.changeset/` - -4. **CI automatically**: - - Calculates next versions - - Generates changelogs - - Creates release PR - -### Running Tests +### Running tests ```bash -# Unit tests -pnpm test:unit - -# Integration tests (requires credentials) -pnpm test:integration - -# All tests with coverage -pnpm test:all - -# Watch mode -pnpm test:watch +pnpm test:unit # Unit tests +pnpm test:integration # Integration tests (requires credentials) +pnpm test:all # All tests with coverage +pnpm test:watch # Watch mode ``` -### Environment Variables for Testing +### Changesets workflow -Create `.env` file in `packages/api`: +We use Changesets to manage versions and changelogs: -```env -CLIENT_ID=your_sandbox_client_id -CLIENT_SECRET=your_sandbox_client_secret -OAK_ENVIRONMENT=sandbox -``` +1. After making changes, run `pnpm changeset` +2. Select impact (Major / Minor / Patch) for affected packages +3. Commit the generated file in `.changeset/` +4. CI automatically calculates versions, generates changelogs, and creates a release PR ### Code coverage -Coverage is reported to [Codecov](https://about.codecov.io) after each successful CI run. The Codecov workflow runs separately with minimal permissions and uploads coverage from the API package. For uploads on pushes and pull requests from this repository, a `CODECOV_TOKEN` secret (from your organization or Codecov dashboard) may be required; when the token is not set, the upload step is skipped and the workflow still succeeds. - ---- - -## 📖 Documentation - -- **API Reference**: See [packages/api/README.md](./packages/api/README.md) -- **Type Definitions**: Included with package, supports IDE autocomplete -- **Examples**: See [examples/](./examples/) directory (coming soon) -- **Changelog**: See [CHANGELOG.md](./CHANGELOG.md) - ---- - -### Development Guidelines +Coverage is reported to [Codecov](https://about.codecov.io) after each successful CI run. -See [CLAUDE.md](./CLAUDE.md) for comprehensive coding standards including: +### Development guidelines -- Architecture principles (Result types, factory pattern) -- Security rules (never expose secrets, timing-safe comparisons) -- Testing requirements (no silent skips, >90% coverage) -- Type system rules (use `unknown`, named interfaces) -- Anti-patterns to avoid +See [CLAUDE.md](./CLAUDE.md) for coding standards including architecture principles, security rules, testing requirements, and anti-patterns. -### Code Review Checklist +### Code review checklist -Before submitting PR: - -- [ ] Run `pnpm build` successfully -- [ ] Run `pnpm test` with >90% coverage -- [ ] Run `pnpm lint` without errors -- [ ] Create changeset with `pnpm changeset` -- [ ] Update documentation if needed -- [ ] Follow patterns in [CLAUDE.md](./CLAUDE.md) +- [ ] `pnpm build` succeeds +- [ ] `pnpm test` passes with >90% coverage +- [ ] `pnpm lint` has no errors +- [ ] Changeset created with `pnpm changeset` +- [ ] Documentation updated if needed --- -## 📄 License - -[MIT LICENSE](LICENSE) +## Documentation +- **Full docs** — [oaknetwork.org/docs/sdk/api-sdk/overview](https://www.oaknetwork.org/docs/sdk/api-sdk/overview) +- **Quickstart** — [oaknetwork.org/docs/sdk/api-sdk/quickstart](https://www.oaknetwork.org/docs/sdk/api-sdk/quickstart) +- **API package README** — [packages/api/README.md](./packages/api/README.md) +- **Changelog** — [CHANGELOG.md](./CHANGELOG.md) --- -## Security - -[SECURITY POLICIES](SECURITY.md) - -## 🔗 Links +## License -- [Oak Network Website](https://oaknetwork.org) -- [API Documentation](https://www.oaknetwork.org/docs/intro) -- [GitHub Repository](https://github.com/oak-network/sdk) -- [Issue Tracker](https://github.com/oak-network/sdk/issues) -- [npm Package](https://www.npmjs.com/package/@oaknetwork/api) +[MIT](LICENSE) ---- - -## 🎯 Roadmap - -**Pre-Launch (Current → March 2026)** +## Security -- ✅ Core API services implemented -- ✅ Comprehensive type safety -- ✅ Webhook verification utilities -- ✅ Full test coverage -- ⏳ Production hardening -- ⏳ Performance optimization -- ⏳ Example applications +[Security Policy](SECURITY.md) -**Post-Launch** +## Links -- Advanced retry strategies -- Request/response middleware -- CLI tools -- TBD (Being evaluated based on user feedback) +- [Oak Network](https://www.oaknetwork.org/) +- [Documentation](https://www.oaknetwork.org/docs/sdk/api-sdk/overview) +- [GitHub](https://github.com/oak-network/sdk) +- [Issues](https://github.com/oak-network/sdk/issues) +- [npm](https://www.npmjs.com/package/@oaknetwork/api) --- -**Questions?** Open an issue or contact support@oaknetwork.org +**Questions?** Open an issue or contact [support@oaknetwork.org](mailto:support@oaknetwork.org) From 5360cacfa71fbffd304e4109245604ae4a7232d2 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Fri, 27 Feb 2026 16:10:54 -0300 Subject: [PATCH 27/31] chore(dependabot): specify npm as package ecosystem in dependabot configuration --- .github/dependabot.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d698d8d0..5f0889ce 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,8 +5,7 @@ version: 2 updates: - - package-ecosystem: "" # See documentation for possible values + - package-ecosystem: "npm" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" - From 4820cc6e1c9d3da4a9f5933c4d87b1e1337864a9 Mon Sep 17 00:00:00 2001 From: fahmidareem3 Date: Sat, 28 Feb 2026 01:15:25 +0600 Subject: [PATCH 28/31] fix: fix minor readme issues by reported by codex --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ab15e5a3..5eb8b7f9 100644 --- a/README.md +++ b/README.md @@ -248,13 +248,18 @@ const plans = createPlanService(client); await plans.create({ name: 'Pro Plan', - amount: 2999, + description: 'Monthly pro subscription', + price: 2999, currency: 'USD', - interval: 'monthly', + frequency: 30, + start_date: '2026-03-01', + is_auto_renewable: true, + allow_amount_override: false, + created_by: customerId, }); await plans.list(); -await plans.get('plan_id'); +await plans.details('plan_id'); ``` ### Transactions @@ -296,7 +301,7 @@ if (wh.ok) { // List / update / delete await webhooks.list(); await webhooks.update('webhook_id', { url: 'https://new-url.com/webhooks' }); -await webhooks.toggleStatus('webhook_id', 'inactive'); +await webhooks.toggle('webhook_id'); await webhooks.delete('webhook_id'); ``` From 7eca1d9e9d957c2c804000516061e1170adfb746 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Mon, 2 Mar 2026 13:43:49 -0300 Subject: [PATCH 29/31] fix(codecov): update Codecov action version and coverage file path in workflow --- .github/workflows/codecov.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 1e114a4d..330e0650 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -19,11 +19,6 @@ jobs: actions: read steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.event.workflow_run.head_sha }} - - name: Download coverage artifact uses: actions/download-artifact@v4 with: @@ -32,8 +27,8 @@ jobs: github-token: ${{ github.token }} - name: Upload to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de with: token: ${{ secrets.CODECOV_TOKEN }} - files: api/coverage/lcov.info + files: packages/api/coverage/lcov.info fail_ci_if_error: false From 057f05585d64d8029b9fddcac23cfb6a9970b68b Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Mon, 2 Mar 2026 15:44:17 -0300 Subject: [PATCH 30/31] fix(codecov): update Codecov workflow to use default branch and add build metadata overrides --- .github/workflows/codecov.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 1e114a4d..59108021 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -22,7 +22,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.workflow_run.head_sha }} + ref: ${{ github.event.repository.default_branch }} - name: Download coverage artifact uses: actions/download-artifact@v4 @@ -36,4 +36,8 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: api/coverage/lcov.info + override_commit: ${{ github.event.workflow_run.head_sha }} + override_branch: ${{ github.event.workflow_run.head_branch }} + override_build: ${{ github.event.workflow_run.run_number }} + override_build_url: ${{ github.event.workflow_run.html_url }} fail_ci_if_error: false From d8165f296bd11a61ee367a8934ab46db1a7520b4 Mon Sep 17 00:00:00 2001 From: andrefelizardo Date: Mon, 2 Mar 2026 16:41:36 -0300 Subject: [PATCH 31/31] fix(codecov): restrict Codecov workflow to main branch only --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 73ee0e91..76091b9b 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -4,7 +4,7 @@ on: workflow_run: workflows: [CI] types: [completed] - branches: [main, develop] + branches: [main] concurrency: group: codecov-${{ github.event.workflow_run.id }}