@openzeppelin/miden-multisig-client 0.12.7 → 0.13.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/README.md +42 -4
- package/dist/account/builder.d.ts +1 -1
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +7 -5
- package/dist/account/builder.js.map +1 -1
- package/dist/account/masm.d.ts +3 -3
- package/dist/account/masm.d.ts.map +1 -1
- package/dist/account/masm.js +101 -98
- package/dist/account/masm.js.map +1 -1
- package/dist/account/storage.d.ts +1 -1
- package/dist/account/storage.d.ts.map +1 -1
- package/dist/account/storage.js +17 -7
- package/dist/account/storage.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +4 -4
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts +1 -1
- package/dist/inspector.d.ts.map +1 -1
- package/dist/inspector.js +16 -10
- package/dist/inspector.js.map +1 -1
- package/dist/inspector.test.js +33 -22
- package/dist/inspector.test.js.map +1 -1
- package/dist/multisig/helpers.d.ts +1 -1
- package/dist/multisig/helpers.d.ts.map +1 -1
- package/dist/multisig/helpers.js +1 -1
- package/dist/multisig/helpers.js.map +1 -1
- package/dist/multisig/helpers.test.js +2 -2
- package/dist/multisig/helpers.test.js.map +1 -1
- package/dist/multisig/proposal/execution.d.ts +18 -0
- package/dist/multisig/proposal/execution.d.ts.map +1 -0
- package/dist/multisig/proposal/execution.js +147 -0
- package/dist/multisig/proposal/execution.js.map +1 -0
- package/dist/multisig/proposal/parser.d.ts +17 -0
- package/dist/multisig/proposal/parser.d.ts.map +1 -0
- package/dist/multisig/proposal/parser.js +147 -0
- package/dist/multisig/proposal/parser.js.map +1 -0
- package/dist/multisig/signing.d.ts +5 -0
- package/dist/multisig/signing.d.ts.map +1 -0
- package/dist/multisig/signing.js +14 -0
- package/dist/multisig/signing.js.map +1 -0
- package/dist/multisig.d.ts +9 -13
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +109 -337
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +8 -4
- package/dist/multisig.test.js.map +1 -1
- package/dist/signer.d.ts +2 -20
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +2 -82
- package/dist/signer.js.map +1 -1
- package/dist/signer.test.js +24 -24
- package/dist/signer.test.js.map +1 -1
- package/dist/signers/ecdsa.d.ts +12 -0
- package/dist/signers/ecdsa.d.ts.map +1 -0
- package/dist/signers/ecdsa.js +30 -0
- package/dist/signers/ecdsa.js.map +1 -0
- package/dist/signers/falcon.d.ts +12 -0
- package/dist/signers/falcon.d.ts.map +1 -0
- package/dist/signers/falcon.js +31 -0
- package/dist/signers/falcon.js.map +1 -0
- package/dist/signers/falcon.test.d.ts +2 -0
- package/dist/signers/falcon.test.d.ts.map +1 -0
- package/dist/signers/falcon.test.js +113 -0
- package/dist/signers/falcon.test.js.map +1 -0
- package/dist/signers/index.d.ts +5 -0
- package/dist/signers/index.d.ts.map +1 -0
- package/dist/signers/index.js +5 -0
- package/dist/signers/index.js.map +1 -0
- package/dist/signers/miden-wallet.d.ts +16 -0
- package/dist/signers/miden-wallet.d.ts.map +1 -0
- package/dist/signers/miden-wallet.js +35 -0
- package/dist/signers/miden-wallet.js.map +1 -0
- package/dist/signers/miden-wallet.test.d.ts +2 -0
- package/dist/signers/miden-wallet.test.d.ts.map +1 -0
- package/dist/signers/miden-wallet.test.js +107 -0
- package/dist/signers/miden-wallet.test.js.map +1 -0
- package/dist/signers/para.d.ts +21 -0
- package/dist/signers/para.d.ts.map +1 -0
- package/dist/signers/para.js +43 -0
- package/dist/signers/para.js.map +1 -0
- package/dist/signers/para.test.d.ts +2 -0
- package/dist/signers/para.test.d.ts.map +1 -0
- package/dist/signers/para.test.js +88 -0
- package/dist/signers/para.test.js.map +1 -0
- package/dist/transaction/consumeNotes.d.ts +3 -3
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +11 -7
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/options.d.ts +2 -2
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +1 -1
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +5 -5
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/summary.d.ts +1 -1
- package/dist/transaction/summary.d.ts.map +1 -1
- package/dist/transaction/summary.js +1 -1
- package/dist/transaction/summary.js.map +1 -1
- package/dist/transaction/updatePsm.d.ts +1 -1
- package/dist/transaction/updatePsm.d.ts.map +1 -1
- package/dist/transaction/updatePsm.js +5 -5
- package/dist/transaction/updatePsm.js.map +1 -1
- package/dist/transaction/updateSigners.d.ts +1 -1
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js +5 -5
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.test.js +1 -1
- package/dist/transaction.test.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/digest.d.ts +6 -0
- package/dist/utils/digest.d.ts.map +1 -0
- package/dist/utils/digest.js +22 -0
- package/dist/utils/digest.js.map +1 -0
- package/dist/utils/ecdsa.d.ts +8 -0
- package/dist/utils/ecdsa.d.ts.map +1 -0
- package/dist/utils/ecdsa.js +60 -0
- package/dist/utils/ecdsa.js.map +1 -0
- package/dist/utils/ecdsa.test.d.ts +2 -0
- package/dist/utils/ecdsa.test.d.ts.map +1 -0
- package/dist/utils/ecdsa.test.js +85 -0
- package/dist/utils/ecdsa.test.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/key.d.ts +10 -0
- package/dist/utils/key.d.ts.map +1 -0
- package/dist/utils/key.js +38 -0
- package/dist/utils/key.js.map +1 -0
- package/dist/utils/key.test.d.ts +2 -0
- package/dist/utils/key.test.d.ts.map +1 -0
- package/dist/utils/key.test.js +80 -0
- package/dist/utils/key.test.js.map +1 -0
- package/dist/utils/random.d.ts +1 -1
- package/dist/utils/random.d.ts.map +1 -1
- package/dist/utils/random.js +1 -1
- package/dist/utils/random.js.map +1 -1
- package/dist/utils/signature.d.ts +2 -1
- package/dist/utils/signature.d.ts.map +1 -1
- package/dist/utils/signature.js +6 -3
- package/dist/utils/signature.js.map +1 -1
- package/dist/utils/signature.test.js +11 -11
- package/dist/utils/signature.test.js.map +1 -1
- package/dist/utils/word.d.ts +6 -1
- package/dist/utils/word.d.ts.map +1 -1
- package/dist/utils/word.js +11 -0
- package/dist/utils/word.js.map +1 -1
- package/dist/utils/word.test.js +54 -3
- package/dist/utils/word.test.js.map +1 -1
- package/package.json +4 -5
- package/src/account/builder.ts +7 -5
- package/src/account/masm.ts +103 -99
- package/src/account/storage.ts +19 -7
- package/src/client.test.ts +4 -4
- package/src/client.ts +3 -3
- package/src/index.ts +8 -1
- package/src/inspector.test.ts +38 -25
- package/src/inspector.ts +18 -10
- package/src/multisig/helpers.test.ts +2 -2
- package/src/multisig/helpers.ts +2 -1
- package/src/multisig/proposal/execution.ts +320 -0
- package/src/multisig/proposal/parser.ts +191 -0
- package/src/multisig/signing.ts +24 -0
- package/src/multisig.test.ts +8 -4
- package/src/multisig.ts +153 -434
- package/src/signer.ts +2 -95
- package/src/signers/ecdsa.ts +35 -0
- package/src/{signer.test.ts → signers/falcon.test.ts} +29 -33
- package/src/signers/falcon.ts +36 -0
- package/src/signers/index.ts +4 -0
- package/src/signers/miden-wallet.test.ts +119 -0
- package/src/signers/miden-wallet.ts +49 -0
- package/src/signers/para.test.ts +103 -0
- package/src/signers/para.ts +60 -0
- package/src/transaction/consumeNotes.ts +14 -10
- package/src/transaction/options.ts +2 -2
- package/src/transaction/p2id.ts +3 -8
- package/src/transaction/summary.ts +2 -2
- package/src/transaction/updatePsm.ts +5 -6
- package/src/transaction/updateSigners.ts +5 -6
- package/src/transaction.test.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils/digest.ts +25 -0
- package/src/utils/ecdsa.test.ts +104 -0
- package/src/utils/ecdsa.ts +77 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/key.test.ts +89 -0
- package/src/utils/key.ts +49 -0
- package/src/utils/random.ts +1 -1
- package/src/utils/signature.test.ts +11 -11
- package/src/utils/signature.ts +10 -3
- package/src/utils/word.test.ts +57 -3
- package/src/utils/word.ts +13 -1
package/dist/multisig.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { AccountInspector } from './inspector.js';
|
|
2
|
-
import { Account, AccountId,
|
|
2
|
+
import { Account, AccountId, } from '@miden-sdk/miden-sdk';
|
|
3
3
|
import { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdatePsmTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, } from './transaction.js';
|
|
4
4
|
import { base64ToUint8Array, uint8ArrayToBase64, normalizeHexWord, } from './utils/encoding.js';
|
|
5
|
-
import { buildSignatureAdviceEntry, signatureHexToBytes, tryComputeEcdsaCommitmentHex } from './utils/signature.js';
|
|
6
5
|
import { computeCommitmentFromTxSummary, accountIdToHex } from './multisig/helpers.js';
|
|
6
|
+
import { buildPsmMetadata, deltaToProposal, resolveMetadata, signatureRequirementForProposal, } from './multisig/proposal/parser.js';
|
|
7
|
+
import { toPsmSignature, buildPsmSignatureFromSigner, } from './multisig/signing.js';
|
|
8
|
+
import { executeProposalWorkflow } from './multisig/proposal/execution.js';
|
|
7
9
|
export class Multisig {
|
|
8
10
|
account;
|
|
9
11
|
threshold;
|
|
@@ -125,8 +127,7 @@ export class Multisig {
|
|
|
125
127
|
const onChain = normalizeHexWord(this.psmCommitment);
|
|
126
128
|
const server = normalizeHexWord(response.ackCommitment);
|
|
127
129
|
if (onChain !== server) {
|
|
128
|
-
throw new Error(`PSM commitment mismatch: on-chain=${onChain}, server=${server}
|
|
129
|
-
`Re-create the account with getPubkey('${this.signatureScheme}') to get the correct PSM commitment.`);
|
|
130
|
+
throw new Error(`PSM commitment mismatch: on-chain=${onChain}, server=${server}`);
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -135,6 +136,12 @@ export class Multisig {
|
|
|
135
136
|
const state = await this.syncState();
|
|
136
137
|
const notes = await this.getConsumableNotes();
|
|
137
138
|
const config = AccountInspector.fromBase64(state.stateDataBase64, this.signatureScheme);
|
|
139
|
+
this.threshold = config.threshold;
|
|
140
|
+
this.signerCommitments = config.signerCommitments;
|
|
141
|
+
if (config.psmCommitment) {
|
|
142
|
+
this.psmCommitment = config.psmCommitment;
|
|
143
|
+
}
|
|
144
|
+
this.procedureThresholds = config.procedureThresholds;
|
|
138
145
|
return { proposals, state, notes, config };
|
|
139
146
|
}
|
|
140
147
|
async getAccountConfig() {
|
|
@@ -142,9 +149,38 @@ export class Multisig {
|
|
|
142
149
|
return AccountInspector.fromBase64(state.stateDataBase64, this.signatureScheme);
|
|
143
150
|
}
|
|
144
151
|
async switchPsm(psmClient) {
|
|
152
|
+
const accountId = AccountId.fromHex(this._accountId);
|
|
153
|
+
const localAccount = await this.webClient.getAccount(accountId);
|
|
154
|
+
if (localAccount) {
|
|
155
|
+
this.account = localAccount;
|
|
156
|
+
const config = AccountInspector.fromAccount(localAccount, this.signatureScheme);
|
|
157
|
+
if (config.psmCommitment) {
|
|
158
|
+
this.psmCommitment = config.psmCommitment;
|
|
159
|
+
}
|
|
160
|
+
this.threshold = config.threshold;
|
|
161
|
+
this.signerCommitments = config.signerCommitments;
|
|
162
|
+
this.procedureThresholds = config.procedureThresholds;
|
|
163
|
+
}
|
|
145
164
|
this.setPsmClient(psmClient);
|
|
146
|
-
const
|
|
147
|
-
|
|
165
|
+
const accountBytes = this.account.serialize();
|
|
166
|
+
const stateData = uint8ArrayToBase64(accountBytes);
|
|
167
|
+
const auth = this.signer.scheme === 'ecdsa'
|
|
168
|
+
? { MidenEcdsa: { cosigner_commitments: this.signerCommitments } }
|
|
169
|
+
: { MidenFalconRpo: { cosigner_commitments: this.signerCommitments } };
|
|
170
|
+
const response = await this.psm.configure({
|
|
171
|
+
accountId: this._accountId,
|
|
172
|
+
auth,
|
|
173
|
+
initialState: { data: stateData, accountId: this._accountId },
|
|
174
|
+
});
|
|
175
|
+
if (!response.success) {
|
|
176
|
+
throw new Error(`Failed to register on PSM: ${response.message}`);
|
|
177
|
+
}
|
|
178
|
+
if (response.ackCommitment) {
|
|
179
|
+
this.psmCommitment = normalizeHexWord(response.ackCommitment);
|
|
180
|
+
}
|
|
181
|
+
if (response.ackPubkey) {
|
|
182
|
+
this.psmPublicKey = response.ackPubkey;
|
|
183
|
+
}
|
|
148
184
|
}
|
|
149
185
|
async syncTransactionProposals() {
|
|
150
186
|
const deltas = await this.psm.getDeltaProposals(this._accountId);
|
|
@@ -153,14 +189,17 @@ export class Multisig {
|
|
|
153
189
|
const proposalId = computeCommitmentFromTxSummary(delta.deltaPayload.txSummary.data);
|
|
154
190
|
serverProposalIds.add(proposalId);
|
|
155
191
|
const existingProposal = this.proposals.get(proposalId);
|
|
156
|
-
const resolvedMetadata = existingProposal?.metadata
|
|
157
|
-
(delta.deltaPayload.metadata
|
|
158
|
-
? this.fromPsmMetadata(delta.deltaPayload.metadata)
|
|
159
|
-
: undefined);
|
|
192
|
+
const resolvedMetadata = resolveMetadata(delta, existingProposal?.metadata);
|
|
160
193
|
if (!resolvedMetadata) {
|
|
161
194
|
throw new Error('Missing proposal metadata from PSM');
|
|
162
195
|
}
|
|
163
|
-
const proposal =
|
|
196
|
+
const proposal = deltaToProposal({
|
|
197
|
+
delta,
|
|
198
|
+
proposalId,
|
|
199
|
+
metadata: resolvedMetadata,
|
|
200
|
+
signaturesRequired: signatureRequirementForProposal(resolvedMetadata, this.threshold, (proposalType) => this.getEffectiveThreshold(proposalType)),
|
|
201
|
+
existingSignatures: existingProposal?.signatures,
|
|
202
|
+
});
|
|
164
203
|
this.proposals.set(proposal.id, proposal);
|
|
165
204
|
}
|
|
166
205
|
for (const [id, proposal] of this.proposals) {
|
|
@@ -177,7 +216,7 @@ export class Multisig {
|
|
|
177
216
|
return Array.from(this.proposals.values());
|
|
178
217
|
}
|
|
179
218
|
async createProposal(nonce, txSummaryBase64, metadata) {
|
|
180
|
-
const psmMetadata =
|
|
219
|
+
const psmMetadata = buildPsmMetadata(metadata);
|
|
181
220
|
const response = await this.psm.pushDeltaProposal({
|
|
182
221
|
accountId: this._accountId,
|
|
183
222
|
nonce,
|
|
@@ -187,7 +226,12 @@ export class Multisig {
|
|
|
187
226
|
metadata: psmMetadata,
|
|
188
227
|
},
|
|
189
228
|
});
|
|
190
|
-
const proposal =
|
|
229
|
+
const proposal = deltaToProposal({
|
|
230
|
+
delta: response.delta,
|
|
231
|
+
proposalId: response.commitment,
|
|
232
|
+
metadata,
|
|
233
|
+
signaturesRequired: signatureRequirementForProposal(metadata, this.threshold, (proposalType) => this.getEffectiveThreshold(proposalType)),
|
|
234
|
+
});
|
|
191
235
|
this.proposals.set(proposal.id, proposal);
|
|
192
236
|
return proposal;
|
|
193
237
|
}
|
|
@@ -195,9 +239,6 @@ export class Multisig {
|
|
|
195
239
|
const targetThreshold = options?.newThreshold ?? this.threshold;
|
|
196
240
|
const targetSignerCommitments = [...this.signerCommitments, newCommitment];
|
|
197
241
|
const { request, salt } = await buildUpdateSignersTransactionRequest(this.webClient, targetThreshold, targetSignerCommitments, { signatureScheme: this.signatureScheme });
|
|
198
|
-
const summary = await executeForSummary(this.webClient, this._accountId, request);
|
|
199
|
-
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
200
|
-
const proposalNonce = options?.nonce ?? Date.now();
|
|
201
242
|
const metadata = {
|
|
202
243
|
proposalType: 'add_signer',
|
|
203
244
|
targetThreshold,
|
|
@@ -205,8 +246,7 @@ export class Multisig {
|
|
|
205
246
|
saltHex: salt.toHex(),
|
|
206
247
|
description: `Add signer ${newCommitment.slice(0, 10)}...`,
|
|
207
248
|
};
|
|
208
|
-
|
|
209
|
-
return this.syncAfterCreate(proposal);
|
|
249
|
+
return this.createAndSyncFromRequest(request, metadata, options?.nonce);
|
|
210
250
|
}
|
|
211
251
|
async createRemoveSignerProposal(signerToRemove, options) {
|
|
212
252
|
const normalizedRemove = signerToRemove.toLowerCase();
|
|
@@ -223,9 +263,6 @@ export class Multisig {
|
|
|
223
263
|
throw new Error(`Invalid threshold ${targetThreshold}. Must be between 1 and ${targetSignerCommitments.length}`);
|
|
224
264
|
}
|
|
225
265
|
const { request, salt } = await buildUpdateSignersTransactionRequest(this.webClient, targetThreshold, targetSignerCommitments, { signatureScheme: this.signatureScheme });
|
|
226
|
-
const summary = await executeForSummary(this.webClient, this._accountId, request);
|
|
227
|
-
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
228
|
-
const proposalNonce = options?.nonce ?? Date.now();
|
|
229
266
|
const metadata = {
|
|
230
267
|
proposalType: 'remove_signer',
|
|
231
268
|
targetThreshold,
|
|
@@ -233,8 +270,7 @@ export class Multisig {
|
|
|
233
270
|
saltHex: salt.toHex(),
|
|
234
271
|
description: `Remove signer ${signerToRemove.slice(0, 10)}...`,
|
|
235
272
|
};
|
|
236
|
-
|
|
237
|
-
return this.syncAfterCreate(proposal);
|
|
273
|
+
return this.createAndSyncFromRequest(request, metadata, options?.nonce);
|
|
238
274
|
}
|
|
239
275
|
async createChangeThresholdProposal(newThreshold, options) {
|
|
240
276
|
if (newThreshold < 1 || newThreshold > this.signerCommitments.length) {
|
|
@@ -244,9 +280,6 @@ export class Multisig {
|
|
|
244
280
|
throw new Error('New threshold is the same as current threshold');
|
|
245
281
|
}
|
|
246
282
|
const { request, salt } = await buildUpdateSignersTransactionRequest(this.webClient, newThreshold, this.signerCommitments, { signatureScheme: this.signatureScheme });
|
|
247
|
-
const summary = await executeForSummary(this.webClient, this._accountId, request);
|
|
248
|
-
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
249
|
-
const proposalNonce = options?.nonce ?? Date.now();
|
|
250
283
|
const metadata = {
|
|
251
284
|
proposalType: 'change_threshold',
|
|
252
285
|
targetThreshold: newThreshold,
|
|
@@ -254,8 +287,7 @@ export class Multisig {
|
|
|
254
287
|
saltHex: salt.toHex(),
|
|
255
288
|
description: `Change threshold from ${this.threshold} to ${newThreshold}`,
|
|
256
289
|
};
|
|
257
|
-
|
|
258
|
-
return this.syncAfterCreate(proposal);
|
|
290
|
+
return this.createAndSyncFromRequest(request, metadata, options?.nonce);
|
|
259
291
|
}
|
|
260
292
|
async createSwitchPsmProposal(newPsmEndpoint, newPsmPubkey, options) {
|
|
261
293
|
const { request, salt } = await buildUpdatePsmTransactionRequest(this.webClient, newPsmPubkey, { signatureScheme: this.signatureScheme });
|
|
@@ -288,27 +320,20 @@ export class Multisig {
|
|
|
288
320
|
if (noteIds.length === 0) {
|
|
289
321
|
throw new Error('At least one note ID is required');
|
|
290
322
|
}
|
|
291
|
-
const { request, salt } = buildConsumeNotesTransactionRequest(noteIds);
|
|
292
|
-
const summary = await executeForSummary(this.webClient, this._accountId, request);
|
|
293
|
-
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
294
|
-
const proposalNonce = options?.nonce ?? Date.now();
|
|
323
|
+
const { request, salt } = await buildConsumeNotesTransactionRequest(this.webClient, noteIds);
|
|
295
324
|
const metadata = {
|
|
296
325
|
proposalType: 'consume_notes',
|
|
297
326
|
noteIds,
|
|
298
327
|
saltHex: salt.toHex(),
|
|
299
328
|
description: `Consume ${noteIds.length} note(s)`,
|
|
300
329
|
};
|
|
301
|
-
|
|
302
|
-
return this.syncAfterCreate(proposal);
|
|
330
|
+
return this.createAndSyncFromRequest(request, metadata, options?.nonce);
|
|
303
331
|
}
|
|
304
332
|
async createSendProposal(recipientId, faucetId, amount, options) {
|
|
305
333
|
if (amount <= 0n) {
|
|
306
334
|
throw new Error('Amount must be greater than 0');
|
|
307
335
|
}
|
|
308
336
|
const { request, salt } = buildP2idTransactionRequest(this._accountId, recipientId, faucetId, amount);
|
|
309
|
-
const summary = await executeForSummary(this.webClient, this._accountId, request);
|
|
310
|
-
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
311
|
-
const proposalNonce = options?.nonce ?? Date.now();
|
|
312
337
|
const metadata = {
|
|
313
338
|
proposalType: 'p2id',
|
|
314
339
|
saltHex: salt.toHex(),
|
|
@@ -317,8 +342,7 @@ export class Multisig {
|
|
|
317
342
|
amount: amount.toString(),
|
|
318
343
|
description: `Send ${amount} to ${recipientId.slice(0, 10)}...`,
|
|
319
344
|
};
|
|
320
|
-
|
|
321
|
-
return this.syncAfterCreate(proposal);
|
|
345
|
+
return this.createAndSyncFromRequest(request, metadata, options?.nonce);
|
|
322
346
|
}
|
|
323
347
|
async getConsumableNotes() {
|
|
324
348
|
const accountId = AccountId.fromHex(this._accountId);
|
|
@@ -328,7 +352,7 @@ export class Multisig {
|
|
|
328
352
|
const inputNote = record.inputNoteRecord();
|
|
329
353
|
const consumability = record.noteConsumability();
|
|
330
354
|
const canConsumeNow = consumability.some((c) => c.accountId().toString().toLowerCase() === this._accountId.toLowerCase() &&
|
|
331
|
-
c.consumableAfterBlock() === undefined);
|
|
355
|
+
c.consumptionStatus().consumableAfterBlock() === undefined);
|
|
332
356
|
if (canConsumeNow) {
|
|
333
357
|
const noteId = inputNote.id().toString();
|
|
334
358
|
const details = inputNote.details();
|
|
@@ -347,171 +371,67 @@ export class Multisig {
|
|
|
347
371
|
}
|
|
348
372
|
async signTransactionProposal(commitment) {
|
|
349
373
|
const existingProposal = this.proposals.get(commitment);
|
|
350
|
-
const
|
|
351
|
-
const signature = this.signer.scheme === 'ecdsa'
|
|
352
|
-
? { scheme: 'ecdsa', signature: signatureHex, publicKey: this.signer.publicKey }
|
|
353
|
-
: { scheme: 'falcon', signature: signatureHex };
|
|
374
|
+
const signature = await buildPsmSignatureFromSigner(this.signer, commitment);
|
|
354
375
|
const delta = await this.psm.signDeltaProposal({
|
|
355
376
|
accountId: this._accountId,
|
|
356
377
|
commitment,
|
|
357
378
|
signature,
|
|
358
379
|
});
|
|
359
|
-
const
|
|
360
|
-
if (
|
|
361
|
-
proposal
|
|
380
|
+
const resolvedMetadata = resolveMetadata(delta, existingProposal?.metadata);
|
|
381
|
+
if (!resolvedMetadata) {
|
|
382
|
+
throw new Error('Missing proposal metadata');
|
|
362
383
|
}
|
|
384
|
+
const proposal = deltaToProposal({
|
|
385
|
+
delta,
|
|
386
|
+
proposalId: commitment,
|
|
387
|
+
metadata: resolvedMetadata,
|
|
388
|
+
signaturesRequired: signatureRequirementForProposal(resolvedMetadata, this.threshold, (proposalType) => this.getEffectiveThreshold(proposalType)),
|
|
389
|
+
existingSignatures: existingProposal?.signatures,
|
|
390
|
+
});
|
|
363
391
|
this.proposals.set(proposal.id, proposal);
|
|
364
|
-
return this.
|
|
392
|
+
return this.listTransactionProposals();
|
|
365
393
|
}
|
|
366
394
|
async signTransactionProposalExternal(params) {
|
|
367
395
|
const { commitment, signature: signatureHex, publicKey, scheme } = params;
|
|
368
396
|
const resolvedScheme = scheme ?? this.signatureScheme;
|
|
369
397
|
const existingProposal = this.proposals.get(commitment);
|
|
370
|
-
const signature = resolvedScheme
|
|
371
|
-
? { scheme: 'ecdsa', signature: signatureHex, publicKey: publicKey }
|
|
372
|
-
: { scheme: 'falcon', signature: signatureHex };
|
|
398
|
+
const signature = toPsmSignature(resolvedScheme, signatureHex, publicKey);
|
|
373
399
|
const delta = await this.psm.signDeltaProposal({
|
|
374
400
|
accountId: this._accountId,
|
|
375
401
|
commitment,
|
|
376
402
|
signature,
|
|
377
403
|
});
|
|
378
|
-
const
|
|
379
|
-
if (
|
|
380
|
-
proposal
|
|
404
|
+
const resolvedMetadata = resolveMetadata(delta, existingProposal?.metadata);
|
|
405
|
+
if (!resolvedMetadata) {
|
|
406
|
+
throw new Error('Missing proposal metadata');
|
|
381
407
|
}
|
|
408
|
+
const proposal = deltaToProposal({
|
|
409
|
+
delta,
|
|
410
|
+
proposalId: commitment,
|
|
411
|
+
metadata: resolvedMetadata,
|
|
412
|
+
signaturesRequired: signatureRequirementForProposal(resolvedMetadata, this.threshold, (proposalType) => this.getEffectiveThreshold(proposalType)),
|
|
413
|
+
existingSignatures: existingProposal?.signatures,
|
|
414
|
+
});
|
|
382
415
|
this.proposals.set(proposal.id, proposal);
|
|
383
|
-
return this.
|
|
416
|
+
return this.listTransactionProposals();
|
|
384
417
|
}
|
|
385
418
|
async executeTransactionProposal(commitment) {
|
|
386
419
|
const proposal = this.proposals.get(commitment);
|
|
387
420
|
if (!proposal) {
|
|
388
421
|
throw new Error(`Proposal not found: ${commitment}`);
|
|
389
422
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
: this.threshold
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
const deltas = await this.psm.getDeltaProposals(this._accountId);
|
|
405
|
-
delta = deltas.find((d) => computeCommitmentFromTxSummary(d.deltaPayload.txSummary.data) === commitment);
|
|
406
|
-
if (!delta) {
|
|
407
|
-
throw new Error(`Proposal not found on server: ${commitment}`);
|
|
408
|
-
}
|
|
409
|
-
txSummaryBase64 = delta.deltaPayload.txSummary.data;
|
|
410
|
-
}
|
|
411
|
-
const txSummaryBytes = base64ToUint8Array(txSummaryBase64);
|
|
412
|
-
const txSummary = TransactionSummary.deserialize(txSummaryBytes);
|
|
413
|
-
const saltHex = txSummary.salt().toHex();
|
|
414
|
-
const txCommitmentHex = txSummary.toCommitment().toHex();
|
|
415
|
-
const adviceMap = new AdviceMap();
|
|
416
|
-
const normalizedSignerCommitments = new Set(this.signerCommitments.map((c) => normalizeHexWord(c)));
|
|
417
|
-
for (const cosignerSig of proposal.signatures) {
|
|
418
|
-
let signerCommitmentHex = normalizeHexWord(cosignerSig.signerId);
|
|
419
|
-
if (cosignerSig.signature.scheme === 'ecdsa' && cosignerSig.signature.publicKey) {
|
|
420
|
-
const derived = tryComputeEcdsaCommitmentHex(cosignerSig.signature.publicKey);
|
|
421
|
-
if (derived && derived !== signerCommitmentHex) {
|
|
422
|
-
if (!normalizedSignerCommitments.has(derived)) {
|
|
423
|
-
throw new Error(`ECDSA public key commitment mismatch: derived commitment ${derived} is not in signerCommitments.`);
|
|
424
|
-
}
|
|
425
|
-
signerCommitmentHex = derived;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
const signerCommitment = Word.fromHex(signerCommitmentHex);
|
|
429
|
-
const sigBytes = signatureHexToBytes(cosignerSig.signature.signature, cosignerSig.signature.scheme);
|
|
430
|
-
const signature = Signature.deserialize(sigBytes);
|
|
431
|
-
const txCommitment = Word.fromHex(normalizeHexWord(txCommitmentHex));
|
|
432
|
-
const isEcdsa = cosignerSig.signature.scheme === 'ecdsa' && cosignerSig.signature.publicKey;
|
|
433
|
-
const { key, values } = buildSignatureAdviceEntry(signerCommitment, txCommitment, signature, isEcdsa ? cosignerSig.signature.publicKey : undefined, isEcdsa ? cosignerSig.signature.signature : undefined);
|
|
434
|
-
adviceMap.insert(key, new FeltArray(values));
|
|
435
|
-
}
|
|
436
|
-
if (!isSwitchPsm && delta) {
|
|
437
|
-
const executionDelta = {
|
|
438
|
-
...delta,
|
|
439
|
-
deltaPayload: delta.deltaPayload.txSummary,
|
|
440
|
-
};
|
|
441
|
-
const pushResult = await this.psm.pushDelta(executionDelta);
|
|
442
|
-
const ackSigHex = pushResult.ackSig;
|
|
443
|
-
if (!ackSigHex) {
|
|
444
|
-
throw new Error('PSM did not return acknowledgment signature');
|
|
445
|
-
}
|
|
446
|
-
const psmAckScheme = pushResult.ackScheme || this.signatureScheme;
|
|
447
|
-
const psmAckPubkey = pushResult.ackPubkey || this.psmPublicKey;
|
|
448
|
-
const psmCommitmentHex = normalizeHexWord(this.psmCommitment);
|
|
449
|
-
if (psmAckScheme === 'ecdsa' && psmAckPubkey) {
|
|
450
|
-
const derived = tryComputeEcdsaCommitmentHex(psmAckPubkey);
|
|
451
|
-
if (derived && derived !== psmCommitmentHex) {
|
|
452
|
-
throw new Error(`PSM public key commitment mismatch`);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
const psmCommitment = Word.fromHex(psmCommitmentHex);
|
|
456
|
-
const ackSigBytes = signatureHexToBytes(ackSigHex, psmAckScheme);
|
|
457
|
-
const ackSignature = Signature.deserialize(ackSigBytes);
|
|
458
|
-
const txCommitmentForAck = Word.fromHex(normalizeHexWord(txCommitmentHex));
|
|
459
|
-
const isAckEcdsa = psmAckScheme === 'ecdsa' && psmAckPubkey;
|
|
460
|
-
const { key: ackKey, values: ackValues } = buildSignatureAdviceEntry(psmCommitment, txCommitmentForAck, ackSignature, isAckEcdsa ? psmAckPubkey : undefined, isAckEcdsa ? ackSigHex : undefined);
|
|
461
|
-
adviceMap.insert(ackKey, new FeltArray(ackValues));
|
|
462
|
-
}
|
|
463
|
-
const metadata = proposal.metadata;
|
|
464
|
-
if (!metadata) {
|
|
465
|
-
throw new Error('Proposal missing metadata');
|
|
466
|
-
}
|
|
467
|
-
let finalRequest;
|
|
468
|
-
switch (metadata.proposalType) {
|
|
469
|
-
case 'consume_notes': {
|
|
470
|
-
if (!metadata.noteIds || metadata.noteIds.length === 0) {
|
|
471
|
-
throw new Error('Proposal missing noteIds. Was it created with createConsumeNotesProposal?');
|
|
472
|
-
}
|
|
473
|
-
const { request } = buildConsumeNotesTransactionRequest(metadata.noteIds, { salt: Word.fromHex(normalizeHexWord(saltHex)), signatureAdviceMap: adviceMap });
|
|
474
|
-
finalRequest = request;
|
|
475
|
-
break;
|
|
476
|
-
}
|
|
477
|
-
case 'switch_psm': {
|
|
478
|
-
if (!metadata.newPsmPubkey) {
|
|
479
|
-
throw new Error('Proposal missing newPsmPubkey. Was it created with createSwitchPsmProposal?');
|
|
480
|
-
}
|
|
481
|
-
const { request } = await buildUpdatePsmTransactionRequest(this.webClient, metadata.newPsmPubkey, {
|
|
482
|
-
salt: Word.fromHex(normalizeHexWord(saltHex)),
|
|
483
|
-
signatureAdviceMap: adviceMap,
|
|
484
|
-
signatureScheme: this.signatureScheme,
|
|
485
|
-
});
|
|
486
|
-
finalRequest = request;
|
|
487
|
-
break;
|
|
488
|
-
}
|
|
489
|
-
case 'p2id': {
|
|
490
|
-
if (!metadata.recipientId || !metadata.faucetId || !metadata.amount) {
|
|
491
|
-
throw new Error('Proposal missing P2ID metadata (recipientId, faucetId, amount). Was it created with createP2idProposal?');
|
|
492
|
-
}
|
|
493
|
-
const { request } = buildP2idTransactionRequest(this._accountId, metadata.recipientId, metadata.faucetId, BigInt(metadata.amount), { salt: Word.fromHex(normalizeHexWord(saltHex)), signatureAdviceMap: adviceMap });
|
|
494
|
-
finalRequest = request;
|
|
495
|
-
break;
|
|
496
|
-
}
|
|
497
|
-
case 'unknown': {
|
|
498
|
-
throw new Error('Cannot execute proposal with unknown type. The proposal must have been imported without proper metadata.');
|
|
499
|
-
}
|
|
500
|
-
default: {
|
|
501
|
-
const { request } = await buildUpdateSignersTransactionRequest(this.webClient, metadata.targetThreshold, metadata.targetSignerCommitments, {
|
|
502
|
-
salt: Word.fromHex(normalizeHexWord(saltHex)),
|
|
503
|
-
signatureAdviceMap: adviceMap,
|
|
504
|
-
signatureScheme: this.signatureScheme,
|
|
505
|
-
});
|
|
506
|
-
finalRequest = request;
|
|
507
|
-
break;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
const accountId = AccountId.fromHex(this._accountId);
|
|
511
|
-
const result = await this.webClient.executeTransaction(accountId, finalRequest);
|
|
512
|
-
const proven = await this.webClient.proveTransaction(result, null);
|
|
513
|
-
const submissionHeight = await this.webClient.submitProvenTransaction(proven, result);
|
|
514
|
-
await this.webClient.applyTransaction(result, submissionHeight);
|
|
423
|
+
await executeProposalWorkflow({
|
|
424
|
+
proposal,
|
|
425
|
+
accountId: this._accountId,
|
|
426
|
+
threshold: this.threshold,
|
|
427
|
+
signerCommitments: this.signerCommitments,
|
|
428
|
+
psmCommitment: this.psmCommitment,
|
|
429
|
+
psmPublicKey: this.psmPublicKey,
|
|
430
|
+
signatureScheme: this.signatureScheme,
|
|
431
|
+
getEffectiveThreshold: (proposalType) => this.getEffectiveThreshold(proposalType),
|
|
432
|
+
psm: this.psm,
|
|
433
|
+
webClient: this.webClient,
|
|
434
|
+
});
|
|
515
435
|
proposal.status = { type: 'finalized' };
|
|
516
436
|
}
|
|
517
437
|
exportTransactionProposalToJson(commitment) {
|
|
@@ -577,7 +497,7 @@ export class Multisig {
|
|
|
577
497
|
const proposals = this.listTransactionProposals();
|
|
578
498
|
return { proposal, proposals };
|
|
579
499
|
}
|
|
580
|
-
signTransactionProposalOffline(commitment) {
|
|
500
|
+
async signTransactionProposalOffline(commitment) {
|
|
581
501
|
const proposal = this.proposals.get(commitment);
|
|
582
502
|
if (!proposal) {
|
|
583
503
|
throw new Error(`Proposal not found: ${commitment}`);
|
|
@@ -586,10 +506,8 @@ export class Multisig {
|
|
|
586
506
|
if (alreadySigned) {
|
|
587
507
|
throw new Error('You have already signed this proposal');
|
|
588
508
|
}
|
|
589
|
-
const signatureHex = this.signer.signCommitment(commitment);
|
|
590
|
-
const sigEntry = this.signer.scheme
|
|
591
|
-
? { scheme: 'ecdsa', signature: signatureHex, publicKey: this.signer.publicKey }
|
|
592
|
-
: { scheme: 'falcon', signature: signatureHex };
|
|
509
|
+
const signatureHex = await this.signer.signCommitment(commitment);
|
|
510
|
+
const sigEntry = toPsmSignature(this.signer.scheme, signatureHex, this.signer.publicKey);
|
|
593
511
|
proposal.signatures.push({
|
|
594
512
|
signerId: this.signer.commitment,
|
|
595
513
|
signature: sigEntry,
|
|
@@ -613,158 +531,12 @@ export class Multisig {
|
|
|
613
531
|
}
|
|
614
532
|
return this.exportTransactionProposalToJson(commitment);
|
|
615
533
|
}
|
|
616
|
-
async
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
catch {
|
|
625
|
-
proposals = this.listTransactionProposals();
|
|
626
|
-
}
|
|
627
|
-
return { proposal, proposals };
|
|
628
|
-
}
|
|
629
|
-
deltaToProposal(delta, proposalId, metadata, existingSignatures) {
|
|
630
|
-
const resolvedMetadata = metadata ??
|
|
631
|
-
(delta.deltaPayload.metadata ? this.fromPsmMetadata(delta.deltaPayload.metadata) : undefined);
|
|
632
|
-
if (!resolvedMetadata) {
|
|
633
|
-
throw new Error('Missing proposal metadata');
|
|
634
|
-
}
|
|
635
|
-
const status = this.deltaStatusToProposalStatus(delta.status, resolvedMetadata.proposalType);
|
|
636
|
-
const signaturesFromStatus = delta.status.status === 'pending'
|
|
637
|
-
? delta.status.cosignerSigs.map((s) => ({
|
|
638
|
-
signerId: s.signerId,
|
|
639
|
-
signature: s.signature,
|
|
640
|
-
timestamp: s.timestamp,
|
|
641
|
-
}))
|
|
642
|
-
: [];
|
|
643
|
-
const signaturesMap = new Map();
|
|
644
|
-
for (const sig of existingSignatures ?? []) {
|
|
645
|
-
signaturesMap.set(sig.signerId, sig);
|
|
646
|
-
}
|
|
647
|
-
for (const sig of signaturesFromStatus) {
|
|
648
|
-
signaturesMap.set(sig.signerId, sig);
|
|
649
|
-
}
|
|
650
|
-
const signatures = Array.from(signaturesMap.values());
|
|
651
|
-
return {
|
|
652
|
-
id: proposalId,
|
|
653
|
-
commitment: proposalId,
|
|
654
|
-
accountId: delta.accountId,
|
|
655
|
-
nonce: delta.nonce,
|
|
656
|
-
status,
|
|
657
|
-
txSummary: delta.deltaPayload.txSummary.data,
|
|
658
|
-
signatures,
|
|
659
|
-
metadata: resolvedMetadata,
|
|
660
|
-
};
|
|
661
|
-
}
|
|
662
|
-
buildPsmMetadata(metadata) {
|
|
663
|
-
const base = {
|
|
664
|
-
proposalType: metadata.proposalType,
|
|
665
|
-
description: metadata.description,
|
|
666
|
-
salt: metadata.saltHex,
|
|
667
|
-
};
|
|
668
|
-
switch (metadata.proposalType) {
|
|
669
|
-
case 'consume_notes':
|
|
670
|
-
return {
|
|
671
|
-
...base,
|
|
672
|
-
noteIds: metadata.noteIds,
|
|
673
|
-
};
|
|
674
|
-
case 'p2id':
|
|
675
|
-
return {
|
|
676
|
-
...base,
|
|
677
|
-
recipientId: metadata.recipientId,
|
|
678
|
-
faucetId: metadata.faucetId,
|
|
679
|
-
amount: metadata.amount,
|
|
680
|
-
};
|
|
681
|
-
case 'switch_psm':
|
|
682
|
-
return {
|
|
683
|
-
...base,
|
|
684
|
-
targetThreshold: metadata.targetThreshold,
|
|
685
|
-
signerCommitments: metadata.targetSignerCommitments,
|
|
686
|
-
newPsmPubkey: metadata.newPsmPubkey,
|
|
687
|
-
newPsmEndpoint: metadata.newPsmEndpoint,
|
|
688
|
-
};
|
|
689
|
-
case 'add_signer':
|
|
690
|
-
case 'remove_signer':
|
|
691
|
-
case 'change_threshold':
|
|
692
|
-
return {
|
|
693
|
-
...base,
|
|
694
|
-
targetThreshold: metadata.targetThreshold,
|
|
695
|
-
signerCommitments: metadata.targetSignerCommitments,
|
|
696
|
-
};
|
|
697
|
-
case 'unknown':
|
|
698
|
-
return base;
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
fromPsmMetadata(psm) {
|
|
702
|
-
if (!psm.proposalType)
|
|
703
|
-
return undefined;
|
|
704
|
-
const base = {
|
|
705
|
-
description: psm.description ?? '',
|
|
706
|
-
saltHex: psm.salt,
|
|
707
|
-
};
|
|
708
|
-
switch (psm.proposalType) {
|
|
709
|
-
case 'p2id':
|
|
710
|
-
return {
|
|
711
|
-
...base,
|
|
712
|
-
proposalType: 'p2id',
|
|
713
|
-
recipientId: psm.recipientId ?? '',
|
|
714
|
-
faucetId: psm.faucetId ?? '',
|
|
715
|
-
amount: psm.amount ?? '0',
|
|
716
|
-
};
|
|
717
|
-
case 'consume_notes':
|
|
718
|
-
return {
|
|
719
|
-
...base,
|
|
720
|
-
proposalType: 'consume_notes',
|
|
721
|
-
noteIds: psm.noteIds ?? [],
|
|
722
|
-
};
|
|
723
|
-
case 'switch_psm':
|
|
724
|
-
return {
|
|
725
|
-
...base,
|
|
726
|
-
proposalType: 'switch_psm',
|
|
727
|
-
newPsmPubkey: psm.newPsmPubkey ?? '',
|
|
728
|
-
newPsmEndpoint: psm.newPsmEndpoint,
|
|
729
|
-
targetThreshold: psm.targetThreshold,
|
|
730
|
-
targetSignerCommitments: psm.signerCommitments,
|
|
731
|
-
};
|
|
732
|
-
case 'add_signer':
|
|
733
|
-
case 'remove_signer':
|
|
734
|
-
case 'change_threshold':
|
|
735
|
-
return {
|
|
736
|
-
...base,
|
|
737
|
-
proposalType: psm.proposalType,
|
|
738
|
-
targetThreshold: psm.targetThreshold ?? 0,
|
|
739
|
-
targetSignerCommitments: psm.signerCommitments ?? [],
|
|
740
|
-
};
|
|
741
|
-
default:
|
|
742
|
-
return undefined;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
deltaStatusToProposalStatus(status, proposalType) {
|
|
746
|
-
switch (status.status) {
|
|
747
|
-
case 'pending': {
|
|
748
|
-
const signaturesCollected = status.cosignerSigs.length;
|
|
749
|
-
const signaturesRequired = proposalType
|
|
750
|
-
? this.getEffectiveThreshold(proposalType)
|
|
751
|
-
: this.threshold;
|
|
752
|
-
if (signaturesCollected >= signaturesRequired) {
|
|
753
|
-
return { type: 'ready' };
|
|
754
|
-
}
|
|
755
|
-
return {
|
|
756
|
-
type: 'pending',
|
|
757
|
-
signaturesCollected,
|
|
758
|
-
signaturesRequired,
|
|
759
|
-
signers: status.cosignerSigs.map((s) => s.signerId),
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
case 'candidate':
|
|
763
|
-
return { type: 'ready' };
|
|
764
|
-
case 'canonical':
|
|
765
|
-
case 'discarded':
|
|
766
|
-
return { type: 'finalized' };
|
|
767
|
-
}
|
|
534
|
+
async createAndSyncFromRequest(request, metadata, nonce) {
|
|
535
|
+
const summary = await executeForSummary(this.webClient, this._accountId, request);
|
|
536
|
+
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
537
|
+
const proposalNonce = nonce ?? Date.now();
|
|
538
|
+
const proposal = await this.createProposal(proposalNonce, summaryBase64, metadata);
|
|
539
|
+
return { proposal, proposals: this.listTransactionProposals() };
|
|
768
540
|
}
|
|
769
541
|
}
|
|
770
542
|
//# sourceMappingURL=multisig.js.map
|