@p2pdotme/sdk 1.2.6 → 1.2.7

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/zkkyc.d.cts CHANGED
@@ -13,7 +13,7 @@ declare class SdkError<TCode extends string = string> extends Error {
13
13
  });
14
14
  }
15
15
 
16
- type ZkkycErrorCode = "VALIDATION_ERROR" | "CONTRACT_READ_ERROR" | "ENCODE_ERROR" | "RECLAIM_INIT_FAILED" | "RECLAIM_SESSION_NOT_FOUND" | "RECLAIM_PROOF_GENERATION_FAILED" | "RECLAIM_PROOF_INVALID" | "RECLAIM_POLLING_ABORTED" | "ZK_PASSPORT_INIT_FAILED" | "ZK_PASSPORT_REJECTED" | "ZK_PASSPORT_VERIFICATION_FAILED" | "ZK_PASSPORT_ABORTED" | "SIMPLE_KYC_SESSION_FAILED" | "SIMPLE_KYC_REDEEM_FAILED" | "PEER_DEPENDENCY_MISSING";
16
+ type ZkkycErrorCode = "VALIDATION_ERROR" | "CONTRACT_READ_ERROR" | "ENCODE_ERROR" | "RECLAIM_INIT_FAILED" | "RECLAIM_SESSION_NOT_FOUND" | "RECLAIM_PROOF_GENERATION_FAILED" | "RECLAIM_PROOF_INVALID" | "RECLAIM_POLLING_ABORTED" | "ZK_PASSPORT_INIT_FAILED" | "ZK_PASSPORT_REJECTED" | "ZK_PASSPORT_VERIFICATION_FAILED" | "ZK_PASSPORT_ABORTED" | "SIMPLE_KYC_SESSION_FAILED" | "SIMPLE_KYC_REDEEM_FAILED" | "BVN_ONBOARD_FAILED" | "BVN_SUBMIT_FAILED" | "BVN_OTP_SEND_FAILED" | "BVN_OTP_CONFIRM_FAILED" | "BVN_ATTESTATION_FAILED" | "BVN_SESSION_EXPIRED" | "PEER_DEPENDENCY_MISSING";
17
17
  declare class ZkkycError extends SdkError<ZkkycErrorCode> {
18
18
  constructor(message: string, options: {
19
19
  code: ZkkycErrorCode;
@@ -97,6 +97,13 @@ declare const ZodSimpleKycSubmitParamsSchema: z.ZodObject<{
97
97
  signature: z.ZodString;
98
98
  }, z.core.$strip>;
99
99
  type SimpleKycSubmitParams = z.infer<typeof ZodSimpleKycSubmitParamsSchema>;
100
+ declare const ZodBvnSubmitParamsSchema: z.ZodObject<{
101
+ nullifier: z.ZodString;
102
+ limit: z.ZodBigInt;
103
+ expiry: z.ZodBigInt;
104
+ signature: z.ZodString;
105
+ }, z.core.$strip>;
106
+ type BvnSubmitParams = z.infer<typeof ZodBvnSubmitParamsSchema>;
100
107
 
101
108
  interface Zkkyc {
102
109
  prepareSocialVerify(params: SocialVerifyParams): Result<{
@@ -115,6 +122,10 @@ interface Zkkyc {
115
122
  to: Address;
116
123
  data: `0x${string}`;
117
124
  }, ZkkycError>;
125
+ prepareSubmitBvnAttestation(params: BvnSubmitParams): Result<{
126
+ to: Address;
127
+ data: `0x${string}`;
128
+ }, ZkkycError>;
118
129
  }
119
130
  /**
120
131
  * Creates a Zkkyc client that binds a reputation manager address,
@@ -287,6 +298,75 @@ interface SimpleKycAttestation {
287
298
  /** The opaque unique-human handle (no PII), for app-side bookkeeping. */
288
299
  readonly identityHash?: string;
289
300
  }
301
+ /** OTP delivery channels the BVN backend exposes. `alternate_phone` needs a number. */
302
+ type BvnOtpMethod = "email" | "phone" | "phone_1" | "alternate_phone";
303
+ /** BVN identity scope requested during onboard. */
304
+ type BvnScope = "identity" | "bank_accounts";
305
+ /**
306
+ * Shared config for every BVN step. `baseUrl` points at the backend proxy — the
307
+ * only party holding the Mono secret + the EIP-712 attestor key — using the
308
+ * `{ ok, data }` envelope.
309
+ */
310
+ interface BvnFlowConfig {
311
+ /** Backend proxy base URL (e.g. https://ngn-bvn-verify-production.up.railway.app). */
312
+ readonly baseUrl: string;
313
+ /** Tenant slug registered on the backend, mapping to one on-chain contract. */
314
+ readonly tenant: string;
315
+ }
316
+ /** An active BVN backend session. Carry this between steps. */
317
+ interface BvnSession {
318
+ readonly sessionId: number;
319
+ readonly sessionToken: string;
320
+ }
321
+ /** An available OTP delivery method returned after submitting the BVN. */
322
+ interface BvnMethod {
323
+ readonly method: string;
324
+ readonly hint?: string;
325
+ }
326
+ /** The confirm-OTP decision. `reject` may carry a reason (e.g. "bvn_reused"). */
327
+ interface BvnDecision {
328
+ readonly decision: "approve" | "reject";
329
+ readonly reason?: string;
330
+ }
331
+ /** The on-chain-ready attestation, shaped for `prepareSubmitBvnAttestation`. */
332
+ interface BvnAttestation {
333
+ readonly nullifier: `0x${string}`;
334
+ readonly limit: bigint;
335
+ readonly expiry: bigint;
336
+ readonly signature: `0x${string}`;
337
+ /** The wallet the attestation is bound to. */
338
+ readonly wallet?: string;
339
+ }
340
+ /** Params for `bvnOnboard`. */
341
+ interface BvnOnboardParams {
342
+ /** The user's EVM wallet — bound into the attestation and credited on-chain. */
343
+ readonly walletAddress: Address;
344
+ /** Identity scope. Defaults to "identity". */
345
+ readonly scope?: BvnScope;
346
+ }
347
+ /** Params for `bvnSendOtp`. */
348
+ interface BvnSendOtpParams {
349
+ readonly method: BvnOtpMethod;
350
+ /** Required only when `method` is "alternate_phone". */
351
+ readonly phoneNumber?: string;
352
+ }
353
+ /** The full BVN flow bound to a config — mirrors the `Zkkyc` client shape. */
354
+ interface BvnFlow {
355
+ /** Step 1 — start a session bound to the wallet + tenant. */
356
+ onboard(params: BvnOnboardParams): ResultAsync<BvnSession, ZkkycError>;
357
+ /** Step 2 — submit the 11-digit BVN, get available OTP methods. */
358
+ submitBvn(session: BvnSession, bvn: string): ResultAsync<BvnMethod[], ZkkycError>;
359
+ /** Step 3 — request an OTP over the chosen channel. */
360
+ sendOtp(session: BvnSession, params: BvnSendOtpParams): ResultAsync<boolean, ZkkycError>;
361
+ /** Step 4 — confirm the OTP; returns approve/reject (never any PII). */
362
+ confirmOtp(session: BvnSession, otp: string): ResultAsync<BvnDecision, ZkkycError>;
363
+ /** Step 5 — mint the signed EIP-712 attestation for an approved session. */
364
+ getAttestation(session: BvnSession): ResultAsync<BvnAttestation, ZkkycError>;
365
+ /** Optional — the address the tenant contract must trust as its signer. */
366
+ getAttestor(): ResultAsync<{
367
+ address: string;
368
+ }, ZkkycError>;
369
+ }
290
370
 
291
371
  /** Default Reclaim provider IDs for each social platform. */
292
372
  declare const DEFAULT_RECLAIM_PROVIDER_IDS: Record<SocialPlatform, string>;
@@ -301,6 +381,21 @@ declare const RECLAIM_APP_LINKS: {
301
381
  };
302
382
  /** Default tenant slug for the P2P reputation contract on the simple-kyc service. */
303
383
  declare const SIMPLE_KYC_DEFAULT_TENANT = "p2p-reputation";
384
+ /** OTP delivery channels the BVN backend (Mono) exposes. */
385
+ declare const BVN_OTP_METHODS: readonly ["email", "phone", "phone_1", "alternate_phone"];
386
+
387
+ /**
388
+ * Drives the BVN (Nigerian Bank Verification Number) on-chain attestation flow.
389
+ *
390
+ * The SDK talks only to a backend proxy — the single party that holds the Mono
391
+ * secret + the EIP-712 attestor key. Every response uses the `{ ok, data }`
392
+ * envelope. On approval, `getAttestation` returns a signed attestation shaped
393
+ * for `zkkyc.prepareSubmitBvnAttestation`, which the app submits on-chain from
394
+ * the same wallet.
395
+ *
396
+ * Flow: onboard → submitBvn → sendOtp → confirmOtp → getAttestation.
397
+ */
398
+ declare function createBvnFlow(config: BvnFlowConfig): BvnFlow;
304
399
 
305
400
  /**
306
401
  * Initializes a Reclaim social verification flow and returns a session. `init()`
@@ -333,4 +428,4 @@ declare function resumeSimpleKycFlow(args: {
333
428
  /** Initializes a ZK Passport verification flow and returns a session. */
334
429
  declare function createZkPassportFlow(params: ZkPassportFlowParams): ResultAsync<ZkPassportSession, ZkkycError>;
335
430
 
336
- export { type AnonAadharProofParams, DEFAULT_RECLAIM_PROVIDER_IDS, RECLAIM_APP_LINKS, type ReclaimFlowParams, type ReclaimProofResult, type ReclaimSession, type ReclaimStatus, SIMPLE_KYC_DEFAULT_TENANT, SOCIAL_PLATFORM_NAMES, type SimpleKycAttestation, type SimpleKycFlowParams, type SimpleKycSession, type SimpleKycStatus, type SimpleKycSubmitParams, type SocialPlatform, type SocialVerifyParams, ZK_PASSPORT_APP_LINKS, type ZkPassportFlowParams, type ZkPassportProofResult, type ZkPassportRegisterParams, type ZkPassportSession, type ZkPassportStatus, type Zkkyc, type ZkkycConfig, ZkkycError, type ZkkycErrorCode, createReclaimFlow, createSimpleKycFlow, createZkPassportFlow, createZkkyc, resumeSimpleKycFlow };
431
+ export { type AnonAadharProofParams, BVN_OTP_METHODS, type BvnAttestation, type BvnDecision, type BvnFlow, type BvnFlowConfig, type BvnMethod, type BvnOnboardParams, type BvnOtpMethod, type BvnScope, type BvnSendOtpParams, type BvnSession, type BvnSubmitParams, DEFAULT_RECLAIM_PROVIDER_IDS, RECLAIM_APP_LINKS, type ReclaimFlowParams, type ReclaimProofResult, type ReclaimSession, type ReclaimStatus, SIMPLE_KYC_DEFAULT_TENANT, SOCIAL_PLATFORM_NAMES, type SimpleKycAttestation, type SimpleKycFlowParams, type SimpleKycSession, type SimpleKycStatus, type SimpleKycSubmitParams, type SocialPlatform, type SocialVerifyParams, ZK_PASSPORT_APP_LINKS, type ZkPassportFlowParams, type ZkPassportProofResult, type ZkPassportRegisterParams, type ZkPassportSession, type ZkPassportStatus, type Zkkyc, type ZkkycConfig, ZkkycError, type ZkkycErrorCode, createBvnFlow, createReclaimFlow, createSimpleKycFlow, createZkPassportFlow, createZkkyc, resumeSimpleKycFlow };
package/dist/zkkyc.d.ts CHANGED
@@ -13,7 +13,7 @@ declare class SdkError<TCode extends string = string> extends Error {
13
13
  });
14
14
  }
15
15
 
16
- type ZkkycErrorCode = "VALIDATION_ERROR" | "CONTRACT_READ_ERROR" | "ENCODE_ERROR" | "RECLAIM_INIT_FAILED" | "RECLAIM_SESSION_NOT_FOUND" | "RECLAIM_PROOF_GENERATION_FAILED" | "RECLAIM_PROOF_INVALID" | "RECLAIM_POLLING_ABORTED" | "ZK_PASSPORT_INIT_FAILED" | "ZK_PASSPORT_REJECTED" | "ZK_PASSPORT_VERIFICATION_FAILED" | "ZK_PASSPORT_ABORTED" | "SIMPLE_KYC_SESSION_FAILED" | "SIMPLE_KYC_REDEEM_FAILED" | "PEER_DEPENDENCY_MISSING";
16
+ type ZkkycErrorCode = "VALIDATION_ERROR" | "CONTRACT_READ_ERROR" | "ENCODE_ERROR" | "RECLAIM_INIT_FAILED" | "RECLAIM_SESSION_NOT_FOUND" | "RECLAIM_PROOF_GENERATION_FAILED" | "RECLAIM_PROOF_INVALID" | "RECLAIM_POLLING_ABORTED" | "ZK_PASSPORT_INIT_FAILED" | "ZK_PASSPORT_REJECTED" | "ZK_PASSPORT_VERIFICATION_FAILED" | "ZK_PASSPORT_ABORTED" | "SIMPLE_KYC_SESSION_FAILED" | "SIMPLE_KYC_REDEEM_FAILED" | "BVN_ONBOARD_FAILED" | "BVN_SUBMIT_FAILED" | "BVN_OTP_SEND_FAILED" | "BVN_OTP_CONFIRM_FAILED" | "BVN_ATTESTATION_FAILED" | "BVN_SESSION_EXPIRED" | "PEER_DEPENDENCY_MISSING";
17
17
  declare class ZkkycError extends SdkError<ZkkycErrorCode> {
18
18
  constructor(message: string, options: {
19
19
  code: ZkkycErrorCode;
@@ -97,6 +97,13 @@ declare const ZodSimpleKycSubmitParamsSchema: z.ZodObject<{
97
97
  signature: z.ZodString;
98
98
  }, z.core.$strip>;
99
99
  type SimpleKycSubmitParams = z.infer<typeof ZodSimpleKycSubmitParamsSchema>;
100
+ declare const ZodBvnSubmitParamsSchema: z.ZodObject<{
101
+ nullifier: z.ZodString;
102
+ limit: z.ZodBigInt;
103
+ expiry: z.ZodBigInt;
104
+ signature: z.ZodString;
105
+ }, z.core.$strip>;
106
+ type BvnSubmitParams = z.infer<typeof ZodBvnSubmitParamsSchema>;
100
107
 
101
108
  interface Zkkyc {
102
109
  prepareSocialVerify(params: SocialVerifyParams): Result<{
@@ -115,6 +122,10 @@ interface Zkkyc {
115
122
  to: Address;
116
123
  data: `0x${string}`;
117
124
  }, ZkkycError>;
125
+ prepareSubmitBvnAttestation(params: BvnSubmitParams): Result<{
126
+ to: Address;
127
+ data: `0x${string}`;
128
+ }, ZkkycError>;
118
129
  }
119
130
  /**
120
131
  * Creates a Zkkyc client that binds a reputation manager address,
@@ -287,6 +298,75 @@ interface SimpleKycAttestation {
287
298
  /** The opaque unique-human handle (no PII), for app-side bookkeeping. */
288
299
  readonly identityHash?: string;
289
300
  }
301
+ /** OTP delivery channels the BVN backend exposes. `alternate_phone` needs a number. */
302
+ type BvnOtpMethod = "email" | "phone" | "phone_1" | "alternate_phone";
303
+ /** BVN identity scope requested during onboard. */
304
+ type BvnScope = "identity" | "bank_accounts";
305
+ /**
306
+ * Shared config for every BVN step. `baseUrl` points at the backend proxy — the
307
+ * only party holding the Mono secret + the EIP-712 attestor key — using the
308
+ * `{ ok, data }` envelope.
309
+ */
310
+ interface BvnFlowConfig {
311
+ /** Backend proxy base URL (e.g. https://ngn-bvn-verify-production.up.railway.app). */
312
+ readonly baseUrl: string;
313
+ /** Tenant slug registered on the backend, mapping to one on-chain contract. */
314
+ readonly tenant: string;
315
+ }
316
+ /** An active BVN backend session. Carry this between steps. */
317
+ interface BvnSession {
318
+ readonly sessionId: number;
319
+ readonly sessionToken: string;
320
+ }
321
+ /** An available OTP delivery method returned after submitting the BVN. */
322
+ interface BvnMethod {
323
+ readonly method: string;
324
+ readonly hint?: string;
325
+ }
326
+ /** The confirm-OTP decision. `reject` may carry a reason (e.g. "bvn_reused"). */
327
+ interface BvnDecision {
328
+ readonly decision: "approve" | "reject";
329
+ readonly reason?: string;
330
+ }
331
+ /** The on-chain-ready attestation, shaped for `prepareSubmitBvnAttestation`. */
332
+ interface BvnAttestation {
333
+ readonly nullifier: `0x${string}`;
334
+ readonly limit: bigint;
335
+ readonly expiry: bigint;
336
+ readonly signature: `0x${string}`;
337
+ /** The wallet the attestation is bound to. */
338
+ readonly wallet?: string;
339
+ }
340
+ /** Params for `bvnOnboard`. */
341
+ interface BvnOnboardParams {
342
+ /** The user's EVM wallet — bound into the attestation and credited on-chain. */
343
+ readonly walletAddress: Address;
344
+ /** Identity scope. Defaults to "identity". */
345
+ readonly scope?: BvnScope;
346
+ }
347
+ /** Params for `bvnSendOtp`. */
348
+ interface BvnSendOtpParams {
349
+ readonly method: BvnOtpMethod;
350
+ /** Required only when `method` is "alternate_phone". */
351
+ readonly phoneNumber?: string;
352
+ }
353
+ /** The full BVN flow bound to a config — mirrors the `Zkkyc` client shape. */
354
+ interface BvnFlow {
355
+ /** Step 1 — start a session bound to the wallet + tenant. */
356
+ onboard(params: BvnOnboardParams): ResultAsync<BvnSession, ZkkycError>;
357
+ /** Step 2 — submit the 11-digit BVN, get available OTP methods. */
358
+ submitBvn(session: BvnSession, bvn: string): ResultAsync<BvnMethod[], ZkkycError>;
359
+ /** Step 3 — request an OTP over the chosen channel. */
360
+ sendOtp(session: BvnSession, params: BvnSendOtpParams): ResultAsync<boolean, ZkkycError>;
361
+ /** Step 4 — confirm the OTP; returns approve/reject (never any PII). */
362
+ confirmOtp(session: BvnSession, otp: string): ResultAsync<BvnDecision, ZkkycError>;
363
+ /** Step 5 — mint the signed EIP-712 attestation for an approved session. */
364
+ getAttestation(session: BvnSession): ResultAsync<BvnAttestation, ZkkycError>;
365
+ /** Optional — the address the tenant contract must trust as its signer. */
366
+ getAttestor(): ResultAsync<{
367
+ address: string;
368
+ }, ZkkycError>;
369
+ }
290
370
 
291
371
  /** Default Reclaim provider IDs for each social platform. */
292
372
  declare const DEFAULT_RECLAIM_PROVIDER_IDS: Record<SocialPlatform, string>;
@@ -301,6 +381,21 @@ declare const RECLAIM_APP_LINKS: {
301
381
  };
302
382
  /** Default tenant slug for the P2P reputation contract on the simple-kyc service. */
303
383
  declare const SIMPLE_KYC_DEFAULT_TENANT = "p2p-reputation";
384
+ /** OTP delivery channels the BVN backend (Mono) exposes. */
385
+ declare const BVN_OTP_METHODS: readonly ["email", "phone", "phone_1", "alternate_phone"];
386
+
387
+ /**
388
+ * Drives the BVN (Nigerian Bank Verification Number) on-chain attestation flow.
389
+ *
390
+ * The SDK talks only to a backend proxy — the single party that holds the Mono
391
+ * secret + the EIP-712 attestor key. Every response uses the `{ ok, data }`
392
+ * envelope. On approval, `getAttestation` returns a signed attestation shaped
393
+ * for `zkkyc.prepareSubmitBvnAttestation`, which the app submits on-chain from
394
+ * the same wallet.
395
+ *
396
+ * Flow: onboard → submitBvn → sendOtp → confirmOtp → getAttestation.
397
+ */
398
+ declare function createBvnFlow(config: BvnFlowConfig): BvnFlow;
304
399
 
305
400
  /**
306
401
  * Initializes a Reclaim social verification flow and returns a session. `init()`
@@ -333,4 +428,4 @@ declare function resumeSimpleKycFlow(args: {
333
428
  /** Initializes a ZK Passport verification flow and returns a session. */
334
429
  declare function createZkPassportFlow(params: ZkPassportFlowParams): ResultAsync<ZkPassportSession, ZkkycError>;
335
430
 
336
- export { type AnonAadharProofParams, DEFAULT_RECLAIM_PROVIDER_IDS, RECLAIM_APP_LINKS, type ReclaimFlowParams, type ReclaimProofResult, type ReclaimSession, type ReclaimStatus, SIMPLE_KYC_DEFAULT_TENANT, SOCIAL_PLATFORM_NAMES, type SimpleKycAttestation, type SimpleKycFlowParams, type SimpleKycSession, type SimpleKycStatus, type SimpleKycSubmitParams, type SocialPlatform, type SocialVerifyParams, ZK_PASSPORT_APP_LINKS, type ZkPassportFlowParams, type ZkPassportProofResult, type ZkPassportRegisterParams, type ZkPassportSession, type ZkPassportStatus, type Zkkyc, type ZkkycConfig, ZkkycError, type ZkkycErrorCode, createReclaimFlow, createSimpleKycFlow, createZkPassportFlow, createZkkyc, resumeSimpleKycFlow };
431
+ export { type AnonAadharProofParams, BVN_OTP_METHODS, type BvnAttestation, type BvnDecision, type BvnFlow, type BvnFlowConfig, type BvnMethod, type BvnOnboardParams, type BvnOtpMethod, type BvnScope, type BvnSendOtpParams, type BvnSession, type BvnSubmitParams, DEFAULT_RECLAIM_PROVIDER_IDS, RECLAIM_APP_LINKS, type ReclaimFlowParams, type ReclaimProofResult, type ReclaimSession, type ReclaimStatus, SIMPLE_KYC_DEFAULT_TENANT, SOCIAL_PLATFORM_NAMES, type SimpleKycAttestation, type SimpleKycFlowParams, type SimpleKycSession, type SimpleKycStatus, type SimpleKycSubmitParams, type SocialPlatform, type SocialVerifyParams, ZK_PASSPORT_APP_LINKS, type ZkPassportFlowParams, type ZkPassportProofResult, type ZkPassportRegisterParams, type ZkPassportSession, type ZkPassportStatus, type Zkkyc, type ZkkycConfig, ZkkycError, type ZkkycErrorCode, createBvnFlow, createReclaimFlow, createSimpleKycFlow, createZkPassportFlow, createZkkyc, resumeSimpleKycFlow };
package/dist/zkkyc.mjs CHANGED
@@ -142,6 +142,20 @@ var ZodSimpleKycSubmitParamsSchema = z2.object({
142
142
  message: "signature must be a hex string"
143
143
  })
144
144
  });
145
+ var ZodBvnSubmitParamsSchema = z2.object({
146
+ /** Per-(tenant, identity) Sybil nullifier (bytes32 hex). */
147
+ nullifier: z2.string().refine((v) => /^0x[a-fA-F0-9]{64}$/.test(v), {
148
+ message: "nullifier must be a bytes32 hex string"
149
+ }),
150
+ /** Remaining limit in micro-USDC (part of the signed struct). */
151
+ limit: z2.bigint(),
152
+ /** Attestation expiry (unix seconds). */
153
+ expiry: z2.bigint(),
154
+ /** 65-byte secp256k1 signature (hex). */
155
+ signature: z2.string().refine((v) => /^0x[a-fA-F0-9]+$/.test(v), {
156
+ message: "signature must be a hex string"
157
+ })
158
+ });
145
159
 
146
160
  // src/contracts/abis/index.ts
147
161
  import { erc20Abi } from "viem";
@@ -946,6 +960,38 @@ var reputationManagerAbi = [
946
960
  outputs: [{ internalType: "bool", name: "", type: "bool" }],
947
961
  stateMutability: "view",
948
962
  type: "function"
963
+ },
964
+ // ── BVN (Nigerian Bank Verification Number) attestation ─────────────────
965
+ { inputs: [], name: "BvnSignerNotSet", type: "error" },
966
+ { inputs: [], name: "BvnAttestationExpired", type: "error" },
967
+ { inputs: [], name: "BvnNullifierAlreadySpent", type: "error" },
968
+ { inputs: [], name: "BvnAlreadyVerified", type: "error" },
969
+ { inputs: [], name: "BvnInvalidSignature", type: "error" },
970
+ {
971
+ inputs: [
972
+ { internalType: "bytes32", name: "nullifier", type: "bytes32" },
973
+ { internalType: "uint256", name: "limit", type: "uint256" },
974
+ { internalType: "uint256", name: "expiry", type: "uint256" },
975
+ { internalType: "bytes", name: "signature", type: "bytes" }
976
+ ],
977
+ name: "submitBvnAttestation",
978
+ outputs: [],
979
+ stateMutability: "nonpayable",
980
+ type: "function"
981
+ },
982
+ {
983
+ inputs: [],
984
+ name: "bvnRp",
985
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
986
+ stateMutability: "view",
987
+ type: "function"
988
+ },
989
+ {
990
+ inputs: [{ internalType: "address", name: "", type: "address" }],
991
+ name: "bvnVerified",
992
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
993
+ stateMutability: "view",
994
+ type: "function"
949
995
  }
950
996
  ];
951
997
 
@@ -1062,6 +1108,33 @@ function prepareSubmitKycAttestation(reputationManagerAddress, params) {
1062
1108
  )()
1063
1109
  );
1064
1110
  }
1111
+ function prepareSubmitBvnAttestation(reputationManagerAddress, params) {
1112
+ return validate(
1113
+ ZodBvnSubmitParamsSchema,
1114
+ params,
1115
+ (message, cause, data) => new ZkkycError(message, { code: "VALIDATION_ERROR", cause, context: { params: data } })
1116
+ ).andThen(
1117
+ (validated) => Result.fromThrowable(
1118
+ () => ({
1119
+ to: reputationManagerAddress,
1120
+ data: encodeFunctionData({
1121
+ abi: ABIS.EXTERNAL.REPUTATION_MANAGER,
1122
+ functionName: "submitBvnAttestation",
1123
+ args: [
1124
+ validated.nullifier,
1125
+ validated.limit,
1126
+ validated.expiry,
1127
+ validated.signature
1128
+ ]
1129
+ })
1130
+ }),
1131
+ (error) => new ZkkycError("Failed to encode submitBvnAttestation", {
1132
+ code: "ENCODE_ERROR",
1133
+ cause: error
1134
+ })
1135
+ )()
1136
+ );
1137
+ }
1065
1138
  function prepareZkPassportRegister(reputationManagerAddress, params) {
1066
1139
  return validate(
1067
1140
  ZodZkPassportRegisterParamsSchema,
@@ -1110,7 +1183,8 @@ function createZkkyc(config) {
1110
1183
  prepareSocialVerify: (params) => prepareSocialVerify(reputationManagerAddress, params),
1111
1184
  prepareSubmitAnonAadharProof: (params) => prepareSubmitAnonAadharProof(reputationManagerAddress, params),
1112
1185
  prepareZkPassportRegister: (params) => prepareZkPassportRegister(reputationManagerAddress, params),
1113
- prepareSubmitKycAttestation: (params) => prepareSubmitKycAttestation(reputationManagerAddress, params)
1186
+ prepareSubmitKycAttestation: (params) => prepareSubmitKycAttestation(reputationManagerAddress, params),
1187
+ prepareSubmitBvnAttestation: (params) => prepareSubmitBvnAttestation(reputationManagerAddress, params)
1114
1188
  };
1115
1189
  }
1116
1190
 
@@ -1131,9 +1205,149 @@ var RECLAIM_APP_LINKS = {
1131
1205
  ANDROID: "https://play.google.com/store/apps/details?id=org.reclaimprotocol.app"
1132
1206
  };
1133
1207
  var SIMPLE_KYC_DEFAULT_TENANT = "p2p-reputation";
1208
+ var BVN_OTP_METHODS = ["email", "phone", "phone_1", "alternate_phone"];
1134
1209
 
1135
- // src/zkkyc/orchestrators/reclaim.ts
1210
+ // src/zkkyc/orchestrators/bvn.ts
1136
1211
  import { ResultAsync } from "neverthrow";
1212
+ function createBvnFlow(config) {
1213
+ const { baseUrl, tenant } = config;
1214
+ async function request(path, failureCode, init, parse) {
1215
+ const response = await fetch(`${baseUrl}${path}`, init);
1216
+ const body = await response.json().catch(() => null);
1217
+ const envelope = body && typeof body === "object" ? body : {};
1218
+ if (!response.ok || envelope.ok === false) {
1219
+ const code = typeof envelope.error === "string" ? envelope.error : "request_failed";
1220
+ const message = typeof envelope.message === "string" ? envelope.message : `BVN request failed (${response.status})`;
1221
+ const isSessionExpired = response.status === 401 || code === "unauthorized";
1222
+ throw new ZkkycError(message, {
1223
+ code: isSessionExpired ? "BVN_SESSION_EXPIRED" : failureCode,
1224
+ context: { status: response.status, backendError: code, path }
1225
+ });
1226
+ }
1227
+ return parse(envelope.data);
1228
+ }
1229
+ function run(failureCode, fn) {
1230
+ return ResultAsync.fromPromise(fn(), (error) => {
1231
+ if (error instanceof ZkkycError) return error;
1232
+ return new ZkkycError("BVN request failed", { code: failureCode, cause: error });
1233
+ });
1234
+ }
1235
+ function authHeaders(token) {
1236
+ return { "content-type": "application/json", "x-session-token": token };
1237
+ }
1238
+ return {
1239
+ onboard(params) {
1240
+ return run(
1241
+ "BVN_ONBOARD_FAILED",
1242
+ () => request(
1243
+ "/v1/onboard",
1244
+ "BVN_ONBOARD_FAILED",
1245
+ {
1246
+ method: "POST",
1247
+ headers: { "content-type": "application/json" },
1248
+ body: JSON.stringify({
1249
+ tenant,
1250
+ wallet: params.walletAddress,
1251
+ scope: params.scope ?? "identity"
1252
+ })
1253
+ },
1254
+ (data) => {
1255
+ const d = data;
1256
+ return { sessionId: d.session_id, sessionToken: d.session_token };
1257
+ }
1258
+ )
1259
+ );
1260
+ },
1261
+ submitBvn(session, bvn) {
1262
+ return run(
1263
+ "BVN_SUBMIT_FAILED",
1264
+ () => request(
1265
+ `/v1/sessions/${session.sessionId}/bvn`,
1266
+ "BVN_SUBMIT_FAILED",
1267
+ {
1268
+ method: "POST",
1269
+ headers: authHeaders(session.sessionToken),
1270
+ body: JSON.stringify({ bvn })
1271
+ },
1272
+ (data) => data.methods
1273
+ )
1274
+ );
1275
+ },
1276
+ sendOtp(session, params) {
1277
+ return run(
1278
+ "BVN_OTP_SEND_FAILED",
1279
+ () => request(
1280
+ `/v1/sessions/${session.sessionId}/otp`,
1281
+ "BVN_OTP_SEND_FAILED",
1282
+ {
1283
+ method: "POST",
1284
+ headers: authHeaders(session.sessionToken),
1285
+ body: JSON.stringify({
1286
+ method: params.method,
1287
+ ...params.method === "alternate_phone" && params.phoneNumber ? { phone_number: params.phoneNumber } : {}
1288
+ })
1289
+ },
1290
+ (data) => data.sent
1291
+ )
1292
+ );
1293
+ },
1294
+ confirmOtp(session, otp) {
1295
+ return run(
1296
+ "BVN_OTP_CONFIRM_FAILED",
1297
+ () => request(
1298
+ `/v1/sessions/${session.sessionId}/otp/confirm`,
1299
+ "BVN_OTP_CONFIRM_FAILED",
1300
+ {
1301
+ method: "POST",
1302
+ headers: authHeaders(session.sessionToken),
1303
+ body: JSON.stringify({ otp })
1304
+ },
1305
+ (data) => {
1306
+ const d = data;
1307
+ return { decision: d.decision, reason: d.reason };
1308
+ }
1309
+ )
1310
+ );
1311
+ },
1312
+ getAttestation(session) {
1313
+ return run(
1314
+ "BVN_ATTESTATION_FAILED",
1315
+ () => request(
1316
+ `/v1/sessions/${session.sessionId}/attestation`,
1317
+ "BVN_ATTESTATION_FAILED",
1318
+ {
1319
+ method: "POST",
1320
+ headers: { "x-session-token": session.sessionToken }
1321
+ },
1322
+ (data) => {
1323
+ const d = data;
1324
+ return {
1325
+ nullifier: d.message.nullifier,
1326
+ limit: BigInt(d.message.limit),
1327
+ expiry: BigInt(d.message.expiry),
1328
+ signature: d.signature,
1329
+ wallet: d.message.wallet
1330
+ };
1331
+ }
1332
+ )
1333
+ );
1334
+ },
1335
+ getAttestor() {
1336
+ return run(
1337
+ "BVN_ATTESTATION_FAILED",
1338
+ () => request(
1339
+ "/v1/attestor",
1340
+ "BVN_ATTESTATION_FAILED",
1341
+ void 0,
1342
+ (data) => data
1343
+ )
1344
+ );
1345
+ }
1346
+ };
1347
+ }
1348
+
1349
+ // src/zkkyc/orchestrators/reclaim.ts
1350
+ import { ResultAsync as ResultAsync2 } from "neverthrow";
1137
1351
 
1138
1352
  // src/zkkyc/orchestrators/types.ts
1139
1353
  var SOCIAL_PLATFORM_NAMES = {
@@ -1148,7 +1362,7 @@ var SOCIAL_PLATFORM_NAMES = {
1148
1362
  // src/zkkyc/orchestrators/reclaim.ts
1149
1363
  var RECLAIM_SESSION_API = "https://api.reclaimprotocol.org/api/sdk/session";
1150
1364
  function createReclaimFlow(params) {
1151
- return ResultAsync.fromPromise(
1365
+ return ResultAsync2.fromPromise(
1152
1366
  (async () => {
1153
1367
  const mod = await import("@reclaimprotocol/js-sdk").catch(() => {
1154
1368
  throw new ZkkycError(
@@ -1252,7 +1466,7 @@ function createReclaimFlow(params) {
1252
1466
  const session = {
1253
1467
  sessionId,
1254
1468
  requestUrl,
1255
- start: () => ResultAsync.fromPromise(pollForProof(), (error) => {
1469
+ start: () => ResultAsync2.fromPromise(pollForProof(), (error) => {
1256
1470
  if (error instanceof ZkkycError) return error;
1257
1471
  return new ZkkycError("Reclaim verification flow failed", {
1258
1472
  code: "RECLAIM_INIT_FAILED",
@@ -1276,10 +1490,10 @@ function createReclaimFlow(params) {
1276
1490
  }
1277
1491
 
1278
1492
  // src/zkkyc/orchestrators/simple-kyc.ts
1279
- import { ResultAsync as ResultAsync2 } from "neverthrow";
1493
+ import { ResultAsync as ResultAsync3 } from "neverthrow";
1280
1494
  function createSimpleKycFlow(params) {
1281
1495
  const { baseUrl, walletAddress, tenant, redirectUrl, country, state, onStatus } = params;
1282
- return ResultAsync2.fromPromise(
1496
+ return ResultAsync3.fromPromise(
1283
1497
  (async () => {
1284
1498
  const res = await fetch(`${baseUrl}/v1/widget/public-sessions`, {
1285
1499
  method: "POST",
@@ -1322,7 +1536,7 @@ function createSimpleKycFlow(params) {
1322
1536
  );
1323
1537
  }
1324
1538
  function resumeSimpleKycFlow(args) {
1325
- return ResultAsync2.fromPromise(
1539
+ return ResultAsync3.fromPromise(
1326
1540
  (async () => {
1327
1541
  const res = await fetch(`${args.baseUrl}/v1/widget/attestation`, {
1328
1542
  method: "POST",
@@ -1356,9 +1570,9 @@ function resumeSimpleKycFlow(args) {
1356
1570
  }
1357
1571
 
1358
1572
  // src/zkkyc/orchestrators/zk-passport.ts
1359
- import { ResultAsync as ResultAsync3 } from "neverthrow";
1573
+ import { ResultAsync as ResultAsync4 } from "neverthrow";
1360
1574
  function createZkPassportFlow(params) {
1361
- return ResultAsync3.fromPromise(
1575
+ return ResultAsync4.fromPromise(
1362
1576
  (async () => {
1363
1577
  const mod = await import("@zkpassport/sdk").catch(() => {
1364
1578
  throw new ZkkycError(
@@ -1454,7 +1668,7 @@ function createZkPassportFlow(params) {
1454
1668
  });
1455
1669
  const session = {
1456
1670
  url,
1457
- result: ResultAsync3.fromPromise(resultPromise, (error) => {
1671
+ result: ResultAsync4.fromPromise(resultPromise, (error) => {
1458
1672
  if (error instanceof ZkkycError) return error;
1459
1673
  return new ZkkycError("ZK Passport flow failed", {
1460
1674
  code: "ZK_PASSPORT_VERIFICATION_FAILED",
@@ -1477,12 +1691,14 @@ function createZkPassportFlow(params) {
1477
1691
  );
1478
1692
  }
1479
1693
  export {
1694
+ BVN_OTP_METHODS,
1480
1695
  DEFAULT_RECLAIM_PROVIDER_IDS,
1481
1696
  RECLAIM_APP_LINKS,
1482
1697
  SIMPLE_KYC_DEFAULT_TENANT,
1483
1698
  SOCIAL_PLATFORM_NAMES,
1484
1699
  ZK_PASSPORT_APP_LINKS,
1485
1700
  ZkkycError,
1701
+ createBvnFlow,
1486
1702
  createReclaimFlow,
1487
1703
  createSimpleKycFlow,
1488
1704
  createZkPassportFlow,