{"_id":"@aevion-io/fintech-sdk","name":"@aevion-io/fintech-sdk","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@aevion-io/fintech-sdk","version":"0.2.0","description":"TypeScript client for the AEVION fintech ecosystem — 6 modules (QGood charity, QMaskCard virtual cards, VeilNetX settlement ledger, Z-Tide reputation, QChainGov governance, QPayNet wallets/transfers) + webhook signing helpers (HMAC-SHA256 with replay prot","main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"keywords":["aevion","fintech","charity","virtual-cards","ledger","governance","wallets","payments","p2p","webhooks","hmac"],"license":"MIT","author":{"name":"AEVION","url":"Dossymbek"},"homepage":"https://github.com/Dossymbek281078/AEVION/tree/main/packages/fintech-sdk#readme","bugs":{"url":"https://github.com/Dossymbek281078/AEVION/issues"},"repository":{"type":"git","url":"git+https://github.com/Dossymbek281078/AEVION.git","directory":"packages/fintech-sdk"},"publishConfig":{"access":"public"},"engines":{"node":">=18"},"devDependencies":{"typescript":"^5.4.0"},"gitHead":"249a529a0bdcc2fb0a737794d729457f66e2ff3f","_id":"@aevion-io/fintech-sdk@0.2.0","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-4Ly06XdPk6ODxATst0gSCERuZEO62P0shbYA/Tzz8JhTdcBBD/qyCqAt01IxN3eB0qpsCGWTgbyFI6QDQ5ZS2w==","shasum":"46189061142e6af9c82872ede708c07a3ffe72ac","tarball":"https://registry.npmjs.org/@aevion-io/fintech-sdk/-/fintech-sdk-0.2.0.tgz","fileCount":44,"unpackedSize":138895,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIF4Aj7rh/zs6e3TLvuKKOqadDDHzEAyfWLO+G6Hq3o2sAiBGzFy3DtwJXWkXn0X/SJQIDnvRdkiCZacrjF6W1nDqQw=="}]},"_npmUser":{"name":"dosymbek","email":"yahiin1978@gmail.com"},"directories":{},"maintainers":[{"name":"dosymbek","email":"yahiin1978@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/fintech-sdk_0.2.0_1779095847219_0.007252817471378847"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-18T09:17:27.119Z","0.2.0":"2026-05-18T09:17:27.358Z","modified":"2026-05-18T09:17:27.604Z"},"maintainers":[{"name":"dosymbek","email":"yahiin1978@gmail.com"}],"description":"TypeScript client for the AEVION fintech ecosystem — 6 modules (QGood charity, QMaskCard virtual cards, VeilNetX settlement ledger, Z-Tide reputation, QChainGov governance, QPayNet wallets/transfers) + webhook signing helpers (HMAC-SHA256 with replay prot","homepage":"https://github.com/Dossymbek281078/AEVION/tree/main/packages/fintech-sdk#readme","keywords":["aevion","fintech","charity","virtual-cards","ledger","governance","wallets","payments","p2p","webhooks","hmac"],"repository":{"type":"git","url":"git+https://github.com/Dossymbek281078/AEVION.git","directory":"packages/fintech-sdk"},"author":{"name":"AEVION","url":"Dossymbek"},"bugs":{"url":"https://github.com/Dossymbek281078/AEVION/issues"},"license":"MIT","readme":"# @aevion-io/fintech-sdk\n\nTypeScript client for the AEVION fintech ecosystem.\n\nWraps **six backend modules** with typed methods, shared error handling, a\nsingle auth-aware client, **and standalone webhook signing utilities**\n(HMAC-SHA256 + timestamp replay protection + rolling secret rotation).\n\n| Module       | What it does                                                  |\n|--------------|---------------------------------------------------------------|\n| **QGood**    | Charity campaigns, donations, matching pools                  |\n| **QMaskCard**| Privacy-preserving virtual cards (single-use, merchant-locked)|\n| **VeilNetX** | Append-only hash-chained settlement ledger                    |\n| **Z-Tide**   | Reputation / standing scoring across the ecosystem            |\n| **QChainGov**| Governance proposals + votes                                  |\n| **QPayNet**  | Wallets, P2P transfers, payment requests, merchant rail       |\n\n> Backend OpenAPI: `GET /api/openapi.json` on your AEVION host.\n\n## Install\n\n```bash\nnpm install @aevion-io/fintech-sdk\n```\n\nNode 18+ required (uses native `fetch`, `AbortSignal.timeout`, and\n`globalThis.crypto.subtle`). Also works in modern browsers, Cloudflare\nWorkers, Deno, and edge runtimes — no native dependencies.\n\n## Quickstart\n\n```ts\nimport { FintechClient } from \"@aevion-io/fintech-sdk\";\n\nconst client = new FintechClient({\n  baseUrl: \"https://aevion-production-a70c.up.railway.app\",\n});\n\n// Anonymous reads\nconst { campaigns } = await client.qgood.listCampaigns({ status: \"active\", limit: 10 });\nconst head = await client.veilnetxLedger.chainHead();\nconst stats = await client.qpaynet.stats();\n\n// Authed actions\nconst authed = client.withToken(\"eyJhbGciOi…\");\nconst wallets = await authed.qpaynet.listWallets();\nconst tx = await authed.qpaynet.transfer({\n  fromWalletId: wallets.wallets[0].id,\n  toWalletId: \"<recipient-uuid>\",\n  amountCents: 5000,\n  paymentRef: \"order_42\",   // idempotency key\n  description: \"Order #42\",\n});\n\n// Merchant charges use X-Merchant-Key, not Bearer\nconst charge = await client.qpaynet.merchantCharge(merchantSecret, {\n  payerWalletId,\n  amountCents: 5000,\n  paymentRef: \"stripe_evt_abc\",\n});\n// charge.idempotent === true on replay — no double-charge\n```\n\n## Authentication\n\nAuthenticated endpoints expect a Bearer JWT from `POST /api/auth/login`. Bind\na token by calling `withToken` — it returns a fresh client; the original is\nunchanged.\n\n```ts\nconst authed = client.withToken(\"eyJhbGciOi…\");\n```\n\nQPayNet `merchantCharge` is the one exception: it authorizes via\n`X-Merchant-Key` header (NOT Bearer). Mint a key with\n`mintMerchantKey` and store the full `secret` server-side — it's shown ONCE.\n\n## Webhook signing\n\nAEVION delivers signed webhook events with two headers:\n\n- `X-Aevion-Signature: sha256=<hex hmac-sha256>`\n- `X-Aevion-Timestamp: <unix seconds>`\n\nThe signed payload is `${timestamp}.${rawBody}`. The SDK ships matching\nsender + receiver helpers — use these instead of rolling your own HMAC.\n\n### Verify incoming webhooks\n\n```ts\nimport { verifyWebhook } from \"@aevion-io/fintech-sdk\";\nimport express from \"express\";\n\napp.post(\"/webhooks/aevion\", express.raw({ type: \"*/*\" }), async (req, res) => {\n  const result = await verifyWebhook({\n    signature: req.headers[\"x-aevion-signature\"] as string,\n    timestamp: req.headers[\"x-aevion-timestamp\"] as string,\n    rawBody: (req.body as Buffer).toString(\"utf8\"),\n    secret: process.env.AEVION_WEBHOOK_SECRET!,\n    // During a rotation window, accept BOTH new + old secrets:\n    previousSecrets: [process.env.AEVION_WEBHOOK_SECRET_OLD ?? \"\"].filter(Boolean),\n  });\n  if (!result.ok) return res.status(401).send(result.reason);\n  if (result.secretIndex > 0) {\n    console.warn(\"[webhook] verified with rotated secret — finish migration soon\");\n  }\n  // process event…\n  res.status(200).end();\n});\n```\n\n### Sign outgoing webhooks (dev fixtures, partner mocks, bridges)\n\n```ts\nimport { signWebhookPayload, aevionWebhookHeaders } from \"@aevion-io/fintech-sdk\";\n\n// Low-level — get signature + timestamp separately\nconst { signature, timestamp } = await signWebhookPayload({ body, secret });\n\n// High-level — get headers ready for fetch\nconst headers = await aevionWebhookHeaders({ body, secret });\nawait fetch(partnerUrl, { method: \"POST\", headers, body: JSON.stringify(body) });\n```\n\n### Replay protection + rotation\n\n- Requests outside a 5-minute window (configurable via `toleranceSec`) are\n  rejected. Sync your server's NTP to keep this happy.\n- Pass `previousSecrets` during a rotation cutover. The verifier tries the\n  current secret first, then each previous one, and reports which matched\n  via `secretIndex` (0 = current, 1+ = previous). Log `secretIndex > 0`\n  to track when the rotation is safe to finalize.\n\nSee the full rotation playbook at `/developers/fintech/troubleshooting`\n(Playbook D) on your AEVION host.\n\n## Error handling\n\nNon-2xx responses throw a plain `SDKError` shape (not an `Error` instance):\n\n```ts\nimport type { SDKError } from \"@aevion-io/fintech-sdk\";\n\ntry {\n  await authed.qchaingov.vote(proposalId, { choice: \"yes\" });\n} catch (e) {\n  const err = e as SDKError;\n  if (err.status === 409 && err.code === \"already_voted\") {\n    // user previously voted on this proposal — surface gracefully\n  } else if (err.status === 429 && err.code === \"streak_cooldown\") {\n    // login-streak still in cooldown window\n  } else {\n    throw e;\n  }\n}\n```\n\n`err.code` mirrors the backend's machine-readable tag (`\"auth required\"`,\n`\"invalid_module\"`, `\"insufficient_balance\"`, `\"already_voted\"`, `\"mask_revoked\"`,\n`\"streak_cooldown\"`, etc.) — safe to switch on.\n\n## Module method index\n\n### `client.qgood`\n\n- `listCampaigns(opts?)` → `{ campaigns, total }`\n- `getCampaign(id)` → `{ campaign, donations }`\n- `createCampaign(body)` → `{ id, status: \"draft\" }`\n- `approveCampaign(id)` *(admin)*\n- `donate(campaignId, body)` → `{ id, campaignId, amountCents, match }`\n- `listMatchingPools()` → `{ pools, total }`\n- `createMatchingPool(body)` *(admin)*\n- `pauseMatchingPool(id)` / `resumeMatchingPool(id)` *(admin)*\n- `stats()` → `QGoodStatsResponse`\n\n### `client.qmaskcard`\n\n- `issueMask(body)` *(auth)*\n- `listMasks({ includeRevoked? })` *(auth)*\n- `revokeMask(id)` *(auth)*\n- `authorize(body)` → idempotent on `(maskId, paymentRef)` *(auth)*\n- `listCharges({ maskId? })` *(auth)*\n- `stats()`\n\n### `client.veilnetxLedger`\n\n- `appendEntry(body)` *(auth)*\n- `listEntries({ module?, fromIdentifier?, limit? })`\n- `getEntry(id)` → `{ entry, integrity, recomputedHash }`\n- `search(hashPrefix, limit?)` — min 4 hex chars\n- `chainHead()` → `{ head, length, tipAt? }`\n- `verifyChain()` → `{ verified, brokenAt, length, head }`\n- `stats()`\n\n### `client.ztide`\n\n- `emitEvent(body)` *(admin or service-key)*\n- `me()` *(auth)*\n- `loginStreak()` *(auth, 20h cooldown)*\n- `leaderboard(limit?)`\n- `rank(userId)`\n- `stats()`\n\n### `client.qchaingov`\n\n- `createProposal(body)` *(auth)*\n- `listProposals(opts?)` / `getProposal(id)`\n- `vote(proposalId, body)` *(auth, 409 on duplicate)*\n- `listVotes(proposalId)`\n- `openProposal(id)` / `closeProposal(id)` / `execute(id)` *(admin)*\n- `stats()`\n\n### `client.qpaynet`\n\n- `health()` / `stats()`\n- `listWallets({ status?, currency? })` / `openWallet(body)` *(auth)*\n- `getPublicWallet(id)` — no auth, returns label + currency only\n- `transfer(body)` — idempotent on `paymentRef` *(auth)*\n- `deposit(body)` — sandbox stub *(auth)*\n- `listTransactions({ walletId?, kind?, since?, limit? })` *(auth)*\n- `createPaymentRequest(body)` / `getPaymentRequest(token)` / `payPaymentRequest(token, body)`\n- `mintMerchantKey(body)` — secret returned **ONCE** *(auth, merchant wallet)*\n- `listMerchantKeys()` *(auth)*\n- `merchantCharge(merchantKeySecret, body)` — X-Merchant-Key header, idempotent on paymentRef\n\n### Webhook signing (standalone)\n\n- `verifyWebhook(opts)` → `{ ok, mode, secretIndex } | { ok: false, reason }`\n- `signWebhookPayload(opts)` → `{ signature, timestamp, signedPayload }`\n- `aevionWebhookHeaders(opts)` → ready-to-fetch header object\n\n## Configuration\n\n```ts\nnew FintechClient({\n  baseUrl: \"https://…\",      // required, trailing slash optional\n  token: \"eyJ…\",             // optional Bearer JWT\n  fetch: customFetch,        // optional fetch override (tests, Node <18)\n  timeoutMs: 10_000,         // optional per-request timeout (default 10000)\n});\n```\n\n`timeoutMs` uses `AbortSignal.timeout` internally; the request aborts with a\n`DOMException` if the server doesn't respond in time.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-f1b18e5d15cd481b185d72c073fafe91"}