@nile-squad/nylonpay-ts 1.0.3 → 1.0.4
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.cjs +23 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +23 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -325,10 +325,14 @@ var TERMINAL_STATES = /* @__PURE__ */ new Set([
|
|
|
325
325
|
"failed",
|
|
326
326
|
"cancelled"
|
|
327
327
|
]);
|
|
328
|
+
function normalizeStatus(raw) {
|
|
329
|
+
if (raw === "completed") return "successful";
|
|
330
|
+
return raw;
|
|
331
|
+
}
|
|
328
332
|
function createPaymentInstance(initialResponse, deps) {
|
|
329
333
|
const state = {
|
|
330
334
|
reference: initialResponse.reference,
|
|
331
|
-
status: initialResponse.status,
|
|
335
|
+
status: normalizeStatus(initialResponse.status),
|
|
332
336
|
transaction: null,
|
|
333
337
|
pollingTimer: null,
|
|
334
338
|
resolved: false,
|
|
@@ -363,7 +367,8 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
363
367
|
state.transaction = txResult.value;
|
|
364
368
|
const event = statusToEvent(status);
|
|
365
369
|
if (event) {
|
|
366
|
-
|
|
370
|
+
const error = status === "failed" ? state.transaction.failureReason ?? void 0 : void 0;
|
|
371
|
+
emitEvent(event, error);
|
|
367
372
|
}
|
|
368
373
|
} else {
|
|
369
374
|
emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
|
|
@@ -378,7 +383,7 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
378
383
|
);
|
|
379
384
|
return;
|
|
380
385
|
}
|
|
381
|
-
const newStatus = response.status;
|
|
386
|
+
const newStatus = normalizeStatus(response.status);
|
|
382
387
|
const oldStatus = state.status;
|
|
383
388
|
state.status = newStatus;
|
|
384
389
|
if (newStatus !== oldStatus) {
|
|
@@ -437,6 +442,12 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
437
442
|
scheduleNextPoll();
|
|
438
443
|
}
|
|
439
444
|
function startPolling() {
|
|
445
|
+
if (TERMINAL_STATES.has(state.status ?? "pending")) {
|
|
446
|
+
setTimeout(() => {
|
|
447
|
+
void handleTerminalState(state.status);
|
|
448
|
+
}, 0);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
440
451
|
scheduleNextPoll();
|
|
441
452
|
}
|
|
442
453
|
function stopPolling() {
|
|
@@ -458,37 +469,28 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
458
469
|
return paymentInstance;
|
|
459
470
|
}
|
|
460
471
|
function wait() {
|
|
461
|
-
return new Promise((resolve
|
|
472
|
+
return new Promise((resolve) => {
|
|
462
473
|
if (state.resolved) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
reject(new Error(`Payment ${state.status ?? "error"}`));
|
|
467
|
-
}
|
|
474
|
+
resolve(
|
|
475
|
+
state.status === "successful" && state.transaction ? state.transaction : null
|
|
476
|
+
);
|
|
468
477
|
return;
|
|
469
478
|
}
|
|
470
479
|
function onSuccess() {
|
|
471
480
|
cleanup();
|
|
472
|
-
|
|
473
|
-
resolve(state.transaction);
|
|
474
|
-
} else {
|
|
475
|
-
reject(
|
|
476
|
-
new Error("Payment successful but transaction data unavailable")
|
|
477
|
-
);
|
|
478
|
-
}
|
|
481
|
+
resolve(state.transaction ?? null);
|
|
479
482
|
}
|
|
480
483
|
function onFailed() {
|
|
481
484
|
cleanup();
|
|
482
|
-
|
|
485
|
+
resolve(null);
|
|
483
486
|
}
|
|
484
487
|
function onCancelled() {
|
|
485
488
|
cleanup();
|
|
486
|
-
|
|
489
|
+
resolve(null);
|
|
487
490
|
}
|
|
488
|
-
function onError(
|
|
491
|
+
function onError() {
|
|
489
492
|
cleanup();
|
|
490
|
-
|
|
491
|
-
reject(new Error(eventData.error ?? "Payment error"));
|
|
493
|
+
resolve(null);
|
|
492
494
|
}
|
|
493
495
|
function cleanup() {
|
|
494
496
|
state.emitter.off("success", onSuccess);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pubsub.ts","../src/fingerprint.ts","../src/nonce.ts","../src/sdk.config.ts","../src/signature.ts","../src/verify-response.ts","../src/transport.ts","../src/payment.ts","../src/verify-webhook.ts","../src/sdk.ts","../src/create-nylon-pay.ts"],"names":["type","platform","arch","release","hostname","createHash","randomBytes","createHmac","timingSafeEqual","Err","Ok"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Simple internal pubsub/event emitter for SDK payment lifecycle events.\n * Functional implementation without classes.\n *\n * @see Spec 2 section 2 - \"emits events such as nylonpay.on('success', (data) => {})\"\n *\n * @example\n * ```ts\n * const emitter = createEmitter<PaymentEvent>();\n * emitter.on(\"success\", (data) => console.log(data));\n * emitter.emit(\"success\", { event: \"success\", timestamp: \"...\" });\n * emitter.off(\"success\", handler);\n * ```\n */\n\n/**\n * Handler function type for event listeners.\n */\nexport type EventHandler<T = unknown> = (data: T) => void;\n\n/**\n * Internal state for the emitter.\n * @internal\n */\ninterface EmitterState<T> {\n listeners: Map<T, Set<EventHandler<T>>>;\n}\n\n/**\n * Create a new event emitter instance.\n *\n * @returns Emitter with on/off/emit methods\n *\n * @example\n * ```ts\n * const emitter = createEmitter<string>();\n * const unsub = emitter.on(\"hello\", (msg) => console.log(msg));\n * emitter.emit(\"hello\", \"world\");\n * unsub(); // remove listener\n * ```\n */\nexport function createEmitter<T extends string>() {\n const state: EmitterState<T> = {\n listeners: new Map(),\n };\n\n /**\n * Subscribe to an event.\n * Returns an unsubscribe function for convenience.\n */\n function on(event: T, handler: EventHandler): () => void {\n if (!state.listeners.has(event)) {\n state.listeners.set(event, new Set());\n }\n state.listeners.get(event)?.add(handler as EventHandler<unknown>);\n return () => off(event, handler);\n }\n\n /**\n * Subscribe to an event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal payment events (e.g. \"successful\", \"failed\").\n * Returns the emitter for chaining.\n */\n function once(event: T, handler: EventHandler): typeof emitter {\n const wrapper: EventHandler = (data) => {\n off(event, wrapper);\n handler(data);\n };\n on(event, wrapper);\n return emitter;\n }\n\n /**\n * Unsubscribe from an event.\n */\n function off(event: T, handler: EventHandler): void {\n const handlers = state.listeners.get(event);\n if (handlers) {\n handlers.delete(handler as EventHandler<unknown>);\n }\n }\n\n /**\n * Emit an event with data to all listeners.\n * Handlers are called synchronously in subscription order.\n */\n function emit(event: T, data: unknown): void {\n const handlers = state.listeners.get(event);\n if (!handlers || handlers.size === 0) return;\n for (const handler of handlers) {\n try {\n (handler as EventHandler<unknown>)(data);\n } catch {\n // Swallow handler errors to prevent one bad handler\n // from breaking the entire event chain\n }\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n */\n function clear(event?: T): void {\n if (event) {\n state.listeners.delete(event);\n } else {\n state.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event.\n */\n function listenerCount(event: T): number {\n return state.listeners.get(event)?.size ?? 0;\n }\n\n const emitter = { on, once, off, emit, clear, listenerCount };\n return emitter;\n}\n\n/**\n * Type for the emitter interface returned by createEmitter.\n */\nexport type Emitter<T extends string> = ReturnType<typeof createEmitter<T>>;\n","/**\n * Server fingerprint generation for SDK requests.\n * Provides a stable identifier based on runtime environment.\n *\n * @see Spec 2 section 1 - \"a server fingerprint based on runtime, os, etc\"\n */\n\nimport { createHash } from \"node:crypto\";\nimport { arch, hostname, platform, release, type } from \"node:os\";\n\n/**\n * Generate a server fingerprint based on runtime environment.\n * This provides a stable identifier for the server making requests.\n * The fingerprint is a SHA-256 hash of system characteristics.\n *\n * @returns Hex-encoded SHA-256 hash of system info\n *\n * @example\n * ```ts\n * const fingerprint = generateFingerprint();\n * // => \"e3b0c44298fc1c149afbf4c8996fb924...\"\n * ```\n */\nexport function generateFingerprint(): string {\n const components = [\n `type:${type()}`,\n `platform:${platform()}`,\n `arch:${arch()}`,\n `release:${release()}`,\n `hostname:${hostname()}`,\n `node:${process.versions.node}`,\n `v8:${process.versions.v8}`,\n ].join(\"|\");\n\n return createHash(\"sha256\").update(components).digest(\"hex\");\n}\n","/**\n * Cryptographically secure nonce generation for SDK requests.\n *\n * @see Spec 2 section 1 - \"Internally the sdk generates a nounce\"\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Generate a cryptographically secure random nonce.\n * Uses Node.js crypto.randomBytes for security.\n *\n * @param length - Byte length of the nonce (default: 16 = 32 hex chars)\n * @returns Hex-encoded random string\n *\n * @example\n * ```ts\n * const nonce = generateNonce();\n * // => \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4\"\n * ```\n */\nexport function generateNonce(length = 16): string {\n return randomBytes(length).toString(\"hex\");\n}\n","/** Default production backend URL */\nexport const DEFAULT_BASE_URL =\n \"https://api.nylonpay.nilesquad.com/api/services\";\n\n/** Default request timeout (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Default max retry attempts for transport failures */\nexport const DEFAULT_MAX_RETRIES = 3;\n\n/** Default polling interval between status checks (2 seconds) */\nexport const DEFAULT_MAX_POLL_INTERVAL_MS = 2_000;\n\n/** Default max total polling duration before timing out (5 minutes) */\nexport const DEFAULT_MAX_POLL_DURATION_MS = 300_000;\n\n/** Default max polling attempts before giving up */\nexport const DEFAULT_MAX_POLL_ATTEMPTS = 150;\n\n/** Nile.js service name for all SDK operations */\nexport const SDK_SERVICE = \"sdk\";\n\n/** Maps SDK operation names to backend action names */\nexport const SDK_ACTIONS = {\n collectPayment: \"sdk-collect-payment\",\n collectPaymentAndResolve: \"sdk-collect-payment-and-resolve\",\n makePayout: \"sdk-make-payout\",\n makePayoutAndResolve: \"sdk-make-payout-and-resolve\",\n getStatus: \"sdk-get-status\",\n getTransaction: \"sdk-get-transaction\",\n verifyPhone: \"sdk-verify-phone\",\n createInvoice: \"sdk-create-invoice\",\n} as const;\n\n/** HTTP status codes that trigger retries */\nexport const RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n","/**\n * HMAC-SHA256 signature creation for SDK requests.\n * Must match the backend's verification logic in verify-signature.ts.\n *\n * Signature payload format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * @see backend/src/services/sdk/verify-signature.ts\n * @see Spec 2 section 1 - \"creates a signature using these values and the api secret (HMAC 256)\"\n */\n\nimport { createHmac } from \"node:crypto\";\n\n/**\n * Recursively sort object keys alphabetically for deterministic JSON.\n * Must match backend's createCanonicalPayload function.\n *\n * @see backend/src/services/sdk/create-canonical-payload.ts\n */\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => sortValue(entry));\n }\n\n if (value && typeof value === \"object\") {\n const sortedEntries = Object.entries(value as Record<string, unknown>).sort(\n ([firstKey], [secondKey]) => firstKey.localeCompare(secondKey),\n );\n\n return Object.fromEntries(\n sortedEntries.map(([entryKey, entryValue]) => [\n entryKey,\n sortValue(entryValue),\n ]),\n );\n }\n\n return value;\n}\n\n/**\n * Create a canonical JSON string from a payload.\n * Keys are sorted alphabetically for deterministic serialization.\n */\nexport function createCanonicalPayload(payload: unknown): string {\n return JSON.stringify(sortValue(payload));\n}\n\n/**\n * Build the signature payload string.\n * Format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * The fingerprint is included in the signature to prevent tampering\n * with server identity information.\n *\n * @see backend/src/services/sdk/verify-signature.ts:createSignaturePayload\n */\nexport function createSignaturePayload(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n timestamp: string;\n}): string {\n return `${input.fingerprint}.${input.nonce}.${input.timestamp}.${createCanonicalPayload(input.payload)}`;\n}\n\n/**\n * Create an HMAC-SHA256 signature for SDK request authentication.\n *\n * The signature includes the server fingerprint to ensure the request\n * origin cannot be spoofed. The fingerprint contains runtime/OS info\n * that is bound to this specific server instance.\n *\n * @param input.fingerprint - Server fingerprint (included in signature)\n * @param input.nonce - Random nonce for replay protection\n * @param input.timestamp - Unix timestamp in milliseconds\n * @param input.payload - Request body (will be canonicalized)\n * @param input.secret - API secret for signing\n * @returns Hex-encoded HMAC-SHA256 signature\n */\nexport function createSignature(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n secret: string;\n timestamp: string;\n}): string {\n const payload = createSignaturePayload(input);\n\n return createHmac(\"sha256\", input.secret).update(payload).digest(\"hex\");\n}\n\n/**\n * Create a timestamp string in milliseconds.\n * Used as part of the signature payload.\n */\nexport function createTimestamp(): string {\n return Date.now().toString();\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { createCanonicalPayload } from \"./signature\";\n\n/**\n * Verify an authenticated backend response body before exposing it to SDK\n * consumers so tampered payloads are rejected consistently.\n *\n * @param data - Response payload without the `_responseSignature` field\n * @param signature - Hex-encoded HMAC-SHA256 signature from the backend\n * @param secret - API secret used for request authentication\n * @returns True when the signature matches the payload\n */\nexport function verifyResponseSignature(\n data: unknown,\n signature: string,\n secret: string,\n): boolean {\n const expectedSignature = createHmac(\"sha256\", secret)\n .update(createCanonicalPayload(data))\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * HTTP transport layer for SDK communication with the Nylon Pay backend.\n * Handles the Nile.js envelope format, HMAC request signing, response\n * signature verification, retries, and timeouts.\n *\n * @internal\n */\n\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { generateFingerprint } from \"./fingerprint\";\nimport { generateNonce } from \"./nonce\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n RETRYABLE_STATUS_CODES,\n SDK_SERVICE,\n} from \"./sdk.config\";\nimport { createSignature, createTimestamp } from \"./signature\";\nimport type { SdkError, TransportRequest } from \"./types\";\nimport { verifyResponseSignature } from \"./verify-response\";\n\n/** Cached fingerprint for this server instance. */\nconst CACHED_FINGERPRINT = generateFingerprint();\n\n/** Calculate exponential backoff delay with jitter. */\nfunction calculateBackoff(attempt: number): number {\n const base = 2 ** attempt * 1000;\n const jitter = Math.random() * 500;\n return base + jitter;\n}\n\n/** Promise-based delay. */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Strip _responseSignature from a payload and return it separately. */\nfunction stripResponseSignature<T>(payload: T): {\n data: T;\n responseSignature: string | null;\n} {\n if (\n !payload ||\n typeof payload !== \"object\" ||\n !(\"_responseSignature\" in payload)\n ) {\n return { data: payload, responseSignature: null };\n }\n\n const { _responseSignature, ...rest } = payload as Record<string, unknown>;\n\n return {\n data: rest as T,\n responseSignature:\n typeof _responseSignature === \"string\" ? _responseSignature : null,\n };\n}\n\n/** Build the Nile.js request envelope. */\nfunction buildEnvelope({\n action,\n payload,\n}: TransportRequest): Record<string, unknown> {\n return {\n intent: \"execute\",\n service: SDK_SERVICE,\n action,\n payload: {\n ...(payload as Record<string, unknown>),\n _fingerprint: CACHED_FINGERPRINT,\n },\n };\n}\n\n/**\n * Build auth headers for a request.\n *\n * The signature is computed over the inner `payload` (the operation input plus\n * `_fingerprint`), NOT the full Nile envelope. This matches the server, which\n * verifies the signature against the raw request payload — see the Transport\n * Contract in the Nylon Pay SDK Spec (https://github.com/nile-squad/specs).\n */\nfunction buildAuthHeaders({\n apiKey,\n apiSecret,\n payload,\n}: {\n apiKey: string;\n apiSecret: string;\n payload: unknown;\n}): Record<string, string> {\n const nonce = generateNonce();\n const timestamp = createTimestamp();\n const signature = createSignature({\n fingerprint: CACHED_FINGERPRINT,\n nonce,\n timestamp,\n payload,\n secret: apiSecret,\n });\n\n return {\n \"content-type\": \"application/json\",\n \"x-nylon-key\": apiKey,\n \"x-nylon-nonce\": nonce,\n \"x-nylon-signature\": signature,\n \"x-nylon-timestamp\": timestamp,\n };\n}\n\n/** Create an AbortController with a timeout. Returns cleanup to clear the timer. */\nfunction withTimeout(timeoutMs: number): {\n controller: AbortController;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n return { controller, cleanup: () => clearTimeout(timeoutId) };\n}\n\n/**\n * Create the transport layer for SDK requests.\n *\n * @param config - Resolved SDK configuration\n * @returns Transport functions\n *\n * @internal\n */\nexport function createTransport({\n apiKey,\n apiSecret,\n baseUrl = DEFAULT_BASE_URL,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n maxRetries = DEFAULT_MAX_RETRIES,\n fetch: fetchImpl,\n}: {\n apiKey: string;\n apiSecret: string;\n baseUrl?: string;\n timeoutMs?: number;\n maxRetries?: number;\n fetch: typeof globalThis.fetch;\n}) {\n /**\n * Send a request to the backend.\n * Builds the envelope and headers once, then retries only the fetch call.\n */\n async function send<T>(\n request: TransportRequest,\n ): Promise<Result<T, string>> {\n const envelope = buildEnvelope(request);\n const signedPayload = (envelope as { payload: unknown }).payload;\n const headers = buildAuthHeaders({\n apiKey,\n apiSecret,\n payload: signedPayload,\n });\n const bodyString = JSON.stringify(envelope);\n\n async function attempt(currentAttempt: number): Promise<Result<T, string>> {\n const { controller, cleanup } = withTimeout(timeoutMs);\n\n try {\n const response = await fetchImpl(baseUrl, {\n method: \"POST\",\n headers,\n body: bodyString,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const statusCode = response.status;\n const retryable = RETRYABLE_STATUS_CODES.has(statusCode);\n\n let errorMessage = `HTTP ${statusCode}`;\n try {\n const errorBody = await response.json();\n if (\n errorBody &&\n typeof errorBody === \"object\" &&\n \"message\" in errorBody\n ) {\n errorMessage = String(errorBody.message);\n }\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n if (retryable && currentAttempt < maxRetries) {\n cleanup();\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n const sdkError: SdkError = {\n code: `HTTP_${statusCode}`,\n message: errorMessage,\n statusCode,\n retryable,\n };\n\n cleanup();\n return Err(JSON.stringify(sdkError));\n }\n\n const responseBody = await response.json();\n\n if (\n !responseBody ||\n typeof responseBody !== \"object\" ||\n !(\"status\" in responseBody)\n ) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"INVALID_RESPONSE\",\n message: \"Response missing status field\",\n retryable: false,\n }),\n );\n }\n\n const { status, message, data } = responseBody as {\n status: boolean;\n message: string;\n data: unknown;\n };\n\n if (status === true) {\n const { data: strippedData, responseSignature } =\n stripResponseSignature(data);\n\n if (responseSignature) {\n const isValid = verifyResponseSignature(\n strippedData,\n responseSignature,\n apiSecret,\n );\n if (!isValid) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"RESPONSE_TAMPERED\",\n message: \"Response signature verification failed\",\n retryable: false,\n }),\n );\n }\n }\n\n cleanup();\n return Ok(strippedData as T);\n }\n\n // status === false\n const parsedError = parseError(message);\n cleanup();\n return Err(JSON.stringify(parsedError));\n } catch (error) {\n cleanup();\n\n const isAbort =\n error instanceof DOMException && error.name === \"AbortError\";\n const sdkError: SdkError = {\n code: isAbort ? \"TIMEOUT\" : \"NETWORK_ERROR\",\n message: isAbort\n ? `Request timed out after ${timeoutMs}ms`\n : String(error),\n retryable: true,\n };\n\n if (currentAttempt < maxRetries) {\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n return Err(JSON.stringify(sdkError));\n }\n }\n\n return attempt(0);\n }\n\n return { send, parseError };\n}\n\n/**\n * Parse an error string into an SdkError object.\n * Tries JSON.parse first; falls back to a generic UNKNOWN error.\n *\n * @example\n * ```ts\n * const result = await sdk.getStatus({ reference: \"ORDER-123\" });\n * if (!result.isOk) {\n * const error = parseError(result.error);\n * console.log(error.code, error.message);\n * }\n * ```\n */\nexport function parseError(error: string): SdkError {\n try {\n const parsed = JSON.parse(error) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"code\" in parsed &&\n \"message\" in parsed &&\n typeof (parsed as Record<string, unknown>).code === \"string\" &&\n typeof (parsed as Record<string, unknown>).message === \"string\"\n ) {\n return parsed as SdkError;\n }\n } catch {\n // Not JSON, fall through\n }\n\n return { code: \"UNKNOWN\", message: error };\n}\n","/**\n * Payment instance with event emission for transaction lifecycle.\n * Handles polling, event emission, and wait-for-completion.\n *\n * @see Spec 2 section 2 - \".collectPayment() returns a payment instance that they have to listen for events on\"\n * @see Spec 2 section 9 - \"sdk on merchant side internally calls another action to our backend to get transaction status updates by polling\"\n */\n\nimport type { Result } from \"slang-ts\";\nimport { createEmitter, type Emitter } from \"./pubsub\";\nimport { parseError } from \"./transport\";\nimport type {\n EventData,\n GetStatusInput,\n GetTransactionInput,\n PaymentEvent,\n PaymentEventHandler,\n PaymentInstance,\n StatusResponse,\n Transaction,\n TransactionStatus,\n} from \"./types\";\n\n/**\n * Internal state for a payment instance.\n * @internal\n */\ntype PaymentState = {\n reference: string;\n status: TransactionStatus | null;\n transaction: Transaction | null;\n pollingTimer: ReturnType<typeof setTimeout> | null;\n resolved: boolean;\n pollAttempts: number;\n pollStartTime: number;\n emitter: Emitter<PaymentEvent>;\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs: number;\n maxPollDuration: number;\n maxPollAttempts: number;\n};\n\n/** Map transaction status to payment event. */\nconst STATUS_TO_EVENT: Partial<Record<TransactionStatus, PaymentEvent>> = {\n successful: \"success\",\n failed: \"failed\",\n processing: \"processing\",\n cancelled: \"cancelled\",\n};\n\nfunction statusToEvent(status: TransactionStatus): PaymentEvent | null {\n return STATUS_TO_EVENT[status] ?? null;\n}\n\n/** Terminal states that stop polling. */\nconst TERMINAL_STATES = new Set<TransactionStatus>([\n \"successful\",\n \"failed\",\n \"cancelled\",\n]);\n\n/**\n * Create a new payment instance.\n *\n * @param initialResponse - Response with reference and initial status\n * @param deps - Dependencies injected by the SDK\n * @returns Payment instance with event subscription\n *\n * @internal\n */\nexport function createPaymentInstance(\n initialResponse: { reference: string; status: TransactionStatus },\n deps: {\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs?: number;\n maxPollDuration?: number;\n maxPollAttempts?: number;\n },\n): PaymentInstance {\n const state: PaymentState = {\n reference: initialResponse.reference,\n status: initialResponse.status,\n transaction: null,\n pollingTimer: null,\n resolved: false,\n pollAttempts: 0,\n pollStartTime: Date.now(),\n emitter: createEmitter<PaymentEvent>(),\n fetchStatus: deps.fetchStatus,\n fetchTransaction: deps.fetchTransaction,\n pollIntervalMs: deps.pollIntervalMs ?? 2000,\n maxPollDuration: deps.maxPollDuration ?? 300000,\n maxPollAttempts: deps.maxPollAttempts ?? 150,\n };\n\n function resolveWithError(error: string): void {\n state.resolved = true;\n stopPolling();\n emitEvent(\"error\", parseError(error).message);\n }\n\n /**\n * Emit an event with current transaction data.\n * @internal\n */\n function emitEvent(event: PaymentEvent, error?: string): void {\n const data: EventData = {\n event,\n transaction: state.transaction ?? undefined,\n error,\n timestamp: new Date().toISOString(),\n };\n state.emitter.emit(event, data);\n }\n\n /**\n * Handle terminal state by fetching full transaction record.\n * @internal\n */\n async function handleTerminalState(status: TransactionStatus): Promise<void> {\n const txResult = await state.fetchTransaction({\n reference: state.reference,\n });\n if (txResult.isOk) {\n state.transaction = txResult.value;\n const event = statusToEvent(status);\n if (event) {\n emitEvent(event);\n }\n } else {\n emitEvent(\"error\", `Failed to fetch transaction: ${txResult.error}`);\n }\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Handle a status response from polling.\n * @internal\n */\n async function handleStatusUpdate(response: StatusResponse): Promise<void> {\n if (response.reference !== state.reference) {\n resolveWithError(\n `Reference mismatch: expected ${state.reference} but got ${response.reference}`,\n );\n return;\n }\n\n const newStatus = response.status;\n const oldStatus = state.status;\n\n state.status = newStatus;\n\n if (newStatus !== oldStatus) {\n const event = statusToEvent(newStatus);\n if (event) {\n if (TERMINAL_STATES.has(newStatus)) {\n await handleTerminalState(newStatus);\n return;\n }\n emitEvent(event);\n }\n }\n }\n\n /**\n * Handle polling error.\n * \"Not found\" during early polling is expected; other errors stop polling.\n * @internal\n */\n function handlePollError(error: string): void {\n const isNotFound =\n error.includes(\"not found\") || error.includes(\"NOT_FOUND\");\n if (isNotFound) {\n return;\n }\n emitEvent(\"error\", parseError(error).message);\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Schedule the next poll tick.\n * Uses a single timeout so the next request only starts after the current one finishes.\n * @internal\n */\n function scheduleNextPoll(): void {\n if (state.resolved || state.pollingTimer) {\n return;\n }\n\n state.pollingTimer = setTimeout(() => {\n state.pollingTimer = null;\n void pollStatus();\n }, state.pollIntervalMs);\n }\n\n /**\n * Execute one polling cycle and queue the next one when appropriate.\n * @internal\n */\n async function pollStatus(): Promise<void> {\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n if (state.pollAttempts >= state.maxPollAttempts) {\n resolveWithError(\"Polling timeout: exceeded maximum attempts\");\n return;\n }\n\n if (Date.now() - state.pollStartTime >= state.maxPollDuration) {\n resolveWithError(\"Polling timeout: exceeded maximum duration\");\n return;\n }\n\n state.pollAttempts += 1;\n\n const result = await state.fetchStatus({ reference: state.reference });\n\n if (result.isOk) {\n await handleStatusUpdate(result.value);\n } else {\n handlePollError(result.error);\n }\n\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n scheduleNextPoll();\n }\n\n /**\n * Start polling for status updates.\n * @internal\n */\n function startPolling(): void {\n scheduleNextPoll();\n }\n\n /**\n * Stop polling.\n * @internal\n */\n function stopPolling(): void {\n if (state.pollingTimer) {\n clearTimeout(state.pollingTimer);\n state.pollingTimer = null;\n }\n }\n\n /**\n * Subscribe to payment events.\n */\n function on(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.on(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Unsubscribe from payment events.\n */\n function off(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.off(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Subscribe to a payment event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal events like \"success\" or \"failed\".\n */\n function once(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.once(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Wait for payment to reach a terminal state.\n * Resolves on success, rejects on failure/cancel/error.\n */\n function wait(): Promise<Transaction> {\n return new Promise((resolve, reject) => {\n if (state.resolved) {\n if (state.status === \"successful\" && state.transaction) {\n resolve(state.transaction);\n } else {\n reject(new Error(`Payment ${state.status ?? \"error\"}`));\n }\n return;\n }\n\n function onSuccess(): void {\n cleanup();\n if (state.transaction) {\n resolve(state.transaction);\n } else {\n reject(\n new Error(\"Payment successful but transaction data unavailable\"),\n );\n }\n }\n\n function onFailed(): void {\n cleanup();\n reject(new Error(\"Payment failed\"));\n }\n\n function onCancelled(): void {\n cleanup();\n reject(new Error(\"Payment cancelled\"));\n }\n\n function onError(data: unknown): void {\n cleanup();\n const eventData = data as EventData;\n reject(new Error(eventData.error ?? \"Payment error\"));\n }\n\n function cleanup(): void {\n state.emitter.off(\"success\", onSuccess);\n state.emitter.off(\"failed\", onFailed);\n state.emitter.off(\"cancelled\", onCancelled);\n state.emitter.off(\"error\", onError);\n }\n\n state.emitter.on(\"success\", onSuccess);\n state.emitter.on(\"failed\", onFailed);\n state.emitter.on(\"cancelled\", onCancelled);\n state.emitter.on(\"error\", onError);\n });\n }\n\n const paymentInstance: PaymentInstance = {\n get reference() {\n return state.reference;\n },\n get status() {\n return state.status;\n },\n on,\n once,\n off,\n wait,\n };\n\n startPolling();\n\n return paymentInstance;\n}\n","/**\n * Standalone webhook signature verification utility.\n * Merchants use this to confirm that incoming webhook payloads\n * were genuinely sent by Nylon Pay before acting on them.\n */\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { VerifyWebhookInput } from \"./types\";\n\n/**\n * Verify that a webhook payload was signed by Nylon Pay.\n * Operates on raw payload bytes, NOT parsed JSON (spec invariant #8).\n *\n * @param input.payload - Raw request body as string or Uint8Array\n * @param input.signature - Signature from the webhook header\n * @param input.secret - Merchant's webhook secret\n * @returns True when the signature is valid\n */\nexport function verifyWebhookSignature(input: VerifyWebhookInput): boolean {\n const payloadBytes =\n typeof input.payload === \"string\"\n ? Buffer.from(input.payload, \"utf8\")\n : Buffer.from(input.payload);\n\n const expectedSignature = createHmac(\"sha256\", input.secret)\n .update(payloadBytes)\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(input.signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * SDK instance providing all merchant-facing payment operations.\n * Created via createNylonPay factory and returned as NylonPaySdk.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { createPaymentInstance } from \"./payment\";\nimport { SDK_ACTIONS } from \"./sdk.config\";\nimport { createTransport } from \"./transport\";\nimport type {\n CollectPaymentInput,\n CreateInvoiceInput,\n GetStatusInput,\n GetTransactionInput,\n InvoiceResponse,\n MakePayoutInput,\n NylonPaySdk,\n PaymentInstance,\n PhoneVerification,\n SdkHooks,\n StatusResponse,\n Transaction,\n TransactionStatus,\n VerifyPhoneInput,\n VerifyWebhookInput,\n} from \"./types\";\nimport { verifyWebhookSignature } from \"./verify-webhook\";\n\nexport type { NylonPaySdk } from \"./types\";\n\ntype ResolvedConfig = {\n apiKey: string;\n apiSecret: string;\n baseUrl: string;\n timeoutMs: number;\n maxRetries: number;\n maxPollIntervalMs: number;\n maxPollDurationMs: number;\n maxPollAttempts: number;\n fetch: typeof globalThis.fetch;\n hooks?: SdkHooks;\n};\n\n/** Generate a random 15-character hex reference for idempotency. */\nfunction generateReference(): string {\n return randomBytes(16).toString(\"hex\").slice(0, 15);\n}\n\n/** Validate that amount is a positive integer. */\nfunction validateAmount(amount: number): void {\n if (!Number.isInteger(amount) || amount <= 0) {\n throw new Error(\"amount must be a positive integer\");\n }\n}\n\n/** Validate that a string value is non-empty. */\nfunction validateNonEmpty(value: string, fieldName: string): void {\n if (!value || value.trim() === \"\") {\n throw new Error(`${fieldName} is required`);\n }\n}\n\n/**\n * Create an SDK instance with resolved configuration.\n * Returns an object implementing the NylonPaySdk interface.\n */\nexport function createSdkInstance(config: ResolvedConfig): NylonPaySdk {\n const transport = createTransport({\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl: config.baseUrl,\n timeoutMs: config.timeoutMs,\n maxRetries: config.maxRetries,\n fetch: config.fetch,\n });\n\n const commonDeps = {\n fetchStatus: (input: GetStatusInput) =>\n transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n }),\n fetchTransaction: (input: GetTransactionInput) =>\n transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n }),\n pollIntervalMs: config.maxPollIntervalMs,\n maxPollDuration: config.maxPollDurationMs,\n maxPollAttempts: config.maxPollAttempts,\n };\n\n /**\n * Initiate a collection payment.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function collectPayment(\n input: CollectPaymentInput,\n ): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.collectPayment,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a collection and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function collectPaymentAndResolve(\n input: CollectPaymentInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.collectPaymentAndResolve,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Initiate a payout.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function makePayout(input: MakePayoutInput): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.makePayout,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a payout and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function makePayoutAndResolve(\n input: MakePayoutInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.makePayoutAndResolve,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the current status of a transaction.\n * Lightweight check that returns only status fields.\n */\n async function getStatus(\n input: GetStatusInput,\n ): Promise<Result<StatusResponse, string>> {\n validateNonEmpty(input.reference, \"reference\");\n\n const result = await transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the full transaction record.\n * Requires at least one of id or reference.\n */\n async function getTransaction(\n input: GetTransactionInput,\n ): Promise<Result<Transaction, string>> {\n if (!input.id && !input.reference) {\n throw new Error(\"id or reference is required\");\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a phone number with the provider.\n * Returns the registered name for identity confirmation.\n */\n async function verifyPhone(\n input: VerifyPhoneInput,\n ): Promise<Result<PhoneVerification, string>> {\n validateNonEmpty(input.phoneNumber, \"phoneNumber\");\n\n const result = await transport.send<PhoneVerification>({\n action: SDK_ACTIONS.verifyPhone,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Create a hosted invoice.\n * Auto-generates reference if omitted. Returns payment link and token.\n */\n async function createInvoice(\n input: CreateInvoiceInput,\n ): Promise<Result<InvoiceResponse, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.description, \"description\");\n\n if (input.items) {\n if (input.items.length > 50) {\n throw new Error(\"items must not exceed 50\");\n }\n for (const item of input.items) {\n if (!Number.isInteger(item.quantity) || item.quantity <= 0) {\n throw new Error(\"item quantity must be a positive integer\");\n }\n if (!Number.isInteger(item.unitPrice) || item.unitPrice <= 0) {\n throw new Error(\"item unitPrice must be a positive integer\");\n }\n }\n }\n\n const payload = { ...input, reference };\n const result = await transport.send<InvoiceResponse>({\n action: SDK_ACTIONS.createInvoice,\n payload,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a webhook payload signature.\n * Delegates to the standalone verifyWebhookSignature utility.\n */\n function verifyWebhook(input: VerifyWebhookInput): boolean {\n return verifyWebhookSignature(input);\n }\n\n return {\n collectPayment,\n collectPaymentAndResolve,\n makePayout,\n makePayoutAndResolve,\n getStatus,\n getTransaction,\n verifyPhone,\n createInvoice,\n verifyWebhookSignature: verifyWebhook,\n };\n}\n","/**\n * Factory function to create a Nylon Pay SDK instance.\n * This is the main entry point for merchants.\n *\n * Calling createNylonPay with the same apiKey and baseUrl returns the same\n * instance (singleton per key+url pair). Pass { force: true } to create a\n * fresh instance and replace the cached one.\n *\n * @example\n * ```ts\n * import { createNylonPay } from \"@nile-squad/nylonpay-ts\";\n *\n * export const nylonpay = createNylonPay({\n * apiKey: \"npk_...\",\n * apiSecret: \"nps_...\",\n * });\n * ```\n */\n\nimport { createSdkInstance, type NylonPaySdk } from \"./sdk\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_POLL_ATTEMPTS,\n DEFAULT_MAX_POLL_DURATION_MS,\n DEFAULT_MAX_POLL_INTERVAL_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n} from \"./sdk.config\";\nimport type { NylonPayConfig } from \"./types\";\n\nconst instances = new Map<string, NylonPaySdk>();\n\n/**\n * Create a Nylon Pay SDK instance.\n *\n * Returns the same instance for the same apiKey + baseUrl combination unless\n * { force: true } is passed. Use your test keys for sandbox, production keys\n * for live.\n *\n * @param config - SDK configuration with apiKey and apiSecret\n * @returns SDK instance with all payment operations\n *\n * @throws Error if required config is missing or invalid\n */\nexport function createNylonPay(config: NylonPayConfig): NylonPaySdk {\n if (!config.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n if (!config.apiKey.startsWith(\"npk_\")) {\n throw new Error('apiKey must start with \"npk_\"');\n }\n if (!config.apiSecret) {\n throw new Error(\"apiSecret is required\");\n }\n if (!config.apiSecret.startsWith(\"nps_\")) {\n throw new Error('apiSecret must start with \"nps_\"');\n }\n\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const instanceKey = `${config.apiKey}:${baseUrl}`;\n\n if (!config.force) {\n const existing = instances.get(instanceKey);\n if (existing) return existing;\n }\n\n const resolvedConfig = {\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n maxPollIntervalMs: config.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS,\n maxPollDurationMs: config.maxPollDurationMs ?? DEFAULT_MAX_POLL_DURATION_MS,\n maxPollAttempts: config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS,\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n hooks: config.hooks,\n };\n\n const instance = createSdkInstance(resolvedConfig);\n instances.set(instanceKey, instance);\n return instance;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pubsub.ts","../src/fingerprint.ts","../src/nonce.ts","../src/sdk.config.ts","../src/signature.ts","../src/verify-response.ts","../src/transport.ts","../src/payment.ts","../src/verify-webhook.ts","../src/sdk.ts","../src/create-nylon-pay.ts"],"names":["type","platform","arch","release","hostname","createHash","randomBytes","createHmac","timingSafeEqual","Err","Ok"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Simple internal pubsub/event emitter for SDK payment lifecycle events.\n * Functional implementation without classes.\n *\n * @see Spec 2 section 2 - \"emits events such as nylonpay.on('success', (data) => {})\"\n *\n * @example\n * ```ts\n * const emitter = createEmitter<PaymentEvent>();\n * emitter.on(\"success\", (data) => console.log(data));\n * emitter.emit(\"success\", { event: \"success\", timestamp: \"...\" });\n * emitter.off(\"success\", handler);\n * ```\n */\n\n/**\n * Handler function type for event listeners.\n */\nexport type EventHandler<T = unknown> = (data: T) => void;\n\n/**\n * Internal state for the emitter.\n * @internal\n */\ninterface EmitterState<T> {\n listeners: Map<T, Set<EventHandler<T>>>;\n}\n\n/**\n * Create a new event emitter instance.\n *\n * @returns Emitter with on/off/emit methods\n *\n * @example\n * ```ts\n * const emitter = createEmitter<string>();\n * const unsub = emitter.on(\"hello\", (msg) => console.log(msg));\n * emitter.emit(\"hello\", \"world\");\n * unsub(); // remove listener\n * ```\n */\nexport function createEmitter<T extends string>() {\n const state: EmitterState<T> = {\n listeners: new Map(),\n };\n\n /**\n * Subscribe to an event.\n * Returns an unsubscribe function for convenience.\n */\n function on(event: T, handler: EventHandler): () => void {\n if (!state.listeners.has(event)) {\n state.listeners.set(event, new Set());\n }\n state.listeners.get(event)?.add(handler as EventHandler<unknown>);\n return () => off(event, handler);\n }\n\n /**\n * Subscribe to an event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal payment events (e.g. \"successful\", \"failed\").\n * Returns the emitter for chaining.\n */\n function once(event: T, handler: EventHandler): typeof emitter {\n const wrapper: EventHandler = (data) => {\n off(event, wrapper);\n handler(data);\n };\n on(event, wrapper);\n return emitter;\n }\n\n /**\n * Unsubscribe from an event.\n */\n function off(event: T, handler: EventHandler): void {\n const handlers = state.listeners.get(event);\n if (handlers) {\n handlers.delete(handler as EventHandler<unknown>);\n }\n }\n\n /**\n * Emit an event with data to all listeners.\n * Handlers are called synchronously in subscription order.\n */\n function emit(event: T, data: unknown): void {\n const handlers = state.listeners.get(event);\n if (!handlers || handlers.size === 0) return;\n for (const handler of handlers) {\n try {\n (handler as EventHandler<unknown>)(data);\n } catch {\n // Swallow handler errors to prevent one bad handler\n // from breaking the entire event chain\n }\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n */\n function clear(event?: T): void {\n if (event) {\n state.listeners.delete(event);\n } else {\n state.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event.\n */\n function listenerCount(event: T): number {\n return state.listeners.get(event)?.size ?? 0;\n }\n\n const emitter = { on, once, off, emit, clear, listenerCount };\n return emitter;\n}\n\n/**\n * Type for the emitter interface returned by createEmitter.\n */\nexport type Emitter<T extends string> = ReturnType<typeof createEmitter<T>>;\n","/**\n * Server fingerprint generation for SDK requests.\n * Provides a stable identifier based on runtime environment.\n *\n * @see Spec 2 section 1 - \"a server fingerprint based on runtime, os, etc\"\n */\n\nimport { createHash } from \"node:crypto\";\nimport { arch, hostname, platform, release, type } from \"node:os\";\n\n/**\n * Generate a server fingerprint based on runtime environment.\n * This provides a stable identifier for the server making requests.\n * The fingerprint is a SHA-256 hash of system characteristics.\n *\n * @returns Hex-encoded SHA-256 hash of system info\n *\n * @example\n * ```ts\n * const fingerprint = generateFingerprint();\n * // => \"e3b0c44298fc1c149afbf4c8996fb924...\"\n * ```\n */\nexport function generateFingerprint(): string {\n const components = [\n `type:${type()}`,\n `platform:${platform()}`,\n `arch:${arch()}`,\n `release:${release()}`,\n `hostname:${hostname()}`,\n `node:${process.versions.node}`,\n `v8:${process.versions.v8}`,\n ].join(\"|\");\n\n return createHash(\"sha256\").update(components).digest(\"hex\");\n}\n","/**\n * Cryptographically secure nonce generation for SDK requests.\n *\n * @see Spec 2 section 1 - \"Internally the sdk generates a nounce\"\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Generate a cryptographically secure random nonce.\n * Uses Node.js crypto.randomBytes for security.\n *\n * @param length - Byte length of the nonce (default: 16 = 32 hex chars)\n * @returns Hex-encoded random string\n *\n * @example\n * ```ts\n * const nonce = generateNonce();\n * // => \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4\"\n * ```\n */\nexport function generateNonce(length = 16): string {\n return randomBytes(length).toString(\"hex\");\n}\n","/** Default production backend URL */\nexport const DEFAULT_BASE_URL =\n \"https://api.nylonpay.nilesquad.com/api/services\";\n\n/** Default request timeout (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Default max retry attempts for transport failures */\nexport const DEFAULT_MAX_RETRIES = 3;\n\n/** Default polling interval between status checks (2 seconds) */\nexport const DEFAULT_MAX_POLL_INTERVAL_MS = 2_000;\n\n/** Default max total polling duration before timing out (5 minutes) */\nexport const DEFAULT_MAX_POLL_DURATION_MS = 300_000;\n\n/** Default max polling attempts before giving up */\nexport const DEFAULT_MAX_POLL_ATTEMPTS = 150;\n\n/** Nile.js service name for all SDK operations */\nexport const SDK_SERVICE = \"sdk\";\n\n/** Maps SDK operation names to backend action names */\nexport const SDK_ACTIONS = {\n collectPayment: \"sdk-collect-payment\",\n collectPaymentAndResolve: \"sdk-collect-payment-and-resolve\",\n makePayout: \"sdk-make-payout\",\n makePayoutAndResolve: \"sdk-make-payout-and-resolve\",\n getStatus: \"sdk-get-status\",\n getTransaction: \"sdk-get-transaction\",\n verifyPhone: \"sdk-verify-phone\",\n createInvoice: \"sdk-create-invoice\",\n} as const;\n\n/** HTTP status codes that trigger retries */\nexport const RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n","/**\n * HMAC-SHA256 signature creation for SDK requests.\n * Must match the backend's verification logic in verify-signature.ts.\n *\n * Signature payload format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * @see backend/src/services/sdk/verify-signature.ts\n * @see Spec 2 section 1 - \"creates a signature using these values and the api secret (HMAC 256)\"\n */\n\nimport { createHmac } from \"node:crypto\";\n\n/**\n * Recursively sort object keys alphabetically for deterministic JSON.\n * Must match backend's createCanonicalPayload function.\n *\n * @see backend/src/services/sdk/create-canonical-payload.ts\n */\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => sortValue(entry));\n }\n\n if (value && typeof value === \"object\") {\n const sortedEntries = Object.entries(value as Record<string, unknown>).sort(\n ([firstKey], [secondKey]) => firstKey.localeCompare(secondKey),\n );\n\n return Object.fromEntries(\n sortedEntries.map(([entryKey, entryValue]) => [\n entryKey,\n sortValue(entryValue),\n ]),\n );\n }\n\n return value;\n}\n\n/**\n * Create a canonical JSON string from a payload.\n * Keys are sorted alphabetically for deterministic serialization.\n */\nexport function createCanonicalPayload(payload: unknown): string {\n return JSON.stringify(sortValue(payload));\n}\n\n/**\n * Build the signature payload string.\n * Format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * The fingerprint is included in the signature to prevent tampering\n * with server identity information.\n *\n * @see backend/src/services/sdk/verify-signature.ts:createSignaturePayload\n */\nexport function createSignaturePayload(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n timestamp: string;\n}): string {\n return `${input.fingerprint}.${input.nonce}.${input.timestamp}.${createCanonicalPayload(input.payload)}`;\n}\n\n/**\n * Create an HMAC-SHA256 signature for SDK request authentication.\n *\n * The signature includes the server fingerprint to ensure the request\n * origin cannot be spoofed. The fingerprint contains runtime/OS info\n * that is bound to this specific server instance.\n *\n * @param input.fingerprint - Server fingerprint (included in signature)\n * @param input.nonce - Random nonce for replay protection\n * @param input.timestamp - Unix timestamp in milliseconds\n * @param input.payload - Request body (will be canonicalized)\n * @param input.secret - API secret for signing\n * @returns Hex-encoded HMAC-SHA256 signature\n */\nexport function createSignature(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n secret: string;\n timestamp: string;\n}): string {\n const payload = createSignaturePayload(input);\n\n return createHmac(\"sha256\", input.secret).update(payload).digest(\"hex\");\n}\n\n/**\n * Create a timestamp string in milliseconds.\n * Used as part of the signature payload.\n */\nexport function createTimestamp(): string {\n return Date.now().toString();\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { createCanonicalPayload } from \"./signature\";\n\n/**\n * Verify an authenticated backend response body before exposing it to SDK\n * consumers so tampered payloads are rejected consistently.\n *\n * @param data - Response payload without the `_responseSignature` field\n * @param signature - Hex-encoded HMAC-SHA256 signature from the backend\n * @param secret - API secret used for request authentication\n * @returns True when the signature matches the payload\n */\nexport function verifyResponseSignature(\n data: unknown,\n signature: string,\n secret: string,\n): boolean {\n const expectedSignature = createHmac(\"sha256\", secret)\n .update(createCanonicalPayload(data))\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * HTTP transport layer for SDK communication with the Nylon Pay backend.\n * Handles the Nile.js envelope format, HMAC request signing, response\n * signature verification, retries, and timeouts.\n *\n * @internal\n */\n\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { generateFingerprint } from \"./fingerprint\";\nimport { generateNonce } from \"./nonce\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n RETRYABLE_STATUS_CODES,\n SDK_SERVICE,\n} from \"./sdk.config\";\nimport { createSignature, createTimestamp } from \"./signature\";\nimport type { SdkError, TransportRequest } from \"./types\";\nimport { verifyResponseSignature } from \"./verify-response\";\n\n/** Cached fingerprint for this server instance. */\nconst CACHED_FINGERPRINT = generateFingerprint();\n\n/** Calculate exponential backoff delay with jitter. */\nfunction calculateBackoff(attempt: number): number {\n const base = 2 ** attempt * 1000;\n const jitter = Math.random() * 500;\n return base + jitter;\n}\n\n/** Promise-based delay. */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Strip _responseSignature from a payload and return it separately. */\nfunction stripResponseSignature<T>(payload: T): {\n data: T;\n responseSignature: string | null;\n} {\n if (\n !payload ||\n typeof payload !== \"object\" ||\n !(\"_responseSignature\" in payload)\n ) {\n return { data: payload, responseSignature: null };\n }\n\n const { _responseSignature, ...rest } = payload as Record<string, unknown>;\n\n return {\n data: rest as T,\n responseSignature:\n typeof _responseSignature === \"string\" ? _responseSignature : null,\n };\n}\n\n/** Build the Nile.js request envelope. */\nfunction buildEnvelope({\n action,\n payload,\n}: TransportRequest): Record<string, unknown> {\n return {\n intent: \"execute\",\n service: SDK_SERVICE,\n action,\n payload: {\n ...(payload as Record<string, unknown>),\n _fingerprint: CACHED_FINGERPRINT,\n },\n };\n}\n\n/**\n * Build auth headers for a request.\n *\n * The signature is computed over the inner `payload` (the operation input plus\n * `_fingerprint`), NOT the full Nile envelope. This matches the server, which\n * verifies the signature against the raw request payload — see the Transport\n * Contract in the Nylon Pay SDK Spec (https://github.com/nile-squad/specs).\n */\nfunction buildAuthHeaders({\n apiKey,\n apiSecret,\n payload,\n}: {\n apiKey: string;\n apiSecret: string;\n payload: unknown;\n}): Record<string, string> {\n const nonce = generateNonce();\n const timestamp = createTimestamp();\n const signature = createSignature({\n fingerprint: CACHED_FINGERPRINT,\n nonce,\n timestamp,\n payload,\n secret: apiSecret,\n });\n\n return {\n \"content-type\": \"application/json\",\n \"x-nylon-key\": apiKey,\n \"x-nylon-nonce\": nonce,\n \"x-nylon-signature\": signature,\n \"x-nylon-timestamp\": timestamp,\n };\n}\n\n/** Create an AbortController with a timeout. Returns cleanup to clear the timer. */\nfunction withTimeout(timeoutMs: number): {\n controller: AbortController;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n return { controller, cleanup: () => clearTimeout(timeoutId) };\n}\n\n/**\n * Create the transport layer for SDK requests.\n *\n * @param config - Resolved SDK configuration\n * @returns Transport functions\n *\n * @internal\n */\nexport function createTransport({\n apiKey,\n apiSecret,\n baseUrl = DEFAULT_BASE_URL,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n maxRetries = DEFAULT_MAX_RETRIES,\n fetch: fetchImpl,\n}: {\n apiKey: string;\n apiSecret: string;\n baseUrl?: string;\n timeoutMs?: number;\n maxRetries?: number;\n fetch: typeof globalThis.fetch;\n}) {\n /**\n * Send a request to the backend.\n * Builds the envelope and headers once, then retries only the fetch call.\n */\n async function send<T>(\n request: TransportRequest,\n ): Promise<Result<T, string>> {\n const envelope = buildEnvelope(request);\n const signedPayload = (envelope as { payload: unknown }).payload;\n const headers = buildAuthHeaders({\n apiKey,\n apiSecret,\n payload: signedPayload,\n });\n const bodyString = JSON.stringify(envelope);\n\n async function attempt(currentAttempt: number): Promise<Result<T, string>> {\n const { controller, cleanup } = withTimeout(timeoutMs);\n\n try {\n const response = await fetchImpl(baseUrl, {\n method: \"POST\",\n headers,\n body: bodyString,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const statusCode = response.status;\n const retryable = RETRYABLE_STATUS_CODES.has(statusCode);\n\n let errorMessage = `HTTP ${statusCode}`;\n try {\n const errorBody = await response.json();\n if (\n errorBody &&\n typeof errorBody === \"object\" &&\n \"message\" in errorBody\n ) {\n errorMessage = String(errorBody.message);\n }\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n if (retryable && currentAttempt < maxRetries) {\n cleanup();\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n const sdkError: SdkError = {\n code: `HTTP_${statusCode}`,\n message: errorMessage,\n statusCode,\n retryable,\n };\n\n cleanup();\n return Err(JSON.stringify(sdkError));\n }\n\n const responseBody = await response.json();\n\n if (\n !responseBody ||\n typeof responseBody !== \"object\" ||\n !(\"status\" in responseBody)\n ) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"INVALID_RESPONSE\",\n message: \"Response missing status field\",\n retryable: false,\n }),\n );\n }\n\n const { status, message, data } = responseBody as {\n status: boolean;\n message: string;\n data: unknown;\n };\n\n if (status === true) {\n const { data: strippedData, responseSignature } =\n stripResponseSignature(data);\n\n if (responseSignature) {\n const isValid = verifyResponseSignature(\n strippedData,\n responseSignature,\n apiSecret,\n );\n if (!isValid) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"RESPONSE_TAMPERED\",\n message: \"Response signature verification failed\",\n retryable: false,\n }),\n );\n }\n }\n\n cleanup();\n return Ok(strippedData as T);\n }\n\n // status === false\n const parsedError = parseError(message);\n cleanup();\n return Err(JSON.stringify(parsedError));\n } catch (error) {\n cleanup();\n\n const isAbort =\n error instanceof DOMException && error.name === \"AbortError\";\n const sdkError: SdkError = {\n code: isAbort ? \"TIMEOUT\" : \"NETWORK_ERROR\",\n message: isAbort\n ? `Request timed out after ${timeoutMs}ms`\n : String(error),\n retryable: true,\n };\n\n if (currentAttempt < maxRetries) {\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n return Err(JSON.stringify(sdkError));\n }\n }\n\n return attempt(0);\n }\n\n return { send, parseError };\n}\n\n/**\n * Parse an error string into an SdkError object.\n * Tries JSON.parse first; falls back to a generic UNKNOWN error.\n *\n * @example\n * ```ts\n * const result = await sdk.getStatus({ reference: \"ORDER-123\" });\n * if (!result.isOk) {\n * const error = parseError(result.error);\n * console.log(error.code, error.message);\n * }\n * ```\n */\nexport function parseError(error: string): SdkError {\n try {\n const parsed = JSON.parse(error) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"code\" in parsed &&\n \"message\" in parsed &&\n typeof (parsed as Record<string, unknown>).code === \"string\" &&\n typeof (parsed as Record<string, unknown>).message === \"string\"\n ) {\n return parsed as SdkError;\n }\n } catch {\n // Not JSON, fall through\n }\n\n return { code: \"UNKNOWN\", message: error };\n}\n","/**\n * Payment instance with event emission for transaction lifecycle.\n * Handles polling, event emission, and wait-for-completion.\n *\n * @see Spec 2 section 2 - \".collectPayment() returns a payment instance that they have to listen for events on\"\n * @see Spec 2 section 9 - \"sdk on merchant side internally calls another action to our backend to get transaction status updates by polling\"\n */\n\nimport type { Result } from \"slang-ts\";\nimport { createEmitter, type Emitter } from \"./pubsub\";\nimport { parseError } from \"./transport\";\nimport type {\n EventData,\n GetStatusInput,\n GetTransactionInput,\n PaymentEvent,\n PaymentEventHandler,\n PaymentInstance,\n StatusResponse,\n Transaction,\n TransactionStatus,\n} from \"./types\";\n\n/**\n * Internal state for a payment instance.\n * @internal\n */\ntype PaymentState = {\n reference: string;\n status: TransactionStatus | null;\n transaction: Transaction | null;\n pollingTimer: ReturnType<typeof setTimeout> | null;\n resolved: boolean;\n pollAttempts: number;\n pollStartTime: number;\n emitter: Emitter<PaymentEvent>;\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs: number;\n maxPollDuration: number;\n maxPollAttempts: number;\n};\n\n/** Map transaction status to payment event. */\nconst STATUS_TO_EVENT: Partial<Record<TransactionStatus, PaymentEvent>> = {\n successful: \"success\",\n failed: \"failed\",\n processing: \"processing\",\n cancelled: \"cancelled\",\n};\n\nfunction statusToEvent(status: TransactionStatus): PaymentEvent | null {\n return STATUS_TO_EVENT[status] ?? null;\n}\n\n/** Terminal states that stop polling. */\nconst TERMINAL_STATES = new Set<TransactionStatus>([\n \"successful\",\n \"failed\",\n \"cancelled\",\n]);\n\n/**\n * Normalise raw backend status strings to TransactionStatus.\n * The backend may return \"completed\" for successful payments — map it to\n * \"successful\" so SDK events fire correctly.\n */\nfunction normalizeStatus(raw: string): TransactionStatus {\n if (raw === \"completed\") return \"successful\";\n return raw as TransactionStatus;\n}\n\n/**\n * Create a new payment instance.\n *\n * @param initialResponse - Response with reference and initial status\n * @param deps - Dependencies injected by the SDK\n * @returns Payment instance with event subscription\n *\n * @internal\n */\nexport function createPaymentInstance(\n initialResponse: { reference: string; status: TransactionStatus },\n deps: {\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs?: number;\n maxPollDuration?: number;\n maxPollAttempts?: number;\n },\n): PaymentInstance {\n const state: PaymentState = {\n reference: initialResponse.reference,\n status: normalizeStatus(initialResponse.status),\n transaction: null,\n pollingTimer: null,\n resolved: false,\n pollAttempts: 0,\n pollStartTime: Date.now(),\n emitter: createEmitter<PaymentEvent>(),\n fetchStatus: deps.fetchStatus,\n fetchTransaction: deps.fetchTransaction,\n pollIntervalMs: deps.pollIntervalMs ?? 2000,\n maxPollDuration: deps.maxPollDuration ?? 300000,\n maxPollAttempts: deps.maxPollAttempts ?? 150,\n };\n\n function resolveWithError(error: string): void {\n state.resolved = true;\n stopPolling();\n emitEvent(\"error\", parseError(error).message);\n }\n\n /**\n * Emit an event with current transaction data.\n * @internal\n */\n function emitEvent(event: PaymentEvent, error?: string): void {\n const data: EventData = {\n event,\n transaction: state.transaction ?? undefined,\n error,\n timestamp: new Date().toISOString(),\n };\n state.emitter.emit(event, data);\n }\n\n /**\n * Handle terminal state by fetching full transaction record.\n * @internal\n */\n async function handleTerminalState(status: TransactionStatus): Promise<void> {\n const txResult = await state.fetchTransaction({\n reference: state.reference,\n });\n if (txResult.isOk) {\n state.transaction = txResult.value;\n const event = statusToEvent(status);\n if (event) {\n const error =\n status === \"failed\"\n ? (state.transaction.failureReason ?? undefined)\n : undefined;\n emitEvent(event, error);\n }\n } else {\n emitEvent(\"error\", `Failed to fetch transaction: ${txResult.error}`);\n }\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Handle a status response from polling.\n * @internal\n */\n async function handleStatusUpdate(response: StatusResponse): Promise<void> {\n if (response.reference !== state.reference) {\n resolveWithError(\n `Reference mismatch: expected ${state.reference} but got ${response.reference}`,\n );\n return;\n }\n\n const newStatus = normalizeStatus(response.status);\n const oldStatus = state.status;\n\n state.status = newStatus;\n\n if (newStatus !== oldStatus) {\n const event = statusToEvent(newStatus);\n if (event) {\n if (TERMINAL_STATES.has(newStatus)) {\n await handleTerminalState(newStatus);\n return;\n }\n emitEvent(event);\n }\n }\n }\n\n /**\n * Handle polling error.\n * \"Not found\" during early polling is expected; other errors stop polling.\n * @internal\n */\n function handlePollError(error: string): void {\n const isNotFound =\n error.includes(\"not found\") || error.includes(\"NOT_FOUND\");\n if (isNotFound) {\n return;\n }\n emitEvent(\"error\", parseError(error).message);\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Schedule the next poll tick.\n * Uses a single timeout so the next request only starts after the current one finishes.\n * @internal\n */\n function scheduleNextPoll(): void {\n if (state.resolved || state.pollingTimer) {\n return;\n }\n\n state.pollingTimer = setTimeout(() => {\n state.pollingTimer = null;\n void pollStatus();\n }, state.pollIntervalMs);\n }\n\n /**\n * Execute one polling cycle and queue the next one when appropriate.\n * @internal\n */\n async function pollStatus(): Promise<void> {\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n if (state.pollAttempts >= state.maxPollAttempts) {\n resolveWithError(\"Polling timeout: exceeded maximum attempts\");\n return;\n }\n\n if (Date.now() - state.pollStartTime >= state.maxPollDuration) {\n resolveWithError(\"Polling timeout: exceeded maximum duration\");\n return;\n }\n\n state.pollAttempts += 1;\n\n const result = await state.fetchStatus({ reference: state.reference });\n\n if (result.isOk) {\n await handleStatusUpdate(result.value);\n } else {\n handlePollError(result.error);\n }\n\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n scheduleNextPoll();\n }\n\n /**\n * Start polling for status updates.\n * If the initial status is already terminal (e.g. sandbox resolves synchronously),\n * emit the terminal event after a tick so handlers registered after instance\n * creation still fire.\n * @internal\n */\n function startPolling(): void {\n if (TERMINAL_STATES.has(state.status ?? \"pending\")) {\n setTimeout(() => {\n void handleTerminalState(state.status as TransactionStatus);\n }, 0);\n return;\n }\n scheduleNextPoll();\n }\n\n /**\n * Stop polling.\n * @internal\n */\n function stopPolling(): void {\n if (state.pollingTimer) {\n clearTimeout(state.pollingTimer);\n state.pollingTimer = null;\n }\n }\n\n /**\n * Subscribe to payment events.\n */\n function on(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.on(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Unsubscribe from payment events.\n */\n function off(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.off(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Subscribe to a payment event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal events like \"success\" or \"failed\".\n */\n function once(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.once(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Wait for payment to reach a terminal state.\n * Resolves with the full Transaction on success, null on failure/cancel/error.\n * Never rejects — check the return value to determine outcome.\n */\n function wait(): Promise<Transaction | null> {\n return new Promise((resolve) => {\n if (state.resolved) {\n resolve(\n state.status === \"successful\" && state.transaction\n ? state.transaction\n : null,\n );\n return;\n }\n\n function onSuccess(): void {\n cleanup();\n resolve(state.transaction ?? null);\n }\n\n function onFailed(): void {\n cleanup();\n resolve(null);\n }\n\n function onCancelled(): void {\n cleanup();\n resolve(null);\n }\n\n function onError(): void {\n cleanup();\n resolve(null);\n }\n\n function cleanup(): void {\n state.emitter.off(\"success\", onSuccess);\n state.emitter.off(\"failed\", onFailed);\n state.emitter.off(\"cancelled\", onCancelled);\n state.emitter.off(\"error\", onError);\n }\n\n state.emitter.on(\"success\", onSuccess);\n state.emitter.on(\"failed\", onFailed);\n state.emitter.on(\"cancelled\", onCancelled);\n state.emitter.on(\"error\", onError);\n });\n }\n\n const paymentInstance: PaymentInstance = {\n get reference() {\n return state.reference;\n },\n get status() {\n return state.status;\n },\n on,\n once,\n off,\n wait,\n };\n\n startPolling();\n\n return paymentInstance;\n}\n","/**\n * Standalone webhook signature verification utility.\n * Merchants use this to confirm that incoming webhook payloads\n * were genuinely sent by Nylon Pay before acting on them.\n */\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { VerifyWebhookInput } from \"./types\";\n\n/**\n * Verify that a webhook payload was signed by Nylon Pay.\n * Operates on raw payload bytes, NOT parsed JSON (spec invariant #8).\n *\n * @param input.payload - Raw request body as string or Uint8Array\n * @param input.signature - Signature from the webhook header\n * @param input.secret - Merchant's webhook secret\n * @returns True when the signature is valid\n */\nexport function verifyWebhookSignature(input: VerifyWebhookInput): boolean {\n const payloadBytes =\n typeof input.payload === \"string\"\n ? Buffer.from(input.payload, \"utf8\")\n : Buffer.from(input.payload);\n\n const expectedSignature = createHmac(\"sha256\", input.secret)\n .update(payloadBytes)\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(input.signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * SDK instance providing all merchant-facing payment operations.\n * Created via createNylonPay factory and returned as NylonPaySdk.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { createPaymentInstance } from \"./payment\";\nimport { SDK_ACTIONS } from \"./sdk.config\";\nimport { createTransport } from \"./transport\";\nimport type {\n CollectPaymentInput,\n CreateInvoiceInput,\n GetStatusInput,\n GetTransactionInput,\n InvoiceResponse,\n MakePayoutInput,\n NylonPaySdk,\n PaymentInstance,\n PhoneVerification,\n SdkHooks,\n StatusResponse,\n Transaction,\n TransactionStatus,\n VerifyPhoneInput,\n VerifyWebhookInput,\n} from \"./types\";\nimport { verifyWebhookSignature } from \"./verify-webhook\";\n\nexport type { NylonPaySdk } from \"./types\";\n\ntype ResolvedConfig = {\n apiKey: string;\n apiSecret: string;\n baseUrl: string;\n timeoutMs: number;\n maxRetries: number;\n maxPollIntervalMs: number;\n maxPollDurationMs: number;\n maxPollAttempts: number;\n fetch: typeof globalThis.fetch;\n hooks?: SdkHooks;\n};\n\n/** Generate a random 15-character hex reference for idempotency. */\nfunction generateReference(): string {\n return randomBytes(16).toString(\"hex\").slice(0, 15);\n}\n\n/** Validate that amount is a positive integer. */\nfunction validateAmount(amount: number): void {\n if (!Number.isInteger(amount) || amount <= 0) {\n throw new Error(\"amount must be a positive integer\");\n }\n}\n\n/** Validate that a string value is non-empty. */\nfunction validateNonEmpty(value: string, fieldName: string): void {\n if (!value || value.trim() === \"\") {\n throw new Error(`${fieldName} is required`);\n }\n}\n\n/**\n * Create an SDK instance with resolved configuration.\n * Returns an object implementing the NylonPaySdk interface.\n */\nexport function createSdkInstance(config: ResolvedConfig): NylonPaySdk {\n const transport = createTransport({\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl: config.baseUrl,\n timeoutMs: config.timeoutMs,\n maxRetries: config.maxRetries,\n fetch: config.fetch,\n });\n\n const commonDeps = {\n fetchStatus: (input: GetStatusInput) =>\n transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n }),\n fetchTransaction: (input: GetTransactionInput) =>\n transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n }),\n pollIntervalMs: config.maxPollIntervalMs,\n maxPollDuration: config.maxPollDurationMs,\n maxPollAttempts: config.maxPollAttempts,\n };\n\n /**\n * Initiate a collection payment.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function collectPayment(\n input: CollectPaymentInput,\n ): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.collectPayment,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a collection and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function collectPaymentAndResolve(\n input: CollectPaymentInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.collectPaymentAndResolve,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Initiate a payout.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function makePayout(input: MakePayoutInput): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.makePayout,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a payout and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function makePayoutAndResolve(\n input: MakePayoutInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.makePayoutAndResolve,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the current status of a transaction.\n * Lightweight check that returns only status fields.\n */\n async function getStatus(\n input: GetStatusInput,\n ): Promise<Result<StatusResponse, string>> {\n validateNonEmpty(input.reference, \"reference\");\n\n const result = await transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the full transaction record.\n * Requires at least one of id or reference.\n */\n async function getTransaction(\n input: GetTransactionInput,\n ): Promise<Result<Transaction, string>> {\n if (!input.id && !input.reference) {\n throw new Error(\"id or reference is required\");\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a phone number with the provider.\n * Returns the registered name for identity confirmation.\n */\n async function verifyPhone(\n input: VerifyPhoneInput,\n ): Promise<Result<PhoneVerification, string>> {\n validateNonEmpty(input.phoneNumber, \"phoneNumber\");\n\n const result = await transport.send<PhoneVerification>({\n action: SDK_ACTIONS.verifyPhone,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Create a hosted invoice.\n * Auto-generates reference if omitted. Returns payment link and token.\n */\n async function createInvoice(\n input: CreateInvoiceInput,\n ): Promise<Result<InvoiceResponse, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.description, \"description\");\n\n if (input.items) {\n if (input.items.length > 50) {\n throw new Error(\"items must not exceed 50\");\n }\n for (const item of input.items) {\n if (!Number.isInteger(item.quantity) || item.quantity <= 0) {\n throw new Error(\"item quantity must be a positive integer\");\n }\n if (!Number.isInteger(item.unitPrice) || item.unitPrice <= 0) {\n throw new Error(\"item unitPrice must be a positive integer\");\n }\n }\n }\n\n const payload = { ...input, reference };\n const result = await transport.send<InvoiceResponse>({\n action: SDK_ACTIONS.createInvoice,\n payload,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a webhook payload signature.\n * Delegates to the standalone verifyWebhookSignature utility.\n */\n function verifyWebhook(input: VerifyWebhookInput): boolean {\n return verifyWebhookSignature(input);\n }\n\n return {\n collectPayment,\n collectPaymentAndResolve,\n makePayout,\n makePayoutAndResolve,\n getStatus,\n getTransaction,\n verifyPhone,\n createInvoice,\n verifyWebhookSignature: verifyWebhook,\n };\n}\n","/**\n * Factory function to create a Nylon Pay SDK instance.\n * This is the main entry point for merchants.\n *\n * Calling createNylonPay with the same apiKey and baseUrl returns the same\n * instance (singleton per key+url pair). Pass { force: true } to create a\n * fresh instance and replace the cached one.\n *\n * @example\n * ```ts\n * import { createNylonPay } from \"@nile-squad/nylonpay-ts\";\n *\n * export const nylonpay = createNylonPay({\n * apiKey: \"npk_...\",\n * apiSecret: \"nps_...\",\n * });\n * ```\n */\n\nimport { createSdkInstance, type NylonPaySdk } from \"./sdk\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_POLL_ATTEMPTS,\n DEFAULT_MAX_POLL_DURATION_MS,\n DEFAULT_MAX_POLL_INTERVAL_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n} from \"./sdk.config\";\nimport type { NylonPayConfig } from \"./types\";\n\nconst instances = new Map<string, NylonPaySdk>();\n\n/**\n * Create a Nylon Pay SDK instance.\n *\n * Returns the same instance for the same apiKey + baseUrl combination unless\n * { force: true } is passed. Use your test keys for sandbox, production keys\n * for live.\n *\n * @param config - SDK configuration with apiKey and apiSecret\n * @returns SDK instance with all payment operations\n *\n * @throws Error if required config is missing or invalid\n */\nexport function createNylonPay(config: NylonPayConfig): NylonPaySdk {\n if (!config.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n if (!config.apiKey.startsWith(\"npk_\")) {\n throw new Error('apiKey must start with \"npk_\"');\n }\n if (!config.apiSecret) {\n throw new Error(\"apiSecret is required\");\n }\n if (!config.apiSecret.startsWith(\"nps_\")) {\n throw new Error('apiSecret must start with \"nps_\"');\n }\n\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const instanceKey = `${config.apiKey}:${baseUrl}`;\n\n if (!config.force) {\n const existing = instances.get(instanceKey);\n if (existing) return existing;\n }\n\n const resolvedConfig = {\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n maxPollIntervalMs: config.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS,\n maxPollDurationMs: config.maxPollDurationMs ?? DEFAULT_MAX_POLL_DURATION_MS,\n maxPollAttempts: config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS,\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n hooks: config.hooks,\n };\n\n const instance = createSdkInstance(resolvedConfig);\n instances.set(instanceKey, instance);\n return instance;\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -535,20 +535,20 @@ interface PaymentInstance {
|
|
|
535
535
|
off(event: PaymentEvent, handler: PaymentEventHandler): PaymentInstance;
|
|
536
536
|
/**
|
|
537
537
|
* Block until the transaction reaches a terminal state. Resolves with
|
|
538
|
-
* the full {@link Transaction} on success
|
|
539
|
-
* cancellation, or polling error.
|
|
538
|
+
* the full {@link Transaction} on success, or `null` on failure,
|
|
539
|
+
* cancellation, or polling error. Never rejects.
|
|
540
540
|
*
|
|
541
541
|
* @example
|
|
542
542
|
* ```ts
|
|
543
|
-
*
|
|
544
|
-
*
|
|
543
|
+
* const tx = await payment.wait();
|
|
544
|
+
* if (tx) {
|
|
545
545
|
* console.log("Paid:", tx.amount, tx.currency);
|
|
546
|
-
* }
|
|
547
|
-
* console.error("Payment did not succeed
|
|
546
|
+
* } else {
|
|
547
|
+
* console.error("Payment did not succeed");
|
|
548
548
|
* }
|
|
549
549
|
* ```
|
|
550
550
|
*/
|
|
551
|
-
wait(): Promise<Transaction>;
|
|
551
|
+
wait(): Promise<Transaction | null>;
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -535,20 +535,20 @@ interface PaymentInstance {
|
|
|
535
535
|
off(event: PaymentEvent, handler: PaymentEventHandler): PaymentInstance;
|
|
536
536
|
/**
|
|
537
537
|
* Block until the transaction reaches a terminal state. Resolves with
|
|
538
|
-
* the full {@link Transaction} on success
|
|
539
|
-
* cancellation, or polling error.
|
|
538
|
+
* the full {@link Transaction} on success, or `null` on failure,
|
|
539
|
+
* cancellation, or polling error. Never rejects.
|
|
540
540
|
*
|
|
541
541
|
* @example
|
|
542
542
|
* ```ts
|
|
543
|
-
*
|
|
544
|
-
*
|
|
543
|
+
* const tx = await payment.wait();
|
|
544
|
+
* if (tx) {
|
|
545
545
|
* console.log("Paid:", tx.amount, tx.currency);
|
|
546
|
-
* }
|
|
547
|
-
* console.error("Payment did not succeed
|
|
546
|
+
* } else {
|
|
547
|
+
* console.error("Payment did not succeed");
|
|
548
548
|
* }
|
|
549
549
|
* ```
|
|
550
550
|
*/
|
|
551
|
-
wait(): Promise<Transaction>;
|
|
551
|
+
wait(): Promise<Transaction | null>;
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
/**
|
package/dist/index.js
CHANGED
|
@@ -323,10 +323,14 @@ var TERMINAL_STATES = /* @__PURE__ */ new Set([
|
|
|
323
323
|
"failed",
|
|
324
324
|
"cancelled"
|
|
325
325
|
]);
|
|
326
|
+
function normalizeStatus(raw) {
|
|
327
|
+
if (raw === "completed") return "successful";
|
|
328
|
+
return raw;
|
|
329
|
+
}
|
|
326
330
|
function createPaymentInstance(initialResponse, deps) {
|
|
327
331
|
const state = {
|
|
328
332
|
reference: initialResponse.reference,
|
|
329
|
-
status: initialResponse.status,
|
|
333
|
+
status: normalizeStatus(initialResponse.status),
|
|
330
334
|
transaction: null,
|
|
331
335
|
pollingTimer: null,
|
|
332
336
|
resolved: false,
|
|
@@ -361,7 +365,8 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
361
365
|
state.transaction = txResult.value;
|
|
362
366
|
const event = statusToEvent(status);
|
|
363
367
|
if (event) {
|
|
364
|
-
|
|
368
|
+
const error = status === "failed" ? state.transaction.failureReason ?? void 0 : void 0;
|
|
369
|
+
emitEvent(event, error);
|
|
365
370
|
}
|
|
366
371
|
} else {
|
|
367
372
|
emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
|
|
@@ -376,7 +381,7 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
376
381
|
);
|
|
377
382
|
return;
|
|
378
383
|
}
|
|
379
|
-
const newStatus = response.status;
|
|
384
|
+
const newStatus = normalizeStatus(response.status);
|
|
380
385
|
const oldStatus = state.status;
|
|
381
386
|
state.status = newStatus;
|
|
382
387
|
if (newStatus !== oldStatus) {
|
|
@@ -435,6 +440,12 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
435
440
|
scheduleNextPoll();
|
|
436
441
|
}
|
|
437
442
|
function startPolling() {
|
|
443
|
+
if (TERMINAL_STATES.has(state.status ?? "pending")) {
|
|
444
|
+
setTimeout(() => {
|
|
445
|
+
void handleTerminalState(state.status);
|
|
446
|
+
}, 0);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
438
449
|
scheduleNextPoll();
|
|
439
450
|
}
|
|
440
451
|
function stopPolling() {
|
|
@@ -456,37 +467,28 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
456
467
|
return paymentInstance;
|
|
457
468
|
}
|
|
458
469
|
function wait() {
|
|
459
|
-
return new Promise((resolve
|
|
470
|
+
return new Promise((resolve) => {
|
|
460
471
|
if (state.resolved) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
reject(new Error(`Payment ${state.status ?? "error"}`));
|
|
465
|
-
}
|
|
472
|
+
resolve(
|
|
473
|
+
state.status === "successful" && state.transaction ? state.transaction : null
|
|
474
|
+
);
|
|
466
475
|
return;
|
|
467
476
|
}
|
|
468
477
|
function onSuccess() {
|
|
469
478
|
cleanup();
|
|
470
|
-
|
|
471
|
-
resolve(state.transaction);
|
|
472
|
-
} else {
|
|
473
|
-
reject(
|
|
474
|
-
new Error("Payment successful but transaction data unavailable")
|
|
475
|
-
);
|
|
476
|
-
}
|
|
479
|
+
resolve(state.transaction ?? null);
|
|
477
480
|
}
|
|
478
481
|
function onFailed() {
|
|
479
482
|
cleanup();
|
|
480
|
-
|
|
483
|
+
resolve(null);
|
|
481
484
|
}
|
|
482
485
|
function onCancelled() {
|
|
483
486
|
cleanup();
|
|
484
|
-
|
|
487
|
+
resolve(null);
|
|
485
488
|
}
|
|
486
|
-
function onError(
|
|
489
|
+
function onError() {
|
|
487
490
|
cleanup();
|
|
488
|
-
|
|
489
|
-
reject(new Error(eventData.error ?? "Payment error"));
|
|
491
|
+
resolve(null);
|
|
490
492
|
}
|
|
491
493
|
function cleanup() {
|
|
492
494
|
state.emitter.off("success", onSuccess);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pubsub.ts","../src/fingerprint.ts","../src/nonce.ts","../src/sdk.config.ts","../src/signature.ts","../src/verify-response.ts","../src/transport.ts","../src/payment.ts","../src/verify-webhook.ts","../src/sdk.ts","../src/create-nylon-pay.ts"],"names":["createHmac","timingSafeEqual","randomBytes","Ok","Err"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Simple internal pubsub/event emitter for SDK payment lifecycle events.\n * Functional implementation without classes.\n *\n * @see Spec 2 section 2 - \"emits events such as nylonpay.on('success', (data) => {})\"\n *\n * @example\n * ```ts\n * const emitter = createEmitter<PaymentEvent>();\n * emitter.on(\"success\", (data) => console.log(data));\n * emitter.emit(\"success\", { event: \"success\", timestamp: \"...\" });\n * emitter.off(\"success\", handler);\n * ```\n */\n\n/**\n * Handler function type for event listeners.\n */\nexport type EventHandler<T = unknown> = (data: T) => void;\n\n/**\n * Internal state for the emitter.\n * @internal\n */\ninterface EmitterState<T> {\n listeners: Map<T, Set<EventHandler<T>>>;\n}\n\n/**\n * Create a new event emitter instance.\n *\n * @returns Emitter with on/off/emit methods\n *\n * @example\n * ```ts\n * const emitter = createEmitter<string>();\n * const unsub = emitter.on(\"hello\", (msg) => console.log(msg));\n * emitter.emit(\"hello\", \"world\");\n * unsub(); // remove listener\n * ```\n */\nexport function createEmitter<T extends string>() {\n const state: EmitterState<T> = {\n listeners: new Map(),\n };\n\n /**\n * Subscribe to an event.\n * Returns an unsubscribe function for convenience.\n */\n function on(event: T, handler: EventHandler): () => void {\n if (!state.listeners.has(event)) {\n state.listeners.set(event, new Set());\n }\n state.listeners.get(event)?.add(handler as EventHandler<unknown>);\n return () => off(event, handler);\n }\n\n /**\n * Subscribe to an event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal payment events (e.g. \"successful\", \"failed\").\n * Returns the emitter for chaining.\n */\n function once(event: T, handler: EventHandler): typeof emitter {\n const wrapper: EventHandler = (data) => {\n off(event, wrapper);\n handler(data);\n };\n on(event, wrapper);\n return emitter;\n }\n\n /**\n * Unsubscribe from an event.\n */\n function off(event: T, handler: EventHandler): void {\n const handlers = state.listeners.get(event);\n if (handlers) {\n handlers.delete(handler as EventHandler<unknown>);\n }\n }\n\n /**\n * Emit an event with data to all listeners.\n * Handlers are called synchronously in subscription order.\n */\n function emit(event: T, data: unknown): void {\n const handlers = state.listeners.get(event);\n if (!handlers || handlers.size === 0) return;\n for (const handler of handlers) {\n try {\n (handler as EventHandler<unknown>)(data);\n } catch {\n // Swallow handler errors to prevent one bad handler\n // from breaking the entire event chain\n }\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n */\n function clear(event?: T): void {\n if (event) {\n state.listeners.delete(event);\n } else {\n state.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event.\n */\n function listenerCount(event: T): number {\n return state.listeners.get(event)?.size ?? 0;\n }\n\n const emitter = { on, once, off, emit, clear, listenerCount };\n return emitter;\n}\n\n/**\n * Type for the emitter interface returned by createEmitter.\n */\nexport type Emitter<T extends string> = ReturnType<typeof createEmitter<T>>;\n","/**\n * Server fingerprint generation for SDK requests.\n * Provides a stable identifier based on runtime environment.\n *\n * @see Spec 2 section 1 - \"a server fingerprint based on runtime, os, etc\"\n */\n\nimport { createHash } from \"node:crypto\";\nimport { arch, hostname, platform, release, type } from \"node:os\";\n\n/**\n * Generate a server fingerprint based on runtime environment.\n * This provides a stable identifier for the server making requests.\n * The fingerprint is a SHA-256 hash of system characteristics.\n *\n * @returns Hex-encoded SHA-256 hash of system info\n *\n * @example\n * ```ts\n * const fingerprint = generateFingerprint();\n * // => \"e3b0c44298fc1c149afbf4c8996fb924...\"\n * ```\n */\nexport function generateFingerprint(): string {\n const components = [\n `type:${type()}`,\n `platform:${platform()}`,\n `arch:${arch()}`,\n `release:${release()}`,\n `hostname:${hostname()}`,\n `node:${process.versions.node}`,\n `v8:${process.versions.v8}`,\n ].join(\"|\");\n\n return createHash(\"sha256\").update(components).digest(\"hex\");\n}\n","/**\n * Cryptographically secure nonce generation for SDK requests.\n *\n * @see Spec 2 section 1 - \"Internally the sdk generates a nounce\"\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Generate a cryptographically secure random nonce.\n * Uses Node.js crypto.randomBytes for security.\n *\n * @param length - Byte length of the nonce (default: 16 = 32 hex chars)\n * @returns Hex-encoded random string\n *\n * @example\n * ```ts\n * const nonce = generateNonce();\n * // => \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4\"\n * ```\n */\nexport function generateNonce(length = 16): string {\n return randomBytes(length).toString(\"hex\");\n}\n","/** Default production backend URL */\nexport const DEFAULT_BASE_URL =\n \"https://api.nylonpay.nilesquad.com/api/services\";\n\n/** Default request timeout (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Default max retry attempts for transport failures */\nexport const DEFAULT_MAX_RETRIES = 3;\n\n/** Default polling interval between status checks (2 seconds) */\nexport const DEFAULT_MAX_POLL_INTERVAL_MS = 2_000;\n\n/** Default max total polling duration before timing out (5 minutes) */\nexport const DEFAULT_MAX_POLL_DURATION_MS = 300_000;\n\n/** Default max polling attempts before giving up */\nexport const DEFAULT_MAX_POLL_ATTEMPTS = 150;\n\n/** Nile.js service name for all SDK operations */\nexport const SDK_SERVICE = \"sdk\";\n\n/** Maps SDK operation names to backend action names */\nexport const SDK_ACTIONS = {\n collectPayment: \"sdk-collect-payment\",\n collectPaymentAndResolve: \"sdk-collect-payment-and-resolve\",\n makePayout: \"sdk-make-payout\",\n makePayoutAndResolve: \"sdk-make-payout-and-resolve\",\n getStatus: \"sdk-get-status\",\n getTransaction: \"sdk-get-transaction\",\n verifyPhone: \"sdk-verify-phone\",\n createInvoice: \"sdk-create-invoice\",\n} as const;\n\n/** HTTP status codes that trigger retries */\nexport const RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n","/**\n * HMAC-SHA256 signature creation for SDK requests.\n * Must match the backend's verification logic in verify-signature.ts.\n *\n * Signature payload format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * @see backend/src/services/sdk/verify-signature.ts\n * @see Spec 2 section 1 - \"creates a signature using these values and the api secret (HMAC 256)\"\n */\n\nimport { createHmac } from \"node:crypto\";\n\n/**\n * Recursively sort object keys alphabetically for deterministic JSON.\n * Must match backend's createCanonicalPayload function.\n *\n * @see backend/src/services/sdk/create-canonical-payload.ts\n */\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => sortValue(entry));\n }\n\n if (value && typeof value === \"object\") {\n const sortedEntries = Object.entries(value as Record<string, unknown>).sort(\n ([firstKey], [secondKey]) => firstKey.localeCompare(secondKey),\n );\n\n return Object.fromEntries(\n sortedEntries.map(([entryKey, entryValue]) => [\n entryKey,\n sortValue(entryValue),\n ]),\n );\n }\n\n return value;\n}\n\n/**\n * Create a canonical JSON string from a payload.\n * Keys are sorted alphabetically for deterministic serialization.\n */\nexport function createCanonicalPayload(payload: unknown): string {\n return JSON.stringify(sortValue(payload));\n}\n\n/**\n * Build the signature payload string.\n * Format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * The fingerprint is included in the signature to prevent tampering\n * with server identity information.\n *\n * @see backend/src/services/sdk/verify-signature.ts:createSignaturePayload\n */\nexport function createSignaturePayload(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n timestamp: string;\n}): string {\n return `${input.fingerprint}.${input.nonce}.${input.timestamp}.${createCanonicalPayload(input.payload)}`;\n}\n\n/**\n * Create an HMAC-SHA256 signature for SDK request authentication.\n *\n * The signature includes the server fingerprint to ensure the request\n * origin cannot be spoofed. The fingerprint contains runtime/OS info\n * that is bound to this specific server instance.\n *\n * @param input.fingerprint - Server fingerprint (included in signature)\n * @param input.nonce - Random nonce for replay protection\n * @param input.timestamp - Unix timestamp in milliseconds\n * @param input.payload - Request body (will be canonicalized)\n * @param input.secret - API secret for signing\n * @returns Hex-encoded HMAC-SHA256 signature\n */\nexport function createSignature(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n secret: string;\n timestamp: string;\n}): string {\n const payload = createSignaturePayload(input);\n\n return createHmac(\"sha256\", input.secret).update(payload).digest(\"hex\");\n}\n\n/**\n * Create a timestamp string in milliseconds.\n * Used as part of the signature payload.\n */\nexport function createTimestamp(): string {\n return Date.now().toString();\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { createCanonicalPayload } from \"./signature\";\n\n/**\n * Verify an authenticated backend response body before exposing it to SDK\n * consumers so tampered payloads are rejected consistently.\n *\n * @param data - Response payload without the `_responseSignature` field\n * @param signature - Hex-encoded HMAC-SHA256 signature from the backend\n * @param secret - API secret used for request authentication\n * @returns True when the signature matches the payload\n */\nexport function verifyResponseSignature(\n data: unknown,\n signature: string,\n secret: string,\n): boolean {\n const expectedSignature = createHmac(\"sha256\", secret)\n .update(createCanonicalPayload(data))\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * HTTP transport layer for SDK communication with the Nylon Pay backend.\n * Handles the Nile.js envelope format, HMAC request signing, response\n * signature verification, retries, and timeouts.\n *\n * @internal\n */\n\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { generateFingerprint } from \"./fingerprint\";\nimport { generateNonce } from \"./nonce\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n RETRYABLE_STATUS_CODES,\n SDK_SERVICE,\n} from \"./sdk.config\";\nimport { createSignature, createTimestamp } from \"./signature\";\nimport type { SdkError, TransportRequest } from \"./types\";\nimport { verifyResponseSignature } from \"./verify-response\";\n\n/** Cached fingerprint for this server instance. */\nconst CACHED_FINGERPRINT = generateFingerprint();\n\n/** Calculate exponential backoff delay with jitter. */\nfunction calculateBackoff(attempt: number): number {\n const base = 2 ** attempt * 1000;\n const jitter = Math.random() * 500;\n return base + jitter;\n}\n\n/** Promise-based delay. */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Strip _responseSignature from a payload and return it separately. */\nfunction stripResponseSignature<T>(payload: T): {\n data: T;\n responseSignature: string | null;\n} {\n if (\n !payload ||\n typeof payload !== \"object\" ||\n !(\"_responseSignature\" in payload)\n ) {\n return { data: payload, responseSignature: null };\n }\n\n const { _responseSignature, ...rest } = payload as Record<string, unknown>;\n\n return {\n data: rest as T,\n responseSignature:\n typeof _responseSignature === \"string\" ? _responseSignature : null,\n };\n}\n\n/** Build the Nile.js request envelope. */\nfunction buildEnvelope({\n action,\n payload,\n}: TransportRequest): Record<string, unknown> {\n return {\n intent: \"execute\",\n service: SDK_SERVICE,\n action,\n payload: {\n ...(payload as Record<string, unknown>),\n _fingerprint: CACHED_FINGERPRINT,\n },\n };\n}\n\n/**\n * Build auth headers for a request.\n *\n * The signature is computed over the inner `payload` (the operation input plus\n * `_fingerprint`), NOT the full Nile envelope. This matches the server, which\n * verifies the signature against the raw request payload — see the Transport\n * Contract in the Nylon Pay SDK Spec (https://github.com/nile-squad/specs).\n */\nfunction buildAuthHeaders({\n apiKey,\n apiSecret,\n payload,\n}: {\n apiKey: string;\n apiSecret: string;\n payload: unknown;\n}): Record<string, string> {\n const nonce = generateNonce();\n const timestamp = createTimestamp();\n const signature = createSignature({\n fingerprint: CACHED_FINGERPRINT,\n nonce,\n timestamp,\n payload,\n secret: apiSecret,\n });\n\n return {\n \"content-type\": \"application/json\",\n \"x-nylon-key\": apiKey,\n \"x-nylon-nonce\": nonce,\n \"x-nylon-signature\": signature,\n \"x-nylon-timestamp\": timestamp,\n };\n}\n\n/** Create an AbortController with a timeout. Returns cleanup to clear the timer. */\nfunction withTimeout(timeoutMs: number): {\n controller: AbortController;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n return { controller, cleanup: () => clearTimeout(timeoutId) };\n}\n\n/**\n * Create the transport layer for SDK requests.\n *\n * @param config - Resolved SDK configuration\n * @returns Transport functions\n *\n * @internal\n */\nexport function createTransport({\n apiKey,\n apiSecret,\n baseUrl = DEFAULT_BASE_URL,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n maxRetries = DEFAULT_MAX_RETRIES,\n fetch: fetchImpl,\n}: {\n apiKey: string;\n apiSecret: string;\n baseUrl?: string;\n timeoutMs?: number;\n maxRetries?: number;\n fetch: typeof globalThis.fetch;\n}) {\n /**\n * Send a request to the backend.\n * Builds the envelope and headers once, then retries only the fetch call.\n */\n async function send<T>(\n request: TransportRequest,\n ): Promise<Result<T, string>> {\n const envelope = buildEnvelope(request);\n const signedPayload = (envelope as { payload: unknown }).payload;\n const headers = buildAuthHeaders({\n apiKey,\n apiSecret,\n payload: signedPayload,\n });\n const bodyString = JSON.stringify(envelope);\n\n async function attempt(currentAttempt: number): Promise<Result<T, string>> {\n const { controller, cleanup } = withTimeout(timeoutMs);\n\n try {\n const response = await fetchImpl(baseUrl, {\n method: \"POST\",\n headers,\n body: bodyString,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const statusCode = response.status;\n const retryable = RETRYABLE_STATUS_CODES.has(statusCode);\n\n let errorMessage = `HTTP ${statusCode}`;\n try {\n const errorBody = await response.json();\n if (\n errorBody &&\n typeof errorBody === \"object\" &&\n \"message\" in errorBody\n ) {\n errorMessage = String(errorBody.message);\n }\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n if (retryable && currentAttempt < maxRetries) {\n cleanup();\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n const sdkError: SdkError = {\n code: `HTTP_${statusCode}`,\n message: errorMessage,\n statusCode,\n retryable,\n };\n\n cleanup();\n return Err(JSON.stringify(sdkError));\n }\n\n const responseBody = await response.json();\n\n if (\n !responseBody ||\n typeof responseBody !== \"object\" ||\n !(\"status\" in responseBody)\n ) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"INVALID_RESPONSE\",\n message: \"Response missing status field\",\n retryable: false,\n }),\n );\n }\n\n const { status, message, data } = responseBody as {\n status: boolean;\n message: string;\n data: unknown;\n };\n\n if (status === true) {\n const { data: strippedData, responseSignature } =\n stripResponseSignature(data);\n\n if (responseSignature) {\n const isValid = verifyResponseSignature(\n strippedData,\n responseSignature,\n apiSecret,\n );\n if (!isValid) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"RESPONSE_TAMPERED\",\n message: \"Response signature verification failed\",\n retryable: false,\n }),\n );\n }\n }\n\n cleanup();\n return Ok(strippedData as T);\n }\n\n // status === false\n const parsedError = parseError(message);\n cleanup();\n return Err(JSON.stringify(parsedError));\n } catch (error) {\n cleanup();\n\n const isAbort =\n error instanceof DOMException && error.name === \"AbortError\";\n const sdkError: SdkError = {\n code: isAbort ? \"TIMEOUT\" : \"NETWORK_ERROR\",\n message: isAbort\n ? `Request timed out after ${timeoutMs}ms`\n : String(error),\n retryable: true,\n };\n\n if (currentAttempt < maxRetries) {\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n return Err(JSON.stringify(sdkError));\n }\n }\n\n return attempt(0);\n }\n\n return { send, parseError };\n}\n\n/**\n * Parse an error string into an SdkError object.\n * Tries JSON.parse first; falls back to a generic UNKNOWN error.\n *\n * @example\n * ```ts\n * const result = await sdk.getStatus({ reference: \"ORDER-123\" });\n * if (!result.isOk) {\n * const error = parseError(result.error);\n * console.log(error.code, error.message);\n * }\n * ```\n */\nexport function parseError(error: string): SdkError {\n try {\n const parsed = JSON.parse(error) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"code\" in parsed &&\n \"message\" in parsed &&\n typeof (parsed as Record<string, unknown>).code === \"string\" &&\n typeof (parsed as Record<string, unknown>).message === \"string\"\n ) {\n return parsed as SdkError;\n }\n } catch {\n // Not JSON, fall through\n }\n\n return { code: \"UNKNOWN\", message: error };\n}\n","/**\n * Payment instance with event emission for transaction lifecycle.\n * Handles polling, event emission, and wait-for-completion.\n *\n * @see Spec 2 section 2 - \".collectPayment() returns a payment instance that they have to listen for events on\"\n * @see Spec 2 section 9 - \"sdk on merchant side internally calls another action to our backend to get transaction status updates by polling\"\n */\n\nimport type { Result } from \"slang-ts\";\nimport { createEmitter, type Emitter } from \"./pubsub\";\nimport { parseError } from \"./transport\";\nimport type {\n EventData,\n GetStatusInput,\n GetTransactionInput,\n PaymentEvent,\n PaymentEventHandler,\n PaymentInstance,\n StatusResponse,\n Transaction,\n TransactionStatus,\n} from \"./types\";\n\n/**\n * Internal state for a payment instance.\n * @internal\n */\ntype PaymentState = {\n reference: string;\n status: TransactionStatus | null;\n transaction: Transaction | null;\n pollingTimer: ReturnType<typeof setTimeout> | null;\n resolved: boolean;\n pollAttempts: number;\n pollStartTime: number;\n emitter: Emitter<PaymentEvent>;\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs: number;\n maxPollDuration: number;\n maxPollAttempts: number;\n};\n\n/** Map transaction status to payment event. */\nconst STATUS_TO_EVENT: Partial<Record<TransactionStatus, PaymentEvent>> = {\n successful: \"success\",\n failed: \"failed\",\n processing: \"processing\",\n cancelled: \"cancelled\",\n};\n\nfunction statusToEvent(status: TransactionStatus): PaymentEvent | null {\n return STATUS_TO_EVENT[status] ?? null;\n}\n\n/** Terminal states that stop polling. */\nconst TERMINAL_STATES = new Set<TransactionStatus>([\n \"successful\",\n \"failed\",\n \"cancelled\",\n]);\n\n/**\n * Create a new payment instance.\n *\n * @param initialResponse - Response with reference and initial status\n * @param deps - Dependencies injected by the SDK\n * @returns Payment instance with event subscription\n *\n * @internal\n */\nexport function createPaymentInstance(\n initialResponse: { reference: string; status: TransactionStatus },\n deps: {\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs?: number;\n maxPollDuration?: number;\n maxPollAttempts?: number;\n },\n): PaymentInstance {\n const state: PaymentState = {\n reference: initialResponse.reference,\n status: initialResponse.status,\n transaction: null,\n pollingTimer: null,\n resolved: false,\n pollAttempts: 0,\n pollStartTime: Date.now(),\n emitter: createEmitter<PaymentEvent>(),\n fetchStatus: deps.fetchStatus,\n fetchTransaction: deps.fetchTransaction,\n pollIntervalMs: deps.pollIntervalMs ?? 2000,\n maxPollDuration: deps.maxPollDuration ?? 300000,\n maxPollAttempts: deps.maxPollAttempts ?? 150,\n };\n\n function resolveWithError(error: string): void {\n state.resolved = true;\n stopPolling();\n emitEvent(\"error\", parseError(error).message);\n }\n\n /**\n * Emit an event with current transaction data.\n * @internal\n */\n function emitEvent(event: PaymentEvent, error?: string): void {\n const data: EventData = {\n event,\n transaction: state.transaction ?? undefined,\n error,\n timestamp: new Date().toISOString(),\n };\n state.emitter.emit(event, data);\n }\n\n /**\n * Handle terminal state by fetching full transaction record.\n * @internal\n */\n async function handleTerminalState(status: TransactionStatus): Promise<void> {\n const txResult = await state.fetchTransaction({\n reference: state.reference,\n });\n if (txResult.isOk) {\n state.transaction = txResult.value;\n const event = statusToEvent(status);\n if (event) {\n emitEvent(event);\n }\n } else {\n emitEvent(\"error\", `Failed to fetch transaction: ${txResult.error}`);\n }\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Handle a status response from polling.\n * @internal\n */\n async function handleStatusUpdate(response: StatusResponse): Promise<void> {\n if (response.reference !== state.reference) {\n resolveWithError(\n `Reference mismatch: expected ${state.reference} but got ${response.reference}`,\n );\n return;\n }\n\n const newStatus = response.status;\n const oldStatus = state.status;\n\n state.status = newStatus;\n\n if (newStatus !== oldStatus) {\n const event = statusToEvent(newStatus);\n if (event) {\n if (TERMINAL_STATES.has(newStatus)) {\n await handleTerminalState(newStatus);\n return;\n }\n emitEvent(event);\n }\n }\n }\n\n /**\n * Handle polling error.\n * \"Not found\" during early polling is expected; other errors stop polling.\n * @internal\n */\n function handlePollError(error: string): void {\n const isNotFound =\n error.includes(\"not found\") || error.includes(\"NOT_FOUND\");\n if (isNotFound) {\n return;\n }\n emitEvent(\"error\", parseError(error).message);\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Schedule the next poll tick.\n * Uses a single timeout so the next request only starts after the current one finishes.\n * @internal\n */\n function scheduleNextPoll(): void {\n if (state.resolved || state.pollingTimer) {\n return;\n }\n\n state.pollingTimer = setTimeout(() => {\n state.pollingTimer = null;\n void pollStatus();\n }, state.pollIntervalMs);\n }\n\n /**\n * Execute one polling cycle and queue the next one when appropriate.\n * @internal\n */\n async function pollStatus(): Promise<void> {\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n if (state.pollAttempts >= state.maxPollAttempts) {\n resolveWithError(\"Polling timeout: exceeded maximum attempts\");\n return;\n }\n\n if (Date.now() - state.pollStartTime >= state.maxPollDuration) {\n resolveWithError(\"Polling timeout: exceeded maximum duration\");\n return;\n }\n\n state.pollAttempts += 1;\n\n const result = await state.fetchStatus({ reference: state.reference });\n\n if (result.isOk) {\n await handleStatusUpdate(result.value);\n } else {\n handlePollError(result.error);\n }\n\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n scheduleNextPoll();\n }\n\n /**\n * Start polling for status updates.\n * @internal\n */\n function startPolling(): void {\n scheduleNextPoll();\n }\n\n /**\n * Stop polling.\n * @internal\n */\n function stopPolling(): void {\n if (state.pollingTimer) {\n clearTimeout(state.pollingTimer);\n state.pollingTimer = null;\n }\n }\n\n /**\n * Subscribe to payment events.\n */\n function on(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.on(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Unsubscribe from payment events.\n */\n function off(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.off(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Subscribe to a payment event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal events like \"success\" or \"failed\".\n */\n function once(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.once(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Wait for payment to reach a terminal state.\n * Resolves on success, rejects on failure/cancel/error.\n */\n function wait(): Promise<Transaction> {\n return new Promise((resolve, reject) => {\n if (state.resolved) {\n if (state.status === \"successful\" && state.transaction) {\n resolve(state.transaction);\n } else {\n reject(new Error(`Payment ${state.status ?? \"error\"}`));\n }\n return;\n }\n\n function onSuccess(): void {\n cleanup();\n if (state.transaction) {\n resolve(state.transaction);\n } else {\n reject(\n new Error(\"Payment successful but transaction data unavailable\"),\n );\n }\n }\n\n function onFailed(): void {\n cleanup();\n reject(new Error(\"Payment failed\"));\n }\n\n function onCancelled(): void {\n cleanup();\n reject(new Error(\"Payment cancelled\"));\n }\n\n function onError(data: unknown): void {\n cleanup();\n const eventData = data as EventData;\n reject(new Error(eventData.error ?? \"Payment error\"));\n }\n\n function cleanup(): void {\n state.emitter.off(\"success\", onSuccess);\n state.emitter.off(\"failed\", onFailed);\n state.emitter.off(\"cancelled\", onCancelled);\n state.emitter.off(\"error\", onError);\n }\n\n state.emitter.on(\"success\", onSuccess);\n state.emitter.on(\"failed\", onFailed);\n state.emitter.on(\"cancelled\", onCancelled);\n state.emitter.on(\"error\", onError);\n });\n }\n\n const paymentInstance: PaymentInstance = {\n get reference() {\n return state.reference;\n },\n get status() {\n return state.status;\n },\n on,\n once,\n off,\n wait,\n };\n\n startPolling();\n\n return paymentInstance;\n}\n","/**\n * Standalone webhook signature verification utility.\n * Merchants use this to confirm that incoming webhook payloads\n * were genuinely sent by Nylon Pay before acting on them.\n */\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { VerifyWebhookInput } from \"./types\";\n\n/**\n * Verify that a webhook payload was signed by Nylon Pay.\n * Operates on raw payload bytes, NOT parsed JSON (spec invariant #8).\n *\n * @param input.payload - Raw request body as string or Uint8Array\n * @param input.signature - Signature from the webhook header\n * @param input.secret - Merchant's webhook secret\n * @returns True when the signature is valid\n */\nexport function verifyWebhookSignature(input: VerifyWebhookInput): boolean {\n const payloadBytes =\n typeof input.payload === \"string\"\n ? Buffer.from(input.payload, \"utf8\")\n : Buffer.from(input.payload);\n\n const expectedSignature = createHmac(\"sha256\", input.secret)\n .update(payloadBytes)\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(input.signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * SDK instance providing all merchant-facing payment operations.\n * Created via createNylonPay factory and returned as NylonPaySdk.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { createPaymentInstance } from \"./payment\";\nimport { SDK_ACTIONS } from \"./sdk.config\";\nimport { createTransport } from \"./transport\";\nimport type {\n CollectPaymentInput,\n CreateInvoiceInput,\n GetStatusInput,\n GetTransactionInput,\n InvoiceResponse,\n MakePayoutInput,\n NylonPaySdk,\n PaymentInstance,\n PhoneVerification,\n SdkHooks,\n StatusResponse,\n Transaction,\n TransactionStatus,\n VerifyPhoneInput,\n VerifyWebhookInput,\n} from \"./types\";\nimport { verifyWebhookSignature } from \"./verify-webhook\";\n\nexport type { NylonPaySdk } from \"./types\";\n\ntype ResolvedConfig = {\n apiKey: string;\n apiSecret: string;\n baseUrl: string;\n timeoutMs: number;\n maxRetries: number;\n maxPollIntervalMs: number;\n maxPollDurationMs: number;\n maxPollAttempts: number;\n fetch: typeof globalThis.fetch;\n hooks?: SdkHooks;\n};\n\n/** Generate a random 15-character hex reference for idempotency. */\nfunction generateReference(): string {\n return randomBytes(16).toString(\"hex\").slice(0, 15);\n}\n\n/** Validate that amount is a positive integer. */\nfunction validateAmount(amount: number): void {\n if (!Number.isInteger(amount) || amount <= 0) {\n throw new Error(\"amount must be a positive integer\");\n }\n}\n\n/** Validate that a string value is non-empty. */\nfunction validateNonEmpty(value: string, fieldName: string): void {\n if (!value || value.trim() === \"\") {\n throw new Error(`${fieldName} is required`);\n }\n}\n\n/**\n * Create an SDK instance with resolved configuration.\n * Returns an object implementing the NylonPaySdk interface.\n */\nexport function createSdkInstance(config: ResolvedConfig): NylonPaySdk {\n const transport = createTransport({\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl: config.baseUrl,\n timeoutMs: config.timeoutMs,\n maxRetries: config.maxRetries,\n fetch: config.fetch,\n });\n\n const commonDeps = {\n fetchStatus: (input: GetStatusInput) =>\n transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n }),\n fetchTransaction: (input: GetTransactionInput) =>\n transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n }),\n pollIntervalMs: config.maxPollIntervalMs,\n maxPollDuration: config.maxPollDurationMs,\n maxPollAttempts: config.maxPollAttempts,\n };\n\n /**\n * Initiate a collection payment.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function collectPayment(\n input: CollectPaymentInput,\n ): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.collectPayment,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a collection and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function collectPaymentAndResolve(\n input: CollectPaymentInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.collectPaymentAndResolve,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Initiate a payout.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function makePayout(input: MakePayoutInput): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.makePayout,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a payout and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function makePayoutAndResolve(\n input: MakePayoutInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.makePayoutAndResolve,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the current status of a transaction.\n * Lightweight check that returns only status fields.\n */\n async function getStatus(\n input: GetStatusInput,\n ): Promise<Result<StatusResponse, string>> {\n validateNonEmpty(input.reference, \"reference\");\n\n const result = await transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the full transaction record.\n * Requires at least one of id or reference.\n */\n async function getTransaction(\n input: GetTransactionInput,\n ): Promise<Result<Transaction, string>> {\n if (!input.id && !input.reference) {\n throw new Error(\"id or reference is required\");\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a phone number with the provider.\n * Returns the registered name for identity confirmation.\n */\n async function verifyPhone(\n input: VerifyPhoneInput,\n ): Promise<Result<PhoneVerification, string>> {\n validateNonEmpty(input.phoneNumber, \"phoneNumber\");\n\n const result = await transport.send<PhoneVerification>({\n action: SDK_ACTIONS.verifyPhone,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Create a hosted invoice.\n * Auto-generates reference if omitted. Returns payment link and token.\n */\n async function createInvoice(\n input: CreateInvoiceInput,\n ): Promise<Result<InvoiceResponse, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.description, \"description\");\n\n if (input.items) {\n if (input.items.length > 50) {\n throw new Error(\"items must not exceed 50\");\n }\n for (const item of input.items) {\n if (!Number.isInteger(item.quantity) || item.quantity <= 0) {\n throw new Error(\"item quantity must be a positive integer\");\n }\n if (!Number.isInteger(item.unitPrice) || item.unitPrice <= 0) {\n throw new Error(\"item unitPrice must be a positive integer\");\n }\n }\n }\n\n const payload = { ...input, reference };\n const result = await transport.send<InvoiceResponse>({\n action: SDK_ACTIONS.createInvoice,\n payload,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a webhook payload signature.\n * Delegates to the standalone verifyWebhookSignature utility.\n */\n function verifyWebhook(input: VerifyWebhookInput): boolean {\n return verifyWebhookSignature(input);\n }\n\n return {\n collectPayment,\n collectPaymentAndResolve,\n makePayout,\n makePayoutAndResolve,\n getStatus,\n getTransaction,\n verifyPhone,\n createInvoice,\n verifyWebhookSignature: verifyWebhook,\n };\n}\n","/**\n * Factory function to create a Nylon Pay SDK instance.\n * This is the main entry point for merchants.\n *\n * Calling createNylonPay with the same apiKey and baseUrl returns the same\n * instance (singleton per key+url pair). Pass { force: true } to create a\n * fresh instance and replace the cached one.\n *\n * @example\n * ```ts\n * import { createNylonPay } from \"@nile-squad/nylonpay-ts\";\n *\n * export const nylonpay = createNylonPay({\n * apiKey: \"npk_...\",\n * apiSecret: \"nps_...\",\n * });\n * ```\n */\n\nimport { createSdkInstance, type NylonPaySdk } from \"./sdk\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_POLL_ATTEMPTS,\n DEFAULT_MAX_POLL_DURATION_MS,\n DEFAULT_MAX_POLL_INTERVAL_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n} from \"./sdk.config\";\nimport type { NylonPayConfig } from \"./types\";\n\nconst instances = new Map<string, NylonPaySdk>();\n\n/**\n * Create a Nylon Pay SDK instance.\n *\n * Returns the same instance for the same apiKey + baseUrl combination unless\n * { force: true } is passed. Use your test keys for sandbox, production keys\n * for live.\n *\n * @param config - SDK configuration with apiKey and apiSecret\n * @returns SDK instance with all payment operations\n *\n * @throws Error if required config is missing or invalid\n */\nexport function createNylonPay(config: NylonPayConfig): NylonPaySdk {\n if (!config.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n if (!config.apiKey.startsWith(\"npk_\")) {\n throw new Error('apiKey must start with \"npk_\"');\n }\n if (!config.apiSecret) {\n throw new Error(\"apiSecret is required\");\n }\n if (!config.apiSecret.startsWith(\"nps_\")) {\n throw new Error('apiSecret must start with \"nps_\"');\n }\n\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const instanceKey = `${config.apiKey}:${baseUrl}`;\n\n if (!config.force) {\n const existing = instances.get(instanceKey);\n if (existing) return existing;\n }\n\n const resolvedConfig = {\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n maxPollIntervalMs: config.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS,\n maxPollDurationMs: config.maxPollDurationMs ?? DEFAULT_MAX_POLL_DURATION_MS,\n maxPollAttempts: config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS,\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n hooks: config.hooks,\n };\n\n const instance = createSdkInstance(resolvedConfig);\n instances.set(instanceKey, instance);\n return instance;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pubsub.ts","../src/fingerprint.ts","../src/nonce.ts","../src/sdk.config.ts","../src/signature.ts","../src/verify-response.ts","../src/transport.ts","../src/payment.ts","../src/verify-webhook.ts","../src/sdk.ts","../src/create-nylon-pay.ts"],"names":["createHmac","timingSafeEqual","randomBytes","Ok","Err"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Simple internal pubsub/event emitter for SDK payment lifecycle events.\n * Functional implementation without classes.\n *\n * @see Spec 2 section 2 - \"emits events such as nylonpay.on('success', (data) => {})\"\n *\n * @example\n * ```ts\n * const emitter = createEmitter<PaymentEvent>();\n * emitter.on(\"success\", (data) => console.log(data));\n * emitter.emit(\"success\", { event: \"success\", timestamp: \"...\" });\n * emitter.off(\"success\", handler);\n * ```\n */\n\n/**\n * Handler function type for event listeners.\n */\nexport type EventHandler<T = unknown> = (data: T) => void;\n\n/**\n * Internal state for the emitter.\n * @internal\n */\ninterface EmitterState<T> {\n listeners: Map<T, Set<EventHandler<T>>>;\n}\n\n/**\n * Create a new event emitter instance.\n *\n * @returns Emitter with on/off/emit methods\n *\n * @example\n * ```ts\n * const emitter = createEmitter<string>();\n * const unsub = emitter.on(\"hello\", (msg) => console.log(msg));\n * emitter.emit(\"hello\", \"world\");\n * unsub(); // remove listener\n * ```\n */\nexport function createEmitter<T extends string>() {\n const state: EmitterState<T> = {\n listeners: new Map(),\n };\n\n /**\n * Subscribe to an event.\n * Returns an unsubscribe function for convenience.\n */\n function on(event: T, handler: EventHandler): () => void {\n if (!state.listeners.has(event)) {\n state.listeners.set(event, new Set());\n }\n state.listeners.get(event)?.add(handler as EventHandler<unknown>);\n return () => off(event, handler);\n }\n\n /**\n * Subscribe to an event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal payment events (e.g. \"successful\", \"failed\").\n * Returns the emitter for chaining.\n */\n function once(event: T, handler: EventHandler): typeof emitter {\n const wrapper: EventHandler = (data) => {\n off(event, wrapper);\n handler(data);\n };\n on(event, wrapper);\n return emitter;\n }\n\n /**\n * Unsubscribe from an event.\n */\n function off(event: T, handler: EventHandler): void {\n const handlers = state.listeners.get(event);\n if (handlers) {\n handlers.delete(handler as EventHandler<unknown>);\n }\n }\n\n /**\n * Emit an event with data to all listeners.\n * Handlers are called synchronously in subscription order.\n */\n function emit(event: T, data: unknown): void {\n const handlers = state.listeners.get(event);\n if (!handlers || handlers.size === 0) return;\n for (const handler of handlers) {\n try {\n (handler as EventHandler<unknown>)(data);\n } catch {\n // Swallow handler errors to prevent one bad handler\n // from breaking the entire event chain\n }\n }\n }\n\n /**\n * Remove all listeners for a specific event, or all events if no event specified.\n */\n function clear(event?: T): void {\n if (event) {\n state.listeners.delete(event);\n } else {\n state.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event.\n */\n function listenerCount(event: T): number {\n return state.listeners.get(event)?.size ?? 0;\n }\n\n const emitter = { on, once, off, emit, clear, listenerCount };\n return emitter;\n}\n\n/**\n * Type for the emitter interface returned by createEmitter.\n */\nexport type Emitter<T extends string> = ReturnType<typeof createEmitter<T>>;\n","/**\n * Server fingerprint generation for SDK requests.\n * Provides a stable identifier based on runtime environment.\n *\n * @see Spec 2 section 1 - \"a server fingerprint based on runtime, os, etc\"\n */\n\nimport { createHash } from \"node:crypto\";\nimport { arch, hostname, platform, release, type } from \"node:os\";\n\n/**\n * Generate a server fingerprint based on runtime environment.\n * This provides a stable identifier for the server making requests.\n * The fingerprint is a SHA-256 hash of system characteristics.\n *\n * @returns Hex-encoded SHA-256 hash of system info\n *\n * @example\n * ```ts\n * const fingerprint = generateFingerprint();\n * // => \"e3b0c44298fc1c149afbf4c8996fb924...\"\n * ```\n */\nexport function generateFingerprint(): string {\n const components = [\n `type:${type()}`,\n `platform:${platform()}`,\n `arch:${arch()}`,\n `release:${release()}`,\n `hostname:${hostname()}`,\n `node:${process.versions.node}`,\n `v8:${process.versions.v8}`,\n ].join(\"|\");\n\n return createHash(\"sha256\").update(components).digest(\"hex\");\n}\n","/**\n * Cryptographically secure nonce generation for SDK requests.\n *\n * @see Spec 2 section 1 - \"Internally the sdk generates a nounce\"\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Generate a cryptographically secure random nonce.\n * Uses Node.js crypto.randomBytes for security.\n *\n * @param length - Byte length of the nonce (default: 16 = 32 hex chars)\n * @returns Hex-encoded random string\n *\n * @example\n * ```ts\n * const nonce = generateNonce();\n * // => \"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4\"\n * ```\n */\nexport function generateNonce(length = 16): string {\n return randomBytes(length).toString(\"hex\");\n}\n","/** Default production backend URL */\nexport const DEFAULT_BASE_URL =\n \"https://api.nylonpay.nilesquad.com/api/services\";\n\n/** Default request timeout (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Default max retry attempts for transport failures */\nexport const DEFAULT_MAX_RETRIES = 3;\n\n/** Default polling interval between status checks (2 seconds) */\nexport const DEFAULT_MAX_POLL_INTERVAL_MS = 2_000;\n\n/** Default max total polling duration before timing out (5 minutes) */\nexport const DEFAULT_MAX_POLL_DURATION_MS = 300_000;\n\n/** Default max polling attempts before giving up */\nexport const DEFAULT_MAX_POLL_ATTEMPTS = 150;\n\n/** Nile.js service name for all SDK operations */\nexport const SDK_SERVICE = \"sdk\";\n\n/** Maps SDK operation names to backend action names */\nexport const SDK_ACTIONS = {\n collectPayment: \"sdk-collect-payment\",\n collectPaymentAndResolve: \"sdk-collect-payment-and-resolve\",\n makePayout: \"sdk-make-payout\",\n makePayoutAndResolve: \"sdk-make-payout-and-resolve\",\n getStatus: \"sdk-get-status\",\n getTransaction: \"sdk-get-transaction\",\n verifyPhone: \"sdk-verify-phone\",\n createInvoice: \"sdk-create-invoice\",\n} as const;\n\n/** HTTP status codes that trigger retries */\nexport const RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n","/**\n * HMAC-SHA256 signature creation for SDK requests.\n * Must match the backend's verification logic in verify-signature.ts.\n *\n * Signature payload format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * @see backend/src/services/sdk/verify-signature.ts\n * @see Spec 2 section 1 - \"creates a signature using these values and the api secret (HMAC 256)\"\n */\n\nimport { createHmac } from \"node:crypto\";\n\n/**\n * Recursively sort object keys alphabetically for deterministic JSON.\n * Must match backend's createCanonicalPayload function.\n *\n * @see backend/src/services/sdk/create-canonical-payload.ts\n */\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => sortValue(entry));\n }\n\n if (value && typeof value === \"object\") {\n const sortedEntries = Object.entries(value as Record<string, unknown>).sort(\n ([firstKey], [secondKey]) => firstKey.localeCompare(secondKey),\n );\n\n return Object.fromEntries(\n sortedEntries.map(([entryKey, entryValue]) => [\n entryKey,\n sortValue(entryValue),\n ]),\n );\n }\n\n return value;\n}\n\n/**\n * Create a canonical JSON string from a payload.\n * Keys are sorted alphabetically for deterministic serialization.\n */\nexport function createCanonicalPayload(payload: unknown): string {\n return JSON.stringify(sortValue(payload));\n}\n\n/**\n * Build the signature payload string.\n * Format: fingerprint.nonce.timestamp.canonicalPayload\n *\n * The fingerprint is included in the signature to prevent tampering\n * with server identity information.\n *\n * @see backend/src/services/sdk/verify-signature.ts:createSignaturePayload\n */\nexport function createSignaturePayload(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n timestamp: string;\n}): string {\n return `${input.fingerprint}.${input.nonce}.${input.timestamp}.${createCanonicalPayload(input.payload)}`;\n}\n\n/**\n * Create an HMAC-SHA256 signature for SDK request authentication.\n *\n * The signature includes the server fingerprint to ensure the request\n * origin cannot be spoofed. The fingerprint contains runtime/OS info\n * that is bound to this specific server instance.\n *\n * @param input.fingerprint - Server fingerprint (included in signature)\n * @param input.nonce - Random nonce for replay protection\n * @param input.timestamp - Unix timestamp in milliseconds\n * @param input.payload - Request body (will be canonicalized)\n * @param input.secret - API secret for signing\n * @returns Hex-encoded HMAC-SHA256 signature\n */\nexport function createSignature(input: {\n fingerprint: string;\n nonce: string;\n payload: unknown;\n secret: string;\n timestamp: string;\n}): string {\n const payload = createSignaturePayload(input);\n\n return createHmac(\"sha256\", input.secret).update(payload).digest(\"hex\");\n}\n\n/**\n * Create a timestamp string in milliseconds.\n * Used as part of the signature payload.\n */\nexport function createTimestamp(): string {\n return Date.now().toString();\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { createCanonicalPayload } from \"./signature\";\n\n/**\n * Verify an authenticated backend response body before exposing it to SDK\n * consumers so tampered payloads are rejected consistently.\n *\n * @param data - Response payload without the `_responseSignature` field\n * @param signature - Hex-encoded HMAC-SHA256 signature from the backend\n * @param secret - API secret used for request authentication\n * @returns True when the signature matches the payload\n */\nexport function verifyResponseSignature(\n data: unknown,\n signature: string,\n secret: string,\n): boolean {\n const expectedSignature = createHmac(\"sha256\", secret)\n .update(createCanonicalPayload(data))\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * HTTP transport layer for SDK communication with the Nylon Pay backend.\n * Handles the Nile.js envelope format, HMAC request signing, response\n * signature verification, retries, and timeouts.\n *\n * @internal\n */\n\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { generateFingerprint } from \"./fingerprint\";\nimport { generateNonce } from \"./nonce\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n RETRYABLE_STATUS_CODES,\n SDK_SERVICE,\n} from \"./sdk.config\";\nimport { createSignature, createTimestamp } from \"./signature\";\nimport type { SdkError, TransportRequest } from \"./types\";\nimport { verifyResponseSignature } from \"./verify-response\";\n\n/** Cached fingerprint for this server instance. */\nconst CACHED_FINGERPRINT = generateFingerprint();\n\n/** Calculate exponential backoff delay with jitter. */\nfunction calculateBackoff(attempt: number): number {\n const base = 2 ** attempt * 1000;\n const jitter = Math.random() * 500;\n return base + jitter;\n}\n\n/** Promise-based delay. */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Strip _responseSignature from a payload and return it separately. */\nfunction stripResponseSignature<T>(payload: T): {\n data: T;\n responseSignature: string | null;\n} {\n if (\n !payload ||\n typeof payload !== \"object\" ||\n !(\"_responseSignature\" in payload)\n ) {\n return { data: payload, responseSignature: null };\n }\n\n const { _responseSignature, ...rest } = payload as Record<string, unknown>;\n\n return {\n data: rest as T,\n responseSignature:\n typeof _responseSignature === \"string\" ? _responseSignature : null,\n };\n}\n\n/** Build the Nile.js request envelope. */\nfunction buildEnvelope({\n action,\n payload,\n}: TransportRequest): Record<string, unknown> {\n return {\n intent: \"execute\",\n service: SDK_SERVICE,\n action,\n payload: {\n ...(payload as Record<string, unknown>),\n _fingerprint: CACHED_FINGERPRINT,\n },\n };\n}\n\n/**\n * Build auth headers for a request.\n *\n * The signature is computed over the inner `payload` (the operation input plus\n * `_fingerprint`), NOT the full Nile envelope. This matches the server, which\n * verifies the signature against the raw request payload — see the Transport\n * Contract in the Nylon Pay SDK Spec (https://github.com/nile-squad/specs).\n */\nfunction buildAuthHeaders({\n apiKey,\n apiSecret,\n payload,\n}: {\n apiKey: string;\n apiSecret: string;\n payload: unknown;\n}): Record<string, string> {\n const nonce = generateNonce();\n const timestamp = createTimestamp();\n const signature = createSignature({\n fingerprint: CACHED_FINGERPRINT,\n nonce,\n timestamp,\n payload,\n secret: apiSecret,\n });\n\n return {\n \"content-type\": \"application/json\",\n \"x-nylon-key\": apiKey,\n \"x-nylon-nonce\": nonce,\n \"x-nylon-signature\": signature,\n \"x-nylon-timestamp\": timestamp,\n };\n}\n\n/** Create an AbortController with a timeout. Returns cleanup to clear the timer. */\nfunction withTimeout(timeoutMs: number): {\n controller: AbortController;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n return { controller, cleanup: () => clearTimeout(timeoutId) };\n}\n\n/**\n * Create the transport layer for SDK requests.\n *\n * @param config - Resolved SDK configuration\n * @returns Transport functions\n *\n * @internal\n */\nexport function createTransport({\n apiKey,\n apiSecret,\n baseUrl = DEFAULT_BASE_URL,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n maxRetries = DEFAULT_MAX_RETRIES,\n fetch: fetchImpl,\n}: {\n apiKey: string;\n apiSecret: string;\n baseUrl?: string;\n timeoutMs?: number;\n maxRetries?: number;\n fetch: typeof globalThis.fetch;\n}) {\n /**\n * Send a request to the backend.\n * Builds the envelope and headers once, then retries only the fetch call.\n */\n async function send<T>(\n request: TransportRequest,\n ): Promise<Result<T, string>> {\n const envelope = buildEnvelope(request);\n const signedPayload = (envelope as { payload: unknown }).payload;\n const headers = buildAuthHeaders({\n apiKey,\n apiSecret,\n payload: signedPayload,\n });\n const bodyString = JSON.stringify(envelope);\n\n async function attempt(currentAttempt: number): Promise<Result<T, string>> {\n const { controller, cleanup } = withTimeout(timeoutMs);\n\n try {\n const response = await fetchImpl(baseUrl, {\n method: \"POST\",\n headers,\n body: bodyString,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const statusCode = response.status;\n const retryable = RETRYABLE_STATUS_CODES.has(statusCode);\n\n let errorMessage = `HTTP ${statusCode}`;\n try {\n const errorBody = await response.json();\n if (\n errorBody &&\n typeof errorBody === \"object\" &&\n \"message\" in errorBody\n ) {\n errorMessage = String(errorBody.message);\n }\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n if (retryable && currentAttempt < maxRetries) {\n cleanup();\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n const sdkError: SdkError = {\n code: `HTTP_${statusCode}`,\n message: errorMessage,\n statusCode,\n retryable,\n };\n\n cleanup();\n return Err(JSON.stringify(sdkError));\n }\n\n const responseBody = await response.json();\n\n if (\n !responseBody ||\n typeof responseBody !== \"object\" ||\n !(\"status\" in responseBody)\n ) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"INVALID_RESPONSE\",\n message: \"Response missing status field\",\n retryable: false,\n }),\n );\n }\n\n const { status, message, data } = responseBody as {\n status: boolean;\n message: string;\n data: unknown;\n };\n\n if (status === true) {\n const { data: strippedData, responseSignature } =\n stripResponseSignature(data);\n\n if (responseSignature) {\n const isValid = verifyResponseSignature(\n strippedData,\n responseSignature,\n apiSecret,\n );\n if (!isValid) {\n cleanup();\n return Err(\n JSON.stringify({\n code: \"RESPONSE_TAMPERED\",\n message: \"Response signature verification failed\",\n retryable: false,\n }),\n );\n }\n }\n\n cleanup();\n return Ok(strippedData as T);\n }\n\n // status === false\n const parsedError = parseError(message);\n cleanup();\n return Err(JSON.stringify(parsedError));\n } catch (error) {\n cleanup();\n\n const isAbort =\n error instanceof DOMException && error.name === \"AbortError\";\n const sdkError: SdkError = {\n code: isAbort ? \"TIMEOUT\" : \"NETWORK_ERROR\",\n message: isAbort\n ? `Request timed out after ${timeoutMs}ms`\n : String(error),\n retryable: true,\n };\n\n if (currentAttempt < maxRetries) {\n await delay(calculateBackoff(currentAttempt));\n return attempt(currentAttempt + 1);\n }\n\n return Err(JSON.stringify(sdkError));\n }\n }\n\n return attempt(0);\n }\n\n return { send, parseError };\n}\n\n/**\n * Parse an error string into an SdkError object.\n * Tries JSON.parse first; falls back to a generic UNKNOWN error.\n *\n * @example\n * ```ts\n * const result = await sdk.getStatus({ reference: \"ORDER-123\" });\n * if (!result.isOk) {\n * const error = parseError(result.error);\n * console.log(error.code, error.message);\n * }\n * ```\n */\nexport function parseError(error: string): SdkError {\n try {\n const parsed = JSON.parse(error) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n \"code\" in parsed &&\n \"message\" in parsed &&\n typeof (parsed as Record<string, unknown>).code === \"string\" &&\n typeof (parsed as Record<string, unknown>).message === \"string\"\n ) {\n return parsed as SdkError;\n }\n } catch {\n // Not JSON, fall through\n }\n\n return { code: \"UNKNOWN\", message: error };\n}\n","/**\n * Payment instance with event emission for transaction lifecycle.\n * Handles polling, event emission, and wait-for-completion.\n *\n * @see Spec 2 section 2 - \".collectPayment() returns a payment instance that they have to listen for events on\"\n * @see Spec 2 section 9 - \"sdk on merchant side internally calls another action to our backend to get transaction status updates by polling\"\n */\n\nimport type { Result } from \"slang-ts\";\nimport { createEmitter, type Emitter } from \"./pubsub\";\nimport { parseError } from \"./transport\";\nimport type {\n EventData,\n GetStatusInput,\n GetTransactionInput,\n PaymentEvent,\n PaymentEventHandler,\n PaymentInstance,\n StatusResponse,\n Transaction,\n TransactionStatus,\n} from \"./types\";\n\n/**\n * Internal state for a payment instance.\n * @internal\n */\ntype PaymentState = {\n reference: string;\n status: TransactionStatus | null;\n transaction: Transaction | null;\n pollingTimer: ReturnType<typeof setTimeout> | null;\n resolved: boolean;\n pollAttempts: number;\n pollStartTime: number;\n emitter: Emitter<PaymentEvent>;\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs: number;\n maxPollDuration: number;\n maxPollAttempts: number;\n};\n\n/** Map transaction status to payment event. */\nconst STATUS_TO_EVENT: Partial<Record<TransactionStatus, PaymentEvent>> = {\n successful: \"success\",\n failed: \"failed\",\n processing: \"processing\",\n cancelled: \"cancelled\",\n};\n\nfunction statusToEvent(status: TransactionStatus): PaymentEvent | null {\n return STATUS_TO_EVENT[status] ?? null;\n}\n\n/** Terminal states that stop polling. */\nconst TERMINAL_STATES = new Set<TransactionStatus>([\n \"successful\",\n \"failed\",\n \"cancelled\",\n]);\n\n/**\n * Normalise raw backend status strings to TransactionStatus.\n * The backend may return \"completed\" for successful payments — map it to\n * \"successful\" so SDK events fire correctly.\n */\nfunction normalizeStatus(raw: string): TransactionStatus {\n if (raw === \"completed\") return \"successful\";\n return raw as TransactionStatus;\n}\n\n/**\n * Create a new payment instance.\n *\n * @param initialResponse - Response with reference and initial status\n * @param deps - Dependencies injected by the SDK\n * @returns Payment instance with event subscription\n *\n * @internal\n */\nexport function createPaymentInstance(\n initialResponse: { reference: string; status: TransactionStatus },\n deps: {\n fetchStatus: (\n input: GetStatusInput,\n ) => Promise<Result<StatusResponse, string>>;\n fetchTransaction: (\n input: GetTransactionInput,\n ) => Promise<Result<Transaction, string>>;\n pollIntervalMs?: number;\n maxPollDuration?: number;\n maxPollAttempts?: number;\n },\n): PaymentInstance {\n const state: PaymentState = {\n reference: initialResponse.reference,\n status: normalizeStatus(initialResponse.status),\n transaction: null,\n pollingTimer: null,\n resolved: false,\n pollAttempts: 0,\n pollStartTime: Date.now(),\n emitter: createEmitter<PaymentEvent>(),\n fetchStatus: deps.fetchStatus,\n fetchTransaction: deps.fetchTransaction,\n pollIntervalMs: deps.pollIntervalMs ?? 2000,\n maxPollDuration: deps.maxPollDuration ?? 300000,\n maxPollAttempts: deps.maxPollAttempts ?? 150,\n };\n\n function resolveWithError(error: string): void {\n state.resolved = true;\n stopPolling();\n emitEvent(\"error\", parseError(error).message);\n }\n\n /**\n * Emit an event with current transaction data.\n * @internal\n */\n function emitEvent(event: PaymentEvent, error?: string): void {\n const data: EventData = {\n event,\n transaction: state.transaction ?? undefined,\n error,\n timestamp: new Date().toISOString(),\n };\n state.emitter.emit(event, data);\n }\n\n /**\n * Handle terminal state by fetching full transaction record.\n * @internal\n */\n async function handleTerminalState(status: TransactionStatus): Promise<void> {\n const txResult = await state.fetchTransaction({\n reference: state.reference,\n });\n if (txResult.isOk) {\n state.transaction = txResult.value;\n const event = statusToEvent(status);\n if (event) {\n const error =\n status === \"failed\"\n ? (state.transaction.failureReason ?? undefined)\n : undefined;\n emitEvent(event, error);\n }\n } else {\n emitEvent(\"error\", `Failed to fetch transaction: ${txResult.error}`);\n }\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Handle a status response from polling.\n * @internal\n */\n async function handleStatusUpdate(response: StatusResponse): Promise<void> {\n if (response.reference !== state.reference) {\n resolveWithError(\n `Reference mismatch: expected ${state.reference} but got ${response.reference}`,\n );\n return;\n }\n\n const newStatus = normalizeStatus(response.status);\n const oldStatus = state.status;\n\n state.status = newStatus;\n\n if (newStatus !== oldStatus) {\n const event = statusToEvent(newStatus);\n if (event) {\n if (TERMINAL_STATES.has(newStatus)) {\n await handleTerminalState(newStatus);\n return;\n }\n emitEvent(event);\n }\n }\n }\n\n /**\n * Handle polling error.\n * \"Not found\" during early polling is expected; other errors stop polling.\n * @internal\n */\n function handlePollError(error: string): void {\n const isNotFound =\n error.includes(\"not found\") || error.includes(\"NOT_FOUND\");\n if (isNotFound) {\n return;\n }\n emitEvent(\"error\", parseError(error).message);\n state.resolved = true;\n stopPolling();\n }\n\n /**\n * Schedule the next poll tick.\n * Uses a single timeout so the next request only starts after the current one finishes.\n * @internal\n */\n function scheduleNextPoll(): void {\n if (state.resolved || state.pollingTimer) {\n return;\n }\n\n state.pollingTimer = setTimeout(() => {\n state.pollingTimer = null;\n void pollStatus();\n }, state.pollIntervalMs);\n }\n\n /**\n * Execute one polling cycle and queue the next one when appropriate.\n * @internal\n */\n async function pollStatus(): Promise<void> {\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n if (state.pollAttempts >= state.maxPollAttempts) {\n resolveWithError(\"Polling timeout: exceeded maximum attempts\");\n return;\n }\n\n if (Date.now() - state.pollStartTime >= state.maxPollDuration) {\n resolveWithError(\"Polling timeout: exceeded maximum duration\");\n return;\n }\n\n state.pollAttempts += 1;\n\n const result = await state.fetchStatus({ reference: state.reference });\n\n if (result.isOk) {\n await handleStatusUpdate(result.value);\n } else {\n handlePollError(result.error);\n }\n\n if (state.resolved) {\n stopPolling();\n return;\n }\n\n scheduleNextPoll();\n }\n\n /**\n * Start polling for status updates.\n * If the initial status is already terminal (e.g. sandbox resolves synchronously),\n * emit the terminal event after a tick so handlers registered after instance\n * creation still fire.\n * @internal\n */\n function startPolling(): void {\n if (TERMINAL_STATES.has(state.status ?? \"pending\")) {\n setTimeout(() => {\n void handleTerminalState(state.status as TransactionStatus);\n }, 0);\n return;\n }\n scheduleNextPoll();\n }\n\n /**\n * Stop polling.\n * @internal\n */\n function stopPolling(): void {\n if (state.pollingTimer) {\n clearTimeout(state.pollingTimer);\n state.pollingTimer = null;\n }\n }\n\n /**\n * Subscribe to payment events.\n */\n function on(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.on(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Unsubscribe from payment events.\n */\n function off(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.off(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Subscribe to a payment event for a single invocation, then auto-unsubscribe.\n * Useful for one-shot handlers on terminal events like \"success\" or \"failed\".\n */\n function once(\n event: PaymentEvent,\n handler: PaymentEventHandler,\n ): PaymentInstance {\n state.emitter.once(event, handler as (data: unknown) => void);\n return paymentInstance;\n }\n\n /**\n * Wait for payment to reach a terminal state.\n * Resolves with the full Transaction on success, null on failure/cancel/error.\n * Never rejects — check the return value to determine outcome.\n */\n function wait(): Promise<Transaction | null> {\n return new Promise((resolve) => {\n if (state.resolved) {\n resolve(\n state.status === \"successful\" && state.transaction\n ? state.transaction\n : null,\n );\n return;\n }\n\n function onSuccess(): void {\n cleanup();\n resolve(state.transaction ?? null);\n }\n\n function onFailed(): void {\n cleanup();\n resolve(null);\n }\n\n function onCancelled(): void {\n cleanup();\n resolve(null);\n }\n\n function onError(): void {\n cleanup();\n resolve(null);\n }\n\n function cleanup(): void {\n state.emitter.off(\"success\", onSuccess);\n state.emitter.off(\"failed\", onFailed);\n state.emitter.off(\"cancelled\", onCancelled);\n state.emitter.off(\"error\", onError);\n }\n\n state.emitter.on(\"success\", onSuccess);\n state.emitter.on(\"failed\", onFailed);\n state.emitter.on(\"cancelled\", onCancelled);\n state.emitter.on(\"error\", onError);\n });\n }\n\n const paymentInstance: PaymentInstance = {\n get reference() {\n return state.reference;\n },\n get status() {\n return state.status;\n },\n on,\n once,\n off,\n wait,\n };\n\n startPolling();\n\n return paymentInstance;\n}\n","/**\n * Standalone webhook signature verification utility.\n * Merchants use this to confirm that incoming webhook payloads\n * were genuinely sent by Nylon Pay before acting on them.\n */\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { VerifyWebhookInput } from \"./types\";\n\n/**\n * Verify that a webhook payload was signed by Nylon Pay.\n * Operates on raw payload bytes, NOT parsed JSON (spec invariant #8).\n *\n * @param input.payload - Raw request body as string or Uint8Array\n * @param input.signature - Signature from the webhook header\n * @param input.secret - Merchant's webhook secret\n * @returns True when the signature is valid\n */\nexport function verifyWebhookSignature(input: VerifyWebhookInput): boolean {\n const payloadBytes =\n typeof input.payload === \"string\"\n ? Buffer.from(input.payload, \"utf8\")\n : Buffer.from(input.payload);\n\n const expectedSignature = createHmac(\"sha256\", input.secret)\n .update(payloadBytes)\n .digest(\"hex\");\n\n const providedBuffer = Buffer.from(input.signature, \"hex\");\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\n\n if (providedBuffer.length !== expectedBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(providedBuffer, expectedBuffer);\n}\n","/**\n * SDK instance providing all merchant-facing payment operations.\n * Created via createNylonPay factory and returned as NylonPaySdk.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { Err, Ok, type Result } from \"slang-ts\";\nimport { createPaymentInstance } from \"./payment\";\nimport { SDK_ACTIONS } from \"./sdk.config\";\nimport { createTransport } from \"./transport\";\nimport type {\n CollectPaymentInput,\n CreateInvoiceInput,\n GetStatusInput,\n GetTransactionInput,\n InvoiceResponse,\n MakePayoutInput,\n NylonPaySdk,\n PaymentInstance,\n PhoneVerification,\n SdkHooks,\n StatusResponse,\n Transaction,\n TransactionStatus,\n VerifyPhoneInput,\n VerifyWebhookInput,\n} from \"./types\";\nimport { verifyWebhookSignature } from \"./verify-webhook\";\n\nexport type { NylonPaySdk } from \"./types\";\n\ntype ResolvedConfig = {\n apiKey: string;\n apiSecret: string;\n baseUrl: string;\n timeoutMs: number;\n maxRetries: number;\n maxPollIntervalMs: number;\n maxPollDurationMs: number;\n maxPollAttempts: number;\n fetch: typeof globalThis.fetch;\n hooks?: SdkHooks;\n};\n\n/** Generate a random 15-character hex reference for idempotency. */\nfunction generateReference(): string {\n return randomBytes(16).toString(\"hex\").slice(0, 15);\n}\n\n/** Validate that amount is a positive integer. */\nfunction validateAmount(amount: number): void {\n if (!Number.isInteger(amount) || amount <= 0) {\n throw new Error(\"amount must be a positive integer\");\n }\n}\n\n/** Validate that a string value is non-empty. */\nfunction validateNonEmpty(value: string, fieldName: string): void {\n if (!value || value.trim() === \"\") {\n throw new Error(`${fieldName} is required`);\n }\n}\n\n/**\n * Create an SDK instance with resolved configuration.\n * Returns an object implementing the NylonPaySdk interface.\n */\nexport function createSdkInstance(config: ResolvedConfig): NylonPaySdk {\n const transport = createTransport({\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl: config.baseUrl,\n timeoutMs: config.timeoutMs,\n maxRetries: config.maxRetries,\n fetch: config.fetch,\n });\n\n const commonDeps = {\n fetchStatus: (input: GetStatusInput) =>\n transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n }),\n fetchTransaction: (input: GetTransactionInput) =>\n transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n }),\n pollIntervalMs: config.maxPollIntervalMs,\n maxPollDuration: config.maxPollDurationMs,\n maxPollAttempts: config.maxPollAttempts,\n };\n\n /**\n * Initiate a collection payment.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function collectPayment(\n input: CollectPaymentInput,\n ): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.collectPayment,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a collection and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function collectPaymentAndResolve(\n input: CollectPaymentInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n if (input.method === \"bank\" && !input.bank) {\n throw new Error('bank details are required when method is \"bank\"');\n }\n\n let payload = { ...input, reference };\n if (config.hooks?.beforeCollect) {\n const mutated = await config.hooks.beforeCollect(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.collectPaymentAndResolve,\n payload,\n });\n\n if (config.hooks?.afterCollect) {\n await config.hooks.afterCollect(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Initiate a payout.\n * Auto-generates reference if omitted. Returns a PaymentInstance\n * that emits events as the transaction progresses.\n */\n async function makePayout(input: MakePayoutInput): Promise<PaymentInstance> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<{\n reference: string;\n status: TransactionStatus;\n }>({\n action: SDK_ACTIONS.makePayout,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return createPaymentInstance(result.value, commonDeps);\n }\n\n return createPaymentInstance(\n { reference, status: \"pending\" },\n {\n ...commonDeps,\n fetchStatus: async () => Err(result.error),\n fetchTransaction: async () => Err(result.error),\n pollIntervalMs: 0,\n maxPollAttempts: 1,\n maxPollDuration: Number.MAX_SAFE_INTEGER,\n },\n );\n }\n\n /**\n * Initiate a payout and block until terminal state.\n * Server polls internally; merchant gets the full transaction record.\n */\n async function makePayoutAndResolve(\n input: MakePayoutInput,\n ): Promise<Result<Transaction, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.customer.name, \"customer.name\");\n validateNonEmpty(input.customer.phoneNumber, \"customer.phoneNumber\");\n validateNonEmpty(input.description, \"description\");\n validateNonEmpty(\n input.destination.accountHolderName,\n \"destination.accountHolderName\",\n );\n validateNonEmpty(\n input.destination.accountNumber,\n \"destination.accountNumber\",\n );\n\n let payload = { ...input, reference };\n if (config.hooks?.beforePayout) {\n const mutated = await config.hooks.beforePayout(payload);\n if (mutated != null)\n payload = { ...mutated, reference: mutated.reference ?? reference };\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.makePayoutAndResolve,\n payload,\n });\n\n if (config.hooks?.afterPayout) {\n await config.hooks.afterPayout(\n result.isOk\n ? Ok({\n reference: result.value.reference,\n status: result.value.status,\n })\n : Err(result.error),\n payload,\n );\n }\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the current status of a transaction.\n * Lightweight check that returns only status fields.\n */\n async function getStatus(\n input: GetStatusInput,\n ): Promise<Result<StatusResponse, string>> {\n validateNonEmpty(input.reference, \"reference\");\n\n const result = await transport.send<StatusResponse>({\n action: SDK_ACTIONS.getStatus,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Get the full transaction record.\n * Requires at least one of id or reference.\n */\n async function getTransaction(\n input: GetTransactionInput,\n ): Promise<Result<Transaction, string>> {\n if (!input.id && !input.reference) {\n throw new Error(\"id or reference is required\");\n }\n\n const result = await transport.send<Transaction>({\n action: SDK_ACTIONS.getTransaction,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a phone number with the provider.\n * Returns the registered name for identity confirmation.\n */\n async function verifyPhone(\n input: VerifyPhoneInput,\n ): Promise<Result<PhoneVerification, string>> {\n validateNonEmpty(input.phoneNumber, \"phoneNumber\");\n\n const result = await transport.send<PhoneVerification>({\n action: SDK_ACTIONS.verifyPhone,\n payload: input,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Create a hosted invoice.\n * Auto-generates reference if omitted. Returns payment link and token.\n */\n async function createInvoice(\n input: CreateInvoiceInput,\n ): Promise<Result<InvoiceResponse, string>> {\n const reference = input.reference ?? generateReference();\n validateAmount(input.amount);\n validateNonEmpty(input.description, \"description\");\n\n if (input.items) {\n if (input.items.length > 50) {\n throw new Error(\"items must not exceed 50\");\n }\n for (const item of input.items) {\n if (!Number.isInteger(item.quantity) || item.quantity <= 0) {\n throw new Error(\"item quantity must be a positive integer\");\n }\n if (!Number.isInteger(item.unitPrice) || item.unitPrice <= 0) {\n throw new Error(\"item unitPrice must be a positive integer\");\n }\n }\n }\n\n const payload = { ...input, reference };\n const result = await transport.send<InvoiceResponse>({\n action: SDK_ACTIONS.createInvoice,\n payload,\n });\n\n if (result.isOk) {\n return Ok(result.value);\n }\n return Err(result.error);\n }\n\n /**\n * Verify a webhook payload signature.\n * Delegates to the standalone verifyWebhookSignature utility.\n */\n function verifyWebhook(input: VerifyWebhookInput): boolean {\n return verifyWebhookSignature(input);\n }\n\n return {\n collectPayment,\n collectPaymentAndResolve,\n makePayout,\n makePayoutAndResolve,\n getStatus,\n getTransaction,\n verifyPhone,\n createInvoice,\n verifyWebhookSignature: verifyWebhook,\n };\n}\n","/**\n * Factory function to create a Nylon Pay SDK instance.\n * This is the main entry point for merchants.\n *\n * Calling createNylonPay with the same apiKey and baseUrl returns the same\n * instance (singleton per key+url pair). Pass { force: true } to create a\n * fresh instance and replace the cached one.\n *\n * @example\n * ```ts\n * import { createNylonPay } from \"@nile-squad/nylonpay-ts\";\n *\n * export const nylonpay = createNylonPay({\n * apiKey: \"npk_...\",\n * apiSecret: \"nps_...\",\n * });\n * ```\n */\n\nimport { createSdkInstance, type NylonPaySdk } from \"./sdk\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_MAX_POLL_ATTEMPTS,\n DEFAULT_MAX_POLL_DURATION_MS,\n DEFAULT_MAX_POLL_INTERVAL_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_TIMEOUT_MS,\n} from \"./sdk.config\";\nimport type { NylonPayConfig } from \"./types\";\n\nconst instances = new Map<string, NylonPaySdk>();\n\n/**\n * Create a Nylon Pay SDK instance.\n *\n * Returns the same instance for the same apiKey + baseUrl combination unless\n * { force: true } is passed. Use your test keys for sandbox, production keys\n * for live.\n *\n * @param config - SDK configuration with apiKey and apiSecret\n * @returns SDK instance with all payment operations\n *\n * @throws Error if required config is missing or invalid\n */\nexport function createNylonPay(config: NylonPayConfig): NylonPaySdk {\n if (!config.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n if (!config.apiKey.startsWith(\"npk_\")) {\n throw new Error('apiKey must start with \"npk_\"');\n }\n if (!config.apiSecret) {\n throw new Error(\"apiSecret is required\");\n }\n if (!config.apiSecret.startsWith(\"nps_\")) {\n throw new Error('apiSecret must start with \"nps_\"');\n }\n\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const instanceKey = `${config.apiKey}:${baseUrl}`;\n\n if (!config.force) {\n const existing = instances.get(instanceKey);\n if (existing) return existing;\n }\n\n const resolvedConfig = {\n apiKey: config.apiKey,\n apiSecret: config.apiSecret,\n baseUrl,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n maxPollIntervalMs: config.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS,\n maxPollDurationMs: config.maxPollDurationMs ?? DEFAULT_MAX_POLL_DURATION_MS,\n maxPollAttempts: config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS,\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n hooks: config.hooks,\n };\n\n const instance = createSdkInstance(resolvedConfig);\n instances.set(instanceKey, instance);\n return instance;\n}\n"]}
|