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 +317 -136
- package/dist/index.d.cts +161 -39
- package/dist/index.d.ts +162 -39
- package/dist/index.js +318 -137
- package/package.json +15 -15
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
2731
|
+
* Parse CPI events from an already-fetched transaction (emit_cpi! pattern).
|
|
2699
2732
|
*/
|
|
2700
|
-
static
|
|
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
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
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.
|
|
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
|
-
|
|
2760
|
-
|
|
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
|
|
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
|
-
*
|
|
2846
|
-
*
|
|
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
|
|
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
|
|
2873
|
-
|
|
2874
|
-
|
|
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
|
-
*
|
|
2913
|
-
*
|
|
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
|
|
2916
|
-
const
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
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
|
-
|
|
2932
|
-
const result = await this.parseLogsForEvents(tx.meta.logMessages, requestId, sig.signature);
|
|
2933
|
-
if (result) return result;
|
|
2934
|
-
}
|
|
3085
|
+
return true;
|
|
2935
3086
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
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
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
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
|
-
|
|
3172
|
+
mapRespondErrorToResult(data, requestId) {
|
|
2962
3173
|
const eventRequestIdHex = "0x" + Buffer.from(data.requestId).toString("hex");
|
|
2963
|
-
if (
|
|
2964
|
-
|
|
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
|
|
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 = {
|