pandascrow 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +208 -2
- package/dist/index.cjs +627 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +523 -0
- package/dist/index.d.ts +523 -0
- package/dist/index.js +594 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0 (2026-10-25)
|
|
4
|
+
|
|
5
|
+
First release.
|
|
6
|
+
|
|
7
|
+
- `Pandascrow` client for the v3 API (sandbox by default, live with `{ sandbox: false }`), with `escrow`, `wallet`, `payouts`, `bank`, `virtualAccounts`, `invoices`, `paymentLinks`, `kyc` and `auth` resources, plus `request()` for anything not wrapped.
|
|
8
|
+
- `metadata` support for escrows, invoices and virtual accounts.
|
|
9
|
+
- `verifyWebhook()` checks the HMAC-SHA256 signature of the raw body, with replay protection. Works on Node.js, Bun, Deno and edge runtimes.
|
|
10
|
+
- `PandascrowError` for every failure, with `status`, `docUrl` and `response`.
|
|
11
|
+
- Typed parameters and responses, ESM + CommonJS builds, no runtime dependencies.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pandascrow Inc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,209 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Pandascrow JavaScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official Node.js / JavaScript library for the [Pandascrow v3 API](https://pandascrow.readme.io/): escrow, wallets, payouts, bank transfers, virtual accounts, invoices, payment links, KYC and webhook verification.
|
|
4
|
+
|
|
5
|
+
- Written in TypeScript, ships its own types
|
|
6
|
+
- ESM and CommonJS
|
|
7
|
+
- No dependencies: uses the built-in `fetch` (Node.js 18+, Bun, Deno, Cloudflare Workers, Vercel Edge)
|
|
8
|
+
|
|
9
|
+
> Use this SDK on your server only. Your API key gives full access to your Pandascrow account, so never ship it to a browser or mobile app.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install pandascrow
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import Pandascrow from 'pandascrow';
|
|
21
|
+
|
|
22
|
+
const ps = new Pandascrow(process.env.PANDASCROW_API_KEY!); // sandbox (default)
|
|
23
|
+
// const ps = new Pandascrow(process.env.PANDASCROW_API_KEY!, { sandbox: false }); // live
|
|
24
|
+
|
|
25
|
+
const escrow = await ps.escrow.createOnetime({
|
|
26
|
+
uuid, // the Pandascrow user acting
|
|
27
|
+
initiator_id: uuid,
|
|
28
|
+
initiator_role: 'seller', // 'buyer' | 'seller' | 'broker'
|
|
29
|
+
title: 'Apartment 4B rent',
|
|
30
|
+
description: '12-month rent, 12 Admiralty Way',
|
|
31
|
+
currency: 'NGN',
|
|
32
|
+
amount: 350000,
|
|
33
|
+
buyer_details: { name: 'Tenant', email: 'tenant@example.com' },
|
|
34
|
+
metadata: { property_id: 'PR-204' }, // your own IDs, see below
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log(escrow.payment_url); // send the buyer here to fund the escrow
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
CommonJS:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const { Pandascrow } = require('pandascrow');
|
|
44
|
+
const ps = new Pandascrow(process.env.PANDASCROW_API_KEY);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Your API key is the **public key** of your application (Dashboard → Developers). It is sent as the `Token` header. Most calls also take the `uuid` of the Pandascrow user you are acting for.
|
|
48
|
+
|
|
49
|
+
Every method returns a promise of the `data` object from the API response.
|
|
50
|
+
|
|
51
|
+
## Errors
|
|
52
|
+
|
|
53
|
+
Every failure rejects with a `PandascrowError`: network errors, timeouts, invalid responses, HTTP errors and any response with `status: false`.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { PandascrowError } from 'pandascrow';
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
await ps.escrow.complete(uuid, escrowId, otp);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
if (err instanceof PandascrowError) {
|
|
62
|
+
err.message; // "Invalid OTP"
|
|
63
|
+
err.status; // 400 (0 for network errors and timeouts)
|
|
64
|
+
err.docUrl; // link to the API reference, when available
|
|
65
|
+
err.response; // full decoded response body
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Metadata
|
|
71
|
+
|
|
72
|
+
Escrows, invoices and virtual accounts accept a `metadata` object with your own identifiers. Pandascrow stores it as-is, returns it when you fetch the record, and includes it as `data.metadata` in every webhook for that record:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await ps.escrow.createOnetime({ ..., metadata: { property_id: 'PR-204' } });
|
|
76
|
+
|
|
77
|
+
// later, in your webhook handler
|
|
78
|
+
event.data.metadata?.property_id; // "PR-204"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Limits: up to 50 keys, key names up to 64 characters, 5 levels of nesting, 8 KB in total.
|
|
82
|
+
|
|
83
|
+
## Resources
|
|
84
|
+
|
|
85
|
+
| Property | Methods |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `escrow` | `createOnetime`, `createMilestone`, `createRecurring`, `create`, `all`, `find`, `complete`, `resendReleaseOtp`, `payNextMilestone`, `completeMilestone`, `regeneratePayment`, `regenerateMilestonePayment`, `dispute`, `disputes`, `joinRecurring` |
|
|
88
|
+
| `wallet` | `list`, `balances`, `transactions`, `accounts`, `payout` |
|
|
89
|
+
| `payouts` | `create`, `all`, `settlementAccounts` |
|
|
90
|
+
| `bank` | `banks`, `validate`, `transfer`, `settlementAccount` |
|
|
91
|
+
| `virtualAccounts` | `createDynamic`, `createStatic`, `reallocate`, `deactivate`, `reactivate`, `confirmPayment` |
|
|
92
|
+
| `invoices` | `create`, `all`, `find`, `pay`, `cancel` |
|
|
93
|
+
| `paymentLinks` | `create`, `all`, `find`, `isSlugAvailable`, `goLive`, `toggleTip`, `payments`, `initiatePayment`, `completePayment`, `addMargin` |
|
|
94
|
+
| `kyc` | `bvn`, `nin`, `phone`, `nuban`, `driversLicense`, `tin`, `cac`, `searchCac`, `email` |
|
|
95
|
+
| `auth` | `login`, `verifyLoginOtp` |
|
|
96
|
+
|
|
97
|
+
Anything not wrapped yet:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
await ps.request('GET', '/clients', { uuid });
|
|
101
|
+
await ps.request('POST', '/escrow/recurring/update', {}, { uuid, escrow_id: 12 });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Examples
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// Milestone escrow, paid stage by stage
|
|
108
|
+
await ps.escrow.createMilestone({
|
|
109
|
+
uuid, initiator_id: uuid, initiator_role: 'buyer',
|
|
110
|
+
title: 'Website build', description: 'Company website', currency: 'NGN',
|
|
111
|
+
seller_details: { name: 'Dev Studio', email: 'studio@example.com' },
|
|
112
|
+
deposit_option: 'milestone',
|
|
113
|
+
milestones: [
|
|
114
|
+
{ title: 'Design', amount: 150000 },
|
|
115
|
+
{ title: 'Build', amount: 350000 },
|
|
116
|
+
],
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// NGN transfer to a bank account (keep the idempotency key to retry safely)
|
|
120
|
+
await ps.bank.transfer(uuid, 25000,
|
|
121
|
+
{ account_number: '0123456789', account_name: 'Ada Obi', bank_code: '058' },
|
|
122
|
+
{ idempotencyKey: 'payout-7781' },
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// Virtual account that accepts any amount, expiring in 24 hours
|
|
126
|
+
await ps.virtualAccounts.createDynamic(uuid, 'Ada Obi', null, { expiryHours: 24, metadata: { customer_id: 'C-9' } });
|
|
127
|
+
|
|
128
|
+
// Invoice
|
|
129
|
+
await ps.invoices.create({
|
|
130
|
+
ownerUuid: uuid,
|
|
131
|
+
client: { full_name: 'Client Co', email: 'billing@client.co' },
|
|
132
|
+
invoice: { currency: 'NGN', due_date: '2026-12-31' },
|
|
133
|
+
items: [{ description: 'Consulting', quantity: 10, unit_price: 20000 }],
|
|
134
|
+
metadata: { order_id: 'A-1001' },
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Webhooks
|
|
139
|
+
|
|
140
|
+
Pandascrow signs every webhook with HMAC-SHA256 of the **raw request body**, using your application's **secret key**, and sends it in the `X-Pandascrow-Signature` header. `verifyWebhook` checks it and returns the parsed event. Always give it the raw body, not a parsed object.
|
|
141
|
+
|
|
142
|
+
**Express**
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import express from 'express';
|
|
146
|
+
import { verifyWebhook } from 'pandascrow';
|
|
147
|
+
|
|
148
|
+
app.post('/webhooks/pandascrow', express.raw({ type: 'application/json' }), async (req, res) => {
|
|
149
|
+
try {
|
|
150
|
+
const event = await verifyWebhook(process.env.PANDASCROW_SECRET_KEY!, req.body, req.get('X-Pandascrow-Signature'));
|
|
151
|
+
|
|
152
|
+
switch (event.event) {
|
|
153
|
+
case 'escrow.paid': /* event.data.metadata?.property_id */ break;
|
|
154
|
+
case 'escrow.completed': break;
|
|
155
|
+
case 'invoice.paid': break;
|
|
156
|
+
}
|
|
157
|
+
res.sendStatus(200);
|
|
158
|
+
} catch {
|
|
159
|
+
res.sendStatus(400);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Next.js (App Router)**
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
// app/api/webhooks/pandascrow/route.ts
|
|
168
|
+
import { verifyWebhook } from 'pandascrow';
|
|
169
|
+
|
|
170
|
+
export async function POST(req: Request) {
|
|
171
|
+
const raw = await req.text();
|
|
172
|
+
try {
|
|
173
|
+
const event = await verifyWebhook(process.env.PANDASCROW_SECRET_KEY!, raw, req.headers.get('x-pandascrow-signature'));
|
|
174
|
+
// handle event.event / event.data
|
|
175
|
+
return new Response('ok');
|
|
176
|
+
} catch {
|
|
177
|
+
return new Response('invalid signature', { status: 400 });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Events older than 5 minutes are rejected; pass `{ tolerance: seconds }` as the fourth argument to change that (`0` turns it off).
|
|
183
|
+
|
|
184
|
+
Events include `escrow.created`, `escrow.paid`, `escrow.completed`, `escrow.milestone.completed`, `escrow.dispute.opened`, `escrow.payout.completed`, `escrow.payout.processing`, `escrow.payout.failed`, `recurring.payment.success`, `invoice.paid` and `wallet.deposit.success`.
|
|
185
|
+
|
|
186
|
+
## Options
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
new Pandascrow(apiKey, {
|
|
190
|
+
sandbox: true, // false for live
|
|
191
|
+
baseUrl: undefined, // override the host, e.g. a local API
|
|
192
|
+
timeout: 30000, // milliseconds
|
|
193
|
+
headers: {}, // extra headers on every request
|
|
194
|
+
fetch: undefined, // custom fetch (logging, retries, tests)
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Development
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npm install
|
|
202
|
+
npm test # unit tests with a fake fetch, never calls the API
|
|
203
|
+
npm run typecheck
|
|
204
|
+
npm run build # dist/ (ESM + CJS + types)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|