@forgezero/providers 0.1.22 → 0.1.24
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 +99 -60
- package/dist/billing.d.ts +305 -0
- package/dist/{binance.js → billing.js} +246 -345
- package/dist/database.js +1 -1
- package/dist/email.js +1 -1
- package/dist/git.d.ts +192 -0
- package/dist/{chain.js → git.js} +77 -145
- package/dist/http.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pool.js +1 -1
- package/dist/storage.js +1 -1
- package/dist/translation.js +1 -1
- package/package.json +10 -10
- package/dist/binance.d.ts +0 -27
- package/dist/chain.d.ts +0 -99
|
@@ -336,369 +336,270 @@ function createService(definition, methods, options = {}) {
|
|
|
336
336
|
}
|
|
337
337
|
};
|
|
338
338
|
}
|
|
339
|
-
var VERSION = "0.1.
|
|
339
|
+
var VERSION = "0.1.24";
|
|
340
340
|
|
|
341
|
-
// src/
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
341
|
+
// src/billing.ts
|
|
342
|
+
var PAYMENT_PROVIDER_KEYS = ["stripe:v1", "paypal:v1", "razorpay:v1"];
|
|
343
|
+
var paymentProviderDefinitions = [
|
|
344
|
+
{
|
|
345
|
+
id: "stripe",
|
|
346
|
+
label: "Stripe",
|
|
347
|
+
multiInstance: true,
|
|
348
|
+
config: {
|
|
349
|
+
type: "object",
|
|
350
|
+
properties: {
|
|
351
|
+
providerApiVersion: { type: "string", minLength: 4, maxLength: 64 },
|
|
352
|
+
mode: { type: "string", enum: ["test", "live"] }
|
|
353
|
+
},
|
|
354
|
+
required: ["providerApiVersion", "mode"],
|
|
355
|
+
additionalProperties: false
|
|
356
|
+
},
|
|
357
|
+
credentials: {
|
|
358
|
+
type: "object",
|
|
359
|
+
properties: {
|
|
360
|
+
secretKey: { type: "string", minLength: 16, maxLength: 512, writeOnly: true },
|
|
361
|
+
webhookSecret: { type: "string", minLength: 16, maxLength: 512, writeOnly: true }
|
|
362
|
+
},
|
|
363
|
+
required: ["secretKey", "webhookSecret"],
|
|
364
|
+
additionalProperties: false
|
|
365
|
+
},
|
|
366
|
+
methods: {}
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
id: "paypal",
|
|
370
|
+
label: "PayPal",
|
|
371
|
+
multiInstance: true,
|
|
372
|
+
config: {
|
|
373
|
+
type: "object",
|
|
374
|
+
properties: {
|
|
375
|
+
providerApiVersion: { type: "string", minLength: 2, maxLength: 64 },
|
|
376
|
+
environment: { type: "string", enum: ["sandbox", "live"] }
|
|
377
|
+
},
|
|
378
|
+
required: ["providerApiVersion", "environment"],
|
|
379
|
+
additionalProperties: false
|
|
380
|
+
},
|
|
381
|
+
credentials: {
|
|
382
|
+
type: "object",
|
|
383
|
+
properties: {
|
|
384
|
+
clientId: { type: "string", minLength: 10, maxLength: 512, writeOnly: true },
|
|
385
|
+
clientSecret: { type: "string", minLength: 10, maxLength: 512, writeOnly: true },
|
|
386
|
+
webhookId: { type: "string", minLength: 4, maxLength: 256, writeOnly: true }
|
|
387
|
+
},
|
|
388
|
+
required: ["clientId", "clientSecret", "webhookId"],
|
|
389
|
+
additionalProperties: false
|
|
390
|
+
},
|
|
391
|
+
methods: {}
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
id: "razorpay",
|
|
395
|
+
label: "Razorpay",
|
|
396
|
+
multiInstance: true,
|
|
397
|
+
config: {
|
|
398
|
+
type: "object",
|
|
399
|
+
properties: {
|
|
400
|
+
providerApiVersion: { type: "string", minLength: 2, maxLength: 64 },
|
|
401
|
+
mode: { type: "string", enum: ["test", "live"] }
|
|
402
|
+
},
|
|
403
|
+
required: ["providerApiVersion", "mode"],
|
|
404
|
+
additionalProperties: false
|
|
405
|
+
},
|
|
406
|
+
credentials: {
|
|
407
|
+
type: "object",
|
|
408
|
+
properties: {
|
|
409
|
+
keyId: { type: "string", minLength: 8, maxLength: 256, writeOnly: true },
|
|
410
|
+
keySecret: { type: "string", minLength: 8, maxLength: 512, writeOnly: true },
|
|
411
|
+
webhookSecret: { type: "string", minLength: 8, maxLength: 512, writeOnly: true }
|
|
412
|
+
},
|
|
413
|
+
required: ["keyId", "keySecret", "webhookSecret"],
|
|
414
|
+
additionalProperties: false
|
|
415
|
+
},
|
|
416
|
+
methods: {}
|
|
349
417
|
}
|
|
350
|
-
|
|
351
|
-
var
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
418
|
+
];
|
|
419
|
+
var billingService = defineService({
|
|
420
|
+
key: "billing",
|
|
421
|
+
methods: {
|
|
422
|
+
createHostedSetup: serviceMethod(),
|
|
423
|
+
completeHostedSetup: serviceMethod(),
|
|
424
|
+
createCustomer: serviceMethod(),
|
|
425
|
+
charge: serviceMethod(),
|
|
426
|
+
detachPaymentMethod: serviceMethod(),
|
|
427
|
+
verifyWebhook: serviceMethod(),
|
|
428
|
+
reconcile: serviceMethod()
|
|
361
429
|
}
|
|
362
|
-
|
|
363
|
-
|
|
430
|
+
});
|
|
431
|
+
function required(value, field, maximum = 512) {
|
|
432
|
+
const result = value.trim();
|
|
433
|
+
if (!result || result.length > maximum)
|
|
434
|
+
throw new Error(`PAYMENT_${field.toUpperCase()}_INVALID`);
|
|
435
|
+
return result;
|
|
436
|
+
}
|
|
437
|
+
function assertHostedInput(input) {
|
|
438
|
+
required(input.tenantKey, "tenant");
|
|
439
|
+
required(input.idempotencyKey, "idempotency", 200);
|
|
440
|
+
for (const [field, value] of [["return_url", input.returnUrl], ["cancel_url", input.cancelUrl]]) {
|
|
441
|
+
const url = new URL(required(value, field, 2048));
|
|
442
|
+
if (url.protocol !== "https:")
|
|
443
|
+
throw new Error(`PAYMENT_${field.toUpperCase()}_INVALID`);
|
|
364
444
|
}
|
|
365
|
-
current.spent += cost;
|
|
366
445
|
}
|
|
367
|
-
function
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
446
|
+
function assertChargeInput(input) {
|
|
447
|
+
required(input.tenantKey, "tenant");
|
|
448
|
+
required(input.invoiceKey, "invoice");
|
|
449
|
+
required(input.providerCustomerReference, "customer_reference");
|
|
450
|
+
required(input.providerPaymentMethodReference, "method_reference");
|
|
451
|
+
required(input.idempotencyKey, "idempotency", 200);
|
|
452
|
+
if (!/^[1-9][0-9]*$/.test(input.amountMinor))
|
|
453
|
+
throw new Error("PAYMENT_AMOUNT_INVALID");
|
|
454
|
+
if (input.currency !== "USD")
|
|
455
|
+
throw new Error("PAYMENT_CURRENCY_INVALID");
|
|
372
456
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
return {
|
|
378
|
-
async call(request) {
|
|
379
|
-
const reserved = request.weight ?? config.budget.defaultCost;
|
|
380
|
-
spend(config.budget, reserved, Date.now());
|
|
381
|
-
const url = new URL(config.baseUrl + request.path);
|
|
382
|
-
for (const [key, value] of Object.entries(request.query ?? {})) {
|
|
383
|
-
url.searchParams.set(key, String(value));
|
|
384
|
-
}
|
|
385
|
-
const controller = new AbortController;
|
|
386
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
387
|
-
try {
|
|
388
|
-
const response = await doFetch(url.toString(), {
|
|
389
|
-
method: request.method ?? "GET",
|
|
390
|
-
signal: controller.signal,
|
|
391
|
-
headers: {
|
|
392
|
-
...request.body === undefined ? {} : { "content-type": "application/json" },
|
|
393
|
-
...request.headers
|
|
394
|
-
},
|
|
395
|
-
...request.body === undefined ? {} : { body: JSON.stringify(request.body) }
|
|
396
|
-
});
|
|
397
|
-
const cost = config.costOf?.(response);
|
|
398
|
-
if (cost !== undefined)
|
|
399
|
-
settle(config.budget.host, reserved, cost);
|
|
400
|
-
const text = await response.text();
|
|
401
|
-
let body;
|
|
402
|
-
try {
|
|
403
|
-
body = text ? JSON.parse(text) : null;
|
|
404
|
-
} catch {
|
|
405
|
-
body = text;
|
|
406
|
-
}
|
|
407
|
-
if (!response.ok) {
|
|
408
|
-
throw Object.assign(new Error(`${config.budget.host} ${response.status}`), {
|
|
409
|
-
status: response.status,
|
|
410
|
-
body,
|
|
411
|
-
retryAfter: response.headers.get("retry-after")
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
return { status: response.status, body, cost };
|
|
415
|
-
} finally {
|
|
416
|
-
clearTimeout(timer);
|
|
417
|
-
}
|
|
418
|
-
},
|
|
419
|
-
budget: () => budgetState(config.budget.host)
|
|
420
|
-
};
|
|
457
|
+
function assertSetupCompletion(input) {
|
|
458
|
+
required(input.tenantKey, "tenant");
|
|
459
|
+
required(input.setupReference, "setup_reference", 512);
|
|
460
|
+
required(input.idempotencyKey, "idempotency", 200);
|
|
421
461
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
default: 0.9,
|
|
446
|
-
description: "Stop at this fraction of the limit. The venue's window boundary is not ours, and the penalty for crossing is a ban rather than a rejection."
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
},
|
|
450
|
-
async invoke(context, request) {
|
|
451
|
-
const config = context.config;
|
|
452
|
-
const client = createHttpClient({
|
|
453
|
-
baseUrl: config.baseUrl,
|
|
454
|
-
fetch: config.fetch,
|
|
455
|
-
costOf: config.costOf,
|
|
456
|
-
budget: {
|
|
457
|
-
host: new URL(config.baseUrl).host,
|
|
458
|
-
limit: config.limit ?? 6000,
|
|
459
|
-
windowMs: config.windowMs ?? 60000,
|
|
460
|
-
defaultCost: 1,
|
|
461
|
-
headroom: config.headroom
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
return client.call(request);
|
|
465
|
-
},
|
|
466
|
-
classify(error) {
|
|
467
|
-
const status = error.status;
|
|
468
|
-
if (status === 418)
|
|
469
|
-
return "backoff";
|
|
470
|
-
if (status === 429)
|
|
471
|
-
return "backoff";
|
|
472
|
-
if (status === 400 || status === 422)
|
|
473
|
-
return "terminal";
|
|
474
|
-
if (status === 401 || status === 403)
|
|
475
|
-
return "retryable";
|
|
476
|
-
return "retryable";
|
|
477
|
-
}
|
|
478
|
-
});
|
|
479
|
-
var binanceWeight = (response) => {
|
|
480
|
-
const header = response.headers.get("x-mbx-used-weight-1m");
|
|
481
|
-
return header === null ? undefined : Number(header);
|
|
482
|
-
};
|
|
483
|
-
var httpProviders = [http];
|
|
484
|
-
|
|
485
|
-
// src/binance.ts
|
|
486
|
-
import { parseAmount, formatAmount, zero, assetSpec } from "@forgezero/runtime/finance/money";
|
|
487
|
-
import {
|
|
488
|
-
parseSymbol,
|
|
489
|
-
VenueError
|
|
490
|
-
} from "@forgezero/runtime/finance/venues";
|
|
491
|
-
var BUDGET_HOST = "binance";
|
|
492
|
-
var DEFAULT_HOSTS = {
|
|
493
|
-
spot: "https://api.binance.com",
|
|
494
|
-
margin: "https://api.binance.com",
|
|
495
|
-
futures: "https://fapi.binance.com"
|
|
496
|
-
};
|
|
497
|
-
var binanceSymbol = (symbol) => {
|
|
498
|
-
const { base, quote } = parseSymbol(symbol);
|
|
499
|
-
return `${base}${quote}`;
|
|
500
|
-
};
|
|
501
|
-
var PATHS = {
|
|
502
|
-
spot: {
|
|
503
|
-
order: "/api/v3/order",
|
|
504
|
-
openOrders: "/api/v3/openOrders",
|
|
505
|
-
account: "/api/v3/account",
|
|
506
|
-
exchangeInfo: "/api/v3/exchangeInfo"
|
|
507
|
-
},
|
|
508
|
-
margin: {
|
|
509
|
-
order: "/sapi/v1/margin/order",
|
|
510
|
-
openOrders: "/sapi/v1/margin/openOrders",
|
|
511
|
-
account: "/sapi/v1/margin/account",
|
|
512
|
-
exchangeInfo: "/api/v3/exchangeInfo"
|
|
513
|
-
},
|
|
514
|
-
futures: {
|
|
515
|
-
order: "/fapi/v1/order",
|
|
516
|
-
openOrders: "/fapi/v1/openOrders",
|
|
517
|
-
account: "/fapi/v2/account",
|
|
518
|
-
exchangeInfo: "/fapi/v1/exchangeInfo"
|
|
462
|
+
function assertHostedResult(value) {
|
|
463
|
+
const hostedUrl = new URL(required(value.hostedUrl, "hosted_url", 2048));
|
|
464
|
+
if (hostedUrl.protocol !== "https:" || hostedUrl.username || hostedUrl.password)
|
|
465
|
+
throw new Error("PAYMENT_HOSTED_URL_INVALID");
|
|
466
|
+
required(value.setupReference, "setup_reference", 512);
|
|
467
|
+
if (!Number.isSafeInteger(value.expiresAtTs) || value.expiresAtTs <= Date.now())
|
|
468
|
+
throw new Error("PAYMENT_SETUP_EXPIRY_INVALID");
|
|
469
|
+
return { ...value, hostedUrl: hostedUrl.toString() };
|
|
470
|
+
}
|
|
471
|
+
function assertCompletionResult(value) {
|
|
472
|
+
required(value.providerPaymentMethodReference, "method_reference", 512);
|
|
473
|
+
if (value.providerCustomerReference !== undefined)
|
|
474
|
+
required(value.providerCustomerReference, "customer_reference", 512);
|
|
475
|
+
const display = value.display;
|
|
476
|
+
if (!display || !["card", "bank", "upi", "paypal", "other"].includes(display.type))
|
|
477
|
+
throw new Error("PAYMENT_DISPLAY_INVALID");
|
|
478
|
+
for (const [field, item, maximum] of [
|
|
479
|
+
["brand", display.brand, 80],
|
|
480
|
+
["last4", display.last4, 8],
|
|
481
|
+
["label", display.label, 160]
|
|
482
|
+
]) {
|
|
483
|
+
if (item !== undefined)
|
|
484
|
+
required(item, `display_${field}`, maximum);
|
|
519
485
|
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
return "accepted";
|
|
526
|
-
case "PARTIALLY_FILLED":
|
|
527
|
-
return "partial";
|
|
528
|
-
case "FILLED":
|
|
529
|
-
return "filled";
|
|
530
|
-
case "CANCELED":
|
|
531
|
-
case "PENDING_CANCEL":
|
|
532
|
-
case "EXPIRED":
|
|
533
|
-
case "EXPIRED_IN_MATCH":
|
|
534
|
-
return "cancelled";
|
|
535
|
-
default:
|
|
536
|
-
return "rejected";
|
|
486
|
+
if (display.last4 !== undefined && !/^[A-Za-z0-9]{1,8}$/.test(display.last4))
|
|
487
|
+
throw new Error("PAYMENT_DISPLAY_LAST4_INVALID");
|
|
488
|
+
for (const value2 of [display.expiresMonth, display.expiresYear]) {
|
|
489
|
+
if (value2 !== undefined && !Number.isSafeInteger(value2))
|
|
490
|
+
throw new Error("PAYMENT_DISPLAY_EXPIRY_INVALID");
|
|
537
491
|
}
|
|
492
|
+
if (display.expiresMonth !== undefined && (display.expiresMonth < 1 || display.expiresMonth > 12))
|
|
493
|
+
throw new Error("PAYMENT_DISPLAY_EXPIRY_INVALID");
|
|
494
|
+
return structuredClone(value);
|
|
538
495
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
async function sign(secret, query) {
|
|
542
|
-
const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
543
|
-
const mac = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(query));
|
|
544
|
-
return [...new Uint8Array(mac)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
496
|
+
function assertCustomerResult(value) {
|
|
497
|
+
return { providerCustomerReference: required(value.providerCustomerReference, "customer_reference", 512) };
|
|
545
498
|
}
|
|
546
|
-
function
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
clients.set(base, client);
|
|
563
|
-
return client;
|
|
564
|
-
};
|
|
565
|
-
async function signed(args) {
|
|
566
|
-
const entries = Object.entries(args.params).filter(([, value]) => value !== undefined);
|
|
567
|
-
const base = new URLSearchParams(entries.map(([name, value]) => [name, String(value)])).toString();
|
|
568
|
-
const withTiming = `${base}${base ? "&" : ""}recvWindow=${recvWindow}×tamp=${now()}`;
|
|
569
|
-
const signature = await sign(options.credentials.apiSecret, withTiming);
|
|
570
|
-
const response = await clientFor(args.type).call({
|
|
571
|
-
path: `${args.path}?${withTiming}&signature=${signature}`,
|
|
572
|
-
method: args.method,
|
|
573
|
-
weight: args.weight,
|
|
574
|
-
headers: { "X-MBX-APIKEY": options.credentials.apiKey }
|
|
575
|
-
});
|
|
576
|
-
return response.body;
|
|
577
|
-
}
|
|
499
|
+
function assertChargeResult(value) {
|
|
500
|
+
const providerAttemptReference = required(value.providerAttemptReference, "attempt_reference", 512);
|
|
501
|
+
if (!["succeeded", "failed", "pending"].includes(value.status))
|
|
502
|
+
throw new Error("PAYMENT_STATUS_INVALID");
|
|
503
|
+
const failureCode = value.failureCode === undefined ? undefined : required(value.failureCode, "failure_code", 160);
|
|
504
|
+
return { providerAttemptReference, status: value.status, ...failureCode ? { failureCode } : {} };
|
|
505
|
+
}
|
|
506
|
+
function assertWebhookResult(value) {
|
|
507
|
+
const providerEventId = required(value.providerEventId, "event_id", 512);
|
|
508
|
+
const eventType = required(value.eventType, "event_type", 160);
|
|
509
|
+
const resourceReference = required(value.resourceReference, "resource_reference", 512);
|
|
510
|
+
if (!["succeeded", "failed", "pending"].includes(value.status))
|
|
511
|
+
throw new Error("PAYMENT_STATUS_INVALID");
|
|
512
|
+
if (!Number.isSafeInteger(value.occurredAtTs) || value.occurredAtTs < 0)
|
|
513
|
+
throw new Error("PAYMENT_EVENT_TIME_INVALID");
|
|
514
|
+
const failureCode = value.failureCode === undefined ? undefined : required(value.failureCode, "failure_code", 160);
|
|
578
515
|
return {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
516
|
+
providerEventId,
|
|
517
|
+
eventType,
|
|
518
|
+
resourceReference,
|
|
519
|
+
status: value.status,
|
|
520
|
+
occurredAtTs: value.occurredAtTs,
|
|
521
|
+
...failureCode ? { failureCode } : {}
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
function assertReconciliationResult(value) {
|
|
525
|
+
const providerAttemptReference = required(value.providerAttemptReference, "attempt_reference", 512);
|
|
526
|
+
if (!["succeeded", "failed", "pending", "not_found"].includes(value.status))
|
|
527
|
+
throw new Error("PAYMENT_STATUS_INVALID");
|
|
528
|
+
const failureCode = value.failureCode === undefined ? undefined : required(value.failureCode, "failure_code", 160);
|
|
529
|
+
return { providerAttemptReference, status: value.status, ...failureCode ? { failureCode } : {} };
|
|
530
|
+
}
|
|
531
|
+
function paymentProviderAdapter(args) {
|
|
532
|
+
const [provider, contractVersion] = args.key.split(":");
|
|
533
|
+
const providerApiVersion = required(args.providerApiVersion, "api_version", 100);
|
|
534
|
+
return Object.freeze({
|
|
535
|
+
key: args.key,
|
|
536
|
+
provider,
|
|
537
|
+
contractVersion,
|
|
538
|
+
providerApiVersion,
|
|
539
|
+
async createHostedSetup(input) {
|
|
540
|
+
assertHostedInput(input);
|
|
541
|
+
return assertHostedResult(await args.driver.createHostedSetup(input));
|
|
597
542
|
},
|
|
598
|
-
async
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
type: "futures",
|
|
602
|
-
path: "/fapi/v1/leverage",
|
|
603
|
-
method: "POST",
|
|
604
|
-
params: { symbol: binanceSymbol(request.symbol), leverage: request.leverage }
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
const raw = await signed({
|
|
608
|
-
type: request.type,
|
|
609
|
-
path: PATHS[request.type].order,
|
|
610
|
-
method: "POST",
|
|
611
|
-
weight: 1,
|
|
612
|
-
params: {
|
|
613
|
-
symbol: binanceSymbol(request.symbol),
|
|
614
|
-
side: SIDE[request.side],
|
|
615
|
-
type: TYPE[request.orderType],
|
|
616
|
-
quantity: formatAmount(request.quantity, { trim: true }),
|
|
617
|
-
price: request.price ? formatAmount(request.price, { trim: true }) : undefined,
|
|
618
|
-
stopPrice: request.stopPrice ? formatAmount(request.stopPrice, { trim: true }) : undefined,
|
|
619
|
-
timeInForce: request.orderType === "market" ? undefined : (request.timeInForce ?? "gtc").toUpperCase(),
|
|
620
|
-
newClientOrderId: request.clientOrderId,
|
|
621
|
-
...request.type === "margin" ? { sideEffectType: "NO_SIDE_EFFECT" } : {},
|
|
622
|
-
...request.dryRun ? { test: "true" } : {}
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
return readOrder(raw, market);
|
|
543
|
+
async completeHostedSetup(input) {
|
|
544
|
+
assertSetupCompletion(input);
|
|
545
|
+
return assertCompletionResult(await args.driver.completeHostedSetup(input));
|
|
626
546
|
},
|
|
627
|
-
async
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
params: { symbol: binanceSymbol(args.symbol), orderId: args.venueOrderId }
|
|
633
|
-
});
|
|
547
|
+
async createCustomer(input) {
|
|
548
|
+
required(input.tenantKey, "tenant");
|
|
549
|
+
required(input.email, "email");
|
|
550
|
+
required(input.idempotencyKey, "idempotency", 200);
|
|
551
|
+
return assertCustomerResult(await args.driver.createCustomer(input));
|
|
634
552
|
},
|
|
635
|
-
async
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
path: PATHS[args.type].openOrders,
|
|
639
|
-
method: "GET",
|
|
640
|
-
weight: args.symbol ? 3 : 40,
|
|
641
|
-
params: { symbol: args.symbol ? binanceSymbol(args.symbol) : undefined }
|
|
642
|
-
});
|
|
643
|
-
return (raw ?? []).map((entry) => readOrder(entry, undefined));
|
|
553
|
+
async charge(input) {
|
|
554
|
+
assertChargeInput(input);
|
|
555
|
+
return assertChargeResult(await args.driver.charge(input));
|
|
644
556
|
},
|
|
645
|
-
async
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
}
|
|
557
|
+
async detachPaymentMethod(input) {
|
|
558
|
+
required(input.tenantKey, "tenant");
|
|
559
|
+
required(input.providerPaymentMethodReference, "method_reference");
|
|
560
|
+
required(input.idempotencyKey, "idempotency", 200);
|
|
561
|
+
return args.driver.detachPaymentMethod(input);
|
|
562
|
+
},
|
|
563
|
+
async verifyWebhook(input) {
|
|
564
|
+
if (!(input.rawBody instanceof Uint8Array) || input.rawBody.byteLength > 1048576) {
|
|
565
|
+
throw new Error("PAYMENT_WEBHOOK_BODY_INVALID");
|
|
566
|
+
}
|
|
567
|
+
return assertWebhookResult(await args.driver.verifyWebhook(input));
|
|
568
|
+
},
|
|
569
|
+
async reconcile(input) {
|
|
570
|
+
required(input.tenantKey, "tenant");
|
|
571
|
+
required(input.providerAttemptReference, "attempt_reference");
|
|
572
|
+
return assertReconciliationResult(await args.driver.reconcile(input));
|
|
655
573
|
}
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
function readOrder(raw, market) {
|
|
659
|
-
const asset = market?.base ?? "BTC";
|
|
660
|
-
const executed = String(raw.executedQty ?? raw.origQty ?? "0");
|
|
661
|
-
let filledQuantity;
|
|
662
|
-
try {
|
|
663
|
-
filledQuantity = parseAmount(executed, asset);
|
|
664
|
-
} catch {
|
|
665
|
-
filledQuantity = zero(asset);
|
|
666
|
-
}
|
|
667
|
-
const quoteFilled = Number(raw.cummulativeQuoteQty ?? 0);
|
|
668
|
-
const filled = Number(executed);
|
|
669
|
-
return {
|
|
670
|
-
venueOrderId: String(raw.orderId ?? ""),
|
|
671
|
-
clientOrderId: raw.clientOrderId ? String(raw.clientOrderId) : undefined,
|
|
672
|
-
status: toOrderStatus(String(raw.status ?? "NEW")),
|
|
673
|
-
filledQuantity,
|
|
674
|
-
...market && filled > 0 && quoteFilled > 0 ? {
|
|
675
|
-
averagePrice: (() => {
|
|
676
|
-
try {
|
|
677
|
-
return parseAmount((quoteFilled / filled).toFixed(assetSpec(market.quote).decimals), market.quote);
|
|
678
|
-
} catch {
|
|
679
|
-
return;
|
|
680
|
-
}
|
|
681
|
-
})()
|
|
682
|
-
} : {},
|
|
683
|
-
raw
|
|
684
|
-
};
|
|
574
|
+
});
|
|
685
575
|
}
|
|
686
|
-
function
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
576
|
+
function definePaymentProvider(args) {
|
|
577
|
+
const classify = args.classify ?? (() => "retryable");
|
|
578
|
+
const branch = (invoke) => defineProviderMethodBranches({
|
|
579
|
+
currentVersion: args.version,
|
|
580
|
+
versions: { [args.version]: { version: args.version, lifecycle: "current", invoke, classify } }
|
|
581
|
+
});
|
|
582
|
+
return defineProvider({
|
|
583
|
+
id: args.id,
|
|
584
|
+
label: args.label,
|
|
585
|
+
multiInstance: true,
|
|
586
|
+
config: args.config,
|
|
587
|
+
credentials: args.credentials,
|
|
588
|
+
methods: {
|
|
589
|
+
createHostedSetup: branch(args.driver.createHostedSetup),
|
|
590
|
+
completeHostedSetup: branch(args.driver.completeHostedSetup),
|
|
591
|
+
createCustomer: branch(args.driver.createCustomer),
|
|
592
|
+
charge: branch(args.driver.charge),
|
|
593
|
+
detachPaymentMethod: branch(args.driver.detachPaymentMethod),
|
|
594
|
+
verifyWebhook: branch(args.driver.verifyWebhook),
|
|
595
|
+
reconcile: branch(args.driver.reconcile)
|
|
596
|
+
}
|
|
597
|
+
});
|
|
698
598
|
}
|
|
699
599
|
export {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
600
|
+
paymentProviderDefinitions,
|
|
601
|
+
paymentProviderAdapter,
|
|
602
|
+
definePaymentProvider,
|
|
603
|
+
billingService,
|
|
604
|
+
PAYMENT_PROVIDER_KEYS
|
|
704
605
|
};
|
package/dist/database.js
CHANGED
package/dist/email.js
CHANGED