@sovereign-sdk/web3 0.14.1 → 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 +117 -70
- package/dist/index.d.ts +117 -70
- package/dist/index.js +405 -231
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +409 -232
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -6
package/dist/index.mjs
CHANGED
|
@@ -124,10 +124,26 @@ var Rollup = class {
|
|
|
124
124
|
* TODO: How to request a specific uniqueness strategy explicitly
|
|
125
125
|
*/
|
|
126
126
|
async dedup(publicKey) {
|
|
127
|
-
|
|
127
|
+
return this.dedupByCredentialId(bytesToHex(publicKey));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Retrieve dedup information about the provided credential ID.
|
|
131
|
+
*/
|
|
132
|
+
async dedupByCredentialId(credentialId) {
|
|
128
133
|
const response = await this.rollup.addresses.dedup(credentialId);
|
|
129
134
|
return response;
|
|
130
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Builds an unsigned transaction for the provided runtime call.
|
|
138
|
+
*/
|
|
139
|
+
async buildUnsignedTransaction(runtimeCall, params) {
|
|
140
|
+
const context = {
|
|
141
|
+
runtimeCall,
|
|
142
|
+
rollup: this,
|
|
143
|
+
overrides: params?.overrides ?? {}
|
|
144
|
+
};
|
|
145
|
+
return this._typeBuilder.unsignedTransaction(context);
|
|
146
|
+
}
|
|
131
147
|
/**
|
|
132
148
|
* Submits a transaction to the rollup.
|
|
133
149
|
*
|
|
@@ -185,12 +201,9 @@ var Rollup = class {
|
|
|
185
201
|
* @param {SovereignClient.RequestOptions} options - The options for the request.
|
|
186
202
|
*/
|
|
187
203
|
async call(runtimeCall, { signer, overrides }, options) {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
overrides: overrides ?? {}
|
|
192
|
-
};
|
|
193
|
-
const unsignedTx = await this._typeBuilder.unsignedTransaction(context);
|
|
204
|
+
const unsignedTx = await this.buildUnsignedTransaction(runtimeCall, {
|
|
205
|
+
overrides
|
|
206
|
+
});
|
|
194
207
|
return this.signAndSubmitTransaction(
|
|
195
208
|
unsignedTx,
|
|
196
209
|
{
|
|
@@ -211,18 +224,15 @@ var Rollup = class {
|
|
|
211
224
|
* @returns A promise that resolves to the signed transaction.
|
|
212
225
|
*/
|
|
213
226
|
async prepareCall(runtimeCall, { signer, overrides }) {
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
overrides: overrides ?? {}
|
|
218
|
-
};
|
|
219
|
-
const unsignedTx = await this._typeBuilder.unsignedTransaction(context);
|
|
227
|
+
const unsignedTx = await this.buildUnsignedTransaction(runtimeCall, {
|
|
228
|
+
overrides
|
|
229
|
+
});
|
|
220
230
|
return this.signTransaction(unsignedTx, signer);
|
|
221
231
|
}
|
|
222
232
|
/**
|
|
223
233
|
* Signs an unsigned transaction using the provided signer.
|
|
224
|
-
* Creates a signature
|
|
225
|
-
*
|
|
234
|
+
* Creates a signature over the serialized transaction signing payload, then constructs a fully
|
|
235
|
+
* signed transaction.
|
|
226
236
|
*
|
|
227
237
|
* @param unsignedTx - The unsigned transaction to sign.
|
|
228
238
|
* @param signer - The signer to use for signing the transaction.
|
|
@@ -230,11 +240,15 @@ var Rollup = class {
|
|
|
230
240
|
*/
|
|
231
241
|
async signTransaction(unsignedTx, signer) {
|
|
232
242
|
const serializer = await this.serializer();
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
243
|
+
const transactionSigningPayload = await this._typeBuilder.transactionSigningPayload({
|
|
244
|
+
unsignedTx,
|
|
245
|
+
chainHash: await this.chainHash(),
|
|
246
|
+
rollup: this
|
|
247
|
+
});
|
|
248
|
+
const signingBytes = serializer.serializeSigningPayload(
|
|
249
|
+
transactionSigningPayload
|
|
237
250
|
);
|
|
251
|
+
const signature = await signer.sign(signingBytes);
|
|
238
252
|
const publicKey = await signer.publicKey();
|
|
239
253
|
const context = {
|
|
240
254
|
unsignedTx,
|
|
@@ -322,10 +336,12 @@ var Rollup = class {
|
|
|
322
336
|
}
|
|
323
337
|
};
|
|
324
338
|
function isVersionMismatchError(e) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
339
|
+
const details = e.error?.details;
|
|
340
|
+
if (details?.code === "invalid_chain_hash_fragment") {
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
const error = details?.error;
|
|
344
|
+
if (typeof error === "string" && error.includes("Signature verification failed")) {
|
|
329
345
|
return true;
|
|
330
346
|
}
|
|
331
347
|
return false;
|
|
@@ -335,6 +351,36 @@ function isVersionMismatchError(e) {
|
|
|
335
351
|
import SovereignClient2 from "@sovereign-sdk/client";
|
|
336
352
|
import { JsSerializer } from "@sovereign-sdk/serializers";
|
|
337
353
|
import { bytesToHex as bytesToHex2 } from "@sovereign-sdk/utils";
|
|
354
|
+
|
|
355
|
+
// src/rollup/chain-hash.ts
|
|
356
|
+
function chainHashFragment(chainHash) {
|
|
357
|
+
if (chainHash.length < 8) {
|
|
358
|
+
throw new Error("chain hash must contain at least 8 bytes");
|
|
359
|
+
}
|
|
360
|
+
return new DataView(
|
|
361
|
+
chainHash.buffer,
|
|
362
|
+
chainHash.byteOffset,
|
|
363
|
+
chainHash.byteLength
|
|
364
|
+
).getBigUint64(0, true).toString();
|
|
365
|
+
}
|
|
366
|
+
function refreshChainHashFragment(unsignedTx, chainHash) {
|
|
367
|
+
unsignedTx.details = {
|
|
368
|
+
...unsignedTx.details,
|
|
369
|
+
chain_hash_fragment: chainHashFragment(chainHash)
|
|
370
|
+
};
|
|
371
|
+
return unsignedTx;
|
|
372
|
+
}
|
|
373
|
+
function assertChainHashFragment(unsignedTx, chainHash) {
|
|
374
|
+
const expectedFragment = chainHashFragment(chainHash);
|
|
375
|
+
const actualFragment = unsignedTx.details.chain_hash_fragment;
|
|
376
|
+
if (actualFragment !== expectedFragment) {
|
|
377
|
+
throw new Error(
|
|
378
|
+
`Cannot sign transaction: chain_hash_fragment ${actualFragment} does not match the current chain hash fragment ${expectedFragment}`
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/rollup/standard-rollup.ts
|
|
338
384
|
var useOrFetchUniqueness = async ({
|
|
339
385
|
overrides
|
|
340
386
|
}) => {
|
|
@@ -347,7 +393,7 @@ function standardTypeBuilder() {
|
|
|
347
393
|
return {
|
|
348
394
|
async unsignedTransaction(context) {
|
|
349
395
|
const { rollup, runtimeCall } = context;
|
|
350
|
-
const
|
|
396
|
+
const overrides = context.overrides;
|
|
351
397
|
const uniqueness = await useOrFetchUniqueness(context);
|
|
352
398
|
const details = {
|
|
353
399
|
...rollup.context.defaultTxDetails,
|
|
@@ -356,7 +402,8 @@ function standardTypeBuilder() {
|
|
|
356
402
|
return {
|
|
357
403
|
runtime_call: runtimeCall,
|
|
358
404
|
uniqueness,
|
|
359
|
-
details
|
|
405
|
+
details,
|
|
406
|
+
address_override: overrides.address_override ?? null
|
|
360
407
|
};
|
|
361
408
|
},
|
|
362
409
|
async transaction({
|
|
@@ -371,10 +418,67 @@ function standardTypeBuilder() {
|
|
|
371
418
|
...unsignedTx
|
|
372
419
|
}
|
|
373
420
|
};
|
|
421
|
+
},
|
|
422
|
+
async transactionSigningPayload({
|
|
423
|
+
unsignedTx,
|
|
424
|
+
chainHash
|
|
425
|
+
}) {
|
|
426
|
+
const normalizedUnsignedTx = refreshChainHashFragment(
|
|
427
|
+
unsignedTx,
|
|
428
|
+
chainHash
|
|
429
|
+
);
|
|
430
|
+
return {
|
|
431
|
+
V0: {
|
|
432
|
+
...normalizedUnsignedTx,
|
|
433
|
+
chain_hash: Array.from(chainHash)
|
|
434
|
+
}
|
|
435
|
+
};
|
|
374
436
|
}
|
|
375
437
|
};
|
|
376
438
|
}
|
|
377
439
|
var StandardRollup = class extends Rollup {
|
|
440
|
+
updateDefaultChainHashFragment(chainHash) {
|
|
441
|
+
this.context.defaultTxDetails.chain_hash_fragment = chainHashFragment(chainHash);
|
|
442
|
+
}
|
|
443
|
+
async credentialAddressFromId(credentialId) {
|
|
444
|
+
if (this.context.credentialIdToAddress) {
|
|
445
|
+
const serializer = await this.serializer();
|
|
446
|
+
return this.context.credentialIdToAddress(
|
|
447
|
+
credentialId,
|
|
448
|
+
serializer.schema
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
return addressFromPublicKey(credentialId, "sov");
|
|
452
|
+
}
|
|
453
|
+
async submitTransaction(transaction, options) {
|
|
454
|
+
try {
|
|
455
|
+
return await super.submitTransaction(transaction, options);
|
|
456
|
+
} catch (error) {
|
|
457
|
+
if (error instanceof VersionMismatchError) {
|
|
458
|
+
this.updateDefaultChainHashFragment(await super.chainHash());
|
|
459
|
+
}
|
|
460
|
+
throw error;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
async hydrate() {
|
|
464
|
+
await super.hydrate();
|
|
465
|
+
this.updateDefaultChainHashFragment(await super.chainHash());
|
|
466
|
+
}
|
|
467
|
+
async multisigSigningBytes(unsignedTx, multisig) {
|
|
468
|
+
const serializer = await this.serializer();
|
|
469
|
+
const chainHash = await this.chainHash();
|
|
470
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
471
|
+
const signingPayload = {
|
|
472
|
+
V1: {
|
|
473
|
+
...unsignedTx,
|
|
474
|
+
chain_hash: Array.from(chainHash),
|
|
475
|
+
credential_address: await this.credentialAddressFromId(
|
|
476
|
+
multisig.getMultisigAddress()
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
return serializer.serializeSigningPayload(signingPayload);
|
|
481
|
+
}
|
|
378
482
|
/**
|
|
379
483
|
* Simulates a runtime call transaction.
|
|
380
484
|
*
|
|
@@ -382,11 +486,15 @@ var StandardRollup = class extends Rollup {
|
|
|
382
486
|
*
|
|
383
487
|
* @param runtimeMessage - The runtime message to call.
|
|
384
488
|
*/
|
|
385
|
-
async simulate(runtimeMessage, { signer }) {
|
|
489
|
+
async simulate(runtimeMessage, { signer, ...params }) {
|
|
386
490
|
const publicKey = await signer.publicKey();
|
|
387
491
|
const sender = bytesToHex2(publicKey);
|
|
388
492
|
const call = runtimeMessage;
|
|
389
|
-
return this.rollup.simulate({
|
|
493
|
+
return this.rollup.simulate({
|
|
494
|
+
...params,
|
|
495
|
+
sender,
|
|
496
|
+
call
|
|
497
|
+
});
|
|
390
498
|
}
|
|
391
499
|
};
|
|
392
500
|
var DEFAULT_TX_DETAILS = {
|
|
@@ -394,26 +502,24 @@ var DEFAULT_TX_DETAILS = {
|
|
|
394
502
|
max_fee: "100000000",
|
|
395
503
|
gas_limit: null
|
|
396
504
|
};
|
|
397
|
-
|
|
505
|
+
function buildContext(context, credentialIdToAddress) {
|
|
398
506
|
const defaultTxDetails = {
|
|
399
507
|
...DEFAULT_TX_DETAILS,
|
|
400
508
|
...context?.defaultTxDetails
|
|
401
509
|
};
|
|
402
|
-
if (!defaultTxDetails.chain_id) {
|
|
403
|
-
const { chain_id } = await client.rollup.constants();
|
|
404
|
-
defaultTxDetails.chain_id = chain_id;
|
|
405
|
-
}
|
|
406
510
|
return {
|
|
407
|
-
|
|
511
|
+
...context,
|
|
512
|
+
defaultTxDetails,
|
|
513
|
+
credentialIdToAddress: credentialIdToAddress ?? context?.credentialIdToAddress
|
|
408
514
|
};
|
|
409
515
|
}
|
|
410
516
|
async function createStandardRollup(rollupConfig, typeBuilderOverrides) {
|
|
411
517
|
const config = rollupConfig ?? {};
|
|
412
518
|
const client = config.client ?? new SovereignClient2({ baseURL: config.url });
|
|
413
519
|
const getSerializer = config.getSerializer ?? ((schema) => new JsSerializer(schema));
|
|
414
|
-
const context =
|
|
520
|
+
const context = buildContext(config.context, config.credentialIdToAddress);
|
|
415
521
|
const txSubmissionEndpoint = config.txSubmissionEndpoint ?? "/sequencer/txs";
|
|
416
|
-
|
|
522
|
+
const rollup = new StandardRollup(
|
|
417
523
|
{
|
|
418
524
|
...config,
|
|
419
525
|
client,
|
|
@@ -426,11 +532,20 @@ async function createStandardRollup(rollupConfig, typeBuilderOverrides) {
|
|
|
426
532
|
...typeBuilderOverrides
|
|
427
533
|
}
|
|
428
534
|
);
|
|
535
|
+
if (!context.defaultTxDetails.chain_hash_fragment) {
|
|
536
|
+
await rollup.hydrate();
|
|
537
|
+
}
|
|
538
|
+
return rollup;
|
|
429
539
|
}
|
|
430
540
|
|
|
431
541
|
// src/rollup/solana-signable-rollup.ts
|
|
542
|
+
import { MAX_SIGNERS, Multisig } from "@sovereign-sdk/multisig";
|
|
432
543
|
import { isLedgerSolanaSigner } from "@sovereign-sdk/signers";
|
|
433
|
-
import {
|
|
544
|
+
import {
|
|
545
|
+
bytesToHex as bytesToHex3,
|
|
546
|
+
hexToBytes as hexToBytes2,
|
|
547
|
+
normalizeHexString
|
|
548
|
+
} from "@sovereign-sdk/utils";
|
|
434
549
|
import bs58 from "bs58";
|
|
435
550
|
import { Base64 as Base642 } from "js-base64";
|
|
436
551
|
var MULTISIG_SIMPLE_DISCRIMINATOR = 128;
|
|
@@ -439,7 +554,6 @@ var CHAIN_HASH_SIZE = 32;
|
|
|
439
554
|
var PUBKEY_SIZE = 32;
|
|
440
555
|
var SIGNATURE_SIZE = 64;
|
|
441
556
|
var MULTISIG_PREAMBLE_FIXED_LENGTH = 53;
|
|
442
|
-
var MAX_MULTISIG_SIGNERS = 21;
|
|
443
557
|
var SIGNING_DOMAIN = new Uint8Array([
|
|
444
558
|
255,
|
|
445
559
|
...new TextEncoder().encode("solana offchain")
|
|
@@ -456,9 +570,9 @@ function compareByteArrays(left, right) {
|
|
|
456
570
|
return left.length - right.length;
|
|
457
571
|
}
|
|
458
572
|
function createSolanaPreamble(pubkeys, chainHash, messageLength) {
|
|
459
|
-
if (pubkeys.length < 1 || pubkeys.length >
|
|
573
|
+
if (pubkeys.length < 1 || pubkeys.length > MAX_SIGNERS) {
|
|
460
574
|
throw new Error(
|
|
461
|
-
`Invalid signer count: expected 1-${
|
|
575
|
+
`Invalid signer count: expected 1-${MAX_SIGNERS} signers, got ${pubkeys.length}`
|
|
462
576
|
);
|
|
463
577
|
}
|
|
464
578
|
const preamble = new Uint8Array(
|
|
@@ -504,45 +618,37 @@ var SolanaSignableRollup = class {
|
|
|
504
618
|
/**
|
|
505
619
|
* Submits serialized data to the Solana endpoint.
|
|
506
620
|
*/
|
|
507
|
-
async submitSerializedMessage(serializedMessage) {
|
|
621
|
+
async submitSerializedMessage(serializedMessage, options) {
|
|
622
|
+
const { body: _, query: __, path, ...requestOptions } = options || {};
|
|
508
623
|
return await this.inner.http.post(
|
|
509
|
-
this.solanaEndpoint,
|
|
624
|
+
path || this.solanaEndpoint,
|
|
510
625
|
{
|
|
511
626
|
// Match AcceptTx shape used by standard sequencer endpoints.
|
|
512
|
-
body: { body: Base642.fromUint8Array(serializedMessage) }
|
|
627
|
+
body: { body: Base642.fromUint8Array(serializedMessage) },
|
|
628
|
+
...requestOptions
|
|
513
629
|
}
|
|
514
630
|
);
|
|
515
631
|
}
|
|
516
632
|
/**
|
|
517
633
|
* Submits a Solana offchain message to the rollup.
|
|
518
634
|
*/
|
|
519
|
-
async submitSolanaMessage(solanaMessage) {
|
|
635
|
+
async submitSolanaMessage(solanaMessage, options) {
|
|
520
636
|
const serializedMessage = this.serializeSolanaMessage(solanaMessage);
|
|
521
|
-
return this.submitSerializedMessage(serializedMessage);
|
|
637
|
+
return this.submitSerializedMessage(serializedMessage, options);
|
|
522
638
|
}
|
|
523
639
|
/**
|
|
524
640
|
* Submits a Solana spec-compliant message to the rollup.
|
|
525
641
|
*/
|
|
526
|
-
async submitSolanaSpecMessage(solanaMessage) {
|
|
642
|
+
async submitSolanaSpecMessage(solanaMessage, options) {
|
|
527
643
|
const serializedMessage = this.serializeSolanaSpecMessage(solanaMessage);
|
|
528
|
-
return this.submitSerializedMessage(serializedMessage);
|
|
644
|
+
return this.submitSerializedMessage(serializedMessage, options);
|
|
529
645
|
}
|
|
530
646
|
/**
|
|
531
647
|
* Submits a Solana spec-compliant multisig message to the rollup.
|
|
532
648
|
*/
|
|
533
|
-
async submitSolanaSpecMultisigMessage(solanaMessage) {
|
|
649
|
+
async submitSolanaSpecMultisigMessage(solanaMessage, options) {
|
|
534
650
|
const serializedMessage = this.serializeSolanaSpecMultisigMessage(solanaMessage);
|
|
535
|
-
return this.submitSerializedMessage(serializedMessage);
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Helper to build an unsigned transaction using the standard type builder.
|
|
539
|
-
*/
|
|
540
|
-
async buildUnsignedTransaction(runtimeCall, overrides) {
|
|
541
|
-
return this.typeBuilder.unsignedTransaction({
|
|
542
|
-
runtimeCall,
|
|
543
|
-
overrides: overrides ?? {},
|
|
544
|
-
rollup: this.inner
|
|
545
|
-
});
|
|
651
|
+
return this.submitSerializedMessage(serializedMessage, options);
|
|
546
652
|
}
|
|
547
653
|
/**
|
|
548
654
|
* Helper to build a transaction result object.
|
|
@@ -570,18 +676,15 @@ var SolanaSignableRollup = class {
|
|
|
570
676
|
* The canonical order is lexicographic by raw pubkey bytes.
|
|
571
677
|
*/
|
|
572
678
|
canonicalizeMultisigPubkeys(multisigPubkeys) {
|
|
573
|
-
if (
|
|
679
|
+
if (multisigPubkeys.length < 1 || multisigPubkeys.length > MAX_SIGNERS) {
|
|
574
680
|
throw new Error(
|
|
575
|
-
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
if (multisigPubkeys.length < 2 || multisigPubkeys.length > MAX_MULTISIG_SIGNERS) {
|
|
579
|
-
throw new Error(
|
|
580
|
-
`Invalid multisig signer count: expected 2-${MAX_MULTISIG_SIGNERS} signers, got ${multisigPubkeys.length}`
|
|
681
|
+
`Invalid multisig signer count: expected 1-${MAX_SIGNERS} signers, got ${multisigPubkeys.length}`
|
|
581
682
|
);
|
|
582
683
|
}
|
|
583
684
|
const seenPubkeys = /* @__PURE__ */ new Set();
|
|
584
|
-
|
|
685
|
+
const normalizedPubkeys = multisigPubkeys.map(normalizeHexString);
|
|
686
|
+
const pubkeyBytes = normalizedPubkeys.map((pubkey) => hexToBytes2(pubkey));
|
|
687
|
+
for (const pubkey of pubkeyBytes) {
|
|
585
688
|
if (pubkey.length !== PUBKEY_SIZE) {
|
|
586
689
|
throw new Error(
|
|
587
690
|
`Invalid public key length: expected ${PUBKEY_SIZE} bytes, got ${pubkey.length}`
|
|
@@ -593,31 +696,36 @@ var SolanaSignableRollup = class {
|
|
|
593
696
|
}
|
|
594
697
|
seenPubkeys.add(pubkeyHex);
|
|
595
698
|
}
|
|
596
|
-
return
|
|
699
|
+
return pubkeyBytes.sort(compareByteArrays);
|
|
597
700
|
}
|
|
598
701
|
/**
|
|
599
|
-
* Helper to create and serialize a
|
|
702
|
+
* Helper to create and serialize a SolanaOffchainSigningPayloadV0 to JSON bytes.
|
|
600
703
|
*/
|
|
601
704
|
async createSolanaJsonBytes(unsignedTx) {
|
|
602
705
|
const serializer = await this.inner.serializer();
|
|
603
706
|
const schema = serializer.schema;
|
|
604
707
|
const chainName = schema.chain_data.chain_name || "";
|
|
605
|
-
const
|
|
708
|
+
const solanaSigningPayload = {
|
|
606
709
|
runtime_call: unsignedTx.runtime_call,
|
|
607
710
|
uniqueness: unsignedTx.uniqueness,
|
|
608
711
|
details: unsignedTx.details,
|
|
609
|
-
chain_name: chainName
|
|
712
|
+
chain_name: chainName,
|
|
713
|
+
...unsignedTx.address_override !== null && unsignedTx.address_override !== void 0 && {
|
|
714
|
+
address_override: unsignedTx.address_override
|
|
715
|
+
},
|
|
716
|
+
version: 0
|
|
610
717
|
};
|
|
611
|
-
return new TextEncoder().encode(JSON.stringify(
|
|
718
|
+
return new TextEncoder().encode(JSON.stringify(solanaSigningPayload));
|
|
612
719
|
}
|
|
613
720
|
/**
|
|
614
721
|
* Signs an unsigned transaction using Solana offchain simple signing and submits it.
|
|
615
722
|
* Returns the transaction result in the same format as standard rollup.
|
|
616
723
|
*/
|
|
617
|
-
async signWithSolanaSimpleAndSubmit(unsignedTx, signer) {
|
|
724
|
+
async signWithSolanaSimpleAndSubmit(unsignedTx, signer, options) {
|
|
725
|
+
const chainHash = await this.inner.chainHash();
|
|
726
|
+
refreshChainHashFragment(unsignedTx, chainHash);
|
|
618
727
|
const jsonBytes = await this.createSolanaJsonBytes(unsignedTx);
|
|
619
728
|
const pubkey = await signer.publicKey();
|
|
620
|
-
const chainHash = await this.inner.chainHash();
|
|
621
729
|
const signature = await signer.sign(jsonBytes);
|
|
622
730
|
const solanaMessage = {
|
|
623
731
|
signed_message: jsonBytes,
|
|
@@ -625,17 +733,18 @@ var SolanaSignableRollup = class {
|
|
|
625
733
|
pubkey,
|
|
626
734
|
signature
|
|
627
735
|
};
|
|
628
|
-
const response = await this.submitSolanaMessage(solanaMessage);
|
|
736
|
+
const response = await this.submitSolanaMessage(solanaMessage, options);
|
|
629
737
|
return this.buildTransactionResult(response, unsignedTx, pubkey, signature);
|
|
630
738
|
}
|
|
631
739
|
/**
|
|
632
740
|
* Signs an unsigned transaction using Solana spec-compliant signing and submits it.
|
|
633
741
|
* Returns the transaction result in the same format as standard rollup.
|
|
634
742
|
*/
|
|
635
|
-
async signWithSolanaSpecAndSubmit(unsignedTx, signer) {
|
|
743
|
+
async signWithSolanaSpecAndSubmit(unsignedTx, signer, options) {
|
|
744
|
+
const chainHash = await this.inner.chainHash();
|
|
745
|
+
refreshChainHashFragment(unsignedTx, chainHash);
|
|
636
746
|
const jsonBytes = await this.createSolanaJsonBytes(unsignedTx);
|
|
637
747
|
const pubkey = await signer.publicKey();
|
|
638
|
-
const chainHash = await this.inner.chainHash();
|
|
639
748
|
const preamble = createSolanaPreamble(
|
|
640
749
|
[pubkey],
|
|
641
750
|
chainHash,
|
|
@@ -650,7 +759,7 @@ var SolanaSignableRollup = class {
|
|
|
650
759
|
signed_message_with_preamble: signedMessageWithPreamble,
|
|
651
760
|
signature
|
|
652
761
|
};
|
|
653
|
-
const response = await this.submitSolanaSpecMessage(solanaMessage);
|
|
762
|
+
const response = await this.submitSolanaSpecMessage(solanaMessage, options);
|
|
654
763
|
return this.buildTransactionResult(response, unsignedTx, pubkey, signature);
|
|
655
764
|
}
|
|
656
765
|
/**
|
|
@@ -674,18 +783,30 @@ var SolanaSignableRollup = class {
|
|
|
674
783
|
options
|
|
675
784
|
);
|
|
676
785
|
case "solanaSimple": {
|
|
677
|
-
const unsignedTx = await this.buildUnsignedTransaction(
|
|
786
|
+
const unsignedTx = await this.inner.buildUnsignedTransaction(
|
|
678
787
|
runtimeCall,
|
|
679
|
-
|
|
788
|
+
{
|
|
789
|
+
overrides: params.overrides
|
|
790
|
+
}
|
|
791
|
+
);
|
|
792
|
+
return this.signWithSolanaSimpleAndSubmit(
|
|
793
|
+
unsignedTx,
|
|
794
|
+
params.signer,
|
|
795
|
+
options
|
|
680
796
|
);
|
|
681
|
-
return this.signWithSolanaSimpleAndSubmit(unsignedTx, params.signer);
|
|
682
797
|
}
|
|
683
798
|
case "solana": {
|
|
684
|
-
const unsignedTx = await this.buildUnsignedTransaction(
|
|
799
|
+
const unsignedTx = await this.inner.buildUnsignedTransaction(
|
|
685
800
|
runtimeCall,
|
|
686
|
-
|
|
801
|
+
{
|
|
802
|
+
overrides: params.overrides
|
|
803
|
+
}
|
|
804
|
+
);
|
|
805
|
+
return this.signWithSolanaSpecAndSubmit(
|
|
806
|
+
unsignedTx,
|
|
807
|
+
params.signer,
|
|
808
|
+
options
|
|
687
809
|
);
|
|
688
|
-
return this.signWithSolanaSpecAndSubmit(unsignedTx, params.signer);
|
|
689
810
|
}
|
|
690
811
|
default:
|
|
691
812
|
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
@@ -711,132 +832,134 @@ var SolanaSignableRollup = class {
|
|
|
711
832
|
options
|
|
712
833
|
);
|
|
713
834
|
case "solanaSimple":
|
|
714
|
-
return this.signWithSolanaSimpleAndSubmit(
|
|
835
|
+
return this.signWithSolanaSimpleAndSubmit(
|
|
836
|
+
unsignedTx,
|
|
837
|
+
params.signer,
|
|
838
|
+
options
|
|
839
|
+
);
|
|
715
840
|
case "solana":
|
|
716
|
-
return this.signWithSolanaSpecAndSubmit(
|
|
841
|
+
return this.signWithSolanaSpecAndSubmit(
|
|
842
|
+
unsignedTx,
|
|
843
|
+
params.signer,
|
|
844
|
+
options
|
|
845
|
+
);
|
|
717
846
|
default:
|
|
718
847
|
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
719
848
|
}
|
|
720
849
|
}
|
|
850
|
+
async buildUnsignedTransaction(runtimeCall, params) {
|
|
851
|
+
return this.inner.buildUnsignedTransaction(runtimeCall, params);
|
|
852
|
+
}
|
|
721
853
|
/**
|
|
722
854
|
* Creates V1 JSON bytes for a multisig transaction, including multisig_id and version.
|
|
723
855
|
* The resulting JSON is what each signer signs directly (no discriminator prefix).
|
|
724
856
|
*/
|
|
725
|
-
async createMultisigJsonBytes(unsignedTx,
|
|
857
|
+
async createMultisigJsonBytes(unsignedTx, multisigId) {
|
|
726
858
|
const serializer = await this.inner.serializer();
|
|
727
859
|
const schema = serializer.schema;
|
|
728
860
|
const chainName = schema.chain_data.chain_name || "";
|
|
729
|
-
const
|
|
861
|
+
const solanaSigningPayload = {
|
|
730
862
|
runtime_call: unsignedTx.runtime_call,
|
|
731
863
|
uniqueness: unsignedTx.uniqueness,
|
|
732
864
|
details: unsignedTx.details,
|
|
733
865
|
chain_name: chainName,
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
866
|
+
multisig_id: multisigId,
|
|
867
|
+
...unsignedTx.address_override !== null && unsignedTx.address_override !== void 0 && {
|
|
868
|
+
address_override: unsignedTx.address_override
|
|
869
|
+
},
|
|
738
870
|
version: 1
|
|
739
871
|
};
|
|
740
|
-
return new TextEncoder().encode(JSON.stringify(
|
|
872
|
+
return new TextEncoder().encode(JSON.stringify(solanaSigningPayload));
|
|
741
873
|
}
|
|
742
874
|
/**
|
|
743
|
-
*
|
|
875
|
+
* Formats the multisig credential in the rollup's configured address format.
|
|
744
876
|
*/
|
|
745
|
-
async
|
|
746
|
-
const
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
);
|
|
756
|
-
return this.combinePreambleAndMessage(preamble, jsonBytes);
|
|
877
|
+
async multisigIdFromMultisig(multisig) {
|
|
878
|
+
const credentialId = multisig.getMultisigAddress();
|
|
879
|
+
if (this.inner.context.credentialIdToAddress) {
|
|
880
|
+
const serializer = await this.inner.serializer();
|
|
881
|
+
return this.inner.context.credentialIdToAddress(
|
|
882
|
+
credentialId,
|
|
883
|
+
serializer.schema
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
return bs58.encode(credentialId);
|
|
757
887
|
}
|
|
758
888
|
/**
|
|
759
|
-
*
|
|
889
|
+
* Creates multisig state from a finalized transaction envelope.
|
|
760
890
|
*/
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
throw new Error(
|
|
767
|
-
`Signer public key ${signerPubkeyHex} is not present in multisigPubkeys`
|
|
768
|
-
);
|
|
769
|
-
}
|
|
770
|
-
const jsonBytes = await this.createMultisigJsonBytes(
|
|
771
|
-
unsignedTx,
|
|
772
|
-
multisigAddress
|
|
773
|
-
);
|
|
774
|
-
const signature = await signer.sign(jsonBytes);
|
|
775
|
-
return this.typeBuilder.transaction({
|
|
776
|
-
unsignedTx,
|
|
777
|
-
sender: pubkey,
|
|
778
|
-
signature,
|
|
779
|
-
rollup: this.inner
|
|
891
|
+
multisigFromTransaction(tx) {
|
|
892
|
+
return new Multisig({
|
|
893
|
+
signatures: tx.signatures,
|
|
894
|
+
unusedPubKeys: tx.unused_pub_keys,
|
|
895
|
+
minSigners: tx.min_signers
|
|
780
896
|
});
|
|
781
897
|
}
|
|
898
|
+
normalizeMultisigTransaction(tx) {
|
|
899
|
+
return {
|
|
900
|
+
...tx,
|
|
901
|
+
signatures: tx.signatures.map((signature) => ({
|
|
902
|
+
signature: normalizeHexString(signature.signature),
|
|
903
|
+
pub_key: normalizeHexString(signature.pub_key)
|
|
904
|
+
})),
|
|
905
|
+
unused_pub_keys: tx.unused_pub_keys.map(normalizeHexString)
|
|
906
|
+
};
|
|
907
|
+
}
|
|
782
908
|
/**
|
|
783
|
-
*
|
|
909
|
+
* Extracts the V0-shaped unsigned fields from a finalized multisig transaction.
|
|
784
910
|
*/
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
);
|
|
793
|
-
}
|
|
794
|
-
const signedMessageWithPreamble = await this.createSpecCompliantMultisigSignedMessage(
|
|
795
|
-
unsignedTx,
|
|
796
|
-
multisigAddress,
|
|
797
|
-
multisigPubkeys
|
|
798
|
-
);
|
|
799
|
-
const signature = await signer.sign(signedMessageWithPreamble);
|
|
800
|
-
return this.typeBuilder.transaction({
|
|
801
|
-
unsignedTx,
|
|
802
|
-
sender: pubkey,
|
|
803
|
-
signature,
|
|
804
|
-
rollup: this.inner
|
|
805
|
-
});
|
|
911
|
+
unsignedTxFromTransaction(tx) {
|
|
912
|
+
return {
|
|
913
|
+
runtime_call: tx.runtime_call,
|
|
914
|
+
uniqueness: tx.uniqueness,
|
|
915
|
+
details: tx.details,
|
|
916
|
+
address_override: tx.address_override
|
|
917
|
+
};
|
|
806
918
|
}
|
|
807
919
|
/**
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
* `authenticator: "standard"` delegates directly to the wrapped standard rollup.
|
|
811
|
-
* `authenticator: "solanaSimple"` signs the V1 JSON payload directly.
|
|
812
|
-
* `authenticator: "solana"` signs the spec-compliant preamble+JSON bytes.
|
|
813
|
-
* Solana multisig authenticators treat `multisigPubkeys` as an unordered set and
|
|
814
|
-
* canonicalize it before signing.
|
|
920
|
+
* Creates the preamble+JSON bytes signed by every signer in a spec-compliant multisig flow.
|
|
815
921
|
*/
|
|
816
|
-
async
|
|
817
|
-
|
|
922
|
+
async createSpecCompliantMultisigSignedMessage(unsignedTx, multisig) {
|
|
923
|
+
const chainHash = await this.inner.chainHash();
|
|
924
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
925
|
+
const jsonBytes = await this.createMultisigJsonBytes(
|
|
926
|
+
unsignedTx,
|
|
927
|
+
await this.multisigIdFromMultisig(multisig)
|
|
928
|
+
);
|
|
929
|
+
const preamble = createSolanaPreamble(
|
|
930
|
+
this.canonicalizeMultisigPubkeys([...multisig.allPubKeys]),
|
|
931
|
+
chainHash,
|
|
932
|
+
jsonBytes.length
|
|
933
|
+
);
|
|
934
|
+
return this.combinePreambleAndMessage(preamble, jsonBytes);
|
|
935
|
+
}
|
|
936
|
+
async multisigSigningBytes(unsignedTx, multisig, authenticator) {
|
|
937
|
+
switch (authenticator) {
|
|
818
938
|
case "standard":
|
|
819
|
-
return this.inner.
|
|
820
|
-
case "solanaSimple":
|
|
821
|
-
|
|
939
|
+
return this.inner.multisigSigningBytes(unsignedTx, multisig);
|
|
940
|
+
case "solanaSimple": {
|
|
941
|
+
assertChainHashFragment(unsignedTx, await this.inner.chainHash());
|
|
942
|
+
return this.createMultisigJsonBytes(
|
|
822
943
|
unsignedTx,
|
|
823
|
-
|
|
824
|
-
params.multisigAddress,
|
|
825
|
-
this.canonicalizeMultisigPubkeys(params.multisigPubkeys)
|
|
944
|
+
await this.multisigIdFromMultisig(multisig)
|
|
826
945
|
);
|
|
946
|
+
}
|
|
827
947
|
case "solana":
|
|
828
|
-
return this.
|
|
948
|
+
return this.createSpecCompliantMultisigSignedMessage(
|
|
829
949
|
unsignedTx,
|
|
830
|
-
|
|
831
|
-
params.multisigAddress,
|
|
832
|
-
this.canonicalizeMultisigPubkeys(params.multisigPubkeys)
|
|
950
|
+
multisig
|
|
833
951
|
);
|
|
834
952
|
}
|
|
953
|
+
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
835
954
|
}
|
|
836
955
|
/**
|
|
837
|
-
* Builds a spec-compliant multisig envelope from a V1 transaction
|
|
956
|
+
* Builds a spec-compliant multisig envelope from a V1 transaction.
|
|
838
957
|
*/
|
|
839
|
-
buildSpecCompliantMultisigEnvelope(tx, signedMessageWithPreamble
|
|
958
|
+
buildSpecCompliantMultisigEnvelope(tx, signedMessageWithPreamble) {
|
|
959
|
+
const multisigPubkeys = this.canonicalizeMultisigPubkeys([
|
|
960
|
+
...tx.signatures.map((signer) => signer.pub_key),
|
|
961
|
+
...tx.unused_pub_keys
|
|
962
|
+
]);
|
|
840
963
|
const multisigPubkeyHexes = multisigPubkeys.map(bytesToHex3);
|
|
841
964
|
const indexByPubkey = /* @__PURE__ */ new Map();
|
|
842
965
|
multisigPubkeyHexes.forEach((pubkeyHex, index) => {
|
|
@@ -846,37 +969,42 @@ var SolanaSignableRollup = class {
|
|
|
846
969
|
const signaturesByIndex = /* @__PURE__ */ new Map();
|
|
847
970
|
let signerBitfield = 0;
|
|
848
971
|
for (const signer of tx.signatures) {
|
|
849
|
-
const
|
|
972
|
+
const normalizedSignerPubkey = normalizeHexString(signer.pub_key);
|
|
973
|
+
const signerIndex = indexByPubkey.get(normalizedSignerPubkey);
|
|
850
974
|
if (signerIndex === void 0) {
|
|
851
975
|
throw new Error(
|
|
852
|
-
`Signed pubkey ${
|
|
976
|
+
`Signed pubkey ${normalizedSignerPubkey} is not present in multisigPubkeys`
|
|
853
977
|
);
|
|
854
978
|
}
|
|
855
|
-
if (accountedPubkeys.has(
|
|
979
|
+
if (accountedPubkeys.has(normalizedSignerPubkey)) {
|
|
856
980
|
throw new Error(
|
|
857
|
-
`Duplicate signed pubkey in multisig transaction: ${
|
|
981
|
+
`Duplicate signed pubkey in multisig transaction: ${normalizedSignerPubkey}`
|
|
858
982
|
);
|
|
859
983
|
}
|
|
860
|
-
accountedPubkeys.add(
|
|
861
|
-
signaturesByIndex.set(
|
|
984
|
+
accountedPubkeys.add(normalizedSignerPubkey);
|
|
985
|
+
signaturesByIndex.set(
|
|
986
|
+
signerIndex,
|
|
987
|
+
hexToBytes2(normalizeHexString(signer.signature))
|
|
988
|
+
);
|
|
862
989
|
signerBitfield = (signerBitfield | 1 << signerIndex) >>> 0;
|
|
863
990
|
}
|
|
864
991
|
for (const unusedPubkey of tx.unused_pub_keys) {
|
|
865
|
-
|
|
992
|
+
const normalizedUnusedPubkey = normalizeHexString(unusedPubkey);
|
|
993
|
+
if (!indexByPubkey.has(normalizedUnusedPubkey)) {
|
|
866
994
|
throw new Error(
|
|
867
|
-
`Unused pubkey ${
|
|
995
|
+
`Unused pubkey ${normalizedUnusedPubkey} is not present in multisigPubkeys`
|
|
868
996
|
);
|
|
869
997
|
}
|
|
870
|
-
if (accountedPubkeys.has(
|
|
998
|
+
if (accountedPubkeys.has(normalizedUnusedPubkey)) {
|
|
871
999
|
throw new Error(
|
|
872
|
-
`Duplicate pubkey in multisig transaction payload: ${
|
|
1000
|
+
`Duplicate pubkey in multisig transaction payload: ${normalizedUnusedPubkey}`
|
|
873
1001
|
);
|
|
874
1002
|
}
|
|
875
|
-
accountedPubkeys.add(
|
|
1003
|
+
accountedPubkeys.add(normalizedUnusedPubkey);
|
|
876
1004
|
}
|
|
877
1005
|
if (accountedPubkeys.size !== multisigPubkeys.length) {
|
|
878
1006
|
throw new Error(
|
|
879
|
-
"
|
|
1007
|
+
"Multisig transaction payload must contain every signer exactly once"
|
|
880
1008
|
);
|
|
881
1009
|
}
|
|
882
1010
|
const orderedSignatures = Array.from(signaturesByIndex.entries()).sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, signature]) => signature);
|
|
@@ -888,72 +1016,100 @@ var SolanaSignableRollup = class {
|
|
|
888
1016
|
};
|
|
889
1017
|
}
|
|
890
1018
|
/**
|
|
891
|
-
* Submits a multisig transaction using
|
|
892
|
-
*
|
|
893
|
-
* Accepts the V1 transaction produced by `MultisigTransaction.asTransaction()`.
|
|
894
|
-
* `authenticator: "standard"` delegates directly to the wrapped standard rollup.
|
|
895
|
-
* Solana authenticators rebuild the appropriate Solana multisig envelope and
|
|
896
|
-
* submit it to the Solana offchain endpoint.
|
|
1019
|
+
* Submits a finalized V1 multisig transaction using a Solana authenticator.
|
|
897
1020
|
*/
|
|
898
|
-
async
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
runtime_call: tx.runtime_call,
|
|
902
|
-
uniqueness: tx.uniqueness,
|
|
903
|
-
details: tx.details
|
|
1021
|
+
async submitMultisigTransactionWithAuthenticator(transaction, authenticator, options) {
|
|
1022
|
+
const finalizedTx = {
|
|
1023
|
+
V1: this.normalizeMultisigTransaction(transaction.V1)
|
|
904
1024
|
};
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1025
|
+
const multisig = this.multisigFromTransaction(finalizedTx.V1);
|
|
1026
|
+
if (!multisig.isComplete) {
|
|
1027
|
+
throw new Error("Multisig transaction is incomplete");
|
|
1028
|
+
}
|
|
1029
|
+
const unsignedTx = this.unsignedTxFromTransaction(finalizedTx.V1);
|
|
1030
|
+
switch (authenticator) {
|
|
910
1031
|
case "solanaSimple": {
|
|
911
|
-
this.
|
|
1032
|
+
const chainHash = await this.inner.chainHash();
|
|
1033
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
912
1034
|
const jsonBytes = await this.createMultisigJsonBytes(
|
|
913
1035
|
unsignedTx,
|
|
914
|
-
|
|
1036
|
+
await this.multisigIdFromMultisig(multisig)
|
|
915
1037
|
);
|
|
916
1038
|
const wireBytes = new Uint8Array(1 + jsonBytes.length);
|
|
917
1039
|
wireBytes[0] = MULTISIG_SIMPLE_DISCRIMINATOR;
|
|
918
1040
|
wireBytes.set(jsonBytes, 1);
|
|
919
|
-
const chainHash = await this.inner.chainHash();
|
|
920
1041
|
const serialized = this.serializeSolanaMultisigMessage({
|
|
921
1042
|
wire_bytes: wireBytes,
|
|
922
1043
|
chain_hash: chainHash,
|
|
923
|
-
signatures:
|
|
1044
|
+
signatures: finalizedTx.V1.signatures.map((s) => ({
|
|
924
1045
|
signature: hexToBytes2(s.signature),
|
|
925
1046
|
pub_key: hexToBytes2(s.pub_key)
|
|
926
1047
|
})),
|
|
927
|
-
unused_pub_keys:
|
|
928
|
-
|
|
1048
|
+
unused_pub_keys: finalizedTx.V1.unused_pub_keys.map(
|
|
1049
|
+
(pk) => hexToBytes2(pk)
|
|
1050
|
+
),
|
|
1051
|
+
min_signers: finalizedTx.V1.min_signers
|
|
929
1052
|
});
|
|
930
|
-
return this.submitSerializedMessage(serialized);
|
|
1053
|
+
return this.submitSerializedMessage(serialized, options);
|
|
931
1054
|
}
|
|
932
1055
|
case "solana": {
|
|
933
|
-
const multisigPubkeys = this.canonicalizeMultisigPubkeys(
|
|
934
|
-
params.multisigPubkeys
|
|
935
|
-
);
|
|
936
1056
|
const signedMessageWithPreamble = await this.createSpecCompliantMultisigSignedMessage(
|
|
937
1057
|
unsignedTx,
|
|
938
|
-
|
|
939
|
-
multisigPubkeys
|
|
1058
|
+
multisig
|
|
940
1059
|
);
|
|
941
1060
|
const message = this.buildSpecCompliantMultisigEnvelope(
|
|
942
|
-
|
|
943
|
-
signedMessageWithPreamble
|
|
944
|
-
|
|
1061
|
+
finalizedTx.V1,
|
|
1062
|
+
signedMessageWithPreamble
|
|
1063
|
+
);
|
|
1064
|
+
return this.submitSolanaSpecMultisigMessage(message, options);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Submits a finalized V0 transaction using a Solana authenticator.
|
|
1070
|
+
*/
|
|
1071
|
+
async submitSingleSignatureTransactionWithAuthenticator(transaction, authenticator, options) {
|
|
1072
|
+
const unsignedTx = {
|
|
1073
|
+
runtime_call: transaction.runtime_call,
|
|
1074
|
+
uniqueness: transaction.uniqueness,
|
|
1075
|
+
details: transaction.details,
|
|
1076
|
+
address_override: transaction.address_override
|
|
1077
|
+
};
|
|
1078
|
+
const pubkey = hexToBytes2(normalizeHexString(transaction.pub_key));
|
|
1079
|
+
const signature = hexToBytes2(normalizeHexString(transaction.signature));
|
|
1080
|
+
const chainHash = await this.inner.chainHash();
|
|
1081
|
+
assertChainHashFragment(unsignedTx, chainHash);
|
|
1082
|
+
switch (authenticator) {
|
|
1083
|
+
case "solanaSimple": {
|
|
1084
|
+
const signedMessage = await this.createSolanaJsonBytes(unsignedTx);
|
|
1085
|
+
const message = {
|
|
1086
|
+
signed_message: signedMessage,
|
|
1087
|
+
chain_hash: chainHash,
|
|
1088
|
+
pubkey,
|
|
1089
|
+
signature
|
|
1090
|
+
};
|
|
1091
|
+
return this.submitSolanaMessage(message, options);
|
|
1092
|
+
}
|
|
1093
|
+
case "solana": {
|
|
1094
|
+
const signedMessage = await this.createSolanaJsonBytes(unsignedTx);
|
|
1095
|
+
const preamble = createSolanaPreamble(
|
|
1096
|
+
[pubkey],
|
|
1097
|
+
chainHash,
|
|
1098
|
+
signedMessage.length
|
|
945
1099
|
);
|
|
946
|
-
|
|
1100
|
+
const message = {
|
|
1101
|
+
signed_message_with_preamble: this.combinePreambleAndMessage(
|
|
1102
|
+
preamble,
|
|
1103
|
+
signedMessage
|
|
1104
|
+
),
|
|
1105
|
+
signature
|
|
1106
|
+
};
|
|
1107
|
+
return this.submitSolanaSpecMessage(message, options);
|
|
947
1108
|
}
|
|
948
1109
|
}
|
|
949
1110
|
}
|
|
950
1111
|
/**
|
|
951
1112
|
* Submits a transaction with the specified authenticator.
|
|
952
|
-
*
|
|
953
|
-
* @param transaction - Either a standard transaction or a Solana message
|
|
954
|
-
* @param authenticator - The authenticator type to use
|
|
955
|
-
* @param options - Optional request options
|
|
956
|
-
* @returns The transaction response
|
|
957
1113
|
*/
|
|
958
1114
|
async submitTransaction(transaction, authenticator, options) {
|
|
959
1115
|
switch (authenticator) {
|
|
@@ -962,17 +1118,34 @@ var SolanaSignableRollup = class {
|
|
|
962
1118
|
transaction,
|
|
963
1119
|
options
|
|
964
1120
|
);
|
|
965
|
-
case "solanaSimple":
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1121
|
+
case "solanaSimple":
|
|
1122
|
+
if ("V1" in transaction) {
|
|
1123
|
+
return this.submitMultisigTransactionWithAuthenticator(
|
|
1124
|
+
transaction,
|
|
1125
|
+
"solanaSimple",
|
|
1126
|
+
options
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
return this.submitSingleSignatureTransactionWithAuthenticator(
|
|
1130
|
+
transaction.V0,
|
|
1131
|
+
"solanaSimple",
|
|
1132
|
+
options
|
|
1133
|
+
);
|
|
1134
|
+
case "solana":
|
|
1135
|
+
if ("V1" in transaction) {
|
|
1136
|
+
return this.submitMultisigTransactionWithAuthenticator(
|
|
1137
|
+
transaction,
|
|
1138
|
+
"solana",
|
|
1139
|
+
options
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
return this.submitSingleSignatureTransactionWithAuthenticator(
|
|
1143
|
+
transaction.V0,
|
|
1144
|
+
"solana",
|
|
1145
|
+
options
|
|
1146
|
+
);
|
|
975
1147
|
}
|
|
1148
|
+
throw new Error(`Unsupported authenticator: ${authenticator}`);
|
|
976
1149
|
}
|
|
977
1150
|
async simulate(runtimeMessage, params) {
|
|
978
1151
|
return this.inner.simulate(runtimeMessage, params);
|
|
@@ -980,6 +1153,9 @@ var SolanaSignableRollup = class {
|
|
|
980
1153
|
async dedup(address) {
|
|
981
1154
|
return this.inner.dedup(address);
|
|
982
1155
|
}
|
|
1156
|
+
async dedupByCredentialId(credentialId) {
|
|
1157
|
+
return this.inner.dedupByCredentialId(credentialId);
|
|
1158
|
+
}
|
|
983
1159
|
async serializer() {
|
|
984
1160
|
return this.inner.serializer();
|
|
985
1161
|
}
|
|
@@ -1015,7 +1191,7 @@ var SolanaSignableRollup = class {
|
|
|
1015
1191
|
return this.inner.http;
|
|
1016
1192
|
}
|
|
1017
1193
|
/**
|
|
1018
|
-
* Helper method to serialize a
|
|
1194
|
+
* Helper method to serialize a SolanaOffchainSimpleEnvelope using borsh encoding.
|
|
1019
1195
|
*/
|
|
1020
1196
|
serializeSolanaMessage(message) {
|
|
1021
1197
|
if (message.chain_hash.length !== CHAIN_HASH_SIZE) {
|
|
@@ -1049,7 +1225,7 @@ var SolanaSignableRollup = class {
|
|
|
1049
1225
|
return buffer;
|
|
1050
1226
|
}
|
|
1051
1227
|
/**
|
|
1052
|
-
* Helper method to serialize a
|
|
1228
|
+
* Helper method to serialize a SolanaOffchainSpecCompliantEnvelope using borsh encoding.
|
|
1053
1229
|
*/
|
|
1054
1230
|
serializeSolanaSpecMessage(message) {
|
|
1055
1231
|
if (message.signature.length !== SIGNATURE_SIZE) {
|
|
@@ -1069,7 +1245,7 @@ var SolanaSignableRollup = class {
|
|
|
1069
1245
|
return buffer;
|
|
1070
1246
|
}
|
|
1071
1247
|
/**
|
|
1072
|
-
* Serializes a
|
|
1248
|
+
* Serializes a SolanaOffchainSimpleMultisigEnvelope using borsh encoding.
|
|
1073
1249
|
* Layout matches the Rust struct:
|
|
1074
1250
|
* [u32 LE: wire_bytes.len][wire_bytes]
|
|
1075
1251
|
* [32 bytes: chain_hash]
|
|
@@ -1130,7 +1306,7 @@ var SolanaSignableRollup = class {
|
|
|
1130
1306
|
return buffer;
|
|
1131
1307
|
}
|
|
1132
1308
|
/**
|
|
1133
|
-
* Serializes a
|
|
1309
|
+
* Serializes a SolanaOffchainSpecCompliantMultisigEnvelope using borsh encoding.
|
|
1134
1310
|
* Layout matches the Rust struct:
|
|
1135
1311
|
* [u32 LE: signed_message_with_preamble.len][signed_message_with_preamble]
|
|
1136
1312
|
* [u32 LE: signatures.len]
|
|
@@ -1183,6 +1359,7 @@ export {
|
|
|
1183
1359
|
StandardRollup,
|
|
1184
1360
|
VersionMismatchError,
|
|
1185
1361
|
addressFromPublicKey,
|
|
1362
|
+
chainHashFragment,
|
|
1186
1363
|
createSolanaSignableRollup,
|
|
1187
1364
|
createStandardRollup,
|
|
1188
1365
|
standardTypeBuilder
|