signet.js 0.2.0 → 0.3.0
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 +182 -122
- package/dist/index.d.cts +25 -36
- package/dist/index.d.ts +25 -36
- package/dist/index.js +182 -122
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -2695,24 +2695,33 @@ const EMIT_CPI_INSTRUCTION_DISCRIMINATOR = Buffer.from([
|
|
|
2695
2695
|
]);
|
|
2696
2696
|
var CpiEventParser = class {
|
|
2697
2697
|
/**
|
|
2698
|
-
* Parse CPI events from
|
|
2698
|
+
* Parse CPI events from an already-fetched transaction (emit_cpi! pattern).
|
|
2699
2699
|
*/
|
|
2700
|
-
static
|
|
2700
|
+
static parseCpiEventsFromTransaction(tx, targetProgramId, program) {
|
|
2701
2701
|
const events$1 = [];
|
|
2702
|
+
if (!tx?.meta?.innerInstructions) return events$1;
|
|
2703
|
+
for (const innerIxSet of tx.meta.innerInstructions) for (const instruction of innerIxSet.instructions) {
|
|
2704
|
+
if (!("programId" in instruction) || !("data" in instruction)) continue;
|
|
2705
|
+
if (instruction.programId.toString() !== targetProgramId) continue;
|
|
2706
|
+
const parsedEvent = this.parseInstruction(instruction.data, program);
|
|
2707
|
+
if (parsedEvent) events$1.push(parsedEvent);
|
|
2708
|
+
}
|
|
2709
|
+
return events$1;
|
|
2710
|
+
}
|
|
2711
|
+
/**
|
|
2712
|
+
* Fetch a transaction by signature and parse its CPI events.
|
|
2713
|
+
* Used by the subscription path where only the signature is available.
|
|
2714
|
+
*/
|
|
2715
|
+
static async fetchAndParseCpiEvents(connection, signature, targetProgramId, program) {
|
|
2702
2716
|
try {
|
|
2703
2717
|
const tx = await connection.getParsedTransaction(signature, {
|
|
2704
2718
|
commitment: "confirmed",
|
|
2705
2719
|
maxSupportedTransactionVersion: 0
|
|
2706
2720
|
});
|
|
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;
|
|
2721
|
+
return this.parseCpiEventsFromTransaction(tx, targetProgramId, program);
|
|
2722
|
+
} catch {
|
|
2723
|
+
return [];
|
|
2724
|
+
}
|
|
2716
2725
|
}
|
|
2717
2726
|
/**
|
|
2718
2727
|
* Parse CPI event from instruction data
|
|
@@ -2742,7 +2751,7 @@ var CpiEventParser = class {
|
|
|
2742
2751
|
return connection.onLogs(program.programId, (logs, context) => {
|
|
2743
2752
|
if (logs.err) return;
|
|
2744
2753
|
(async () => {
|
|
2745
|
-
const events$1 = await this.
|
|
2754
|
+
const events$1 = await this.fetchAndParseCpiEvents(connection, logs.signature, program.programId.toString(), program);
|
|
2746
2755
|
for (const event of events$1) {
|
|
2747
2756
|
const handler = eventHandlers.get(event.name);
|
|
2748
2757
|
if (handler) try {
|
|
@@ -2842,15 +2851,15 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2842
2851
|
}
|
|
2843
2852
|
/**
|
|
2844
2853
|
* Sends a transaction to the program to request a signature, then
|
|
2845
|
-
*
|
|
2846
|
-
*
|
|
2854
|
+
* races a WebSocket listener against polling backfill to find the result.
|
|
2855
|
+
* If the signature is not found within the timeout, it will throw an error.
|
|
2847
2856
|
*/
|
|
2848
2857
|
async sign(args, options) {
|
|
2849
2858
|
const algo = options?.sign?.algo ?? "";
|
|
2850
2859
|
const dest = options?.sign?.dest ?? "";
|
|
2851
2860
|
const params = options?.sign?.params ?? "";
|
|
2852
2861
|
const delay = options?.retry?.delay ?? 5e3;
|
|
2853
|
-
const
|
|
2862
|
+
const timeoutMs = delay * (options?.retry?.retryCount ?? 12);
|
|
2854
2863
|
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
2864
|
const requestId = this.getRequestId(args, {
|
|
2856
2865
|
algo,
|
|
@@ -2868,24 +2877,38 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2868
2877
|
const transaction = new __solana_web3_js.Transaction().add(instruction);
|
|
2869
2878
|
transaction.feePayer = this.provider.wallet.publicKey;
|
|
2870
2879
|
const hash = await this.sendAndConfirmWithoutWebSocket(transaction, options?.remainingSigners);
|
|
2880
|
+
const controller = new AbortController();
|
|
2881
|
+
const successPromise = this.waitForEvent({
|
|
2882
|
+
eventName: "signatureRespondedEvent",
|
|
2883
|
+
requestId,
|
|
2884
|
+
signer: this.programId,
|
|
2885
|
+
afterSignature: hash,
|
|
2886
|
+
timeoutMs,
|
|
2887
|
+
backfillIntervalMs: delay,
|
|
2888
|
+
signal: controller.signal
|
|
2889
|
+
});
|
|
2890
|
+
const errorPromise = this.waitForEvent({
|
|
2891
|
+
eventName: "signatureErrorEvent",
|
|
2892
|
+
requestId,
|
|
2893
|
+
signer: this.programId,
|
|
2894
|
+
afterSignature: hash,
|
|
2895
|
+
timeoutMs,
|
|
2896
|
+
backfillIntervalMs: delay,
|
|
2897
|
+
signal: controller.signal
|
|
2898
|
+
}).then((err) => {
|
|
2899
|
+
throw new SignatureContractError(err.error, requestId, { hash });
|
|
2900
|
+
});
|
|
2901
|
+
successPromise.catch(() => {});
|
|
2902
|
+
errorPromise.catch(() => {});
|
|
2871
2903
|
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;
|
|
2904
|
+
const result = await Promise.race([successPromise, errorPromise]);
|
|
2905
|
+
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"));
|
|
2906
|
+
return result;
|
|
2886
2907
|
} catch (error) {
|
|
2887
2908
|
if (error instanceof SignatureNotFoundError || error instanceof SignatureContractError) throw error;
|
|
2888
2909
|
else throw new SigningError(requestId, { hash }, error instanceof Error ? error : void 0);
|
|
2910
|
+
} finally {
|
|
2911
|
+
controller.abort();
|
|
2889
2912
|
}
|
|
2890
2913
|
}
|
|
2891
2914
|
async sendAndConfirmWithoutWebSocket(transaction, signers) {
|
|
@@ -2909,70 +2932,147 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2909
2932
|
throw new __solana_web3_js.TransactionExpiredTimeoutError(signature, timeout / 1e3);
|
|
2910
2933
|
}
|
|
2911
2934
|
/**
|
|
2912
|
-
*
|
|
2913
|
-
*
|
|
2935
|
+
* Waits for a specific event matching the given requestId by combining
|
|
2936
|
+
* a WebSocket listener (real-time) with polling backfill (resilience).
|
|
2914
2937
|
*/
|
|
2915
|
-
async
|
|
2916
|
-
const
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2938
|
+
async waitForEvent(options) {
|
|
2939
|
+
const { eventName, requestId, signer, afterSignature, timeoutMs = 6e4, backfillIntervalMs = 5e3, backfillLimit = 50, signal } = options;
|
|
2940
|
+
return await new Promise((resolve, reject) => {
|
|
2941
|
+
let settled = false;
|
|
2942
|
+
const seenSignatures = /* @__PURE__ */ new Set();
|
|
2943
|
+
let lastCheckedSignature = afterSignature;
|
|
2944
|
+
const cleanupFns = [];
|
|
2945
|
+
const cleanup = () => {
|
|
2946
|
+
for (const fn of cleanupFns) try {
|
|
2947
|
+
fn();
|
|
2948
|
+
} catch {}
|
|
2949
|
+
};
|
|
2950
|
+
const settle = (action) => {
|
|
2951
|
+
if (settled) return;
|
|
2952
|
+
settled = true;
|
|
2953
|
+
cleanup();
|
|
2954
|
+
action();
|
|
2955
|
+
};
|
|
2956
|
+
const processEvent = (name, data, txSignature) => {
|
|
2957
|
+
if (settled) return false;
|
|
2958
|
+
if (txSignature && seenSignatures.has(txSignature)) return false;
|
|
2959
|
+
if (txSignature) seenSignatures.add(txSignature);
|
|
2960
|
+
if (name !== eventName) return false;
|
|
2961
|
+
const result = this.mapEventForName(eventName, data, requestId);
|
|
2962
|
+
if (result !== void 0) {
|
|
2963
|
+
settle(() => {
|
|
2964
|
+
resolve(result);
|
|
2930
2965
|
});
|
|
2931
|
-
|
|
2932
|
-
const result = await this.parseLogsForEvents(tx.meta.logMessages, requestId, sig.signature);
|
|
2933
|
-
if (result) return result;
|
|
2934
|
-
}
|
|
2966
|
+
return true;
|
|
2935
2967
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2968
|
+
return false;
|
|
2969
|
+
};
|
|
2970
|
+
if (signal) {
|
|
2971
|
+
if (signal.aborted) {
|
|
2972
|
+
settle(() => {
|
|
2973
|
+
reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2974
|
+
});
|
|
2975
|
+
return;
|
|
2976
|
+
}
|
|
2977
|
+
const onAbort = () => {
|
|
2978
|
+
settle(() => {
|
|
2979
|
+
reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2980
|
+
});
|
|
2981
|
+
};
|
|
2982
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2983
|
+
cleanupFns.push(() => {
|
|
2984
|
+
signal.removeEventListener("abort", onAbort);
|
|
2985
|
+
});
|
|
2942
2986
|
}
|
|
2943
|
-
|
|
2987
|
+
const timeoutId = setTimeout(() => {
|
|
2988
|
+
settle(() => {
|
|
2989
|
+
reject(new SignatureNotFoundError(requestId));
|
|
2990
|
+
});
|
|
2991
|
+
}, timeoutMs);
|
|
2992
|
+
cleanupFns.push(() => {
|
|
2993
|
+
clearTimeout(timeoutId);
|
|
2994
|
+
});
|
|
2995
|
+
const parser = new __coral_xyz_anchor.EventParser(this.program.programId, this.program.coder);
|
|
2996
|
+
const subId = this.connection.onLogs(signer, (logs, _context) => {
|
|
2997
|
+
if (settled) return;
|
|
2998
|
+
if (logs.err) return;
|
|
2999
|
+
for (const evt of parser.parseLogs(logs.logs)) {
|
|
3000
|
+
if (!evt) continue;
|
|
3001
|
+
if (processEvent(evt.name, evt.data, logs.signature)) return;
|
|
3002
|
+
}
|
|
3003
|
+
CpiEventParser.fetchAndParseCpiEvents(this.connection, logs.signature, this.programId.toString(), this.program).then((cpiEvents) => {
|
|
3004
|
+
for (const event of cpiEvents) if (processEvent(event.name, event.data, logs.signature)) return;
|
|
3005
|
+
});
|
|
3006
|
+
}, "confirmed");
|
|
3007
|
+
cleanupFns.push(() => {
|
|
3008
|
+
this.connection.removeOnLogsListener(subId);
|
|
3009
|
+
});
|
|
3010
|
+
const runBackfill = async () => {
|
|
3011
|
+
if (settled) return;
|
|
3012
|
+
try {
|
|
3013
|
+
const signatures = await this.connection.getSignaturesForAddress(signer, {
|
|
3014
|
+
until: lastCheckedSignature,
|
|
3015
|
+
limit: backfillLimit
|
|
3016
|
+
}, "confirmed");
|
|
3017
|
+
if (signatures.length > 0) lastCheckedSignature = signatures[0].signature;
|
|
3018
|
+
for (const sig of signatures) {
|
|
3019
|
+
if (settled) return;
|
|
3020
|
+
if (seenSignatures.has(sig.signature)) continue;
|
|
3021
|
+
const tx = await this.connection.getParsedTransaction(sig.signature, {
|
|
3022
|
+
commitment: "confirmed",
|
|
3023
|
+
maxSupportedTransactionVersion: 0
|
|
3024
|
+
});
|
|
3025
|
+
if (!tx) continue;
|
|
3026
|
+
const cpiEvents = CpiEventParser.parseCpiEventsFromTransaction(tx, this.programId.toString(), this.program);
|
|
3027
|
+
for (const event of cpiEvents) if (processEvent(event.name, event.data, sig.signature)) return;
|
|
3028
|
+
const logs = tx.meta?.logMessages;
|
|
3029
|
+
if (logs) for (const evt of parser.parseLogs(logs)) {
|
|
3030
|
+
if (!evt) continue;
|
|
3031
|
+
if (processEvent(evt.name, evt.data, sig.signature)) return;
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
} catch {}
|
|
3035
|
+
};
|
|
3036
|
+
runBackfill();
|
|
3037
|
+
const intervalId = setInterval(() => {
|
|
3038
|
+
runBackfill();
|
|
3039
|
+
}, backfillIntervalMs);
|
|
3040
|
+
cleanupFns.push(() => {
|
|
3041
|
+
clearInterval(intervalId);
|
|
3042
|
+
});
|
|
3043
|
+
});
|
|
2944
3044
|
}
|
|
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
|
-
}
|
|
3045
|
+
mapRespondToResult(data, requestId) {
|
|
3046
|
+
if ("0x" + Buffer.from(data.requestId).toString("hex") !== requestId) return void 0;
|
|
3047
|
+
return {
|
|
3048
|
+
r: Buffer.from(data.signature.bigR.x).toString("hex"),
|
|
3049
|
+
s: Buffer.from(data.signature.s).toString("hex"),
|
|
3050
|
+
v: data.signature.recoveryId + 27
|
|
3051
|
+
};
|
|
2960
3052
|
}
|
|
2961
|
-
|
|
3053
|
+
mapRespondErrorToResult(data, requestId) {
|
|
2962
3054
|
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 {
|
|
3055
|
+
if (eventRequestIdHex !== requestId) return void 0;
|
|
3056
|
+
return {
|
|
2972
3057
|
requestId: eventRequestIdHex,
|
|
2973
3058
|
error: data.error
|
|
2974
3059
|
};
|
|
2975
3060
|
}
|
|
3061
|
+
mapRespondBidirectionalToResult(data, requestId) {
|
|
3062
|
+
if ("0x" + Buffer.from(data.requestId).toString("hex") !== requestId) return void 0;
|
|
3063
|
+
return {
|
|
3064
|
+
serializedOutput: data.serializedOutput,
|
|
3065
|
+
signature: data.signature
|
|
3066
|
+
};
|
|
3067
|
+
}
|
|
3068
|
+
mapEventForName(eventName, data, requestId) {
|
|
3069
|
+
switch (eventName) {
|
|
3070
|
+
case "signatureRespondedEvent": return this.mapRespondToResult(data, requestId);
|
|
3071
|
+
case "signatureErrorEvent": return this.mapRespondErrorToResult(data, requestId);
|
|
3072
|
+
case "respondBidirectionalEvent": return this.mapRespondBidirectionalToResult(data, requestId);
|
|
3073
|
+
default: return;
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
2976
3076
|
/**
|
|
2977
3077
|
* Generates the request ID for a signature request allowing to track the response.
|
|
2978
3078
|
*/
|
|
@@ -2992,46 +3092,6 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2992
3092
|
chainId: KDF_CHAIN_IDS.SOLANA
|
|
2993
3093
|
});
|
|
2994
3094
|
}
|
|
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
3095
|
};
|
|
3036
3096
|
|
|
3037
3097
|
//#endregion
|
package/dist/index.d.cts
CHANGED
|
@@ -1550,16 +1550,17 @@ interface Signature {
|
|
|
1550
1550
|
s: number[];
|
|
1551
1551
|
recoveryId: number;
|
|
1552
1552
|
}
|
|
1553
|
-
interface
|
|
1554
|
-
|
|
1555
|
-
responder: PublicKey;
|
|
1553
|
+
interface RespondBidirectionalData {
|
|
1554
|
+
serializedOutput: Buffer;
|
|
1556
1555
|
signature: Signature;
|
|
1557
1556
|
}
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1557
|
+
type ChainSignaturesEventName = 'signatureRespondedEvent' | 'signatureErrorEvent' | 'respondBidirectionalEvent';
|
|
1558
|
+
interface EventResultMap {
|
|
1559
|
+
signatureRespondedEvent: RSVSignature;
|
|
1560
|
+
signatureErrorEvent: SignatureErrorData;
|
|
1561
|
+
respondBidirectionalEvent: RespondBidirectionalData;
|
|
1562
1562
|
}
|
|
1563
|
+
type EventResult<E extends ChainSignaturesEventName> = EventResultMap[E];
|
|
1563
1564
|
//#endregion
|
|
1564
1565
|
//#region src/contracts/solana/ChainSignaturesContract.d.ts
|
|
1565
1566
|
declare class ChainSignatureContract$1 extends ChainSignatureContract {
|
|
@@ -1608,8 +1609,8 @@ declare class ChainSignatureContract$1 extends ChainSignatureContract {
|
|
|
1608
1609
|
}): Promise<TransactionInstruction>;
|
|
1609
1610
|
/**
|
|
1610
1611
|
* Sends a transaction to the program to request a signature, then
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1612
|
+
* races a WebSocket listener against polling backfill to find the result.
|
|
1613
|
+
* If the signature is not found within the timeout, it will throw an error.
|
|
1613
1614
|
*/
|
|
1614
1615
|
sign(args: SignArgs, options?: Partial<SignOptions> & {
|
|
1615
1616
|
remainingAccounts?: AccountMeta[];
|
|
@@ -1617,39 +1618,27 @@ declare class ChainSignatureContract$1 extends ChainSignatureContract {
|
|
|
1617
1618
|
}): Promise<RSVSignature>;
|
|
1618
1619
|
private sendAndConfirmWithoutWebSocket;
|
|
1619
1620
|
/**
|
|
1620
|
-
*
|
|
1621
|
-
*
|
|
1621
|
+
* Waits for a specific event matching the given requestId by combining
|
|
1622
|
+
* a WebSocket listener (real-time) with polling backfill (resilience).
|
|
1622
1623
|
*/
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
payload: _payload,
|
|
1626
|
-
path: _path,
|
|
1627
|
-
afterSignature,
|
|
1628
|
-
options
|
|
1629
|
-
}: {
|
|
1624
|
+
waitForEvent<E extends ChainSignaturesEventName>(options: {
|
|
1625
|
+
eventName: E;
|
|
1630
1626
|
requestId: string;
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
private
|
|
1640
|
-
private
|
|
1627
|
+
signer: PublicKey;
|
|
1628
|
+
afterSignature?: string;
|
|
1629
|
+
timeoutMs?: number;
|
|
1630
|
+
backfillIntervalMs?: number;
|
|
1631
|
+
backfillLimit?: number;
|
|
1632
|
+
signal?: AbortSignal;
|
|
1633
|
+
}): Promise<EventResult<E>>;
|
|
1634
|
+
private mapRespondToResult;
|
|
1635
|
+
private mapRespondErrorToResult;
|
|
1636
|
+
private mapRespondBidirectionalToResult;
|
|
1637
|
+
private mapEventForName;
|
|
1641
1638
|
/**
|
|
1642
1639
|
* Generates the request ID for a signature request allowing to track the response.
|
|
1643
1640
|
*/
|
|
1644
1641
|
getRequestId(args: SignArgs, options?: SignOptions['sign']): string;
|
|
1645
|
-
/**
|
|
1646
|
-
* Subscribes to program events using Anchor's EventParser for regular events,
|
|
1647
|
-
* and CPI parsing for emit_cpi!-emitted events. Returns an unsubscribe fn.
|
|
1648
|
-
*/
|
|
1649
|
-
subscribeToEvents(handlers: {
|
|
1650
|
-
onSignatureResponded?: (event: SignatureRespondedEvent, slot: number) => Promise<void> | void;
|
|
1651
|
-
onSignatureError?: (event: SignatureErrorEvent, slot: number) => Promise<void> | void;
|
|
1652
|
-
}): Promise<() => Promise<void>>;
|
|
1653
1642
|
}
|
|
1654
1643
|
declare namespace index_d_exports$4 {
|
|
1655
1644
|
export { ChainSignatureContract$1 as ChainSignatureContract, ChainSignaturesProject, utils };
|
package/dist/index.d.ts
CHANGED
|
@@ -1548,16 +1548,17 @@ interface Signature {
|
|
|
1548
1548
|
s: number[];
|
|
1549
1549
|
recoveryId: number;
|
|
1550
1550
|
}
|
|
1551
|
-
interface
|
|
1552
|
-
|
|
1553
|
-
responder: PublicKey;
|
|
1551
|
+
interface RespondBidirectionalData {
|
|
1552
|
+
serializedOutput: Buffer;
|
|
1554
1553
|
signature: Signature;
|
|
1555
1554
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1555
|
+
type ChainSignaturesEventName = 'signatureRespondedEvent' | 'signatureErrorEvent' | 'respondBidirectionalEvent';
|
|
1556
|
+
interface EventResultMap {
|
|
1557
|
+
signatureRespondedEvent: RSVSignature;
|
|
1558
|
+
signatureErrorEvent: SignatureErrorData;
|
|
1559
|
+
respondBidirectionalEvent: RespondBidirectionalData;
|
|
1560
1560
|
}
|
|
1561
|
+
type EventResult<E extends ChainSignaturesEventName> = EventResultMap[E];
|
|
1561
1562
|
//#endregion
|
|
1562
1563
|
//#region src/contracts/solana/ChainSignaturesContract.d.ts
|
|
1563
1564
|
declare class ChainSignatureContract$1 extends ChainSignatureContract {
|
|
@@ -1606,8 +1607,8 @@ declare class ChainSignatureContract$1 extends ChainSignatureContract {
|
|
|
1606
1607
|
}): Promise<TransactionInstruction>;
|
|
1607
1608
|
/**
|
|
1608
1609
|
* Sends a transaction to the program to request a signature, then
|
|
1609
|
-
*
|
|
1610
|
-
*
|
|
1610
|
+
* races a WebSocket listener against polling backfill to find the result.
|
|
1611
|
+
* If the signature is not found within the timeout, it will throw an error.
|
|
1611
1612
|
*/
|
|
1612
1613
|
sign(args: SignArgs, options?: Partial<SignOptions> & {
|
|
1613
1614
|
remainingAccounts?: AccountMeta[];
|
|
@@ -1615,39 +1616,27 @@ declare class ChainSignatureContract$1 extends ChainSignatureContract {
|
|
|
1615
1616
|
}): Promise<RSVSignature>;
|
|
1616
1617
|
private sendAndConfirmWithoutWebSocket;
|
|
1617
1618
|
/**
|
|
1618
|
-
*
|
|
1619
|
-
*
|
|
1619
|
+
* Waits for a specific event matching the given requestId by combining
|
|
1620
|
+
* a WebSocket listener (real-time) with polling backfill (resilience).
|
|
1620
1621
|
*/
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
payload: _payload,
|
|
1624
|
-
path: _path,
|
|
1625
|
-
afterSignature,
|
|
1626
|
-
options
|
|
1627
|
-
}: {
|
|
1622
|
+
waitForEvent<E extends ChainSignaturesEventName>(options: {
|
|
1623
|
+
eventName: E;
|
|
1628
1624
|
requestId: string;
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
private
|
|
1638
|
-
private
|
|
1625
|
+
signer: PublicKey;
|
|
1626
|
+
afterSignature?: string;
|
|
1627
|
+
timeoutMs?: number;
|
|
1628
|
+
backfillIntervalMs?: number;
|
|
1629
|
+
backfillLimit?: number;
|
|
1630
|
+
signal?: AbortSignal;
|
|
1631
|
+
}): Promise<EventResult<E>>;
|
|
1632
|
+
private mapRespondToResult;
|
|
1633
|
+
private mapRespondErrorToResult;
|
|
1634
|
+
private mapRespondBidirectionalToResult;
|
|
1635
|
+
private mapEventForName;
|
|
1639
1636
|
/**
|
|
1640
1637
|
* Generates the request ID for a signature request allowing to track the response.
|
|
1641
1638
|
*/
|
|
1642
1639
|
getRequestId(args: SignArgs, options?: SignOptions['sign']): string;
|
|
1643
|
-
/**
|
|
1644
|
-
* Subscribes to program events using Anchor's EventParser for regular events,
|
|
1645
|
-
* and CPI parsing for emit_cpi!-emitted events. Returns an unsubscribe fn.
|
|
1646
|
-
*/
|
|
1647
|
-
subscribeToEvents(handlers: {
|
|
1648
|
-
onSignatureResponded?: (event: SignatureRespondedEvent, slot: number) => Promise<void> | void;
|
|
1649
|
-
onSignatureError?: (event: SignatureErrorEvent, slot: number) => Promise<void> | void;
|
|
1650
|
-
}): Promise<() => Promise<void>>;
|
|
1651
1640
|
}
|
|
1652
1641
|
declare namespace index_d_exports$4 {
|
|
1653
1642
|
export { ChainSignatureContract$1 as ChainSignatureContract, ChainSignaturesProject, utils };
|
package/dist/index.js
CHANGED
|
@@ -2652,24 +2652,33 @@ const EMIT_CPI_INSTRUCTION_DISCRIMINATOR = Buffer.from([
|
|
|
2652
2652
|
]);
|
|
2653
2653
|
var CpiEventParser = class {
|
|
2654
2654
|
/**
|
|
2655
|
-
* Parse CPI events from
|
|
2655
|
+
* Parse CPI events from an already-fetched transaction (emit_cpi! pattern).
|
|
2656
2656
|
*/
|
|
2657
|
-
static
|
|
2657
|
+
static parseCpiEventsFromTransaction(tx, targetProgramId, program) {
|
|
2658
2658
|
const events$1 = [];
|
|
2659
|
+
if (!tx?.meta?.innerInstructions) return events$1;
|
|
2660
|
+
for (const innerIxSet of tx.meta.innerInstructions) for (const instruction of innerIxSet.instructions) {
|
|
2661
|
+
if (!("programId" in instruction) || !("data" in instruction)) continue;
|
|
2662
|
+
if (instruction.programId.toString() !== targetProgramId) continue;
|
|
2663
|
+
const parsedEvent = this.parseInstruction(instruction.data, program);
|
|
2664
|
+
if (parsedEvent) events$1.push(parsedEvent);
|
|
2665
|
+
}
|
|
2666
|
+
return events$1;
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Fetch a transaction by signature and parse its CPI events.
|
|
2670
|
+
* Used by the subscription path where only the signature is available.
|
|
2671
|
+
*/
|
|
2672
|
+
static async fetchAndParseCpiEvents(connection, signature, targetProgramId, program) {
|
|
2659
2673
|
try {
|
|
2660
2674
|
const tx = await connection.getParsedTransaction(signature, {
|
|
2661
2675
|
commitment: "confirmed",
|
|
2662
2676
|
maxSupportedTransactionVersion: 0
|
|
2663
2677
|
});
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
const parsedEvent = this.parseInstruction(instruction.data, program);
|
|
2669
|
-
if (parsedEvent) events$1.push(parsedEvent);
|
|
2670
|
-
}
|
|
2671
|
-
} catch {}
|
|
2672
|
-
return events$1;
|
|
2678
|
+
return this.parseCpiEventsFromTransaction(tx, targetProgramId, program);
|
|
2679
|
+
} catch {
|
|
2680
|
+
return [];
|
|
2681
|
+
}
|
|
2673
2682
|
}
|
|
2674
2683
|
/**
|
|
2675
2684
|
* Parse CPI event from instruction data
|
|
@@ -2699,7 +2708,7 @@ var CpiEventParser = class {
|
|
|
2699
2708
|
return connection.onLogs(program.programId, (logs, context) => {
|
|
2700
2709
|
if (logs.err) return;
|
|
2701
2710
|
(async () => {
|
|
2702
|
-
const events$1 = await this.
|
|
2711
|
+
const events$1 = await this.fetchAndParseCpiEvents(connection, logs.signature, program.programId.toString(), program);
|
|
2703
2712
|
for (const event of events$1) {
|
|
2704
2713
|
const handler = eventHandlers.get(event.name);
|
|
2705
2714
|
if (handler) try {
|
|
@@ -2799,15 +2808,15 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2799
2808
|
}
|
|
2800
2809
|
/**
|
|
2801
2810
|
* Sends a transaction to the program to request a signature, then
|
|
2802
|
-
*
|
|
2803
|
-
*
|
|
2811
|
+
* races a WebSocket listener against polling backfill to find the result.
|
|
2812
|
+
* If the signature is not found within the timeout, it will throw an error.
|
|
2804
2813
|
*/
|
|
2805
2814
|
async sign(args, options) {
|
|
2806
2815
|
const algo = options?.sign?.algo ?? "";
|
|
2807
2816
|
const dest = options?.sign?.dest ?? "";
|
|
2808
2817
|
const params = options?.sign?.params ?? "";
|
|
2809
2818
|
const delay = options?.retry?.delay ?? 5e3;
|
|
2810
|
-
const
|
|
2819
|
+
const timeoutMs = delay * (options?.retry?.retryCount ?? 12);
|
|
2811
2820
|
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");
|
|
2812
2821
|
const requestId = this.getRequestId(args, {
|
|
2813
2822
|
algo,
|
|
@@ -2825,24 +2834,38 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2825
2834
|
const transaction = new Transaction().add(instruction);
|
|
2826
2835
|
transaction.feePayer = this.provider.wallet.publicKey;
|
|
2827
2836
|
const hash = await this.sendAndConfirmWithoutWebSocket(transaction, options?.remainingSigners);
|
|
2837
|
+
const controller = new AbortController();
|
|
2838
|
+
const successPromise = this.waitForEvent({
|
|
2839
|
+
eventName: "signatureRespondedEvent",
|
|
2840
|
+
requestId,
|
|
2841
|
+
signer: this.programId,
|
|
2842
|
+
afterSignature: hash,
|
|
2843
|
+
timeoutMs,
|
|
2844
|
+
backfillIntervalMs: delay,
|
|
2845
|
+
signal: controller.signal
|
|
2846
|
+
});
|
|
2847
|
+
const errorPromise = this.waitForEvent({
|
|
2848
|
+
eventName: "signatureErrorEvent",
|
|
2849
|
+
requestId,
|
|
2850
|
+
signer: this.programId,
|
|
2851
|
+
afterSignature: hash,
|
|
2852
|
+
timeoutMs,
|
|
2853
|
+
backfillIntervalMs: delay,
|
|
2854
|
+
signal: controller.signal
|
|
2855
|
+
}).then((err) => {
|
|
2856
|
+
throw new SignatureContractError(err.error, requestId, { hash });
|
|
2857
|
+
});
|
|
2858
|
+
successPromise.catch(() => {});
|
|
2859
|
+
errorPromise.catch(() => {});
|
|
2828
2860
|
try {
|
|
2829
|
-
const
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
path: args.path,
|
|
2833
|
-
afterSignature: hash,
|
|
2834
|
-
options: {
|
|
2835
|
-
delay,
|
|
2836
|
-
retryCount
|
|
2837
|
-
}
|
|
2838
|
-
});
|
|
2839
|
-
if (!pollResult) throw new SignatureNotFoundError(requestId, { hash });
|
|
2840
|
-
if ("error" in pollResult) throw new SignatureContractError(pollResult.error, requestId, { hash });
|
|
2841
|
-
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"));
|
|
2842
|
-
return pollResult;
|
|
2861
|
+
const result = await Promise.race([successPromise, errorPromise]);
|
|
2862
|
+
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"));
|
|
2863
|
+
return result;
|
|
2843
2864
|
} catch (error) {
|
|
2844
2865
|
if (error instanceof SignatureNotFoundError || error instanceof SignatureContractError) throw error;
|
|
2845
2866
|
else throw new SigningError(requestId, { hash }, error instanceof Error ? error : void 0);
|
|
2867
|
+
} finally {
|
|
2868
|
+
controller.abort();
|
|
2846
2869
|
}
|
|
2847
2870
|
}
|
|
2848
2871
|
async sendAndConfirmWithoutWebSocket(transaction, signers) {
|
|
@@ -2866,70 +2889,147 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2866
2889
|
throw new TransactionExpiredTimeoutError(signature, timeout / 1e3);
|
|
2867
2890
|
}
|
|
2868
2891
|
/**
|
|
2869
|
-
*
|
|
2870
|
-
*
|
|
2892
|
+
* Waits for a specific event matching the given requestId by combining
|
|
2893
|
+
* a WebSocket listener (real-time) with polling backfill (resilience).
|
|
2871
2894
|
*/
|
|
2872
|
-
async
|
|
2873
|
-
const
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2895
|
+
async waitForEvent(options) {
|
|
2896
|
+
const { eventName, requestId, signer, afterSignature, timeoutMs = 6e4, backfillIntervalMs = 5e3, backfillLimit = 50, signal } = options;
|
|
2897
|
+
return await new Promise((resolve, reject) => {
|
|
2898
|
+
let settled = false;
|
|
2899
|
+
const seenSignatures = /* @__PURE__ */ new Set();
|
|
2900
|
+
let lastCheckedSignature = afterSignature;
|
|
2901
|
+
const cleanupFns = [];
|
|
2902
|
+
const cleanup = () => {
|
|
2903
|
+
for (const fn of cleanupFns) try {
|
|
2904
|
+
fn();
|
|
2905
|
+
} catch {}
|
|
2906
|
+
};
|
|
2907
|
+
const settle = (action) => {
|
|
2908
|
+
if (settled) return;
|
|
2909
|
+
settled = true;
|
|
2910
|
+
cleanup();
|
|
2911
|
+
action();
|
|
2912
|
+
};
|
|
2913
|
+
const processEvent = (name, data, txSignature) => {
|
|
2914
|
+
if (settled) return false;
|
|
2915
|
+
if (txSignature && seenSignatures.has(txSignature)) return false;
|
|
2916
|
+
if (txSignature) seenSignatures.add(txSignature);
|
|
2917
|
+
if (name !== eventName) return false;
|
|
2918
|
+
const result = this.mapEventForName(eventName, data, requestId);
|
|
2919
|
+
if (result !== void 0) {
|
|
2920
|
+
settle(() => {
|
|
2921
|
+
resolve(result);
|
|
2887
2922
|
});
|
|
2888
|
-
|
|
2889
|
-
const result = await this.parseLogsForEvents(tx.meta.logMessages, requestId, sig.signature);
|
|
2890
|
-
if (result) return result;
|
|
2891
|
-
}
|
|
2923
|
+
return true;
|
|
2892
2924
|
}
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2925
|
+
return false;
|
|
2926
|
+
};
|
|
2927
|
+
if (signal) {
|
|
2928
|
+
if (signal.aborted) {
|
|
2929
|
+
settle(() => {
|
|
2930
|
+
reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2931
|
+
});
|
|
2932
|
+
return;
|
|
2933
|
+
}
|
|
2934
|
+
const onAbort = () => {
|
|
2935
|
+
settle(() => {
|
|
2936
|
+
reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2937
|
+
});
|
|
2938
|
+
};
|
|
2939
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2940
|
+
cleanupFns.push(() => {
|
|
2941
|
+
signal.removeEventListener("abort", onAbort);
|
|
2942
|
+
});
|
|
2899
2943
|
}
|
|
2900
|
-
|
|
2944
|
+
const timeoutId = setTimeout(() => {
|
|
2945
|
+
settle(() => {
|
|
2946
|
+
reject(new SignatureNotFoundError(requestId));
|
|
2947
|
+
});
|
|
2948
|
+
}, timeoutMs);
|
|
2949
|
+
cleanupFns.push(() => {
|
|
2950
|
+
clearTimeout(timeoutId);
|
|
2951
|
+
});
|
|
2952
|
+
const parser = new EventParser(this.program.programId, this.program.coder);
|
|
2953
|
+
const subId = this.connection.onLogs(signer, (logs, _context) => {
|
|
2954
|
+
if (settled) return;
|
|
2955
|
+
if (logs.err) return;
|
|
2956
|
+
for (const evt of parser.parseLogs(logs.logs)) {
|
|
2957
|
+
if (!evt) continue;
|
|
2958
|
+
if (processEvent(evt.name, evt.data, logs.signature)) return;
|
|
2959
|
+
}
|
|
2960
|
+
CpiEventParser.fetchAndParseCpiEvents(this.connection, logs.signature, this.programId.toString(), this.program).then((cpiEvents) => {
|
|
2961
|
+
for (const event of cpiEvents) if (processEvent(event.name, event.data, logs.signature)) return;
|
|
2962
|
+
});
|
|
2963
|
+
}, "confirmed");
|
|
2964
|
+
cleanupFns.push(() => {
|
|
2965
|
+
this.connection.removeOnLogsListener(subId);
|
|
2966
|
+
});
|
|
2967
|
+
const runBackfill = async () => {
|
|
2968
|
+
if (settled) return;
|
|
2969
|
+
try {
|
|
2970
|
+
const signatures = await this.connection.getSignaturesForAddress(signer, {
|
|
2971
|
+
until: lastCheckedSignature,
|
|
2972
|
+
limit: backfillLimit
|
|
2973
|
+
}, "confirmed");
|
|
2974
|
+
if (signatures.length > 0) lastCheckedSignature = signatures[0].signature;
|
|
2975
|
+
for (const sig of signatures) {
|
|
2976
|
+
if (settled) return;
|
|
2977
|
+
if (seenSignatures.has(sig.signature)) continue;
|
|
2978
|
+
const tx = await this.connection.getParsedTransaction(sig.signature, {
|
|
2979
|
+
commitment: "confirmed",
|
|
2980
|
+
maxSupportedTransactionVersion: 0
|
|
2981
|
+
});
|
|
2982
|
+
if (!tx) continue;
|
|
2983
|
+
const cpiEvents = CpiEventParser.parseCpiEventsFromTransaction(tx, this.programId.toString(), this.program);
|
|
2984
|
+
for (const event of cpiEvents) if (processEvent(event.name, event.data, sig.signature)) return;
|
|
2985
|
+
const logs = tx.meta?.logMessages;
|
|
2986
|
+
if (logs) for (const evt of parser.parseLogs(logs)) {
|
|
2987
|
+
if (!evt) continue;
|
|
2988
|
+
if (processEvent(evt.name, evt.data, sig.signature)) return;
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
} catch {}
|
|
2992
|
+
};
|
|
2993
|
+
runBackfill();
|
|
2994
|
+
const intervalId = setInterval(() => {
|
|
2995
|
+
runBackfill();
|
|
2996
|
+
}, backfillIntervalMs);
|
|
2997
|
+
cleanupFns.push(() => {
|
|
2998
|
+
clearInterval(intervalId);
|
|
2999
|
+
});
|
|
3000
|
+
});
|
|
2901
3001
|
}
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
if (mapped) return mapped;
|
|
2910
|
-
}
|
|
2911
|
-
const parser = new EventParser(this.program.programId, this.program.coder);
|
|
2912
|
-
for (const evt of parser.parseLogs(logs)) {
|
|
2913
|
-
if (!evt) continue;
|
|
2914
|
-
const mapped = this.mapEventToResult(evt.name, evt.name === "signatureRespondedEvent" ? evt.data : evt.data, requestId);
|
|
2915
|
-
if (mapped) return mapped;
|
|
2916
|
-
}
|
|
3002
|
+
mapRespondToResult(data, requestId) {
|
|
3003
|
+
if ("0x" + Buffer.from(data.requestId).toString("hex") !== requestId) return void 0;
|
|
3004
|
+
return {
|
|
3005
|
+
r: Buffer.from(data.signature.bigR.x).toString("hex"),
|
|
3006
|
+
s: Buffer.from(data.signature.s).toString("hex"),
|
|
3007
|
+
v: data.signature.recoveryId + 27
|
|
3008
|
+
};
|
|
2917
3009
|
}
|
|
2918
|
-
|
|
3010
|
+
mapRespondErrorToResult(data, requestId) {
|
|
2919
3011
|
const eventRequestIdHex = "0x" + Buffer.from(data.requestId).toString("hex");
|
|
2920
|
-
if (
|
|
2921
|
-
|
|
2922
|
-
return {
|
|
2923
|
-
r: Buffer.from(d.signature.bigR.x).toString("hex"),
|
|
2924
|
-
s: Buffer.from(d.signature.s).toString("hex"),
|
|
2925
|
-
v: d.signature.recoveryId + 27
|
|
2926
|
-
};
|
|
2927
|
-
}
|
|
2928
|
-
if (name === "signatureErrorEvent" && eventRequestIdHex === requestId) return {
|
|
3012
|
+
if (eventRequestIdHex !== requestId) return void 0;
|
|
3013
|
+
return {
|
|
2929
3014
|
requestId: eventRequestIdHex,
|
|
2930
3015
|
error: data.error
|
|
2931
3016
|
};
|
|
2932
3017
|
}
|
|
3018
|
+
mapRespondBidirectionalToResult(data, requestId) {
|
|
3019
|
+
if ("0x" + Buffer.from(data.requestId).toString("hex") !== requestId) return void 0;
|
|
3020
|
+
return {
|
|
3021
|
+
serializedOutput: data.serializedOutput,
|
|
3022
|
+
signature: data.signature
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
mapEventForName(eventName, data, requestId) {
|
|
3026
|
+
switch (eventName) {
|
|
3027
|
+
case "signatureRespondedEvent": return this.mapRespondToResult(data, requestId);
|
|
3028
|
+
case "signatureErrorEvent": return this.mapRespondErrorToResult(data, requestId);
|
|
3029
|
+
case "respondBidirectionalEvent": return this.mapRespondBidirectionalToResult(data, requestId);
|
|
3030
|
+
default: return;
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
2933
3033
|
/**
|
|
2934
3034
|
* Generates the request ID for a signature request allowing to track the response.
|
|
2935
3035
|
*/
|
|
@@ -2949,46 +3049,6 @@ var ChainSignatureContract$1 = class extends ChainSignatureContract {
|
|
|
2949
3049
|
chainId: KDF_CHAIN_IDS.SOLANA
|
|
2950
3050
|
});
|
|
2951
3051
|
}
|
|
2952
|
-
/**
|
|
2953
|
-
* Subscribes to program events using Anchor's EventParser for regular events,
|
|
2954
|
-
* and CPI parsing for emit_cpi!-emitted events. Returns an unsubscribe fn.
|
|
2955
|
-
*/
|
|
2956
|
-
async subscribeToEvents(handlers) {
|
|
2957
|
-
const commitment = "confirmed";
|
|
2958
|
-
const cpiHandlers = /* @__PURE__ */ new Map();
|
|
2959
|
-
if (handlers.onSignatureResponded) {
|
|
2960
|
-
const onSignatureResponded = handlers.onSignatureResponded;
|
|
2961
|
-
cpiHandlers.set("signatureRespondedEvent", async (e, s) => {
|
|
2962
|
-
await onSignatureResponded(e, s);
|
|
2963
|
-
});
|
|
2964
|
-
}
|
|
2965
|
-
if (handlers.onSignatureError) {
|
|
2966
|
-
const onSignatureError = handlers.onSignatureError;
|
|
2967
|
-
cpiHandlers.set("signatureErrorEvent", async (e, s) => {
|
|
2968
|
-
await onSignatureError(e, s);
|
|
2969
|
-
});
|
|
2970
|
-
}
|
|
2971
|
-
const cpiSubId = CpiEventParser.subscribeToCpiEvents(this.connection, this.program, cpiHandlers);
|
|
2972
|
-
const parser = new EventParser(this.program.programId, this.program.coder);
|
|
2973
|
-
const subId = this.connection.onLogs(this.program.programId, (logs, context) => {
|
|
2974
|
-
if (logs.err) return;
|
|
2975
|
-
for (const evt of parser.parseLogs(logs.logs)) {
|
|
2976
|
-
if (!evt) continue;
|
|
2977
|
-
if (evt.name === "signatureRespondedEvent") {
|
|
2978
|
-
const onSignatureResponded = handlers.onSignatureResponded;
|
|
2979
|
-
if (onSignatureResponded) onSignatureResponded(evt.data, context.slot);
|
|
2980
|
-
}
|
|
2981
|
-
if (evt.name === "signatureErrorEvent") {
|
|
2982
|
-
const onSignatureError = handlers.onSignatureError;
|
|
2983
|
-
if (onSignatureError) onSignatureError(evt.data, context.slot);
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2986
|
-
}, commitment);
|
|
2987
|
-
return async () => {
|
|
2988
|
-
await this.connection.removeOnLogsListener(subId);
|
|
2989
|
-
await this.connection.removeOnLogsListener(cpiSubId);
|
|
2990
|
-
};
|
|
2991
|
-
}
|
|
2992
3052
|
};
|
|
2993
3053
|
|
|
2994
3054
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signet.js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A TypeScript library for handling multi-chain transactions and signatures using Signet MPC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"docs:dev": "vocs dev",
|
|
38
38
|
"docs:build": "vocs build",
|
|
39
39
|
"docs:preview": "vocs preview",
|
|
40
|
-
"format": "prettier --write ."
|
|
40
|
+
"format": "prettier --write .",
|
|
41
|
+
"lint": "eslint 'src/**/*.ts'",
|
|
42
|
+
"typecheck": "tsc --noEmit"
|
|
41
43
|
},
|
|
42
44
|
"author": "Sig Network",
|
|
43
45
|
"license": "MIT",
|