signet.js 0.2.0 → 0.3.1-beta.1

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 CHANGED
@@ -177,7 +177,7 @@ const EPSILON_DERIVATION_PREFIX_V2 = "sig.network v2.0.0 epsilon derivation";
177
177
  * @param keyVersion - Key version controlling which derivation prefix to use (legacy v1 for 0, CAIP-2 v2 otherwise)
178
178
  * @returns The derived child public key in uncompressed SEC1 format (04 || x || y)
179
179
  */
180
- function deriveChildPublicKey(rootUncompressedPubKeySEC1, predecessorId, path = "", chainId, keyVersion) {
180
+ function deriveChildPublicKey(rootUncompressedPubKeySEC1, predecessorId, path = "", chainId, _keyVersion) {
181
181
  const ec = new EC("secp256k1");
182
182
  const derivationPath = `${EPSILON_DERIVATION_PREFIX_V2}:${chainId}:${predecessorId}:${path}`;
183
183
  let scalarHex = "";
@@ -262,7 +262,7 @@ var EVM = class extends ChainAdapter {
262
262
  async attachGasAndNonce(transaction) {
263
263
  const fees = await fetchEVMFeeProperties(this.client, transaction);
264
264
  const nonce = await this.client.getTransactionCount({ address: transaction.from });
265
- const { from, ...rest } = transaction;
265
+ const { from: _from, ...rest } = transaction;
266
266
  return {
267
267
  ...fees,
268
268
  nonce,
@@ -1391,7 +1391,39 @@ const getRootPublicKey = (contractAddress, chain) => {
1391
1391
 
1392
1392
  //#endregion
1393
1393
  //#region src/contracts/evm/utils.ts
1394
- const getRequestId = (request) => {
1394
+ /**
1395
+ * Generates a unique request ID for EVM signature requests using keccak256 hashing.
1396
+ *
1397
+ * The request ID is computed by ABI-encoding the request parameters and hashing
1398
+ * the result. This ID is used to track signature requests and match them with
1399
+ * responses from the MPC network.
1400
+ *
1401
+ * @param request - The signature request parameters
1402
+ * @param request.address - The address of the requester (EVM address format)
1403
+ * @param request.payload - The data payload to be signed as a hex string
1404
+ * @param request.path - The derivation path for the signing key
1405
+ * @param request.keyVersion - The version of the signing key
1406
+ * @param request.chainId - The chain ID where the request originated
1407
+ * @param request.algo - The signing algorithm identifier
1408
+ * @param request.dest - The destination identifier for the signature
1409
+ * @param request.params - Additional parameters for the signing process
1410
+ * @returns The keccak256 hash of the encoded request as a hex string
1411
+ *
1412
+ * @example
1413
+ * ```typescript
1414
+ * const requestId = getRequestIdRespond({
1415
+ * address: '0x1234...abcd',
1416
+ * payload: '0xdeadbeef',
1417
+ * path: 'ethereum,1',
1418
+ * keyVersion: 0,
1419
+ * chainId: 1n,
1420
+ * algo: '',
1421
+ * dest: '',
1422
+ * params: '',
1423
+ * })
1424
+ * ```
1425
+ */
1426
+ const getRequestIdRespond$1 = (request) => {
1395
1427
  return (0, viem.keccak256)((0, viem.encodeAbiParameters)([
1396
1428
  { type: "address" },
1397
1429
  { type: "bytes" },
@@ -1598,7 +1630,7 @@ var ChainSignatureContract$2 = class extends ChainSignatureContract {
1598
1630
  }) {
1599
1631
  if (!this.walletClient.account) throw new Error("Wallet client account required to compute requestId");
1600
1632
  if (!this.publicClient.chain?.id) throw new Error("Public client chain required to compute requestId");
1601
- return getRequestId({
1633
+ return getRequestIdRespond$1({
1602
1634
  payload: `0x${Buffer.from(args.payload).toString("hex")}`,
1603
1635
  path: args.path,
1604
1636
  keyVersion: args.key_version,
@@ -1652,6 +1684,7 @@ var ChainSignatureContract$2 = class extends ChainSignatureContract {
1652
1684
  //#region src/contracts/evm/index.ts
1653
1685
  var evm_exports = /* @__PURE__ */ __export({
1654
1686
  ChainSignatureContract: () => ChainSignatureContract$2,
1687
+ getRequestIdRespond: () => getRequestIdRespond$1,
1655
1688
  utils: () => utils$1
1656
1689
  });
1657
1690
  const utils$1 = {
@@ -2695,24 +2728,33 @@ const EMIT_CPI_INSTRUCTION_DISCRIMINATOR = Buffer.from([
2695
2728
  ]);
2696
2729
  var CpiEventParser = class {
2697
2730
  /**
2698
- * Parse CPI events from a transaction (emit_cpi! pattern)
2731
+ * Parse CPI events from an already-fetched transaction (emit_cpi! pattern).
2699
2732
  */
2700
- static async parseCpiEvents(connection, signature, targetProgramId, program) {
2733
+ static parseCpiEventsFromTransaction(tx, targetProgramId, program) {
2701
2734
  const events$1 = [];
2735
+ if (!tx?.meta?.innerInstructions) return events$1;
2736
+ for (const innerIxSet of tx.meta.innerInstructions) for (const instruction of innerIxSet.instructions) {
2737
+ if (!("programId" in instruction) || !("data" in instruction)) continue;
2738
+ if (instruction.programId.toString() !== targetProgramId) continue;
2739
+ const parsedEvent = this.parseInstruction(instruction.data, program);
2740
+ if (parsedEvent) events$1.push(parsedEvent);
2741
+ }
2742
+ return events$1;
2743
+ }
2744
+ /**
2745
+ * Fetch a transaction by signature and parse its CPI events.
2746
+ * Used by the subscription path where only the signature is available.
2747
+ */
2748
+ static async fetchAndParseCpiEvents(connection, signature, targetProgramId, program) {
2702
2749
  try {
2703
2750
  const tx = await connection.getParsedTransaction(signature, {
2704
2751
  commitment: "confirmed",
2705
2752
  maxSupportedTransactionVersion: 0
2706
2753
  });
2707
- if (!tx?.meta?.innerInstructions) return events$1;
2708
- for (const innerIxSet of tx.meta.innerInstructions) for (const instruction of innerIxSet.instructions) {
2709
- if (!("programId" in instruction) || !("data" in instruction)) continue;
2710
- if (instruction.programId.toString() !== targetProgramId) continue;
2711
- const parsedEvent = this.parseInstruction(instruction.data, program);
2712
- if (parsedEvent) events$1.push(parsedEvent);
2713
- }
2714
- } catch {}
2715
- return events$1;
2754
+ return this.parseCpiEventsFromTransaction(tx, targetProgramId, program);
2755
+ } catch {
2756
+ return [];
2757
+ }
2716
2758
  }
2717
2759
  /**
2718
2760
  * Parse CPI event from instruction data
@@ -2742,7 +2784,7 @@ var CpiEventParser = class {
2742
2784
  return connection.onLogs(program.programId, (logs, context) => {
2743
2785
  if (logs.err) return;
2744
2786
  (async () => {
2745
- const events$1 = await this.parseCpiEvents(connection, logs.signature, program.programId.toString(), program);
2787
+ const events$1 = await this.fetchAndParseCpiEvents(connection, logs.signature, program.programId.toString(), program);
2746
2788
  for (const event of events$1) {
2747
2789
  const handler = eventHandlers.get(event.name);
2748
2790
  if (handler) try {
@@ -2756,17 +2798,103 @@ var CpiEventParser = class {
2756
2798
 
2757
2799
  //#endregion
2758
2800
  //#region src/contracts/solana/utils.ts
2759
- function generateRequestIdSolana({ address: address$1, payload, path, keyVersion, chainId, algo, dest, params }) {
2760
- const payloadHex = "0x" + Buffer.from(payload).toString("hex");
2801
+ /**
2802
+ * Generates a unique request ID for Solana signature requests using keccak256 hashing.
2803
+ *
2804
+ * The request ID is computed by ABI-encoding the request parameters and hashing
2805
+ * the result. This ID is used to track signature requests and match them with
2806
+ * responses from the MPC network.
2807
+ *
2808
+ * @param request - The signature request parameters
2809
+ * @param request.address - The sender's address (Solana public key as string)
2810
+ * @param request.payload - The data payload to be signed
2811
+ * @param request.path - The derivation path for the signing key
2812
+ * @param request.keyVersion - The version of the signing key
2813
+ * @param request.chainId - The CAIP-2 chain identifier (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')
2814
+ * @param request.algo - The signing algorithm identifier
2815
+ * @param request.dest - The destination identifier for the signature
2816
+ * @param request.params - Additional parameters for the signing process
2817
+ * @returns The keccak256 hash of the encoded request as a hex string
2818
+ *
2819
+ * @example
2820
+ * ```typescript
2821
+ * const requestId = getRequestIdRespond({
2822
+ * address: 'So11111111111111111111111111111111111111112',
2823
+ * payload: new Uint8Array([1, 2, 3, 4]),
2824
+ * path: 'solana,1',
2825
+ * keyVersion: 0,
2826
+ * chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
2827
+ * algo: '',
2828
+ * dest: '',
2829
+ * params: '',
2830
+ * })
2831
+ * ```
2832
+ */
2833
+ function getRequestIdRespond(request) {
2834
+ const payloadHex = "0x" + Buffer.from(request.payload).toString("hex");
2761
2835
  return (0, viem.keccak256)((0, viem.encodeAbiParameters)((0, viem.parseAbiParameters)("string, bytes, string, uint32, string, string, string, string"), [
2762
- address$1,
2836
+ request.address,
2763
2837
  payloadHex,
2764
- path,
2765
- keyVersion,
2766
- chainId,
2767
- algo,
2768
- dest,
2769
- params
2838
+ request.path,
2839
+ request.keyVersion,
2840
+ request.chainId,
2841
+ request.algo,
2842
+ request.dest,
2843
+ request.params
2844
+ ]));
2845
+ }
2846
+ /**
2847
+ * Generates a unique request ID for bidirectional sign operations using keccak256 hashing.
2848
+ *
2849
+ * Unlike `getRequestIdRespond`, this function uses packed encoding (solidityPacked)
2850
+ * instead of standard ABI encoding. This is used for cross-chain bidirectional
2851
+ * signing flows where the request originates from a different chain.
2852
+ *
2853
+ * @param request - The bidirectional signature request parameters
2854
+ * @param request.sender - The sender's address (Solana public key as string)
2855
+ * @param request.payload - The data payload to be signed
2856
+ * @param request.caip2Id - The CAIP-2 chain identifier (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')
2857
+ * @param request.keyVersion - The version of the signing key
2858
+ * @param request.path - The derivation path for the signing key
2859
+ * @param request.algo - The signing algorithm identifier
2860
+ * @param request.dest - The destination identifier for the signature
2861
+ * @param request.params - Additional parameters for the signing process
2862
+ * @returns The keccak256 hash of the packed encoded request as a hex string
2863
+ *
2864
+ * @example
2865
+ * ```typescript
2866
+ * const requestId = getRequestIdBidirectional({
2867
+ * sender: 'So11111111111111111111111111111111111111112',
2868
+ * payload: new Uint8Array([1, 2, 3, 4]),
2869
+ * caip2Id: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
2870
+ * keyVersion: 0,
2871
+ * path: 'ethereum,1',
2872
+ * algo: '',
2873
+ * dest: '',
2874
+ * params: '',
2875
+ * })
2876
+ * ```
2877
+ */
2878
+ function getRequestIdBidirectional(request) {
2879
+ const payloadHex = `0x${Buffer.from(request.payload).toString("hex")}`;
2880
+ return (0, viem.keccak256)((0, viem.encodePacked)([
2881
+ "string",
2882
+ "bytes",
2883
+ "string",
2884
+ "uint32",
2885
+ "string",
2886
+ "string",
2887
+ "string",
2888
+ "string"
2889
+ ], [
2890
+ request.sender,
2891
+ payloadHex,
2892
+ request.caip2Id,
2893
+ request.keyVersion,
2894
+ request.path,
2895
+ request.algo,
2896
+ request.dest,
2897
+ request.params
2770
2898
  ]));
2771
2899
  }
2772
2900
 
@@ -2842,15 +2970,15 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
2842
2970
  }
2843
2971
  /**
2844
2972
  * Sends a transaction to the program to request a signature, then
2845
- * polls for the signature result. If the signature is not found within the retry
2846
- * parameters, it will throw an error.
2973
+ * races a WebSocket listener against polling backfill to find the result.
2974
+ * If the signature is not found within the timeout, it will throw an error.
2847
2975
  */
2848
2976
  async sign(args, options) {
2849
2977
  const algo = options?.sign?.algo ?? "";
2850
2978
  const dest = options?.sign?.dest ?? "";
2851
2979
  const params = options?.sign?.params ?? "";
2852
2980
  const delay = options?.retry?.delay ?? 5e3;
2853
- const retryCount = options?.retry?.retryCount ?? 12;
2981
+ const timeoutMs = delay * (options?.retry?.retryCount ?? 12);
2854
2982
  if (options?.remainingAccounts?.filter((acc) => acc.isSigner)?.some((acc) => !options?.remainingSigners?.some((signer) => signer.publicKey.equals(acc.pubkey)))) throw new Error("All accounts marked as signers must have a corresponding signer");
2855
2983
  const requestId = this.getRequestId(args, {
2856
2984
  algo,
@@ -2868,24 +2996,38 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
2868
2996
  const transaction = new __solana_web3_js.Transaction().add(instruction);
2869
2997
  transaction.feePayer = this.provider.wallet.publicKey;
2870
2998
  const hash = await this.sendAndConfirmWithoutWebSocket(transaction, options?.remainingSigners);
2999
+ const controller = new AbortController();
3000
+ const successPromise = this.waitForEvent({
3001
+ eventName: "signatureRespondedEvent",
3002
+ requestId,
3003
+ signer: this.programId,
3004
+ afterSignature: hash,
3005
+ timeoutMs,
3006
+ backfillIntervalMs: delay,
3007
+ signal: controller.signal
3008
+ });
3009
+ const errorPromise = this.waitForEvent({
3010
+ eventName: "signatureErrorEvent",
3011
+ requestId,
3012
+ signer: this.programId,
3013
+ afterSignature: hash,
3014
+ timeoutMs,
3015
+ backfillIntervalMs: delay,
3016
+ signal: controller.signal
3017
+ }).then((err) => {
3018
+ throw new SignatureContractError(err.error, requestId, { hash });
3019
+ });
3020
+ successPromise.catch(() => {});
3021
+ errorPromise.catch(() => {});
2871
3022
  try {
2872
- const pollResult = await this.pollForRequestId({
2873
- requestId,
2874
- payload: args.payload,
2875
- path: args.path,
2876
- afterSignature: hash,
2877
- options: {
2878
- delay,
2879
- retryCount
2880
- }
2881
- });
2882
- if (!pollResult) throw new SignatureNotFoundError(requestId, { hash });
2883
- if ("error" in pollResult) throw new SignatureContractError(pollResult.error, requestId, { hash });
2884
- if (!await verifyRecoveredAddress(pollResult, args.payload, this.requesterAddress, args.path, this, args.key_version)) throw new SigningError(requestId, { hash }, /* @__PURE__ */ new Error("Signature verification failed: recovered address does not match expected address"));
2885
- return pollResult;
3023
+ const result = await Promise.race([successPromise, errorPromise]);
3024
+ if (!await verifyRecoveredAddress(result, args.payload, this.requesterAddress, args.path, this, args.key_version)) throw new SigningError(requestId, { hash }, /* @__PURE__ */ new Error("Signature verification failed: recovered address does not match expected address"));
3025
+ return result;
2886
3026
  } catch (error) {
2887
3027
  if (error instanceof SignatureNotFoundError || error instanceof SignatureContractError) throw error;
2888
3028
  else throw new SigningError(requestId, { hash }, error instanceof Error ? error : void 0);
3029
+ } finally {
3030
+ controller.abort();
2889
3031
  }
2890
3032
  }
2891
3033
  async sendAndConfirmWithoutWebSocket(transaction, signers) {
@@ -2909,70 +3051,147 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
2909
3051
  throw new __solana_web3_js.TransactionExpiredTimeoutError(signature, timeout / 1e3);
2910
3052
  }
2911
3053
  /**
2912
- * Polls for signature or error events matching the given requestId starting from the solana transaction with signature afterSignature.
2913
- * Returns a signature, error data, or undefined if nothing is found.
3054
+ * Waits for a specific event matching the given requestId by combining
3055
+ * a WebSocket listener (real-time) with polling backfill (resilience).
2914
3056
  */
2915
- async pollForRequestId({ requestId, payload: _payload, path: _path, afterSignature, options }) {
2916
- const delay = options?.delay ?? 5e3;
2917
- const retryCount = options?.retryCount ?? 12;
2918
- let lastCheckedSignature = afterSignature;
2919
- for (let i = 0; i < retryCount; i++) {
2920
- try {
2921
- const signatures = await this.connection.getSignaturesForAddress(this.programId, {
2922
- until: lastCheckedSignature,
2923
- limit: 50
2924
- }, "confirmed");
2925
- if (signatures.length > 0) lastCheckedSignature = signatures[signatures.length - 1].signature;
2926
- for (const sig of signatures) {
2927
- const tx = await this.connection.getParsedTransaction(sig.signature, {
2928
- commitment: "confirmed",
2929
- maxSupportedTransactionVersion: 0
3057
+ async waitForEvent(options) {
3058
+ const { eventName, requestId, signer, afterSignature, timeoutMs = 6e4, backfillIntervalMs = 5e3, backfillLimit = 50, signal } = options;
3059
+ return await new Promise((resolve, reject) => {
3060
+ let settled = false;
3061
+ const seenSignatures = /* @__PURE__ */ new Set();
3062
+ let lastCheckedSignature = afterSignature;
3063
+ const cleanupFns = [];
3064
+ const cleanup = () => {
3065
+ for (const fn of cleanupFns) try {
3066
+ fn();
3067
+ } catch {}
3068
+ };
3069
+ const settle = (action) => {
3070
+ if (settled) return;
3071
+ settled = true;
3072
+ cleanup();
3073
+ action();
3074
+ };
3075
+ const processEvent = (name, data, txSignature) => {
3076
+ if (settled) return false;
3077
+ if (txSignature && seenSignatures.has(txSignature)) return false;
3078
+ if (txSignature) seenSignatures.add(txSignature);
3079
+ if (name !== eventName) return false;
3080
+ const result = this.mapEventForName(eventName, data, requestId);
3081
+ if (result !== void 0) {
3082
+ settle(() => {
3083
+ resolve(result);
2930
3084
  });
2931
- if (tx?.meta?.logMessages) {
2932
- const result = await this.parseLogsForEvents(tx.meta.logMessages, requestId, sig.signature);
2933
- if (result) return result;
2934
- }
3085
+ return true;
2935
3086
  }
2936
- } catch (error) {
2937
- console.error("Error checking for events:", error);
2938
- }
2939
- if (i < retryCount - 1) {
2940
- console.log(`Retrying get signature: ${i + 1}/${retryCount}`);
2941
- await new Promise((resolve) => setTimeout(resolve, delay));
3087
+ return false;
3088
+ };
3089
+ if (signal) {
3090
+ if (signal.aborted) {
3091
+ settle(() => {
3092
+ reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
3093
+ });
3094
+ return;
3095
+ }
3096
+ const onAbort = () => {
3097
+ settle(() => {
3098
+ reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
3099
+ });
3100
+ };
3101
+ signal.addEventListener("abort", onAbort, { once: true });
3102
+ cleanupFns.push(() => {
3103
+ signal.removeEventListener("abort", onAbort);
3104
+ });
2942
3105
  }
2943
- }
3106
+ const timeoutId = setTimeout(() => {
3107
+ settle(() => {
3108
+ reject(new SignatureNotFoundError(requestId));
3109
+ });
3110
+ }, timeoutMs);
3111
+ cleanupFns.push(() => {
3112
+ clearTimeout(timeoutId);
3113
+ });
3114
+ const parser = new __coral_xyz_anchor.EventParser(this.program.programId, this.program.coder);
3115
+ const subId = this.connection.onLogs(signer, (logs, _context) => {
3116
+ if (settled) return;
3117
+ if (logs.err) return;
3118
+ for (const evt of parser.parseLogs(logs.logs)) {
3119
+ if (!evt) continue;
3120
+ if (processEvent(evt.name, evt.data, logs.signature)) return;
3121
+ }
3122
+ CpiEventParser.fetchAndParseCpiEvents(this.connection, logs.signature, this.programId.toString(), this.program).then((cpiEvents) => {
3123
+ for (const event of cpiEvents) if (processEvent(event.name, event.data, logs.signature)) return;
3124
+ });
3125
+ }, "confirmed");
3126
+ cleanupFns.push(() => {
3127
+ this.connection.removeOnLogsListener(subId);
3128
+ });
3129
+ const runBackfill = async () => {
3130
+ if (settled) return;
3131
+ try {
3132
+ const signatures = await this.connection.getSignaturesForAddress(signer, {
3133
+ until: lastCheckedSignature,
3134
+ limit: backfillLimit
3135
+ }, "confirmed");
3136
+ if (signatures.length > 0) lastCheckedSignature = signatures[0].signature;
3137
+ for (const sig of signatures) {
3138
+ if (settled) return;
3139
+ if (seenSignatures.has(sig.signature)) continue;
3140
+ const tx = await this.connection.getParsedTransaction(sig.signature, {
3141
+ commitment: "confirmed",
3142
+ maxSupportedTransactionVersion: 0
3143
+ });
3144
+ if (!tx) continue;
3145
+ const cpiEvents = CpiEventParser.parseCpiEventsFromTransaction(tx, this.programId.toString(), this.program);
3146
+ for (const event of cpiEvents) if (processEvent(event.name, event.data, sig.signature)) return;
3147
+ const logs = tx.meta?.logMessages;
3148
+ if (logs) for (const evt of parser.parseLogs(logs)) {
3149
+ if (!evt) continue;
3150
+ if (processEvent(evt.name, evt.data, sig.signature)) return;
3151
+ }
3152
+ }
3153
+ } catch {}
3154
+ };
3155
+ runBackfill();
3156
+ const intervalId = setInterval(() => {
3157
+ runBackfill();
3158
+ }, backfillIntervalMs);
3159
+ cleanupFns.push(() => {
3160
+ clearInterval(intervalId);
3161
+ });
3162
+ });
2944
3163
  }
2945
- /**
2946
- * Parses transaction logs for signature or error events.
2947
- */
2948
- async parseLogsForEvents(logs, requestId, signature) {
2949
- const cpiEvents = await CpiEventParser.parseCpiEvents(this.connection, signature, this.programId.toString(), this.program);
2950
- for (const event of cpiEvents) {
2951
- const mapped = this.mapEventToResult(event.name, event.name === "signatureRespondedEvent" ? event.data : event.data, requestId);
2952
- if (mapped) return mapped;
2953
- }
2954
- const parser = new __coral_xyz_anchor.EventParser(this.program.programId, this.program.coder);
2955
- for (const evt of parser.parseLogs(logs)) {
2956
- if (!evt) continue;
2957
- const mapped = this.mapEventToResult(evt.name, evt.name === "signatureRespondedEvent" ? evt.data : evt.data, requestId);
2958
- if (mapped) return mapped;
2959
- }
3164
+ mapRespondToResult(data, requestId) {
3165
+ if ("0x" + Buffer.from(data.requestId).toString("hex") !== requestId) return void 0;
3166
+ return {
3167
+ r: Buffer.from(data.signature.bigR.x).toString("hex"),
3168
+ s: Buffer.from(data.signature.s).toString("hex"),
3169
+ v: data.signature.recoveryId + 27
3170
+ };
2960
3171
  }
2961
- mapEventToResult(name, data, requestId) {
3172
+ mapRespondErrorToResult(data, requestId) {
2962
3173
  const eventRequestIdHex = "0x" + Buffer.from(data.requestId).toString("hex");
2963
- if (name === "signatureRespondedEvent" && eventRequestIdHex === requestId) {
2964
- const d = data;
2965
- return {
2966
- r: Buffer.from(d.signature.bigR.x).toString("hex"),
2967
- s: Buffer.from(d.signature.s).toString("hex"),
2968
- v: d.signature.recoveryId + 27
2969
- };
2970
- }
2971
- if (name === "signatureErrorEvent" && eventRequestIdHex === requestId) return {
3174
+ if (eventRequestIdHex !== requestId) return void 0;
3175
+ return {
2972
3176
  requestId: eventRequestIdHex,
2973
3177
  error: data.error
2974
3178
  };
2975
3179
  }
3180
+ mapRespondBidirectionalToResult(data, requestId) {
3181
+ if ("0x" + Buffer.from(data.requestId).toString("hex") !== requestId) return void 0;
3182
+ return {
3183
+ serializedOutput: data.serializedOutput,
3184
+ signature: data.signature
3185
+ };
3186
+ }
3187
+ mapEventForName(eventName, data, requestId) {
3188
+ switch (eventName) {
3189
+ case "signatureRespondedEvent": return this.mapRespondToResult(data, requestId);
3190
+ case "signatureErrorEvent": return this.mapRespondErrorToResult(data, requestId);
3191
+ case "respondBidirectionalEvent": return this.mapRespondBidirectionalToResult(data, requestId);
3192
+ default: return;
3193
+ }
3194
+ }
2976
3195
  /**
2977
3196
  * Generates the request ID for a signature request allowing to track the response.
2978
3197
  */
@@ -2981,7 +3200,7 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
2981
3200
  dest: "",
2982
3201
  params: ""
2983
3202
  }) {
2984
- return generateRequestIdSolana({
3203
+ return getRequestIdRespond({
2985
3204
  payload: args.payload,
2986
3205
  path: args.path,
2987
3206
  keyVersion: args.key_version,
@@ -2992,52 +3211,14 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
2992
3211
  chainId: KDF_CHAIN_IDS.SOLANA
2993
3212
  });
2994
3213
  }
2995
- /**
2996
- * Subscribes to program events using Anchor's EventParser for regular events,
2997
- * and CPI parsing for emit_cpi!-emitted events. Returns an unsubscribe fn.
2998
- */
2999
- async subscribeToEvents(handlers) {
3000
- const commitment = "confirmed";
3001
- const cpiHandlers = /* @__PURE__ */ new Map();
3002
- if (handlers.onSignatureResponded) {
3003
- const onSignatureResponded = handlers.onSignatureResponded;
3004
- cpiHandlers.set("signatureRespondedEvent", async (e, s) => {
3005
- await onSignatureResponded(e, s);
3006
- });
3007
- }
3008
- if (handlers.onSignatureError) {
3009
- const onSignatureError = handlers.onSignatureError;
3010
- cpiHandlers.set("signatureErrorEvent", async (e, s) => {
3011
- await onSignatureError(e, s);
3012
- });
3013
- }
3014
- const cpiSubId = CpiEventParser.subscribeToCpiEvents(this.connection, this.program, cpiHandlers);
3015
- const parser = new __coral_xyz_anchor.EventParser(this.program.programId, this.program.coder);
3016
- const subId = this.connection.onLogs(this.program.programId, (logs, context) => {
3017
- if (logs.err) return;
3018
- for (const evt of parser.parseLogs(logs.logs)) {
3019
- if (!evt) continue;
3020
- if (evt.name === "signatureRespondedEvent") {
3021
- const onSignatureResponded = handlers.onSignatureResponded;
3022
- if (onSignatureResponded) onSignatureResponded(evt.data, context.slot);
3023
- }
3024
- if (evt.name === "signatureErrorEvent") {
3025
- const onSignatureError = handlers.onSignatureError;
3026
- if (onSignatureError) onSignatureError(evt.data, context.slot);
3027
- }
3028
- }
3029
- }, commitment);
3030
- return async () => {
3031
- await this.connection.removeOnLogsListener(subId);
3032
- await this.connection.removeOnLogsListener(cpiSubId);
3033
- };
3034
- }
3035
3214
  };
3036
3215
 
3037
3216
  //#endregion
3038
3217
  //#region src/contracts/solana/index.ts
3039
3218
  var solana_exports = /* @__PURE__ */ __export({
3040
3219
  ChainSignatureContract: () => ChainSignatureContract$1,
3220
+ getRequestIdBidirectional: () => getRequestIdBidirectional,
3221
+ getRequestIdRespond: () => getRequestIdRespond,
3041
3222
  utils: () => utils
3042
3223
  });
3043
3224
  const utils = {