signet.js 0.0.12 → 0.2.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 ADDED
@@ -0,0 +1,3080 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (all, symbols) => {
9
+ let target = {};
10
+ for (var name in all) {
11
+ __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ }
16
+ if (symbols) {
17
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ }
19
+ return target;
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
24
+ key = keys[i];
25
+ if (!__hasOwnProp.call(to, key) && key !== except) {
26
+ __defProp(to, key, {
27
+ get: ((k) => from[k]).bind(null, key),
28
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
29
+ });
30
+ }
31
+ }
32
+ }
33
+ return to;
34
+ };
35
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
36
+ value: mod,
37
+ enumerable: true
38
+ }) : target, mod));
39
+
40
+ //#endregion
41
+ let __scure_base = require("@scure/base");
42
+ let elliptic = require("elliptic");
43
+ elliptic = __toESM(elliptic);
44
+ let viem = require("viem");
45
+ let bitcoinjs_lib = require("bitcoinjs-lib");
46
+ bitcoinjs_lib = __toESM(bitcoinjs_lib);
47
+ let coinselect = require("coinselect");
48
+ coinselect = __toESM(coinselect);
49
+ let __cosmjs_amino = require("@cosmjs/amino");
50
+ let __cosmjs_crypto = require("@cosmjs/crypto");
51
+ let __cosmjs_encoding = require("@cosmjs/encoding");
52
+ let __cosmjs_proto_signing = require("@cosmjs/proto-signing");
53
+ let __cosmjs_stargate = require("@cosmjs/stargate");
54
+ let bech32 = require("bech32");
55
+ let cosmjs_types_cosmos_tx_signing_v1beta1_signing_js = require("cosmjs-types/cosmos/tx/signing/v1beta1/signing.js");
56
+ let cosmjs_types_cosmos_tx_v1beta1_tx_js = require("cosmjs-types/cosmos/tx/v1beta1/tx.js");
57
+ let chain_registry = require("chain-registry");
58
+ let bn_js = require("bn.js");
59
+ bn_js = __toESM(bn_js);
60
+ require("viem/chains");
61
+ let __coral_xyz_anchor = require("@coral-xyz/anchor");
62
+ __coral_xyz_anchor = __toESM(__coral_xyz_anchor);
63
+ let __solana_web3_js = require("@solana/web3.js");
64
+
65
+ //#region src/constants.ts
66
+ var constants_exports = /* @__PURE__ */ __export({
67
+ CHAINS: () => CHAINS,
68
+ CONTRACT_ADDRESSES: () => CONTRACT_ADDRESSES,
69
+ ENVS: () => ENVS,
70
+ KDF_CHAIN_IDS: () => KDF_CHAIN_IDS,
71
+ ROOT_PUBLIC_KEYS: () => ROOT_PUBLIC_KEYS
72
+ });
73
+ const ENVS = {
74
+ TESTNET_DEV: "TESTNET_DEV",
75
+ TESTNET: "TESTNET",
76
+ MAINNET: "MAINNET"
77
+ };
78
+ const CHAINS = {
79
+ ETHEREUM: "ETHEREUM",
80
+ SOLANA: "SOLANA"
81
+ };
82
+ /**
83
+ * Root public keys for the Sig Network Smart Contracts across different environments.
84
+ *
85
+ * These keys should never change.
86
+ */
87
+ const ROOT_PUBLIC_KEYS = {
88
+ [ENVS.TESTNET_DEV]: "secp256k1:54hU5wcCmVUPFWLDALXMh1fFToZsVXrx9BbTbHzSfQq1Kd1rJZi52iPa4QQxo6s5TgjWqgpY8HamYuUDzG6fAaUq",
89
+ [ENVS.TESTNET]: "secp256k1:3Ww8iFjqTHufye5aRGUvrQqETegR4gVUcW8FX5xzscaN9ENhpkffojsxJwi6N1RbbHMTxYa9UyKeqK3fsMuwxjR5",
90
+ [ENVS.MAINNET]: "secp256k1:4tY4qMzusmgX5wYdG35663Y3Qar3CTbpApotwk9ZKLoF79XA4DjG8XoByaKdNHKQX9Lz5hd7iJqsWdTKyA7dKa6Z"
91
+ };
92
+ /**
93
+ * Chain IDs used in the key derivation function (KDF) for deriving child public keys to
94
+ * distinguish between different chains.
95
+ *
96
+ * @see {@link deriveChildPublicKey} in cryptography.ts for usage details
97
+ */
98
+ const KDF_CHAIN_IDS = {
99
+ [CHAINS.ETHEREUM]: "eip155:1",
100
+ [CHAINS.SOLANA]: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
101
+ };
102
+ /**
103
+ * Contract addresses for different chains and environments.
104
+ *
105
+ * - Testnet Dev: Used for internal development, very unstable
106
+ * - Testnet: Used for external development, stable
107
+ * - Mainnet: Production contract address
108
+ *
109
+ * @see ChainSignatureContract documentation for implementation details
110
+ */
111
+ const CONTRACT_ADDRESSES = {
112
+ [CHAINS.ETHEREUM]: {
113
+ [ENVS.TESTNET_DEV]: "0x69C6b28Fdc74618817fa380De29a653060e14009",
114
+ [ENVS.TESTNET]: "0x83458E8Bf8206131Fe5c05127007FA164c0948A2",
115
+ [ENVS.MAINNET]: "0xf8bdC0612361a1E49a8E01423d4C0cFc5dF4791A"
116
+ },
117
+ [CHAINS.SOLANA]: {
118
+ [ENVS.TESTNET_DEV]: "SigDuEPNeDjh3oJv7MUraPN7zaTFomS6ZWfpXwjUg4B",
119
+ [ENVS.TESTNET]: "SigTVbfRK9LsXWpSv9KgpabrQcFKr5hDdUwMhYsXyKg",
120
+ [ENVS.MAINNET]: "SigMcRMjKfnC7RDG5q4yUMZM1s5KJ9oYTPP4NmJRDRw"
121
+ }
122
+ };
123
+
124
+ //#endregion
125
+ //#region src/utils/cryptography.ts
126
+ var cryptography_exports = /* @__PURE__ */ __export({
127
+ compressPubKey: () => compressPubKey,
128
+ deriveChildPublicKey: () => deriveChildPublicKey,
129
+ najToUncompressedPubKeySEC1: () => najToUncompressedPubKeySEC1,
130
+ toRSV: () => toRSV,
131
+ verifyRecoveredAddress: () => verifyRecoveredAddress
132
+ });
133
+ const { ec: EC } = elliptic.default;
134
+ const toRSV = (signature) => {
135
+ if ("bigR" in signature && "x" in signature.bigR && "s" in signature && typeof signature.s === "bigint") return {
136
+ r: signature.bigR.x.toString(16).padStart(64, "0"),
137
+ s: signature.s.toString(16).padStart(64, "0"),
138
+ v: signature.recoveryId + 27
139
+ };
140
+ throw new Error("Invalid signature format");
141
+ };
142
+ /**
143
+ * Compresses an uncompressed public key to its compressed format following SEC1 standards.
144
+ * In SEC1, a compressed public key consists of a prefix (02 or 03) followed by the x-coordinate.
145
+ * The prefix indicates whether the y-coordinate is even (02) or odd (03).
146
+ *
147
+ * @param uncompressedPubKeySEC1 - The uncompressed public key in hex format, with or without '04' prefix
148
+ * @returns The compressed public key in hex format
149
+ * @throws Error if the uncompressed public key length is invalid
150
+ */
151
+ const compressPubKey = (uncompressedPubKeySEC1) => {
152
+ const slicedPubKey = uncompressedPubKeySEC1.slice(2);
153
+ if (slicedPubKey.length !== 128) throw new Error("Invalid uncompressed public key length");
154
+ const x = slicedPubKey.slice(0, 64);
155
+ const y = slicedPubKey.slice(64);
156
+ return (parseInt(y.slice(-1), 16) % 2 === 0 ? "02" : "03") + x;
157
+ };
158
+ /**
159
+ * Converts a NAJ public key to an uncompressed SEC1 public key.
160
+ *
161
+ * @param najPublicKey - The NAJ public key to convert (e.g. secp 256k1:3Ww8iFjqTHufye5aRGUvrQqETegR4gVUcW8FX5xzscaN9ENhpkffojsxJwi6N1RbbHMTxYa9UyKeqK3fsMuwxjR5)
162
+ * @returns The uncompressed SEC1 public key (e.g. 04 || x || y)
163
+ */
164
+ const najToUncompressedPubKeySEC1 = (najPublicKey) => {
165
+ const decodedKey = __scure_base.base58.decode(najPublicKey.split(":")[1]);
166
+ return `04${Buffer.from(decodedKey).toString("hex")}`;
167
+ };
168
+ const EPSILON_DERIVATION_PREFIX_V2 = "sig.network v2.0.0 epsilon derivation";
169
+ /**
170
+ * Derives a child public key from a parent public key using the Sig.Network epsilon derivation scheme.
171
+ * The parent public keys are defined in @constants.ts
172
+ *
173
+ * @param rootUncompressedPubKeySEC1 - The parent public key in uncompressed SEC1 format (e.g. 04 || x || y)
174
+ * @param predecessorId - The predecessor ID is the address of the account calling the signer contract (e.g EOA or Contract Address)
175
+ * @param path - Optional derivation path suffix (defaults to empty string)
176
+ * @param chainId - CAIP-2 chain identifier used for derivation
177
+ * @param keyVersion - Key version controlling which derivation prefix to use (legacy v1 for 0, CAIP-2 v2 otherwise)
178
+ * @returns The derived child public key in uncompressed SEC1 format (04 || x || y)
179
+ */
180
+ function deriveChildPublicKey(rootUncompressedPubKeySEC1, predecessorId, path = "", chainId, keyVersion) {
181
+ const ec = new EC("secp256k1");
182
+ const derivationPath = `${EPSILON_DERIVATION_PREFIX_V2}:${chainId}:${predecessorId}:${path}`;
183
+ let scalarHex = "";
184
+ if (chainId === KDF_CHAIN_IDS.ETHEREUM) scalarHex = (0, viem.keccak256)(Buffer.from(derivationPath)).slice(2);
185
+ else if (chainId === KDF_CHAIN_IDS.SOLANA) scalarHex = (0, viem.keccak256)(Buffer.from(derivationPath)).slice(2);
186
+ else throw new Error("Invalid chain ID");
187
+ const x = rootUncompressedPubKeySEC1.substring(2, 66);
188
+ const y = rootUncompressedPubKeySEC1.substring(66);
189
+ const oldPublicKeyPoint = ec.curve.point(x, y);
190
+ const scalarTimesG = ec.g.mul(scalarHex);
191
+ const newPublicKeyPoint = oldPublicKeyPoint.add(scalarTimesG);
192
+ return `04${newPublicKeyPoint.getX().toString("hex").padStart(64, "0")}${newPublicKeyPoint.getY().toString("hex").padStart(64, "0")}`;
193
+ }
194
+ /**
195
+ * Verifies that a secp256k1 signature was created by the expected derived address
196
+ * by recovering the signing address and comparing it with the address derived from the contract.
197
+ *
198
+ * @param signature - The RSV signature to verify
199
+ * @param payload - The original message that was signed (as byte array)
200
+ * @param requesterAddress - The address of the requester
201
+ * @param path - The derivation path used for key generation
202
+ * @param contract - The contract instance for deriving addresses
203
+ * @returns Promise resolving to true if the recovered address matches the expected address
204
+ */
205
+ async function verifyRecoveredAddress(signature, payload, requesterAddress, path, contract, keyVersion) {
206
+ try {
207
+ const { address: expectedAddress } = await new EVM({
208
+ publicClient: (0, viem.createPublicClient)({ transport: (0, viem.http)("https://dontcare.com") }),
209
+ contract
210
+ }).deriveAddressAndPublicKey(requesterAddress, path, keyVersion);
211
+ return (await (0, viem.recoverAddress)({
212
+ hash: new Uint8Array(payload),
213
+ signature: {
214
+ r: `0x${signature.r}`,
215
+ s: `0x${signature.s}`,
216
+ yParity: signature.v
217
+ }
218
+ })).toLowerCase() === expectedAddress.toLowerCase();
219
+ } catch (error) {
220
+ console.error("Signature verification failed:", error);
221
+ return false;
222
+ }
223
+ }
224
+
225
+ //#endregion
226
+ //#region src/utils/index.ts
227
+ var utils_exports = /* @__PURE__ */ __export({ cryptography: () => cryptography_exports });
228
+
229
+ //#endregion
230
+ //#region src/chain-adapters/ChainAdapter.ts
231
+ var ChainAdapter = class {};
232
+
233
+ //#endregion
234
+ //#region src/chain-adapters/EVM/utils.ts
235
+ async function fetchEVMFeeProperties(client, transaction) {
236
+ const [gas, feeData] = await Promise.all([client.estimateGas(transaction), client.estimateFeesPerGas()]);
237
+ return {
238
+ gas,
239
+ maxFeePerGas: feeData.maxFeePerGas ?? BigInt(1e10),
240
+ maxPriorityFeePerGas: feeData.maxPriorityFeePerGas ?? BigInt(1e10)
241
+ };
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/chain-adapters/EVM/EVM.ts
246
+ /**
247
+ * Implementation of the ChainAdapter interface for EVM-compatible networks.
248
+ * Handles interactions with Ethereum Virtual Machine based blockchains like Ethereum, BSC, Polygon, etc.
249
+ */
250
+ var EVM = class extends ChainAdapter {
251
+ /**
252
+ * Creates a new EVM chain instance
253
+ * @param params - Configuration parameters
254
+ * @param params.publicClient - A Viem PublicClient instance for reading from the blockchain
255
+ * @param params.contract - Instance of the chain signature contract for MPC operations
256
+ */
257
+ constructor({ publicClient, contract }) {
258
+ super();
259
+ this.contract = contract;
260
+ this.client = publicClient;
261
+ }
262
+ async attachGasAndNonce(transaction) {
263
+ const fees = await fetchEVMFeeProperties(this.client, transaction);
264
+ const nonce = await this.client.getTransactionCount({ address: transaction.from });
265
+ const { from, ...rest } = transaction;
266
+ return {
267
+ ...fees,
268
+ nonce,
269
+ chainId: Number(await this.client.getChainId()),
270
+ type: "eip1559",
271
+ ...rest
272
+ };
273
+ }
274
+ transformRSVSignature(signature) {
275
+ return {
276
+ r: `0x${signature.r}`,
277
+ s: `0x${signature.s}`,
278
+ yParity: signature.v - 27
279
+ };
280
+ }
281
+ assembleSignature(signature) {
282
+ const { r, s, yParity } = this.transformRSVSignature(signature);
283
+ if (yParity === void 0) throw new Error("Missing yParity");
284
+ return (0, viem.concatHex)([
285
+ r,
286
+ s,
287
+ (0, viem.numberToHex)(yParity + 27, { size: 1 })
288
+ ]);
289
+ }
290
+ async deriveAddressAndPublicKey(predecessor, path, keyVersion) {
291
+ const uncompressedPubKey = await this.contract.getDerivedPublicKey({
292
+ path,
293
+ predecessor,
294
+ keyVersion
295
+ });
296
+ if (!uncompressedPubKey) throw new Error("Failed to get derived public key");
297
+ const publicKeyNoPrefix = uncompressedPubKey.startsWith("04") ? uncompressedPubKey.slice(2) : uncompressedPubKey;
298
+ return {
299
+ address: (0, viem.getAddress)(`0x${(0, viem.keccak256)(Buffer.from(publicKeyNoPrefix, "hex")).slice(-40)}`),
300
+ publicKey: uncompressedPubKey
301
+ };
302
+ }
303
+ async getBalance(address$1) {
304
+ return {
305
+ balance: await this.client.getBalance({ address: address$1 }),
306
+ decimals: 18
307
+ };
308
+ }
309
+ serializeTransaction(transaction) {
310
+ return (0, viem.serializeTransaction)(transaction);
311
+ }
312
+ deserializeTransaction(serialized) {
313
+ return (0, viem.parseTransaction)(serialized);
314
+ }
315
+ async prepareTransactionForSigning(transactionRequest) {
316
+ const transaction = await this.attachGasAndNonce(transactionRequest);
317
+ const txHash = (0, viem.toBytes)((0, viem.keccak256)((0, viem.serializeTransaction)(transaction)));
318
+ return {
319
+ transaction,
320
+ hashesToSign: [Array.from(txHash)]
321
+ };
322
+ }
323
+ async prepareMessageForSigning(message) {
324
+ return { hashToSign: Array.from((0, viem.toBytes)((0, viem.hashMessage)(message))) };
325
+ }
326
+ async prepareTypedDataForSigning(typedDataRequest) {
327
+ return { hashToSign: Array.from((0, viem.toBytes)((0, viem.hashTypedData)(typedDataRequest))) };
328
+ }
329
+ /**
330
+ * This implementation is a common step for Biconomy and Alchemy.
331
+ * Key differences between implementations:
332
+ * - Signature format: Biconomy omits 0x00 prefix when concatenating, Alchemy includes it
333
+ * - Version support: Biconomy only supports v6, Alchemy supports both v6 and v7
334
+ * - Validation: Biconomy uses modules for signature validation, Alchemy uses built-in validation
335
+ */
336
+ async prepareUserOpForSigning(userOp, entryPointAddress, chainIdArgs) {
337
+ const chainId = chainIdArgs ?? await this.client.getChainId();
338
+ const entryPoint = entryPointAddress || "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
339
+ const userOpHash = (0, viem.keccak256)((0, viem.encodeAbiParameters)([
340
+ { type: "bytes32" },
341
+ { type: "address" },
342
+ { type: "uint256" }
343
+ ], [
344
+ (0, viem.keccak256)((0, viem.encodeAbiParameters)([
345
+ { type: "address" },
346
+ { type: "uint256" },
347
+ { type: "bytes32" },
348
+ { type: "bytes32" },
349
+ { type: "bytes32" },
350
+ { type: "uint256" },
351
+ { type: "bytes32" },
352
+ { type: "bytes32" }
353
+ ], [
354
+ userOp.sender,
355
+ (0, viem.hexToBigInt)(userOp.nonce),
356
+ (0, viem.keccak256)("factory" in userOp && "factoryData" in userOp && userOp.factory && userOp.factoryData ? (0, viem.concat)([userOp.factory, userOp.factoryData]) : "initCode" in userOp ? userOp.initCode : "0x"),
357
+ (0, viem.keccak256)(userOp.callData),
358
+ (0, viem.concat)([(0, viem.pad)(userOp.verificationGasLimit, { size: 16 }), (0, viem.pad)(userOp.callGasLimit, { size: 16 })]),
359
+ (0, viem.hexToBigInt)(userOp.preVerificationGas),
360
+ (0, viem.concat)([(0, viem.pad)(userOp.maxPriorityFeePerGas, { size: 16 }), (0, viem.pad)(userOp.maxFeePerGas, { size: 16 })]),
361
+ (0, viem.keccak256)("paymaster" in userOp && userOp.paymaster && (0, viem.isAddress)(userOp.paymaster) ? (0, viem.concat)([
362
+ userOp.paymaster,
363
+ (0, viem.pad)(userOp.paymasterVerificationGasLimit, { size: 16 }),
364
+ (0, viem.pad)(userOp.paymasterPostOpGasLimit, { size: 16 }),
365
+ userOp.paymasterData
366
+ ]) : "paymasterAndData" in userOp ? userOp.paymasterAndData : "0x")
367
+ ])),
368
+ entryPoint,
369
+ BigInt(chainId)
370
+ ]));
371
+ return {
372
+ userOp,
373
+ hashToSign: Array.from((0, viem.toBytes)((0, viem.hashMessage)({ raw: userOpHash })))
374
+ };
375
+ }
376
+ finalizeTransactionSigning({ transaction, rsvSignatures }) {
377
+ return (0, viem.serializeTransaction)(transaction, this.transformRSVSignature(rsvSignatures[0]));
378
+ }
379
+ finalizeMessageSigning({ rsvSignature }) {
380
+ return this.assembleSignature(rsvSignature);
381
+ }
382
+ finalizeTypedDataSigning({ rsvSignature }) {
383
+ return this.assembleSignature(rsvSignature);
384
+ }
385
+ finalizeUserOpSigning({ userOp, rsvSignature }) {
386
+ const { r, s, yParity } = this.transformRSVSignature(rsvSignature);
387
+ if (yParity === void 0) throw new Error("Missing yParity");
388
+ return {
389
+ ...userOp,
390
+ signature: (0, viem.concatHex)([
391
+ "0x00",
392
+ r,
393
+ s,
394
+ (0, viem.numberToHex)(Number(yParity + 27), { size: 1 })
395
+ ])
396
+ };
397
+ }
398
+ async broadcastTx(txSerialized) {
399
+ try {
400
+ return await this.client.sendRawTransaction({ serializedTransaction: txSerialized });
401
+ } catch (error) {
402
+ console.error("Transaction broadcast failed:", error);
403
+ throw new Error("Failed to broadcast transaction.");
404
+ }
405
+ }
406
+ };
407
+
408
+ //#endregion
409
+ //#region src/chain-adapters/EVM/index.ts
410
+ var EVM_exports = /* @__PURE__ */ __export({
411
+ EVM: () => EVM,
412
+ fetchEVMFeeProperties: () => fetchEVMFeeProperties
413
+ });
414
+
415
+ //#endregion
416
+ //#region src/chain-adapters/Bitcoin/utils.ts
417
+ function parseBTCNetwork(network) {
418
+ switch (network.toLowerCase()) {
419
+ case "mainnet": return bitcoinjs_lib.networks.bitcoin;
420
+ case "testnet": return bitcoinjs_lib.networks.testnet;
421
+ case "regtest": return bitcoinjs_lib.networks.regtest;
422
+ default: throw new Error(`Unknown Bitcoin network: ${network}`);
423
+ }
424
+ }
425
+
426
+ //#endregion
427
+ //#region src/chain-adapters/Bitcoin/Bitcoin.ts
428
+ /**
429
+ * Implementation of the ChainAdapter interface for Bitcoin network.
430
+ * Handles interactions with both Bitcoin mainnet and testnet, supporting P2WPKH transactions.
431
+ */
432
+ var Bitcoin = class Bitcoin extends ChainAdapter {
433
+ static {
434
+ this.SATOSHIS_PER_BTC = 1e8;
435
+ }
436
+ /**
437
+ * Creates a new Bitcoin chain instance
438
+ * @param params - Configuration parameters
439
+ * @param params.network - Network identifier (mainnet/testnet)
440
+ * @param params.contract - Instance of the chain signature contract for MPC operations
441
+ * @param params.btcRpcAdapter - Bitcoin RPC adapter for network interactions
442
+ */
443
+ constructor({ network, contract, btcRpcAdapter }) {
444
+ super();
445
+ this.network = network;
446
+ this.btcRpcAdapter = btcRpcAdapter;
447
+ this.contract = contract;
448
+ }
449
+ /**
450
+ * Converts satoshis to BTC
451
+ * @param satoshis - Amount in satoshis
452
+ * @returns Amount in BTC
453
+ */
454
+ static toBTC(satoshis) {
455
+ return satoshis / Bitcoin.SATOSHIS_PER_BTC;
456
+ }
457
+ /**
458
+ * Converts BTC to satoshis
459
+ * @param btc - Amount in BTC
460
+ * @returns Amount in satoshis (rounded)
461
+ */
462
+ static toSatoshi(btc) {
463
+ return Math.round(btc * Bitcoin.SATOSHIS_PER_BTC);
464
+ }
465
+ async fetchTransaction(transactionId) {
466
+ const data = await this.btcRpcAdapter.getTransaction(transactionId);
467
+ const tx = new bitcoinjs_lib.Transaction();
468
+ data.vout.forEach((vout) => {
469
+ const scriptPubKey = Buffer.from(vout.scriptpubkey, "hex");
470
+ tx.addOutput(scriptPubKey, Number(vout.value));
471
+ });
472
+ return tx;
473
+ }
474
+ static transformRSVSignature(signature) {
475
+ const r = signature.r.padStart(64, "0");
476
+ const s = signature.s.padStart(64, "0");
477
+ const rawSignature = Buffer.from(r + s, "hex");
478
+ if (rawSignature.length !== 64) throw new Error("Invalid signature length.");
479
+ return rawSignature;
480
+ }
481
+ /**
482
+ * Creates a Partially Signed Bitcoin Transaction (PSBT)
483
+ * @param params - Parameters for creating the PSBT
484
+ * @param params.transactionRequest - Transaction request containing inputs and outputs
485
+ * @returns Created PSBT instance
486
+ */
487
+ async createPSBT({ transactionRequest }) {
488
+ const { inputs, outputs } = transactionRequest.inputs && transactionRequest.outputs ? transactionRequest : await this.btcRpcAdapter.selectUTXOs(transactionRequest.from, [{
489
+ address: transactionRequest.to,
490
+ value: parseFloat(transactionRequest.value)
491
+ }]);
492
+ const psbt = new bitcoinjs_lib.Psbt({ network: parseBTCNetwork(this.network) });
493
+ await Promise.all(inputs.map(async (input) => {
494
+ if (!input.scriptPubKey) input.scriptPubKey = (await this.fetchTransaction(input.txid)).outs[input.vout].script;
495
+ psbt.addInput({
496
+ hash: input.txid,
497
+ index: input.vout,
498
+ witnessUtxo: {
499
+ script: input.scriptPubKey,
500
+ value: input.value
501
+ }
502
+ });
503
+ }));
504
+ outputs.forEach((out) => {
505
+ if ("address" in out) psbt.addOutput({
506
+ address: out.address,
507
+ value: out.value
508
+ });
509
+ else if ("script" in out) psbt.addOutput({
510
+ script: out.script,
511
+ value: out.value
512
+ });
513
+ else if (transactionRequest.from !== void 0) psbt.addOutput({
514
+ value: Number(out.value),
515
+ address: transactionRequest.from
516
+ });
517
+ });
518
+ return psbt;
519
+ }
520
+ async getBalance(address$1) {
521
+ return {
522
+ balance: BigInt(await this.btcRpcAdapter.getBalance(address$1)),
523
+ decimals: 8
524
+ };
525
+ }
526
+ async deriveAddressAndPublicKey(predecessor, path, keyVersion) {
527
+ const uncompressedPubKey = await this.contract.getDerivedPublicKey({
528
+ path,
529
+ predecessor,
530
+ keyVersion
531
+ });
532
+ if (!uncompressedPubKey) throw new Error("Failed to get derived public key");
533
+ const derivedKey = compressPubKey(uncompressedPubKey);
534
+ const publicKeyBuffer = Buffer.from(derivedKey, "hex");
535
+ const network = parseBTCNetwork(this.network);
536
+ const { address: address$1 } = bitcoinjs_lib.payments.p2wpkh({
537
+ pubkey: publicKeyBuffer,
538
+ network
539
+ });
540
+ if (!address$1) throw new Error("Failed to generate Bitcoin address");
541
+ return {
542
+ address: address$1,
543
+ publicKey: derivedKey
544
+ };
545
+ }
546
+ serializeTransaction(transaction) {
547
+ return JSON.stringify({
548
+ psbt: transaction.psbt.toHex(),
549
+ publicKey: transaction.publicKey
550
+ });
551
+ }
552
+ deserializeTransaction(serialized) {
553
+ const transactionJSON = JSON.parse(serialized);
554
+ return {
555
+ psbt: bitcoinjs_lib.Psbt.fromHex(transactionJSON.psbt),
556
+ publicKey: transactionJSON.publicKey
557
+ };
558
+ }
559
+ async prepareTransactionForSigning(transactionRequest) {
560
+ const publicKeyBuffer = Buffer.from(transactionRequest.publicKey, "hex");
561
+ const psbt = await this.createPSBT({ transactionRequest });
562
+ const psbtHex = psbt.toHex();
563
+ const hashesToSign = [];
564
+ const mockKeyPair = (index) => ({
565
+ publicKey: publicKeyBuffer,
566
+ sign: (hash) => {
567
+ hashesToSign[index] = Array.from(hash);
568
+ return Buffer.alloc(64);
569
+ }
570
+ });
571
+ for (let index = 0; index < psbt.inputCount; index++) psbt.signInput(index, mockKeyPair(index));
572
+ return {
573
+ transaction: {
574
+ psbt: bitcoinjs_lib.Psbt.fromHex(psbtHex),
575
+ publicKey: transactionRequest.publicKey
576
+ },
577
+ hashesToSign
578
+ };
579
+ }
580
+ finalizeTransactionSigning({ transaction: { psbt, publicKey }, rsvSignatures }) {
581
+ const publicKeyBuffer = Buffer.from(publicKey, "hex");
582
+ const keyPair = (index) => ({
583
+ publicKey: publicKeyBuffer,
584
+ sign: () => {
585
+ const mpcSignature = rsvSignatures[index];
586
+ return Bitcoin.transformRSVSignature(mpcSignature);
587
+ }
588
+ });
589
+ for (let index = 0; index < psbt.inputCount; index++) psbt.signInput(index, keyPair(index));
590
+ psbt.finalizeAllInputs();
591
+ return psbt.extractTransaction().toHex();
592
+ }
593
+ async broadcastTx(txSerialized) {
594
+ return await this.btcRpcAdapter.broadcastTransaction(txSerialized);
595
+ }
596
+ };
597
+
598
+ //#endregion
599
+ //#region src/chain-adapters/Bitcoin/BTCRpcAdapter/BTCRpcAdapter.ts
600
+ var BTCRpcAdapter = class {};
601
+
602
+ //#endregion
603
+ //#region src/chain-adapters/Bitcoin/BTCRpcAdapter/Mempool/Mempool.ts
604
+ var Mempool = class extends BTCRpcAdapter {
605
+ constructor(providerUrl) {
606
+ super();
607
+ this.providerUrl = providerUrl;
608
+ }
609
+ async fetchFeeRate(confirmationTarget = 6) {
610
+ const data = await (await fetch(`${this.providerUrl}/v1/fees/recommended`)).json();
611
+ if (confirmationTarget <= 1) return data.fastestFee;
612
+ else if (confirmationTarget <= 3) return data.halfHourFee;
613
+ else if (confirmationTarget <= 6) return data.hourFee;
614
+ else return data.economyFee;
615
+ }
616
+ async fetchUTXOs(address$1) {
617
+ try {
618
+ return await (await fetch(`${this.providerUrl}/address/${address$1}/utxo`)).json();
619
+ } catch (error) {
620
+ console.error("Failed to fetch UTXOs:", error);
621
+ return [];
622
+ }
623
+ }
624
+ async selectUTXOs(from, targets, confirmationTarget = 6) {
625
+ const utxos = await this.fetchUTXOs(from);
626
+ const feeRate = await this.fetchFeeRate(confirmationTarget);
627
+ const ret = (0, coinselect.default)(utxos, targets, Math.ceil(feeRate + 1));
628
+ if (!ret.inputs || !ret.outputs) throw new Error("Invalid transaction: coinselect failed to find a suitable set of inputs and outputs. This could be due to insufficient funds, or no inputs being available that meet the criteria.");
629
+ return {
630
+ inputs: ret.inputs,
631
+ outputs: ret.outputs
632
+ };
633
+ }
634
+ async broadcastTransaction(transactionHex) {
635
+ const response = await fetch(`${this.providerUrl}/tx`, {
636
+ method: "POST",
637
+ body: transactionHex
638
+ });
639
+ if (response.ok) return await response.text();
640
+ throw new Error(`Failed to broadcast transaction: ${await response.text()}`);
641
+ }
642
+ async getBalance(address$1) {
643
+ const data = await (await fetch(`${this.providerUrl}/address/${address$1}`)).json();
644
+ return data.chain_stats.funded_txo_sum - data.chain_stats.spent_txo_sum;
645
+ }
646
+ async getTransaction(txid) {
647
+ return await (await fetch(`${this.providerUrl}/tx/${txid}`)).json();
648
+ }
649
+ };
650
+
651
+ //#endregion
652
+ //#region src/chain-adapters/Bitcoin/BTCRpcAdapter/index.ts
653
+ const BTCRpcAdapters = { Mempool };
654
+
655
+ //#endregion
656
+ //#region src/chain-adapters/Bitcoin/index.ts
657
+ var Bitcoin_exports = /* @__PURE__ */ __export({
658
+ BTCRpcAdapter: () => BTCRpcAdapter,
659
+ BTCRpcAdapters: () => BTCRpcAdapters,
660
+ Bitcoin: () => Bitcoin
661
+ });
662
+
663
+ //#endregion
664
+ //#region src/chain-adapters/Cosmos/utils.ts
665
+ const fetchChainInfo = async (chainId) => {
666
+ const chainInfo = chain_registry.chains.find((chain) => chain.chain_id === chainId);
667
+ if (!chainInfo) throw new Error(`Chain info not found for chainId: ${chainId}`);
668
+ const { bech32_prefix: prefix, chain_id: expectedChainId } = chainInfo;
669
+ const denom = chainInfo.staking?.staking_tokens?.[0]?.denom;
670
+ const rpcUrl = chainInfo.apis?.rpc?.[0]?.address;
671
+ const restUrl = chainInfo.apis?.rest?.[0]?.address;
672
+ const gasPrice = chainInfo.fees?.fee_tokens?.[0]?.average_gas_price;
673
+ if (!prefix || !denom || !rpcUrl || !restUrl || !expectedChainId || gasPrice === void 0) throw new Error(`Missing required chain information for ${chainInfo.chain_name}`);
674
+ const asset = chain_registry.assets.find((asset$1) => asset$1.chain_name === chainInfo.chain_name)?.assets.find((asset$1) => asset$1.base === denom);
675
+ const decimals = asset?.denom_units.find((unit) => unit.denom === asset.display)?.exponent;
676
+ if (decimals === void 0) throw new Error(`Could not find decimals for ${denom} on chain ${chainInfo.chain_name}`);
677
+ return {
678
+ prefix,
679
+ denom,
680
+ rpcUrl,
681
+ restUrl,
682
+ expectedChainId,
683
+ gasPrice,
684
+ decimals
685
+ };
686
+ };
687
+
688
+ //#endregion
689
+ //#region src/chain-adapters/Cosmos/Cosmos.ts
690
+ /**
691
+ * Implementation of the ChainAdapter interface for Cosmos-based networks.
692
+ * Handles interactions with Cosmos SDK chains like Cosmos Hub, Osmosis, etc.
693
+ */
694
+ var Cosmos = class extends ChainAdapter {
695
+ /**
696
+ * Creates a new Cosmos chain instance
697
+ * @param params - Configuration parameters
698
+ * @param params.chainId - Chain id for the Cosmos network
699
+ * @param params.contract - Instance of the chain signature contract for MPC operations
700
+ * @param params.endpoints - Optional RPC and REST endpoints
701
+ * @param params.endpoints.rpcUrl - Optional RPC endpoint URL
702
+ * @param params.endpoints.restUrl - Optional REST endpoint URL
703
+ */
704
+ constructor({ chainId, contract, endpoints }) {
705
+ super();
706
+ this.contract = contract;
707
+ this.registry = new __cosmjs_proto_signing.Registry();
708
+ this.chainId = chainId;
709
+ this.endpoints = endpoints;
710
+ }
711
+ transformRSVSignature(rsvSignature) {
712
+ return new Uint8Array([...(0, __cosmjs_encoding.fromHex)(rsvSignature.r), ...(0, __cosmjs_encoding.fromHex)(rsvSignature.s)]);
713
+ }
714
+ async getChainInfo() {
715
+ return {
716
+ ...await fetchChainInfo(this.chainId),
717
+ ...this.endpoints
718
+ };
719
+ }
720
+ async getBalance(address$1) {
721
+ try {
722
+ const { restUrl, denom, decimals } = await this.getChainInfo();
723
+ const response = await fetch(`${restUrl}/cosmos/bank/v1beta1/balances/${address$1}`);
724
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
725
+ const amount = (await response.json()).balances.find((b) => b.denom === denom)?.amount ?? "0";
726
+ return {
727
+ balance: BigInt(amount),
728
+ decimals
729
+ };
730
+ } catch (error) {
731
+ console.error("Failed to fetch Cosmos balance:", error);
732
+ throw new Error("Failed to fetch Cosmos balance");
733
+ }
734
+ }
735
+ async deriveAddressAndPublicKey(predecessor, path, keyVersion) {
736
+ const { prefix } = await this.getChainInfo();
737
+ const uncompressedPubKey = await this.contract.getDerivedPublicKey({
738
+ path,
739
+ predecessor,
740
+ keyVersion
741
+ });
742
+ if (!uncompressedPubKey) throw new Error("Failed to get derived public key");
743
+ const derivedKey = compressPubKey(uncompressedPubKey);
744
+ const ripemd160Hash = (0, __cosmjs_crypto.ripemd160)((0, __cosmjs_crypto.sha256)((0, __cosmjs_encoding.fromHex)(derivedKey)));
745
+ return {
746
+ address: bech32.bech32.encode(prefix, bech32.bech32.toWords(ripemd160Hash)),
747
+ publicKey: derivedKey
748
+ };
749
+ }
750
+ serializeTransaction(transaction) {
751
+ return (0, __cosmjs_encoding.toBase64)(cosmjs_types_cosmos_tx_v1beta1_tx_js.TxRaw.encode(transaction).finish());
752
+ }
753
+ deserializeTransaction(serialized) {
754
+ return cosmjs_types_cosmos_tx_v1beta1_tx_js.TxRaw.decode((0, __cosmjs_encoding.fromBase64)(serialized));
755
+ }
756
+ async prepareTransactionForSigning(transactionRequest) {
757
+ const { denom, rpcUrl, gasPrice } = await this.getChainInfo();
758
+ const publicKeyBytes = (0, __cosmjs_encoding.fromHex)(transactionRequest.publicKey);
759
+ const fee = (0, __cosmjs_stargate.calculateFee)(transactionRequest.gas || 2e5, __cosmjs_stargate.GasPrice.fromString(`${gasPrice}${denom}`));
760
+ const accountOnChain = await (await __cosmjs_stargate.StargateClient.connect(rpcUrl)).getAccount(transactionRequest.address);
761
+ if (!accountOnChain) throw new Error(`Account ${transactionRequest.address} does not exist on chain`);
762
+ const { accountNumber, sequence } = accountOnChain;
763
+ const txBodyEncodeObject = {
764
+ typeUrl: "/cosmos.tx.v1beta1.TxBody",
765
+ value: {
766
+ messages: transactionRequest.messages,
767
+ memo: transactionRequest.memo || ""
768
+ }
769
+ };
770
+ const txBodyBytes = this.registry.encode(txBodyEncodeObject);
771
+ const authInfoBytes = (0, __cosmjs_proto_signing.makeAuthInfoBytes)([{
772
+ pubkey: (0, __cosmjs_proto_signing.encodePubkey)((0, __cosmjs_amino.encodeSecp256k1Pubkey)(publicKeyBytes)),
773
+ sequence
774
+ }], fee.amount, Number(fee.gas), void 0, void 0, cosmjs_types_cosmos_tx_signing_v1beta1_signing_js.SignMode.SIGN_MODE_DIRECT);
775
+ const signBytes = (0, __cosmjs_proto_signing.makeSignBytes)((0, __cosmjs_proto_signing.makeSignDoc)(txBodyBytes, authInfoBytes, this.chainId, accountNumber));
776
+ const payload = Array.from((0, __cosmjs_crypto.sha256)(signBytes));
777
+ return {
778
+ transaction: cosmjs_types_cosmos_tx_v1beta1_tx_js.TxRaw.fromPartial({
779
+ bodyBytes: txBodyBytes,
780
+ authInfoBytes,
781
+ signatures: []
782
+ }),
783
+ hashesToSign: [payload]
784
+ };
785
+ }
786
+ finalizeTransactionSigning({ transaction, rsvSignatures }) {
787
+ transaction.signatures = rsvSignatures.map((sig) => this.transformRSVSignature(sig));
788
+ const txBytes = cosmjs_types_cosmos_tx_v1beta1_tx_js.TxRaw.encode(transaction).finish();
789
+ return Buffer.from(txBytes).toString("hex");
790
+ }
791
+ async broadcastTx(txSerialized) {
792
+ try {
793
+ const { rpcUrl } = await this.getChainInfo();
794
+ const client = await __cosmjs_stargate.StargateClient.connect(rpcUrl);
795
+ const txBytes = (0, __cosmjs_encoding.fromHex)(txSerialized);
796
+ const broadcastResponse = await client.broadcastTx(txBytes);
797
+ if (broadcastResponse.code !== 0) throw new Error(`Broadcast error: ${broadcastResponse.rawLog}`);
798
+ return broadcastResponse.transactionHash;
799
+ } catch (error) {
800
+ console.error("Transaction broadcast failed:", error);
801
+ throw new Error("Failed to broadcast transaction.");
802
+ }
803
+ }
804
+ };
805
+
806
+ //#endregion
807
+ //#region src/chain-adapters/Cosmos/index.ts
808
+ var Cosmos_exports = /* @__PURE__ */ __export({ Cosmos: () => Cosmos });
809
+
810
+ //#endregion
811
+ //#region src/chain-adapters/index.ts
812
+ var chain_adapters_exports = /* @__PURE__ */ __export({
813
+ ChainAdapter: () => ChainAdapter,
814
+ btc: () => Bitcoin_exports,
815
+ cosmos: () => Cosmos_exports,
816
+ evm: () => EVM_exports
817
+ });
818
+
819
+ //#endregion
820
+ //#region src/contracts/ChainSignatureContract.ts
821
+ /**
822
+ * Base contract interface required for compatibility with ChainAdapter instances like EVM and Bitcoin.
823
+ *
824
+ * See {@link EVM} and {@link Bitcoin} for example implementations.
825
+ */
826
+ var BaseChainSignatureContract = class {};
827
+ /**
828
+ * Full contract interface that extends BaseChainSignatureContract to provide all Sig Network Smart Contract capabilities.
829
+ */
830
+ var ChainSignatureContract = class extends BaseChainSignatureContract {};
831
+
832
+ //#endregion
833
+ //#region src/contracts/evm/ChainSignaturesContractABI.ts
834
+ var ChainSignaturesContractABI_exports = /* @__PURE__ */ __export({ abi: () => abi });
835
+ const abi = [
836
+ {
837
+ inputs: [{
838
+ internalType: "address",
839
+ name: "_mpc_network",
840
+ type: "address"
841
+ }, {
842
+ internalType: "uint256",
843
+ name: "_signatureDeposit",
844
+ type: "uint256"
845
+ }],
846
+ stateMutability: "nonpayable",
847
+ type: "constructor"
848
+ },
849
+ {
850
+ inputs: [],
851
+ name: "AccessControlBadConfirmation",
852
+ type: "error"
853
+ },
854
+ {
855
+ inputs: [{
856
+ internalType: "address",
857
+ name: "account",
858
+ type: "address"
859
+ }, {
860
+ internalType: "bytes32",
861
+ name: "neededRole",
862
+ type: "bytes32"
863
+ }],
864
+ name: "AccessControlUnauthorizedAccount",
865
+ type: "error"
866
+ },
867
+ {
868
+ anonymous: false,
869
+ inputs: [
870
+ {
871
+ indexed: true,
872
+ internalType: "bytes32",
873
+ name: "role",
874
+ type: "bytes32"
875
+ },
876
+ {
877
+ indexed: true,
878
+ internalType: "bytes32",
879
+ name: "previousAdminRole",
880
+ type: "bytes32"
881
+ },
882
+ {
883
+ indexed: true,
884
+ internalType: "bytes32",
885
+ name: "newAdminRole",
886
+ type: "bytes32"
887
+ }
888
+ ],
889
+ name: "RoleAdminChanged",
890
+ type: "event"
891
+ },
892
+ {
893
+ anonymous: false,
894
+ inputs: [
895
+ {
896
+ indexed: true,
897
+ internalType: "bytes32",
898
+ name: "role",
899
+ type: "bytes32"
900
+ },
901
+ {
902
+ indexed: true,
903
+ internalType: "address",
904
+ name: "account",
905
+ type: "address"
906
+ },
907
+ {
908
+ indexed: true,
909
+ internalType: "address",
910
+ name: "sender",
911
+ type: "address"
912
+ }
913
+ ],
914
+ name: "RoleGranted",
915
+ type: "event"
916
+ },
917
+ {
918
+ anonymous: false,
919
+ inputs: [
920
+ {
921
+ indexed: true,
922
+ internalType: "bytes32",
923
+ name: "role",
924
+ type: "bytes32"
925
+ },
926
+ {
927
+ indexed: true,
928
+ internalType: "address",
929
+ name: "account",
930
+ type: "address"
931
+ },
932
+ {
933
+ indexed: true,
934
+ internalType: "address",
935
+ name: "sender",
936
+ type: "address"
937
+ }
938
+ ],
939
+ name: "RoleRevoked",
940
+ type: "event"
941
+ },
942
+ {
943
+ anonymous: false,
944
+ inputs: [
945
+ {
946
+ indexed: true,
947
+ internalType: "bytes32",
948
+ name: "requestId",
949
+ type: "bytes32"
950
+ },
951
+ {
952
+ indexed: false,
953
+ internalType: "address",
954
+ name: "responder",
955
+ type: "address"
956
+ },
957
+ {
958
+ indexed: false,
959
+ internalType: "string",
960
+ name: "error",
961
+ type: "string"
962
+ }
963
+ ],
964
+ name: "SignatureError",
965
+ type: "event"
966
+ },
967
+ {
968
+ anonymous: false,
969
+ inputs: [
970
+ {
971
+ indexed: false,
972
+ internalType: "address",
973
+ name: "sender",
974
+ type: "address"
975
+ },
976
+ {
977
+ indexed: false,
978
+ internalType: "bytes32",
979
+ name: "payload",
980
+ type: "bytes32"
981
+ },
982
+ {
983
+ indexed: false,
984
+ internalType: "uint32",
985
+ name: "keyVersion",
986
+ type: "uint32"
987
+ },
988
+ {
989
+ indexed: false,
990
+ internalType: "uint256",
991
+ name: "deposit",
992
+ type: "uint256"
993
+ },
994
+ {
995
+ indexed: false,
996
+ internalType: "uint256",
997
+ name: "chainId",
998
+ type: "uint256"
999
+ },
1000
+ {
1001
+ indexed: false,
1002
+ internalType: "string",
1003
+ name: "path",
1004
+ type: "string"
1005
+ },
1006
+ {
1007
+ indexed: false,
1008
+ internalType: "string",
1009
+ name: "algo",
1010
+ type: "string"
1011
+ },
1012
+ {
1013
+ indexed: false,
1014
+ internalType: "string",
1015
+ name: "dest",
1016
+ type: "string"
1017
+ },
1018
+ {
1019
+ indexed: false,
1020
+ internalType: "string",
1021
+ name: "params",
1022
+ type: "string"
1023
+ }
1024
+ ],
1025
+ name: "SignatureRequested",
1026
+ type: "event"
1027
+ },
1028
+ {
1029
+ anonymous: false,
1030
+ inputs: [
1031
+ {
1032
+ indexed: true,
1033
+ internalType: "bytes32",
1034
+ name: "requestId",
1035
+ type: "bytes32"
1036
+ },
1037
+ {
1038
+ indexed: false,
1039
+ internalType: "address",
1040
+ name: "responder",
1041
+ type: "address"
1042
+ },
1043
+ {
1044
+ components: [
1045
+ {
1046
+ components: [{
1047
+ internalType: "uint256",
1048
+ name: "x",
1049
+ type: "uint256"
1050
+ }, {
1051
+ internalType: "uint256",
1052
+ name: "y",
1053
+ type: "uint256"
1054
+ }],
1055
+ internalType: "struct ChainSignatures.AffinePoint",
1056
+ name: "bigR",
1057
+ type: "tuple"
1058
+ },
1059
+ {
1060
+ internalType: "uint256",
1061
+ name: "s",
1062
+ type: "uint256"
1063
+ },
1064
+ {
1065
+ internalType: "uint8",
1066
+ name: "recoveryId",
1067
+ type: "uint8"
1068
+ }
1069
+ ],
1070
+ indexed: false,
1071
+ internalType: "struct ChainSignatures.Signature",
1072
+ name: "signature",
1073
+ type: "tuple"
1074
+ }
1075
+ ],
1076
+ name: "SignatureResponded",
1077
+ type: "event"
1078
+ },
1079
+ {
1080
+ anonymous: false,
1081
+ inputs: [{
1082
+ indexed: true,
1083
+ internalType: "address",
1084
+ name: "owner",
1085
+ type: "address"
1086
+ }, {
1087
+ indexed: false,
1088
+ internalType: "uint256",
1089
+ name: "amount",
1090
+ type: "uint256"
1091
+ }],
1092
+ name: "Withdraw",
1093
+ type: "event"
1094
+ },
1095
+ {
1096
+ inputs: [],
1097
+ name: "DEFAULT_ADMIN_ROLE",
1098
+ outputs: [{
1099
+ internalType: "bytes32",
1100
+ name: "",
1101
+ type: "bytes32"
1102
+ }],
1103
+ stateMutability: "view",
1104
+ type: "function"
1105
+ },
1106
+ {
1107
+ inputs: [{
1108
+ internalType: "bytes32",
1109
+ name: "role",
1110
+ type: "bytes32"
1111
+ }],
1112
+ name: "getRoleAdmin",
1113
+ outputs: [{
1114
+ internalType: "bytes32",
1115
+ name: "",
1116
+ type: "bytes32"
1117
+ }],
1118
+ stateMutability: "view",
1119
+ type: "function"
1120
+ },
1121
+ {
1122
+ inputs: [],
1123
+ name: "getSignatureDeposit",
1124
+ outputs: [{
1125
+ internalType: "uint256",
1126
+ name: "",
1127
+ type: "uint256"
1128
+ }],
1129
+ stateMutability: "view",
1130
+ type: "function"
1131
+ },
1132
+ {
1133
+ inputs: [{
1134
+ internalType: "bytes32",
1135
+ name: "role",
1136
+ type: "bytes32"
1137
+ }, {
1138
+ internalType: "address",
1139
+ name: "account",
1140
+ type: "address"
1141
+ }],
1142
+ name: "grantRole",
1143
+ outputs: [],
1144
+ stateMutability: "nonpayable",
1145
+ type: "function"
1146
+ },
1147
+ {
1148
+ inputs: [{
1149
+ internalType: "bytes32",
1150
+ name: "role",
1151
+ type: "bytes32"
1152
+ }, {
1153
+ internalType: "address",
1154
+ name: "account",
1155
+ type: "address"
1156
+ }],
1157
+ name: "hasRole",
1158
+ outputs: [{
1159
+ internalType: "bool",
1160
+ name: "",
1161
+ type: "bool"
1162
+ }],
1163
+ stateMutability: "view",
1164
+ type: "function"
1165
+ },
1166
+ {
1167
+ inputs: [{
1168
+ internalType: "bytes32",
1169
+ name: "role",
1170
+ type: "bytes32"
1171
+ }, {
1172
+ internalType: "address",
1173
+ name: "callerConfirmation",
1174
+ type: "address"
1175
+ }],
1176
+ name: "renounceRole",
1177
+ outputs: [],
1178
+ stateMutability: "nonpayable",
1179
+ type: "function"
1180
+ },
1181
+ {
1182
+ inputs: [{
1183
+ components: [{
1184
+ internalType: "bytes32",
1185
+ name: "requestId",
1186
+ type: "bytes32"
1187
+ }, {
1188
+ components: [
1189
+ {
1190
+ components: [{
1191
+ internalType: "uint256",
1192
+ name: "x",
1193
+ type: "uint256"
1194
+ }, {
1195
+ internalType: "uint256",
1196
+ name: "y",
1197
+ type: "uint256"
1198
+ }],
1199
+ internalType: "struct ChainSignatures.AffinePoint",
1200
+ name: "bigR",
1201
+ type: "tuple"
1202
+ },
1203
+ {
1204
+ internalType: "uint256",
1205
+ name: "s",
1206
+ type: "uint256"
1207
+ },
1208
+ {
1209
+ internalType: "uint8",
1210
+ name: "recoveryId",
1211
+ type: "uint8"
1212
+ }
1213
+ ],
1214
+ internalType: "struct ChainSignatures.Signature",
1215
+ name: "signature",
1216
+ type: "tuple"
1217
+ }],
1218
+ internalType: "struct ChainSignatures.Response[]",
1219
+ name: "_responses",
1220
+ type: "tuple[]"
1221
+ }],
1222
+ name: "respond",
1223
+ outputs: [],
1224
+ stateMutability: "nonpayable",
1225
+ type: "function"
1226
+ },
1227
+ {
1228
+ inputs: [{
1229
+ components: [{
1230
+ internalType: "bytes32",
1231
+ name: "requestId",
1232
+ type: "bytes32"
1233
+ }, {
1234
+ internalType: "string",
1235
+ name: "errorMessage",
1236
+ type: "string"
1237
+ }],
1238
+ internalType: "struct ChainSignatures.ErrorResponse[]",
1239
+ name: "_errors",
1240
+ type: "tuple[]"
1241
+ }],
1242
+ name: "respondError",
1243
+ outputs: [],
1244
+ stateMutability: "nonpayable",
1245
+ type: "function"
1246
+ },
1247
+ {
1248
+ inputs: [{
1249
+ internalType: "bytes32",
1250
+ name: "role",
1251
+ type: "bytes32"
1252
+ }, {
1253
+ internalType: "address",
1254
+ name: "account",
1255
+ type: "address"
1256
+ }],
1257
+ name: "revokeRole",
1258
+ outputs: [],
1259
+ stateMutability: "nonpayable",
1260
+ type: "function"
1261
+ },
1262
+ {
1263
+ inputs: [{
1264
+ internalType: "uint256",
1265
+ name: "_amount",
1266
+ type: "uint256"
1267
+ }],
1268
+ name: "setSignatureDeposit",
1269
+ outputs: [],
1270
+ stateMutability: "nonpayable",
1271
+ type: "function"
1272
+ },
1273
+ {
1274
+ inputs: [{
1275
+ components: [
1276
+ {
1277
+ internalType: "bytes32",
1278
+ name: "payload",
1279
+ type: "bytes32"
1280
+ },
1281
+ {
1282
+ internalType: "string",
1283
+ name: "path",
1284
+ type: "string"
1285
+ },
1286
+ {
1287
+ internalType: "uint32",
1288
+ name: "keyVersion",
1289
+ type: "uint32"
1290
+ },
1291
+ {
1292
+ internalType: "string",
1293
+ name: "algo",
1294
+ type: "string"
1295
+ },
1296
+ {
1297
+ internalType: "string",
1298
+ name: "dest",
1299
+ type: "string"
1300
+ },
1301
+ {
1302
+ internalType: "string",
1303
+ name: "params",
1304
+ type: "string"
1305
+ }
1306
+ ],
1307
+ internalType: "struct ChainSignatures.SignRequest",
1308
+ name: "_request",
1309
+ type: "tuple"
1310
+ }],
1311
+ name: "sign",
1312
+ outputs: [],
1313
+ stateMutability: "payable",
1314
+ type: "function"
1315
+ },
1316
+ {
1317
+ inputs: [{
1318
+ internalType: "bytes4",
1319
+ name: "interfaceId",
1320
+ type: "bytes4"
1321
+ }],
1322
+ name: "supportsInterface",
1323
+ outputs: [{
1324
+ internalType: "bool",
1325
+ name: "",
1326
+ type: "bool"
1327
+ }],
1328
+ stateMutability: "view",
1329
+ type: "function"
1330
+ },
1331
+ {
1332
+ inputs: [{
1333
+ internalType: "uint256",
1334
+ name: "_amount",
1335
+ type: "uint256"
1336
+ }, {
1337
+ internalType: "address",
1338
+ name: "_receiver",
1339
+ type: "address"
1340
+ }],
1341
+ name: "withdraw",
1342
+ outputs: [],
1343
+ stateMutability: "nonpayable",
1344
+ type: "function"
1345
+ }
1346
+ ];
1347
+
1348
+ //#endregion
1349
+ //#region src/contracts/evm/errors.ts
1350
+ var errors_exports$1 = /* @__PURE__ */ __export({
1351
+ ChainSignatureError: () => ChainSignatureError,
1352
+ SignatureContractError: () => SignatureContractError$1,
1353
+ SignatureNotFoundError: () => SignatureNotFoundError$1,
1354
+ SigningError: () => SigningError$1
1355
+ });
1356
+ var ChainSignatureError = class extends Error {
1357
+ constructor(message, requestId, receipt) {
1358
+ super(message);
1359
+ this.name = "ChainSignatureError";
1360
+ this.requestId = requestId;
1361
+ this.receipt = receipt;
1362
+ }
1363
+ };
1364
+ var SignatureNotFoundError$1 = class extends ChainSignatureError {
1365
+ constructor(requestId, receipt) {
1366
+ super("Signature not found after maximum retries", requestId, receipt);
1367
+ this.name = "SignatureNotFoundError";
1368
+ }
1369
+ };
1370
+ var SignatureContractError$1 = class extends ChainSignatureError {
1371
+ constructor(errorCode, requestId, receipt) {
1372
+ super(`Signature error: ${errorCode}`, requestId, receipt);
1373
+ this.name = "SignatureContractError";
1374
+ this.errorCode = errorCode;
1375
+ }
1376
+ };
1377
+ var SigningError$1 = class extends ChainSignatureError {
1378
+ constructor(requestId, receipt, originalError) {
1379
+ super("Error signing request", requestId, receipt);
1380
+ this.name = "SigningError";
1381
+ this.originalError = originalError;
1382
+ }
1383
+ };
1384
+
1385
+ //#endregion
1386
+ //#region src/utils/publicKey.ts
1387
+ const getRootPublicKey = (contractAddress, chain) => {
1388
+ const environment = Object.entries(CONTRACT_ADDRESSES[chain]).find(([_, address$1]) => address$1.toLowerCase() === contractAddress.toLowerCase())?.[0];
1389
+ if (environment) return ROOT_PUBLIC_KEYS[environment];
1390
+ };
1391
+
1392
+ //#endregion
1393
+ //#region src/contracts/evm/utils.ts
1394
+ const getRequestId = (request) => {
1395
+ return (0, viem.keccak256)((0, viem.encodeAbiParameters)([
1396
+ { type: "address" },
1397
+ { type: "bytes" },
1398
+ { type: "string" },
1399
+ { type: "uint32" },
1400
+ { type: "uint256" },
1401
+ { type: "string" },
1402
+ { type: "string" },
1403
+ { type: "string" }
1404
+ ], [
1405
+ request.address,
1406
+ request.payload,
1407
+ request.path,
1408
+ Number(request.keyVersion),
1409
+ request.chainId,
1410
+ request.algo,
1411
+ request.dest,
1412
+ request.params
1413
+ ]));
1414
+ };
1415
+
1416
+ //#endregion
1417
+ //#region src/contracts/evm/ChainSignaturesContract.ts
1418
+ /**
1419
+ * Implementation of the ChainSignatureContract for EVM chains.
1420
+ *
1421
+ * When signing data, the contract emits a SignatureRequested event with a requestId.
1422
+ * This requestId is used to track the signature request and retrieve the signature
1423
+ * once it's available. The sign method handles this process automatically by polling
1424
+ * for the signature using the requestId.
1425
+ */
1426
+ var ChainSignatureContract$2 = class extends ChainSignatureContract {
1427
+ /**
1428
+ * Creates a new instance of the ChainSignatureContract for EVM chains.
1429
+ *
1430
+ * @param args - Configuration options for the contract
1431
+ * @param args.publicClient - A Viem PublicClient instance for reading from the blockchain
1432
+ * @param args.walletClient - A Viem WalletClient instance for sending transactions
1433
+ * @param args.contractAddress - The address of the deployed ChainSignatures contract (e.g. `0x857ED3A242B59cC24144814a0DF41C397a3811E6`)
1434
+ * @param args.rootPublicKey - Optional root public key. If not provided, it will be derived from the contract address
1435
+ */
1436
+ constructor(args) {
1437
+ super();
1438
+ this.publicClient = args.publicClient;
1439
+ this.walletClient = args.walletClient;
1440
+ this.contractAddress = args.contractAddress;
1441
+ const rootPublicKey = args.rootPublicKey || getRootPublicKey(this.contractAddress, CHAINS.ETHEREUM);
1442
+ if (!rootPublicKey) throw new Error(`Invalid public key, please provide a valid root public key or contract address`);
1443
+ this.rootPublicKey = rootPublicKey;
1444
+ }
1445
+ async getCurrentSignatureDeposit() {
1446
+ return new bn_js.default((await this.publicClient.readContract({
1447
+ address: this.contractAddress,
1448
+ abi,
1449
+ functionName: "getSignatureDeposit"
1450
+ })).toString());
1451
+ }
1452
+ async getDerivedPublicKey(args) {
1453
+ return deriveChildPublicKey(await this.getPublicKey(), args.predecessor.toLowerCase(), args.path, KDF_CHAIN_IDS.ETHEREUM, args.keyVersion);
1454
+ }
1455
+ async getPublicKey() {
1456
+ return najToUncompressedPubKeySEC1(this.rootPublicKey);
1457
+ }
1458
+ async getLatestKeyVersion() {
1459
+ const version = await this.publicClient.readContract({
1460
+ address: this.contractAddress,
1461
+ abi,
1462
+ functionName: "latestKeyVersion"
1463
+ });
1464
+ return Number(version);
1465
+ }
1466
+ /**
1467
+ * Sends a sign request transaction and return the transaction hash.
1468
+ *
1469
+ * @param args - The signature arguments
1470
+ * @param options - The signing options
1471
+ * @returns The transaction hash
1472
+ */
1473
+ async createSignatureRequest(args, options = { sign: {
1474
+ algo: "",
1475
+ dest: "",
1476
+ params: ""
1477
+ } }) {
1478
+ if (!this.walletClient?.account) throw new Error("Wallet client required for signing operations");
1479
+ const requestParams = await this.getSignRequestParams(args, options.sign);
1480
+ const requestId = this.getRequestId(args, options.sign);
1481
+ return {
1482
+ txHash: await this.walletClient.sendTransaction({
1483
+ ...options.transaction,
1484
+ account: this.walletClient.account,
1485
+ to: requestParams.target,
1486
+ data: requestParams.data,
1487
+ value: requestParams.value,
1488
+ chain: this.walletClient.chain
1489
+ }),
1490
+ requestId
1491
+ };
1492
+ }
1493
+ /**
1494
+ * Sends a transaction to the contract to request a signature, then
1495
+ * polls for the signature result. If the signature is not found within the retry
1496
+ * parameters, it will throw an error.
1497
+ */
1498
+ async sign(args, options = {
1499
+ sign: {
1500
+ algo: "",
1501
+ dest: "",
1502
+ params: ""
1503
+ },
1504
+ retry: {
1505
+ delay: 5e3,
1506
+ retryCount: 12
1507
+ }
1508
+ }) {
1509
+ const { txHash, requestId } = await this.createSignatureRequest(args, options);
1510
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash: txHash });
1511
+ try {
1512
+ const pollResult = await this.pollForRequestId({
1513
+ requestId,
1514
+ payload: args.payload,
1515
+ path: args.path,
1516
+ keyVersion: args.key_version,
1517
+ fromBlock: receipt.blockNumber,
1518
+ options: options.retry
1519
+ });
1520
+ if (!pollResult) throw new SignatureNotFoundError$1(requestId, receipt);
1521
+ if ("error" in pollResult) throw new SignatureContractError$1(pollResult.error, requestId, receipt);
1522
+ return pollResult;
1523
+ } catch (error) {
1524
+ if (error instanceof SignatureNotFoundError$1 || error instanceof SignatureContractError$1) throw error;
1525
+ else throw new SigningError$1(requestId, receipt, error instanceof Error ? error : void 0);
1526
+ }
1527
+ }
1528
+ async pollForRequestId({ requestId, payload, path, keyVersion, fromBlock, options }) {
1529
+ const delay = options?.delay ?? 5e3;
1530
+ const retryCount = options?.retryCount ?? 12;
1531
+ const result = await (0, viem.withRetry)(async () => {
1532
+ const result$1 = await this.getSignatureFromEvents(requestId, fromBlock);
1533
+ if (result$1) {
1534
+ if (!await verifyRecoveredAddress(result$1, payload, this.walletClient.account?.address, path, this, keyVersion)) throw new Error("Signature not found yet");
1535
+ return result$1;
1536
+ } else throw new Error("Signature not found yet");
1537
+ }, {
1538
+ delay,
1539
+ retryCount,
1540
+ shouldRetry: ({ count, error }) => {
1541
+ console.log(`Retrying get signature: ${count}/${retryCount}`);
1542
+ return error.message === "Signature not found yet";
1543
+ }
1544
+ });
1545
+ if (result) return result;
1546
+ return await this.getErrorFromEvents(requestId, fromBlock);
1547
+ }
1548
+ async getSignRequestParams(args, options = {
1549
+ algo: "",
1550
+ dest: "",
1551
+ params: ""
1552
+ }) {
1553
+ const request = {
1554
+ payload: `0x${Buffer.from(args.payload).toString("hex")}`,
1555
+ path: args.path,
1556
+ keyVersion: args.key_version,
1557
+ algo: options.algo ?? "",
1558
+ dest: options.dest ?? "",
1559
+ params: options.params ?? ""
1560
+ };
1561
+ return {
1562
+ target: this.contractAddress,
1563
+ data: (0, viem.encodeFunctionData)({
1564
+ abi,
1565
+ functionName: "sign",
1566
+ args: [request]
1567
+ }),
1568
+ value: BigInt((await this.getCurrentSignatureDeposit()).toString())
1569
+ };
1570
+ }
1571
+ /**
1572
+ * Generates the request ID for a signature request allowing to track the response.
1573
+ *
1574
+ * @param args - The signature request object containing:
1575
+ * @param args.payload - The data payload to be signed as a hex string
1576
+ * @param args.path - The derivation path for the key
1577
+ * @param args.keyVersion - The version of the key to use
1578
+ * @param options - The signature request object containing:
1579
+ * @param options.algo - The signing algorithm to use
1580
+ * @param options.dest - The destination for the signature
1581
+ * @param options.params - Additional parameters for the signing process
1582
+ * @returns A hex string representing the unique request ID
1583
+ *
1584
+ * @example
1585
+ * ```typescript
1586
+ * const requestId = ChainSignatureContract.getRequestId({
1587
+ * payload: payload: `0x${Buffer.from(args.payload).toString('hex')}`,,
1588
+ * path: '',
1589
+ * keyVersion: 0
1590
+ * });
1591
+ * console.log(requestId); // 0x...
1592
+ * ```
1593
+ */
1594
+ getRequestId(args, options = {
1595
+ algo: "",
1596
+ dest: "",
1597
+ params: ""
1598
+ }) {
1599
+ if (!this.walletClient.account) throw new Error("Wallet client account required to compute requestId");
1600
+ if (!this.publicClient.chain?.id) throw new Error("Public client chain required to compute requestId");
1601
+ return getRequestId({
1602
+ payload: `0x${Buffer.from(args.payload).toString("hex")}`,
1603
+ path: args.path,
1604
+ keyVersion: args.key_version,
1605
+ algo: options.algo ?? "",
1606
+ dest: options.dest ?? "",
1607
+ params: options.params ?? "",
1608
+ address: this.walletClient.account.address,
1609
+ chainId: BigInt(this.publicClient.chain.id)
1610
+ });
1611
+ }
1612
+ async getErrorFromEvents(requestId, fromBlock) {
1613
+ const errorLogs = await this.publicClient.getContractEvents({
1614
+ address: this.contractAddress,
1615
+ abi,
1616
+ eventName: "SignatureError",
1617
+ args: { requestId },
1618
+ fromBlock,
1619
+ toBlock: "latest"
1620
+ });
1621
+ if (errorLogs.length > 0) {
1622
+ const { args: errorData } = errorLogs[errorLogs.length - 1];
1623
+ return errorData;
1624
+ }
1625
+ }
1626
+ /**
1627
+ * Searches for SignatureResponded events that match the given requestId.
1628
+ * It works in conjunction with the getRequestId method which generates the unique
1629
+ * identifier for a signature request.
1630
+ *
1631
+ * @param requestId - The identifier for the signature request
1632
+ * @param fromBlock - The block number to start searching from
1633
+ * @returns The RSV signature if found, undefined otherwise
1634
+ */
1635
+ async getSignatureFromEvents(requestId, fromBlock) {
1636
+ const logs = await this.publicClient.getContractEvents({
1637
+ address: this.contractAddress,
1638
+ abi,
1639
+ eventName: "SignatureResponded",
1640
+ args: { requestId },
1641
+ fromBlock,
1642
+ toBlock: "latest"
1643
+ });
1644
+ if (logs.length > 0) {
1645
+ const { args: signatureData } = logs[logs.length - 1];
1646
+ return toRSV(signatureData.signature);
1647
+ }
1648
+ }
1649
+ };
1650
+
1651
+ //#endregion
1652
+ //#region src/contracts/evm/index.ts
1653
+ var evm_exports = /* @__PURE__ */ __export({
1654
+ ChainSignatureContract: () => ChainSignatureContract$2,
1655
+ utils: () => utils$1
1656
+ });
1657
+ const utils$1 = {
1658
+ ChainSignaturesContractABI: ChainSignaturesContractABI_exports,
1659
+ errors: errors_exports$1
1660
+ };
1661
+
1662
+ //#endregion
1663
+ //#region src/contracts/solana/errors.ts
1664
+ var errors_exports = /* @__PURE__ */ __export({
1665
+ ResponseError: () => ResponseError,
1666
+ SignatureContractError: () => SignatureContractError,
1667
+ SignatureNotFoundError: () => SignatureNotFoundError,
1668
+ SigningError: () => SigningError
1669
+ });
1670
+ var SignatureNotFoundError = class extends Error {
1671
+ constructor(requestId, metadata$1) {
1672
+ const message = requestId ? `Signature not found for request ID: ${requestId}` : "Signature not found";
1673
+ super(message);
1674
+ this.name = "SignatureNotFoundError";
1675
+ this.requestId = requestId;
1676
+ this.hash = metadata$1?.hash;
1677
+ }
1678
+ };
1679
+ var SignatureContractError = class extends Error {
1680
+ constructor(message, requestId, metadata$1) {
1681
+ super(message);
1682
+ this.name = "SignatureContractError";
1683
+ this.requestId = requestId;
1684
+ this.hash = metadata$1?.hash;
1685
+ }
1686
+ };
1687
+ var SigningError = class extends Error {
1688
+ constructor(requestId, metadata$1, originalError) {
1689
+ super(`Signing error for request ID: ${requestId}`);
1690
+ this.name = "SigningError";
1691
+ this.requestId = requestId;
1692
+ this.hash = metadata$1?.hash;
1693
+ this.originalError = originalError;
1694
+ }
1695
+ };
1696
+ var ResponseError = class extends Error {
1697
+ constructor(message) {
1698
+ super(message);
1699
+ this.name = "ResponseError";
1700
+ }
1701
+ };
1702
+
1703
+ //#endregion
1704
+ //#region src/contracts/solana/types/chain_signatures_project.json
1705
+ var chain_signatures_project_exports = /* @__PURE__ */ __export({
1706
+ accounts: () => accounts,
1707
+ address: () => address,
1708
+ default: () => chain_signatures_project_default,
1709
+ errors: () => errors,
1710
+ events: () => events,
1711
+ instructions: () => instructions,
1712
+ metadata: () => metadata,
1713
+ types: () => types
1714
+ });
1715
+ var address = "H5tHfpYoEnarrrzcV7sWBcZhiKMvL2aRpUYvb1ydWkwS";
1716
+ var metadata = {
1717
+ "name": "chain_signatures",
1718
+ "version": "0.4.0",
1719
+ "spec": "0.1.0",
1720
+ "description": "Chain signatures program for cross-chain signing on Solana",
1721
+ "repository": "https://github.com/sig-net/signet-solana-program"
1722
+ };
1723
+ var instructions = [
1724
+ {
1725
+ "name": "get_signature_deposit",
1726
+ "docs": ["* @dev Function to get the current signature deposit amount.\n * @return The current signature deposit amount."],
1727
+ "discriminator": [
1728
+ 45,
1729
+ 243,
1730
+ 86,
1731
+ 86,
1732
+ 58,
1733
+ 57,
1734
+ 172,
1735
+ 253
1736
+ ],
1737
+ "accounts": [{
1738
+ "name": "program_state",
1739
+ "pda": { "seeds": [{
1740
+ "kind": "const",
1741
+ "value": [
1742
+ 112,
1743
+ 114,
1744
+ 111,
1745
+ 103,
1746
+ 114,
1747
+ 97,
1748
+ 109,
1749
+ 45,
1750
+ 115,
1751
+ 116,
1752
+ 97,
1753
+ 116,
1754
+ 101
1755
+ ]
1756
+ }] }
1757
+ }],
1758
+ "args": [],
1759
+ "returns": "u64"
1760
+ },
1761
+ {
1762
+ "name": "initialize",
1763
+ "docs": ["* @dev Function to initialize the program state.\n * @param signature_deposit The deposit required for signature requests.\n * @param chain_id The CAIP-2 chain identifier."],
1764
+ "discriminator": [
1765
+ 175,
1766
+ 175,
1767
+ 109,
1768
+ 31,
1769
+ 13,
1770
+ 152,
1771
+ 155,
1772
+ 237
1773
+ ],
1774
+ "accounts": [
1775
+ {
1776
+ "name": "program_state",
1777
+ "writable": true,
1778
+ "pda": { "seeds": [{
1779
+ "kind": "const",
1780
+ "value": [
1781
+ 112,
1782
+ 114,
1783
+ 111,
1784
+ 103,
1785
+ 114,
1786
+ 97,
1787
+ 109,
1788
+ 45,
1789
+ 115,
1790
+ 116,
1791
+ 97,
1792
+ 116,
1793
+ 101
1794
+ ]
1795
+ }] }
1796
+ },
1797
+ {
1798
+ "name": "admin",
1799
+ "writable": true,
1800
+ "signer": true
1801
+ },
1802
+ {
1803
+ "name": "system_program",
1804
+ "address": "11111111111111111111111111111111"
1805
+ }
1806
+ ],
1807
+ "args": [{
1808
+ "name": "signature_deposit",
1809
+ "type": "u64"
1810
+ }, {
1811
+ "name": "chain_id",
1812
+ "type": "string"
1813
+ }]
1814
+ },
1815
+ {
1816
+ "name": "respond",
1817
+ "docs": ["* @dev Function to respond to signature requests.\n * @param request_ids The array of request IDs.\n * @param signatures The array of signature responses.\n * @notice When multiple entries reuse a request id, events emit in canonical signature order (PSBT-style)."],
1818
+ "discriminator": [
1819
+ 72,
1820
+ 65,
1821
+ 227,
1822
+ 97,
1823
+ 42,
1824
+ 255,
1825
+ 147,
1826
+ 12
1827
+ ],
1828
+ "accounts": [
1829
+ {
1830
+ "name": "responder",
1831
+ "signer": true
1832
+ },
1833
+ {
1834
+ "name": "event_authority",
1835
+ "pda": { "seeds": [{
1836
+ "kind": "const",
1837
+ "value": [
1838
+ 95,
1839
+ 95,
1840
+ 101,
1841
+ 118,
1842
+ 101,
1843
+ 110,
1844
+ 116,
1845
+ 95,
1846
+ 97,
1847
+ 117,
1848
+ 116,
1849
+ 104,
1850
+ 111,
1851
+ 114,
1852
+ 105,
1853
+ 116,
1854
+ 121
1855
+ ]
1856
+ }] }
1857
+ },
1858
+ { "name": "program" }
1859
+ ],
1860
+ "args": [{
1861
+ "name": "request_ids",
1862
+ "type": { "vec": { "array": ["u8", 32] } }
1863
+ }, {
1864
+ "name": "signatures",
1865
+ "type": { "vec": { "defined": { "name": "Signature" } } }
1866
+ }]
1867
+ },
1868
+ {
1869
+ "name": "respond_bidirectional",
1870
+ "docs": ["* @dev Function to finalize bidirectional flow\n * @param request_id The ID of the signature request to respond to\n * @param serialized_output output of the previously executed transaction\n * @param signature ECDSA signature of the serialized output and request_id (keccak256(request_id.concat(serialized_output)))"],
1871
+ "discriminator": [
1872
+ 138,
1873
+ 0,
1874
+ 45,
1875
+ 246,
1876
+ 236,
1877
+ 211,
1878
+ 109,
1879
+ 81
1880
+ ],
1881
+ "accounts": [{
1882
+ "name": "responder",
1883
+ "signer": true
1884
+ }],
1885
+ "args": [
1886
+ {
1887
+ "name": "request_id",
1888
+ "type": { "array": ["u8", 32] }
1889
+ },
1890
+ {
1891
+ "name": "serialized_output",
1892
+ "type": "bytes"
1893
+ },
1894
+ {
1895
+ "name": "signature",
1896
+ "type": { "defined": { "name": "Signature" } }
1897
+ }
1898
+ ]
1899
+ },
1900
+ {
1901
+ "name": "respond_error",
1902
+ "docs": ["* @dev Function to emit signature generation errors.\n * @param errors The array of signature generation errors."],
1903
+ "discriminator": [
1904
+ 3,
1905
+ 170,
1906
+ 41,
1907
+ 132,
1908
+ 72,
1909
+ 184,
1910
+ 252,
1911
+ 69
1912
+ ],
1913
+ "accounts": [{
1914
+ "name": "responder",
1915
+ "signer": true
1916
+ }],
1917
+ "args": [{
1918
+ "name": "errors",
1919
+ "type": { "vec": { "defined": { "name": "ErrorResponse" } } }
1920
+ }]
1921
+ },
1922
+ {
1923
+ "name": "sign",
1924
+ "docs": ["* @dev Function to request a signature.\n * @param payload The payload to be signed.\n * @param key_version The version of the key used for signing.\n * @param path The derivation path for the user account.\n * @param algo The algorithm used for signing.\n * @param dest The response destination.\n * @param params Additional parameters."],
1925
+ "discriminator": [
1926
+ 5,
1927
+ 221,
1928
+ 155,
1929
+ 46,
1930
+ 237,
1931
+ 91,
1932
+ 28,
1933
+ 236
1934
+ ],
1935
+ "accounts": [
1936
+ {
1937
+ "name": "program_state",
1938
+ "writable": true,
1939
+ "pda": { "seeds": [{
1940
+ "kind": "const",
1941
+ "value": [
1942
+ 112,
1943
+ 114,
1944
+ 111,
1945
+ 103,
1946
+ 114,
1947
+ 97,
1948
+ 109,
1949
+ 45,
1950
+ 115,
1951
+ 116,
1952
+ 97,
1953
+ 116,
1954
+ 101
1955
+ ]
1956
+ }] }
1957
+ },
1958
+ {
1959
+ "name": "requester",
1960
+ "writable": true,
1961
+ "signer": true
1962
+ },
1963
+ {
1964
+ "name": "fee_payer",
1965
+ "writable": true,
1966
+ "signer": true,
1967
+ "optional": true
1968
+ },
1969
+ {
1970
+ "name": "system_program",
1971
+ "address": "11111111111111111111111111111111"
1972
+ },
1973
+ {
1974
+ "name": "event_authority",
1975
+ "pda": { "seeds": [{
1976
+ "kind": "const",
1977
+ "value": [
1978
+ 95,
1979
+ 95,
1980
+ 101,
1981
+ 118,
1982
+ 101,
1983
+ 110,
1984
+ 116,
1985
+ 95,
1986
+ 97,
1987
+ 117,
1988
+ 116,
1989
+ 104,
1990
+ 111,
1991
+ 114,
1992
+ 105,
1993
+ 116,
1994
+ 121
1995
+ ]
1996
+ }] }
1997
+ },
1998
+ { "name": "program" }
1999
+ ],
2000
+ "args": [
2001
+ {
2002
+ "name": "payload",
2003
+ "type": { "array": ["u8", 32] }
2004
+ },
2005
+ {
2006
+ "name": "key_version",
2007
+ "type": "u32"
2008
+ },
2009
+ {
2010
+ "name": "path",
2011
+ "type": "string"
2012
+ },
2013
+ {
2014
+ "name": "algo",
2015
+ "type": "string"
2016
+ },
2017
+ {
2018
+ "name": "dest",
2019
+ "type": "string"
2020
+ },
2021
+ {
2022
+ "name": "params",
2023
+ "type": "string"
2024
+ }
2025
+ ]
2026
+ },
2027
+ {
2028
+ "name": "sign_bidirectional",
2029
+ "docs": ["* @dev Function to initiate bidirectional flow\n * @param serialized_transaction transaction to be signed\n * @param caip2_id chain identifier\n * @param key_version The version of the key used for signing.\n * @param path The derivation path for the user account.\n * @param algo The algorithm used for signing.\n * @param dest The response destination.\n * @param params Additional parameters.\n * @param program_id Program ID to callback after execution (not yet enabled).\n * @param output_deserialization_schema schema for transaction output deserialization\n * @param respond_serialization_schema serialization schema for respond_bidirectional payload"],
2030
+ "discriminator": [
2031
+ 21,
2032
+ 104,
2033
+ 182,
2034
+ 213,
2035
+ 189,
2036
+ 143,
2037
+ 219,
2038
+ 48
2039
+ ],
2040
+ "accounts": [
2041
+ {
2042
+ "name": "program_state",
2043
+ "writable": true,
2044
+ "pda": { "seeds": [{
2045
+ "kind": "const",
2046
+ "value": [
2047
+ 112,
2048
+ 114,
2049
+ 111,
2050
+ 103,
2051
+ 114,
2052
+ 97,
2053
+ 109,
2054
+ 45,
2055
+ 115,
2056
+ 116,
2057
+ 97,
2058
+ 116,
2059
+ 101
2060
+ ]
2061
+ }] }
2062
+ },
2063
+ {
2064
+ "name": "requester",
2065
+ "writable": true,
2066
+ "signer": true
2067
+ },
2068
+ {
2069
+ "name": "fee_payer",
2070
+ "writable": true,
2071
+ "signer": true,
2072
+ "optional": true
2073
+ },
2074
+ {
2075
+ "name": "system_program",
2076
+ "address": "11111111111111111111111111111111"
2077
+ },
2078
+ {
2079
+ "name": "instructions",
2080
+ "optional": true
2081
+ },
2082
+ {
2083
+ "name": "event_authority",
2084
+ "pda": { "seeds": [{
2085
+ "kind": "const",
2086
+ "value": [
2087
+ 95,
2088
+ 95,
2089
+ 101,
2090
+ 118,
2091
+ 101,
2092
+ 110,
2093
+ 116,
2094
+ 95,
2095
+ 97,
2096
+ 117,
2097
+ 116,
2098
+ 104,
2099
+ 111,
2100
+ 114,
2101
+ 105,
2102
+ 116,
2103
+ 121
2104
+ ]
2105
+ }] }
2106
+ },
2107
+ { "name": "program" }
2108
+ ],
2109
+ "args": [
2110
+ {
2111
+ "name": "serialized_transaction",
2112
+ "type": "bytes"
2113
+ },
2114
+ {
2115
+ "name": "caip2_id",
2116
+ "type": "string"
2117
+ },
2118
+ {
2119
+ "name": "key_version",
2120
+ "type": "u32"
2121
+ },
2122
+ {
2123
+ "name": "path",
2124
+ "type": "string"
2125
+ },
2126
+ {
2127
+ "name": "algo",
2128
+ "type": "string"
2129
+ },
2130
+ {
2131
+ "name": "dest",
2132
+ "type": "string"
2133
+ },
2134
+ {
2135
+ "name": "params",
2136
+ "type": "string"
2137
+ },
2138
+ {
2139
+ "name": "program_id",
2140
+ "type": "pubkey"
2141
+ },
2142
+ {
2143
+ "name": "output_deserialization_schema",
2144
+ "type": "bytes"
2145
+ },
2146
+ {
2147
+ "name": "respond_serialization_schema",
2148
+ "type": "bytes"
2149
+ }
2150
+ ]
2151
+ },
2152
+ {
2153
+ "name": "update_deposit",
2154
+ "docs": ["* @dev Function to set the signature deposit amount.\n * @param new_deposit The new deposit amount."],
2155
+ "discriminator": [
2156
+ 126,
2157
+ 116,
2158
+ 15,
2159
+ 164,
2160
+ 238,
2161
+ 179,
2162
+ 155,
2163
+ 59
2164
+ ],
2165
+ "accounts": [
2166
+ {
2167
+ "name": "program_state",
2168
+ "writable": true,
2169
+ "pda": { "seeds": [{
2170
+ "kind": "const",
2171
+ "value": [
2172
+ 112,
2173
+ 114,
2174
+ 111,
2175
+ 103,
2176
+ 114,
2177
+ 97,
2178
+ 109,
2179
+ 45,
2180
+ 115,
2181
+ 116,
2182
+ 97,
2183
+ 116,
2184
+ 101
2185
+ ]
2186
+ }] }
2187
+ },
2188
+ {
2189
+ "name": "admin",
2190
+ "writable": true,
2191
+ "signer": true,
2192
+ "relations": ["program_state"]
2193
+ },
2194
+ {
2195
+ "name": "system_program",
2196
+ "address": "11111111111111111111111111111111"
2197
+ }
2198
+ ],
2199
+ "args": [{
2200
+ "name": "new_deposit",
2201
+ "type": "u64"
2202
+ }]
2203
+ },
2204
+ {
2205
+ "name": "withdraw_funds",
2206
+ "docs": ["* @dev Function to withdraw funds from the program.\n * @param amount The amount to withdraw."],
2207
+ "discriminator": [
2208
+ 241,
2209
+ 36,
2210
+ 29,
2211
+ 111,
2212
+ 208,
2213
+ 31,
2214
+ 104,
2215
+ 217
2216
+ ],
2217
+ "accounts": [
2218
+ {
2219
+ "name": "program_state",
2220
+ "writable": true,
2221
+ "pda": { "seeds": [{
2222
+ "kind": "const",
2223
+ "value": [
2224
+ 112,
2225
+ 114,
2226
+ 111,
2227
+ 103,
2228
+ 114,
2229
+ 97,
2230
+ 109,
2231
+ 45,
2232
+ 115,
2233
+ 116,
2234
+ 97,
2235
+ 116,
2236
+ 101
2237
+ ]
2238
+ }] }
2239
+ },
2240
+ {
2241
+ "name": "admin",
2242
+ "writable": true,
2243
+ "signer": true,
2244
+ "relations": ["program_state"]
2245
+ },
2246
+ {
2247
+ "name": "recipient",
2248
+ "docs": ["function by checking it is not the zero address."],
2249
+ "writable": true
2250
+ },
2251
+ {
2252
+ "name": "system_program",
2253
+ "address": "11111111111111111111111111111111"
2254
+ }
2255
+ ],
2256
+ "args": [{
2257
+ "name": "amount",
2258
+ "type": "u64"
2259
+ }]
2260
+ }
2261
+ ];
2262
+ var accounts = [{
2263
+ "name": "ProgramState",
2264
+ "discriminator": [
2265
+ 77,
2266
+ 209,
2267
+ 137,
2268
+ 229,
2269
+ 149,
2270
+ 67,
2271
+ 167,
2272
+ 230
2273
+ ]
2274
+ }];
2275
+ var events = [
2276
+ {
2277
+ "name": "DepositUpdatedEvent",
2278
+ "discriminator": [
2279
+ 215,
2280
+ 193,
2281
+ 53,
2282
+ 27,
2283
+ 221,
2284
+ 101,
2285
+ 249,
2286
+ 108
2287
+ ]
2288
+ },
2289
+ {
2290
+ "name": "FundsWithdrawnEvent",
2291
+ "discriminator": [
2292
+ 86,
2293
+ 232,
2294
+ 194,
2295
+ 4,
2296
+ 211,
2297
+ 69,
2298
+ 172,
2299
+ 202
2300
+ ]
2301
+ },
2302
+ {
2303
+ "name": "RespondBidirectionalEvent",
2304
+ "discriminator": [
2305
+ 195,
2306
+ 195,
2307
+ 28,
2308
+ 1,
2309
+ 102,
2310
+ 100,
2311
+ 189,
2312
+ 234
2313
+ ]
2314
+ },
2315
+ {
2316
+ "name": "SignBidirectionalEvent",
2317
+ "discriminator": [
2318
+ 135,
2319
+ 205,
2320
+ 217,
2321
+ 152,
2322
+ 96,
2323
+ 187,
2324
+ 11,
2325
+ 124
2326
+ ]
2327
+ },
2328
+ {
2329
+ "name": "SignatureErrorEvent",
2330
+ "discriminator": [
2331
+ 42,
2332
+ 28,
2333
+ 210,
2334
+ 105,
2335
+ 9,
2336
+ 196,
2337
+ 189,
2338
+ 51
2339
+ ]
2340
+ },
2341
+ {
2342
+ "name": "SignatureRequestedEvent",
2343
+ "discriminator": [
2344
+ 171,
2345
+ 129,
2346
+ 105,
2347
+ 91,
2348
+ 154,
2349
+ 49,
2350
+ 160,
2351
+ 34
2352
+ ]
2353
+ },
2354
+ {
2355
+ "name": "SignatureRespondedEvent",
2356
+ "discriminator": [
2357
+ 118,
2358
+ 146,
2359
+ 248,
2360
+ 151,
2361
+ 194,
2362
+ 93,
2363
+ 18,
2364
+ 86
2365
+ ]
2366
+ }
2367
+ ];
2368
+ var errors = [
2369
+ {
2370
+ "code": 6e3,
2371
+ "name": "InsufficientDeposit",
2372
+ "msg": "Insufficient deposit amount"
2373
+ },
2374
+ {
2375
+ "code": 6001,
2376
+ "name": "InvalidInputLength",
2377
+ "msg": "Arrays must have the same length"
2378
+ },
2379
+ {
2380
+ "code": 6002,
2381
+ "name": "Unauthorized",
2382
+ "msg": "Unauthorized access"
2383
+ },
2384
+ {
2385
+ "code": 6003,
2386
+ "name": "InsufficientFunds",
2387
+ "msg": "Insufficient funds for withdrawal"
2388
+ },
2389
+ {
2390
+ "code": 6004,
2391
+ "name": "InvalidRecipient",
2392
+ "msg": "Invalid recipient address"
2393
+ },
2394
+ {
2395
+ "code": 6005,
2396
+ "name": "InvalidTransaction",
2397
+ "msg": "Invalid transaction data"
2398
+ },
2399
+ {
2400
+ "code": 6006,
2401
+ "name": "MissingInstructionSysvar",
2402
+ "msg": "Missing instruction sysvar"
2403
+ }
2404
+ ];
2405
+ var types = [
2406
+ {
2407
+ "name": "AffinePoint",
2408
+ "type": {
2409
+ "kind": "struct",
2410
+ "fields": [{
2411
+ "name": "x",
2412
+ "type": { "array": ["u8", 32] }
2413
+ }, {
2414
+ "name": "y",
2415
+ "type": { "array": ["u8", 32] }
2416
+ }]
2417
+ }
2418
+ },
2419
+ {
2420
+ "name": "DepositUpdatedEvent",
2421
+ "docs": ["* @dev Emitted when the deposit amount is updated.\n * @param old_deposit The previous deposit amount.\n * @param new_deposit The new deposit amount."],
2422
+ "type": {
2423
+ "kind": "struct",
2424
+ "fields": [{
2425
+ "name": "old_deposit",
2426
+ "type": "u64"
2427
+ }, {
2428
+ "name": "new_deposit",
2429
+ "type": "u64"
2430
+ }]
2431
+ }
2432
+ },
2433
+ {
2434
+ "name": "ErrorResponse",
2435
+ "type": {
2436
+ "kind": "struct",
2437
+ "fields": [{
2438
+ "name": "request_id",
2439
+ "type": { "array": ["u8", 32] }
2440
+ }, {
2441
+ "name": "error_message",
2442
+ "type": "string"
2443
+ }]
2444
+ }
2445
+ },
2446
+ {
2447
+ "name": "FundsWithdrawnEvent",
2448
+ "docs": ["* @dev Emitted when a withdrawal is made.\n * @param amount The amount withdrawn.\n * @param recipient The address of the recipient."],
2449
+ "type": {
2450
+ "kind": "struct",
2451
+ "fields": [{
2452
+ "name": "amount",
2453
+ "type": "u64"
2454
+ }, {
2455
+ "name": "recipient",
2456
+ "type": "pubkey"
2457
+ }]
2458
+ }
2459
+ },
2460
+ {
2461
+ "name": "ProgramState",
2462
+ "type": {
2463
+ "kind": "struct",
2464
+ "fields": [
2465
+ {
2466
+ "name": "admin",
2467
+ "type": "pubkey"
2468
+ },
2469
+ {
2470
+ "name": "signature_deposit",
2471
+ "type": "u64"
2472
+ },
2473
+ {
2474
+ "name": "chain_id",
2475
+ "type": "string"
2476
+ }
2477
+ ]
2478
+ }
2479
+ },
2480
+ {
2481
+ "name": "RespondBidirectionalEvent",
2482
+ "docs": ["* @dev Emitted when a read response is received.\n * @param request_id The ID of the request. Must be calculated off-chain.\n * @param responder The address of the responder.\n * @param serialized_output The serialized output.\n * @param signature The signature."],
2483
+ "type": {
2484
+ "kind": "struct",
2485
+ "fields": [
2486
+ {
2487
+ "name": "request_id",
2488
+ "type": { "array": ["u8", 32] }
2489
+ },
2490
+ {
2491
+ "name": "responder",
2492
+ "type": "pubkey"
2493
+ },
2494
+ {
2495
+ "name": "serialized_output",
2496
+ "type": "bytes"
2497
+ },
2498
+ {
2499
+ "name": "signature",
2500
+ "type": { "defined": { "name": "Signature" } }
2501
+ }
2502
+ ]
2503
+ }
2504
+ },
2505
+ {
2506
+ "name": "SignBidirectionalEvent",
2507
+ "docs": ["* @dev Emitted when a sign_bidirectional request is made.\n * @param sender The address of the sender.\n * @param serialized_transaction The serialized transaction to be signed.\n * @param caip2_id The SLIP-44 chain ID.\n * @param key_version The version of the key used for signing.\n * @param deposit The deposit amount.\n * @param path The derivation path for the user account.\n * @param algo The algorithm used for signing.\n * @param dest The response destination.\n * @param params Additional parameters.\n * @param program_id Program ID to callback after execution (not yet enabled).\n * @param output_deserialization_schema Schema for transaction output deserialization.\n * @param respond_serialization_schema Serialization schema for respond_bidirectional payload."],
2508
+ "type": {
2509
+ "kind": "struct",
2510
+ "fields": [
2511
+ {
2512
+ "name": "sender",
2513
+ "type": "pubkey"
2514
+ },
2515
+ {
2516
+ "name": "serialized_transaction",
2517
+ "type": "bytes"
2518
+ },
2519
+ {
2520
+ "name": "caip2_id",
2521
+ "type": "string"
2522
+ },
2523
+ {
2524
+ "name": "key_version",
2525
+ "type": "u32"
2526
+ },
2527
+ {
2528
+ "name": "deposit",
2529
+ "type": "u64"
2530
+ },
2531
+ {
2532
+ "name": "path",
2533
+ "type": "string"
2534
+ },
2535
+ {
2536
+ "name": "algo",
2537
+ "type": "string"
2538
+ },
2539
+ {
2540
+ "name": "dest",
2541
+ "type": "string"
2542
+ },
2543
+ {
2544
+ "name": "params",
2545
+ "type": "string"
2546
+ },
2547
+ {
2548
+ "name": "program_id",
2549
+ "type": "pubkey"
2550
+ },
2551
+ {
2552
+ "name": "output_deserialization_schema",
2553
+ "type": "bytes"
2554
+ },
2555
+ {
2556
+ "name": "respond_serialization_schema",
2557
+ "type": "bytes"
2558
+ }
2559
+ ]
2560
+ }
2561
+ },
2562
+ {
2563
+ "name": "Signature",
2564
+ "type": {
2565
+ "kind": "struct",
2566
+ "fields": [
2567
+ {
2568
+ "name": "big_r",
2569
+ "type": { "defined": { "name": "AffinePoint" } }
2570
+ },
2571
+ {
2572
+ "name": "s",
2573
+ "type": { "array": ["u8", 32] }
2574
+ },
2575
+ {
2576
+ "name": "recovery_id",
2577
+ "type": "u8"
2578
+ }
2579
+ ]
2580
+ }
2581
+ },
2582
+ {
2583
+ "name": "SignatureErrorEvent",
2584
+ "docs": ["* @dev Emitted when a signature error is received.\n * @notice Any address can emit this event. Do not rely on it for business logic.\n * @param request_id The ID of the request. Must be calculated off-chain.\n * @param responder The address of the responder.\n * @param error The error message."],
2585
+ "type": {
2586
+ "kind": "struct",
2587
+ "fields": [
2588
+ {
2589
+ "name": "request_id",
2590
+ "type": { "array": ["u8", 32] }
2591
+ },
2592
+ {
2593
+ "name": "responder",
2594
+ "type": "pubkey"
2595
+ },
2596
+ {
2597
+ "name": "error",
2598
+ "type": "string"
2599
+ }
2600
+ ]
2601
+ }
2602
+ },
2603
+ {
2604
+ "name": "SignatureRequestedEvent",
2605
+ "docs": ["* @dev Emitted when a signature is requested.\n * @param sender The address of the sender.\n * @param payload The payload to be signed.\n * @param key_version The version of the key used for signing.\n * @param deposit The deposit amount.\n * @param chain_id The CAIP-2 ID of the blockchain.\n * @param path The derivation path for the user account.\n * @param algo The algorithm used for signing.\n * @param dest The response destination.\n * @param params Additional parameters.\n * @param fee_payer Optional fee payer account."],
2606
+ "type": {
2607
+ "kind": "struct",
2608
+ "fields": [
2609
+ {
2610
+ "name": "sender",
2611
+ "type": "pubkey"
2612
+ },
2613
+ {
2614
+ "name": "payload",
2615
+ "type": { "array": ["u8", 32] }
2616
+ },
2617
+ {
2618
+ "name": "key_version",
2619
+ "type": "u32"
2620
+ },
2621
+ {
2622
+ "name": "deposit",
2623
+ "type": "u64"
2624
+ },
2625
+ {
2626
+ "name": "chain_id",
2627
+ "type": "string"
2628
+ },
2629
+ {
2630
+ "name": "path",
2631
+ "type": "string"
2632
+ },
2633
+ {
2634
+ "name": "algo",
2635
+ "type": "string"
2636
+ },
2637
+ {
2638
+ "name": "dest",
2639
+ "type": "string"
2640
+ },
2641
+ {
2642
+ "name": "params",
2643
+ "type": "string"
2644
+ },
2645
+ {
2646
+ "name": "fee_payer",
2647
+ "type": { "option": "pubkey" }
2648
+ }
2649
+ ]
2650
+ }
2651
+ },
2652
+ {
2653
+ "name": "SignatureRespondedEvent",
2654
+ "docs": ["* @dev Emitted when a signature response is received.\n * @notice Any address can emit this event. Clients should always verify the validity of the signature.\n * @param request_id The ID of the request. Must be calculated off-chain.\n * @param responder The address of the responder.\n * @param signature The signature response."],
2655
+ "type": {
2656
+ "kind": "struct",
2657
+ "fields": [
2658
+ {
2659
+ "name": "request_id",
2660
+ "type": { "array": ["u8", 32] }
2661
+ },
2662
+ {
2663
+ "name": "responder",
2664
+ "type": "pubkey"
2665
+ },
2666
+ {
2667
+ "name": "signature",
2668
+ "type": { "defined": { "name": "Signature" } }
2669
+ }
2670
+ ]
2671
+ }
2672
+ }
2673
+ ];
2674
+ var chain_signatures_project_default = {
2675
+ address,
2676
+ metadata,
2677
+ instructions,
2678
+ accounts,
2679
+ events,
2680
+ errors,
2681
+ types
2682
+ };
2683
+
2684
+ //#endregion
2685
+ //#region src/contracts/solana/CpiEventParser.ts
2686
+ const EMIT_CPI_INSTRUCTION_DISCRIMINATOR = Buffer.from([
2687
+ 228,
2688
+ 69,
2689
+ 165,
2690
+ 46,
2691
+ 81,
2692
+ 203,
2693
+ 154,
2694
+ 29
2695
+ ]);
2696
+ var CpiEventParser = class {
2697
+ /**
2698
+ * Parse CPI events from a transaction (emit_cpi! pattern)
2699
+ */
2700
+ static async parseCpiEvents(connection, signature, targetProgramId, program) {
2701
+ const events$1 = [];
2702
+ try {
2703
+ const tx = await connection.getParsedTransaction(signature, {
2704
+ commitment: "confirmed",
2705
+ maxSupportedTransactionVersion: 0
2706
+ });
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;
2716
+ }
2717
+ /**
2718
+ * Parse CPI event from instruction data
2719
+ * Structure: [8 bytes: anchor discriminator][8 bytes: event discriminator][event data]
2720
+ */
2721
+ static parseInstruction(instructionData, program) {
2722
+ try {
2723
+ const ixData = __coral_xyz_anchor.utils.bytes.bs58.decode(instructionData);
2724
+ if (ixData.length < 16) return null;
2725
+ const ixDiscriminator = ixData.subarray(0, 8);
2726
+ if (Buffer.compare(ixDiscriminator, EMIT_CPI_INSTRUCTION_DISCRIMINATOR) !== 0) return null;
2727
+ const eventDiscriminator = ixData.subarray(8, 16);
2728
+ if (!program.idl.events?.find((event) => {
2729
+ const idlDiscriminator = Buffer.from(event.discriminator);
2730
+ return Buffer.compare(eventDiscriminator, idlDiscriminator) === 0;
2731
+ })) return null;
2732
+ const fullEventData = ixData.subarray(8);
2733
+ return program.coder.events.decode(__coral_xyz_anchor.utils.bytes.base64.encode(fullEventData));
2734
+ } catch {
2735
+ return null;
2736
+ }
2737
+ }
2738
+ /**
2739
+ * Subscribe to CPI events for a program
2740
+ */
2741
+ static subscribeToCpiEvents(connection, program, eventHandlers) {
2742
+ return connection.onLogs(program.programId, (logs, context) => {
2743
+ if (logs.err) return;
2744
+ (async () => {
2745
+ const events$1 = await this.parseCpiEvents(connection, logs.signature, program.programId.toString(), program);
2746
+ for (const event of events$1) {
2747
+ const handler = eventHandlers.get(event.name);
2748
+ if (handler) try {
2749
+ await handler(event.data, context.slot);
2750
+ } catch {}
2751
+ }
2752
+ })();
2753
+ }, "confirmed");
2754
+ }
2755
+ };
2756
+
2757
+ //#endregion
2758
+ //#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");
2761
+ return (0, viem.keccak256)((0, viem.encodeAbiParameters)((0, viem.parseAbiParameters)("string, bytes, string, uint32, string, string, string, string"), [
2762
+ address$1,
2763
+ payloadHex,
2764
+ path,
2765
+ keyVersion,
2766
+ chainId,
2767
+ algo,
2768
+ dest,
2769
+ params
2770
+ ]));
2771
+ }
2772
+
2773
+ //#endregion
2774
+ //#region src/contracts/solana/ChainSignaturesContract.ts
2775
+ var ChainSignatureContract$1 = class extends ChainSignatureContract {
2776
+ /**
2777
+ * Creates a new instance of the ChainSignatureContract for Solana chains.
2778
+ *
2779
+ * @param args - Configuration options for the contract
2780
+ * @param args.provider - An Anchor Provider for interacting with Solana
2781
+ * @param args.programId - The program ID as a string or PublicKey
2782
+ * @param args.config - Optional configuration
2783
+ * @param args.config.rootPublicKey - Optional root public key. If not provided, it will be derived from the program ID
2784
+ * @param args.config.requesterAddress - Provider wallet address is always the fee payer but requester can be overridden
2785
+ * @param args.config.idl - Optional custom IDL. If not provided, the default ChainSignatures IDL will be used
2786
+ */
2787
+ constructor(args) {
2788
+ super();
2789
+ this.provider = args.provider;
2790
+ this.requesterAddress = args.config?.requesterAddress ?? this.provider.wallet.publicKey.toString();
2791
+ this.programId = typeof args.programId === "string" ? new __solana_web3_js.PublicKey(args.programId) : args.programId;
2792
+ this.program = new __coral_xyz_anchor.Program({
2793
+ ...args.config?.idl || chain_signatures_project_default,
2794
+ address: this.programId.toString()
2795
+ }, this.provider);
2796
+ const rootPublicKey = args.config?.rootPublicKey || getRootPublicKey(this.programId.toString(), CHAINS.SOLANA);
2797
+ if (!rootPublicKey) throw new Error(`Invalid public key, please provide a valid root public key or program ID`);
2798
+ this.rootPublicKey = rootPublicKey;
2799
+ }
2800
+ /**
2801
+ * Gets the connection from the provider
2802
+ */
2803
+ get connection() {
2804
+ return this.provider.connection;
2805
+ }
2806
+ async getCurrentSignatureDeposit() {
2807
+ try {
2808
+ const programStatePDA = await this.getProgramStatePDA();
2809
+ return new bn_js.default((await this.program.account.programState.fetch(programStatePDA)).signatureDeposit.toString());
2810
+ } catch (error) {
2811
+ throw new Error(`Failed to get signature deposit: ${error instanceof Error ? error.message : String(error)}`);
2812
+ }
2813
+ }
2814
+ /**
2815
+ * Get the Program State PDA
2816
+ */
2817
+ async getProgramStatePDA() {
2818
+ const [pda] = __solana_web3_js.PublicKey.findProgramAddressSync([Buffer.from("program-state")], this.programId);
2819
+ return pda;
2820
+ }
2821
+ async getDerivedPublicKey(args) {
2822
+ return deriveChildPublicKey(await this.getPublicKey(), args.predecessor, args.path, KDF_CHAIN_IDS.SOLANA, args.keyVersion);
2823
+ }
2824
+ async getPublicKey() {
2825
+ return najToUncompressedPubKeySEC1(this.rootPublicKey);
2826
+ }
2827
+ async getSignRequestInstruction(args, options) {
2828
+ const fixedRemainingAccounts = [{
2829
+ pubkey: __solana_web3_js.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], this.program.programId)[0],
2830
+ isWritable: false,
2831
+ isSigner: false
2832
+ }, {
2833
+ pubkey: this.program.programId,
2834
+ isWritable: false,
2835
+ isSigner: false
2836
+ }];
2837
+ return await this.program.methods.sign(Array.from(args.payload), args.key_version, args.path, options?.sign?.algo || "", options?.sign?.dest || "", options?.sign?.params || "").accounts({
2838
+ requester: this.requesterAddress,
2839
+ feePayer: this.provider.wallet.publicKey,
2840
+ program: this.programId
2841
+ }).remainingAccounts([...fixedRemainingAccounts, ...options?.remainingAccounts ?? []]).instruction();
2842
+ }
2843
+ /**
2844
+ * 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.
2847
+ */
2848
+ async sign(args, options) {
2849
+ const algo = options?.sign?.algo ?? "";
2850
+ const dest = options?.sign?.dest ?? "";
2851
+ const params = options?.sign?.params ?? "";
2852
+ const delay = options?.retry?.delay ?? 5e3;
2853
+ const retryCount = options?.retry?.retryCount ?? 12;
2854
+ 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
+ const requestId = this.getRequestId(args, {
2856
+ algo,
2857
+ dest,
2858
+ params
2859
+ });
2860
+ const instruction = await this.getSignRequestInstruction(args, {
2861
+ sign: {
2862
+ algo,
2863
+ dest,
2864
+ params
2865
+ },
2866
+ remainingAccounts: options?.remainingAccounts
2867
+ });
2868
+ const transaction = new __solana_web3_js.Transaction().add(instruction);
2869
+ transaction.feePayer = this.provider.wallet.publicKey;
2870
+ const hash = await this.sendAndConfirmWithoutWebSocket(transaction, options?.remainingSigners);
2871
+ 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;
2886
+ } catch (error) {
2887
+ if (error instanceof SignatureNotFoundError || error instanceof SignatureContractError) throw error;
2888
+ else throw new SigningError(requestId, { hash }, error instanceof Error ? error : void 0);
2889
+ }
2890
+ }
2891
+ async sendAndConfirmWithoutWebSocket(transaction, signers) {
2892
+ const { blockhash } = await this.provider.connection.getLatestBlockhash("confirmed");
2893
+ transaction.recentBlockhash = blockhash;
2894
+ transaction = await this.provider.wallet.signTransaction(transaction);
2895
+ if (signers && signers.length > 0) transaction.partialSign(...signers);
2896
+ const signature = await this.provider.connection.sendRawTransaction(transaction.serialize(), {
2897
+ skipPreflight: false,
2898
+ preflightCommitment: "processed",
2899
+ maxRetries: 3
2900
+ });
2901
+ const startTime = Date.now();
2902
+ const timeout = 3e4;
2903
+ while (Date.now() - startTime < timeout) {
2904
+ const status = await this.provider.connection.getSignatureStatus(signature);
2905
+ if (status.value?.err) throw new Error(`Transaction failed: ${JSON.stringify(status.value.err)}`);
2906
+ if (status.value?.confirmationStatus === "confirmed" || status.value?.confirmationStatus === "finalized") return signature;
2907
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
2908
+ }
2909
+ throw new __solana_web3_js.TransactionExpiredTimeoutError(signature, timeout / 1e3);
2910
+ }
2911
+ /**
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.
2914
+ */
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
2930
+ });
2931
+ if (tx?.meta?.logMessages) {
2932
+ const result = await this.parseLogsForEvents(tx.meta.logMessages, requestId, sig.signature);
2933
+ if (result) return result;
2934
+ }
2935
+ }
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));
2942
+ }
2943
+ }
2944
+ }
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
+ }
2960
+ }
2961
+ mapEventToResult(name, data, requestId) {
2962
+ 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 {
2972
+ requestId: eventRequestIdHex,
2973
+ error: data.error
2974
+ };
2975
+ }
2976
+ /**
2977
+ * Generates the request ID for a signature request allowing to track the response.
2978
+ */
2979
+ getRequestId(args, options = {
2980
+ algo: "",
2981
+ dest: "",
2982
+ params: ""
2983
+ }) {
2984
+ return generateRequestIdSolana({
2985
+ payload: args.payload,
2986
+ path: args.path,
2987
+ keyVersion: args.key_version,
2988
+ algo: options.algo || "",
2989
+ dest: options.dest || "",
2990
+ params: options.params || "",
2991
+ address: this.requesterAddress,
2992
+ chainId: KDF_CHAIN_IDS.SOLANA
2993
+ });
2994
+ }
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
+ };
3036
+
3037
+ //#endregion
3038
+ //#region src/contracts/solana/index.ts
3039
+ var solana_exports = /* @__PURE__ */ __export({
3040
+ ChainSignatureContract: () => ChainSignatureContract$1,
3041
+ utils: () => utils
3042
+ });
3043
+ const utils = {
3044
+ ChainSignaturesContractIdl: chain_signatures_project_exports,
3045
+ errors: errors_exports
3046
+ };
3047
+
3048
+ //#endregion
3049
+ //#region src/contracts/index.ts
3050
+ var contracts_exports = /* @__PURE__ */ __export({
3051
+ ChainSignatureContract: () => ChainSignatureContract,
3052
+ evm: () => evm_exports,
3053
+ solana: () => solana_exports
3054
+ });
3055
+
3056
+ //#endregion
3057
+ Object.defineProperty(exports, 'chainAdapters', {
3058
+ enumerable: true,
3059
+ get: function () {
3060
+ return chain_adapters_exports;
3061
+ }
3062
+ });
3063
+ Object.defineProperty(exports, 'constants', {
3064
+ enumerable: true,
3065
+ get: function () {
3066
+ return constants_exports;
3067
+ }
3068
+ });
3069
+ Object.defineProperty(exports, 'contracts', {
3070
+ enumerable: true,
3071
+ get: function () {
3072
+ return contracts_exports;
3073
+ }
3074
+ });
3075
+ Object.defineProperty(exports, 'utils', {
3076
+ enumerable: true,
3077
+ get: function () {
3078
+ return utils_exports;
3079
+ }
3080
+ });