@wefunder/sdk 0.1.0-beta.8 → 0.1.0-beta.9
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/README.md +173 -146
- package/dist/index.cjs +430 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5651 -2045
- package/dist/index.d.ts +5651 -2045
- package/dist/index.js +418 -39
- package/dist/index.js.map +1 -1
- package/examples_manifest.json +31 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1136,23 +1136,36 @@ var sdk_gen_exports = {};
|
|
|
1136
1136
|
__export(sdk_gen_exports, {
|
|
1137
1137
|
approveSyndicateMember: () => approveSyndicateMember,
|
|
1138
1138
|
closeSyndicateDeal: () => closeSyndicateDeal,
|
|
1139
|
+
createInstallation: () => createInstallation,
|
|
1140
|
+
createInstallationToken: () => createInstallationToken,
|
|
1139
1141
|
createIntent: () => createIntent,
|
|
1140
1142
|
createPartnerInvite: () => createPartnerInvite,
|
|
1143
|
+
createWebhookEndpoint: () => createWebhookEndpoint,
|
|
1141
1144
|
createWebhookSubscription: () => createWebhookSubscription,
|
|
1145
|
+
deleteWebhookEndpoint: () => deleteWebhookEndpoint,
|
|
1142
1146
|
deleteWebhookSubscription: () => deleteWebhookSubscription,
|
|
1143
1147
|
demoteSyndicateMember: () => demoteSyndicateMember,
|
|
1144
1148
|
exportSyndicateMembersCsv: () => exportSyndicateMembersCsv,
|
|
1145
1149
|
finalizeSyndicateDeal: () => finalizeSyndicateDeal,
|
|
1150
|
+
followCompany: () => followCompany,
|
|
1146
1151
|
getAttributionMe: () => getAttributionMe,
|
|
1147
1152
|
getAttributionStats: () => getAttributionStats,
|
|
1153
|
+
getCompany: () => getCompany,
|
|
1154
|
+
getCompanyDisclosures: () => getCompanyDisclosures,
|
|
1155
|
+
getCompanyPitch: () => getCompanyPitch,
|
|
1156
|
+
getCompanyUpdate: () => getCompanyUpdate,
|
|
1148
1157
|
getCurrentUser: () => getCurrentUser,
|
|
1158
|
+
getInstallation: () => getInstallation,
|
|
1149
1159
|
getIntent: () => getIntent,
|
|
1160
|
+
getInvestment: () => getInvestment,
|
|
1150
1161
|
getOffering: () => getOffering,
|
|
1162
|
+
getOfferingStats: () => getOfferingStats,
|
|
1151
1163
|
getPortfolio: () => getPortfolio,
|
|
1152
1164
|
getSyndicate: () => getSyndicate,
|
|
1153
1165
|
getSyndicateDeal: () => getSyndicateDeal,
|
|
1154
1166
|
getSyndicatePortfolio: () => getSyndicatePortfolio,
|
|
1155
1167
|
getSyndicateStatistics: () => getSyndicateStatistics,
|
|
1168
|
+
getWebhookEndpoint: () => getWebhookEndpoint,
|
|
1156
1169
|
getWebhookSubscription: () => getWebhookSubscription,
|
|
1157
1170
|
hideSyndicateMember: () => hideSyndicateMember,
|
|
1158
1171
|
inviteSyndicateMember: () => inviteSyndicateMember,
|
|
@@ -1160,9 +1173,15 @@ __export(sdk_gen_exports, {
|
|
|
1160
1173
|
listAttributedInvestments: () => listAttributedInvestments,
|
|
1161
1174
|
listAttributionCampaigns: () => listAttributionCampaigns,
|
|
1162
1175
|
listCampaigns: () => listCampaigns,
|
|
1176
|
+
listCompanyQuestions: () => listCompanyQuestions,
|
|
1177
|
+
listCompanyUpdates: () => listCompanyUpdates,
|
|
1163
1178
|
listConnectedApps: () => listConnectedApps,
|
|
1179
|
+
listEligibleInstallTargets: () => listEligibleInstallTargets,
|
|
1180
|
+
listFollowedCompanies: () => listFollowedCompanies,
|
|
1181
|
+
listInstallations: () => listInstallations,
|
|
1164
1182
|
listIntents: () => listIntents,
|
|
1165
1183
|
listInvestments: () => listInvestments,
|
|
1184
|
+
listMyCompanies: () => listMyCompanies,
|
|
1166
1185
|
listOfferings: () => listOfferings,
|
|
1167
1186
|
listPartnerInvites: () => listPartnerInvites,
|
|
1168
1187
|
listPortfolioPositions: () => listPortfolioPositions,
|
|
@@ -1172,9 +1191,12 @@ __export(sdk_gen_exports, {
|
|
|
1172
1191
|
listSyndicateMembers: () => listSyndicateMembers,
|
|
1173
1192
|
listSyndicatePortfolioPositions: () => listSyndicatePortfolioPositions,
|
|
1174
1193
|
listSyndicates: () => listSyndicates,
|
|
1194
|
+
listWebhookEndpoints: () => listWebhookEndpoints,
|
|
1175
1195
|
listWebhookSubscriptions: () => listWebhookSubscriptions,
|
|
1196
|
+
previewIntent: () => previewIntent,
|
|
1176
1197
|
promoteSyndicateMember: () => promoteSyndicateMember,
|
|
1177
1198
|
reactivateWebhookSubscription: () => reactivateWebhookSubscription,
|
|
1199
|
+
reenableWebhookEndpoint: () => reenableWebhookEndpoint,
|
|
1178
1200
|
regenerateWebhookSecret: () => regenerateWebhookSecret,
|
|
1179
1201
|
registerAsPartner: () => registerAsPartner,
|
|
1180
1202
|
removeSyndicateMember: () => removeSyndicateMember,
|
|
@@ -1182,10 +1204,16 @@ __export(sdk_gen_exports, {
|
|
|
1182
1204
|
resendSyndicateInvite: () => resendSyndicateInvite,
|
|
1183
1205
|
restoreSyndicateMember: () => restoreSyndicateMember,
|
|
1184
1206
|
revokeConnectedApp: () => revokeConnectedApp,
|
|
1207
|
+
revokeInstallation: () => revokeInstallation,
|
|
1185
1208
|
revokePartnerInvite: () => revokePartnerInvite,
|
|
1209
|
+
rotateWebhookEndpointSecret: () => rotateWebhookEndpointSecret,
|
|
1210
|
+
searchCompanies: () => searchCompanies,
|
|
1211
|
+
testWebhookEndpoint: () => testWebhookEndpoint,
|
|
1186
1212
|
testWebhookSubscription: () => testWebhookSubscription,
|
|
1213
|
+
unfollowCompany: () => unfollowCompany,
|
|
1187
1214
|
updateSyndicate: () => updateSyndicate,
|
|
1188
|
-
updateSyndicateMember: () => updateSyndicateMember
|
|
1215
|
+
updateSyndicateMember: () => updateSyndicateMember,
|
|
1216
|
+
updateWebhookEndpoint: () => updateWebhookEndpoint
|
|
1189
1217
|
});
|
|
1190
1218
|
|
|
1191
1219
|
// src/generated/client.gen.ts
|
|
@@ -1193,6 +1221,12 @@ var client = createClient(createConfig());
|
|
|
1193
1221
|
|
|
1194
1222
|
// src/generated/sdk.gen.ts
|
|
1195
1223
|
var listOfferings = (options) => (options?.client ?? client).get({
|
|
1224
|
+
querySerializer: {
|
|
1225
|
+
parameters: {
|
|
1226
|
+
industry: { array: { explode: false } },
|
|
1227
|
+
business_model: { array: { explode: false } }
|
|
1228
|
+
}
|
|
1229
|
+
},
|
|
1196
1230
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1197
1231
|
url: "/explore",
|
|
1198
1232
|
...options
|
|
@@ -1202,16 +1236,87 @@ var getOffering = (options) => (options.client ?? client).get({
|
|
|
1202
1236
|
url: "/offerings/{external_id}",
|
|
1203
1237
|
...options
|
|
1204
1238
|
});
|
|
1239
|
+
var getCompanyDisclosures = (options) => (options.client ?? client).get({
|
|
1240
|
+
querySerializer: {
|
|
1241
|
+
parameters: { sections: { array: { explode: false } } }
|
|
1242
|
+
},
|
|
1243
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1244
|
+
url: "/companies/{id}/disclosures",
|
|
1245
|
+
...options
|
|
1246
|
+
});
|
|
1247
|
+
var getCompanyPitch = (options) => (options.client ?? client).get({
|
|
1248
|
+
querySerializer: {
|
|
1249
|
+
parameters: { sections: { array: { explode: false } } }
|
|
1250
|
+
},
|
|
1251
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1252
|
+
url: "/companies/{id}/pitch",
|
|
1253
|
+
...options
|
|
1254
|
+
});
|
|
1255
|
+
var listCompanyUpdates = (options) => (options.client ?? client).get({
|
|
1256
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1257
|
+
url: "/companies/{id}/updates",
|
|
1258
|
+
...options
|
|
1259
|
+
});
|
|
1260
|
+
var getCompanyUpdate = (options) => (options.client ?? client).get({
|
|
1261
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1262
|
+
url: "/companies/{id}/updates/{update_id}",
|
|
1263
|
+
...options
|
|
1264
|
+
});
|
|
1265
|
+
var listCompanyQuestions = (options) => (options.client ?? client).get({
|
|
1266
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1267
|
+
url: "/companies/{id}/questions",
|
|
1268
|
+
...options
|
|
1269
|
+
});
|
|
1270
|
+
var searchCompanies = (options) => (options.client ?? client).get({
|
|
1271
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1272
|
+
url: "/companies/search",
|
|
1273
|
+
...options
|
|
1274
|
+
});
|
|
1275
|
+
var getCompany = (options) => (options.client ?? client).get({
|
|
1276
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1277
|
+
url: "/companies/{id}",
|
|
1278
|
+
...options
|
|
1279
|
+
});
|
|
1205
1280
|
var getCurrentUser = (options) => (options?.client ?? client).get({
|
|
1206
1281
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1207
1282
|
url: "/users/me",
|
|
1208
1283
|
...options
|
|
1209
1284
|
});
|
|
1285
|
+
var listMyCompanies = (options) => (options?.client ?? client).get({
|
|
1286
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1287
|
+
url: "/users/me/companies",
|
|
1288
|
+
...options
|
|
1289
|
+
});
|
|
1290
|
+
var listFollowedCompanies = (options) => (options?.client ?? client).get({
|
|
1291
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1292
|
+
url: "/users/me/follows",
|
|
1293
|
+
...options
|
|
1294
|
+
});
|
|
1295
|
+
var unfollowCompany = (options) => (options.client ?? client).delete({
|
|
1296
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1297
|
+
url: "/users/me/follows/{company_id}",
|
|
1298
|
+
...options
|
|
1299
|
+
});
|
|
1300
|
+
var followCompany = (options) => (options.client ?? client).put({
|
|
1301
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1302
|
+
url: "/users/me/follows/{company_id}",
|
|
1303
|
+
...options
|
|
1304
|
+
});
|
|
1210
1305
|
var listInvestments = (options) => (options?.client ?? client).get({
|
|
1211
1306
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1212
1307
|
url: "/investments",
|
|
1213
1308
|
...options
|
|
1214
1309
|
});
|
|
1310
|
+
var getInvestment = (options) => (options.client ?? client).get({
|
|
1311
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1312
|
+
url: "/investments/{id}",
|
|
1313
|
+
...options
|
|
1314
|
+
});
|
|
1315
|
+
var getOfferingStats = (options) => (options.client ?? client).get({
|
|
1316
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1317
|
+
url: "/offerings/{offering_id}/stats",
|
|
1318
|
+
...options
|
|
1319
|
+
});
|
|
1215
1320
|
var getPortfolio = (options) => (options?.client ?? client).get({
|
|
1216
1321
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1217
1322
|
url: "/portfolio",
|
|
@@ -1363,6 +1468,15 @@ var finalizeSyndicateDeal = (options) => (options.client ?? client).post({
|
|
|
1363
1468
|
url: "/syndicates/{syndicate_id}/deals/{fundraise_id}/finalize",
|
|
1364
1469
|
...options
|
|
1365
1470
|
});
|
|
1471
|
+
var previewIntent = (options) => (options.client ?? client).post({
|
|
1472
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1473
|
+
url: "/intents/preview",
|
|
1474
|
+
...options,
|
|
1475
|
+
headers: {
|
|
1476
|
+
"Content-Type": "application/json",
|
|
1477
|
+
...options.headers
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1366
1480
|
var listIntents = (options) => (options?.client ?? client).get({
|
|
1367
1481
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1368
1482
|
url: "/intents",
|
|
@@ -1407,6 +1521,96 @@ var listAttributedInvestments = (options) => (options.client ?? client).get({
|
|
|
1407
1521
|
url: "/campaigns/{campaign_id}/attribution/investments",
|
|
1408
1522
|
...options
|
|
1409
1523
|
});
|
|
1524
|
+
var listInstallations = (options) => (options?.client ?? client).get({
|
|
1525
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1526
|
+
url: "/installations",
|
|
1527
|
+
...options
|
|
1528
|
+
});
|
|
1529
|
+
var createInstallation = (options) => (options.client ?? client).post({
|
|
1530
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1531
|
+
url: "/installations",
|
|
1532
|
+
...options,
|
|
1533
|
+
headers: {
|
|
1534
|
+
"Content-Type": "application/json",
|
|
1535
|
+
...options.headers
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
var listEligibleInstallTargets = (options) => (options?.client ?? client).get({
|
|
1539
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1540
|
+
url: "/installations/eligible",
|
|
1541
|
+
...options
|
|
1542
|
+
});
|
|
1543
|
+
var revokeInstallation = (options) => (options.client ?? client).delete({
|
|
1544
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1545
|
+
url: "/installations/{external_id}",
|
|
1546
|
+
...options
|
|
1547
|
+
});
|
|
1548
|
+
var getInstallation = (options) => (options.client ?? client).get({
|
|
1549
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1550
|
+
url: "/installations/{external_id}",
|
|
1551
|
+
...options
|
|
1552
|
+
});
|
|
1553
|
+
var createInstallationToken = (options) => (options.client ?? client).post({
|
|
1554
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1555
|
+
url: "/installations/{external_id}/tokens",
|
|
1556
|
+
...options,
|
|
1557
|
+
headers: {
|
|
1558
|
+
"Content-Type": "application/json",
|
|
1559
|
+
...options.headers
|
|
1560
|
+
}
|
|
1561
|
+
});
|
|
1562
|
+
var listWebhookEndpoints = (options) => (options?.client ?? client).get({
|
|
1563
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1564
|
+
url: "/webhook_endpoints",
|
|
1565
|
+
...options
|
|
1566
|
+
});
|
|
1567
|
+
var createWebhookEndpoint = (options) => (options.client ?? client).post({
|
|
1568
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1569
|
+
url: "/webhook_endpoints",
|
|
1570
|
+
...options,
|
|
1571
|
+
headers: {
|
|
1572
|
+
"Content-Type": "application/json",
|
|
1573
|
+
...options.headers
|
|
1574
|
+
}
|
|
1575
|
+
});
|
|
1576
|
+
var deleteWebhookEndpoint = (options) => (options.client ?? client).delete({
|
|
1577
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1578
|
+
url: "/webhook_endpoints/{external_id}",
|
|
1579
|
+
...options
|
|
1580
|
+
});
|
|
1581
|
+
var getWebhookEndpoint = (options) => (options.client ?? client).get({
|
|
1582
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1583
|
+
url: "/webhook_endpoints/{external_id}",
|
|
1584
|
+
...options
|
|
1585
|
+
});
|
|
1586
|
+
var updateWebhookEndpoint = (options) => (options.client ?? client).patch({
|
|
1587
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1588
|
+
url: "/webhook_endpoints/{external_id}",
|
|
1589
|
+
...options,
|
|
1590
|
+
headers: {
|
|
1591
|
+
"Content-Type": "application/json",
|
|
1592
|
+
...options.headers
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
var rotateWebhookEndpointSecret = (options) => (options.client ?? client).post({
|
|
1596
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1597
|
+
url: "/webhook_endpoints/{external_id}/rotate_secret",
|
|
1598
|
+
...options
|
|
1599
|
+
});
|
|
1600
|
+
var reenableWebhookEndpoint = (options) => (options.client ?? client).post({
|
|
1601
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1602
|
+
url: "/webhook_endpoints/{external_id}/reenable",
|
|
1603
|
+
...options
|
|
1604
|
+
});
|
|
1605
|
+
var testWebhookEndpoint = (options) => (options.client ?? client).post({
|
|
1606
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1607
|
+
url: "/webhook_endpoints/{external_id}/test",
|
|
1608
|
+
...options,
|
|
1609
|
+
headers: {
|
|
1610
|
+
"Content-Type": "application/json",
|
|
1611
|
+
...options.headers
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1410
1614
|
var listWebhookSubscriptions = (options) => (options.client ?? client).get({
|
|
1411
1615
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1412
1616
|
url: "/campaigns/{campaign_id}/attribution/webhooks",
|
|
@@ -1624,10 +1828,17 @@ var Wefunder = class _Wefunder {
|
|
|
1624
1828
|
getOffering({ client: this.#client, path: { external_id: externalId } })
|
|
1625
1829
|
)
|
|
1626
1830
|
};
|
|
1831
|
+
/**
|
|
1832
|
+
* Investments (`read:investments`). `list` is a bootstrap listing; pass `updated_since`
|
|
1833
|
+
* or a saved `cursor` for sync mode (`meta.mode === "delta"`). Persist `meta.next_cursor`
|
|
1834
|
+
* from your last page — it is always present — and resume from it next time.
|
|
1835
|
+
*/
|
|
1627
1836
|
investments = {
|
|
1628
1837
|
list: this.#page(listInvestments),
|
|
1629
|
-
all: () => paginate((cursor) => this.investments.list({ cursor })),
|
|
1630
|
-
collect: () => collect((cursor) => this.investments.list({ cursor }))
|
|
1838
|
+
all: (query) => paginate((cursor) => this.investments.list({ ...query, cursor })),
|
|
1839
|
+
collect: (query) => collect((cursor) => this.investments.list({ ...query, cursor })),
|
|
1840
|
+
/** The current record (not the published projection) for one investment (`inv_…`). */
|
|
1841
|
+
get: (id) => this.#unwrapData(getInvestment({ client: this.#client, path: { id } }))
|
|
1631
1842
|
};
|
|
1632
1843
|
portfolio = {
|
|
1633
1844
|
get: (query) => this.#unwrapData(getPortfolio({ client: this.#client, query })),
|
|
@@ -1657,17 +1868,76 @@ var Wefunder = class _Wefunder {
|
|
|
1657
1868
|
attribution = {
|
|
1658
1869
|
me: () => this.#unwrapData(getAttributionMe({ client: this.#client }))
|
|
1659
1870
|
};
|
|
1871
|
+
/**
|
|
1872
|
+
* Webhook endpoints (`/webhook_endpoints`, scopes `read:webhooks` / `write:webhooks`).
|
|
1873
|
+
* Endpoints belong to your application and are managed through the LIVE API —
|
|
1874
|
+
* create sandbox receivers there with `mode: "test"`; they're mirrored into
|
|
1875
|
+
* sandbox. The signing `secret` is returned ONLY by `create` and `rotateSecret`.
|
|
1876
|
+
* Verify deliveries with `constructEvent` (see the webhooks module).
|
|
1877
|
+
*/
|
|
1878
|
+
webhookEndpoints = {
|
|
1879
|
+
/** All of your app's endpoints (secret omitted). `meta.quota` is the per-app limit. */
|
|
1880
|
+
list: () => this.#unwrap(listWebhookEndpoints({ client: this.#client })),
|
|
1881
|
+
get: (id) => this.#unwrapData(
|
|
1882
|
+
getWebhookEndpoint({ client: this.#client, path: { external_id: id } })
|
|
1883
|
+
),
|
|
1884
|
+
/** Store `attributes.secret` from the result — it is never shown again. */
|
|
1885
|
+
create: (input) => this.#unwrapData(createWebhookEndpoint({ client: this.#client, body: input })),
|
|
1886
|
+
/** `events` replaces the subscription list wholesale (no merge); omit to leave unchanged. */
|
|
1887
|
+
update: (id, input) => this.#unwrapData(
|
|
1888
|
+
updateWebhookEndpoint({ client: this.#client, path: { external_id: id }, body: input })
|
|
1889
|
+
),
|
|
1890
|
+
/** Stops deliveries immediately. Removal is permanent — create a new endpoint to resume. */
|
|
1891
|
+
remove: (id) => this.#unwrapData(
|
|
1892
|
+
deleteWebhookEndpoint({ client: this.#client, path: { external_id: id } })
|
|
1893
|
+
),
|
|
1894
|
+
/**
|
|
1895
|
+
* New secret (shown once). The old one keeps signing for a 24h overlap — deliveries
|
|
1896
|
+
* carry a `v1` for both, and `constructEvent` accepts either.
|
|
1897
|
+
*/
|
|
1898
|
+
rotateSecret: (id) => this.#unwrapData(
|
|
1899
|
+
rotateWebhookEndpointSecret({ client: this.#client, path: { external_id: id } })
|
|
1900
|
+
),
|
|
1901
|
+
/** Recover an auto-disabled endpoint after fixing your server. Idempotent. */
|
|
1902
|
+
reenable: (id) => this.#unwrapData(
|
|
1903
|
+
reenableWebhookEndpoint({ client: this.#client, path: { external_id: id } })
|
|
1904
|
+
),
|
|
1905
|
+
/**
|
|
1906
|
+
* POST a real, signed example event at the endpoint (production envelope + signature)
|
|
1907
|
+
* and report the outcome inline. Defaults to the endpoint's first subscribed event.
|
|
1908
|
+
* Doesn't affect delivery health. Rate-limited to 10/min per endpoint.
|
|
1909
|
+
*/
|
|
1910
|
+
test: (id, event) => this.#unwrapData(
|
|
1911
|
+
testWebhookEndpoint({
|
|
1912
|
+
client: this.#client,
|
|
1913
|
+
path: { external_id: id },
|
|
1914
|
+
body: event ? { event } : void 0
|
|
1915
|
+
})
|
|
1916
|
+
)
|
|
1917
|
+
};
|
|
1660
1918
|
};
|
|
1661
1919
|
|
|
1662
1920
|
// src/webhooks.ts
|
|
1663
1921
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
1664
|
-
var SIGNATURE_HEADER = "
|
|
1665
|
-
var
|
|
1666
|
-
var
|
|
1667
|
-
var
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1922
|
+
var SIGNATURE_HEADER = "wefunder-signature";
|
|
1923
|
+
var DEFAULT_TOLERANCE_SECONDS = 300;
|
|
1924
|
+
var LEGACY_SIGNATURE_HEADER = "x-wefunder-signature";
|
|
1925
|
+
var LEGACY_TIMESTAMP_HEADER = "x-wefunder-timestamp";
|
|
1926
|
+
var LEGACY_EVENT_HEADER = "x-wefunder-event";
|
|
1927
|
+
var LEGACY_DELIVERY_ID_HEADER = "x-wefunder-delivery-id";
|
|
1928
|
+
var WebhookSignatureError = class extends Error {
|
|
1929
|
+
reason;
|
|
1930
|
+
constructor(reason, message) {
|
|
1931
|
+
super(message);
|
|
1932
|
+
this.name = "WebhookSignatureError";
|
|
1933
|
+
this.reason = reason;
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
function bodyBuffer(payload) {
|
|
1937
|
+
return typeof payload === "string" ? Buffer.from(payload, "utf8") : Buffer.from(payload);
|
|
1938
|
+
}
|
|
1939
|
+
function computeWebhookSignature(secret, timestamp, payload) {
|
|
1940
|
+
return createHmac("sha256", secret).update(`${timestamp}.`).update(bodyBuffer(payload)).digest("hex");
|
|
1671
1941
|
}
|
|
1672
1942
|
function constantTimeEqual(a, b) {
|
|
1673
1943
|
const ab = Buffer.from(a);
|
|
@@ -1675,66 +1945,175 @@ function constantTimeEqual(a, b) {
|
|
|
1675
1945
|
if (ab.length !== bb.length) return false;
|
|
1676
1946
|
return timingSafeEqual(ab, bb);
|
|
1677
1947
|
}
|
|
1948
|
+
function parseSignatureHeader(header) {
|
|
1949
|
+
let timestamp;
|
|
1950
|
+
const signatures = [];
|
|
1951
|
+
for (const part of header.split(",")) {
|
|
1952
|
+
const eq = part.indexOf("=");
|
|
1953
|
+
if (eq < 0) continue;
|
|
1954
|
+
const key = part.slice(0, eq).trim();
|
|
1955
|
+
const value = part.slice(eq + 1).trim();
|
|
1956
|
+
if (key === "t") {
|
|
1957
|
+
if (!/^\d+$/.test(value)) return null;
|
|
1958
|
+
timestamp = Number(value);
|
|
1959
|
+
} else if (key === "v1" && value) {
|
|
1960
|
+
signatures.push(value);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
if (timestamp === void 0 || signatures.length === 0) return null;
|
|
1964
|
+
return { timestamp, signatures };
|
|
1965
|
+
}
|
|
1966
|
+
function signWebhook(opts) {
|
|
1967
|
+
const t = opts.timestamp ?? Math.floor(Date.now() / 1e3);
|
|
1968
|
+
const secrets = [opts.secret, ...opts.additionalSecrets ?? []];
|
|
1969
|
+
const entries = secrets.map((s) => `v1=${computeWebhookSignature(s, t, opts.payload)}`);
|
|
1970
|
+
return [`t=${t}`, ...entries].join(",");
|
|
1971
|
+
}
|
|
1972
|
+
function checkWebhookSignature(opts) {
|
|
1973
|
+
const parsed = parseSignatureHeader(opts.header);
|
|
1974
|
+
if (!parsed) return "malformed_header";
|
|
1975
|
+
const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
|
|
1976
|
+
if (tolerance > 0) {
|
|
1977
|
+
const nowSec = (opts.now ?? Date.now)() / 1e3;
|
|
1978
|
+
if (Math.abs(nowSec - parsed.timestamp) > tolerance) return "timestamp_out_of_tolerance";
|
|
1979
|
+
}
|
|
1980
|
+
const expected = computeWebhookSignature(opts.secret, parsed.timestamp, opts.payload);
|
|
1981
|
+
return parsed.signatures.some((sig) => constantTimeEqual(sig, expected)) ? null : "signature_mismatch";
|
|
1982
|
+
}
|
|
1678
1983
|
function verifyWebhook(opts) {
|
|
1679
|
-
|
|
1680
|
-
|
|
1984
|
+
if ("header" in opts) return checkWebhookSignature(opts) === null;
|
|
1985
|
+
return verifyLegacyWebhook(opts);
|
|
1986
|
+
}
|
|
1987
|
+
function verifyLegacyWebhook(opts) {
|
|
1988
|
+
const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
|
|
1681
1989
|
const ts = Number(opts.timestamp);
|
|
1682
1990
|
if (!Number.isFinite(ts)) return false;
|
|
1683
|
-
if (tolerance > 0 && Math.abs(now / 1e3 - ts) > tolerance) return false;
|
|
1684
|
-
const expected =
|
|
1991
|
+
if (tolerance > 0 && Math.abs((opts.now ?? Date.now)() / 1e3 - ts) > tolerance) return false;
|
|
1992
|
+
const expected = `sha256=${computeWebhookSignature(opts.secret, opts.timestamp, opts.payload)}`;
|
|
1685
1993
|
return constantTimeEqual(opts.signature, expected);
|
|
1686
1994
|
}
|
|
1687
|
-
function
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1995
|
+
function headerGetter(headers) {
|
|
1996
|
+
if (typeof headers === "string") {
|
|
1997
|
+
return (name) => name === SIGNATURE_HEADER ? headers : void 0;
|
|
1998
|
+
}
|
|
1999
|
+
if (headers instanceof Headers) return (name) => headers.get(name) ?? void 0;
|
|
2000
|
+
return (name) => {
|
|
2001
|
+
let v = headers[name];
|
|
2002
|
+
if (v === void 0) {
|
|
2003
|
+
const hit = Object.keys(headers).find((k) => k.toLowerCase() === name);
|
|
2004
|
+
if (hit) v = headers[hit];
|
|
2005
|
+
}
|
|
1691
2006
|
return Array.isArray(v) ? v[0] : v;
|
|
1692
2007
|
};
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
2008
|
+
}
|
|
2009
|
+
function constructEvent(payload, headers, secret, opts) {
|
|
2010
|
+
const get = headerGetter(headers);
|
|
2011
|
+
const header = get(SIGNATURE_HEADER);
|
|
2012
|
+
if (!header) {
|
|
2013
|
+
const legacySig = get(LEGACY_SIGNATURE_HEADER);
|
|
2014
|
+
const legacyTs = get(LEGACY_TIMESTAMP_HEADER);
|
|
2015
|
+
if (legacySig && legacyTs) return constructLegacyEvent(payload, get, legacySig, legacyTs, secret, opts);
|
|
2016
|
+
throw new WebhookSignatureError("missing_header", describeFailure("missing_header"));
|
|
2017
|
+
}
|
|
2018
|
+
const failure = checkWebhookSignature({ payload, header, secret, ...opts });
|
|
2019
|
+
if (failure) throw new WebhookSignatureError(failure, describeFailure(failure));
|
|
2020
|
+
const parsed = parseSignatureHeader(header);
|
|
2021
|
+
const env = parseEnvelope(payload);
|
|
1707
2022
|
return {
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
2023
|
+
id: String(env.id ?? ""),
|
|
2024
|
+
event: String(env.event ?? ""),
|
|
2025
|
+
created_at: String(env.created_at ?? ""),
|
|
2026
|
+
mode: env.mode === "test" ? "test" : "live",
|
|
2027
|
+
data: env.data,
|
|
2028
|
+
timestamp: parsed.timestamp
|
|
1712
2029
|
};
|
|
1713
2030
|
}
|
|
2031
|
+
function constructLegacyEvent(payload, get, signature, timestamp, secret, opts) {
|
|
2032
|
+
if (!verifyLegacyWebhook({ payload, signature, timestamp, secret, ...opts })) {
|
|
2033
|
+
throw new WebhookSignatureError("signature_mismatch", describeFailure("signature_mismatch"));
|
|
2034
|
+
}
|
|
2035
|
+
const env = parseEnvelope(payload);
|
|
2036
|
+
return {
|
|
2037
|
+
id: String(env.id ?? get(LEGACY_DELIVERY_ID_HEADER) ?? ""),
|
|
2038
|
+
event: String(env.event ?? get(LEGACY_EVENT_HEADER) ?? ""),
|
|
2039
|
+
created_at: String(env.created_at ?? ""),
|
|
2040
|
+
mode: env.mode === "test" ? "test" : "live",
|
|
2041
|
+
data: env.data ?? env,
|
|
2042
|
+
timestamp: Number(timestamp)
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
function parseEnvelope(payload) {
|
|
2046
|
+
try {
|
|
2047
|
+
const parsed = JSON.parse(bodyBuffer(payload).toString("utf8"));
|
|
2048
|
+
if (parsed === null || typeof parsed !== "object") throw new Error("not an object");
|
|
2049
|
+
return parsed;
|
|
2050
|
+
} catch {
|
|
2051
|
+
throw new WebhookSignatureError("invalid_payload", describeFailure("invalid_payload"));
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
function describeFailure(reason) {
|
|
2055
|
+
switch (reason) {
|
|
2056
|
+
case "missing_header":
|
|
2057
|
+
return "Missing Wefunder-Signature header";
|
|
2058
|
+
case "malformed_header":
|
|
2059
|
+
return "Wefunder-Signature header is malformed (expected t=<unix>,v1=<hex>)";
|
|
2060
|
+
case "timestamp_out_of_tolerance":
|
|
2061
|
+
return "Webhook timestamp is outside the replay tolerance";
|
|
2062
|
+
case "signature_mismatch":
|
|
2063
|
+
return "Webhook signature verification failed";
|
|
2064
|
+
case "invalid_payload":
|
|
2065
|
+
return "Webhook body is not a JSON object";
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
async function constructEventFromRequest(request, secret, opts) {
|
|
2069
|
+
const payload = await request.text();
|
|
2070
|
+
return constructEvent(payload, request.headers, secret, opts);
|
|
2071
|
+
}
|
|
2072
|
+
async function dispatchWebhook(event, handlers) {
|
|
2073
|
+
const specific = event.event === "default" ? void 0 : handlers[event.event];
|
|
2074
|
+
if (specific) {
|
|
2075
|
+
await specific(event);
|
|
2076
|
+
return true;
|
|
2077
|
+
}
|
|
2078
|
+
if (handlers.default) {
|
|
2079
|
+
await handlers.default(event);
|
|
2080
|
+
return true;
|
|
2081
|
+
}
|
|
2082
|
+
return false;
|
|
2083
|
+
}
|
|
1714
2084
|
export {
|
|
1715
2085
|
DEFAULT_API_BASE_URL,
|
|
1716
2086
|
DEFAULT_API_VERSION,
|
|
1717
2087
|
DEFAULT_AUTHORIZE_BASE_URL,
|
|
1718
2088
|
DEFAULT_OAUTH_BASE_URL,
|
|
1719
2089
|
DEFAULT_TOKEN_BASE_URL,
|
|
1720
|
-
|
|
1721
|
-
|
|
2090
|
+
DEFAULT_TOLERANCE_SECONDS,
|
|
2091
|
+
LEGACY_DELIVERY_ID_HEADER,
|
|
2092
|
+
LEGACY_EVENT_HEADER,
|
|
2093
|
+
LEGACY_SIGNATURE_HEADER,
|
|
2094
|
+
LEGACY_TIMESTAMP_HEADER,
|
|
1722
2095
|
REQUEST_ID_HEADER,
|
|
1723
2096
|
SANDBOX_AUTHORIZE_BASE_URL,
|
|
1724
2097
|
SIGNATURE_HEADER,
|
|
1725
|
-
|
|
2098
|
+
WebhookSignatureError,
|
|
1726
2099
|
Wefunder,
|
|
1727
2100
|
WefunderAuthError,
|
|
1728
2101
|
WefunderError,
|
|
2102
|
+
checkWebhookSignature,
|
|
1729
2103
|
clientCredentialsGrant,
|
|
1730
2104
|
collect,
|
|
2105
|
+
computeWebhookSignature,
|
|
1731
2106
|
constructEvent,
|
|
2107
|
+
constructEventFromRequest,
|
|
1732
2108
|
createAuthorizationUrl,
|
|
2109
|
+
dispatchWebhook,
|
|
1733
2110
|
exchangeCode,
|
|
1734
2111
|
generatePkce,
|
|
1735
2112
|
modeForToken,
|
|
1736
2113
|
paginate,
|
|
2114
|
+
parseSignatureHeader,
|
|
1737
2115
|
refreshToken,
|
|
2116
|
+
signWebhook,
|
|
1738
2117
|
verifyWebhook
|
|
1739
2118
|
};
|
|
1740
2119
|
//# sourceMappingURL=index.js.map
|