@vesant-sdk/transaction 0.1.1-next.f2f4e87 → 0.1.2-dev.8d808aa
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/dist/index.d.mts +188 -52
- package/dist/index.d.ts +188 -52
- package/dist/index.js +191 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +188 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,45 +1,47 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseClient, RequestOptions, BaseClientConfig, VesantError, WebhookDedupStore } from '@vesant-sdk/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* TypeScript types for the Transaction Monitoring (TM) Service
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
type
|
|
8
|
-
type
|
|
9
|
-
type TransactionStatus = "pending" | "processing" | "completed" | "failed" | "cancelled" | "reversed" | "
|
|
6
|
+
type TransactionType = "withdrawal" | "deposit" | "transfer" | "bet" | "payment" | "adjustment" | "payout";
|
|
7
|
+
type TransactionMode = "wire_transfer" | "crypto" | "swift" | "ach" | "bank_transfer" | "card";
|
|
8
|
+
type TransactionSubType = "sweepstakes" | "cash";
|
|
9
|
+
type TransactionStatus = "pending" | "processing" | "completed" | "failed" | "cancelled" | "reversed" | "blocked" | "flagged" | "hold" | "suspend";
|
|
10
10
|
interface TransactionCreateDTO {
|
|
11
11
|
tx_id: string;
|
|
12
12
|
reference: string;
|
|
13
|
-
tenant_id?: string;
|
|
14
13
|
customer_id: string;
|
|
15
14
|
transaction_type: TransactionType;
|
|
16
15
|
transaction_mode: TransactionMode;
|
|
16
|
+
sub_type?: TransactionSubType;
|
|
17
17
|
amount: string;
|
|
18
|
-
currency
|
|
19
|
-
/**
|
|
20
|
-
* Required for non-USD currencies. The backend only auto-converts when currency is "USD".
|
|
21
|
-
* If omitted for crypto or foreign-currency withdrawals, withheld_usd and released_usd
|
|
22
|
-
* will be 0 and the gateway will receive $0.
|
|
23
|
-
*/
|
|
18
|
+
/** Defaults server-side to `amount` when omitted and `currency` is USD. */
|
|
24
19
|
amount_usd?: number;
|
|
20
|
+
currency: string;
|
|
25
21
|
status?: TransactionStatus;
|
|
26
22
|
source_account?: string;
|
|
27
23
|
destination_account?: string;
|
|
28
24
|
country?: string;
|
|
29
25
|
ip_address?: string;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
/** Spelling matches the backend's JSON tag — `beneficiary_comment` is ignored by the API. */
|
|
27
|
+
benificiary_comment?: string;
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
29
|
+
transaction_date: string;
|
|
30
|
+
/** Device fingerprint ID from the Sift beacon. */
|
|
31
|
+
device_id?: string;
|
|
32
|
+
/** Session ID for session-level fraud signals. */
|
|
33
|
+
session_id?: string;
|
|
34
|
+
/** Raw User-Agent string forwarded to Sift for device classification. Falls back to the request's own header. */
|
|
35
|
+
user_agent?: string;
|
|
33
36
|
}
|
|
34
37
|
type WithholdingType = "none" | "backup_us" | "backup_non_us" | "treaty";
|
|
35
38
|
/** Reason backup withholding or treaty rate was applied. */
|
|
36
39
|
type WithholdingReason = "tin_not_verified" | "customer_tax_form_not_verified" | "b_notice_backup_withholding";
|
|
37
40
|
/**
|
|
38
|
-
* Reason a withdrawal was
|
|
41
|
+
* Reason a withdrawal was suspended (status = "suspend").
|
|
39
42
|
* Reflects TIN/W-9 deficiencies that triggered the tenant's configured transaction action.
|
|
40
43
|
*/
|
|
41
44
|
type HoldReason = "no_tax_profile_found" | "tin_rejected" | "tin_expired" | "tin_not_provided" | "tin_not_verified" | "form_not_certified";
|
|
42
|
-
type JSONB = Record<string, any>;
|
|
43
45
|
type Transaction = {
|
|
44
46
|
id: string;
|
|
45
47
|
tx_id: string;
|
|
@@ -48,26 +50,21 @@ type Transaction = {
|
|
|
48
50
|
customer_id: string;
|
|
49
51
|
transaction_type: TransactionType;
|
|
50
52
|
transaction_mode: TransactionMode;
|
|
53
|
+
sub_type?: TransactionSubType;
|
|
51
54
|
amount: string;
|
|
52
55
|
withheld_amount: string;
|
|
53
56
|
released_amount: string;
|
|
54
57
|
withholding_rate: number;
|
|
55
|
-
withholding_type
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
amount_usd?: number;
|
|
62
|
-
/** Withheld amount in USD. */
|
|
63
|
-
withheld_usd?: number;
|
|
64
|
-
/** Released (net) amount in USD. */
|
|
65
|
-
released_usd?: number;
|
|
58
|
+
withholding_type: string;
|
|
59
|
+
withholding_reason?: string;
|
|
60
|
+
hold_reason?: string;
|
|
61
|
+
amount_usd: number;
|
|
62
|
+
withheld_usd: number;
|
|
63
|
+
released_usd: number;
|
|
66
64
|
/**
|
|
67
65
|
* True when this is the customer's first withdrawal.
|
|
68
|
-
* Correct on the POST /transactions response and on tm.transaction.callback
|
|
69
|
-
*
|
|
70
|
-
* always returns false regardless of actual history.
|
|
66
|
+
* Correct on the POST /transactions response and on tm.transaction.callback.
|
|
67
|
+
* Not persisted — getTransaction() always returns false regardless of actual history.
|
|
71
68
|
*/
|
|
72
69
|
is_first_withdrawal?: boolean;
|
|
73
70
|
tax_year: number;
|
|
@@ -78,8 +75,8 @@ type Transaction = {
|
|
|
78
75
|
country?: string;
|
|
79
76
|
ip_address?: string;
|
|
80
77
|
risk_score: number;
|
|
81
|
-
metadata?:
|
|
82
|
-
|
|
78
|
+
metadata?: Record<string, unknown>;
|
|
79
|
+
benificiary_comment?: string;
|
|
83
80
|
transaction_date: string;
|
|
84
81
|
created_at: string;
|
|
85
82
|
updated_at: string;
|
|
@@ -96,45 +93,45 @@ interface TransactionClientConfig {
|
|
|
96
93
|
environment?: 'production' | 'sandbox';
|
|
97
94
|
}
|
|
98
95
|
/**
|
|
99
|
-
* Response from POST /api/v1/
|
|
96
|
+
* Response from POST /api/v1/transactions.
|
|
100
97
|
*
|
|
101
|
-
* Status → outcome mapping:
|
|
102
|
-
* "
|
|
103
|
-
*
|
|
104
|
-
* "
|
|
105
|
-
* "suspend" — blocked, hold_reason set, no funds moved
|
|
98
|
+
* Status → outcome mapping (withdrawal transactions only):
|
|
99
|
+
* "pending" — Vesant accepted; trigger the payment gateway (full release,
|
|
100
|
+
* backup withholding applied, or treaty rate applied)
|
|
101
|
+
* "suspend" — blocked, hold_reason set, no funds moved
|
|
106
102
|
*/
|
|
107
103
|
type TransactionCreateResponse = {
|
|
108
104
|
transaction: Transaction;
|
|
109
105
|
message: string;
|
|
110
106
|
};
|
|
111
107
|
/**
|
|
112
|
-
* Fired after every transaction is created.
|
|
113
|
-
* Delivers the final
|
|
114
|
-
* can mirror it without a separate polling call.
|
|
108
|
+
* Fired after every transaction is created and after a suspended transaction is released.
|
|
109
|
+
* Delivers the final compliance-evaluated state including withholding outcome.
|
|
115
110
|
*/
|
|
116
111
|
interface TransactionCallbackEvent {
|
|
117
112
|
event_type: "tm.transaction.callback";
|
|
113
|
+
id: string;
|
|
114
|
+
tenant_id: string;
|
|
115
|
+
entity_id: string;
|
|
116
|
+
user_id: string;
|
|
118
117
|
tx_id: string;
|
|
119
118
|
reference: string;
|
|
120
119
|
customer_id: string;
|
|
121
|
-
transaction_type:
|
|
122
|
-
transaction_mode:
|
|
123
|
-
status:
|
|
120
|
+
transaction_type: string;
|
|
121
|
+
transaction_mode: string;
|
|
122
|
+
status: string;
|
|
124
123
|
amount: string;
|
|
125
124
|
currency: string;
|
|
126
125
|
withheld_amount: string;
|
|
127
126
|
released_amount: string;
|
|
128
127
|
withholding_rate: number;
|
|
129
|
-
withholding_type:
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
withholding_type: string;
|
|
129
|
+
withholding_reason?: string | null;
|
|
130
|
+
hold_reason?: string | null;
|
|
132
131
|
amount_usd: number;
|
|
133
132
|
withheld_usd: number;
|
|
134
133
|
released_usd: number;
|
|
135
134
|
is_first_withdrawal: boolean;
|
|
136
|
-
/** Set when status is "suspend" or "hold"; null otherwise. */
|
|
137
|
-
hold_reason: HoldReason | null;
|
|
138
135
|
transaction_date: string;
|
|
139
136
|
}
|
|
140
137
|
/**
|
|
@@ -154,34 +151,173 @@ interface TransactionHeldEvent {
|
|
|
154
151
|
}
|
|
155
152
|
/** Discriminated union of all TM service webhook event payloads. */
|
|
156
153
|
type TransactionWebhookEvent = TransactionCallbackEvent | TransactionHeldEvent;
|
|
154
|
+
interface TmTenantSettings {
|
|
155
|
+
tenant_id: string;
|
|
156
|
+
transaction_monitoring_enabled: boolean;
|
|
157
|
+
tax_monitoring_enabled: boolean;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Semantic handler interface for the three withholding outcomes of a tm.transaction.callback.
|
|
161
|
+
* Register with TransactionWebhookHandler.registerCallbackHandler().
|
|
162
|
+
*/
|
|
163
|
+
interface TransactionCallbackHandler {
|
|
164
|
+
onWithheld?(event: TransactionCallbackEvent): void | Promise<void>;
|
|
165
|
+
onHeld?(event: TransactionCallbackEvent): void | Promise<void>;
|
|
166
|
+
onReleased?(event: TransactionCallbackEvent): void | Promise<void>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
type WithdrawalState = 'vesant_pending' | 'withheld' | 'suspend' | 'released' | 'failed';
|
|
170
|
+
declare class PendingWithdrawal {
|
|
171
|
+
private _state;
|
|
172
|
+
private _event;
|
|
173
|
+
private _error;
|
|
174
|
+
private _waitPromise;
|
|
175
|
+
private _resolveWait?;
|
|
176
|
+
private _rejectWait?;
|
|
177
|
+
readonly tx_id: string;
|
|
178
|
+
readonly initialTransaction: Transaction;
|
|
179
|
+
constructor(tx_id: string, transaction: Transaction);
|
|
180
|
+
status(): WithdrawalState;
|
|
181
|
+
callbackEvent(): TransactionCallbackEvent | null;
|
|
182
|
+
wait(signal?: AbortSignal): Promise<TransactionCallbackEvent>;
|
|
183
|
+
/** Called by TransactionWebhookHandler when the tm.transaction.callback arrives for this tx_id. */
|
|
184
|
+
_settle(event: TransactionCallbackEvent): void;
|
|
185
|
+
/** Called to fail the pending withdrawal with a generic error (e.g. abort, network loss). */
|
|
186
|
+
_fail(err: unknown): void;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
type CustomerType = 'US_PERSON' | 'NON_US_PERSON' | 'NON_US_ENTITY';
|
|
190
|
+
type CTPFormStatus = 'requested' | 'signed' | 'manual' | 'bounced' | 'uploaded' | 'expired' | 're_requested';
|
|
191
|
+
type CTPTINStatus = 'not_required' | 'pending' | 'submitted' | 'verified' | 'rejected' | 'error' | 'expired';
|
|
192
|
+
interface CustomerTaxProfileRecord {
|
|
193
|
+
id: string;
|
|
194
|
+
tenant_id: string;
|
|
195
|
+
customer_id: string;
|
|
196
|
+
customer_type: CustomerType;
|
|
197
|
+
form_type: string;
|
|
198
|
+
form_status: CTPFormStatus;
|
|
199
|
+
tin_status: CTPTINStatus;
|
|
200
|
+
tin_value?: string;
|
|
201
|
+
recipient_name?: string;
|
|
202
|
+
business_name?: string;
|
|
203
|
+
account_number?: string;
|
|
204
|
+
address?: string;
|
|
205
|
+
address_city?: string;
|
|
206
|
+
address_state?: string;
|
|
207
|
+
address_zip?: string;
|
|
208
|
+
address_country?: string;
|
|
209
|
+
customer_name?: string;
|
|
210
|
+
avalara_form_id?: string;
|
|
211
|
+
avalara_company_id?: string;
|
|
212
|
+
signed_at?: string;
|
|
213
|
+
verified_at?: string;
|
|
214
|
+
expiry_date?: string;
|
|
215
|
+
backup_withholding: boolean;
|
|
216
|
+
b_notice_received: boolean;
|
|
217
|
+
e_delivery_consent: boolean;
|
|
218
|
+
withholding_enabled_by?: string;
|
|
219
|
+
withholding_enabled_at?: string;
|
|
220
|
+
tin_due_date?: string;
|
|
221
|
+
last_tin_check?: string;
|
|
222
|
+
request_count: number;
|
|
223
|
+
reminders_sent: number;
|
|
224
|
+
last_reminder_at?: string;
|
|
225
|
+
created_at: string;
|
|
226
|
+
updated_at: string;
|
|
227
|
+
}
|
|
228
|
+
type TaxFormTrigger = 'trigger_account_creation' | 'trigger_first_withdrawal' | 'trigger_threshold' | 'trigger_manual' | 'trigger_tin_invalid' | 'trigger_w8ben_expiry' | 'trigger_tin_expired';
|
|
229
|
+
interface CustomerTaxProfileDocuments {
|
|
230
|
+
w_form: string;
|
|
231
|
+
'1099_form': string;
|
|
232
|
+
}
|
|
233
|
+
interface RequestTaxFormWithProfileInput {
|
|
234
|
+
customer_id: string;
|
|
235
|
+
email: string;
|
|
236
|
+
trigger: TaxFormTrigger;
|
|
237
|
+
first_name?: string;
|
|
238
|
+
last_name?: string;
|
|
239
|
+
date_of_birth?: string;
|
|
240
|
+
phone_number?: string;
|
|
241
|
+
country?: string;
|
|
242
|
+
state?: string;
|
|
243
|
+
city?: string;
|
|
244
|
+
zip_code?: string;
|
|
245
|
+
address?: string;
|
|
246
|
+
ip_address?: string;
|
|
247
|
+
form_type?: string;
|
|
248
|
+
}
|
|
249
|
+
interface RequestTaxFormWithProfileOutput {
|
|
250
|
+
profile?: CustomerTaxProfileRecord;
|
|
251
|
+
request_id?: string;
|
|
252
|
+
reference_id?: string;
|
|
253
|
+
form_id?: string;
|
|
254
|
+
public_url?: string;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
declare class TaxTransactionClient extends BaseClient {
|
|
258
|
+
getCustomerDocuments(customerID: string): Promise<CustomerTaxProfileDocuments>;
|
|
259
|
+
requestTaxFormWithProfile(input: RequestTaxFormWithProfileInput, requestOptions?: RequestOptions): Promise<RequestTaxFormWithProfileOutput>;
|
|
260
|
+
}
|
|
157
261
|
|
|
158
262
|
/**
|
|
159
263
|
* TransactionClient — SDK for the Transaction Monitoring service
|
|
160
264
|
*/
|
|
161
265
|
|
|
162
266
|
declare class TransactionClient extends BaseClient {
|
|
267
|
+
readonly tax: TaxTransactionClient;
|
|
163
268
|
constructor(config: BaseClientConfig);
|
|
269
|
+
/**
|
|
270
|
+
* Submit a transaction via the unified ingestion endpoint.
|
|
271
|
+
*
|
|
272
|
+
* POST /api/v1/transactions is gated on ANY of transaction monitoring, tax,
|
|
273
|
+
* or fraud being enabled for the tenant, so fraud-only and tax-only tenants
|
|
274
|
+
* can ingest even with TM switched off.
|
|
275
|
+
*/
|
|
164
276
|
createTransaction(request: TransactionCreateDTO, requestOptions?: RequestOptions): Promise<TransactionCreateResponse>;
|
|
277
|
+
submitWithdrawal(request: TransactionCreateDTO, requestOptions?: RequestOptions): Promise<PendingWithdrawal>;
|
|
165
278
|
getTransaction(transactionId: string, requestOptions?: RequestOptions): Promise<Transaction>;
|
|
279
|
+
getSettings(): Promise<TmTenantSettings>;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
declare class DuplicateTransactionError extends VesantError {
|
|
283
|
+
readonly tx_id: string;
|
|
284
|
+
constructor(tx_id: string, message?: string);
|
|
285
|
+
}
|
|
286
|
+
declare class TaxHoldError extends Error {
|
|
287
|
+
readonly tx_id: string;
|
|
288
|
+
readonly hold_reason: HoldReason;
|
|
289
|
+
readonly event: TransactionCallbackEvent;
|
|
290
|
+
constructor(event: TransactionCallbackEvent);
|
|
166
291
|
}
|
|
167
292
|
|
|
168
293
|
type EventHandler<T> = (event: T) => void | Promise<void>;
|
|
294
|
+
declare const TRANSACTION_SIGNATURE_HEADER = "x-webhook-signature";
|
|
169
295
|
interface TransactionWebhookHandlerConfig {
|
|
170
296
|
secret: string;
|
|
171
297
|
/** Reject duplicate event_type+tx_id pairs within replayWindow. Default: true. */
|
|
172
298
|
replayProtection?: boolean;
|
|
173
299
|
/** How long (ms) to remember seen events for replay detection. Default: 300_000 (5 min). */
|
|
174
300
|
replayWindow?: number;
|
|
301
|
+
/** Pluggable dedup store for replay protection (default: in-memory, process-local). */
|
|
302
|
+
dedupStore?: WebhookDedupStore;
|
|
175
303
|
}
|
|
176
304
|
declare class TransactionWebhookHandler {
|
|
177
305
|
private readonly handlers;
|
|
178
306
|
private readonly secret;
|
|
179
307
|
private readonly replayProtection;
|
|
180
308
|
private readonly replayWindow;
|
|
181
|
-
private
|
|
309
|
+
private readonly dedupStore;
|
|
310
|
+
private readonly pendingWithdrawals;
|
|
311
|
+
private callbackHandler;
|
|
182
312
|
constructor(config: TransactionWebhookHandlerConfig);
|
|
183
313
|
on(eventType: 'tm.transaction.callback', handler: EventHandler<TransactionCallbackEvent>): this;
|
|
184
314
|
on(eventType: 'tm.transaction.held', handler: EventHandler<TransactionHeldEvent>): this;
|
|
315
|
+
/** Register a semantic callback handler for the three withholding outcomes. Replaces any previous handler. */
|
|
316
|
+
registerCallbackHandler(handler: TransactionCallbackHandler): this;
|
|
317
|
+
/** Track a PendingWithdrawal so it is auto-settled when its tm.transaction.callback arrives. */
|
|
318
|
+
link(pending: PendingWithdrawal): this;
|
|
319
|
+
/** Stop tracking a PendingWithdrawal by tx_id. */
|
|
320
|
+
unlink(tx_id: string): this;
|
|
185
321
|
/** Verify HMAC-SHA256 signature only. Returns false instead of throwing. */
|
|
186
322
|
verify(rawBody: string, signature: string): Promise<boolean>;
|
|
187
323
|
/** Parse and validate required fields. Does not verify signature — use verifyAndParse in production. */
|
|
@@ -192,4 +328,4 @@ declare class TransactionWebhookHandler {
|
|
|
192
328
|
handle(body: string, signature: string): Promise<void>;
|
|
193
329
|
}
|
|
194
330
|
|
|
195
|
-
export { type HoldReason, type
|
|
331
|
+
export { type CTPFormStatus, type CTPTINStatus, type CustomerTaxProfileDocuments, type CustomerTaxProfileRecord, type CustomerType, DuplicateTransactionError, type HoldReason, PendingWithdrawal, type RequestTaxFormWithProfileInput, type RequestTaxFormWithProfileOutput, TRANSACTION_SIGNATURE_HEADER, type TaxFormTrigger, TaxHoldError, TaxTransactionClient, type TmTenantSettings, type Transaction, type TransactionCallbackEvent, type TransactionCallbackHandler, TransactionClient, type TransactionClientConfig, type TransactionCreateDTO, type TransactionCreateResponse, type TransactionHeldEvent, type TransactionMode, type TransactionStatus, type TransactionSubType, type TransactionType, type TransactionWebhookEvent, TransactionWebhookHandler, type TransactionWebhookHandlerConfig, type WithdrawalState, type WithholdingReason, type WithholdingType };
|