@sovereign-sdk/multisig 0.1.2 → 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.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -104,6 +104,21 @@ declare class MultisigTransaction {
|
|
|
104
104
|
* @returns A readonly view of the unsigned transaction
|
|
105
105
|
*/
|
|
106
106
|
get unsignedTransaction(): Readonly<UnsignedTransaction<unknown>>;
|
|
107
|
+
/**
|
|
108
|
+
* Gets the signatures and public keys collected so far.
|
|
109
|
+
* @returns A readonly view of the signatures and public keys
|
|
110
|
+
*/
|
|
111
|
+
get signaturesAndPubKeys(): Readonly<SignatureAndPubKey[]>;
|
|
112
|
+
/**
|
|
113
|
+
* Gets the remaining public keys that haven't signed yet.
|
|
114
|
+
* @returns A readonly view of the remaining public keys
|
|
115
|
+
*/
|
|
116
|
+
get remainingPubKeys(): Readonly<Set<HexString>>;
|
|
117
|
+
/**
|
|
118
|
+
* Gets the threshold number of signatures required for the multisig to be complete.
|
|
119
|
+
* @returns The threshold number of signatures
|
|
120
|
+
*/
|
|
121
|
+
get threshold(): number;
|
|
107
122
|
/**
|
|
108
123
|
* Converts the multisig to a V1 transaction that can be submitted to the network.
|
|
109
124
|
* @returns A V1 transaction containing all collected signatures and unused public keys
|
package/dist/index.d.ts
CHANGED
|
@@ -104,6 +104,21 @@ declare class MultisigTransaction {
|
|
|
104
104
|
* @returns A readonly view of the unsigned transaction
|
|
105
105
|
*/
|
|
106
106
|
get unsignedTransaction(): Readonly<UnsignedTransaction<unknown>>;
|
|
107
|
+
/**
|
|
108
|
+
* Gets the signatures and public keys collected so far.
|
|
109
|
+
* @returns A readonly view of the signatures and public keys
|
|
110
|
+
*/
|
|
111
|
+
get signaturesAndPubKeys(): Readonly<SignatureAndPubKey[]>;
|
|
112
|
+
/**
|
|
113
|
+
* Gets the remaining public keys that haven't signed yet.
|
|
114
|
+
* @returns A readonly view of the remaining public keys
|
|
115
|
+
*/
|
|
116
|
+
get remainingPubKeys(): Readonly<Set<HexString>>;
|
|
117
|
+
/**
|
|
118
|
+
* Gets the threshold number of signatures required for the multisig to be complete.
|
|
119
|
+
* @returns The threshold number of signatures
|
|
120
|
+
*/
|
|
121
|
+
get threshold(): number;
|
|
107
122
|
/**
|
|
108
123
|
* Converts the multisig to a V1 transaction that can be submitted to the network.
|
|
109
124
|
* @returns A V1 transaction containing all collected signatures and unused public keys
|
package/dist/index.js
CHANGED
|
@@ -153,6 +153,27 @@ var MultisigTransaction = class _MultisigTransaction {
|
|
|
153
153
|
get unsignedTransaction() {
|
|
154
154
|
return this.unsignedTx;
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Gets the signatures and public keys collected so far.
|
|
158
|
+
* @returns A readonly view of the signatures and public keys
|
|
159
|
+
*/
|
|
160
|
+
get signaturesAndPubKeys() {
|
|
161
|
+
return this.signatures;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Gets the remaining public keys that haven't signed yet.
|
|
165
|
+
* @returns A readonly view of the remaining public keys
|
|
166
|
+
*/
|
|
167
|
+
get remainingPubKeys() {
|
|
168
|
+
return this.unusedPubKeys;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Gets the threshold number of signatures required for the multisig to be complete.
|
|
172
|
+
* @returns The threshold number of signatures
|
|
173
|
+
*/
|
|
174
|
+
get threshold() {
|
|
175
|
+
return this.minSigners;
|
|
176
|
+
}
|
|
156
177
|
/**
|
|
157
178
|
* Converts the multisig to a V1 transaction that can be submitted to the network.
|
|
158
179
|
* @returns A V1 transaction containing all collected signatures and unused public keys
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n SignatureAndPubKey,\n Transaction,\n TransactionV0,\n UnsignedTransaction,\n} from \"@sovereign-sdk/types\";\nimport type { HexString } from \"@sovereign-sdk/utils\";\n\n/**\n * Base error class for multisig-related errors.\n */\nexport class MultisigError extends Error {}\n\n/**\n * Error thrown when a transaction has an unsupported version for multisig operations.\n */\nexport class InvalidTransactionVersionError extends MultisigError {}\n\n/**\n * Error thrown when a provided transaction doesn't match the expected unsigned transaction.\n */\nexport class TransactionMismatchError extends Error {\n constructor() {\n super(\n \"Provided transaction does not match the expected unsigned transaction\",\n );\n }\n}\n\n/**\n * Error thrown when multisig is constructed or used with invalid parameters.\n */\nexport class InvalidMultisigParameterError extends MultisigError {\n constructor(desc: string) {\n super(`Multisig was constructed with invalid parameter: ${desc}`);\n }\n}\n\n/**\n * Parameters for constructing a MultisigTransaction.\n */\nexport type MultisigParams = {\n /** The unsigned transaction to be signed by multiple parties */\n unsignedTx: UnsignedTransaction<unknown>;\n /** Array of signatures with pubkeys already collected */\n signatures: SignatureAndPubKey[];\n /** Array of public keys that haven't signed yet */\n unusedPubKeys: HexString[];\n /** Minimum number of signatures required */\n minSigners: number;\n};\n\n/**\n * Parameters for creating a MultisigTransaction from existing signed transactions.\n */\nexport type FromTransactionsParams = {\n /** Array of signed transactions to extract signatures from */\n txns: Transaction<unknown>[];\n /** Minimum number of signatures required */\n minSigners: number;\n /** All public keys that are members of the multisig */\n allPubKeys: HexString[];\n};\n\n/**\n * Represents a multisig transaction that collects signatures from multiple parties.\n * Only supports nonce-based transactions and V0 transaction variants for signature collection.\n */\nexport class MultisigTransaction {\n private unsignedTx: UnsignedTransaction<unknown>;\n private signatures: SignatureAndPubKey[] = [];\n private minSigners: number;\n private unusedPubKeys = new Set<HexString>();\n\n /**\n * Creates a new MultisigTransaction instance.\n * @param params - The multisig parameters including unsigned transaction, signatures, and public keys\n */\n constructor({\n unsignedTx,\n signatures,\n unusedPubKeys,\n minSigners,\n }: MultisigParams) {\n this.unsignedTx = unsignedTx;\n this.signatures = signatures;\n this.unusedPubKeys = new Set(unusedPubKeys);\n this.minSigners = minSigners;\n }\n\n /**\n * Creates an empty MultisigTransaction with no signatures collected yet.\n * @param unsignedTx - The unsigned transaction to be signed by multiple parties\n * @param minSigners - Minimum number of signatures required for completion\n * @param allPubKeys - All public keys that are members of the multisig\n * @returns A new empty MultisigTransaction instance\n */\n static empty(\n unsignedTx: UnsignedTransaction<unknown>,\n minSigners: number,\n allPubKeys: HexString[],\n ): MultisigTransaction {\n return new MultisigTransaction({\n unsignedTx,\n signatures: [],\n unusedPubKeys: allPubKeys,\n minSigners,\n });\n }\n\n /**\n * Creates a MultisigTransaction from an array of already-signed transactions.\n * Extracts signatures and validates that all transactions are identical except for signatures.\n * @param params - Parameters including the signed transactions, minimum signers, and all public keys\n * @returns A new MultisigTransaction instance\n * @throws {InvalidTransactionVersionError} If any transaction is not V0 variant\n * @throws {TransactionMismatchError} If transactions don't match each other\n * @throws {InvalidMultisigParameterError} If public keys are invalid or transaction is not nonce-based\n */\n static fromTransactions({\n txns,\n minSigners,\n allPubKeys,\n }: FromTransactionsParams): MultisigTransaction {\n const signatures: SignatureAndPubKey[] = [];\n const unsignedTx = asUnsignedTransaction(txns[0]);\n const unusedPubKeys = new Set<HexString>(allPubKeys);\n\n assertIsNonceBasedTx(unsignedTx);\n\n for (const tx of txns) {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n if (!unusedPubKeys.delete(pub_key)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pub_key}`,\n );\n }\n\n signatures.push({ pub_key, signature });\n }\n\n return new MultisigTransaction({\n unsignedTx,\n signatures,\n unusedPubKeys: Array.from(unusedPubKeys),\n minSigners,\n });\n }\n\n /**\n * Adds a signature & public key from a signed transaction to the multisig transaction.\n * @param tx - The signed transaction to extract signature from\n * @throws {InvalidTransactionVersionError} If the transaction is not V0 variant\n * @throws {TransactionMismatchError} If the transaction doesn't match the unsigned transaction\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignedTransaction(tx: Transaction<unknown>): void {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, this.unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n this.addSignature(signature, pub_key);\n }\n\n /**\n * Adds a signature to the multisig transaction.\n * @param signature - The signature to add\n * @param pubKey - The public key corresponding to the signature\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignature(signature: HexString, pubKey: HexString): void {\n if (!this.unusedPubKeys.delete(pubKey)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pubKey}`,\n );\n }\n\n this.signatures.push({ pub_key: pubKey, signature });\n }\n\n /**\n * Checks if the multisig has collected enough signatures to be complete.\n * @returns True if the number of signatures meets or exceeds the minimum required\n */\n get isComplete(): boolean {\n return this.signatures.length >= this.minSigners;\n }\n\n /**\n * Gets the unsigned transaction.\n * @returns A readonly view of the unsigned transaction\n */\n get unsignedTransaction(): Readonly<UnsignedTransaction<unknown>> {\n return this.unsignedTx;\n }\n\n /**\n * Converts the multisig to a V1 transaction that can be submitted to the network.\n * @returns A V1 transaction containing all collected signatures and unused public keys\n */\n asTransaction(): Transaction<unknown> {\n return {\n V1: {\n runtime_call: this.unsignedTx.runtime_call,\n uniqueness: this.unsignedTx.uniqueness,\n details: this.unsignedTx.details,\n unused_pub_keys: Array.from(this.unusedPubKeys),\n signatures: this.signatures,\n min_signers: this.minSigners,\n },\n };\n }\n}\n\nfunction assertTxVariant(\n tx: Transaction<unknown>,\n): asserts tx is TransactionV0<unknown> {\n if (\"V1\" in tx) {\n throw new InvalidTransactionVersionError(\n \"Input transaction was an unsupported variant (V1)\",\n );\n }\n}\n\nfunction asUnsignedTransaction(\n tx: Transaction<unknown>,\n): UnsignedTransaction<unknown> {\n if (\"V0\" in tx) {\n return {\n runtime_call: tx.V0.runtime_call,\n uniqueness: tx.V0.uniqueness,\n details: tx.V0.details,\n };\n }\n\n if (\"V1\" in tx) {\n return {\n runtime_call: tx.V1.runtime_call,\n uniqueness: tx.V1.uniqueness,\n details: tx.V1.details,\n };\n }\n\n throw new InvalidTransactionVersionError(\n \"Transaction variant is neither V0 nor V1\",\n );\n}\n\nfunction assertTxMatchesUnsignedTx(\n tx: Transaction<unknown>,\n unsignedTx: UnsignedTransaction<unknown>,\n): void {\n const txAsUnsigned = asUnsignedTransaction(tx);\n\n if (JSON.stringify(txAsUnsigned) !== JSON.stringify(unsignedTx)) {\n throw new TransactionMismatchError();\n }\n}\n\nfunction assertIsNonceBasedTx(unsignedTx: UnsignedTransaction<unknown>): void {\n if (!(\"nonce\" in unsignedTx.uniqueness)) {\n throw new InvalidMultisigParameterError(\n \"Only nonce-based transactions are supported for multisig\",\n );\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n SignatureAndPubKey,\n Transaction,\n TransactionV0,\n UnsignedTransaction,\n} from \"@sovereign-sdk/types\";\nimport type { HexString } from \"@sovereign-sdk/utils\";\n\n/**\n * Base error class for multisig-related errors.\n */\nexport class MultisigError extends Error {}\n\n/**\n * Error thrown when a transaction has an unsupported version for multisig operations.\n */\nexport class InvalidTransactionVersionError extends MultisigError {}\n\n/**\n * Error thrown when a provided transaction doesn't match the expected unsigned transaction.\n */\nexport class TransactionMismatchError extends Error {\n constructor() {\n super(\n \"Provided transaction does not match the expected unsigned transaction\",\n );\n }\n}\n\n/**\n * Error thrown when multisig is constructed or used with invalid parameters.\n */\nexport class InvalidMultisigParameterError extends MultisigError {\n constructor(desc: string) {\n super(`Multisig was constructed with invalid parameter: ${desc}`);\n }\n}\n\n/**\n * Parameters for constructing a MultisigTransaction.\n */\nexport type MultisigParams = {\n /** The unsigned transaction to be signed by multiple parties */\n unsignedTx: UnsignedTransaction<unknown>;\n /** Array of signatures with pubkeys already collected */\n signatures: SignatureAndPubKey[];\n /** Array of public keys that haven't signed yet */\n unusedPubKeys: HexString[];\n /** Minimum number of signatures required */\n minSigners: number;\n};\n\n/**\n * Parameters for creating a MultisigTransaction from existing signed transactions.\n */\nexport type FromTransactionsParams = {\n /** Array of signed transactions to extract signatures from */\n txns: Transaction<unknown>[];\n /** Minimum number of signatures required */\n minSigners: number;\n /** All public keys that are members of the multisig */\n allPubKeys: HexString[];\n};\n\n/**\n * Represents a multisig transaction that collects signatures from multiple parties.\n * Only supports nonce-based transactions and V0 transaction variants for signature collection.\n */\nexport class MultisigTransaction {\n private unsignedTx: UnsignedTransaction<unknown>;\n private signatures: SignatureAndPubKey[] = [];\n private minSigners: number;\n private unusedPubKeys = new Set<HexString>();\n\n /**\n * Creates a new MultisigTransaction instance.\n * @param params - The multisig parameters including unsigned transaction, signatures, and public keys\n */\n constructor({\n unsignedTx,\n signatures,\n unusedPubKeys,\n minSigners,\n }: MultisigParams) {\n this.unsignedTx = unsignedTx;\n this.signatures = signatures;\n this.unusedPubKeys = new Set(unusedPubKeys);\n this.minSigners = minSigners;\n }\n\n /**\n * Creates an empty MultisigTransaction with no signatures collected yet.\n * @param unsignedTx - The unsigned transaction to be signed by multiple parties\n * @param minSigners - Minimum number of signatures required for completion\n * @param allPubKeys - All public keys that are members of the multisig\n * @returns A new empty MultisigTransaction instance\n */\n static empty(\n unsignedTx: UnsignedTransaction<unknown>,\n minSigners: number,\n allPubKeys: HexString[],\n ): MultisigTransaction {\n return new MultisigTransaction({\n unsignedTx,\n signatures: [],\n unusedPubKeys: allPubKeys,\n minSigners,\n });\n }\n\n /**\n * Creates a MultisigTransaction from an array of already-signed transactions.\n * Extracts signatures and validates that all transactions are identical except for signatures.\n * @param params - Parameters including the signed transactions, minimum signers, and all public keys\n * @returns A new MultisigTransaction instance\n * @throws {InvalidTransactionVersionError} If any transaction is not V0 variant\n * @throws {TransactionMismatchError} If transactions don't match each other\n * @throws {InvalidMultisigParameterError} If public keys are invalid or transaction is not nonce-based\n */\n static fromTransactions({\n txns,\n minSigners,\n allPubKeys,\n }: FromTransactionsParams): MultisigTransaction {\n const signatures: SignatureAndPubKey[] = [];\n const unsignedTx = asUnsignedTransaction(txns[0]);\n const unusedPubKeys = new Set<HexString>(allPubKeys);\n\n assertIsNonceBasedTx(unsignedTx);\n\n for (const tx of txns) {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n if (!unusedPubKeys.delete(pub_key)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pub_key}`,\n );\n }\n\n signatures.push({ pub_key, signature });\n }\n\n return new MultisigTransaction({\n unsignedTx,\n signatures,\n unusedPubKeys: Array.from(unusedPubKeys),\n minSigners,\n });\n }\n\n /**\n * Adds a signature & public key from a signed transaction to the multisig transaction.\n * @param tx - The signed transaction to extract signature from\n * @throws {InvalidTransactionVersionError} If the transaction is not V0 variant\n * @throws {TransactionMismatchError} If the transaction doesn't match the unsigned transaction\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignedTransaction(tx: Transaction<unknown>): void {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, this.unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n this.addSignature(signature, pub_key);\n }\n\n /**\n * Adds a signature to the multisig transaction.\n * @param signature - The signature to add\n * @param pubKey - The public key corresponding to the signature\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignature(signature: HexString, pubKey: HexString): void {\n if (!this.unusedPubKeys.delete(pubKey)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pubKey}`,\n );\n }\n\n this.signatures.push({ pub_key: pubKey, signature });\n }\n\n /**\n * Checks if the multisig has collected enough signatures to be complete.\n * @returns True if the number of signatures meets or exceeds the minimum required\n */\n get isComplete(): boolean {\n return this.signatures.length >= this.minSigners;\n }\n\n /**\n * Gets the unsigned transaction.\n * @returns A readonly view of the unsigned transaction\n */\n get unsignedTransaction(): Readonly<UnsignedTransaction<unknown>> {\n return this.unsignedTx;\n }\n\n /**\n * Gets the signatures and public keys collected so far.\n * @returns A readonly view of the signatures and public keys\n */\n get signaturesAndPubKeys(): Readonly<SignatureAndPubKey[]> {\n return this.signatures;\n }\n\n /**\n * Gets the remaining public keys that haven't signed yet.\n * @returns A readonly view of the remaining public keys\n */\n get remainingPubKeys(): Readonly<Set<HexString>> {\n return this.unusedPubKeys;\n }\n\n /**\n * Gets the threshold number of signatures required for the multisig to be complete.\n * @returns The threshold number of signatures\n */\n get threshold(): number {\n return this.minSigners;\n }\n\n /**\n * Converts the multisig to a V1 transaction that can be submitted to the network.\n * @returns A V1 transaction containing all collected signatures and unused public keys\n */\n asTransaction(): Transaction<unknown> {\n return {\n V1: {\n runtime_call: this.unsignedTx.runtime_call,\n uniqueness: this.unsignedTx.uniqueness,\n details: this.unsignedTx.details,\n unused_pub_keys: Array.from(this.unusedPubKeys),\n signatures: this.signatures,\n min_signers: this.minSigners,\n },\n };\n }\n}\n\nfunction assertTxVariant(\n tx: Transaction<unknown>,\n): asserts tx is TransactionV0<unknown> {\n if (\"V1\" in tx) {\n throw new InvalidTransactionVersionError(\n \"Input transaction was an unsupported variant (V1)\",\n );\n }\n}\n\nfunction asUnsignedTransaction(\n tx: Transaction<unknown>,\n): UnsignedTransaction<unknown> {\n if (\"V0\" in tx) {\n return {\n runtime_call: tx.V0.runtime_call,\n uniqueness: tx.V0.uniqueness,\n details: tx.V0.details,\n };\n }\n\n if (\"V1\" in tx) {\n return {\n runtime_call: tx.V1.runtime_call,\n uniqueness: tx.V1.uniqueness,\n details: tx.V1.details,\n };\n }\n\n throw new InvalidTransactionVersionError(\n \"Transaction variant is neither V0 nor V1\",\n );\n}\n\nfunction assertTxMatchesUnsignedTx(\n tx: Transaction<unknown>,\n unsignedTx: UnsignedTransaction<unknown>,\n): void {\n const txAsUnsigned = asUnsignedTransaction(tx);\n\n if (JSON.stringify(txAsUnsigned) !== JSON.stringify(unsignedTx)) {\n throw new TransactionMismatchError();\n }\n}\n\nfunction assertIsNonceBasedTx(unsignedTx: UnsignedTransaction<unknown>): void {\n if (!(\"nonce\" in unsignedTx.uniqueness)) {\n throw new InvalidMultisigParameterError(\n \"Only nonce-based transactions are supported for multisig\",\n );\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -125,6 +125,27 @@ var MultisigTransaction = class _MultisigTransaction {
|
|
|
125
125
|
get unsignedTransaction() {
|
|
126
126
|
return this.unsignedTx;
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Gets the signatures and public keys collected so far.
|
|
130
|
+
* @returns A readonly view of the signatures and public keys
|
|
131
|
+
*/
|
|
132
|
+
get signaturesAndPubKeys() {
|
|
133
|
+
return this.signatures;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Gets the remaining public keys that haven't signed yet.
|
|
137
|
+
* @returns A readonly view of the remaining public keys
|
|
138
|
+
*/
|
|
139
|
+
get remainingPubKeys() {
|
|
140
|
+
return this.unusedPubKeys;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Gets the threshold number of signatures required for the multisig to be complete.
|
|
144
|
+
* @returns The threshold number of signatures
|
|
145
|
+
*/
|
|
146
|
+
get threshold() {
|
|
147
|
+
return this.minSigners;
|
|
148
|
+
}
|
|
128
149
|
/**
|
|
129
150
|
* Converts the multisig to a V1 transaction that can be submitted to the network.
|
|
130
151
|
* @returns A V1 transaction containing all collected signatures and unused public keys
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n SignatureAndPubKey,\n Transaction,\n TransactionV0,\n UnsignedTransaction,\n} from \"@sovereign-sdk/types\";\nimport type { HexString } from \"@sovereign-sdk/utils\";\n\n/**\n * Base error class for multisig-related errors.\n */\nexport class MultisigError extends Error {}\n\n/**\n * Error thrown when a transaction has an unsupported version for multisig operations.\n */\nexport class InvalidTransactionVersionError extends MultisigError {}\n\n/**\n * Error thrown when a provided transaction doesn't match the expected unsigned transaction.\n */\nexport class TransactionMismatchError extends Error {\n constructor() {\n super(\n \"Provided transaction does not match the expected unsigned transaction\",\n );\n }\n}\n\n/**\n * Error thrown when multisig is constructed or used with invalid parameters.\n */\nexport class InvalidMultisigParameterError extends MultisigError {\n constructor(desc: string) {\n super(`Multisig was constructed with invalid parameter: ${desc}`);\n }\n}\n\n/**\n * Parameters for constructing a MultisigTransaction.\n */\nexport type MultisigParams = {\n /** The unsigned transaction to be signed by multiple parties */\n unsignedTx: UnsignedTransaction<unknown>;\n /** Array of signatures with pubkeys already collected */\n signatures: SignatureAndPubKey[];\n /** Array of public keys that haven't signed yet */\n unusedPubKeys: HexString[];\n /** Minimum number of signatures required */\n minSigners: number;\n};\n\n/**\n * Parameters for creating a MultisigTransaction from existing signed transactions.\n */\nexport type FromTransactionsParams = {\n /** Array of signed transactions to extract signatures from */\n txns: Transaction<unknown>[];\n /** Minimum number of signatures required */\n minSigners: number;\n /** All public keys that are members of the multisig */\n allPubKeys: HexString[];\n};\n\n/**\n * Represents a multisig transaction that collects signatures from multiple parties.\n * Only supports nonce-based transactions and V0 transaction variants for signature collection.\n */\nexport class MultisigTransaction {\n private unsignedTx: UnsignedTransaction<unknown>;\n private signatures: SignatureAndPubKey[] = [];\n private minSigners: number;\n private unusedPubKeys = new Set<HexString>();\n\n /**\n * Creates a new MultisigTransaction instance.\n * @param params - The multisig parameters including unsigned transaction, signatures, and public keys\n */\n constructor({\n unsignedTx,\n signatures,\n unusedPubKeys,\n minSigners,\n }: MultisigParams) {\n this.unsignedTx = unsignedTx;\n this.signatures = signatures;\n this.unusedPubKeys = new Set(unusedPubKeys);\n this.minSigners = minSigners;\n }\n\n /**\n * Creates an empty MultisigTransaction with no signatures collected yet.\n * @param unsignedTx - The unsigned transaction to be signed by multiple parties\n * @param minSigners - Minimum number of signatures required for completion\n * @param allPubKeys - All public keys that are members of the multisig\n * @returns A new empty MultisigTransaction instance\n */\n static empty(\n unsignedTx: UnsignedTransaction<unknown>,\n minSigners: number,\n allPubKeys: HexString[],\n ): MultisigTransaction {\n return new MultisigTransaction({\n unsignedTx,\n signatures: [],\n unusedPubKeys: allPubKeys,\n minSigners,\n });\n }\n\n /**\n * Creates a MultisigTransaction from an array of already-signed transactions.\n * Extracts signatures and validates that all transactions are identical except for signatures.\n * @param params - Parameters including the signed transactions, minimum signers, and all public keys\n * @returns A new MultisigTransaction instance\n * @throws {InvalidTransactionVersionError} If any transaction is not V0 variant\n * @throws {TransactionMismatchError} If transactions don't match each other\n * @throws {InvalidMultisigParameterError} If public keys are invalid or transaction is not nonce-based\n */\n static fromTransactions({\n txns,\n minSigners,\n allPubKeys,\n }: FromTransactionsParams): MultisigTransaction {\n const signatures: SignatureAndPubKey[] = [];\n const unsignedTx = asUnsignedTransaction(txns[0]);\n const unusedPubKeys = new Set<HexString>(allPubKeys);\n\n assertIsNonceBasedTx(unsignedTx);\n\n for (const tx of txns) {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n if (!unusedPubKeys.delete(pub_key)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pub_key}`,\n );\n }\n\n signatures.push({ pub_key, signature });\n }\n\n return new MultisigTransaction({\n unsignedTx,\n signatures,\n unusedPubKeys: Array.from(unusedPubKeys),\n minSigners,\n });\n }\n\n /**\n * Adds a signature & public key from a signed transaction to the multisig transaction.\n * @param tx - The signed transaction to extract signature from\n * @throws {InvalidTransactionVersionError} If the transaction is not V0 variant\n * @throws {TransactionMismatchError} If the transaction doesn't match the unsigned transaction\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignedTransaction(tx: Transaction<unknown>): void {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, this.unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n this.addSignature(signature, pub_key);\n }\n\n /**\n * Adds a signature to the multisig transaction.\n * @param signature - The signature to add\n * @param pubKey - The public key corresponding to the signature\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignature(signature: HexString, pubKey: HexString): void {\n if (!this.unusedPubKeys.delete(pubKey)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pubKey}`,\n );\n }\n\n this.signatures.push({ pub_key: pubKey, signature });\n }\n\n /**\n * Checks if the multisig has collected enough signatures to be complete.\n * @returns True if the number of signatures meets or exceeds the minimum required\n */\n get isComplete(): boolean {\n return this.signatures.length >= this.minSigners;\n }\n\n /**\n * Gets the unsigned transaction.\n * @returns A readonly view of the unsigned transaction\n */\n get unsignedTransaction(): Readonly<UnsignedTransaction<unknown>> {\n return this.unsignedTx;\n }\n\n /**\n * Converts the multisig to a V1 transaction that can be submitted to the network.\n * @returns A V1 transaction containing all collected signatures and unused public keys\n */\n asTransaction(): Transaction<unknown> {\n return {\n V1: {\n runtime_call: this.unsignedTx.runtime_call,\n uniqueness: this.unsignedTx.uniqueness,\n details: this.unsignedTx.details,\n unused_pub_keys: Array.from(this.unusedPubKeys),\n signatures: this.signatures,\n min_signers: this.minSigners,\n },\n };\n }\n}\n\nfunction assertTxVariant(\n tx: Transaction<unknown>,\n): asserts tx is TransactionV0<unknown> {\n if (\"V1\" in tx) {\n throw new InvalidTransactionVersionError(\n \"Input transaction was an unsupported variant (V1)\",\n );\n }\n}\n\nfunction asUnsignedTransaction(\n tx: Transaction<unknown>,\n): UnsignedTransaction<unknown> {\n if (\"V0\" in tx) {\n return {\n runtime_call: tx.V0.runtime_call,\n uniqueness: tx.V0.uniqueness,\n details: tx.V0.details,\n };\n }\n\n if (\"V1\" in tx) {\n return {\n runtime_call: tx.V1.runtime_call,\n uniqueness: tx.V1.uniqueness,\n details: tx.V1.details,\n };\n }\n\n throw new InvalidTransactionVersionError(\n \"Transaction variant is neither V0 nor V1\",\n );\n}\n\nfunction assertTxMatchesUnsignedTx(\n tx: Transaction<unknown>,\n unsignedTx: UnsignedTransaction<unknown>,\n): void {\n const txAsUnsigned = asUnsignedTransaction(tx);\n\n if (JSON.stringify(txAsUnsigned) !== JSON.stringify(unsignedTx)) {\n throw new TransactionMismatchError();\n }\n}\n\nfunction assertIsNonceBasedTx(unsignedTx: UnsignedTransaction<unknown>): void {\n if (!(\"nonce\" in unsignedTx.uniqueness)) {\n throw new InvalidMultisigParameterError(\n \"Only nonce-based transactions are supported for multisig\",\n );\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n SignatureAndPubKey,\n Transaction,\n TransactionV0,\n UnsignedTransaction,\n} from \"@sovereign-sdk/types\";\nimport type { HexString } from \"@sovereign-sdk/utils\";\n\n/**\n * Base error class for multisig-related errors.\n */\nexport class MultisigError extends Error {}\n\n/**\n * Error thrown when a transaction has an unsupported version for multisig operations.\n */\nexport class InvalidTransactionVersionError extends MultisigError {}\n\n/**\n * Error thrown when a provided transaction doesn't match the expected unsigned transaction.\n */\nexport class TransactionMismatchError extends Error {\n constructor() {\n super(\n \"Provided transaction does not match the expected unsigned transaction\",\n );\n }\n}\n\n/**\n * Error thrown when multisig is constructed or used with invalid parameters.\n */\nexport class InvalidMultisigParameterError extends MultisigError {\n constructor(desc: string) {\n super(`Multisig was constructed with invalid parameter: ${desc}`);\n }\n}\n\n/**\n * Parameters for constructing a MultisigTransaction.\n */\nexport type MultisigParams = {\n /** The unsigned transaction to be signed by multiple parties */\n unsignedTx: UnsignedTransaction<unknown>;\n /** Array of signatures with pubkeys already collected */\n signatures: SignatureAndPubKey[];\n /** Array of public keys that haven't signed yet */\n unusedPubKeys: HexString[];\n /** Minimum number of signatures required */\n minSigners: number;\n};\n\n/**\n * Parameters for creating a MultisigTransaction from existing signed transactions.\n */\nexport type FromTransactionsParams = {\n /** Array of signed transactions to extract signatures from */\n txns: Transaction<unknown>[];\n /** Minimum number of signatures required */\n minSigners: number;\n /** All public keys that are members of the multisig */\n allPubKeys: HexString[];\n};\n\n/**\n * Represents a multisig transaction that collects signatures from multiple parties.\n * Only supports nonce-based transactions and V0 transaction variants for signature collection.\n */\nexport class MultisigTransaction {\n private unsignedTx: UnsignedTransaction<unknown>;\n private signatures: SignatureAndPubKey[] = [];\n private minSigners: number;\n private unusedPubKeys = new Set<HexString>();\n\n /**\n * Creates a new MultisigTransaction instance.\n * @param params - The multisig parameters including unsigned transaction, signatures, and public keys\n */\n constructor({\n unsignedTx,\n signatures,\n unusedPubKeys,\n minSigners,\n }: MultisigParams) {\n this.unsignedTx = unsignedTx;\n this.signatures = signatures;\n this.unusedPubKeys = new Set(unusedPubKeys);\n this.minSigners = minSigners;\n }\n\n /**\n * Creates an empty MultisigTransaction with no signatures collected yet.\n * @param unsignedTx - The unsigned transaction to be signed by multiple parties\n * @param minSigners - Minimum number of signatures required for completion\n * @param allPubKeys - All public keys that are members of the multisig\n * @returns A new empty MultisigTransaction instance\n */\n static empty(\n unsignedTx: UnsignedTransaction<unknown>,\n minSigners: number,\n allPubKeys: HexString[],\n ): MultisigTransaction {\n return new MultisigTransaction({\n unsignedTx,\n signatures: [],\n unusedPubKeys: allPubKeys,\n minSigners,\n });\n }\n\n /**\n * Creates a MultisigTransaction from an array of already-signed transactions.\n * Extracts signatures and validates that all transactions are identical except for signatures.\n * @param params - Parameters including the signed transactions, minimum signers, and all public keys\n * @returns A new MultisigTransaction instance\n * @throws {InvalidTransactionVersionError} If any transaction is not V0 variant\n * @throws {TransactionMismatchError} If transactions don't match each other\n * @throws {InvalidMultisigParameterError} If public keys are invalid or transaction is not nonce-based\n */\n static fromTransactions({\n txns,\n minSigners,\n allPubKeys,\n }: FromTransactionsParams): MultisigTransaction {\n const signatures: SignatureAndPubKey[] = [];\n const unsignedTx = asUnsignedTransaction(txns[0]);\n const unusedPubKeys = new Set<HexString>(allPubKeys);\n\n assertIsNonceBasedTx(unsignedTx);\n\n for (const tx of txns) {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n if (!unusedPubKeys.delete(pub_key)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pub_key}`,\n );\n }\n\n signatures.push({ pub_key, signature });\n }\n\n return new MultisigTransaction({\n unsignedTx,\n signatures,\n unusedPubKeys: Array.from(unusedPubKeys),\n minSigners,\n });\n }\n\n /**\n * Adds a signature & public key from a signed transaction to the multisig transaction.\n * @param tx - The signed transaction to extract signature from\n * @throws {InvalidTransactionVersionError} If the transaction is not V0 variant\n * @throws {TransactionMismatchError} If the transaction doesn't match the unsigned transaction\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignedTransaction(tx: Transaction<unknown>): void {\n assertTxVariant(tx);\n assertTxMatchesUnsignedTx(tx, this.unsignedTx);\n\n const { pub_key, signature } = tx.V0;\n\n this.addSignature(signature, pub_key);\n }\n\n /**\n * Adds a signature to the multisig transaction.\n * @param signature - The signature to add\n * @param pubKey - The public key corresponding to the signature\n * @throws {InvalidMultisigParameterError} If the public key is not a member or has already signed\n */\n addSignature(signature: HexString, pubKey: HexString): void {\n if (!this.unusedPubKeys.delete(pubKey)) {\n throw new InvalidMultisigParameterError(\n `Public key is not a member of the multisig or has already signed: ${pubKey}`,\n );\n }\n\n this.signatures.push({ pub_key: pubKey, signature });\n }\n\n /**\n * Checks if the multisig has collected enough signatures to be complete.\n * @returns True if the number of signatures meets or exceeds the minimum required\n */\n get isComplete(): boolean {\n return this.signatures.length >= this.minSigners;\n }\n\n /**\n * Gets the unsigned transaction.\n * @returns A readonly view of the unsigned transaction\n */\n get unsignedTransaction(): Readonly<UnsignedTransaction<unknown>> {\n return this.unsignedTx;\n }\n\n /**\n * Gets the signatures and public keys collected so far.\n * @returns A readonly view of the signatures and public keys\n */\n get signaturesAndPubKeys(): Readonly<SignatureAndPubKey[]> {\n return this.signatures;\n }\n\n /**\n * Gets the remaining public keys that haven't signed yet.\n * @returns A readonly view of the remaining public keys\n */\n get remainingPubKeys(): Readonly<Set<HexString>> {\n return this.unusedPubKeys;\n }\n\n /**\n * Gets the threshold number of signatures required for the multisig to be complete.\n * @returns The threshold number of signatures\n */\n get threshold(): number {\n return this.minSigners;\n }\n\n /**\n * Converts the multisig to a V1 transaction that can be submitted to the network.\n * @returns A V1 transaction containing all collected signatures and unused public keys\n */\n asTransaction(): Transaction<unknown> {\n return {\n V1: {\n runtime_call: this.unsignedTx.runtime_call,\n uniqueness: this.unsignedTx.uniqueness,\n details: this.unsignedTx.details,\n unused_pub_keys: Array.from(this.unusedPubKeys),\n signatures: this.signatures,\n min_signers: this.minSigners,\n },\n };\n }\n}\n\nfunction assertTxVariant(\n tx: Transaction<unknown>,\n): asserts tx is TransactionV0<unknown> {\n if (\"V1\" in tx) {\n throw new InvalidTransactionVersionError(\n \"Input transaction was an unsupported variant (V1)\",\n );\n }\n}\n\nfunction asUnsignedTransaction(\n tx: Transaction<unknown>,\n): UnsignedTransaction<unknown> {\n if (\"V0\" in tx) {\n return {\n runtime_call: tx.V0.runtime_call,\n uniqueness: tx.V0.uniqueness,\n details: tx.V0.details,\n };\n }\n\n if (\"V1\" in tx) {\n return {\n runtime_call: tx.V1.runtime_call,\n uniqueness: tx.V1.uniqueness,\n details: tx.V1.details,\n };\n }\n\n throw new InvalidTransactionVersionError(\n \"Transaction variant is neither V0 nor V1\",\n );\n}\n\nfunction assertTxMatchesUnsignedTx(\n tx: Transaction<unknown>,\n unsignedTx: UnsignedTransaction<unknown>,\n): void {\n const txAsUnsigned = asUnsignedTransaction(tx);\n\n if (JSON.stringify(txAsUnsigned) !== JSON.stringify(unsignedTx)) {\n throw new TransactionMismatchError();\n }\n}\n\nfunction assertIsNonceBasedTx(unsignedTx: UnsignedTransaction<unknown>): void {\n if (!(\"nonce\" in unsignedTx.uniqueness)) {\n throw new InvalidMultisigParameterError(\n \"Only nonce-based transactions are supported for multisig\",\n );\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sovereign-sdk/multisig",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Multisig functionality for Sovereign SDK applications",
|
|
5
5
|
"repository": "github:Sovereign-Labs/sovereign-sdk",
|
|
6
6
|
"files": [
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"typescript": "^5.6.3",
|
|
24
24
|
"vitest": "4.0.7",
|
|
25
25
|
"@sovereign-sdk/types": "^0.1.2",
|
|
26
|
-
"@sovereign-sdk/web3": "^0.12.
|
|
26
|
+
"@sovereign-sdk/web3": "^0.12.1"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"tsup": "^8.3.0",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@sovereign-sdk/signers": "^0.
|
|
36
|
+
"@sovereign-sdk/signers": "^0.5.0",
|
|
37
37
|
"@sovereign-sdk/utils": "^0.0.4"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|