@sovereign-sdk/web3 0.14.0 → 0.15.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 +33 -3
- package/dist/index.d.mts +118 -71
- package/dist/index.d.ts +118 -71
- package/dist/index.js +406 -232
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +410 -233
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -7
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ __export(src_exports, {
|
|
|
40
40
|
StandardRollup: () => StandardRollup,
|
|
41
41
|
VersionMismatchError: () => VersionMismatchError,
|
|
42
42
|
addressFromPublicKey: () => addressFromPublicKey,
|
|
43
|
+
chainHashFragment: () => chainHashFragment,
|
|
43
44
|
createSolanaSignableRollup: () => createSolanaSignableRollup,
|
|
44
45
|
createStandardRollup: () => createStandardRollup,
|
|
45
46
|
standardTypeBuilder: () => standardTypeBuilder
|
|
@@ -169,13 +170,29 @@ var Rollup = class {
|
|
|
169
170
|
* Retrieve dedup information about the provided address.
|
|
170
171
|
*
|
|
171
172
|
* @param publicKey - The public key to dedup.
|
|
172
|
-
* TODO: How to
|
|
173
|
+
* TODO: How to request a specific uniqueness strategy explicitly
|
|
173
174
|
*/
|
|
174
175
|
async dedup(publicKey) {
|
|
175
|
-
|
|
176
|
+
return this.dedupByCredentialId((0, import_utils2.bytesToHex)(publicKey));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Retrieve dedup information about the provided credential ID.
|
|
180
|
+
*/
|
|
181
|
+
async dedupByCredentialId(credentialId) {
|
|
176
182
|
const response = await this.rollup.addresses.dedup(credentialId);
|
|
177
183
|
return response;
|
|
178
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Builds an unsigned transaction for the provided runtime call.
|
|
187
|
+
*/
|
|
188
|
+
async buildUnsignedTransaction(runtimeCall, params) {
|
|
189
|
+
const context = {
|
|
190
|
+
runtimeCall,
|
|
191
|
+
rollup: this,
|
|
192
|
+
overrides: params?.overrides ?? {}
|
|
193
|
+
};
|
|
194
|
+
return this._typeBuilder.unsignedTransaction(context);
|
|
195
|
+
}
|
|
179
196
|
/**
|
|
180
197
|
* Submits a transaction to the rollup.
|
|
181
198
|
*
|
|
@@ -233,12 +250,9 @@ var Rollup = class {
|
|
|
233
250
|
* @param {SovereignClient.RequestOptions} options - The options for the request.
|
|
234
251
|
*/
|
|
235
252
|
async call(runtimeCall, { signer, overrides }, options) {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
overrides: overrides ?? {}
|
|
240
|
-
};
|
|
241
|
-
const unsignedTx = await this._typeBuilder.unsignedTransaction(context);
|
|
253
|
+
const unsignedTx = await this.buildUnsignedTransaction(runtimeCall, {
|
|
254
|
+
overrides
|
|
255
|
+
});
|
|
242
256
|
return this.signAndSubmitTransaction(
|
|
243
257
|
unsignedTx,
|
|
244
258
|
{
|
|
@@ -259,18 +273,15 @@ var Rollup = class {
|
|
|
259
273
|
* @returns A promise that resolves to the signed transaction.
|
|
260
274
|
*/
|
|
261
275
|
async prepareCall(runtimeCall, { signer, overrides }) {
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
overrides: overrides ?? {}
|
|
266
|
-
};
|
|
267
|
-
const unsignedTx = await this._typeBuilder.unsignedTransaction(context);
|
|
276
|
+
const unsignedTx = await this.buildUnsignedTransaction(runtimeCall, {
|
|
277
|
+
overrides
|
|
278
|
+
});
|
|
268
279
|
return this.signTransaction(unsignedTx, signer);
|
|
269
280
|
}
|
|
270
281
|
/**
|
|
271
282
|
* Signs an unsigned transaction using the provided signer.
|
|
272
|
-
* Creates a signature
|
|
273
|
-
*
|
|
283
|
+
* Creates a signature over the serialized transaction signing payload, then constructs a fully
|
|
284
|
+
* signed transaction.
|
|
274
285
|
*
|
|
275
286
|
* @param unsignedTx - The unsigned transaction to sign.
|
|
276
287
|
* @param signer - The signer to use for signing the transaction.
|
|
@@ -278,11 +289,15 @@ var Rollup = class {
|
|
|
278
289
|
*/
|
|
279
290
|
async signTransaction(unsignedTx, signer) {
|
|
280
291
|
const serializer = await this.serializer();
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
292
|
+
const transactionSigningPayload = await this._typeBuilder.transactionSigningPayload({
|
|
293
|
+
unsignedTx,
|
|
294
|
+
chainHash: await this.chainHash(),
|
|
295
|
+
rollup: this
|
|
296
|
+
});
|
|
297
|
+
const signingBytes = serializer.serializeSigningPayload(
|
|
298
|
+
transactionSigningPayload
|
|
285
299
|
);
|
|
300
|
+
const signature = await signer.sign(signingBytes);
|
|
286
301
|
const publicKey = await signer.publicKey();
|
|
287
302
|
const context = {
|
|
288
303
|
unsignedTx,
|
|
@@ -370,10 +385,12 @@ var Rollup = class {
|
|
|
370
385
|
}
|
|
371
386
|
};
|
|
372
387
|
function isVersionMismatchError(e) {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
388
|
+
const details = e.error?.details;
|
|
389
|
+
if (details?.code === "invalid_chain_hash_fragment") {
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
const error = details?.error;
|
|
393
|
+
if (typeof error === "string" && error.includes("Signature verification failed")) {
|
|
377
394
|
return true;
|
|
378
395
|
}
|
|
379
396
|
return false;
|
|
@@ -383,6 +400,36 @@ function isVersionMismatchError(e) {
|
|
|
383
400
|
var import_client2 = __toESM(require("@sovereign-sdk/client"));
|
|
384
401
|
var import_serializers = require("@sovereign-sdk/serializers");
|
|
385
402
|
var import_utils3 = require("@sovereign-sdk/utils");
|
|
403
|
+
|
|
404
|
+
// src/rollup/chain-hash.ts
|
|
405
|
+
function chainHashFragment(chainHash) {
|
|
406
|
+
if (chainHash.length < 8) {
|
|
407
|
+
throw new Error("chain hash must contain at least 8 bytes");
|
|
408
|
+
}
|
|
409
|
+
return new DataView(
|
|
410
|
+
chainHash.buffer,
|
|
411
|
+
chainHash.byteOffset,
|
|
412
|
+
chainHash.byteLength
|
|
413
|
+
).getBigUint64(0, true).toString();
|
|
414
|
+
}
|
|
415
|
+
function refreshChainHashFragment(unsignedTx, chainHash) {
|
|
416
|
+
unsignedTx.details = {
|
|
417
|
+
...unsignedTx.details,
|
|
418
|
+
chain_hash_fragment: chainHashFragment(chainHash)
|
|
419
|
+
};
|
|
420
|
+
return unsignedTx;
|
|
421
|
+
}
|
|
422
|
+
function assertChainHashFragment(unsignedTx, chainHash) {
|
|
423
|
+
const expectedFragment = chainHashFragment(chainHash);
|
|
424
|
+
const actualFragment = unsignedTx.details.chain_hash_fragment;
|
|
425
|
+
if (actualFragment !== expectedFragment) {
|
|
426
|
+
throw new Error(
|
|
427
|
+
`Cannot sign transaction: chain_hash_fragment ${actualFragment} does not match the current chain hash fragment ${expectedFragment}`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/rollup/standard-rollup.ts
|
|
386
433
|
var useOrFetchUniqueness = async ({
|
|
387
434
|
overrides
|
|
388
435
|
}) => {
|
|
@@ -395,7 +442,7 @@ function standardTypeBuilder() {
|
|
|
395
442
|
return {
|
|
396
443
|
async unsignedTransaction(context) {
|
|
397
444
|
const { rollup, runtimeCall } = context;
|
|
398
|
-
const
|
|
445
|
+
const overrides = context.overrides;
|
|
399
446
|
const uniqueness = await useOrFetchUniqueness(context);
|
|
400
447
|
const details = {
|
|
401
448
|
...rollup.context.defaultTxDetails,
|
|
@@ -404,7 +451,8 @@ function standardTypeBuilder() {
|
|
|
404
451
|
return {
|
|
405
452
|
runtime_call: runtimeCall,
|
|
406
453
|
uniqueness,
|
|
407
|
-
details
|
|
454
|
+
details,
|
|
455
|
+
address_override: overrides.address_override ?? null
|
|
408
456
|
};
|
|
409
457
|
},
|
|
410
458
|
async transaction({
|
|
@@ -419,10 +467,67 @@ function standardTypeBuilder() {
|
|
|
419
467
|
...unsignedTx
|
|
420
468
|
}
|
|
421
469
|
};
|
|
470
|
+
},
|
|
471
|
+
async transactionSigningPayload({
|
|
472
|
+
unsignedTx,
|
|
473
|
+
chainHash
|
|
474
|
+
}) {
|
|
475
|
+
const normalizedUnsignedTx = refreshChainHashFragment(
|
|
476
|
+
unsignedTx,
|
|
477
|
+
chainHash
|
|
478
|
+
);
|
|
479
|
+
return {
|
|
480
|
+
V0: {
|
|
481
|
+
...normalizedUnsignedTx,
|
|
482
|
+
chain_hash: Array.from(chainHash)
|
|
483
|
+
}
|
|
484
|
+
};
|
|
422
485
|
}
|
|
423
486
|
};
|
|
424
487
|
}
|
|
425
488
|
var StandardRollup = class extends Rollup {
|
|
489
|
+
updateDefaultChainHashFragment(chainHash) {
|
|
490
|
+
this.context.defaultTxDetails.chain_hash_fragment = chainHashFragment(chainHash);
|
|
491
|
+
}
|
|
492
|
+
async credentialAddressFromId(credentialId) {
|
|
493
|
+
if (this.context.credentialIdToAddress) {
|
|
494
|
+
const serializer = await this.serializer();
|
|
495
|
+
return this.context.credentialIdToAddress(
|
|
496
|
+
credentialId,
|
|
497
|
+
serializer.schema
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
return addressFromPublicKey(credentialId, "sov");
|
|
501
|
+
}
|
|
502
|
+
async submitTransaction(transaction, options) {
|
|
503
|
+
try {
|
|
504
|
+
return await super.submitTransaction(transaction, options);
|
|
505
|
+
} catch (error) {
|
|
506
|
+
if (error instanceof VersionMismatchError) {
|
|
507
|
+
this.updateDefaultChainHashFragment(await super.chainHash());
|
|
508
|
+
}
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
async hydrate() {
|
|
513
|
+
await super.hydrate();
|
|
514
|
+
this.updateDefaultChainHashFragment(await super.chainHash());
|
|
515
|
+
}
|
|
516
|
+
async multisigSigningBytes(unsignedTx, multisig) {
|
|
517
|
+
const serializer = await this.serializer();
|
|
518
|
+
const chainHash = await this.chainHash();
|
|
519
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
520
|
+
const signingPayload = {
|
|
521
|
+
V1: {
|
|
522
|
+
...unsignedTx,
|
|
523
|
+
chain_hash: Array.from(chainHash),
|
|
524
|
+
credential_address: await this.credentialAddressFromId(
|
|
525
|
+
multisig.getMultisigAddress()
|
|
526
|
+
)
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
return serializer.serializeSigningPayload(signingPayload);
|
|
530
|
+
}
|
|
426
531
|
/**
|
|
427
532
|
* Simulates a runtime call transaction.
|
|
428
533
|
*
|
|
@@ -430,11 +535,15 @@ var StandardRollup = class extends Rollup {
|
|
|
430
535
|
*
|
|
431
536
|
* @param runtimeMessage - The runtime message to call.
|
|
432
537
|
*/
|
|
433
|
-
async simulate(runtimeMessage, { signer }) {
|
|
538
|
+
async simulate(runtimeMessage, { signer, ...params }) {
|
|
434
539
|
const publicKey = await signer.publicKey();
|
|
435
540
|
const sender = (0, import_utils3.bytesToHex)(publicKey);
|
|
436
541
|
const call = runtimeMessage;
|
|
437
|
-
return this.rollup.simulate({
|
|
542
|
+
return this.rollup.simulate({
|
|
543
|
+
...params,
|
|
544
|
+
sender,
|
|
545
|
+
call
|
|
546
|
+
});
|
|
438
547
|
}
|
|
439
548
|
};
|
|
440
549
|
var DEFAULT_TX_DETAILS = {
|
|
@@ -442,26 +551,24 @@ var DEFAULT_TX_DETAILS = {
|
|
|
442
551
|
max_fee: "100000000",
|
|
443
552
|
gas_limit: null
|
|
444
553
|
};
|
|
445
|
-
|
|
554
|
+
function buildContext(context, credentialIdToAddress) {
|
|
446
555
|
const defaultTxDetails = {
|
|
447
556
|
...DEFAULT_TX_DETAILS,
|
|
448
557
|
...context?.defaultTxDetails
|
|
449
558
|
};
|
|
450
|
-
if (!defaultTxDetails.chain_id) {
|
|
451
|
-
const { chain_id } = await client.rollup.constants();
|
|
452
|
-
defaultTxDetails.chain_id = chain_id;
|
|
453
|
-
}
|
|
454
559
|
return {
|
|
455
|
-
|
|
560
|
+
...context,
|
|
561
|
+
defaultTxDetails,
|
|
562
|
+
credentialIdToAddress: credentialIdToAddress ?? context?.credentialIdToAddress
|
|
456
563
|
};
|
|
457
564
|
}
|
|
458
565
|
async function createStandardRollup(rollupConfig, typeBuilderOverrides) {
|
|
459
566
|
const config = rollupConfig ?? {};
|
|
460
567
|
const client = config.client ?? new import_client2.default({ baseURL: config.url });
|
|
461
568
|
const getSerializer = config.getSerializer ?? ((schema) => new import_serializers.JsSerializer(schema));
|
|
462
|
-
const context =
|
|
569
|
+
const context = buildContext(config.context, config.credentialIdToAddress);
|
|
463
570
|
const txSubmissionEndpoint = config.txSubmissionEndpoint ?? "/sequencer/txs";
|
|
464
|
-
|
|
571
|
+
const rollup = new StandardRollup(
|
|
465
572
|
{
|
|
466
573
|
...config,
|
|
467
574
|
client,
|
|
@@ -474,9 +581,14 @@ async function createStandardRollup(rollupConfig, typeBuilderOverrides) {
|
|
|
474
581
|
...typeBuilderOverrides
|
|
475
582
|
}
|
|
476
583
|
);
|
|
584
|
+
if (!context.defaultTxDetails.chain_hash_fragment) {
|
|
585
|
+
await rollup.hydrate();
|
|
586
|
+
}
|
|
587
|
+
return rollup;
|
|
477
588
|
}
|
|
478
589
|
|
|
479
590
|
// src/rollup/solana-signable-rollup.ts
|
|
591
|
+
var import_multisig = require("@sovereign-sdk/multisig");
|
|
480
592
|
var import_signers = require("@sovereign-sdk/signers");
|
|
481
593
|
var import_utils4 = require("@sovereign-sdk/utils");
|
|
482
594
|
var import_bs58 = __toESM(require("bs58"));
|
|
@@ -487,7 +599,6 @@ var CHAIN_HASH_SIZE = 32;
|
|
|
487
599
|
var PUBKEY_SIZE = 32;
|
|
488
600
|
var SIGNATURE_SIZE = 64;
|
|
489
601
|
var MULTISIG_PREAMBLE_FIXED_LENGTH = 53;
|
|
490
|
-
var MAX_MULTISIG_SIGNERS = 21;
|
|
491
602
|
var SIGNING_DOMAIN = new Uint8Array([
|
|
492
603
|
255,
|
|
493
604
|
...new TextEncoder().encode("solana offchain")
|
|
@@ -504,9 +615,9 @@ function compareByteArrays(left, right) {
|
|
|
504
615
|
return left.length - right.length;
|
|
505
616
|
}
|
|
506
617
|
function createSolanaPreamble(pubkeys, chainHash, messageLength) {
|
|
507
|
-
if (pubkeys.length < 1 || pubkeys.length >
|
|
618
|
+
if (pubkeys.length < 1 || pubkeys.length > import_multisig.MAX_SIGNERS) {
|
|
508
619
|
throw new Error(
|
|
509
|
-
`Invalid signer count: expected 1-${
|
|
620
|
+
`Invalid signer count: expected 1-${import_multisig.MAX_SIGNERS} signers, got ${pubkeys.length}`
|
|
510
621
|
);
|
|
511
622
|
}
|
|
512
623
|
const preamble = new Uint8Array(
|
|
@@ -552,45 +663,37 @@ var SolanaSignableRollup = class {
|
|
|
552
663
|
/**
|
|
553
664
|
* Submits serialized data to the Solana endpoint.
|
|
554
665
|
*/
|
|
555
|
-
async submitSerializedMessage(serializedMessage) {
|
|
666
|
+
async submitSerializedMessage(serializedMessage, options) {
|
|
667
|
+
const { body: _, query: __, path, ...requestOptions } = options || {};
|
|
556
668
|
return await this.inner.http.post(
|
|
557
|
-
this.solanaEndpoint,
|
|
669
|
+
path || this.solanaEndpoint,
|
|
558
670
|
{
|
|
559
671
|
// Match AcceptTx shape used by standard sequencer endpoints.
|
|
560
|
-
body: { body: import_js_base642.Base64.fromUint8Array(serializedMessage) }
|
|
672
|
+
body: { body: import_js_base642.Base64.fromUint8Array(serializedMessage) },
|
|
673
|
+
...requestOptions
|
|
561
674
|
}
|
|
562
675
|
);
|
|
563
676
|
}
|
|
564
677
|
/**
|
|
565
678
|
* Submits a Solana offchain message to the rollup.
|
|
566
679
|
*/
|
|
567
|
-
async submitSolanaMessage(solanaMessage) {
|
|
680
|
+
async submitSolanaMessage(solanaMessage, options) {
|
|
568
681
|
const serializedMessage = this.serializeSolanaMessage(solanaMessage);
|
|
569
|
-
return this.submitSerializedMessage(serializedMessage);
|
|
682
|
+
return this.submitSerializedMessage(serializedMessage, options);
|
|
570
683
|
}
|
|
571
684
|
/**
|
|
572
685
|
* Submits a Solana spec-compliant message to the rollup.
|
|
573
686
|
*/
|
|
574
|
-
async submitSolanaSpecMessage(solanaMessage) {
|
|
687
|
+
async submitSolanaSpecMessage(solanaMessage, options) {
|
|
575
688
|
const serializedMessage = this.serializeSolanaSpecMessage(solanaMessage);
|
|
576
|
-
return this.submitSerializedMessage(serializedMessage);
|
|
689
|
+
return this.submitSerializedMessage(serializedMessage, options);
|
|
577
690
|
}
|
|
578
691
|
/**
|
|
579
692
|
* Submits a Solana spec-compliant multisig message to the rollup.
|
|
580
693
|
*/
|
|
581
|
-
async submitSolanaSpecMultisigMessage(solanaMessage) {
|
|
694
|
+
async submitSolanaSpecMultisigMessage(solanaMessage, options) {
|
|
582
695
|
const serializedMessage = this.serializeSolanaSpecMultisigMessage(solanaMessage);
|
|
583
|
-
return this.submitSerializedMessage(serializedMessage);
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Helper to build an unsigned transaction using the standard type builder.
|
|
587
|
-
*/
|
|
588
|
-
async buildUnsignedTransaction(runtimeCall, overrides) {
|
|
589
|
-
return this.typeBuilder.unsignedTransaction({
|
|
590
|
-
runtimeCall,
|
|
591
|
-
overrides: overrides ?? {},
|
|
592
|
-
rollup: this.inner
|
|
593
|
-
});
|
|
696
|
+
return this.submitSerializedMessage(serializedMessage, options);
|
|
594
697
|
}
|
|
595
698
|
/**
|
|
596
699
|
* Helper to build a transaction result object.
|
|
@@ -618,18 +721,15 @@ var SolanaSignableRollup = class {
|
|
|
618
721
|
* The canonical order is lexicographic by raw pubkey bytes.
|
|
619
722
|
*/
|
|
620
723
|
canonicalizeMultisigPubkeys(multisigPubkeys) {
|
|
621
|
-
if (
|
|
724
|
+
if (multisigPubkeys.length < 1 || multisigPubkeys.length > import_multisig.MAX_SIGNERS) {
|
|
622
725
|
throw new Error(
|
|
623
|
-
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
if (multisigPubkeys.length < 2 || multisigPubkeys.length > MAX_MULTISIG_SIGNERS) {
|
|
627
|
-
throw new Error(
|
|
628
|
-
`Invalid multisig signer count: expected 2-${MAX_MULTISIG_SIGNERS} signers, got ${multisigPubkeys.length}`
|
|
726
|
+
`Invalid multisig signer count: expected 1-${import_multisig.MAX_SIGNERS} signers, got ${multisigPubkeys.length}`
|
|
629
727
|
);
|
|
630
728
|
}
|
|
631
729
|
const seenPubkeys = /* @__PURE__ */ new Set();
|
|
632
|
-
|
|
730
|
+
const normalizedPubkeys = multisigPubkeys.map(import_utils4.normalizeHexString);
|
|
731
|
+
const pubkeyBytes = normalizedPubkeys.map((pubkey) => (0, import_utils4.hexToBytes)(pubkey));
|
|
732
|
+
for (const pubkey of pubkeyBytes) {
|
|
633
733
|
if (pubkey.length !== PUBKEY_SIZE) {
|
|
634
734
|
throw new Error(
|
|
635
735
|
`Invalid public key length: expected ${PUBKEY_SIZE} bytes, got ${pubkey.length}`
|
|
@@ -641,31 +741,36 @@ var SolanaSignableRollup = class {
|
|
|
641
741
|
}
|
|
642
742
|
seenPubkeys.add(pubkeyHex);
|
|
643
743
|
}
|
|
644
|
-
return
|
|
744
|
+
return pubkeyBytes.sort(compareByteArrays);
|
|
645
745
|
}
|
|
646
746
|
/**
|
|
647
|
-
* Helper to create and serialize a
|
|
747
|
+
* Helper to create and serialize a SolanaOffchainSigningPayloadV0 to JSON bytes.
|
|
648
748
|
*/
|
|
649
749
|
async createSolanaJsonBytes(unsignedTx) {
|
|
650
750
|
const serializer = await this.inner.serializer();
|
|
651
751
|
const schema = serializer.schema;
|
|
652
752
|
const chainName = schema.chain_data.chain_name || "";
|
|
653
|
-
const
|
|
753
|
+
const solanaSigningPayload = {
|
|
654
754
|
runtime_call: unsignedTx.runtime_call,
|
|
655
755
|
uniqueness: unsignedTx.uniqueness,
|
|
656
756
|
details: unsignedTx.details,
|
|
657
|
-
chain_name: chainName
|
|
757
|
+
chain_name: chainName,
|
|
758
|
+
...unsignedTx.address_override !== null && unsignedTx.address_override !== void 0 && {
|
|
759
|
+
address_override: unsignedTx.address_override
|
|
760
|
+
},
|
|
761
|
+
version: 0
|
|
658
762
|
};
|
|
659
|
-
return new TextEncoder().encode(JSON.stringify(
|
|
763
|
+
return new TextEncoder().encode(JSON.stringify(solanaSigningPayload));
|
|
660
764
|
}
|
|
661
765
|
/**
|
|
662
766
|
* Signs an unsigned transaction using Solana offchain simple signing and submits it.
|
|
663
767
|
* Returns the transaction result in the same format as standard rollup.
|
|
664
768
|
*/
|
|
665
|
-
async signWithSolanaSimpleAndSubmit(unsignedTx, signer) {
|
|
769
|
+
async signWithSolanaSimpleAndSubmit(unsignedTx, signer, options) {
|
|
770
|
+
const chainHash = await this.inner.chainHash();
|
|
771
|
+
refreshChainHashFragment(unsignedTx, chainHash);
|
|
666
772
|
const jsonBytes = await this.createSolanaJsonBytes(unsignedTx);
|
|
667
773
|
const pubkey = await signer.publicKey();
|
|
668
|
-
const chainHash = await this.inner.chainHash();
|
|
669
774
|
const signature = await signer.sign(jsonBytes);
|
|
670
775
|
const solanaMessage = {
|
|
671
776
|
signed_message: jsonBytes,
|
|
@@ -673,17 +778,18 @@ var SolanaSignableRollup = class {
|
|
|
673
778
|
pubkey,
|
|
674
779
|
signature
|
|
675
780
|
};
|
|
676
|
-
const response = await this.submitSolanaMessage(solanaMessage);
|
|
781
|
+
const response = await this.submitSolanaMessage(solanaMessage, options);
|
|
677
782
|
return this.buildTransactionResult(response, unsignedTx, pubkey, signature);
|
|
678
783
|
}
|
|
679
784
|
/**
|
|
680
785
|
* Signs an unsigned transaction using Solana spec-compliant signing and submits it.
|
|
681
786
|
* Returns the transaction result in the same format as standard rollup.
|
|
682
787
|
*/
|
|
683
|
-
async signWithSolanaSpecAndSubmit(unsignedTx, signer) {
|
|
788
|
+
async signWithSolanaSpecAndSubmit(unsignedTx, signer, options) {
|
|
789
|
+
const chainHash = await this.inner.chainHash();
|
|
790
|
+
refreshChainHashFragment(unsignedTx, chainHash);
|
|
684
791
|
const jsonBytes = await this.createSolanaJsonBytes(unsignedTx);
|
|
685
792
|
const pubkey = await signer.publicKey();
|
|
686
|
-
const chainHash = await this.inner.chainHash();
|
|
687
793
|
const preamble = createSolanaPreamble(
|
|
688
794
|
[pubkey],
|
|
689
795
|
chainHash,
|
|
@@ -698,7 +804,7 @@ var SolanaSignableRollup = class {
|
|
|
698
804
|
signed_message_with_preamble: signedMessageWithPreamble,
|
|
699
805
|
signature
|
|
700
806
|
};
|
|
701
|
-
const response = await this.submitSolanaSpecMessage(solanaMessage);
|
|
807
|
+
const response = await this.submitSolanaSpecMessage(solanaMessage, options);
|
|
702
808
|
return this.buildTransactionResult(response, unsignedTx, pubkey, signature);
|
|
703
809
|
}
|
|
704
810
|
/**
|
|
@@ -722,18 +828,30 @@ var SolanaSignableRollup = class {
|
|
|
722
828
|
options
|
|
723
829
|
);
|
|
724
830
|
case "solanaSimple": {
|
|
725
|
-
const unsignedTx = await this.buildUnsignedTransaction(
|
|
831
|
+
const unsignedTx = await this.inner.buildUnsignedTransaction(
|
|
726
832
|
runtimeCall,
|
|
727
|
-
|
|
833
|
+
{
|
|
834
|
+
overrides: params.overrides
|
|
835
|
+
}
|
|
836
|
+
);
|
|
837
|
+
return this.signWithSolanaSimpleAndSubmit(
|
|
838
|
+
unsignedTx,
|
|
839
|
+
params.signer,
|
|
840
|
+
options
|
|
728
841
|
);
|
|
729
|
-
return this.signWithSolanaSimpleAndSubmit(unsignedTx, params.signer);
|
|
730
842
|
}
|
|
731
843
|
case "solana": {
|
|
732
|
-
const unsignedTx = await this.buildUnsignedTransaction(
|
|
844
|
+
const unsignedTx = await this.inner.buildUnsignedTransaction(
|
|
733
845
|
runtimeCall,
|
|
734
|
-
|
|
846
|
+
{
|
|
847
|
+
overrides: params.overrides
|
|
848
|
+
}
|
|
849
|
+
);
|
|
850
|
+
return this.signWithSolanaSpecAndSubmit(
|
|
851
|
+
unsignedTx,
|
|
852
|
+
params.signer,
|
|
853
|
+
options
|
|
735
854
|
);
|
|
736
|
-
return this.signWithSolanaSpecAndSubmit(unsignedTx, params.signer);
|
|
737
855
|
}
|
|
738
856
|
default:
|
|
739
857
|
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
@@ -759,132 +877,134 @@ var SolanaSignableRollup = class {
|
|
|
759
877
|
options
|
|
760
878
|
);
|
|
761
879
|
case "solanaSimple":
|
|
762
|
-
return this.signWithSolanaSimpleAndSubmit(
|
|
880
|
+
return this.signWithSolanaSimpleAndSubmit(
|
|
881
|
+
unsignedTx,
|
|
882
|
+
params.signer,
|
|
883
|
+
options
|
|
884
|
+
);
|
|
763
885
|
case "solana":
|
|
764
|
-
return this.signWithSolanaSpecAndSubmit(
|
|
886
|
+
return this.signWithSolanaSpecAndSubmit(
|
|
887
|
+
unsignedTx,
|
|
888
|
+
params.signer,
|
|
889
|
+
options
|
|
890
|
+
);
|
|
765
891
|
default:
|
|
766
892
|
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
767
893
|
}
|
|
768
894
|
}
|
|
895
|
+
async buildUnsignedTransaction(runtimeCall, params) {
|
|
896
|
+
return this.inner.buildUnsignedTransaction(runtimeCall, params);
|
|
897
|
+
}
|
|
769
898
|
/**
|
|
770
899
|
* Creates V1 JSON bytes for a multisig transaction, including multisig_id and version.
|
|
771
900
|
* The resulting JSON is what each signer signs directly (no discriminator prefix).
|
|
772
901
|
*/
|
|
773
|
-
async createMultisigJsonBytes(unsignedTx,
|
|
902
|
+
async createMultisigJsonBytes(unsignedTx, multisigId) {
|
|
774
903
|
const serializer = await this.inner.serializer();
|
|
775
904
|
const schema = serializer.schema;
|
|
776
905
|
const chainName = schema.chain_data.chain_name || "";
|
|
777
|
-
const
|
|
906
|
+
const solanaSigningPayload = {
|
|
778
907
|
runtime_call: unsignedTx.runtime_call,
|
|
779
908
|
uniqueness: unsignedTx.uniqueness,
|
|
780
909
|
details: unsignedTx.details,
|
|
781
910
|
chain_name: chainName,
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
911
|
+
multisig_id: multisigId,
|
|
912
|
+
...unsignedTx.address_override !== null && unsignedTx.address_override !== void 0 && {
|
|
913
|
+
address_override: unsignedTx.address_override
|
|
914
|
+
},
|
|
786
915
|
version: 1
|
|
787
916
|
};
|
|
788
|
-
return new TextEncoder().encode(JSON.stringify(
|
|
917
|
+
return new TextEncoder().encode(JSON.stringify(solanaSigningPayload));
|
|
789
918
|
}
|
|
790
919
|
/**
|
|
791
|
-
*
|
|
920
|
+
* Formats the multisig credential in the rollup's configured address format.
|
|
792
921
|
*/
|
|
793
|
-
async
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
);
|
|
804
|
-
return this.combinePreambleAndMessage(preamble, jsonBytes);
|
|
922
|
+
async multisigIdFromMultisig(multisig) {
|
|
923
|
+
const credentialId = multisig.getMultisigAddress();
|
|
924
|
+
if (this.inner.context.credentialIdToAddress) {
|
|
925
|
+
const serializer = await this.inner.serializer();
|
|
926
|
+
return this.inner.context.credentialIdToAddress(
|
|
927
|
+
credentialId,
|
|
928
|
+
serializer.schema
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
return import_bs58.default.encode(credentialId);
|
|
805
932
|
}
|
|
806
933
|
/**
|
|
807
|
-
*
|
|
934
|
+
* Creates multisig state from a finalized transaction envelope.
|
|
808
935
|
*/
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
throw new Error(
|
|
815
|
-
`Signer public key ${signerPubkeyHex} is not present in multisigPubkeys`
|
|
816
|
-
);
|
|
817
|
-
}
|
|
818
|
-
const jsonBytes = await this.createMultisigJsonBytes(
|
|
819
|
-
unsignedTx,
|
|
820
|
-
multisigAddress
|
|
821
|
-
);
|
|
822
|
-
const signature = await signer.sign(jsonBytes);
|
|
823
|
-
return this.typeBuilder.transaction({
|
|
824
|
-
unsignedTx,
|
|
825
|
-
sender: pubkey,
|
|
826
|
-
signature,
|
|
827
|
-
rollup: this.inner
|
|
936
|
+
multisigFromTransaction(tx) {
|
|
937
|
+
return new import_multisig.Multisig({
|
|
938
|
+
signatures: tx.signatures,
|
|
939
|
+
unusedPubKeys: tx.unused_pub_keys,
|
|
940
|
+
minSigners: tx.min_signers
|
|
828
941
|
});
|
|
829
942
|
}
|
|
943
|
+
normalizeMultisigTransaction(tx) {
|
|
944
|
+
return {
|
|
945
|
+
...tx,
|
|
946
|
+
signatures: tx.signatures.map((signature) => ({
|
|
947
|
+
signature: (0, import_utils4.normalizeHexString)(signature.signature),
|
|
948
|
+
pub_key: (0, import_utils4.normalizeHexString)(signature.pub_key)
|
|
949
|
+
})),
|
|
950
|
+
unused_pub_keys: tx.unused_pub_keys.map(import_utils4.normalizeHexString)
|
|
951
|
+
};
|
|
952
|
+
}
|
|
830
953
|
/**
|
|
831
|
-
*
|
|
954
|
+
* Extracts the V0-shaped unsigned fields from a finalized multisig transaction.
|
|
832
955
|
*/
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
);
|
|
841
|
-
}
|
|
842
|
-
const signedMessageWithPreamble = await this.createSpecCompliantMultisigSignedMessage(
|
|
843
|
-
unsignedTx,
|
|
844
|
-
multisigAddress,
|
|
845
|
-
multisigPubkeys
|
|
846
|
-
);
|
|
847
|
-
const signature = await signer.sign(signedMessageWithPreamble);
|
|
848
|
-
return this.typeBuilder.transaction({
|
|
849
|
-
unsignedTx,
|
|
850
|
-
sender: pubkey,
|
|
851
|
-
signature,
|
|
852
|
-
rollup: this.inner
|
|
853
|
-
});
|
|
956
|
+
unsignedTxFromTransaction(tx) {
|
|
957
|
+
return {
|
|
958
|
+
runtime_call: tx.runtime_call,
|
|
959
|
+
uniqueness: tx.uniqueness,
|
|
960
|
+
details: tx.details,
|
|
961
|
+
address_override: tx.address_override
|
|
962
|
+
};
|
|
854
963
|
}
|
|
855
964
|
/**
|
|
856
|
-
*
|
|
857
|
-
*
|
|
858
|
-
* `authenticator: "standard"` delegates directly to the wrapped standard rollup.
|
|
859
|
-
* `authenticator: "solanaSimple"` signs the V1 JSON payload directly.
|
|
860
|
-
* `authenticator: "solana"` signs the spec-compliant preamble+JSON bytes.
|
|
861
|
-
* Solana multisig authenticators treat `multisigPubkeys` as an unordered set and
|
|
862
|
-
* canonicalize it before signing.
|
|
965
|
+
* Creates the preamble+JSON bytes signed by every signer in a spec-compliant multisig flow.
|
|
863
966
|
*/
|
|
864
|
-
async
|
|
865
|
-
|
|
967
|
+
async createSpecCompliantMultisigSignedMessage(unsignedTx, multisig) {
|
|
968
|
+
const chainHash = await this.inner.chainHash();
|
|
969
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
970
|
+
const jsonBytes = await this.createMultisigJsonBytes(
|
|
971
|
+
unsignedTx,
|
|
972
|
+
await this.multisigIdFromMultisig(multisig)
|
|
973
|
+
);
|
|
974
|
+
const preamble = createSolanaPreamble(
|
|
975
|
+
this.canonicalizeMultisigPubkeys([...multisig.allPubKeys]),
|
|
976
|
+
chainHash,
|
|
977
|
+
jsonBytes.length
|
|
978
|
+
);
|
|
979
|
+
return this.combinePreambleAndMessage(preamble, jsonBytes);
|
|
980
|
+
}
|
|
981
|
+
async multisigSigningBytes(unsignedTx, multisig, authenticator) {
|
|
982
|
+
switch (authenticator) {
|
|
866
983
|
case "standard":
|
|
867
|
-
return this.inner.
|
|
868
|
-
case "solanaSimple":
|
|
869
|
-
|
|
984
|
+
return this.inner.multisigSigningBytes(unsignedTx, multisig);
|
|
985
|
+
case "solanaSimple": {
|
|
986
|
+
assertChainHashFragment(unsignedTx, await this.inner.chainHash());
|
|
987
|
+
return this.createMultisigJsonBytes(
|
|
870
988
|
unsignedTx,
|
|
871
|
-
|
|
872
|
-
params.multisigAddress,
|
|
873
|
-
this.canonicalizeMultisigPubkeys(params.multisigPubkeys)
|
|
989
|
+
await this.multisigIdFromMultisig(multisig)
|
|
874
990
|
);
|
|
991
|
+
}
|
|
875
992
|
case "solana":
|
|
876
|
-
return this.
|
|
993
|
+
return this.createSpecCompliantMultisigSignedMessage(
|
|
877
994
|
unsignedTx,
|
|
878
|
-
|
|
879
|
-
params.multisigAddress,
|
|
880
|
-
this.canonicalizeMultisigPubkeys(params.multisigPubkeys)
|
|
995
|
+
multisig
|
|
881
996
|
);
|
|
882
997
|
}
|
|
998
|
+
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
883
999
|
}
|
|
884
1000
|
/**
|
|
885
|
-
* Builds a spec-compliant multisig envelope from a V1 transaction
|
|
1001
|
+
* Builds a spec-compliant multisig envelope from a V1 transaction.
|
|
886
1002
|
*/
|
|
887
|
-
buildSpecCompliantMultisigEnvelope(tx, signedMessageWithPreamble
|
|
1003
|
+
buildSpecCompliantMultisigEnvelope(tx, signedMessageWithPreamble) {
|
|
1004
|
+
const multisigPubkeys = this.canonicalizeMultisigPubkeys([
|
|
1005
|
+
...tx.signatures.map((signer) => signer.pub_key),
|
|
1006
|
+
...tx.unused_pub_keys
|
|
1007
|
+
]);
|
|
888
1008
|
const multisigPubkeyHexes = multisigPubkeys.map(import_utils4.bytesToHex);
|
|
889
1009
|
const indexByPubkey = /* @__PURE__ */ new Map();
|
|
890
1010
|
multisigPubkeyHexes.forEach((pubkeyHex, index) => {
|
|
@@ -894,37 +1014,42 @@ var SolanaSignableRollup = class {
|
|
|
894
1014
|
const signaturesByIndex = /* @__PURE__ */ new Map();
|
|
895
1015
|
let signerBitfield = 0;
|
|
896
1016
|
for (const signer of tx.signatures) {
|
|
897
|
-
const
|
|
1017
|
+
const normalizedSignerPubkey = (0, import_utils4.normalizeHexString)(signer.pub_key);
|
|
1018
|
+
const signerIndex = indexByPubkey.get(normalizedSignerPubkey);
|
|
898
1019
|
if (signerIndex === void 0) {
|
|
899
1020
|
throw new Error(
|
|
900
|
-
`Signed pubkey ${
|
|
1021
|
+
`Signed pubkey ${normalizedSignerPubkey} is not present in multisigPubkeys`
|
|
901
1022
|
);
|
|
902
1023
|
}
|
|
903
|
-
if (accountedPubkeys.has(
|
|
1024
|
+
if (accountedPubkeys.has(normalizedSignerPubkey)) {
|
|
904
1025
|
throw new Error(
|
|
905
|
-
`Duplicate signed pubkey in multisig transaction: ${
|
|
1026
|
+
`Duplicate signed pubkey in multisig transaction: ${normalizedSignerPubkey}`
|
|
906
1027
|
);
|
|
907
1028
|
}
|
|
908
|
-
accountedPubkeys.add(
|
|
909
|
-
signaturesByIndex.set(
|
|
1029
|
+
accountedPubkeys.add(normalizedSignerPubkey);
|
|
1030
|
+
signaturesByIndex.set(
|
|
1031
|
+
signerIndex,
|
|
1032
|
+
(0, import_utils4.hexToBytes)((0, import_utils4.normalizeHexString)(signer.signature))
|
|
1033
|
+
);
|
|
910
1034
|
signerBitfield = (signerBitfield | 1 << signerIndex) >>> 0;
|
|
911
1035
|
}
|
|
912
1036
|
for (const unusedPubkey of tx.unused_pub_keys) {
|
|
913
|
-
|
|
1037
|
+
const normalizedUnusedPubkey = (0, import_utils4.normalizeHexString)(unusedPubkey);
|
|
1038
|
+
if (!indexByPubkey.has(normalizedUnusedPubkey)) {
|
|
914
1039
|
throw new Error(
|
|
915
|
-
`Unused pubkey ${
|
|
1040
|
+
`Unused pubkey ${normalizedUnusedPubkey} is not present in multisigPubkeys`
|
|
916
1041
|
);
|
|
917
1042
|
}
|
|
918
|
-
if (accountedPubkeys.has(
|
|
1043
|
+
if (accountedPubkeys.has(normalizedUnusedPubkey)) {
|
|
919
1044
|
throw new Error(
|
|
920
|
-
`Duplicate pubkey in multisig transaction payload: ${
|
|
1045
|
+
`Duplicate pubkey in multisig transaction payload: ${normalizedUnusedPubkey}`
|
|
921
1046
|
);
|
|
922
1047
|
}
|
|
923
|
-
accountedPubkeys.add(
|
|
1048
|
+
accountedPubkeys.add(normalizedUnusedPubkey);
|
|
924
1049
|
}
|
|
925
1050
|
if (accountedPubkeys.size !== multisigPubkeys.length) {
|
|
926
1051
|
throw new Error(
|
|
927
|
-
"
|
|
1052
|
+
"Multisig transaction payload must contain every signer exactly once"
|
|
928
1053
|
);
|
|
929
1054
|
}
|
|
930
1055
|
const orderedSignatures = Array.from(signaturesByIndex.entries()).sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, signature]) => signature);
|
|
@@ -936,72 +1061,100 @@ var SolanaSignableRollup = class {
|
|
|
936
1061
|
};
|
|
937
1062
|
}
|
|
938
1063
|
/**
|
|
939
|
-
* Submits a multisig transaction using
|
|
940
|
-
*
|
|
941
|
-
* Accepts the V1 transaction produced by `MultisigTransaction.asTransaction()`.
|
|
942
|
-
* `authenticator: "standard"` delegates directly to the wrapped standard rollup.
|
|
943
|
-
* Solana authenticators rebuild the appropriate Solana multisig envelope and
|
|
944
|
-
* submit it to the Solana offchain endpoint.
|
|
1064
|
+
* Submits a finalized V1 multisig transaction using a Solana authenticator.
|
|
945
1065
|
*/
|
|
946
|
-
async
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
runtime_call: tx.runtime_call,
|
|
950
|
-
uniqueness: tx.uniqueness,
|
|
951
|
-
details: tx.details
|
|
1066
|
+
async submitMultisigTransactionWithAuthenticator(transaction, authenticator, options) {
|
|
1067
|
+
const finalizedTx = {
|
|
1068
|
+
V1: this.normalizeMultisigTransaction(transaction.V1)
|
|
952
1069
|
};
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1070
|
+
const multisig = this.multisigFromTransaction(finalizedTx.V1);
|
|
1071
|
+
if (!multisig.isComplete) {
|
|
1072
|
+
throw new Error("Multisig transaction is incomplete");
|
|
1073
|
+
}
|
|
1074
|
+
const unsignedTx = this.unsignedTxFromTransaction(finalizedTx.V1);
|
|
1075
|
+
switch (authenticator) {
|
|
958
1076
|
case "solanaSimple": {
|
|
959
|
-
this.
|
|
1077
|
+
const chainHash = await this.inner.chainHash();
|
|
1078
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
960
1079
|
const jsonBytes = await this.createMultisigJsonBytes(
|
|
961
1080
|
unsignedTx,
|
|
962
|
-
|
|
1081
|
+
await this.multisigIdFromMultisig(multisig)
|
|
963
1082
|
);
|
|
964
1083
|
const wireBytes = new Uint8Array(1 + jsonBytes.length);
|
|
965
1084
|
wireBytes[0] = MULTISIG_SIMPLE_DISCRIMINATOR;
|
|
966
1085
|
wireBytes.set(jsonBytes, 1);
|
|
967
|
-
const chainHash = await this.inner.chainHash();
|
|
968
1086
|
const serialized = this.serializeSolanaMultisigMessage({
|
|
969
1087
|
wire_bytes: wireBytes,
|
|
970
1088
|
chain_hash: chainHash,
|
|
971
|
-
signatures:
|
|
1089
|
+
signatures: finalizedTx.V1.signatures.map((s) => ({
|
|
972
1090
|
signature: (0, import_utils4.hexToBytes)(s.signature),
|
|
973
1091
|
pub_key: (0, import_utils4.hexToBytes)(s.pub_key)
|
|
974
1092
|
})),
|
|
975
|
-
unused_pub_keys:
|
|
976
|
-
|
|
1093
|
+
unused_pub_keys: finalizedTx.V1.unused_pub_keys.map(
|
|
1094
|
+
(pk) => (0, import_utils4.hexToBytes)(pk)
|
|
1095
|
+
),
|
|
1096
|
+
min_signers: finalizedTx.V1.min_signers
|
|
977
1097
|
});
|
|
978
|
-
return this.submitSerializedMessage(serialized);
|
|
1098
|
+
return this.submitSerializedMessage(serialized, options);
|
|
979
1099
|
}
|
|
980
1100
|
case "solana": {
|
|
981
|
-
const multisigPubkeys = this.canonicalizeMultisigPubkeys(
|
|
982
|
-
params.multisigPubkeys
|
|
983
|
-
);
|
|
984
1101
|
const signedMessageWithPreamble = await this.createSpecCompliantMultisigSignedMessage(
|
|
985
1102
|
unsignedTx,
|
|
986
|
-
|
|
987
|
-
multisigPubkeys
|
|
1103
|
+
multisig
|
|
988
1104
|
);
|
|
989
1105
|
const message = this.buildSpecCompliantMultisigEnvelope(
|
|
990
|
-
|
|
991
|
-
signedMessageWithPreamble
|
|
992
|
-
|
|
1106
|
+
finalizedTx.V1,
|
|
1107
|
+
signedMessageWithPreamble
|
|
1108
|
+
);
|
|
1109
|
+
return this.submitSolanaSpecMultisigMessage(message, options);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Submits a finalized V0 transaction using a Solana authenticator.
|
|
1115
|
+
*/
|
|
1116
|
+
async submitSingleSignatureTransactionWithAuthenticator(transaction, authenticator, options) {
|
|
1117
|
+
const unsignedTx = {
|
|
1118
|
+
runtime_call: transaction.runtime_call,
|
|
1119
|
+
uniqueness: transaction.uniqueness,
|
|
1120
|
+
details: transaction.details,
|
|
1121
|
+
address_override: transaction.address_override
|
|
1122
|
+
};
|
|
1123
|
+
const pubkey = (0, import_utils4.hexToBytes)((0, import_utils4.normalizeHexString)(transaction.pub_key));
|
|
1124
|
+
const signature = (0, import_utils4.hexToBytes)((0, import_utils4.normalizeHexString)(transaction.signature));
|
|
1125
|
+
const chainHash = await this.inner.chainHash();
|
|
1126
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
1127
|
+
switch (authenticator) {
|
|
1128
|
+
case "solanaSimple": {
|
|
1129
|
+
const signedMessage = await this.createSolanaJsonBytes(unsignedTx);
|
|
1130
|
+
const message = {
|
|
1131
|
+
signed_message: signedMessage,
|
|
1132
|
+
chain_hash: chainHash,
|
|
1133
|
+
pubkey,
|
|
1134
|
+
signature
|
|
1135
|
+
};
|
|
1136
|
+
return this.submitSolanaMessage(message, options);
|
|
1137
|
+
}
|
|
1138
|
+
case "solana": {
|
|
1139
|
+
const signedMessage = await this.createSolanaJsonBytes(unsignedTx);
|
|
1140
|
+
const preamble = createSolanaPreamble(
|
|
1141
|
+
[pubkey],
|
|
1142
|
+
chainHash,
|
|
1143
|
+
signedMessage.length
|
|
993
1144
|
);
|
|
994
|
-
|
|
1145
|
+
const message = {
|
|
1146
|
+
signed_message_with_preamble: this.combinePreambleAndMessage(
|
|
1147
|
+
preamble,
|
|
1148
|
+
signedMessage
|
|
1149
|
+
),
|
|
1150
|
+
signature
|
|
1151
|
+
};
|
|
1152
|
+
return this.submitSolanaSpecMessage(message, options);
|
|
995
1153
|
}
|
|
996
1154
|
}
|
|
997
1155
|
}
|
|
998
1156
|
/**
|
|
999
1157
|
* Submits a transaction with the specified authenticator.
|
|
1000
|
-
*
|
|
1001
|
-
* @param transaction - Either a standard transaction or a Solana message
|
|
1002
|
-
* @param authenticator - The authenticator type to use
|
|
1003
|
-
* @param options - Optional request options
|
|
1004
|
-
* @returns The transaction response
|
|
1005
1158
|
*/
|
|
1006
1159
|
async submitTransaction(transaction, authenticator, options) {
|
|
1007
1160
|
switch (authenticator) {
|
|
@@ -1010,17 +1163,34 @@ var SolanaSignableRollup = class {
|
|
|
1010
1163
|
transaction,
|
|
1011
1164
|
options
|
|
1012
1165
|
);
|
|
1013
|
-
case "solanaSimple":
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1166
|
+
case "solanaSimple":
|
|
1167
|
+
if ("V1" in transaction) {
|
|
1168
|
+
return this.submitMultisigTransactionWithAuthenticator(
|
|
1169
|
+
transaction,
|
|
1170
|
+
"solanaSimple",
|
|
1171
|
+
options
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
return this.submitSingleSignatureTransactionWithAuthenticator(
|
|
1175
|
+
transaction.V0,
|
|
1176
|
+
"solanaSimple",
|
|
1177
|
+
options
|
|
1178
|
+
);
|
|
1179
|
+
case "solana":
|
|
1180
|
+
if ("V1" in transaction) {
|
|
1181
|
+
return this.submitMultisigTransactionWithAuthenticator(
|
|
1182
|
+
transaction,
|
|
1183
|
+
"solana",
|
|
1184
|
+
options
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
return this.submitSingleSignatureTransactionWithAuthenticator(
|
|
1188
|
+
transaction.V0,
|
|
1189
|
+
"solana",
|
|
1190
|
+
options
|
|
1191
|
+
);
|
|
1023
1192
|
}
|
|
1193
|
+
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
1024
1194
|
}
|
|
1025
1195
|
async simulate(runtimeMessage, params) {
|
|
1026
1196
|
return this.inner.simulate(runtimeMessage, params);
|
|
@@ -1028,6 +1198,9 @@ var SolanaSignableRollup = class {
|
|
|
1028
1198
|
async dedup(address) {
|
|
1029
1199
|
return this.inner.dedup(address);
|
|
1030
1200
|
}
|
|
1201
|
+
async dedupByCredentialId(credentialId) {
|
|
1202
|
+
return this.inner.dedupByCredentialId(credentialId);
|
|
1203
|
+
}
|
|
1031
1204
|
async serializer() {
|
|
1032
1205
|
return this.inner.serializer();
|
|
1033
1206
|
}
|
|
@@ -1063,7 +1236,7 @@ var SolanaSignableRollup = class {
|
|
|
1063
1236
|
return this.inner.http;
|
|
1064
1237
|
}
|
|
1065
1238
|
/**
|
|
1066
|
-
* Helper method to serialize a
|
|
1239
|
+
* Helper method to serialize a SolanaOffchainSimpleEnvelope using borsh encoding.
|
|
1067
1240
|
*/
|
|
1068
1241
|
serializeSolanaMessage(message) {
|
|
1069
1242
|
if (message.chain_hash.length !== CHAIN_HASH_SIZE) {
|
|
@@ -1097,7 +1270,7 @@ var SolanaSignableRollup = class {
|
|
|
1097
1270
|
return buffer;
|
|
1098
1271
|
}
|
|
1099
1272
|
/**
|
|
1100
|
-
* Helper method to serialize a
|
|
1273
|
+
* Helper method to serialize a SolanaOffchainSpecCompliantEnvelope using borsh encoding.
|
|
1101
1274
|
*/
|
|
1102
1275
|
serializeSolanaSpecMessage(message) {
|
|
1103
1276
|
if (message.signature.length !== SIGNATURE_SIZE) {
|
|
@@ -1117,7 +1290,7 @@ var SolanaSignableRollup = class {
|
|
|
1117
1290
|
return buffer;
|
|
1118
1291
|
}
|
|
1119
1292
|
/**
|
|
1120
|
-
* Serializes a
|
|
1293
|
+
* Serializes a SolanaOffchainSimpleMultisigEnvelope using borsh encoding.
|
|
1121
1294
|
* Layout matches the Rust struct:
|
|
1122
1295
|
* [u32 LE: wire_bytes.len][wire_bytes]
|
|
1123
1296
|
* [32 bytes: chain_hash]
|
|
@@ -1178,7 +1351,7 @@ var SolanaSignableRollup = class {
|
|
|
1178
1351
|
return buffer;
|
|
1179
1352
|
}
|
|
1180
1353
|
/**
|
|
1181
|
-
* Serializes a
|
|
1354
|
+
* Serializes a SolanaOffchainSpecCompliantMultisigEnvelope using borsh encoding.
|
|
1182
1355
|
* Layout matches the Rust struct:
|
|
1183
1356
|
* [u32 LE: signed_message_with_preamble.len][signed_message_with_preamble]
|
|
1184
1357
|
* [u32 LE: signatures.len]
|
|
@@ -1232,6 +1405,7 @@ var SovereignClient3 = __toESM(require("@sovereign-sdk/client"));
|
|
|
1232
1405
|
StandardRollup,
|
|
1233
1406
|
VersionMismatchError,
|
|
1234
1407
|
addressFromPublicKey,
|
|
1408
|
+
chainHashFragment,
|
|
1235
1409
|
createSolanaSignableRollup,
|
|
1236
1410
|
createStandardRollup,
|
|
1237
1411
|
standardTypeBuilder
|