@shelby-protocol/cli 0.0.21 → 0.0.23
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/bin/entry.js +2076 -1681
- package/package.json +2 -2
package/bin/entry.js
CHANGED
|
@@ -459,13 +459,13 @@ custom_config:
|
|
|
459
459
|
event_index: []
|
|
460
460
|
event_type: []
|
|
461
461
|
sequence_number: []
|
|
462
|
-
0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5::placement_group::
|
|
462
|
+
0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5::placement_group::StorageProviderVacatedEvent:
|
|
463
463
|
constant_values:
|
|
464
464
|
- column: "status"
|
|
465
465
|
table: "placement_group_slots"
|
|
466
|
-
value: "
|
|
466
|
+
value: "vacated"
|
|
467
467
|
event_fields:
|
|
468
|
-
$.
|
|
468
|
+
$.vacated_at:
|
|
469
469
|
- column: "updated_at"
|
|
470
470
|
table: "placement_group_slots"
|
|
471
471
|
$.placement_group_address:
|
|
@@ -505,13 +505,246 @@ import { Command } from "@commander-js/extra-typings";
|
|
|
505
505
|
|
|
506
506
|
// package.json
|
|
507
507
|
var name = "@shelby-protocol/cli";
|
|
508
|
-
var version = "0.0.
|
|
508
|
+
var version = "0.0.23";
|
|
509
509
|
|
|
510
510
|
// src/commands/account.tsx
|
|
511
511
|
import readline from "readline";
|
|
512
512
|
import { Account as Account3, AptosApiError as AptosApiError2, Ed25519PrivateKey as Ed25519PrivateKey4 } from "@aptos-labs/ts-sdk";
|
|
513
513
|
import { Option } from "@commander-js/extra-typings";
|
|
514
514
|
|
|
515
|
+
// ../../packages/sdk/dist/chunk-4ZOFT75Q.mjs
|
|
516
|
+
import { Network } from "@aptos-labs/ts-sdk";
|
|
517
|
+
var NetworkToShelbyRPCBaseUrl = {
|
|
518
|
+
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
|
|
519
|
+
[Network.NETNA]: void 0,
|
|
520
|
+
[Network.DEVNET]: void 0,
|
|
521
|
+
[Network.TESTNET]: "https://api.testnet.shelby.xyz/shelby",
|
|
522
|
+
[Network.MAINNET]: void 0,
|
|
523
|
+
[Network.LOCAL]: void 0,
|
|
524
|
+
[Network.CUSTOM]: void 0
|
|
525
|
+
};
|
|
526
|
+
var NetworkToShelbyBlobIndexerBaseUrl = {
|
|
527
|
+
[Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
|
|
528
|
+
[Network.NETNA]: void 0,
|
|
529
|
+
[Network.DEVNET]: void 0,
|
|
530
|
+
[Network.TESTNET]: "https://api.testnet.aptoslabs.com/nocode/v1/public/cmlfqs5wt00qrs601zt5s4kfj/v1/graphql",
|
|
531
|
+
[Network.MAINNET]: void 0,
|
|
532
|
+
[Network.LOCAL]: void 0,
|
|
533
|
+
[Network.CUSTOM]: void 0
|
|
534
|
+
};
|
|
535
|
+
var NetworkToGasStationBaseUrl = {
|
|
536
|
+
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/gs/v1",
|
|
537
|
+
[Network.NETNA]: void 0,
|
|
538
|
+
[Network.DEVNET]: void 0,
|
|
539
|
+
[Network.TESTNET]: "https://api.testnet.shelby.xyz/gs/v1",
|
|
540
|
+
[Network.MAINNET]: void 0,
|
|
541
|
+
[Network.LOCAL]: void 0,
|
|
542
|
+
[Network.CUSTOM]: void 0
|
|
543
|
+
};
|
|
544
|
+
var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
|
|
545
|
+
var MICROPAYMENTS_DEPLOYER = "0xb42ac038b6dae86f6171e28e297aab9555ce09909445ec579e4ffe6b8d4d63bf";
|
|
546
|
+
var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
|
|
547
|
+
var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
|
|
548
|
+
|
|
549
|
+
// ../../packages/sdk/dist/chunk-KTVNKLBT.mjs
|
|
550
|
+
import {
|
|
551
|
+
AccountAddress,
|
|
552
|
+
Deserializer,
|
|
553
|
+
Hex,
|
|
554
|
+
Serializer
|
|
555
|
+
} from "@aptos-labs/ts-sdk";
|
|
556
|
+
var MICROPAYMENTS_MODULE_NAME = "micropayments";
|
|
557
|
+
var WITHDRAW_APPROVAL_STRUCT_NAME = "WithdrawApproval";
|
|
558
|
+
function serializeTypeInfo(serializer, moduleAddress, moduleName, structName) {
|
|
559
|
+
moduleAddress.serialize(serializer);
|
|
560
|
+
const moduleNameBytes = new TextEncoder().encode(moduleName);
|
|
561
|
+
serializer.serializeBytes(moduleNameBytes);
|
|
562
|
+
const structNameBytes = new TextEncoder().encode(structName);
|
|
563
|
+
serializer.serializeBytes(structNameBytes);
|
|
564
|
+
}
|
|
565
|
+
var StaleChannelStateError = class _StaleChannelStateError extends Error {
|
|
566
|
+
/**
|
|
567
|
+
* The last valid micropayment stored by the server.
|
|
568
|
+
* Clients can use this to reset their local channel state.
|
|
569
|
+
*/
|
|
570
|
+
storedMicropayment;
|
|
571
|
+
constructor(storedMicropayment, message) {
|
|
572
|
+
super(
|
|
573
|
+
message ?? "Client has stale channel state. Use the returned micropayment to reset local state."
|
|
574
|
+
);
|
|
575
|
+
this.name = "StaleChannelStateError";
|
|
576
|
+
this.storedMicropayment = storedMicropayment;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Returns the stored micropayment as a base64-encoded string.
|
|
580
|
+
*/
|
|
581
|
+
toBase64() {
|
|
582
|
+
const bytes = this.storedMicropayment.bcsToBytes();
|
|
583
|
+
const binaryString = Array.from(
|
|
584
|
+
bytes,
|
|
585
|
+
(byte) => String.fromCharCode(byte)
|
|
586
|
+
).join("");
|
|
587
|
+
return btoa(binaryString);
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Creates a StaleChannelStateError from a base64-encoded micropayment string.
|
|
591
|
+
*/
|
|
592
|
+
static fromBase64(base64, message) {
|
|
593
|
+
const binaryString = atob(base64);
|
|
594
|
+
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
|
|
595
|
+
const micropayment = SenderBuiltMicropayment.deserialize(bytes);
|
|
596
|
+
return new _StaleChannelStateError(micropayment, message);
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
var SenderBuiltMicropayment = class _SenderBuiltMicropayment {
|
|
600
|
+
/**
|
|
601
|
+
* The sender's address (owner of the payment channel).
|
|
602
|
+
*/
|
|
603
|
+
sender;
|
|
604
|
+
/**
|
|
605
|
+
* The receiver's address (beneficiary of the withdrawal).
|
|
606
|
+
*/
|
|
607
|
+
receiver;
|
|
608
|
+
/**
|
|
609
|
+
* The unique ID of the payment channel.
|
|
610
|
+
*/
|
|
611
|
+
paymentChannelId;
|
|
612
|
+
/**
|
|
613
|
+
* The cumulative amount the receiver is authorized to withdraw.
|
|
614
|
+
*/
|
|
615
|
+
amount;
|
|
616
|
+
/**
|
|
617
|
+
* The fungible asset metadata address.
|
|
618
|
+
*/
|
|
619
|
+
fungibleAssetAddress;
|
|
620
|
+
/**
|
|
621
|
+
* Monotonically increasing sequence number for replay protection.
|
|
622
|
+
*/
|
|
623
|
+
sequenceNumber;
|
|
624
|
+
/**
|
|
625
|
+
* The sender's Ed25519 public key (32 bytes).
|
|
626
|
+
* Used by the receiver to verify the signature before submitting.
|
|
627
|
+
*/
|
|
628
|
+
publicKey;
|
|
629
|
+
/**
|
|
630
|
+
* The Ed25519 signature of the SignedMessage<WithdrawApproval> struct.
|
|
631
|
+
* The SignedMessage includes TypeInfo for domain separation.
|
|
632
|
+
*/
|
|
633
|
+
signature;
|
|
634
|
+
/**
|
|
635
|
+
* The deployer address of the micropayments module.
|
|
636
|
+
* This is needed to reconstruct the TypeInfo for signature verification.
|
|
637
|
+
*/
|
|
638
|
+
deployer;
|
|
639
|
+
constructor(sender, receiver, paymentChannelId, amount, fungibleAssetAddress, sequenceNumber, publicKey, signature, deployer) {
|
|
640
|
+
this.sender = sender;
|
|
641
|
+
this.receiver = receiver;
|
|
642
|
+
this.paymentChannelId = paymentChannelId;
|
|
643
|
+
this.amount = amount;
|
|
644
|
+
this.fungibleAssetAddress = fungibleAssetAddress;
|
|
645
|
+
this.sequenceNumber = sequenceNumber;
|
|
646
|
+
this.publicKey = publicKey;
|
|
647
|
+
this.signature = signature;
|
|
648
|
+
this.deployer = deployer ?? AccountAddress.fromString(MICROPAYMENTS_DEPLOYER);
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Creates the BCS-serialized message that was signed.
|
|
652
|
+
* This is a SignedMessage<WithdrawApproval> which includes:
|
|
653
|
+
* 1. TypeInfo (module_address, module_name, struct_name)
|
|
654
|
+
* 2. WithdrawApproval struct fields
|
|
655
|
+
*
|
|
656
|
+
* This format is used with signature_verify_strict_t for domain separation.
|
|
657
|
+
*/
|
|
658
|
+
getSignedMessage() {
|
|
659
|
+
return _SenderBuiltMicropayment.buildSignedMessage({
|
|
660
|
+
deployer: this.deployer,
|
|
661
|
+
sender: this.sender,
|
|
662
|
+
receiver: this.receiver,
|
|
663
|
+
fungibleAssetAddress: this.fungibleAssetAddress,
|
|
664
|
+
amount: this.amount,
|
|
665
|
+
paymentChannelId: this.paymentChannelId,
|
|
666
|
+
sequenceNumber: this.sequenceNumber
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Static helper to build the SignedMessage<WithdrawApproval> bytes from raw parameters.
|
|
671
|
+
* This can be used to create the message for signing without constructing the full object.
|
|
672
|
+
*
|
|
673
|
+
* @param params - The withdrawal approval parameters.
|
|
674
|
+
* @returns The BCS-serialized SignedMessage<WithdrawApproval> bytes.
|
|
675
|
+
*/
|
|
676
|
+
static buildSignedMessage(params) {
|
|
677
|
+
const serializer = new Serializer();
|
|
678
|
+
serializeTypeInfo(
|
|
679
|
+
serializer,
|
|
680
|
+
params.deployer,
|
|
681
|
+
MICROPAYMENTS_MODULE_NAME,
|
|
682
|
+
WITHDRAW_APPROVAL_STRUCT_NAME
|
|
683
|
+
);
|
|
684
|
+
params.sender.serialize(serializer);
|
|
685
|
+
params.receiver.serialize(serializer);
|
|
686
|
+
params.fungibleAssetAddress.serialize(serializer);
|
|
687
|
+
serializer.serializeU64(params.amount);
|
|
688
|
+
serializer.serializeU64(params.paymentChannelId);
|
|
689
|
+
serializer.serializeU64(params.sequenceNumber);
|
|
690
|
+
return serializer.toUint8Array();
|
|
691
|
+
}
|
|
692
|
+
serialize(serializer) {
|
|
693
|
+
this.sender.serialize(serializer);
|
|
694
|
+
this.receiver.serialize(serializer);
|
|
695
|
+
this.fungibleAssetAddress.serialize(serializer);
|
|
696
|
+
serializer.serializeU64(this.amount);
|
|
697
|
+
serializer.serializeU64(this.paymentChannelId);
|
|
698
|
+
serializer.serializeU64(this.sequenceNumber);
|
|
699
|
+
serializer.serializeBytes(this.publicKey);
|
|
700
|
+
serializer.serializeBytes(this.signature);
|
|
701
|
+
this.deployer.serialize(serializer);
|
|
702
|
+
}
|
|
703
|
+
bcsToBytes() {
|
|
704
|
+
const serializer = new Serializer();
|
|
705
|
+
this.serialize(serializer);
|
|
706
|
+
return serializer.toUint8Array();
|
|
707
|
+
}
|
|
708
|
+
bcsToHex() {
|
|
709
|
+
return Hex.fromHexInput(this.bcsToBytes());
|
|
710
|
+
}
|
|
711
|
+
toStringWithoutPrefix() {
|
|
712
|
+
return this.bcsToHex().toStringWithoutPrefix();
|
|
713
|
+
}
|
|
714
|
+
toString() {
|
|
715
|
+
return this.bcsToHex().toString();
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Deserializes a SenderBuiltMicropayment from BCS bytes.
|
|
719
|
+
* @param bytes - The bytes to deserialize from (Uint8Array or hex string).
|
|
720
|
+
* @returns A new SenderBuiltMicropayment instance.
|
|
721
|
+
*/
|
|
722
|
+
static deserialize(bytes) {
|
|
723
|
+
const bytesArray = typeof bytes === "string" ? Hex.fromHexInput(bytes).toUint8Array() : bytes;
|
|
724
|
+
const deserializer = new Deserializer(bytesArray);
|
|
725
|
+
const sender = AccountAddress.deserialize(deserializer);
|
|
726
|
+
const receiver = AccountAddress.deserialize(deserializer);
|
|
727
|
+
const fungibleAssetAddress = AccountAddress.deserialize(deserializer);
|
|
728
|
+
const amount = deserializer.deserializeU64();
|
|
729
|
+
const paymentChannelId = deserializer.deserializeU64();
|
|
730
|
+
const sequenceNumber = deserializer.deserializeU64();
|
|
731
|
+
const publicKey = deserializer.deserializeBytes();
|
|
732
|
+
const signature = deserializer.deserializeBytes();
|
|
733
|
+
const deployer = AccountAddress.deserialize(deserializer);
|
|
734
|
+
return new _SenderBuiltMicropayment(
|
|
735
|
+
sender,
|
|
736
|
+
receiver,
|
|
737
|
+
paymentChannelId,
|
|
738
|
+
amount,
|
|
739
|
+
fungibleAssetAddress,
|
|
740
|
+
sequenceNumber,
|
|
741
|
+
publicKey,
|
|
742
|
+
signature,
|
|
743
|
+
deployer
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
|
|
515
748
|
// ../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs
|
|
516
749
|
var __assign = function() {
|
|
517
750
|
__assign = Object.assign || function __assign2(t) {
|
|
@@ -3857,32 +4090,7 @@ var getAptosConfig = (config) => {
|
|
|
3857
4090
|
});
|
|
3858
4091
|
};
|
|
3859
4092
|
|
|
3860
|
-
// ../../packages/sdk/dist/chunk-
|
|
3861
|
-
import { Network } from "@aptos-labs/ts-sdk";
|
|
3862
|
-
var NetworkToShelbyRPCBaseUrl = {
|
|
3863
|
-
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
|
|
3864
|
-
[Network.NETNA]: void 0,
|
|
3865
|
-
[Network.DEVNET]: void 0,
|
|
3866
|
-
[Network.TESTNET]: void 0,
|
|
3867
|
-
[Network.MAINNET]: void 0,
|
|
3868
|
-
[Network.LOCAL]: void 0,
|
|
3869
|
-
[Network.CUSTOM]: void 0
|
|
3870
|
-
};
|
|
3871
|
-
var NetworkToShelbyBlobIndexerBaseUrl = {
|
|
3872
|
-
[Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
|
|
3873
|
-
[Network.NETNA]: void 0,
|
|
3874
|
-
[Network.DEVNET]: void 0,
|
|
3875
|
-
[Network.TESTNET]: void 0,
|
|
3876
|
-
[Network.MAINNET]: void 0,
|
|
3877
|
-
[Network.LOCAL]: void 0,
|
|
3878
|
-
[Network.CUSTOM]: void 0
|
|
3879
|
-
};
|
|
3880
|
-
var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
|
|
3881
|
-
var MICROPAYMENTS_DEPLOYER = "0xb42ac038b6dae86f6171e28e297aab9555ce09909445ec579e4ffe6b8d4d63bf";
|
|
3882
|
-
var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
|
|
3883
|
-
var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
|
|
3884
|
-
|
|
3885
|
-
// ../../packages/sdk/dist/chunk-3ZL3FSNA.mjs
|
|
4093
|
+
// ../../packages/sdk/dist/chunk-CGYJLKBU.mjs
|
|
3886
4094
|
import { Network as Network2 } from "@aptos-labs/ts-sdk";
|
|
3887
4095
|
|
|
3888
4096
|
// ../../node_modules/.pnpm/graphql-request@7.2.0_graphql@16.11.0/node_modules/graphql-request/build/legacy/classes/ClientError.js
|
|
@@ -4397,7 +4605,7 @@ var parseRequestArgs = (documentOrOptions, variables, requestHeaders) => {
|
|
|
4397
4605
|
};
|
|
4398
4606
|
};
|
|
4399
4607
|
|
|
4400
|
-
// ../../packages/sdk/dist/chunk-
|
|
4608
|
+
// ../../packages/sdk/dist/chunk-CGYJLKBU.mjs
|
|
4401
4609
|
function createShelbyIndexerClient(baseUrl, options) {
|
|
4402
4610
|
const graphqlClient = new GraphQLClient(baseUrl, options);
|
|
4403
4611
|
return getSdk(graphqlClient);
|
|
@@ -4430,14 +4638,41 @@ function getShelbyIndexerClient(config) {
|
|
|
4430
4638
|
});
|
|
4431
4639
|
}
|
|
4432
4640
|
|
|
4433
|
-
// ../../packages/sdk/dist/chunk-
|
|
4434
|
-
import {
|
|
4435
|
-
var
|
|
4436
|
-
|
|
4437
|
-
};
|
|
4641
|
+
// ../../packages/sdk/dist/chunk-Z4FZ7W6L.mjs
|
|
4642
|
+
import { z } from "zod";
|
|
4643
|
+
var BlobNameSchema = z.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name2) => !name2.endsWith("/"), {
|
|
4644
|
+
message: "Blob name cannot end with a slash"
|
|
4645
|
+
});
|
|
4646
|
+
|
|
4647
|
+
// ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
|
|
4648
|
+
function sleep(ms) {
|
|
4649
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
4650
|
+
}
|
|
4651
|
+
|
|
4652
|
+
// ../../packages/sdk/dist/chunk-IE6LYVIA.mjs
|
|
4653
|
+
import { z as z2 } from "zod";
|
|
4654
|
+
var StartMultipartUploadResponseSchema = z2.object({
|
|
4655
|
+
uploadId: z2.string()
|
|
4656
|
+
});
|
|
4657
|
+
var UploadPartResponseSchema = z2.object({
|
|
4658
|
+
success: z2.literal(true)
|
|
4659
|
+
});
|
|
4660
|
+
var CompleteMultipartUploadResponseSchema = z2.object({
|
|
4661
|
+
success: z2.literal(true)
|
|
4662
|
+
});
|
|
4663
|
+
var RPCErrorResponseSchema = z2.object({
|
|
4664
|
+
error: z2.string()
|
|
4665
|
+
});
|
|
4666
|
+
var StaleMicropaymentErrorResponseSchema = z2.object({
|
|
4667
|
+
error: z2.string().optional(),
|
|
4668
|
+
storedMicropayment: z2.string().optional()
|
|
4669
|
+
});
|
|
4438
4670
|
|
|
4439
|
-
// ../../packages/sdk/dist/chunk-
|
|
4440
|
-
import {
|
|
4671
|
+
// ../../packages/sdk/dist/chunk-UEZNZBJO.mjs
|
|
4672
|
+
import {
|
|
4673
|
+
AccountAddress as AccountAddress2,
|
|
4674
|
+
Hex as Hex2
|
|
4675
|
+
} from "@aptos-labs/ts-sdk";
|
|
4441
4676
|
async function* readInChunks(input, chunkSize) {
|
|
4442
4677
|
let idx = 0;
|
|
4443
4678
|
if (isReadableStream(input)) {
|
|
@@ -4497,7 +4732,7 @@ function zeroPadBytes(buffer, desiredLength) {
|
|
|
4497
4732
|
return paddedBuffer;
|
|
4498
4733
|
}
|
|
4499
4734
|
async function concatHashes(parts) {
|
|
4500
|
-
const chunks = parts.map((part) =>
|
|
4735
|
+
const chunks = parts.map((part) => Hex2.fromHexInput(part).toUint8Array());
|
|
4501
4736
|
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
4502
4737
|
const combined = new Uint8Array(totalLength);
|
|
4503
4738
|
let offset = 0;
|
|
@@ -4505,7 +4740,7 @@ async function concatHashes(parts) {
|
|
|
4505
4740
|
combined.set(chunk, offset);
|
|
4506
4741
|
offset += chunk.byteLength;
|
|
4507
4742
|
}
|
|
4508
|
-
return
|
|
4743
|
+
return Hex2.fromHexInput(
|
|
4509
4744
|
new Uint8Array(await crypto.subtle.digest("SHA-256", combined))
|
|
4510
4745
|
);
|
|
4511
4746
|
}
|
|
@@ -4525,1546 +4760,1743 @@ function getBlobNameSuffix(blobName) {
|
|
|
4525
4760
|
const parts = blobName.split("/");
|
|
4526
4761
|
return parts.slice(1).join("/") || "";
|
|
4527
4762
|
}
|
|
4763
|
+
function normalizeAddress(address) {
|
|
4764
|
+
return AccountAddress2.from(address, { maxMissingChars: 63 });
|
|
4765
|
+
}
|
|
4528
4766
|
|
|
4529
|
-
// ../../packages/sdk/dist/chunk-
|
|
4530
|
-
var
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
// 10MiB
|
|
4538
|
-
chunksetSizeBytes: 10 * 1024 * 1024
|
|
4539
|
-
}
|
|
4540
|
-
};
|
|
4541
|
-
var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
4542
|
-
"ChunkSet10MiB_Chunk1MiB"
|
|
4543
|
-
/* ChunkSet10MiB_Chunk1MiB */
|
|
4544
|
-
].chunkSizeBytes;
|
|
4545
|
-
var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
4546
|
-
"ChunkSet10MiB_Chunk1MiB"
|
|
4547
|
-
/* ChunkSet10MiB_Chunk1MiB */
|
|
4548
|
-
].chunksetSizeBytes;
|
|
4549
|
-
var ERASURE_CODE_AND_CHUNK_MAPPING = {
|
|
4550
|
-
[
|
|
4551
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4552
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4553
|
-
]: {
|
|
4554
|
-
...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
|
|
4767
|
+
// ../../packages/sdk/dist/chunk-EFR6H3RT.mjs
|
|
4768
|
+
var MICROPAYMENT_HEADER = "X-Shelby-Micropayment";
|
|
4769
|
+
function encodeURIComponentKeepSlashes(str) {
|
|
4770
|
+
return encodeURIComponent(str).replace(/%2F/g, "/");
|
|
4771
|
+
}
|
|
4772
|
+
function validateTotalBytes(totalBytes) {
|
|
4773
|
+
if (!Number.isInteger(totalBytes) || totalBytes < 0) {
|
|
4774
|
+
throw new Error("totalBytes must be a non-negative integer");
|
|
4555
4775
|
}
|
|
4556
|
-
}
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
[
|
|
4561
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4562
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4563
|
-
]: {
|
|
4564
|
-
// total chunks (data + parity)
|
|
4565
|
-
erasure_n: 16,
|
|
4566
|
-
// data chunks
|
|
4567
|
-
erasure_k: 10,
|
|
4568
|
-
// helper nodes
|
|
4569
|
-
erasure_d: 13
|
|
4776
|
+
}
|
|
4777
|
+
function getErrorCode(error) {
|
|
4778
|
+
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
|
|
4779
|
+
return error.code;
|
|
4570
4780
|
}
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4575
|
-
].erasure_n;
|
|
4576
|
-
var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS[
|
|
4577
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4578
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4579
|
-
].erasure_k;
|
|
4580
|
-
var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS[
|
|
4581
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4582
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4583
|
-
].erasure_d;
|
|
4584
|
-
var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
|
|
4585
|
-
|
|
4586
|
-
// ../../packages/sdk/dist/chunk-RLRI2533.mjs
|
|
4587
|
-
import { Hex as Hex2 } from "@aptos-labs/ts-sdk";
|
|
4588
|
-
import { z } from "zod";
|
|
4589
|
-
var COMMITMENT_SCHEMA_VERSION = "1.3";
|
|
4590
|
-
var ChunksetCommitmentSchema = z.object({
|
|
4591
|
-
// Chunkset root (vector commitment of child chunks)
|
|
4592
|
-
chunkset_root: z.string(),
|
|
4593
|
-
// the size is known statically from the current configuration
|
|
4594
|
-
chunk_commitments: z.array(z.string())
|
|
4595
|
-
}).refine(
|
|
4596
|
-
(data) => {
|
|
4597
|
-
return data.chunk_commitments.length === DEFAULT_ERASURE_K + DEFAULT_ERASURE_M;
|
|
4598
|
-
},
|
|
4599
|
-
{
|
|
4600
|
-
message: `Chunkset must have exactly ${DEFAULT_ERASURE_K + DEFAULT_ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${DEFAULT_ERASURE_K} + ${DEFAULT_ERASURE_M})`,
|
|
4601
|
-
path: ["chunk_commitments"]
|
|
4781
|
+
if (error instanceof Error) {
|
|
4782
|
+
const match = error.message.match(/\bE[A-Z0-9_]+\b/);
|
|
4783
|
+
return match?.[0];
|
|
4602
4784
|
}
|
|
4603
|
-
|
|
4604
|
-
function expectedTotalChunksets(rawSize, chunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES) {
|
|
4605
|
-
if (chunksetSize <= 0) {
|
|
4606
|
-
throw new Error("chunksetSize must be positive");
|
|
4607
|
-
}
|
|
4608
|
-
if (rawSize === 0) return 1;
|
|
4609
|
-
return Math.ceil(rawSize / chunksetSize);
|
|
4610
|
-
}
|
|
4611
|
-
var BlobCommitmentsSchema = z.object({
|
|
4612
|
-
schema_version: z.string(),
|
|
4613
|
-
raw_data_size: z.number(),
|
|
4614
|
-
// FIXME I am not sure about this being here, or if it should be somewhere else
|
|
4615
|
-
blob_merkle_root: z.string(),
|
|
4616
|
-
chunkset_commitments: z.array(ChunksetCommitmentSchema)
|
|
4617
|
-
}).refine(
|
|
4618
|
-
(data) => {
|
|
4619
|
-
return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
|
|
4620
|
-
},
|
|
4621
|
-
{
|
|
4622
|
-
message: "Total chunkset count mismatches with raw data size",
|
|
4623
|
-
// FIXME put more details in here
|
|
4624
|
-
path: ["chunkset_commitments"]
|
|
4625
|
-
}
|
|
4626
|
-
);
|
|
4627
|
-
async function generateMerkleRoot(leafHashes) {
|
|
4628
|
-
if (!leafHashes.length) {
|
|
4629
|
-
throw new Error(
|
|
4630
|
-
"An empty array cannot be used to construct a Merkle tree."
|
|
4631
|
-
);
|
|
4632
|
-
}
|
|
4633
|
-
const zeroArray = new Uint8Array(leafHashes[0].toUint8Array().length);
|
|
4634
|
-
const zeroBytes = Hex2.fromHexInput(zeroArray);
|
|
4635
|
-
let currentLeaves = leafHashes;
|
|
4636
|
-
while (currentLeaves.length > 1) {
|
|
4637
|
-
if (currentLeaves.length % 2 !== 0) {
|
|
4638
|
-
currentLeaves.push(zeroBytes);
|
|
4639
|
-
}
|
|
4640
|
-
const nextLeaves = [];
|
|
4641
|
-
for (let i = 0; i < currentLeaves.length; i += 2) {
|
|
4642
|
-
nextLeaves.push(
|
|
4643
|
-
await concatHashes([
|
|
4644
|
-
currentLeaves[i].toUint8Array(),
|
|
4645
|
-
currentLeaves[i + 1].toUint8Array()
|
|
4646
|
-
])
|
|
4647
|
-
);
|
|
4648
|
-
}
|
|
4649
|
-
currentLeaves = nextLeaves;
|
|
4650
|
-
}
|
|
4651
|
-
return currentLeaves[0];
|
|
4652
|
-
}
|
|
4653
|
-
async function generateChunksetCommitments(shouldPad, chunksetIdx, chunksetData, expectedChunksetSize, provider, onChunk) {
|
|
4654
|
-
const { erasure_n } = provider.config;
|
|
4655
|
-
const chunksetPayload = shouldPad ? zeroPadBytes(chunksetData, expectedChunksetSize) : validatePrePaddedChunkset(
|
|
4656
|
-
chunksetData,
|
|
4657
|
-
expectedChunksetSize,
|
|
4658
|
-
chunksetIdx
|
|
4659
|
-
);
|
|
4660
|
-
const { chunks } = provider.encode(chunksetPayload);
|
|
4661
|
-
if (chunks.length !== erasure_n) {
|
|
4662
|
-
throw new Error(
|
|
4663
|
-
`Erasure provider produced ${chunks.length} chunks, expected ${erasure_n}.`
|
|
4664
|
-
);
|
|
4665
|
-
}
|
|
4666
|
-
const chunkRoots = provider.getChunkMerkleRoots();
|
|
4667
|
-
let chunkIdx = 0;
|
|
4668
|
-
for (const chunkData of chunks) {
|
|
4669
|
-
if (onChunk !== void 0) {
|
|
4670
|
-
await onChunk(chunksetIdx, chunkIdx, chunkData);
|
|
4671
|
-
}
|
|
4672
|
-
chunkIdx += 1;
|
|
4673
|
-
}
|
|
4674
|
-
const a = await generateMerkleRoot(
|
|
4675
|
-
chunkRoots.map((a2) => Hex2.fromHexInput(a2))
|
|
4676
|
-
);
|
|
4677
|
-
const entry = {
|
|
4678
|
-
chunkset_root: a.toString(),
|
|
4679
|
-
chunk_commitments: chunkRoots.map(
|
|
4680
|
-
(chunk) => Hex2.fromHexInput(chunk).toString()
|
|
4681
|
-
)
|
|
4682
|
-
};
|
|
4683
|
-
return { h: a, entry };
|
|
4684
|
-
}
|
|
4685
|
-
async function generateCommitments(provider, fullData, onChunk, options) {
|
|
4686
|
-
const expectedChunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES;
|
|
4687
|
-
const shouldPad = options?.pad ?? true;
|
|
4688
|
-
const chunksetCommitments = [];
|
|
4689
|
-
const chunksetCommitmentHashes = [];
|
|
4690
|
-
let rawDataSize = 0;
|
|
4691
|
-
const chunksetGen = readInChunks(fullData, expectedChunksetSize);
|
|
4692
|
-
for await (const [chunksetIdx, chunksetData] of chunksetGen) {
|
|
4693
|
-
rawDataSize += chunksetData.length;
|
|
4694
|
-
const { h, entry } = await generateChunksetCommitments(
|
|
4695
|
-
shouldPad,
|
|
4696
|
-
chunksetIdx,
|
|
4697
|
-
chunksetData,
|
|
4698
|
-
expectedChunksetSize,
|
|
4699
|
-
provider,
|
|
4700
|
-
onChunk
|
|
4701
|
-
);
|
|
4702
|
-
chunksetCommitments.push(entry);
|
|
4703
|
-
chunksetCommitmentHashes.push(h);
|
|
4704
|
-
}
|
|
4705
|
-
if (rawDataSize === 0) {
|
|
4706
|
-
const zeroChunkset = new Uint8Array(expectedChunksetSize);
|
|
4707
|
-
const { h, entry } = await generateChunksetCommitments(
|
|
4708
|
-
shouldPad,
|
|
4709
|
-
0,
|
|
4710
|
-
zeroChunkset,
|
|
4711
|
-
expectedChunksetSize,
|
|
4712
|
-
provider,
|
|
4713
|
-
onChunk
|
|
4714
|
-
);
|
|
4715
|
-
chunksetCommitments.push(entry);
|
|
4716
|
-
chunksetCommitmentHashes.push(h);
|
|
4717
|
-
}
|
|
4718
|
-
return {
|
|
4719
|
-
schema_version: COMMITMENT_SCHEMA_VERSION,
|
|
4720
|
-
raw_data_size: rawDataSize,
|
|
4721
|
-
blob_merkle_root: (await generateMerkleRoot(chunksetCommitmentHashes)).toString(),
|
|
4722
|
-
chunkset_commitments: chunksetCommitments
|
|
4723
|
-
};
|
|
4724
|
-
}
|
|
4725
|
-
function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
|
|
4726
|
-
if (chunkset.byteLength !== expectedSize) {
|
|
4727
|
-
throw new Error(
|
|
4728
|
-
`Chunkset ${chunksetIdx} has size ${chunkset.byteLength} bytes but expected ${expectedSize} bytes. Enable padding or supply pre-padded data before calling generateCommitments.`
|
|
4729
|
-
);
|
|
4730
|
-
}
|
|
4731
|
-
return chunkset;
|
|
4785
|
+
return void 0;
|
|
4732
4786
|
}
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
Aptos,
|
|
4738
|
-
Hex as Hex3,
|
|
4739
|
-
U32
|
|
4740
|
-
} from "@aptos-labs/ts-sdk";
|
|
4741
|
-
var MissingTransactionSubmitterError = class extends Error {
|
|
4742
|
-
constructor() {
|
|
4743
|
-
super(
|
|
4744
|
-
"USD sponsorship (usdSponsor) requires a transaction submitter to be configured. The sponsored transaction is a multi-agent transaction that must be co-signed by the sponsor. Configure a transaction submitter via aptos.pluginSettings.TRANSACTION_SUBMITTER that routes transactions to a service (like a gas station) capable of providing the sponsor's signature."
|
|
4745
|
-
);
|
|
4746
|
-
this.name = "MissingTransactionSubmitterError";
|
|
4747
|
-
}
|
|
4748
|
-
};
|
|
4749
|
-
var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
4750
|
-
aptos;
|
|
4751
|
-
deployer;
|
|
4787
|
+
var ShelbyRPCClient = class {
|
|
4788
|
+
baseUrl;
|
|
4789
|
+
apiKey;
|
|
4790
|
+
rpcConfig;
|
|
4752
4791
|
indexer;
|
|
4753
|
-
defaultOptions;
|
|
4754
4792
|
/**
|
|
4755
|
-
*
|
|
4756
|
-
*
|
|
4793
|
+
* Creates a new ShelbyRPCClient for interacting with Shelby RPC nodes.
|
|
4794
|
+
* This client handles blob storage operations including upload and download.
|
|
4757
4795
|
*
|
|
4758
4796
|
* @param config - The client configuration object.
|
|
4759
4797
|
* @param config.network - The Shelby network to use.
|
|
4760
|
-
* @param defaultOptions - Optional default options for blob operations.
|
|
4761
4798
|
*
|
|
4762
4799
|
* @example
|
|
4763
4800
|
* ```typescript
|
|
4764
|
-
* const
|
|
4765
|
-
*
|
|
4766
|
-
*
|
|
4767
|
-
* clientConfig: {
|
|
4768
|
-
* API_KEY: "AG-***",
|
|
4769
|
-
* },
|
|
4770
|
-
* },
|
|
4801
|
+
* const client = new ShelbyRPCClient({
|
|
4802
|
+
* network: Network.SHELBYNET,
|
|
4803
|
+
* apiKey: "AG-***",
|
|
4771
4804
|
* });
|
|
4772
4805
|
* ```
|
|
4773
|
-
*
|
|
4774
|
-
* @example
|
|
4775
|
-
* ```typescript
|
|
4776
|
-
* // With default options for USD sponsorship
|
|
4777
|
-
* const blobClient = new ShelbyBlobClient(
|
|
4778
|
-
* {
|
|
4779
|
-
* network: Network.SHELBYNET,
|
|
4780
|
-
* aptos: {
|
|
4781
|
-
* pluginSettings: {
|
|
4782
|
-
* TRANSACTION_SUBMITTER: myGasStationSubmitter,
|
|
4783
|
-
* },
|
|
4784
|
-
* },
|
|
4785
|
-
* },
|
|
4786
|
-
* {
|
|
4787
|
-
* usdSponsor: { feePayerAddress: sponsorAddress },
|
|
4788
|
-
* }
|
|
4789
|
-
* );
|
|
4790
|
-
* ```
|
|
4791
4806
|
*/
|
|
4792
|
-
constructor(config
|
|
4793
|
-
this.
|
|
4794
|
-
this.
|
|
4807
|
+
constructor(config) {
|
|
4808
|
+
this.baseUrl = config.rpc?.baseUrl ?? NetworkToShelbyRPCBaseUrl.shelbynet;
|
|
4809
|
+
this.apiKey = config.apiKey ?? config.rpc?.apiKey;
|
|
4810
|
+
this.rpcConfig = config.rpc ?? {};
|
|
4795
4811
|
this.indexer = getShelbyIndexerClient(config);
|
|
4796
|
-
this.defaultOptions = defaultOptions ?? {};
|
|
4797
|
-
}
|
|
4798
|
-
/**
|
|
4799
|
-
* Merges method-level options with default options, giving precedence to method-level values.
|
|
4800
|
-
*/
|
|
4801
|
-
mergeOptions(options) {
|
|
4802
|
-
return {
|
|
4803
|
-
build: options?.build ?? this.defaultOptions.build,
|
|
4804
|
-
submit: options?.submit ?? this.defaultOptions.submit,
|
|
4805
|
-
usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
|
|
4806
|
-
chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes
|
|
4807
|
-
};
|
|
4808
4812
|
}
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4813
|
+
async #uploadPart(uploadId, partIdx, partData) {
|
|
4814
|
+
const nRetries = 5;
|
|
4815
|
+
let lastResponse;
|
|
4816
|
+
let lastError;
|
|
4817
|
+
const partUrl = buildRequestUrl(
|
|
4818
|
+
`/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
|
|
4819
|
+
this.baseUrl
|
|
4820
|
+
);
|
|
4821
|
+
for (let i = 0; i < nRetries; ++i) {
|
|
4822
|
+
try {
|
|
4823
|
+
lastResponse = await fetch(partUrl, {
|
|
4824
|
+
method: "PUT",
|
|
4825
|
+
headers: {
|
|
4826
|
+
"Content-Type": "application/octet-stream",
|
|
4827
|
+
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
4828
|
+
},
|
|
4829
|
+
body: partData
|
|
4830
|
+
});
|
|
4831
|
+
lastError = void 0;
|
|
4832
|
+
} catch (error) {
|
|
4833
|
+
lastError = error;
|
|
4834
|
+
if (i < nRetries - 1) {
|
|
4835
|
+
const delay = 2 ** i * 100;
|
|
4836
|
+
await sleep(delay);
|
|
4837
|
+
continue;
|
|
4838
|
+
}
|
|
4839
|
+
break;
|
|
4840
|
+
}
|
|
4841
|
+
if (lastResponse.ok) return;
|
|
4842
|
+
if (i < nRetries - 1) {
|
|
4843
|
+
const delay = 2 ** i * 100;
|
|
4844
|
+
await sleep(delay);
|
|
4845
|
+
}
|
|
4818
4846
|
}
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
throw new
|
|
4847
|
+
if (lastError !== void 0) {
|
|
4848
|
+
const errorCode = getErrorCode(lastError);
|
|
4849
|
+
const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
|
|
4850
|
+
throw new Error(
|
|
4851
|
+
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. The connection to the Shelby RPC endpoint was interrupted while sending data${errorCode ? ` (${errorCode})` : ""}. Endpoint: ${partUrl.toString()}, partBytes: ${partData.length}. Last error: ${errorMessage}`,
|
|
4852
|
+
{ cause: lastError }
|
|
4853
|
+
);
|
|
4823
4854
|
}
|
|
4855
|
+
const errorBody = await lastResponse?.text().catch(() => "");
|
|
4856
|
+
throw new Error(
|
|
4857
|
+
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. status: ${lastResponse?.status}, body: ${errorBody}`
|
|
4858
|
+
);
|
|
4824
4859
|
}
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4860
|
+
async #putBlobMultipart(account, blobName, blobData, totalBytes, partSize = 5 * 1024 * 1024, onProgress) {
|
|
4861
|
+
validateTotalBytes(totalBytes);
|
|
4862
|
+
const startResponse = await fetch(
|
|
4863
|
+
buildRequestUrl("/v1/multipart-uploads", this.baseUrl),
|
|
4864
|
+
{
|
|
4865
|
+
method: "POST",
|
|
4866
|
+
headers: {
|
|
4867
|
+
"Content-Type": "application/json",
|
|
4868
|
+
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
4869
|
+
},
|
|
4870
|
+
body: JSON.stringify({
|
|
4871
|
+
rawAccount: account.toString(),
|
|
4872
|
+
rawBlobName: blobName,
|
|
4873
|
+
rawPartSize: partSize
|
|
4874
|
+
})
|
|
4875
|
+
}
|
|
4876
|
+
);
|
|
4877
|
+
if (!startResponse.ok) {
|
|
4878
|
+
let errorBodyText = "Could not read error body";
|
|
4879
|
+
try {
|
|
4880
|
+
errorBodyText = await startResponse.text();
|
|
4881
|
+
} catch (_e) {
|
|
4882
|
+
}
|
|
4883
|
+
throw new Error(
|
|
4884
|
+
`Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
|
|
4885
|
+
);
|
|
4886
|
+
}
|
|
4887
|
+
const { uploadId } = StartMultipartUploadResponseSchema.parse(
|
|
4888
|
+
await startResponse.json()
|
|
4889
|
+
);
|
|
4890
|
+
const totalParts = Math.ceil(totalBytes / partSize);
|
|
4891
|
+
let uploadedBytes = 0;
|
|
4892
|
+
for await (const [partIdx, partData] of readInChunks(blobData, partSize)) {
|
|
4893
|
+
await this.#uploadPart(uploadId, partIdx, partData);
|
|
4894
|
+
uploadedBytes += partData.length;
|
|
4895
|
+
onProgress?.({
|
|
4896
|
+
phase: "uploading",
|
|
4897
|
+
partIdx,
|
|
4898
|
+
totalParts,
|
|
4899
|
+
partBytes: partData.length,
|
|
4900
|
+
uploadedBytes,
|
|
4901
|
+
totalBytes
|
|
4902
|
+
});
|
|
4903
|
+
}
|
|
4904
|
+
if (uploadedBytes !== totalBytes) {
|
|
4905
|
+
throw new Error(
|
|
4906
|
+
`Uploaded bytes (${uploadedBytes}) did not match declared totalBytes (${totalBytes})`
|
|
4907
|
+
);
|
|
4908
|
+
}
|
|
4909
|
+
const finalPartIdx = totalParts > 0 ? totalParts - 1 : 0;
|
|
4910
|
+
onProgress?.({
|
|
4911
|
+
phase: "finalizing",
|
|
4912
|
+
partIdx: finalPartIdx,
|
|
4913
|
+
totalParts,
|
|
4914
|
+
// no part uploaded in this phase
|
|
4915
|
+
partBytes: 0,
|
|
4916
|
+
uploadedBytes: totalBytes,
|
|
4917
|
+
totalBytes
|
|
4918
|
+
});
|
|
4919
|
+
const completeResponse = await fetch(
|
|
4920
|
+
buildRequestUrl(
|
|
4921
|
+
`/v1/multipart-uploads/${uploadId}/complete`,
|
|
4922
|
+
this.baseUrl
|
|
4923
|
+
),
|
|
4924
|
+
{
|
|
4925
|
+
method: "POST",
|
|
4926
|
+
headers: {
|
|
4927
|
+
"Content-Type": "application/json",
|
|
4928
|
+
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
4929
|
+
}
|
|
4930
|
+
}
|
|
4931
|
+
);
|
|
4932
|
+
if (!completeResponse.ok) {
|
|
4933
|
+
let errorBodyText = "Could not read error body";
|
|
4934
|
+
try {
|
|
4935
|
+
errorBodyText = await completeResponse.text();
|
|
4936
|
+
} catch (_e) {
|
|
4937
|
+
}
|
|
4938
|
+
throw new Error(
|
|
4939
|
+
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
4940
|
+
);
|
|
4941
|
+
}
|
|
4942
|
+
}
|
|
4943
|
+
/**
|
|
4944
|
+
* Uploads blob data to the Shelby RPC node for storage by storage providers.
|
|
4945
|
+
* This method should be called after blob commitments have been registered on the blockchain.
|
|
4946
|
+
* Uses multipart upload for efficient handling of large files.
|
|
4947
|
+
*
|
|
4948
|
+
* @param params.account - The account that owns the blob.
|
|
4949
|
+
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
4950
|
+
* @param params.blobData - The raw blob data as a Uint8Array or ReadableStream.
|
|
4951
|
+
* @param params.totalBytes - Total byte length. Required for streams; optional for Uint8Array.
|
|
4832
4952
|
*
|
|
4833
4953
|
* @example
|
|
4834
4954
|
* ```typescript
|
|
4835
|
-
* const
|
|
4836
|
-
*
|
|
4837
|
-
*
|
|
4955
|
+
* const blobData = new TextEncoder().encode("Hello, world!");
|
|
4956
|
+
*
|
|
4957
|
+
* await client.putBlob({
|
|
4958
|
+
* account: AccountAddress.from("0x1"),
|
|
4959
|
+
* blobName: "greetings/hello.txt",
|
|
4960
|
+
* blobData,
|
|
4838
4961
|
* });
|
|
4839
4962
|
* ```
|
|
4840
4963
|
*/
|
|
4841
|
-
async
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
createBlobKey({
|
|
4848
|
-
account: params.account,
|
|
4849
|
-
blobName: params.name
|
|
4850
|
-
})
|
|
4851
|
-
]
|
|
4852
|
-
}
|
|
4853
|
-
});
|
|
4854
|
-
if (!rawMetadata?.[0]?.vec?.[0]) {
|
|
4855
|
-
return void 0;
|
|
4856
|
-
}
|
|
4857
|
-
const metadata = rawMetadata[0].vec[0];
|
|
4858
|
-
let encoding;
|
|
4859
|
-
if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
|
|
4860
|
-
encoding = {
|
|
4861
|
-
variant: "clay",
|
|
4862
|
-
...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
|
|
4863
|
-
...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
|
|
4864
|
-
};
|
|
4865
|
-
} else {
|
|
4964
|
+
async putBlob(params) {
|
|
4965
|
+
BlobNameSchema.parse(params.blobName);
|
|
4966
|
+
let totalBytes;
|
|
4967
|
+
if (params.blobData instanceof Uint8Array) {
|
|
4968
|
+
totalBytes = params.totalBytes ?? params.blobData.length;
|
|
4969
|
+
if (totalBytes !== params.blobData.length) {
|
|
4866
4970
|
throw new Error(
|
|
4867
|
-
"
|
|
4971
|
+
"totalBytes must match blobData.length when blobData is a Uint8Array"
|
|
4868
4972
|
);
|
|
4869
4973
|
}
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
name: params.name,
|
|
4876
|
-
blobNameSuffix: getBlobNameSuffix(params.name),
|
|
4877
|
-
size: Number(metadata.blob_size),
|
|
4878
|
-
encoding,
|
|
4879
|
-
expirationMicros: Number(metadata.expiration_micros),
|
|
4880
|
-
creationMicros: Number(metadata.creation_micros),
|
|
4881
|
-
sliceAddress: AccountAddress2.fromString(metadata.slice.inner),
|
|
4882
|
-
isWritten: metadata.is_written
|
|
4883
|
-
};
|
|
4884
|
-
} catch (error) {
|
|
4885
|
-
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
4886
|
-
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
|
|
4887
|
-
return void 0;
|
|
4974
|
+
} else {
|
|
4975
|
+
if (params.totalBytes === void 0) {
|
|
4976
|
+
throw new Error(
|
|
4977
|
+
"totalBytes is required when blobData is a ReadableStream"
|
|
4978
|
+
);
|
|
4888
4979
|
}
|
|
4889
|
-
|
|
4980
|
+
totalBytes = params.totalBytes;
|
|
4890
4981
|
}
|
|
4982
|
+
validateTotalBytes(totalBytes);
|
|
4983
|
+
await this.#putBlobMultipart(
|
|
4984
|
+
params.account,
|
|
4985
|
+
params.blobName,
|
|
4986
|
+
params.blobData,
|
|
4987
|
+
totalBytes,
|
|
4988
|
+
void 0,
|
|
4989
|
+
params.onProgress
|
|
4990
|
+
);
|
|
4891
4991
|
}
|
|
4892
4992
|
/**
|
|
4893
|
-
*
|
|
4894
|
-
*
|
|
4993
|
+
* Downloads a blob from the Shelby RPC node.
|
|
4994
|
+
* Returns a streaming response with validation to ensure data integrity.
|
|
4895
4995
|
*
|
|
4896
|
-
* @param params.account - The account
|
|
4897
|
-
* @param params.
|
|
4898
|
-
* @param params.
|
|
4899
|
-
* @
|
|
4996
|
+
* @param params.account - The account that owns the blob.
|
|
4997
|
+
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
4998
|
+
* @param params.range - Optional byte range for partial downloads.
|
|
4999
|
+
* @param params.range.start - Starting byte position (inclusive).
|
|
5000
|
+
* @param params.range.end - Ending byte position (inclusive, optional).
|
|
5001
|
+
* @param params.micropayment - Optional micropayment to attach to the request.
|
|
5002
|
+
*
|
|
5003
|
+
* @returns A ShelbyBlob object containing the account, name, readable stream, and content length.
|
|
5004
|
+
*
|
|
5005
|
+
* @throws Error if the download fails or content length doesn't match.
|
|
5006
|
+
* @throws StaleChannelStateError if the micropayment is stale (server has newer state).
|
|
4900
5007
|
*
|
|
4901
5008
|
* @example
|
|
4902
5009
|
* ```typescript
|
|
4903
|
-
* //
|
|
4904
|
-
* const
|
|
4905
|
-
* account: AccountAddress.
|
|
5010
|
+
* // Download entire blob
|
|
5011
|
+
* const blob = await client.getBlob({
|
|
5012
|
+
* account: AccountAddress.from("0x1"),
|
|
5013
|
+
* blobName: "documents/report.pdf"
|
|
4906
5014
|
* });
|
|
4907
|
-
* ```
|
|
4908
|
-
*/
|
|
4909
|
-
getAccountBlobs(params) {
|
|
4910
|
-
const { where, ...rest } = params;
|
|
4911
|
-
return this.getBlobs({
|
|
4912
|
-
where: {
|
|
4913
|
-
...where,
|
|
4914
|
-
owner: { _eq: AccountAddress2.from(params.account).toString() }
|
|
4915
|
-
},
|
|
4916
|
-
pagination: rest.pagination,
|
|
4917
|
-
orderBy: rest.orderBy
|
|
4918
|
-
});
|
|
4919
|
-
}
|
|
4920
|
-
/**
|
|
4921
|
-
* Retrieves blobs and their metadata from the blockchain.
|
|
4922
5015
|
*
|
|
4923
|
-
*
|
|
4924
|
-
*
|
|
4925
|
-
*
|
|
4926
|
-
*
|
|
5016
|
+
* // Download partial content (bytes 100-199)
|
|
5017
|
+
* const partial = await client.getBlob({
|
|
5018
|
+
* account: AccountAddress.from("0x1"),
|
|
5019
|
+
* blobName: "large-file.bin",
|
|
5020
|
+
* range: { start: 100, end: 199 }
|
|
5021
|
+
* });
|
|
4927
5022
|
*
|
|
4928
|
-
*
|
|
4929
|
-
*
|
|
4930
|
-
*
|
|
4931
|
-
*
|
|
4932
|
-
*
|
|
5023
|
+
* // Download with micropayment
|
|
5024
|
+
* const blob = await client.getBlob({
|
|
5025
|
+
* account: AccountAddress.from("0x1"),
|
|
5026
|
+
* blobName: "documents/report.pdf",
|
|
5027
|
+
* micropayment: senderBuiltMicropayment
|
|
4933
5028
|
* });
|
|
4934
5029
|
* ```
|
|
4935
5030
|
*/
|
|
4936
|
-
async
|
|
4937
|
-
|
|
4938
|
-
const
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
};
|
|
4944
|
-
const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
|
|
4945
|
-
const { blobs } = await this.indexer.getBlobs({
|
|
4946
|
-
where: finalWhere,
|
|
4947
|
-
limit,
|
|
4948
|
-
offset,
|
|
4949
|
-
orderBy
|
|
4950
|
-
});
|
|
4951
|
-
return blobs.map(
|
|
4952
|
-
(blob) => ({
|
|
4953
|
-
owner: AccountAddress2.from(blob.owner),
|
|
4954
|
-
name: blob.blob_name,
|
|
4955
|
-
blobNameSuffix: getBlobNameSuffix(blob.blob_name),
|
|
4956
|
-
blobMerkleRoot: Hex3.fromHexInput(blob.blob_commitment).toUint8Array(),
|
|
4957
|
-
size: Number(blob.size),
|
|
4958
|
-
// TODO: Add encoding when supported in NCI
|
|
4959
|
-
encoding: {
|
|
4960
|
-
variant: "clay",
|
|
4961
|
-
...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
|
|
4962
|
-
...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
|
|
4963
|
-
},
|
|
4964
|
-
expirationMicros: Number(blob.expires_at),
|
|
4965
|
-
creationMicros: Number(blob.created_at),
|
|
4966
|
-
sliceAddress: AccountAddress2.from(blob.slice_address),
|
|
4967
|
-
isWritten: Boolean(Number(blob.is_written)),
|
|
4968
|
-
isDeleted: Boolean(Number(blob.is_deleted))
|
|
4969
|
-
})
|
|
5031
|
+
async getBlob(params) {
|
|
5032
|
+
BlobNameSchema.parse(params.blobName);
|
|
5033
|
+
const url = buildRequestUrl(
|
|
5034
|
+
`/v1/blobs/${params.account.toString()}/${encodeURIComponentKeepSlashes(
|
|
5035
|
+
params.blobName
|
|
5036
|
+
)}`,
|
|
5037
|
+
this.baseUrl
|
|
4970
5038
|
);
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
5039
|
+
const headers = new Headers();
|
|
5040
|
+
if (params.range !== void 0) {
|
|
5041
|
+
const { start, end } = params.range;
|
|
5042
|
+
if (end === void 0) {
|
|
5043
|
+
headers.set("Range", `bytes=${start}-`);
|
|
5044
|
+
} else {
|
|
5045
|
+
if (end < start) {
|
|
5046
|
+
throw new Error("Range end cannot be less than start.");
|
|
5047
|
+
}
|
|
5048
|
+
headers.set("Range", `bytes=${start}-${end}`);
|
|
5049
|
+
}
|
|
5050
|
+
}
|
|
5051
|
+
if (this.apiKey) {
|
|
5052
|
+
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
5053
|
+
}
|
|
5054
|
+
if (params.micropayment) {
|
|
5055
|
+
const bytes = params.micropayment.bcsToBytes();
|
|
5056
|
+
const binaryString = Array.from(
|
|
5057
|
+
bytes,
|
|
5058
|
+
(byte) => String.fromCharCode(byte)
|
|
5059
|
+
).join("");
|
|
5060
|
+
headers.set(MICROPAYMENT_HEADER, btoa(binaryString));
|
|
5061
|
+
}
|
|
5062
|
+
const response = await fetch(url, { headers });
|
|
5063
|
+
if (response.status === 409) {
|
|
5064
|
+
let json;
|
|
5065
|
+
try {
|
|
5066
|
+
json = await response.json();
|
|
5067
|
+
} catch {
|
|
5068
|
+
throw new Error(
|
|
5069
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
5070
|
+
);
|
|
5071
|
+
}
|
|
5072
|
+
const parseResult = StaleMicropaymentErrorResponseSchema.safeParse(json);
|
|
5073
|
+
if (!parseResult.success) {
|
|
5074
|
+
throw new Error(
|
|
5075
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
5076
|
+
);
|
|
5077
|
+
}
|
|
5078
|
+
const errorBody = parseResult.data;
|
|
5079
|
+
if (errorBody.storedMicropayment) {
|
|
5080
|
+
throw StaleChannelStateError.fromBase64(
|
|
5081
|
+
errorBody.storedMicropayment,
|
|
5082
|
+
errorBody.error
|
|
5083
|
+
);
|
|
5084
|
+
}
|
|
5085
|
+
throw new Error(
|
|
5086
|
+
errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
|
|
5087
|
+
);
|
|
5088
|
+
}
|
|
5089
|
+
if (!response.ok) {
|
|
5090
|
+
throw new Error(
|
|
5091
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
5092
|
+
);
|
|
5093
|
+
}
|
|
5094
|
+
if (!response.body) {
|
|
5095
|
+
throw new Error("Response body is null");
|
|
5096
|
+
}
|
|
5097
|
+
const contentLengthHeader = response.headers.get("content-length");
|
|
5098
|
+
if (contentLengthHeader === null) {
|
|
5099
|
+
throw new Error(
|
|
5100
|
+
"Response did not have content-length header, which is required"
|
|
5101
|
+
);
|
|
5102
|
+
}
|
|
5103
|
+
const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
|
|
5104
|
+
if (Number.isNaN(expectedContentLength)) {
|
|
5105
|
+
throw new Error(
|
|
5106
|
+
`Invalid content-length header received: ${contentLengthHeader}`
|
|
5107
|
+
);
|
|
5108
|
+
}
|
|
5109
|
+
const validatingStream = new ReadableStream({
|
|
5110
|
+
start(controller) {
|
|
5111
|
+
const maybeReader = response.body?.getReader();
|
|
5112
|
+
if (!maybeReader) {
|
|
5113
|
+
controller.error(new Error("Response body reader is unavailable"));
|
|
5114
|
+
return;
|
|
5115
|
+
}
|
|
5116
|
+
const reader = maybeReader;
|
|
5117
|
+
let bytesReceived = 0;
|
|
5118
|
+
function pump() {
|
|
5119
|
+
return reader.read().then(({ done, value }) => {
|
|
5120
|
+
if (done) {
|
|
5121
|
+
if (bytesReceived !== expectedContentLength) {
|
|
5122
|
+
controller.error(
|
|
5123
|
+
new Error(
|
|
5124
|
+
`Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
|
|
5125
|
+
)
|
|
5126
|
+
);
|
|
5127
|
+
return;
|
|
5128
|
+
}
|
|
5129
|
+
controller.close();
|
|
5130
|
+
return;
|
|
5131
|
+
}
|
|
5132
|
+
bytesReceived += value.byteLength;
|
|
5133
|
+
controller.enqueue(value);
|
|
5134
|
+
return pump();
|
|
5135
|
+
}).catch((error) => {
|
|
5136
|
+
controller.error(error);
|
|
5137
|
+
});
|
|
5138
|
+
}
|
|
5139
|
+
return pump();
|
|
5140
|
+
}
|
|
4980
5141
|
});
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
5142
|
+
return {
|
|
5143
|
+
account: normalizeAddress(params.account),
|
|
5144
|
+
name: params.blobName,
|
|
5145
|
+
readable: validatingStream,
|
|
5146
|
+
contentLength: expectedContentLength
|
|
4986
5147
|
};
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5148
|
+
}
|
|
5149
|
+
};
|
|
5150
|
+
|
|
5151
|
+
// ../../packages/sdk/dist/chunk-OGKZ575S.mjs
|
|
5152
|
+
import {
|
|
5153
|
+
createDecoder,
|
|
5154
|
+
createEncoder
|
|
5155
|
+
} from "@shelby-protocol/clay-codes";
|
|
5156
|
+
function getTotalChunks(config) {
|
|
5157
|
+
return config.erasure_n;
|
|
5158
|
+
}
|
|
5159
|
+
var ClayErasureCodingProvider = class _ClayErasureCodingProvider {
|
|
5160
|
+
config;
|
|
5161
|
+
encoderCache;
|
|
5162
|
+
decoderCache;
|
|
5163
|
+
lastFunction;
|
|
5164
|
+
constructor(config) {
|
|
5165
|
+
this.config = config;
|
|
5166
|
+
this.lastFunction = "none";
|
|
5003
5167
|
}
|
|
5004
5168
|
/**
|
|
5005
|
-
*
|
|
5006
|
-
*
|
|
5007
|
-
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5008
|
-
* @returns The total number of blobs.
|
|
5009
|
-
*
|
|
5010
|
-
* @example
|
|
5011
|
-
* ```typescript
|
|
5012
|
-
* const count = await client.getBlobsCount();
|
|
5013
|
-
* ```
|
|
5169
|
+
* Static factory method to create an initialized ClayErasureCodingProvider
|
|
5014
5170
|
*/
|
|
5015
|
-
async
|
|
5016
|
-
const
|
|
5017
|
-
|
|
5018
|
-
|
|
5171
|
+
static async create(config) {
|
|
5172
|
+
const provider = new _ClayErasureCodingProvider(config);
|
|
5173
|
+
[provider.encoderCache, provider.decoderCache] = await Promise.all([
|
|
5174
|
+
createEncoder({
|
|
5175
|
+
n: getTotalChunks(config),
|
|
5176
|
+
k: config.erasure_k,
|
|
5177
|
+
d: config.erasure_d,
|
|
5178
|
+
chunkSizeBytes: config.chunkSizeBytes
|
|
5179
|
+
}),
|
|
5180
|
+
createDecoder({
|
|
5181
|
+
n: getTotalChunks(config),
|
|
5182
|
+
k: config.erasure_k,
|
|
5183
|
+
d: config.erasure_d,
|
|
5184
|
+
chunkSizeBytes: config.chunkSizeBytes,
|
|
5185
|
+
erasedChunksMask: 0
|
|
5186
|
+
// No chunks erased initially; will be reconfigured on decode
|
|
5187
|
+
})
|
|
5188
|
+
]);
|
|
5189
|
+
return provider;
|
|
5190
|
+
}
|
|
5191
|
+
encode(data) {
|
|
5192
|
+
const { erasure_k, chunkSizeBytes } = this.config;
|
|
5193
|
+
if (!this.encoderCache) {
|
|
5194
|
+
throw new Error("Encoder cache is missing");
|
|
5195
|
+
}
|
|
5196
|
+
const systematicCapacity = erasure_k * chunkSizeBytes;
|
|
5197
|
+
if (data.byteLength > systematicCapacity) {
|
|
5198
|
+
throw new Error(
|
|
5199
|
+
`Data size ${data.byteLength} bytes exceeds systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}).`
|
|
5200
|
+
);
|
|
5201
|
+
}
|
|
5202
|
+
if (this.requiresPadding(data.length)) {
|
|
5203
|
+
throw new Error(
|
|
5204
|
+
`Data size ${data.length} bytes does not match systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}). Provide pre-padded data before encoding.`
|
|
5205
|
+
);
|
|
5206
|
+
}
|
|
5207
|
+
this.lastFunction = "encoded";
|
|
5208
|
+
return this.encoderCache.erasureCode(data);
|
|
5209
|
+
}
|
|
5210
|
+
decode(available, config) {
|
|
5211
|
+
if (!this.decoderCache) {
|
|
5212
|
+
throw new Error("Decoder cache is missing");
|
|
5213
|
+
}
|
|
5214
|
+
const { erasure_k, chunkSizeBytes } = this.config;
|
|
5215
|
+
if (available.length < erasure_k) {
|
|
5216
|
+
throw new Error(
|
|
5217
|
+
`Insufficient available chunks: need at least ${erasure_k}, received ${available.length}.`
|
|
5218
|
+
);
|
|
5219
|
+
}
|
|
5220
|
+
for (let i = 0; i < available.length; i++) {
|
|
5221
|
+
const chunk = available[i];
|
|
5222
|
+
if (chunk.length !== chunkSizeBytes) {
|
|
5223
|
+
throw new Error(
|
|
5224
|
+
`Chunk ${i} size ${chunk.length} bytes does not match expected chunkSizeBytes ${chunkSizeBytes}.`
|
|
5225
|
+
);
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
this.lastFunction = "decoded";
|
|
5229
|
+
return this.decoderCache.decode(available, config);
|
|
5230
|
+
}
|
|
5231
|
+
getChunkMerkleRoots() {
|
|
5232
|
+
if (this.decoderCache && this.lastFunction === "decoded")
|
|
5233
|
+
return this.decoderCache.getChunkMerkleRoots();
|
|
5234
|
+
if (this.encoderCache && this.lastFunction === "encoded")
|
|
5235
|
+
return this.encoderCache.getChunkMerkleRoots();
|
|
5236
|
+
throw new Error(
|
|
5237
|
+
"You must call encode or decode before calling getChunkMerkleRoots"
|
|
5238
|
+
);
|
|
5019
5239
|
}
|
|
5020
5240
|
/**
|
|
5021
|
-
*
|
|
5241
|
+
* Determines if data can be erasure coded as-is or requires padding.
|
|
5022
5242
|
*
|
|
5023
|
-
*
|
|
5024
|
-
*
|
|
5243
|
+
* Data can be erasure coded without padding if its size exactly matches
|
|
5244
|
+
* the total systematic data capacity (k * chunkSizeBytes).
|
|
5025
5245
|
*
|
|
5026
|
-
* @
|
|
5027
|
-
*
|
|
5028
|
-
* const count = await client.getBlobActivitiesCount();
|
|
5029
|
-
* ```
|
|
5246
|
+
* @param dataSize - Size of the data in bytes
|
|
5247
|
+
* @returns true if data needs padding, false if it can be coded as-is
|
|
5030
5248
|
*/
|
|
5031
|
-
|
|
5032
|
-
const {
|
|
5033
|
-
const
|
|
5034
|
-
return
|
|
5249
|
+
requiresPadding(dataSize) {
|
|
5250
|
+
const { erasure_k, chunkSizeBytes } = this.config;
|
|
5251
|
+
const systematicCapacity = erasure_k * chunkSizeBytes;
|
|
5252
|
+
return dataSize !== systematicCapacity;
|
|
5035
5253
|
}
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
* blobName: "foo/bar.txt",
|
|
5058
|
-
* blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
5059
|
-
* size: data.length,
|
|
5060
|
-
* expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
|
|
5061
|
-
* });
|
|
5062
|
-
* ```
|
|
5063
|
-
*/
|
|
5064
|
-
async registerBlob(params) {
|
|
5065
|
-
const options = this.mergeOptions(params.options);
|
|
5066
|
-
this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
|
|
5067
|
-
const chunksetSize = options.chunksetSizeBytes ?? DEFAULT_CHUNKSET_SIZE_BYTES;
|
|
5068
|
-
const buildArgs = {
|
|
5069
|
-
...options.build,
|
|
5070
|
-
data: _ShelbyBlobClient.createRegisterBlobPayload({
|
|
5071
|
-
deployer: this.deployer,
|
|
5072
|
-
account: params.account.accountAddress,
|
|
5073
|
-
blobName: params.blobName,
|
|
5074
|
-
blobSize: params.size,
|
|
5075
|
-
blobMerkleRoot: params.blobMerkleRoot,
|
|
5076
|
-
numChunksets: expectedTotalChunksets(params.size, chunksetSize),
|
|
5077
|
-
expirationMicros: params.expirationMicros,
|
|
5078
|
-
useSponsoredUsdVariant: options.usdSponsor !== void 0
|
|
5079
|
-
}),
|
|
5080
|
-
sender: params.account.accountAddress
|
|
5081
|
-
};
|
|
5082
|
-
const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
|
|
5083
|
-
...buildArgs,
|
|
5084
|
-
secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
|
|
5085
|
-
}) : await this.aptos.transaction.build.simple(buildArgs);
|
|
5086
|
-
return {
|
|
5087
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5088
|
-
signer: params.account,
|
|
5089
|
-
transaction,
|
|
5090
|
-
...options.submit
|
|
5091
|
-
})
|
|
5092
|
-
};
|
|
5254
|
+
};
|
|
5255
|
+
|
|
5256
|
+
// ../../packages/sdk/dist/chunk-JTXYKO3U.mjs
|
|
5257
|
+
var CHUNK_SIZE_PARAMS = {
|
|
5258
|
+
[
|
|
5259
|
+
"ChunkSet10MiB_Chunk1MiB"
|
|
5260
|
+
/* ChunkSet10MiB_Chunk1MiB */
|
|
5261
|
+
]: {
|
|
5262
|
+
// 1MiB
|
|
5263
|
+
chunkSizeBytes: 1 * 1024 * 1024,
|
|
5264
|
+
// 10MiB
|
|
5265
|
+
chunksetSizeBytes: 10 * 1024 * 1024
|
|
5266
|
+
},
|
|
5267
|
+
[
|
|
5268
|
+
"ChunkSet2MiB_Chunk1MiB"
|
|
5269
|
+
/* ChunkSet2MiB_Chunk1MiB */
|
|
5270
|
+
]: {
|
|
5271
|
+
// 1MiB
|
|
5272
|
+
chunkSizeBytes: 1 * 1024 * 1024,
|
|
5273
|
+
// 2MiB
|
|
5274
|
+
chunksetSizeBytes: 2 * 1024 * 1024
|
|
5093
5275
|
}
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
data: _ShelbyBlobClient.createDeleteBlobPayload({
|
|
5116
|
-
deployer: this.deployer,
|
|
5117
|
-
blobName: params.blobName
|
|
5118
|
-
}),
|
|
5119
|
-
sender: params.account.accountAddress
|
|
5120
|
-
});
|
|
5121
|
-
return {
|
|
5122
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5123
|
-
signer: params.account,
|
|
5124
|
-
transaction
|
|
5125
|
-
})
|
|
5126
|
-
};
|
|
5276
|
+
};
|
|
5277
|
+
var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
5278
|
+
"ChunkSet10MiB_Chunk1MiB"
|
|
5279
|
+
/* ChunkSet10MiB_Chunk1MiB */
|
|
5280
|
+
].chunkSizeBytes;
|
|
5281
|
+
var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
5282
|
+
"ChunkSet10MiB_Chunk1MiB"
|
|
5283
|
+
/* ChunkSet10MiB_Chunk1MiB */
|
|
5284
|
+
].chunksetSizeBytes;
|
|
5285
|
+
var ERASURE_CODE_AND_CHUNK_MAPPING = {
|
|
5286
|
+
[
|
|
5287
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
5288
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
5289
|
+
]: {
|
|
5290
|
+
...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
|
|
5291
|
+
},
|
|
5292
|
+
[
|
|
5293
|
+
"ClayCode_4Total_2Data_3Helper"
|
|
5294
|
+
/* ClayCode_4Total_2Data_3Helper */
|
|
5295
|
+
]: {
|
|
5296
|
+
...CHUNK_SIZE_PARAMS.ChunkSet2MiB_Chunk1MiB
|
|
5127
5297
|
}
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
...params.options,
|
|
5158
|
-
data: _ShelbyBlobClient.createDeleteMultipleBlobsPayload({
|
|
5159
|
-
deployer: this.deployer,
|
|
5160
|
-
blobNames: params.blobNames
|
|
5161
|
-
}),
|
|
5162
|
-
sender: params.account.accountAddress
|
|
5163
|
-
});
|
|
5164
|
-
return {
|
|
5165
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5166
|
-
signer: params.account,
|
|
5167
|
-
transaction
|
|
5168
|
-
})
|
|
5169
|
-
};
|
|
5298
|
+
};
|
|
5299
|
+
|
|
5300
|
+
// ../../packages/sdk/dist/chunk-AUQDI5BS.mjs
|
|
5301
|
+
var ERASURE_CODE_PARAMS = {
|
|
5302
|
+
[
|
|
5303
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
5304
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
5305
|
+
]: {
|
|
5306
|
+
// total chunks (data + parity)
|
|
5307
|
+
erasure_n: 16,
|
|
5308
|
+
// data chunks
|
|
5309
|
+
erasure_k: 10,
|
|
5310
|
+
// helper nodes
|
|
5311
|
+
erasure_d: 13,
|
|
5312
|
+
// enum index
|
|
5313
|
+
enumIndex: 0
|
|
5314
|
+
},
|
|
5315
|
+
[
|
|
5316
|
+
"ClayCode_4Total_2Data_3Helper"
|
|
5317
|
+
/* ClayCode_4Total_2Data_3Helper */
|
|
5318
|
+
]: {
|
|
5319
|
+
// total chunks (data + parity)
|
|
5320
|
+
erasure_n: 4,
|
|
5321
|
+
// data chunks
|
|
5322
|
+
erasure_k: 2,
|
|
5323
|
+
// helper nodes
|
|
5324
|
+
erasure_d: 3,
|
|
5325
|
+
// enum index
|
|
5326
|
+
enumIndex: 1
|
|
5170
5327
|
}
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
*/
|
|
5196
|
-
async addChunksetAcknowledgements(params) {
|
|
5197
|
-
const transaction = await this.aptos.transaction.build.simple({
|
|
5198
|
-
...params.options?.build,
|
|
5199
|
-
data: _ShelbyBlobClient.createChunksetAcknowledgementsPayload({
|
|
5200
|
-
blobOwner: params.blobOwner,
|
|
5201
|
-
blobName: params.blobName,
|
|
5202
|
-
creationMicros: params.creationMicros,
|
|
5203
|
-
chunksetIdx: params.chunksetIdx,
|
|
5204
|
-
storageProviderAcks: params.storageProviderAcks
|
|
5205
|
-
}),
|
|
5206
|
-
sender: params.account.accountAddress
|
|
5207
|
-
});
|
|
5208
|
-
return {
|
|
5209
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5210
|
-
signer: params.account,
|
|
5211
|
-
transaction
|
|
5212
|
-
})
|
|
5213
|
-
};
|
|
5328
|
+
};
|
|
5329
|
+
var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS[
|
|
5330
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
5331
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
5332
|
+
].erasure_n;
|
|
5333
|
+
var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS[
|
|
5334
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
5335
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
5336
|
+
].erasure_k;
|
|
5337
|
+
var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS[
|
|
5338
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
5339
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
5340
|
+
].erasure_d;
|
|
5341
|
+
var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
|
|
5342
|
+
|
|
5343
|
+
// ../../packages/sdk/dist/chunk-HPPMI7DC.mjs
|
|
5344
|
+
function defaultErasureCodingConfig() {
|
|
5345
|
+
console.log(
|
|
5346
|
+
`default erasure coding, with env: ${process.env.SHELBY_ENCODING}`
|
|
5347
|
+
);
|
|
5348
|
+
const encoding = Number(process.env.SHELBY_ENCODING) || 0;
|
|
5349
|
+
if (encoding === 0) {
|
|
5350
|
+
console.log("getting default erasure coding (16,10,13)");
|
|
5351
|
+
return erasureCodingConfig16Total10Data13Helper();
|
|
5214
5352
|
}
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
blobSize: blob.blobSize,
|
|
5262
|
-
blobMerkleRoot: blob.blobMerkleRoot,
|
|
5263
|
-
numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
|
|
5264
|
-
})),
|
|
5265
|
-
useSponsoredUsdVariant: options.usdSponsor !== void 0
|
|
5266
|
-
})
|
|
5267
|
-
};
|
|
5268
|
-
const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
|
|
5269
|
-
...buildArgs,
|
|
5270
|
-
secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
|
|
5271
|
-
}) : await this.aptos.transaction.build.simple(buildArgs);
|
|
5272
|
-
return {
|
|
5273
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5274
|
-
signer: params.account,
|
|
5275
|
-
transaction,
|
|
5276
|
-
...options.submit
|
|
5277
|
-
})
|
|
5278
|
-
};
|
|
5353
|
+
console.log("getting default erasure coding (4,2,3)");
|
|
5354
|
+
return erasureCodingConfig4Total2Data3Helper();
|
|
5355
|
+
}
|
|
5356
|
+
function erasureCodingConfig16Total10Data13Helper() {
|
|
5357
|
+
return erasureCodingConfig(
|
|
5358
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
5359
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
5360
|
+
);
|
|
5361
|
+
}
|
|
5362
|
+
function erasureCodingConfig4Total2Data3Helper() {
|
|
5363
|
+
return erasureCodingConfig(
|
|
5364
|
+
"ClayCode_4Total_2Data_3Helper"
|
|
5365
|
+
/* ClayCode_4Total_2Data_3Helper */
|
|
5366
|
+
);
|
|
5367
|
+
}
|
|
5368
|
+
function erasureCodingConfig(encodingScheme) {
|
|
5369
|
+
return {
|
|
5370
|
+
erasure_n: ERASURE_CODE_PARAMS[encodingScheme].erasure_n,
|
|
5371
|
+
erasure_k: ERASURE_CODE_PARAMS[encodingScheme].erasure_k,
|
|
5372
|
+
erasure_d: ERASURE_CODE_PARAMS[encodingScheme].erasure_d,
|
|
5373
|
+
chunkSizeBytes: DEFAULT_CHUNK_SIZE_BYTES,
|
|
5374
|
+
enumIndex: ERASURE_CODE_PARAMS[encodingScheme].enumIndex
|
|
5375
|
+
};
|
|
5376
|
+
}
|
|
5377
|
+
|
|
5378
|
+
// ../../packages/sdk/dist/chunk-3NRBHSMQ.mjs
|
|
5379
|
+
var createBlobKey = (params) => {
|
|
5380
|
+
return `@${normalizeAddress(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
|
|
5381
|
+
};
|
|
5382
|
+
|
|
5383
|
+
// ../../packages/sdk/dist/chunk-BXEVML7N.mjs
|
|
5384
|
+
import { Hex as Hex3 } from "@aptos-labs/ts-sdk";
|
|
5385
|
+
import { z as z3 } from "zod";
|
|
5386
|
+
var COMMITMENT_SCHEMA_VERSION = "1.3";
|
|
5387
|
+
var ChunksetCommitmentSchema = z3.object({
|
|
5388
|
+
// Chunkset root (vector commitment of child chunks)
|
|
5389
|
+
chunkset_root: z3.string(),
|
|
5390
|
+
// the size is known statically from the current configuration
|
|
5391
|
+
chunk_commitments: z3.array(z3.string())
|
|
5392
|
+
}).refine(
|
|
5393
|
+
(data) => {
|
|
5394
|
+
return data.chunk_commitments.length === DEFAULT_ERASURE_K + DEFAULT_ERASURE_M;
|
|
5395
|
+
},
|
|
5396
|
+
{
|
|
5397
|
+
message: `Chunkset must have exactly ${DEFAULT_ERASURE_K + DEFAULT_ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${DEFAULT_ERASURE_K} + ${DEFAULT_ERASURE_M})`,
|
|
5398
|
+
path: ["chunk_commitments"]
|
|
5279
5399
|
}
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5285
|
-
* @param params.account - The account that will own the blob.
|
|
5286
|
-
* @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
5287
|
-
* @param params.blobSize - The size of the blob in bytes.
|
|
5288
|
-
* @param params.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
5289
|
-
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
5290
|
-
* @param params.numChunksets - The total number of chunksets in the blob.
|
|
5291
|
-
*
|
|
5292
|
-
* @returns An Aptos transaction payload data object for the register_blob Move function.
|
|
5293
|
-
*
|
|
5294
|
-
* @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
|
|
5295
|
-
*/
|
|
5296
|
-
static createRegisterBlobPayload(params) {
|
|
5297
|
-
const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
|
|
5298
|
-
return {
|
|
5299
|
-
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
|
|
5300
|
-
functionArguments: [
|
|
5301
|
-
params.blobName,
|
|
5302
|
-
params.expirationMicros,
|
|
5303
|
-
Hex3.fromHexString(params.blobMerkleRoot).toUint8Array(),
|
|
5304
|
-
params.numChunksets,
|
|
5305
|
-
params.blobSize,
|
|
5306
|
-
// TODO
|
|
5307
|
-
0,
|
|
5308
|
-
// payment tier
|
|
5309
|
-
0
|
|
5310
|
-
// encoding
|
|
5311
|
-
]
|
|
5312
|
-
};
|
|
5400
|
+
);
|
|
5401
|
+
function expectedTotalChunksets(rawSize, chunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES) {
|
|
5402
|
+
if (chunksetSize <= 0) {
|
|
5403
|
+
throw new Error("chunksetSize must be positive");
|
|
5313
5404
|
}
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5405
|
+
if (rawSize === 0) return 1;
|
|
5406
|
+
return Math.ceil(rawSize / chunksetSize);
|
|
5407
|
+
}
|
|
5408
|
+
var BlobCommitmentsSchema = z3.object({
|
|
5409
|
+
schema_version: z3.string(),
|
|
5410
|
+
raw_data_size: z3.number(),
|
|
5411
|
+
// FIXME I am not sure about this being here, or if it should be somewhere else
|
|
5412
|
+
blob_merkle_root: z3.string(),
|
|
5413
|
+
chunkset_commitments: z3.array(ChunksetCommitmentSchema)
|
|
5414
|
+
}).refine(
|
|
5415
|
+
(data) => {
|
|
5416
|
+
return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
|
|
5417
|
+
},
|
|
5418
|
+
{
|
|
5419
|
+
message: "Total chunkset count mismatches with raw data size",
|
|
5420
|
+
// FIXME put more details in here
|
|
5421
|
+
path: ["chunkset_commitments"]
|
|
5422
|
+
}
|
|
5423
|
+
);
|
|
5424
|
+
async function generateMerkleRoot(leafHashes) {
|
|
5425
|
+
if (!leafHashes.length) {
|
|
5426
|
+
throw new Error(
|
|
5427
|
+
"An empty array cannot be used to construct a Merkle tree."
|
|
5428
|
+
);
|
|
5429
|
+
}
|
|
5430
|
+
const zeroArray = new Uint8Array(leafHashes[0].toUint8Array().length);
|
|
5431
|
+
const zeroBytes = Hex3.fromHexInput(zeroArray);
|
|
5432
|
+
let currentLeaves = leafHashes;
|
|
5433
|
+
while (currentLeaves.length > 1) {
|
|
5434
|
+
if (currentLeaves.length % 2 !== 0) {
|
|
5435
|
+
currentLeaves.push(zeroBytes);
|
|
5436
|
+
}
|
|
5437
|
+
const nextLeaves = [];
|
|
5438
|
+
for (let i = 0; i < currentLeaves.length; i += 2) {
|
|
5439
|
+
nextLeaves.push(
|
|
5440
|
+
await concatHashes([
|
|
5441
|
+
currentLeaves[i].toUint8Array(),
|
|
5442
|
+
currentLeaves[i + 1].toUint8Array()
|
|
5443
|
+
])
|
|
5341
5444
|
);
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
});
|
|
5345
|
-
return {
|
|
5346
|
-
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
|
|
5347
|
-
functionArguments: [
|
|
5348
|
-
blobNames,
|
|
5349
|
-
params.expirationMicros,
|
|
5350
|
-
blobMerkleRoots,
|
|
5351
|
-
blobNumChunksets,
|
|
5352
|
-
blobSizes,
|
|
5353
|
-
// TODO
|
|
5354
|
-
0,
|
|
5355
|
-
0
|
|
5356
|
-
]
|
|
5357
|
-
};
|
|
5445
|
+
}
|
|
5446
|
+
currentLeaves = nextLeaves;
|
|
5358
5447
|
}
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
functionArguments: [params.blobName]
|
|
5374
|
-
};
|
|
5448
|
+
return currentLeaves[0];
|
|
5449
|
+
}
|
|
5450
|
+
async function generateChunksetCommitments(shouldPad, chunksetIdx, chunksetData, expectedChunksetSize, provider, onChunk) {
|
|
5451
|
+
const { erasure_n } = provider.config;
|
|
5452
|
+
const chunksetPayload = shouldPad ? zeroPadBytes(chunksetData, expectedChunksetSize) : validatePrePaddedChunkset(
|
|
5453
|
+
chunksetData,
|
|
5454
|
+
expectedChunksetSize,
|
|
5455
|
+
chunksetIdx
|
|
5456
|
+
);
|
|
5457
|
+
const { chunks } = provider.encode(chunksetPayload);
|
|
5458
|
+
if (chunks.length !== erasure_n) {
|
|
5459
|
+
throw new Error(
|
|
5460
|
+
`Erasure provider produced ${chunks.length} chunks, expected ${erasure_n}.`
|
|
5461
|
+
);
|
|
5375
5462
|
}
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
*
|
|
5384
|
-
* This operation is atomic: if any blob deletion fails (e.g., blob not found),
|
|
5385
|
-
* the entire transaction fails and no blobs are deleted.
|
|
5386
|
-
*
|
|
5387
|
-
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5388
|
-
* @param params.blobNames - Array of blob name suffixes without the account address prefix
|
|
5389
|
-
* (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
|
|
5390
|
-
* prefix is automatically derived from the transaction sender.
|
|
5391
|
-
*
|
|
5392
|
-
* @returns An Aptos transaction payload data object for the delete_multiple_blobs Move function.
|
|
5393
|
-
*
|
|
5394
|
-
* @see https://github.com/shelby/shelby/blob/main/move/shelby_contract/sources/blob_metadata.move
|
|
5395
|
-
*/
|
|
5396
|
-
static createDeleteMultipleBlobsPayload(params) {
|
|
5397
|
-
return {
|
|
5398
|
-
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_blobs`,
|
|
5399
|
-
functionArguments: [params.blobNames]
|
|
5400
|
-
};
|
|
5463
|
+
const chunkRoots = provider.getChunkMerkleRoots();
|
|
5464
|
+
let chunkIdx = 0;
|
|
5465
|
+
for (const chunkData of chunks) {
|
|
5466
|
+
if (onChunk !== void 0) {
|
|
5467
|
+
await onChunk(chunksetIdx, chunkIdx, chunkData);
|
|
5468
|
+
}
|
|
5469
|
+
chunkIdx += 1;
|
|
5401
5470
|
}
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5471
|
+
const a = await generateMerkleRoot(
|
|
5472
|
+
chunkRoots.map((a2) => Hex3.fromHexInput(a2))
|
|
5473
|
+
);
|
|
5474
|
+
const entry = {
|
|
5475
|
+
chunkset_root: a.toString(),
|
|
5476
|
+
chunk_commitments: chunkRoots.map(
|
|
5477
|
+
(chunk) => Hex3.fromHexInput(chunk).toString()
|
|
5478
|
+
)
|
|
5479
|
+
};
|
|
5480
|
+
return { h: a, entry };
|
|
5481
|
+
}
|
|
5482
|
+
async function generateCommitments(provider, fullData, onChunk, options) {
|
|
5483
|
+
const expectedChunksetSize = provider.config.chunkSizeBytes * provider.config.erasure_k;
|
|
5484
|
+
const shouldPad = options?.pad ?? true;
|
|
5485
|
+
const chunksetCommitments = [];
|
|
5486
|
+
const chunksetCommitmentHashes = [];
|
|
5487
|
+
let rawDataSize = 0;
|
|
5488
|
+
const chunksetGen = readInChunks(fullData, expectedChunksetSize);
|
|
5489
|
+
for await (const [chunksetIdx, chunksetData] of chunksetGen) {
|
|
5490
|
+
rawDataSize += chunksetData.length;
|
|
5491
|
+
const { h, entry } = await generateChunksetCommitments(
|
|
5492
|
+
shouldPad,
|
|
5493
|
+
chunksetIdx,
|
|
5494
|
+
chunksetData,
|
|
5495
|
+
expectedChunksetSize,
|
|
5496
|
+
provider,
|
|
5497
|
+
onChunk
|
|
5406
5498
|
);
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
functionArguments: [
|
|
5410
|
-
createBlobKey({
|
|
5411
|
-
account: params.blobOwner,
|
|
5412
|
-
blobName: params.blobName
|
|
5413
|
-
}),
|
|
5414
|
-
params.chunksetIdx,
|
|
5415
|
-
params.creationMicros,
|
|
5416
|
-
new U32(Number(ackBitMask)),
|
|
5417
|
-
params.storageProviderAcks.map((ack) => ack.signature)
|
|
5418
|
-
]
|
|
5419
|
-
};
|
|
5499
|
+
chunksetCommitments.push(entry);
|
|
5500
|
+
chunksetCommitmentHashes.push(h);
|
|
5420
5501
|
}
|
|
5421
|
-
|
|
5502
|
+
if (rawDataSize === 0) {
|
|
5503
|
+
const zeroChunkset = new Uint8Array(expectedChunksetSize);
|
|
5504
|
+
const { h, entry } = await generateChunksetCommitments(
|
|
5505
|
+
shouldPad,
|
|
5506
|
+
0,
|
|
5507
|
+
zeroChunkset,
|
|
5508
|
+
expectedChunksetSize,
|
|
5509
|
+
provider,
|
|
5510
|
+
onChunk
|
|
5511
|
+
);
|
|
5512
|
+
chunksetCommitments.push(entry);
|
|
5513
|
+
chunksetCommitmentHashes.push(h);
|
|
5514
|
+
}
|
|
5515
|
+
return {
|
|
5516
|
+
schema_version: COMMITMENT_SCHEMA_VERSION,
|
|
5517
|
+
raw_data_size: rawDataSize,
|
|
5518
|
+
blob_merkle_root: (await generateMerkleRoot(chunksetCommitmentHashes)).toString(),
|
|
5519
|
+
chunkset_commitments: chunksetCommitments
|
|
5520
|
+
};
|
|
5521
|
+
}
|
|
5522
|
+
function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
|
|
5523
|
+
if (chunkset.byteLength !== expectedSize) {
|
|
5524
|
+
throw new Error(
|
|
5525
|
+
`Chunkset ${chunksetIdx} has size ${chunkset.byteLength} bytes but expected ${expectedSize} bytes. Enable padding or supply pre-padded data before calling generateCommitments.`
|
|
5526
|
+
);
|
|
5527
|
+
}
|
|
5528
|
+
return chunkset;
|
|
5529
|
+
}
|
|
5422
5530
|
|
|
5423
|
-
// ../../packages/sdk/dist/chunk-
|
|
5531
|
+
// ../../packages/sdk/dist/chunk-IBAUPQOF.mjs
|
|
5424
5532
|
import {
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
constructor(config) {
|
|
5437
|
-
this.config = config;
|
|
5438
|
-
this.lastFunction = "none";
|
|
5533
|
+
AccountAddress as AccountAddress3,
|
|
5534
|
+
Aptos,
|
|
5535
|
+
Hex as Hex4,
|
|
5536
|
+
U32
|
|
5537
|
+
} from "@aptos-labs/ts-sdk";
|
|
5538
|
+
var MissingTransactionSubmitterError = class extends Error {
|
|
5539
|
+
constructor() {
|
|
5540
|
+
super(
|
|
5541
|
+
"USD sponsorship (usdSponsor) requires a transaction submitter to be configured. The sponsored transaction is a multi-agent transaction that must be co-signed by the sponsor. Configure a transaction submitter via aptos.pluginSettings.TRANSACTION_SUBMITTER that routes transactions to a service (like a gas station) capable of providing the sponsor's signature."
|
|
5542
|
+
);
|
|
5543
|
+
this.name = "MissingTransactionSubmitterError";
|
|
5439
5544
|
}
|
|
5545
|
+
};
|
|
5546
|
+
var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
5547
|
+
aptos;
|
|
5548
|
+
deployer;
|
|
5549
|
+
indexer;
|
|
5550
|
+
defaultOptions;
|
|
5440
5551
|
/**
|
|
5441
|
-
*
|
|
5552
|
+
* The ShelbyBlobClient is used to interact with the Shelby contract on the Aptos blockchain. This
|
|
5553
|
+
* includes functions for registering blob commitments and retrieving blob metadata.
|
|
5554
|
+
*
|
|
5555
|
+
* @param config - The client configuration object.
|
|
5556
|
+
* @param config.network - The Shelby network to use.
|
|
5557
|
+
* @param defaultOptions - Optional default options for blob operations.
|
|
5558
|
+
*
|
|
5559
|
+
* @example
|
|
5560
|
+
* ```typescript
|
|
5561
|
+
* const blobClient = new ShelbyBlobClient({
|
|
5562
|
+
* aptos: {
|
|
5563
|
+
* network: Network.SHELBYNET,
|
|
5564
|
+
* clientConfig: {
|
|
5565
|
+
* API_KEY: "AG-***",
|
|
5566
|
+
* },
|
|
5567
|
+
* },
|
|
5568
|
+
* });
|
|
5569
|
+
* ```
|
|
5570
|
+
*
|
|
5571
|
+
* @example
|
|
5572
|
+
* ```typescript
|
|
5573
|
+
* // With default options for USD sponsorship
|
|
5574
|
+
* const blobClient = new ShelbyBlobClient(
|
|
5575
|
+
* {
|
|
5576
|
+
* network: Network.SHELBYNET,
|
|
5577
|
+
* aptos: {
|
|
5578
|
+
* pluginSettings: {
|
|
5579
|
+
* TRANSACTION_SUBMITTER: myGasStationSubmitter,
|
|
5580
|
+
* },
|
|
5581
|
+
* },
|
|
5582
|
+
* },
|
|
5583
|
+
* {
|
|
5584
|
+
* usdSponsor: { feePayerAddress: sponsorAddress },
|
|
5585
|
+
* }
|
|
5586
|
+
* );
|
|
5587
|
+
* ```
|
|
5442
5588
|
*/
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
chunkSizeBytes: options?.chunkSizeBytes ?? DEFAULT_CHUNK_SIZE_BYTES
|
|
5449
|
-
});
|
|
5450
|
-
const provider = new _ClayErasureCodingProvider(config);
|
|
5451
|
-
[provider.encoderCache, provider.decoderCache] = await Promise.all([
|
|
5452
|
-
createEncoder({
|
|
5453
|
-
n: getTotalChunks(config),
|
|
5454
|
-
k: config.erasure_k,
|
|
5455
|
-
d: config.erasure_d,
|
|
5456
|
-
chunkSizeBytes: config.chunkSizeBytes
|
|
5457
|
-
}),
|
|
5458
|
-
createDecoder({
|
|
5459
|
-
n: getTotalChunks(config),
|
|
5460
|
-
k: config.erasure_k,
|
|
5461
|
-
d: config.erasure_d,
|
|
5462
|
-
chunkSizeBytes: config.chunkSizeBytes,
|
|
5463
|
-
erasedChunksMask: 0
|
|
5464
|
-
// No chunks erased initially; will be reconfigured on decode
|
|
5465
|
-
})
|
|
5466
|
-
]);
|
|
5467
|
-
return provider;
|
|
5468
|
-
}
|
|
5469
|
-
encode(data) {
|
|
5470
|
-
const { erasure_k, chunkSizeBytes } = this.config;
|
|
5471
|
-
if (!this.encoderCache) {
|
|
5472
|
-
throw new Error("Encoder cache is missing");
|
|
5473
|
-
}
|
|
5474
|
-
const systematicCapacity = erasure_k * chunkSizeBytes;
|
|
5475
|
-
if (data.byteLength > systematicCapacity) {
|
|
5476
|
-
throw new Error(
|
|
5477
|
-
`Data size ${data.byteLength} bytes exceeds systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}).`
|
|
5478
|
-
);
|
|
5479
|
-
}
|
|
5480
|
-
if (this.requiresPadding(data.length)) {
|
|
5481
|
-
throw new Error(
|
|
5482
|
-
`Data size ${data.length} bytes does not match systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}). Provide pre-padded data before encoding.`
|
|
5483
|
-
);
|
|
5484
|
-
}
|
|
5485
|
-
this.lastFunction = "encoded";
|
|
5486
|
-
return this.encoderCache.erasureCode(data);
|
|
5589
|
+
constructor(config, defaultOptions) {
|
|
5590
|
+
this.aptos = new Aptos(getAptosConfig(config));
|
|
5591
|
+
this.deployer = config.deployer ?? AccountAddress3.fromString(SHELBY_DEPLOYER);
|
|
5592
|
+
this.indexer = getShelbyIndexerClient(config);
|
|
5593
|
+
this.defaultOptions = defaultOptions ?? {};
|
|
5487
5594
|
}
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5595
|
+
/**
|
|
5596
|
+
* Merges method-level options with default options, giving precedence to method-level values.
|
|
5597
|
+
*/
|
|
5598
|
+
mergeOptions(options) {
|
|
5599
|
+
return {
|
|
5600
|
+
build: options?.build ?? this.defaultOptions.build,
|
|
5601
|
+
submit: options?.submit ?? this.defaultOptions.submit,
|
|
5602
|
+
usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
|
|
5603
|
+
chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes
|
|
5604
|
+
};
|
|
5605
|
+
}
|
|
5606
|
+
/**
|
|
5607
|
+
* Validates that if USD sponsorship is requested, a transaction submitter is
|
|
5608
|
+
* configured as well. Checks both the client-level and method-level transaction
|
|
5609
|
+
* submitter configurations. Throws MissingTransactionSubmitterError if usdSponsor is
|
|
5610
|
+
* provided without a transaction submitter.
|
|
5611
|
+
*/
|
|
5612
|
+
validateUsdSponsorConfig(usdSponsor, submit) {
|
|
5613
|
+
if (!usdSponsor) {
|
|
5614
|
+
return;
|
|
5491
5615
|
}
|
|
5492
|
-
const
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
);
|
|
5616
|
+
const hasClientSubmitter = this.aptos.config.getTransactionSubmitter();
|
|
5617
|
+
const hasMethodSubmitter = submit?.transactionSubmitter !== void 0 && submit?.transactionSubmitter !== null;
|
|
5618
|
+
if (!hasClientSubmitter && !hasMethodSubmitter) {
|
|
5619
|
+
throw new MissingTransactionSubmitterError();
|
|
5497
5620
|
}
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5621
|
+
}
|
|
5622
|
+
/**
|
|
5623
|
+
* Retrieves the blob metadata from the blockchain. If it does not exist,
|
|
5624
|
+
* returns `undefined`.
|
|
5625
|
+
*
|
|
5626
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
5627
|
+
* @param params.name - The name of the blob (e.g. "foo/bar")
|
|
5628
|
+
* @returns The blob metadata.
|
|
5629
|
+
*
|
|
5630
|
+
* @example
|
|
5631
|
+
* ```typescript
|
|
5632
|
+
* const metadata = await client.getBlobMetadata({
|
|
5633
|
+
* account: AccountAddress.fromString("0x1"),
|
|
5634
|
+
* name: "foo/bar.txt",
|
|
5635
|
+
* });
|
|
5636
|
+
* ```
|
|
5637
|
+
*/
|
|
5638
|
+
async getBlobMetadata(params) {
|
|
5639
|
+
try {
|
|
5640
|
+
const rawMetadata = await this.aptos.view({
|
|
5641
|
+
payload: {
|
|
5642
|
+
function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
|
|
5643
|
+
functionArguments: [
|
|
5644
|
+
createBlobKey({
|
|
5645
|
+
account: params.account,
|
|
5646
|
+
blobName: params.name
|
|
5647
|
+
})
|
|
5648
|
+
]
|
|
5649
|
+
}
|
|
5650
|
+
});
|
|
5651
|
+
if (!rawMetadata?.[0]?.vec?.[0]) {
|
|
5652
|
+
return void 0;
|
|
5653
|
+
}
|
|
5654
|
+
const metadata = rawMetadata[0].vec[0];
|
|
5655
|
+
let encoding;
|
|
5656
|
+
if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
|
|
5657
|
+
console.log("read blob metadata with ClayCode_16Total_10Data_13Helper");
|
|
5658
|
+
encoding = {
|
|
5659
|
+
variant: "clay",
|
|
5660
|
+
...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
|
|
5661
|
+
...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
|
|
5662
|
+
};
|
|
5663
|
+
} else if (metadata.encoding.__variant__ === "ClayCode_4Total_2Data_3Helper") {
|
|
5664
|
+
console.log("read blob metadata with ClayCode_4Total_2Data_3Helper");
|
|
5665
|
+
encoding = {
|
|
5666
|
+
variant: "clay",
|
|
5667
|
+
...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
|
|
5668
|
+
...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
|
|
5669
|
+
};
|
|
5670
|
+
} else {
|
|
5501
5671
|
throw new Error(
|
|
5502
|
-
|
|
5672
|
+
"Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
|
|
5503
5673
|
);
|
|
5504
5674
|
}
|
|
5675
|
+
return {
|
|
5676
|
+
blobMerkleRoot: Hex4.fromHexInput(
|
|
5677
|
+
metadata.blob_commitment
|
|
5678
|
+
).toUint8Array(),
|
|
5679
|
+
owner: normalizeAddress(metadata.owner),
|
|
5680
|
+
name: params.name,
|
|
5681
|
+
blobNameSuffix: getBlobNameSuffix(params.name),
|
|
5682
|
+
size: Number(metadata.blob_size),
|
|
5683
|
+
encoding,
|
|
5684
|
+
expirationMicros: Number(metadata.expiration_micros),
|
|
5685
|
+
creationMicros: Number(metadata.creation_micros),
|
|
5686
|
+
sliceAddress: normalizeAddress(metadata.slice.inner),
|
|
5687
|
+
isWritten: metadata.is_written
|
|
5688
|
+
};
|
|
5689
|
+
} catch (error) {
|
|
5690
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
5691
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
|
|
5692
|
+
return void 0;
|
|
5693
|
+
}
|
|
5694
|
+
throw error;
|
|
5505
5695
|
}
|
|
5506
|
-
this.lastFunction = "decoded";
|
|
5507
|
-
return this.decoderCache.decode(available, config);
|
|
5508
|
-
}
|
|
5509
|
-
getChunkMerkleRoots() {
|
|
5510
|
-
if (this.decoderCache && this.lastFunction === "decoded")
|
|
5511
|
-
return this.decoderCache.getChunkMerkleRoots();
|
|
5512
|
-
if (this.encoderCache && this.lastFunction === "encoded")
|
|
5513
|
-
return this.encoderCache.getChunkMerkleRoots();
|
|
5514
|
-
throw new Error(
|
|
5515
|
-
"You must call encode or decode before calling getChunkMerkleRoots"
|
|
5516
|
-
);
|
|
5517
5696
|
}
|
|
5518
5697
|
/**
|
|
5519
|
-
*
|
|
5698
|
+
* Retrieves all the blobs and their metadata for an account from the
|
|
5699
|
+
* blockchain.
|
|
5520
5700
|
*
|
|
5521
|
-
*
|
|
5522
|
-
*
|
|
5701
|
+
* @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
|
|
5702
|
+
* @param params.pagination (optional) - The pagination options.
|
|
5703
|
+
* @param params.orderBy (optional) - The order by clause to sort the blobs by.
|
|
5704
|
+
* @returns The blob metadata for all the blobs for the account.
|
|
5523
5705
|
*
|
|
5524
|
-
* @
|
|
5525
|
-
*
|
|
5706
|
+
* @example
|
|
5707
|
+
* ```typescript
|
|
5708
|
+
* // BlobMetadata[]
|
|
5709
|
+
* const blobs = await client.getAccountBlobs({
|
|
5710
|
+
* account: AccountAddress.fromString("0x1"),
|
|
5711
|
+
* });
|
|
5712
|
+
* ```
|
|
5526
5713
|
*/
|
|
5527
|
-
|
|
5528
|
-
const {
|
|
5529
|
-
|
|
5530
|
-
|
|
5714
|
+
getAccountBlobs(params) {
|
|
5715
|
+
const { where, ...rest } = params;
|
|
5716
|
+
return this.getBlobs({
|
|
5717
|
+
where: {
|
|
5718
|
+
...where,
|
|
5719
|
+
owner: { _eq: normalizeAddress(params.account).toString() }
|
|
5720
|
+
},
|
|
5721
|
+
pagination: rest.pagination,
|
|
5722
|
+
orderBy: rest.orderBy
|
|
5723
|
+
});
|
|
5531
5724
|
}
|
|
5532
|
-
};
|
|
5533
|
-
function buildClayConfig(input) {
|
|
5534
|
-
const { erasure_n, erasure_k, erasure_d, chunkSizeBytes } = input;
|
|
5535
|
-
if (erasure_n <= 0)
|
|
5536
|
-
throw new Error("erasure_n (total number of chunks) must be > 0");
|
|
5537
|
-
if (erasure_k <= 0)
|
|
5538
|
-
throw new Error("erasure_k (number of data chunks) must be > 0");
|
|
5539
|
-
if (erasure_k >= erasure_n)
|
|
5540
|
-
throw new Error(
|
|
5541
|
-
`erasure_k (${erasure_k}) must be < erasure_n (${erasure_n})`
|
|
5542
|
-
);
|
|
5543
|
-
if (erasure_d <= erasure_k)
|
|
5544
|
-
throw new Error(
|
|
5545
|
-
`erasure_d (${erasure_d}) must be > erasure_k (${erasure_k})`
|
|
5546
|
-
);
|
|
5547
|
-
if (erasure_d >= erasure_n)
|
|
5548
|
-
throw new Error(
|
|
5549
|
-
`erasure_d (${erasure_d}) must be < erasure_n (${erasure_n})`
|
|
5550
|
-
);
|
|
5551
|
-
if (chunkSizeBytes <= 0) throw new Error("chunkSizeBytes must be > 0");
|
|
5552
|
-
return {
|
|
5553
|
-
erasure_n,
|
|
5554
|
-
erasure_k,
|
|
5555
|
-
erasure_d,
|
|
5556
|
-
chunkSizeBytes
|
|
5557
|
-
};
|
|
5558
|
-
}
|
|
5559
|
-
|
|
5560
|
-
// ../../packages/sdk/dist/chunk-4MG4XGY4.mjs
|
|
5561
|
-
import {
|
|
5562
|
-
AccountAuthenticator,
|
|
5563
|
-
Deserializer,
|
|
5564
|
-
Hex as Hex4,
|
|
5565
|
-
MultiAgentTransaction,
|
|
5566
|
-
Serializer
|
|
5567
|
-
} from "@aptos-labs/ts-sdk";
|
|
5568
|
-
var StaleChannelStateError = class _StaleChannelStateError extends Error {
|
|
5569
5725
|
/**
|
|
5570
|
-
*
|
|
5571
|
-
*
|
|
5726
|
+
* Retrieves blobs and their metadata from the blockchain.
|
|
5727
|
+
*
|
|
5728
|
+
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5729
|
+
* @param params.pagination (optional) - The pagination options.
|
|
5730
|
+
* @param params.orderBy (optional) - The order by clause to sort the blobs by.
|
|
5731
|
+
* @returns The blob metadata for all the blobs that match the where clause.
|
|
5732
|
+
*
|
|
5733
|
+
* @example
|
|
5734
|
+
* ```typescript
|
|
5735
|
+
* // BlobMetadata[]
|
|
5736
|
+
* const blobs = await client.getBlobs({
|
|
5737
|
+
* where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
|
|
5738
|
+
* });
|
|
5739
|
+
* ```
|
|
5572
5740
|
*/
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5741
|
+
async getBlobs(params = {}) {
|
|
5742
|
+
const { limit, offset } = params.pagination ?? {};
|
|
5743
|
+
const { orderBy, where } = params;
|
|
5744
|
+
const currentMicros = String(Date.now() * 1e3);
|
|
5745
|
+
const defaultActiveFilter = {
|
|
5746
|
+
expires_at: { _gte: currentMicros },
|
|
5747
|
+
is_deleted: { _eq: "0" }
|
|
5748
|
+
};
|
|
5749
|
+
const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
|
|
5750
|
+
const { blobs } = await this.indexer.getBlobs({
|
|
5751
|
+
where: finalWhere,
|
|
5752
|
+
limit,
|
|
5753
|
+
offset,
|
|
5754
|
+
orderBy
|
|
5755
|
+
});
|
|
5756
|
+
return blobs.map(
|
|
5757
|
+
(blob) => ({
|
|
5758
|
+
owner: normalizeAddress(blob.owner),
|
|
5759
|
+
name: blob.blob_name,
|
|
5760
|
+
blobNameSuffix: getBlobNameSuffix(blob.blob_name),
|
|
5761
|
+
blobMerkleRoot: Hex4.fromHexInput(blob.blob_commitment).toUint8Array(),
|
|
5762
|
+
size: Number(blob.size),
|
|
5763
|
+
// TODO: Add encoding when supported in NCI
|
|
5764
|
+
encoding: {
|
|
5765
|
+
variant: "clay",
|
|
5766
|
+
...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
|
|
5767
|
+
...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
|
|
5768
|
+
},
|
|
5769
|
+
expirationMicros: Number(blob.expires_at),
|
|
5770
|
+
creationMicros: Number(blob.created_at),
|
|
5771
|
+
sliceAddress: normalizeAddress(blob.slice_address),
|
|
5772
|
+
isWritten: Boolean(Number(blob.is_written)),
|
|
5773
|
+
isDeleted: Boolean(Number(blob.is_deleted))
|
|
5774
|
+
})
|
|
5577
5775
|
);
|
|
5578
|
-
|
|
5579
|
-
|
|
5776
|
+
}
|
|
5777
|
+
async getBlobActivities(params) {
|
|
5778
|
+
const { limit, offset } = params.pagination ?? {};
|
|
5779
|
+
const { orderBy, where } = params;
|
|
5780
|
+
const { blob_activities } = await this.indexer.getBlobActivities({
|
|
5781
|
+
where,
|
|
5782
|
+
limit,
|
|
5783
|
+
offset,
|
|
5784
|
+
orderBy
|
|
5785
|
+
});
|
|
5786
|
+
const activityTypeMapping = {
|
|
5787
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
|
|
5788
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
|
|
5789
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
|
|
5790
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
|
|
5791
|
+
};
|
|
5792
|
+
return blob_activities.map(
|
|
5793
|
+
(activity) => ({
|
|
5794
|
+
blobName: activity.blob_name,
|
|
5795
|
+
accountAddress: normalizeAddress(activity.blob_name.substring(1, 65)),
|
|
5796
|
+
type: activityTypeMapping[activity.event_type] ?? "unknown",
|
|
5797
|
+
eventType: activity.event_type,
|
|
5798
|
+
eventIndex: Number(activity.event_index),
|
|
5799
|
+
transactionHash: activity.transaction_hash,
|
|
5800
|
+
// Using Number here in JS is technically not okay because txn version can be
|
|
5801
|
+
// as large as u64::MAX, but it should be fine for a long while.
|
|
5802
|
+
transactionVersion: Number(activity.transaction_version),
|
|
5803
|
+
timestamp: `${activity.timestamp}Z`
|
|
5804
|
+
})
|
|
5805
|
+
);
|
|
5806
|
+
}
|
|
5807
|
+
/**
|
|
5808
|
+
* Retrieves the total number of blobs from the blockchain.
|
|
5809
|
+
*
|
|
5810
|
+
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5811
|
+
* @returns The total number of blobs.
|
|
5812
|
+
*
|
|
5813
|
+
* @example
|
|
5814
|
+
* ```typescript
|
|
5815
|
+
* const count = await client.getBlobsCount();
|
|
5816
|
+
* ```
|
|
5817
|
+
*/
|
|
5818
|
+
async getBlobsCount(params) {
|
|
5819
|
+
const { where } = params;
|
|
5820
|
+
const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
|
|
5821
|
+
return blobs_aggregate?.aggregate?.count ?? 0;
|
|
5580
5822
|
}
|
|
5581
5823
|
/**
|
|
5582
|
-
*
|
|
5824
|
+
* Retrieves the total number of blob activities from the blockchain.
|
|
5825
|
+
*
|
|
5826
|
+
* @param params.where (optional) - The where clause to filter the blob activities by.
|
|
5827
|
+
* @returns The total number of blob activities.
|
|
5828
|
+
*
|
|
5829
|
+
* @example
|
|
5830
|
+
* ```typescript
|
|
5831
|
+
* const count = await client.getBlobActivitiesCount();
|
|
5832
|
+
* ```
|
|
5583
5833
|
*/
|
|
5584
|
-
|
|
5585
|
-
const
|
|
5586
|
-
const
|
|
5587
|
-
|
|
5588
|
-
(byte) => String.fromCharCode(byte)
|
|
5589
|
-
).join("");
|
|
5590
|
-
return btoa(binaryString);
|
|
5834
|
+
async getBlobActivitiesCount(params) {
|
|
5835
|
+
const { where } = params;
|
|
5836
|
+
const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
|
|
5837
|
+
return blob_activities_aggregate?.aggregate?.count ?? 0;
|
|
5591
5838
|
}
|
|
5592
5839
|
/**
|
|
5593
|
-
*
|
|
5840
|
+
* Registers a blob on the blockchain by writing its merkle root and metadata.
|
|
5841
|
+
*
|
|
5842
|
+
* @param params.account - The account that is signing and paying for the transaction.
|
|
5843
|
+
* @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
5844
|
+
* @param params.blobMerkleRoot - The merkle root of the blob commitments.
|
|
5845
|
+
* @param params.size - The size of the blob in bytes.
|
|
5846
|
+
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
5847
|
+
* @param params.options - Optional transaction building options.
|
|
5848
|
+
* @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
|
|
5849
|
+
* @param params.options.build - Additional Aptos transaction building options.
|
|
5850
|
+
*
|
|
5851
|
+
* @returns An object containing the pending transaction.
|
|
5852
|
+
*
|
|
5853
|
+
* @example
|
|
5854
|
+
* ```typescript
|
|
5855
|
+
* const provider = await ClayErasureCodingProvider.create();
|
|
5856
|
+
* const blobCommitments = await generateCommitments(provider, data);
|
|
5857
|
+
*
|
|
5858
|
+
* const { transaction } = await client.registerBlob({
|
|
5859
|
+
* account: signer,
|
|
5860
|
+
* blobName: "foo/bar.txt",
|
|
5861
|
+
* blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
5862
|
+
* size: data.length,
|
|
5863
|
+
* expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
|
|
5864
|
+
* });
|
|
5865
|
+
* ```
|
|
5594
5866
|
*/
|
|
5595
|
-
|
|
5596
|
-
const
|
|
5597
|
-
|
|
5598
|
-
const
|
|
5599
|
-
|
|
5867
|
+
async registerBlob(params) {
|
|
5868
|
+
const options = this.mergeOptions(params.options);
|
|
5869
|
+
this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
|
|
5870
|
+
const config = params.config ?? defaultErasureCodingConfig();
|
|
5871
|
+
const chunksetSize = config.chunkSizeBytes * config.erasure_k;
|
|
5872
|
+
const buildArgs = {
|
|
5873
|
+
...options.build,
|
|
5874
|
+
data: _ShelbyBlobClient.createRegisterBlobPayload({
|
|
5875
|
+
deployer: this.deployer,
|
|
5876
|
+
account: params.account.accountAddress,
|
|
5877
|
+
blobName: params.blobName,
|
|
5878
|
+
blobSize: params.size,
|
|
5879
|
+
blobMerkleRoot: params.blobMerkleRoot,
|
|
5880
|
+
numChunksets: expectedTotalChunksets(params.size, chunksetSize),
|
|
5881
|
+
expirationMicros: params.expirationMicros,
|
|
5882
|
+
useSponsoredUsdVariant: options.usdSponsor !== void 0,
|
|
5883
|
+
encoding: config.enumIndex
|
|
5884
|
+
}),
|
|
5885
|
+
sender: params.account.accountAddress
|
|
5886
|
+
};
|
|
5887
|
+
const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
|
|
5888
|
+
...buildArgs,
|
|
5889
|
+
secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
|
|
5890
|
+
}) : await this.aptos.transaction.build.simple(buildArgs);
|
|
5891
|
+
return {
|
|
5892
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5893
|
+
signer: params.account,
|
|
5894
|
+
transaction,
|
|
5895
|
+
...options.submit
|
|
5896
|
+
})
|
|
5897
|
+
};
|
|
5600
5898
|
}
|
|
5601
|
-
};
|
|
5602
|
-
var SenderBuiltMicropayment = class _SenderBuiltMicropayment {
|
|
5603
5899
|
/**
|
|
5604
|
-
*
|
|
5900
|
+
* Deletes a blob on the blockchain.
|
|
5901
|
+
*
|
|
5902
|
+
* @param params.account - The account that is signing and paying for the transaction.
|
|
5903
|
+
* @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
5904
|
+
* @param params.options - Optional transaction building options.
|
|
5905
|
+
*
|
|
5906
|
+
* @returns An object containing the pending transaction.
|
|
5907
|
+
*
|
|
5908
|
+
* @example
|
|
5909
|
+
* ```typescript
|
|
5910
|
+
*
|
|
5911
|
+
* const { transaction } = await client.deleteBlob({
|
|
5912
|
+
* account: signer,
|
|
5913
|
+
* blobName: "foo/bar.txt",
|
|
5914
|
+
* });
|
|
5915
|
+
* ```
|
|
5605
5916
|
*/
|
|
5606
|
-
|
|
5917
|
+
async deleteBlob(params) {
|
|
5918
|
+
const transaction = await this.aptos.transaction.build.simple({
|
|
5919
|
+
...params.options,
|
|
5920
|
+
data: _ShelbyBlobClient.createDeleteBlobPayload({
|
|
5921
|
+
deployer: this.deployer,
|
|
5922
|
+
blobName: params.blobName
|
|
5923
|
+
}),
|
|
5924
|
+
sender: params.account.accountAddress
|
|
5925
|
+
});
|
|
5926
|
+
return {
|
|
5927
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5928
|
+
signer: params.account,
|
|
5929
|
+
transaction
|
|
5930
|
+
})
|
|
5931
|
+
};
|
|
5932
|
+
}
|
|
5607
5933
|
/**
|
|
5608
|
-
*
|
|
5934
|
+
* Deletes multiple blobs on the blockchain in a single atomic transaction.
|
|
5935
|
+
*
|
|
5936
|
+
* **Note:** This function requires the `delete_multiple_blobs` entry function
|
|
5937
|
+
* which will be deployed to the smart contract on 2026-02-04. Using this
|
|
5938
|
+
* function before that date will result in a transaction failure.
|
|
5939
|
+
*
|
|
5940
|
+
* This operation is atomic: if any blob deletion fails (e.g., blob not found),
|
|
5941
|
+
* the entire transaction fails and no blobs are deleted.
|
|
5942
|
+
*
|
|
5943
|
+
* @param params.account - The account that is signing and paying for the transaction.
|
|
5944
|
+
* @param params.blobNames - Array of blob name suffixes without the account address prefix
|
|
5945
|
+
* (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
|
|
5946
|
+
* prefix is automatically derived from the signer.
|
|
5947
|
+
* @param params.options - Optional transaction building options.
|
|
5948
|
+
*
|
|
5949
|
+
* @returns An object containing the pending transaction.
|
|
5950
|
+
*
|
|
5951
|
+
* @example
|
|
5952
|
+
* ```typescript
|
|
5953
|
+
*
|
|
5954
|
+
* const { transaction } = await client.deleteMultipleBlobs({
|
|
5955
|
+
* account: signer,
|
|
5956
|
+
* blobNames: ["foo/bar.txt", "baz.txt"],
|
|
5957
|
+
* });
|
|
5958
|
+
* ```
|
|
5609
5959
|
*/
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
return Hex4.fromHexInput(this.bcsToBytes());
|
|
5626
|
-
}
|
|
5627
|
-
toStringWithoutPrefix() {
|
|
5628
|
-
return this.bcsToHex().toStringWithoutPrefix();
|
|
5629
|
-
}
|
|
5630
|
-
toString() {
|
|
5631
|
-
return this.bcsToHex().toString();
|
|
5960
|
+
async deleteMultipleBlobs(params) {
|
|
5961
|
+
const transaction = await this.aptos.transaction.build.simple({
|
|
5962
|
+
...params.options,
|
|
5963
|
+
data: _ShelbyBlobClient.createDeleteMultipleBlobsPayload({
|
|
5964
|
+
deployer: this.deployer,
|
|
5965
|
+
blobNames: params.blobNames
|
|
5966
|
+
}),
|
|
5967
|
+
sender: params.account.accountAddress
|
|
5968
|
+
});
|
|
5969
|
+
return {
|
|
5970
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5971
|
+
signer: params.account,
|
|
5972
|
+
transaction
|
|
5973
|
+
})
|
|
5974
|
+
};
|
|
5632
5975
|
}
|
|
5633
5976
|
/**
|
|
5634
|
-
*
|
|
5635
|
-
*
|
|
5636
|
-
* @
|
|
5977
|
+
* Acks the blob chunksets on-chain. If each chunkset meets the necessary threshold, the entire blob will be marked as written.
|
|
5978
|
+
*
|
|
5979
|
+
* @param params.account - The account that is signing the transaction.
|
|
5980
|
+
* @param params.blobOwner - The account that owns the blob.
|
|
5981
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
5982
|
+
* @param params.creationMicros - The creation time of the blob in microseconds.
|
|
5983
|
+
* @param params.chunksetIdx - The index of the chunkset being acknowledged.
|
|
5984
|
+
* @param params.storageProviderChunksetAcks - The signatures
|
|
5985
|
+
* @param params.options - Additional options for transaction building and encoding.
|
|
5986
|
+
*
|
|
5987
|
+
* @returns The blob commitments and the pending transaction.
|
|
5988
|
+
*
|
|
5989
|
+
* @example
|
|
5990
|
+
* ```typescript
|
|
5991
|
+
* const { transaction } = await client.addChunksetAcknowledgements({
|
|
5992
|
+
* account: signer,
|
|
5993
|
+
* blobOwner: owner,
|
|
5994
|
+
* blobName: "foo/bar.txt",
|
|
5995
|
+
* creationMicros, // Taken from the blob metadata at registration time.
|
|
5996
|
+
* chunksetIdx,
|
|
5997
|
+
* storageProviderAcks: An array of StorageProviderAck types, each having the slot index and signature from the SP.
|
|
5998
|
+
* });
|
|
5999
|
+
* ```
|
|
5637
6000
|
*/
|
|
5638
|
-
|
|
5639
|
-
const
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
5657
|
-
}
|
|
5658
|
-
|
|
5659
|
-
// ../../packages/sdk/dist/chunk-IE6LYVIA.mjs
|
|
5660
|
-
import { z as z3 } from "zod";
|
|
5661
|
-
var StartMultipartUploadResponseSchema = z3.object({
|
|
5662
|
-
uploadId: z3.string()
|
|
5663
|
-
});
|
|
5664
|
-
var UploadPartResponseSchema = z3.object({
|
|
5665
|
-
success: z3.literal(true)
|
|
5666
|
-
});
|
|
5667
|
-
var CompleteMultipartUploadResponseSchema = z3.object({
|
|
5668
|
-
success: z3.literal(true)
|
|
5669
|
-
});
|
|
5670
|
-
var RPCErrorResponseSchema = z3.object({
|
|
5671
|
-
error: z3.string()
|
|
5672
|
-
});
|
|
5673
|
-
var StaleMicropaymentErrorResponseSchema = z3.object({
|
|
5674
|
-
error: z3.string().optional(),
|
|
5675
|
-
storedMicropayment: z3.string().optional()
|
|
5676
|
-
});
|
|
5677
|
-
|
|
5678
|
-
// ../../packages/sdk/dist/chunk-ZAM2EUVN.mjs
|
|
5679
|
-
import { AccountAddress as AccountAddress4 } from "@aptos-labs/ts-sdk";
|
|
5680
|
-
var MICROPAYMENT_HEADER = "X-Shelby-Micropayment";
|
|
5681
|
-
function encodeURIComponentKeepSlashes(str) {
|
|
5682
|
-
return encodeURIComponent(str).replace(/%2F/g, "/");
|
|
5683
|
-
}
|
|
5684
|
-
function validateTotalBytes(totalBytes) {
|
|
5685
|
-
if (!Number.isInteger(totalBytes) || totalBytes < 0) {
|
|
5686
|
-
throw new Error("totalBytes must be a non-negative integer");
|
|
5687
|
-
}
|
|
5688
|
-
}
|
|
5689
|
-
function getErrorCode(error) {
|
|
5690
|
-
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
|
|
5691
|
-
return error.code;
|
|
5692
|
-
}
|
|
5693
|
-
if (error instanceof Error) {
|
|
5694
|
-
const match = error.message.match(/\bE[A-Z0-9_]+\b/);
|
|
5695
|
-
return match?.[0];
|
|
6001
|
+
async addChunksetAcknowledgements(params) {
|
|
6002
|
+
const transaction = await this.aptos.transaction.build.simple({
|
|
6003
|
+
...params.options?.build,
|
|
6004
|
+
data: _ShelbyBlobClient.createChunksetAcknowledgementsPayload({
|
|
6005
|
+
blobOwner: params.blobOwner,
|
|
6006
|
+
blobName: params.blobName,
|
|
6007
|
+
creationMicros: params.creationMicros,
|
|
6008
|
+
chunksetIdx: params.chunksetIdx,
|
|
6009
|
+
storageProviderAcks: params.storageProviderAcks
|
|
6010
|
+
}),
|
|
6011
|
+
sender: params.account.accountAddress
|
|
6012
|
+
});
|
|
6013
|
+
return {
|
|
6014
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
6015
|
+
signer: params.account,
|
|
6016
|
+
transaction
|
|
6017
|
+
})
|
|
6018
|
+
};
|
|
5696
6019
|
}
|
|
5697
|
-
return void 0;
|
|
5698
|
-
}
|
|
5699
|
-
var ShelbyRPCClient = class {
|
|
5700
|
-
baseUrl;
|
|
5701
|
-
apiKey;
|
|
5702
|
-
rpcConfig;
|
|
5703
|
-
indexer;
|
|
5704
6020
|
/**
|
|
5705
|
-
*
|
|
5706
|
-
* This client handles blob storage operations including upload and download.
|
|
6021
|
+
* Registers multiple blobs on the blockchain by writing their merkle roots and metadata.
|
|
5707
6022
|
*
|
|
5708
|
-
* @param
|
|
5709
|
-
* @param
|
|
6023
|
+
* @param params.account - The account that is signing and paying for the transaction.
|
|
6024
|
+
* @param params.expirationMicros - The expiration time of the blobs in microseconds.
|
|
6025
|
+
* @param params.blobs - The blobs to register.
|
|
6026
|
+
* @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
6027
|
+
* @param params.blobs.blobSize - The size of the blob in bytes.
|
|
6028
|
+
* @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
6029
|
+
* @param params.options - Optional transaction building options.
|
|
6030
|
+
* @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
|
|
6031
|
+
* @param params.options.build - Additional Aptos transaction building options.
|
|
6032
|
+
*
|
|
6033
|
+
* @returns An object containing the pending transaction.
|
|
5710
6034
|
*
|
|
5711
6035
|
* @example
|
|
5712
6036
|
* ```typescript
|
|
5713
|
-
* const
|
|
5714
|
-
*
|
|
5715
|
-
*
|
|
6037
|
+
* const provider = await ClayErasureCodingProvider.create();
|
|
6038
|
+
* const blobCommitments = await generateCommitments(provider, data);
|
|
6039
|
+
*
|
|
6040
|
+
* const { transaction } = await client.batchRegisterBlobs({
|
|
6041
|
+
* account: signer,
|
|
6042
|
+
* expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
|
|
6043
|
+
* blobs: [
|
|
6044
|
+
* {
|
|
6045
|
+
* blobName: "foo/bar.txt",
|
|
6046
|
+
* blobSize: data.length,
|
|
6047
|
+
* blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
6048
|
+
* },
|
|
6049
|
+
* ],
|
|
5716
6050
|
* });
|
|
5717
6051
|
* ```
|
|
5718
6052
|
*/
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
this.
|
|
5722
|
-
|
|
5723
|
-
|
|
6053
|
+
async batchRegisterBlobs(params) {
|
|
6054
|
+
const options = this.mergeOptions(params.options);
|
|
6055
|
+
this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
|
|
6056
|
+
const config = params.config ?? defaultErasureCodingConfig();
|
|
6057
|
+
const chunksetSize = config.chunkSizeBytes * config.erasure_k;
|
|
6058
|
+
const buildArgs = {
|
|
6059
|
+
...options.build,
|
|
6060
|
+
sender: params.account.accountAddress,
|
|
6061
|
+
data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
|
|
6062
|
+
deployer: this.deployer,
|
|
6063
|
+
account: params.account.accountAddress,
|
|
6064
|
+
expirationMicros: params.expirationMicros,
|
|
6065
|
+
blobs: params.blobs.map((blob) => ({
|
|
6066
|
+
blobName: blob.blobName,
|
|
6067
|
+
blobSize: blob.blobSize,
|
|
6068
|
+
blobMerkleRoot: blob.blobMerkleRoot,
|
|
6069
|
+
numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
|
|
6070
|
+
})),
|
|
6071
|
+
useSponsoredUsdVariant: options.usdSponsor !== void 0,
|
|
6072
|
+
encoding: config.enumIndex
|
|
6073
|
+
})
|
|
6074
|
+
};
|
|
6075
|
+
const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
|
|
6076
|
+
...buildArgs,
|
|
6077
|
+
secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
|
|
6078
|
+
}) : await this.aptos.transaction.build.simple(buildArgs);
|
|
6079
|
+
return {
|
|
6080
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
6081
|
+
signer: params.account,
|
|
6082
|
+
transaction,
|
|
6083
|
+
...options.submit
|
|
6084
|
+
})
|
|
6085
|
+
};
|
|
5724
6086
|
}
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
}
|
|
5758
|
-
}
|
|
5759
|
-
if (lastError !== void 0) {
|
|
5760
|
-
const errorCode = getErrorCode(lastError);
|
|
5761
|
-
const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
|
|
5762
|
-
throw new Error(
|
|
5763
|
-
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. The connection to the Shelby RPC endpoint was interrupted while sending data${errorCode ? ` (${errorCode})` : ""}. Endpoint: ${partUrl.toString()}, partBytes: ${partData.length}. Last error: ${errorMessage}`,
|
|
5764
|
-
{ cause: lastError }
|
|
5765
|
-
);
|
|
5766
|
-
}
|
|
5767
|
-
const errorBody = await lastResponse?.text().catch(() => "");
|
|
5768
|
-
throw new Error(
|
|
5769
|
-
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. status: ${lastResponse?.status}, body: ${errorBody}`
|
|
5770
|
-
);
|
|
6087
|
+
/**
|
|
6088
|
+
* Creates a transaction payload to register a blob on the blockchain.
|
|
6089
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
6090
|
+
*
|
|
6091
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
6092
|
+
* @param params.account - The account that will own the blob.
|
|
6093
|
+
* @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
6094
|
+
* @param params.blobSize - The size of the blob in bytes.
|
|
6095
|
+
* @param params.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
6096
|
+
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
6097
|
+
* @param params.numChunksets - The total number of chunksets in the blob.
|
|
6098
|
+
*
|
|
6099
|
+
* @returns An Aptos transaction payload data object for the register_blob Move function.
|
|
6100
|
+
*
|
|
6101
|
+
* @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
|
|
6102
|
+
*/
|
|
6103
|
+
static createRegisterBlobPayload(params) {
|
|
6104
|
+
const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
|
|
6105
|
+
return {
|
|
6106
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
|
|
6107
|
+
functionArguments: [
|
|
6108
|
+
params.blobName,
|
|
6109
|
+
params.expirationMicros,
|
|
6110
|
+
Hex4.fromHexString(params.blobMerkleRoot).toUint8Array(),
|
|
6111
|
+
params.numChunksets,
|
|
6112
|
+
params.blobSize,
|
|
6113
|
+
// TODO
|
|
6114
|
+
0,
|
|
6115
|
+
// payment tier
|
|
6116
|
+
params.encoding
|
|
6117
|
+
]
|
|
6118
|
+
};
|
|
5771
6119
|
}
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
const { uploadId } = StartMultipartUploadResponseSchema.parse(
|
|
5800
|
-
await startResponse.json()
|
|
5801
|
-
);
|
|
5802
|
-
const totalParts = Math.ceil(totalBytes / partSize);
|
|
5803
|
-
let uploadedBytes = 0;
|
|
5804
|
-
for await (const [partIdx, partData] of readInChunks(blobData, partSize)) {
|
|
5805
|
-
await this.#uploadPart(uploadId, partIdx, partData);
|
|
5806
|
-
uploadedBytes += partData.length;
|
|
5807
|
-
onProgress?.({
|
|
5808
|
-
phase: "uploading",
|
|
5809
|
-
partIdx,
|
|
5810
|
-
totalParts,
|
|
5811
|
-
partBytes: partData.length,
|
|
5812
|
-
uploadedBytes,
|
|
5813
|
-
totalBytes
|
|
5814
|
-
});
|
|
5815
|
-
}
|
|
5816
|
-
if (uploadedBytes !== totalBytes) {
|
|
5817
|
-
throw new Error(
|
|
5818
|
-
`Uploaded bytes (${uploadedBytes}) did not match declared totalBytes (${totalBytes})`
|
|
5819
|
-
);
|
|
5820
|
-
}
|
|
5821
|
-
const finalPartIdx = totalParts > 0 ? totalParts - 1 : 0;
|
|
5822
|
-
onProgress?.({
|
|
5823
|
-
phase: "finalizing",
|
|
5824
|
-
partIdx: finalPartIdx,
|
|
5825
|
-
totalParts,
|
|
5826
|
-
// no part uploaded in this phase
|
|
5827
|
-
partBytes: 0,
|
|
5828
|
-
uploadedBytes: totalBytes,
|
|
5829
|
-
totalBytes
|
|
5830
|
-
});
|
|
5831
|
-
const completeResponse = await fetch(
|
|
5832
|
-
buildRequestUrl(
|
|
5833
|
-
`/v1/multipart-uploads/${uploadId}/complete`,
|
|
5834
|
-
this.baseUrl
|
|
5835
|
-
),
|
|
5836
|
-
{
|
|
5837
|
-
method: "POST",
|
|
5838
|
-
headers: {
|
|
5839
|
-
"Content-Type": "application/json",
|
|
5840
|
-
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
5841
|
-
}
|
|
5842
|
-
}
|
|
5843
|
-
);
|
|
5844
|
-
if (!completeResponse.ok) {
|
|
5845
|
-
let errorBodyText = "Could not read error body";
|
|
5846
|
-
try {
|
|
5847
|
-
errorBodyText = await completeResponse.text();
|
|
5848
|
-
} catch (_e) {
|
|
5849
|
-
}
|
|
5850
|
-
throw new Error(
|
|
5851
|
-
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
6120
|
+
/**
|
|
6121
|
+
* Creates a transaction payload to register multiple blobs on the blockchain.
|
|
6122
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
6123
|
+
*
|
|
6124
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
6125
|
+
* @param params.account - The account that will own the blobs.
|
|
6126
|
+
* @param params.expirationMicros - The expiration time of the blobs in microseconds.
|
|
6127
|
+
* @param params.blobs - The blobs to register.
|
|
6128
|
+
* @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
6129
|
+
* @param params.blobs.blobSize - The size of the blob in bytes.
|
|
6130
|
+
* @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
6131
|
+
* @param params.blobs.numChunksets - The total number of chunksets in the blob.
|
|
6132
|
+
*
|
|
6133
|
+
* @returns An Aptos transaction payload data object for the register_multiple_blobs Move function.
|
|
6134
|
+
*
|
|
6135
|
+
* @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
|
|
6136
|
+
*/
|
|
6137
|
+
static createBatchRegisterBlobsPayload(params) {
|
|
6138
|
+
const functionName = params.useSponsoredUsdVariant ? "register_multiple_blobs_with_sponsor" : "register_multiple_blobs";
|
|
6139
|
+
const blobNames = [];
|
|
6140
|
+
const blobMerkleRoots = [];
|
|
6141
|
+
const blobNumChunksets = [];
|
|
6142
|
+
const blobSizes = [];
|
|
6143
|
+
params.blobs.forEach((blob) => {
|
|
6144
|
+
blobNames.push(blob.blobName);
|
|
6145
|
+
blobMerkleRoots.push(
|
|
6146
|
+
Hex4.fromHexString(blob.blobMerkleRoot).toUint8Array()
|
|
5852
6147
|
);
|
|
5853
|
-
|
|
6148
|
+
blobNumChunksets.push(blob.numChunksets);
|
|
6149
|
+
blobSizes.push(blob.blobSize);
|
|
6150
|
+
});
|
|
6151
|
+
return {
|
|
6152
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
|
|
6153
|
+
functionArguments: [
|
|
6154
|
+
blobNames,
|
|
6155
|
+
params.expirationMicros,
|
|
6156
|
+
blobMerkleRoots,
|
|
6157
|
+
blobNumChunksets,
|
|
6158
|
+
blobSizes,
|
|
6159
|
+
// TODO
|
|
6160
|
+
0,
|
|
6161
|
+
// payment tier
|
|
6162
|
+
params.encoding
|
|
6163
|
+
]
|
|
6164
|
+
};
|
|
5854
6165
|
}
|
|
5855
6166
|
/**
|
|
5856
|
-
*
|
|
5857
|
-
* This
|
|
5858
|
-
* Uses multipart upload for efficient handling of large files.
|
|
6167
|
+
* Creates a transaction payload to delete a blob on the blockchain.
|
|
6168
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
5859
6169
|
*
|
|
5860
|
-
* @param params.
|
|
5861
|
-
* @param params.blobName - The name
|
|
5862
|
-
* @param params.blobData - The raw blob data as a Uint8Array or ReadableStream.
|
|
5863
|
-
* @param params.totalBytes - Total byte length. Required for streams; optional for Uint8Array.
|
|
6170
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
6171
|
+
* @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
|
|
5864
6172
|
*
|
|
5865
|
-
* @
|
|
5866
|
-
* ```typescript
|
|
5867
|
-
* const blobData = new TextEncoder().encode("Hello, world!");
|
|
6173
|
+
* @returns An Aptos transaction payload data object for the delete_blob Move function.
|
|
5868
6174
|
*
|
|
5869
|
-
*
|
|
5870
|
-
* account: AccountAddress.from("0x1"),
|
|
5871
|
-
* blobName: "greetings/hello.txt",
|
|
5872
|
-
* blobData,
|
|
5873
|
-
* });
|
|
5874
|
-
* ```
|
|
6175
|
+
* @see https://github.com/shelby/shelby/blob/64e9d7b4f0005e586faeb1e4085c79159234b6b6/move/shelby_contract/sources/global_metadata.move#L616
|
|
5875
6176
|
*/
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
if (totalBytes !== params.blobData.length) {
|
|
5882
|
-
throw new Error(
|
|
5883
|
-
"totalBytes must match blobData.length when blobData is a Uint8Array"
|
|
5884
|
-
);
|
|
5885
|
-
}
|
|
5886
|
-
} else {
|
|
5887
|
-
if (params.totalBytes === void 0) {
|
|
5888
|
-
throw new Error(
|
|
5889
|
-
"totalBytes is required when blobData is a ReadableStream"
|
|
5890
|
-
);
|
|
5891
|
-
}
|
|
5892
|
-
totalBytes = params.totalBytes;
|
|
5893
|
-
}
|
|
5894
|
-
validateTotalBytes(totalBytes);
|
|
5895
|
-
await this.#putBlobMultipart(
|
|
5896
|
-
params.account,
|
|
5897
|
-
params.blobName,
|
|
5898
|
-
params.blobData,
|
|
5899
|
-
totalBytes,
|
|
5900
|
-
void 0,
|
|
5901
|
-
params.onProgress
|
|
5902
|
-
);
|
|
6177
|
+
static createDeleteBlobPayload(params) {
|
|
6178
|
+
return {
|
|
6179
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_blob`,
|
|
6180
|
+
functionArguments: [params.blobName]
|
|
6181
|
+
};
|
|
5903
6182
|
}
|
|
5904
6183
|
/**
|
|
5905
|
-
*
|
|
5906
|
-
*
|
|
6184
|
+
* Creates a transaction payload to delete multiple blobs on the blockchain.
|
|
6185
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
5907
6186
|
*
|
|
5908
|
-
*
|
|
5909
|
-
*
|
|
5910
|
-
*
|
|
5911
|
-
* @param params.range.start - Starting byte position (inclusive).
|
|
5912
|
-
* @param params.range.end - Ending byte position (inclusive, optional).
|
|
5913
|
-
* @param params.micropayment - Optional micropayment to attach to the request.
|
|
6187
|
+
* **Note:** This function requires the `delete_multiple_blobs` entry function
|
|
6188
|
+
* which will be deployed to the smart contract on 2026-02-04. Using this
|
|
6189
|
+
* function before that date will result in a transaction failure.
|
|
5914
6190
|
*
|
|
5915
|
-
*
|
|
6191
|
+
* This operation is atomic: if any blob deletion fails (e.g., blob not found),
|
|
6192
|
+
* the entire transaction fails and no blobs are deleted.
|
|
5916
6193
|
*
|
|
5917
|
-
* @
|
|
5918
|
-
* @
|
|
6194
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
6195
|
+
* @param params.blobNames - Array of blob name suffixes without the account address prefix
|
|
6196
|
+
* (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
|
|
6197
|
+
* prefix is automatically derived from the transaction sender.
|
|
6198
|
+
*
|
|
6199
|
+
* @returns An Aptos transaction payload data object for the delete_multiple_blobs Move function.
|
|
6200
|
+
*
|
|
6201
|
+
* @see https://github.com/shelby/shelby/blob/main/move/shelby_contract/sources/blob_metadata.move
|
|
6202
|
+
*/
|
|
6203
|
+
static createDeleteMultipleBlobsPayload(params) {
|
|
6204
|
+
return {
|
|
6205
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_blobs`,
|
|
6206
|
+
functionArguments: [params.blobNames]
|
|
6207
|
+
};
|
|
6208
|
+
}
|
|
6209
|
+
static createChunksetAcknowledgementsPayload(params) {
|
|
6210
|
+
const ackBitMask = params.storageProviderAcks.reduce(
|
|
6211
|
+
(acc, ack) => acc | 1 << ack.slot,
|
|
6212
|
+
0
|
|
6213
|
+
);
|
|
6214
|
+
return {
|
|
6215
|
+
function: `${SHELBY_DEPLOYER}::blob_metadata::add_chunkset_acknowledgements`,
|
|
6216
|
+
functionArguments: [
|
|
6217
|
+
createBlobKey({
|
|
6218
|
+
account: params.blobOwner,
|
|
6219
|
+
blobName: params.blobName
|
|
6220
|
+
}),
|
|
6221
|
+
params.chunksetIdx,
|
|
6222
|
+
params.creationMicros,
|
|
6223
|
+
new U32(Number(ackBitMask)),
|
|
6224
|
+
params.storageProviderAcks.map((ack) => ack.signature)
|
|
6225
|
+
]
|
|
6226
|
+
};
|
|
6227
|
+
}
|
|
6228
|
+
};
|
|
6229
|
+
|
|
6230
|
+
// ../../packages/sdk/dist/chunk-7O77OM4T.mjs
|
|
6231
|
+
import {
|
|
6232
|
+
AccountAddress as AccountAddress4,
|
|
6233
|
+
Aptos as Aptos2,
|
|
6234
|
+
Hex as Hex5
|
|
6235
|
+
} from "@aptos-labs/ts-sdk";
|
|
6236
|
+
function parseStorageProviderState(raw) {
|
|
6237
|
+
switch (raw.__variant__) {
|
|
6238
|
+
case "Active":
|
|
6239
|
+
return {
|
|
6240
|
+
variant: "Active",
|
|
6241
|
+
quota: raw.quota.value,
|
|
6242
|
+
stakeAtStartOfStakingEpoch: raw.stake_at_start_of_staking_epoch,
|
|
6243
|
+
faulty: raw.faulty,
|
|
6244
|
+
leaving: raw.leaving
|
|
6245
|
+
};
|
|
6246
|
+
case "Waitlisted":
|
|
6247
|
+
return {
|
|
6248
|
+
variant: "Waitlisted"
|
|
6249
|
+
};
|
|
6250
|
+
case "Frozen":
|
|
6251
|
+
return {
|
|
6252
|
+
variant: "Frozen",
|
|
6253
|
+
frozenReason: raw.frozen_reason,
|
|
6254
|
+
frozenFrom: raw.frozen_from,
|
|
6255
|
+
frozenTill: raw.frozen_till
|
|
6256
|
+
};
|
|
6257
|
+
}
|
|
6258
|
+
}
|
|
6259
|
+
var ShelbyMetadataClient = class {
|
|
6260
|
+
aptos;
|
|
6261
|
+
deployer;
|
|
6262
|
+
/**
|
|
6263
|
+
* The ShelbyMetadataClient is used to interact with the Shelby contract on the Aptos blockchain. This
|
|
6264
|
+
* includes functions like gathering basic details about the Shelby system, including storage provider information.
|
|
6265
|
+
*
|
|
6266
|
+
* @param config.aptos.config - The Aptos config.
|
|
6267
|
+
* @param config.shelbyDeployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
|
|
5919
6268
|
*
|
|
5920
6269
|
* @example
|
|
5921
6270
|
* ```typescript
|
|
5922
|
-
*
|
|
5923
|
-
* const
|
|
5924
|
-
*
|
|
5925
|
-
|
|
5926
|
-
|
|
6271
|
+
* const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
|
|
6272
|
+
* const metadataClient = new ShelbyMetadataClient({ aptos });
|
|
6273
|
+
* ```
|
|
6274
|
+
*/
|
|
6275
|
+
constructor(config) {
|
|
6276
|
+
this.aptos = new Aptos2(getAptosConfig(config));
|
|
6277
|
+
this.deployer = config.deployer ?? AccountAddress4.fromString(SHELBY_DEPLOYER);
|
|
6278
|
+
}
|
|
6279
|
+
/**
|
|
6280
|
+
* Retrieves storage provider list from the blockchain.
|
|
5927
6281
|
*
|
|
5928
|
-
*
|
|
5929
|
-
* const partial = await client.getBlob({
|
|
5930
|
-
* account: AccountAddress.from("0x1"),
|
|
5931
|
-
* blobName: "large-file.bin",
|
|
5932
|
-
* range: { start: 100, end: 199 }
|
|
5933
|
-
* });
|
|
6282
|
+
* @returns A list of storage providers, or empty array if none exist.
|
|
5934
6283
|
*
|
|
5935
|
-
*
|
|
5936
|
-
*
|
|
5937
|
-
*
|
|
5938
|
-
* blobName: "documents/report.pdf",
|
|
5939
|
-
* micropayment: senderBuiltMicropayment
|
|
5940
|
-
* });
|
|
6284
|
+
* @example
|
|
6285
|
+
* ```typescript
|
|
6286
|
+
* const spList = await client.getStorageProviders();
|
|
5941
6287
|
* ```
|
|
5942
6288
|
*/
|
|
5943
|
-
async
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
this.baseUrl
|
|
5950
|
-
);
|
|
5951
|
-
const headers = new Headers();
|
|
5952
|
-
if (params.range !== void 0) {
|
|
5953
|
-
const { start, end } = params.range;
|
|
5954
|
-
if (end === void 0) {
|
|
5955
|
-
headers.set("Range", `bytes=${start}-`);
|
|
5956
|
-
} else {
|
|
5957
|
-
if (end < start) {
|
|
5958
|
-
throw new Error("Range end cannot be less than start.");
|
|
6289
|
+
async getStorageProviders() {
|
|
6290
|
+
try {
|
|
6291
|
+
const rawMetadata = await this.aptos.view({
|
|
6292
|
+
payload: {
|
|
6293
|
+
function: `${this.deployer.toString()}::storage_provider_registry::get_all_storage_providers`,
|
|
6294
|
+
functionArguments: []
|
|
5959
6295
|
}
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
const response = await fetch(url, { headers });
|
|
5975
|
-
if (response.status === 409) {
|
|
5976
|
-
let json;
|
|
5977
|
-
try {
|
|
5978
|
-
json = await response.json();
|
|
5979
|
-
} catch {
|
|
5980
|
-
throw new Error(
|
|
5981
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
5982
|
-
);
|
|
5983
|
-
}
|
|
5984
|
-
const parseResult = StaleMicropaymentErrorResponseSchema.safeParse(json);
|
|
5985
|
-
if (!parseResult.success) {
|
|
5986
|
-
throw new Error(
|
|
5987
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
5988
|
-
);
|
|
5989
|
-
}
|
|
5990
|
-
const errorBody = parseResult.data;
|
|
5991
|
-
if (errorBody.storedMicropayment) {
|
|
5992
|
-
throw StaleChannelStateError.fromBase64(
|
|
5993
|
-
errorBody.storedMicropayment,
|
|
5994
|
-
errorBody.error
|
|
5995
|
-
);
|
|
6296
|
+
});
|
|
6297
|
+
const metadata = rawMetadata[0];
|
|
6298
|
+
return metadata.map((provider) => ({
|
|
6299
|
+
address: normalizeAddress(provider.address),
|
|
6300
|
+
ipAddress: provider.ip_address,
|
|
6301
|
+
port: provider.port,
|
|
6302
|
+
blsPublicKey: Hex5.fromHexInput(provider.bls_public_key).toUint8Array(),
|
|
6303
|
+
availabilityZone: provider.availability_zone,
|
|
6304
|
+
state: parseStorageProviderState(provider.state)
|
|
6305
|
+
}));
|
|
6306
|
+
} catch (error) {
|
|
6307
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
6308
|
+
error.message?.includes("sub_status: Some(404)")) {
|
|
6309
|
+
return [];
|
|
5996
6310
|
}
|
|
5997
|
-
throw
|
|
5998
|
-
errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
|
|
5999
|
-
);
|
|
6000
|
-
}
|
|
6001
|
-
if (!response.ok) {
|
|
6002
|
-
throw new Error(
|
|
6003
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
6004
|
-
);
|
|
6005
|
-
}
|
|
6006
|
-
if (!response.body) {
|
|
6007
|
-
throw new Error("Response body is null");
|
|
6008
|
-
}
|
|
6009
|
-
const contentLengthHeader = response.headers.get("content-length");
|
|
6010
|
-
if (contentLengthHeader === null) {
|
|
6011
|
-
throw new Error(
|
|
6012
|
-
"Response did not have content-length header, which is required"
|
|
6013
|
-
);
|
|
6311
|
+
throw error;
|
|
6014
6312
|
}
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6313
|
+
}
|
|
6314
|
+
/**
|
|
6315
|
+
* Retrieves the list of placement group addresses.
|
|
6316
|
+
*
|
|
6317
|
+
* @returns The placement group address list, or an empty array if none exist.
|
|
6318
|
+
*
|
|
6319
|
+
* @example
|
|
6320
|
+
* ```typescript
|
|
6321
|
+
* const pgList = await client.getPlacementGroupAddresses();
|
|
6322
|
+
* ```
|
|
6323
|
+
*/
|
|
6324
|
+
async getPlacementGroupAddresses() {
|
|
6325
|
+
try {
|
|
6326
|
+
const pgSizeMetadata = await this.aptos.view({
|
|
6327
|
+
payload: {
|
|
6328
|
+
function: `${this.deployer.toString()}::placement_group_registry::get_number_of_placement_groups`,
|
|
6329
|
+
functionArguments: []
|
|
6330
|
+
}
|
|
6331
|
+
});
|
|
6332
|
+
const finalPlacementGroupIndex = pgSizeMetadata[0] - 1;
|
|
6333
|
+
const addressMetadataArray = await this.aptos.view({
|
|
6334
|
+
payload: {
|
|
6335
|
+
function: `${this.deployer.toString()}::placement_group_registry::get_placement_group_addresses`,
|
|
6336
|
+
functionArguments: [0, finalPlacementGroupIndex]
|
|
6337
|
+
}
|
|
6338
|
+
});
|
|
6339
|
+
const metadata = addressMetadataArray[0];
|
|
6340
|
+
return metadata.map((pg) => normalizeAddress(pg));
|
|
6341
|
+
} catch (error) {
|
|
6342
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
6343
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("E_PLACEMENT_GROUP_NOT_FOUND"))) {
|
|
6344
|
+
return [];
|
|
6345
|
+
}
|
|
6346
|
+
throw error;
|
|
6020
6347
|
}
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6348
|
+
}
|
|
6349
|
+
/**
|
|
6350
|
+
* Retrieves the list of slice addresses.
|
|
6351
|
+
*
|
|
6352
|
+
* @returns The slice group list, or an empty array if none exist.
|
|
6353
|
+
*
|
|
6354
|
+
* @example
|
|
6355
|
+
* ```typescript
|
|
6356
|
+
* const pgList = await client.getSliceAddresses();
|
|
6357
|
+
* ```
|
|
6358
|
+
*/
|
|
6359
|
+
async getSliceAddresses() {
|
|
6360
|
+
try {
|
|
6361
|
+
const sliceSizeMetadata = await this.aptos.view({
|
|
6362
|
+
payload: {
|
|
6363
|
+
function: `${this.deployer.toString()}::slice_registry::get_number_of_slices`,
|
|
6364
|
+
functionArguments: []
|
|
6027
6365
|
}
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
controller.error(
|
|
6035
|
-
new Error(
|
|
6036
|
-
`Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
|
|
6037
|
-
)
|
|
6038
|
-
);
|
|
6039
|
-
return;
|
|
6040
|
-
}
|
|
6041
|
-
controller.close();
|
|
6042
|
-
return;
|
|
6043
|
-
}
|
|
6044
|
-
bytesReceived += value.byteLength;
|
|
6045
|
-
controller.enqueue(value);
|
|
6046
|
-
return pump();
|
|
6047
|
-
}).catch((error) => {
|
|
6048
|
-
controller.error(error);
|
|
6049
|
-
});
|
|
6366
|
+
});
|
|
6367
|
+
const finalSliceIndex = sliceSizeMetadata[0] - 1;
|
|
6368
|
+
const addressMetadataArray = await this.aptos.view({
|
|
6369
|
+
payload: {
|
|
6370
|
+
function: `${this.deployer.toString()}::slice_registry::get_slice_addresses`,
|
|
6371
|
+
functionArguments: [0, finalSliceIndex]
|
|
6050
6372
|
}
|
|
6051
|
-
|
|
6373
|
+
});
|
|
6374
|
+
const metadata = addressMetadataArray[0];
|
|
6375
|
+
return metadata.map((slice) => normalizeAddress(slice));
|
|
6376
|
+
} catch (error) {
|
|
6377
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
6378
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("E_SLICE_NOT_FOUND"))) {
|
|
6379
|
+
return [];
|
|
6380
|
+
}
|
|
6381
|
+
throw error;
|
|
6382
|
+
}
|
|
6383
|
+
}
|
|
6384
|
+
/**
|
|
6385
|
+
* Gets the placement group address for a slice.
|
|
6386
|
+
*
|
|
6387
|
+
* @param sliceAddress - The address of the slice account.
|
|
6388
|
+
* @returns The placement group address as a string.
|
|
6389
|
+
*/
|
|
6390
|
+
async getPlacementGroupAddressForSlice(sliceAddress) {
|
|
6391
|
+
const sliceMetadata = await this.aptos.view({
|
|
6392
|
+
payload: {
|
|
6393
|
+
function: `${this.deployer.toString()}::slice::get_slice_info`,
|
|
6394
|
+
functionArguments: [sliceAddress.toString()]
|
|
6052
6395
|
}
|
|
6053
6396
|
});
|
|
6054
|
-
return
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6397
|
+
return sliceMetadata[0].placement_group_assignments[0].placement_group_address;
|
|
6398
|
+
}
|
|
6399
|
+
/**
|
|
6400
|
+
* Retrieves the designated storage providers for a slice.
|
|
6401
|
+
*
|
|
6402
|
+
* Designated SPs are those appointed to store data for their slots:
|
|
6403
|
+
* - Active: Currently serving data
|
|
6404
|
+
* - Receiving: Receiving data during slot transfer
|
|
6405
|
+
* - Repairing: Repairing data after crash or failed transfer
|
|
6406
|
+
* - Reconstructing: Reconstructing data if the repair fails
|
|
6407
|
+
*
|
|
6408
|
+
* @param params.account - The address of the slice account.
|
|
6409
|
+
* @returns An array where result[i] is the designated SP for slot i, or null if no SP is designated.
|
|
6410
|
+
*
|
|
6411
|
+
* @example
|
|
6412
|
+
* ```typescript
|
|
6413
|
+
* const providers = await client.getDesignatedStorageProvidersForSlice({ account: sliceAddress });
|
|
6414
|
+
* ```
|
|
6415
|
+
*/
|
|
6416
|
+
async getDesignatedStorageProvidersForSlice(params) {
|
|
6417
|
+
const placementGroupAddress = await this.getPlacementGroupAddressForSlice(
|
|
6418
|
+
params.account
|
|
6419
|
+
);
|
|
6420
|
+
const rawMetadata = await this.aptos.view({
|
|
6421
|
+
payload: {
|
|
6422
|
+
function: `${this.deployer.toString()}::placement_group::get_designated_storage_providers`,
|
|
6423
|
+
functionArguments: [placementGroupAddress]
|
|
6424
|
+
}
|
|
6425
|
+
});
|
|
6426
|
+
const providers = rawMetadata[0];
|
|
6427
|
+
return providers.map(
|
|
6428
|
+
(opt) => opt.vec.length > 0 ? normalizeAddress(opt.vec[0]) : null
|
|
6429
|
+
);
|
|
6430
|
+
}
|
|
6431
|
+
/**
|
|
6432
|
+
* Retrieves the active storage providers for a slice.
|
|
6433
|
+
*
|
|
6434
|
+
* Active SPs have a complete copy of the data for the slot, and are not in any data transfer/repair/reconstruction phase.
|
|
6435
|
+
* Active SP can be audited for the data it contains.
|
|
6436
|
+
* Each slot has at most one active SP.
|
|
6437
|
+
*
|
|
6438
|
+
* @param params.account - The address of the slice account.
|
|
6439
|
+
* @returns An array where result[i] is the active SP for slot i, or null if no SP is active.
|
|
6440
|
+
*
|
|
6441
|
+
* @example
|
|
6442
|
+
* ```typescript
|
|
6443
|
+
* const providers = await client.getActiveStorageProvidersForSlice({ account: sliceAddress });
|
|
6444
|
+
* ```
|
|
6445
|
+
*/
|
|
6446
|
+
async getActiveStorageProvidersForSlice(params) {
|
|
6447
|
+
const placementGroupAddress = await this.getPlacementGroupAddressForSlice(
|
|
6448
|
+
params.account
|
|
6449
|
+
);
|
|
6450
|
+
const rawMetadata = await this.aptos.view({
|
|
6451
|
+
payload: {
|
|
6452
|
+
function: `${this.deployer.toString()}::placement_group::get_active_storage_providers`,
|
|
6453
|
+
functionArguments: [placementGroupAddress]
|
|
6454
|
+
}
|
|
6455
|
+
});
|
|
6456
|
+
const providers = rawMetadata[0];
|
|
6457
|
+
return providers.map(
|
|
6458
|
+
(opt) => opt.vec.length > 0 ? normalizeAddress(opt.vec[0]) : null
|
|
6459
|
+
);
|
|
6460
|
+
}
|
|
6461
|
+
/**
|
|
6462
|
+
* Retrieves the serving storage providers for a slice.
|
|
6463
|
+
*
|
|
6464
|
+
* Serving SPs are those that can respond to read requests. The serving logic is:
|
|
6465
|
+
* - If an Active SP exists for a slot: Only the Active SP is serving
|
|
6466
|
+
* - If no Active SP (transition in progress): Both Designated and Vacating SPs serve
|
|
6467
|
+
*
|
|
6468
|
+
* Each slot may have multiple serving SPs during transitions.
|
|
6469
|
+
*
|
|
6470
|
+
* @param params.account - The address of the slice account.
|
|
6471
|
+
* @returns An array where result[i] contains the serving SPs for slot i.
|
|
6472
|
+
*
|
|
6473
|
+
* @example
|
|
6474
|
+
* ```typescript
|
|
6475
|
+
* const providers = await client.getServingStorageProvidersForSlice({ account: sliceAddress });
|
|
6476
|
+
* ```
|
|
6477
|
+
*/
|
|
6478
|
+
async getServingStorageProvidersForSlice(params) {
|
|
6479
|
+
const placementGroupAddress = await this.getPlacementGroupAddressForSlice(
|
|
6480
|
+
params.account
|
|
6481
|
+
);
|
|
6482
|
+
const rawMetadata = await this.aptos.view({
|
|
6483
|
+
payload: {
|
|
6484
|
+
function: `${this.deployer.toString()}::placement_group::get_serving_storage_providers`,
|
|
6485
|
+
functionArguments: [placementGroupAddress]
|
|
6486
|
+
}
|
|
6487
|
+
});
|
|
6488
|
+
const providers = rawMetadata[0];
|
|
6489
|
+
return providers.map(
|
|
6490
|
+
(slotProviders) => slotProviders.map((addr) => normalizeAddress(addr))
|
|
6491
|
+
);
|
|
6060
6492
|
}
|
|
6061
6493
|
};
|
|
6062
6494
|
|
|
6063
|
-
// ../../packages/sdk/dist/chunk-
|
|
6495
|
+
// ../../packages/sdk/dist/chunk-5CES6RPZ.mjs
|
|
6064
6496
|
import {
|
|
6065
|
-
|
|
6066
|
-
Aptos as Aptos2,
|
|
6497
|
+
Aptos as Aptos3,
|
|
6067
6498
|
DEFAULT_TXN_TIMEOUT_SEC,
|
|
6499
|
+
Network as Network3,
|
|
6068
6500
|
TransactionResponseType
|
|
6069
6501
|
} from "@aptos-labs/ts-sdk";
|
|
6070
6502
|
|
|
@@ -6205,13 +6637,17 @@ function validateConcurrency(concurrency) {
|
|
|
6205
6637
|
}
|
|
6206
6638
|
}
|
|
6207
6639
|
|
|
6208
|
-
// ../../packages/sdk/dist/chunk-
|
|
6640
|
+
// ../../packages/sdk/dist/chunk-5CES6RPZ.mjs
|
|
6209
6641
|
var ShelbyClient = class {
|
|
6210
6642
|
/**
|
|
6211
6643
|
* The coordination client is used to interact with the Aptos blockchain which handles the commitments
|
|
6212
6644
|
* and metadata for blobs.
|
|
6213
6645
|
*/
|
|
6214
6646
|
coordination;
|
|
6647
|
+
/**
|
|
6648
|
+
* The metadata client is used for protocol-level metadata queries.
|
|
6649
|
+
*/
|
|
6650
|
+
metadata;
|
|
6215
6651
|
/**
|
|
6216
6652
|
* The RPC client is used to interact with the Shelby RPC node which can be responsible for storing,
|
|
6217
6653
|
* confirming, and retrieving blobs from the storage layer.
|
|
@@ -6261,8 +6697,9 @@ var ShelbyClient = class {
|
|
|
6261
6697
|
*/
|
|
6262
6698
|
constructor(config, provider) {
|
|
6263
6699
|
this.config = config;
|
|
6264
|
-
this.aptos = new
|
|
6700
|
+
this.aptos = new Aptos3(getAptosConfig(config));
|
|
6265
6701
|
this.coordination = new ShelbyBlobClient(config);
|
|
6702
|
+
this.metadata = new ShelbyMetadataClient(config);
|
|
6266
6703
|
this.rpc = new ShelbyRPCClient(config);
|
|
6267
6704
|
this._provider = provider;
|
|
6268
6705
|
}
|
|
@@ -6272,7 +6709,9 @@ var ShelbyClient = class {
|
|
|
6272
6709
|
*/
|
|
6273
6710
|
async getProvider() {
|
|
6274
6711
|
if (!this._provider) {
|
|
6275
|
-
this._provider = await ClayErasureCodingProvider.create(
|
|
6712
|
+
this._provider = await ClayErasureCodingProvider.create(
|
|
6713
|
+
defaultErasureCodingConfig()
|
|
6714
|
+
);
|
|
6276
6715
|
}
|
|
6277
6716
|
return this._provider;
|
|
6278
6717
|
}
|
|
@@ -6329,6 +6768,7 @@ var ShelbyClient = class {
|
|
|
6329
6768
|
blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
6330
6769
|
size: params.blobData.length,
|
|
6331
6770
|
expirationMicros: params.expirationMicros,
|
|
6771
|
+
config: provider.config,
|
|
6332
6772
|
options: params.options
|
|
6333
6773
|
});
|
|
6334
6774
|
await this.coordination.aptos.waitForTransaction({
|
|
@@ -6409,6 +6849,7 @@ var ShelbyClient = class {
|
|
|
6409
6849
|
blobSize: blob.blobData.length,
|
|
6410
6850
|
blobMerkleRoot: blobCommitments[index].blob_merkle_root
|
|
6411
6851
|
})),
|
|
6852
|
+
config: provider.config,
|
|
6412
6853
|
options: params.options
|
|
6413
6854
|
});
|
|
6414
6855
|
await this.coordination.aptos.waitForTransaction({
|
|
@@ -6466,6 +6907,11 @@ var ShelbyClient = class {
|
|
|
6466
6907
|
* ```
|
|
6467
6908
|
*/
|
|
6468
6909
|
async fundAccountWithShelbyUSD(params) {
|
|
6910
|
+
if (this.config.network === Network3.TESTNET) {
|
|
6911
|
+
throw new Error(
|
|
6912
|
+
`ShelbyUSD cannot be minted programmatically on ${Network3.TESTNET}. Please use the faucet at https://docs.shelby.xyz/apis/faucet/shelbyusd instead.`
|
|
6913
|
+
);
|
|
6914
|
+
}
|
|
6469
6915
|
const { address, amount } = params;
|
|
6470
6916
|
try {
|
|
6471
6917
|
const faucet = this.config.faucet?.baseUrl ?? "https://faucet.shelbynet.shelby.xyz/fund?asset=shelbyusd";
|
|
@@ -6473,7 +6919,7 @@ var ShelbyClient = class {
|
|
|
6473
6919
|
const response = await fetch(`${faucet}`, {
|
|
6474
6920
|
method: "POST",
|
|
6475
6921
|
body: JSON.stringify({
|
|
6476
|
-
address:
|
|
6922
|
+
address: normalizeAddress(address).toString(),
|
|
6477
6923
|
amount
|
|
6478
6924
|
}),
|
|
6479
6925
|
headers: {
|
|
@@ -6527,48 +6973,22 @@ var ShelbyClient = class {
|
|
|
6527
6973
|
}
|
|
6528
6974
|
};
|
|
6529
6975
|
|
|
6530
|
-
// ../../packages/sdk/dist/chunk-
|
|
6976
|
+
// ../../packages/sdk/dist/chunk-33BZ7KYA.mjs
|
|
6531
6977
|
var ShelbyNodeClient = class extends ShelbyClient {
|
|
6532
6978
|
};
|
|
6533
6979
|
|
|
6534
|
-
// ../../packages/sdk/dist/chunk-YZXIPUVQ.mjs
|
|
6535
|
-
import {
|
|
6536
|
-
AccountAddress as AccountAddress6,
|
|
6537
|
-
Aptos as Aptos3,
|
|
6538
|
-
Hex as Hex5
|
|
6539
|
-
} from "@aptos-labs/ts-sdk";
|
|
6540
|
-
|
|
6541
|
-
// ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
|
|
6542
|
-
var __defProp2 = Object.defineProperty;
|
|
6543
|
-
var __export = (target, all) => {
|
|
6544
|
-
for (var name2 in all)
|
|
6545
|
-
__defProp2(target, name2, { get: all[name2], enumerable: true });
|
|
6546
|
-
};
|
|
6547
|
-
|
|
6548
|
-
// ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
|
|
6549
|
-
var testUtil_exports = {};
|
|
6550
|
-
__export(testUtil_exports, {
|
|
6551
|
-
makeChunk: () => makeChunk
|
|
6552
|
-
});
|
|
6553
|
-
function makeChunk(n) {
|
|
6554
|
-
const c = Buffer.alloc(n);
|
|
6555
|
-
for (let i = 0; i < n; ++i) {
|
|
6556
|
-
c[i] = i % 256;
|
|
6557
|
-
}
|
|
6558
|
-
return c;
|
|
6559
|
-
}
|
|
6560
|
-
|
|
6561
6980
|
// ../../packages/reed-solomon/dist/index.mjs
|
|
6562
6981
|
var __toBinaryNode = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
|
|
6563
6982
|
var reed_solomon_erasure_bg_default = __toBinaryNode("AGFzbQEAAAAB/oCAgAASYAJ/fwF/YAF/AX9gBH9/f38AYAABf2ABfwBgAn9/AGADf39/AX9gAABgBH9/f38Bf2AGf39/f39/AX9gA39/fwBgBX9/f39/AX9gCH9/f39/f39/AGABfwF+YAZ/f39/f38AYAV/f39/fwBgB39/f39/f38Bf2ADfn9/AX8Dj4GAgACNAQkFBgYCBgkKCQwKAAsIDgYGBQsCBQ8PEAgGCgARCgACBQAFCgUFCAIAAgUBAgAABAQFAgIACgoFBAUKBQAEBQUEBAgABQEGCAADAgYGCgAEBQAFBA8EBAULAQEFAAAAAQEKCAoAAAAKAAUFBgAABAcBBwcBAQEAAQABAw0NDQ0HAwMBDQQEBAQEBAQFBASFgICAAAFwAS0tBYOAgIAAAQASBomAgIAAAX8BQYCAwAALB8eAgIAABQZtZW1vcnkCAAZlbmNvZGUADQtyZWNvbnN0cnVjdAAIEV9fd2JpbmRnZW5fbWFsbG9jAEUPX193YmluZGdlbl9mcmVlAFsJvICAgAABAEEBCywoXIQBMnh5hgGFASl2d3pVQ11OaIgBPlJ7hwF8ZEiLAYoBSxs8iQF9TyAqVn5eNAtlHowBgwEKnoWCgACNAaomARd/IwBB8CRrIgYkAEEAIQcCQCAAKAIIIgggAksNAEEBIQcgCCACSQ0AAkACQAJAAkACQAJAAkACQCACRQ0AAkACQCABKAIEIglFDQAgASACQQN0IgpqIQsgASEMA0AgCkUNAiAKQXhqIQpBCCEHIAwoAgQhDSAMQQhqIQwgDSAJRg0ADAsLCyAGQfAkaiQAQQoPC0ELIQcgAiAERw0IQQAhDEEAIQoDQCAMIAMgCmotAABqIQwgCkEBaiIKIAJJDQALQQ0hByAMIAhGDQhBCSEHIAwgACgCACIKSQ0IIAZCADcD4BwCQCAKQSFJDQAgBkHgHGogChAlCyAGIAZB4BxqQYgCEEYhDCAAKAIEIQogDEIANwPgHAJAIApBIUkNACAMQeAcaiAKECQgAEEEaigCACEKCyAMQYgCaiAMQeAcakGIAhBGGiAMQgA3A+AcAkAgCkEhSQ0AIAxB4BxqIAoQJAsgDEGQBGogDEHgHGpBiAIQRhogACgCACEKIAxCADcD4BwCQCAKQSFJDQAgDEHgHGogChAiIAAoAgAhCgsgDEGYBmogDEHgHGpBiAEQRhogDEIANwPgHAJAIApBIUkNACAMQeAcaiAKECILIAxBoAdqIAxB4BxqQYgBEEYaAkAgCyABRg0AIAJBA3QhDSAMQaAHakEMaiEEIAxBoAdqQQhqIQsgDEGIAmpBCGohDiAMQZAEakEIaiEPIAxBmAZqQQxqIRAgDEGYBmpBCGohESAMQQhqIRJBACEKA0AgCiACTw0DAkACQAJAIAMgCmotAABFDQAgDEEMaigCACAMKAIAIgcgB0EgSyIIGyIJIAAoAgBPDQIgAUEEaigCACETIAEoAgAhFAJAIAkgB0EgIAgbRw0AIAxBf0EAQX8gCWd2IAlBAWpBAkkbIgdBAWoiCCAIIAdJGxAlIAwoAgAhBwsgEigCACEIIAxBDEEAIAdBIEsiBxtqIAlBAWo2AgAgCCASIAcbIAlBA3RqIgcgEzYCBCAHIBQ2AgACQCAQKAIAIAwoApgGIgkgCUEgSyIIGyIHIAlBICAIGyIIRw0AAkACQCAIQQFqIgkgCEkNAEEAIQgCQCAJQQJJDQBBfyAJQX9qZ3YhCAsgCEEBaiIJIAhPDQELQX8hCQsgDEGYBmogCRAiIAwoApgGIQkLIBEoAgAgESAJQSBLIggbIQkgECAMQZgGaiAIGyEIDAELIAFBBGooAgAhCSABKAIAIQgCQAJAIAogACgCAE8NAAJAIAxBiAJqQQxqKAIAIAwoAogCIgcgB0EgSyIUGyITIAdBICAUGyIURw0AAkACQCAUQQFqIgcgFEkNAEEAIRQCQCAHQQJJDQBBfyAHQX9qZ3YhFAsgFEEBaiIHIBRPDQELQX8hBwsgDEGIAmogBxAkIAwoAogCIQcLIA4oAgAhFCAMQYgCakEMQQAgB0EgSyIHG2ogE0EBajYCACAUIA4gBxsgE0EDdGoiByAINgIAIAdBBGohBwwBCwJAIAxBkARqQQxqKAIAIAwoApAEIgcgB0EgSyIUGyITIAdBICAUGyIURw0AAkACQCAUQQFqIgcgFEkNAEEAIRQCQCAHQQJJDQBBfyAHQX9qZ3YhFAsgFEEBaiIHIBRPDQELQX8hBwsgDEGQBGogBxAkIAwoApAEIQcLIA8oAgAhFCAMQZAEakEMQQAgB0EgSyIHG2ogE0EBajYCACAUIA8gBxsgE0EDdGoiByAINgIAIAdBBGohBwsgByAJNgIAAkAgBCgCACAMKAKgByIJIAlBIEsiCBsiByAJQSAgCBsiCEcNAAJAAkAgCEEBaiIJIAhJDQBBACEIAkAgCUECSQ0AQX8gCUF/amd2IQgLIAhBAWoiCSAITw0BC0F/IQkLIAxBoAdqIAkQIiAMKAKgByEJCyALKAIAIAsgCUEgSyIIGyEJIAQgDEGgB2ogCBshCAsgCCAHQQFqNgIAIAkgB0ECdGogCjYCAAsgAUEIaiEBIApBAWohCiANQXhqIg0NAAsLIAxBmAZqQQhqIggoAgAhBCAMQZgGakEMaigCACEBIAwoApgGIQkgDCAAQZwIaiIVIAxBoAdqQQhqIgooAgAgCiAMKAKgByIHQSBLIg0bIhYgDEGgB2pBDGooAgAgByANGyIXEBkiCjYCuAogCg0HIAAoAgAiByAHbCIKQX9MDQICQAJAAkAgCkUNAEEBIQsgCkEBEG0iDUUNCSAKIRIgCkGACE0NAQwCC0EBIQ0LIAxB4BxqIA0gChBGGiAMQbAIakECaiAMQeAcakECai0AADoAACAMIAwvAOAcOwGwCCAMKADjHCEQIAwoAOccIRIgDEHQFGogDEHrHGpB+AcQRhpBACELAkAgCkUNACANIApBARBnCyAQIQ0LIAxBzAxqIAs6AAAgDEHNDGoiECAMLwGwCDsAACAMQcAMakEUaiIRIBI2AgAgDEHADGpBEGoiEiANNgIAIAxBzwxqIAxBsAhqQQJqLQAAOgAAIAwgCjYCyAwgDCAHNgLEDCAMIAc2AsAMIAxB2AxqIAxB0BRqQfgHEEYaAkACQAJAIAEgCSAJQSBLIgobIgdFDQAgBCAIIAobIhggB0ECdGohGSAAQRlqIRNBACEIIABBFGohFCAAQSBqIQ4gAEEQaiEPIAxByAxqIRogAEEcaiEbA0ACQCAAKAIAIgRFDQAgGCgCACELQQAhCgNAIA4oAgAgFCgCACIHIAdBgAhLIgcbIgkgCiAPKAIAIAtsaiINTQ0EIBEoAgAgGigCACIJIAlBgAhLIgkbIhwgCiAIIAwoAsQMbGoiAU0NBSASKAIAIBAgCRsgAWogGygCACATIAcbIA1qLQAAOgAAIApBAWoiCiAESQ0ACwsgCEEBaiEIIBhBBGoiGCAZRw0ACwsgDEHgHGogDEHADGoQASAMLQDsHEECRg0FIAxB0BRqIAxB4BxqQZAIEEYaQZgIQQQQbCIKRQ0GIApCgYCAgBA3AgAgCkEIaiAMQdAUakGQCBBGGiAMIAo2AuAcIBUgFiAXIAxB4BxqECZB/wFxIgdBAkcNBwJAIAxBwAxqQQhqKAIAIgdBgQhJDQAgDEHQDGooAgAgB0EBEGcLIAwoArgKIgdFDQkgByAHKAIAIg1Bf2o2AgAgDUEBRw0JIAxBuApqEEEMCQtBlLXEACANIAkQOgALQaS1xAAgASAcEDoAC0HQs8QAQQBBABA6AAtBgLTEACAKIAIQOgALEHIAC0GDgsAAQSsQNwALQZgIQQQQaQALQYOCwABBKyAHQQFxEDYACyAKQQEQaQALIAwgCjYCrAggAEEEaigCACEKIAxCADcD4BwCQCAKQSFJDQAgDEHgHGogChAlCyAMQbAIaiAMQeAcakGIAhBGGgJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIAIgFFDQAgDEG4CGohCEEAIQoDQCAKIAJPDQMCQAJAIAMgCmotAABFDQAgCkEBaiIKIAFJDQIMAQsgDCgCrAgiB0EMaigCACINIApsIgkgDWoiBCAJSQ0JIAcoAhwgB0EQaigCACILIAtBgAhLIgsbIhAgBEkNCiAHKAIYIAdBFWogCxsgCWohBAJAIAxBsAhqQQxqKAIAIAwoArAIIgcgB0EgSyILGyIJIAdBICALGyILRw0AAkACQCALQQFqIgcgC0kNAEEAIQsCQCAHQQJJDQBBfyAHQX9qZ3YhCwsgC0EBaiIHIAtPDQELQX8hBwsgDEGwCGogBxAlIAwoArAIIQcLIAgoAgAhCyAMQbAIakEMQQAgB0EgSyIHG2ogCUEBajYCACALIAggBxsgCUEDdGoiByANNgIEIAcgBDYCACAKQQFqIgogAUkNAQsLIAAoAgAhCQwBC0EAIQkLIAxBiAJqQQhqIRMgDEEIaiESAkAgCUUNACAMQYgCakEMaigCACAMKAKIAiIKIApBIEsiChshASATKAIAIBMgChshCCAMQQxqKAIAIAwoAgAiCiAKQSBLIgobIQQgEigCACASIAobIQogDEGwCGpBDGooAgAgDCgCsAgiByAHQSBLIgcbIQsgDEGwCGpBCGoiDSgCACANIAcbIRBBACEHA0AgByAETw0DIAAgECALIAcgCigCACAKQQRqKAIAIAggARAJIApBCGohCiAHQQFqIg0hByANIAlJDQALCyAFDQwgAEEEaigCACEKIAxCADcD4BwCQCAKQSFJDQAgDEHgHGogChAlCyAMQbgKaiAMQeAcakGIAhBGGiAMQcAMaiAAEBECQCAAKAIAIgcgAEEIaigCACIBTw0AIAdBA3QhCiAMQbgKakEIaiEIIAxBwAxqQQhqIQQgDEHADGpBDGohFANAIAcgAk8NBgJAIAMgB2otAAANACAUKAIAIAwoAsAMIg0gDUEgSyINGyILIAcgACgCACIJayIQTQ0MIAQoAgAgBCANGyAJQQN0ayAKaiINKAIAIQsgDUEEaigCACEQAkAgDEG4CmpBDGooAgAgDCgCuAoiDSANQSBLIhEbIgkgDUEgIBEbIhFHDQACQAJAIBFBAWoiDSARSQ0AQQAhEQJAIA1BAkkNAEF/IA1Bf2pndiERCyARQQFqIg0gEU8NAQtBfyENCyAMQbgKaiANECUgDCgCuAohDQsgCCgCACERIAxBuApqQQxBACANQSBLIg0baiAJQQFqNgIAIBEgCCANGyAJQQN0aiINIBA2AgQgDSALNgIACyAKQQhqIQogB0EBaiIHIAFJDQALIAAoAgAhBwsgDEIANwPgHAJAIAdBIUkNACAMQeAcaiAHECUgACgCACEHCyAMQdAUaiAMQeAcakGIAhBGGgJAAkACQCAHRQ0AIAxB0BRqQQhqIQggDEGIAmpBDGohFEEAIRFBACEBQQAhCgNAIAogAk8NBgJAAkAgAyAKai0AAEUNACAMQQxqKAIAIAwoAgAiDSANQSBLIg0bIgkgAU0NDSAMQQhqKAIAIBIgDRsgAUEDdGohDSABQQFqIQEMAQsgFCgCACAMKAKIAiINIA1BIEsiDRsiCSARTQ0NIAxBiAJqQQhqKAIAIBMgDRsgEUEDdGohDSARQQFqIRELIApBAWohCiANKAIAIQQgDSgCBCELAkAgDEHQFGpBDGooAgAgDCgC0BQiDSANQSBLIhAbIgkgDUEgIBAbIhBHDQACQAJAIBBBAWoiDSAQSQ0AQQAhEAJAIA1BAkkNAEF/IA1Bf2pndiEQCyAQQQFqIg0gEE8NAQtBfyENCyAMQdAUaiANECUgDCgC0BQhDQsgCCgCACEQIAxB0BRqQQxBACANQSBLIg0baiAJQQFqNgIAIBAgCCANGyAJQQN0aiINIAs2AgQgDSAENgIAIAogB0kNAAsgDCgC0BQhCiAAKAIAIgINAQwCC0EAIQIgDCgC0BQhCkEARQ0BCyAMQZAEakEMaigCACAMKAKQBCIHIAdBIEsiBxshCSAMQZAEakEIaiINKAIAIA0gBxshASAMQdAUakEMaigCACAKIApBIEsiBxshAyAMQdAUakEIaiIKKAIAIAogBxshCiAMQbgKakEMaigCACAMKAK4CiIHIAdBIEsiBxshCCAMQbgKakEIaiINKAIAIA0gBxshBEEAIQcDQCAHIANPDQUgACAEIAggByAKKAIAIApBBGooAgAgASAJEAkgCkEIaiEKIAdBAWoiDSEHIA0gAkkNAAsgDCgC0BQhCgsCQAJAIApBIU8NACAMKALADCIKQSFPDQEMDAsgDEHYFGooAgAgCkEDdEEEEGcgDCgCwAwiCkEhSQ0LCyAMQcgMaigCACAKQQN0QQQQZyAMKAK4CiIKQSFPDQsMDAtBkLTEACAKIAIQOgALQeCzxAAgByAEEDoAC0GwtMQAIAogAhA6AAtB4LPEACAHIAMQOgALQaC0xAAgByACEDoACyAJIAQQOwALIAQgEBA5AAtBwLPEACABIAkQOgALQcCzxAAgESAJEDoAC0HAs8QAIBAgCxA6AAsgDCgCuAoiCkEhSQ0BCyAMQcAKaigCACAKQQN0QQQQZwsCQCAMKAKwCCIKQSFJDQAgDEG4CGooAgAgCkEDdEEEEGcLIAwoAqwIIgogCigCACIKQX9qNgIAAkACQAJAAkACQAJAAkACQAJAAkACQCAKQQFGDQBBISEKIAwoAqAHIgdBIU8NAQwCCyAMQawIahBBQSEhCiAMKAKgByIHQSFJDQELIAxBqAdqKAIAIAdBAnRBBBBnIAwoApgGIgcgCkkNAQwCCyAMKAKYBiIHIApPDQELQSEhCiAMKAKQBCIHQSFPDQEMAgsgDEGgBmooAgAgB0ECdEEEEGdBISEKIAwoApAEIgdBIUkNAQsgDEGYBGooAgAgB0EDdEEEEGcgDCgCiAIiByAKSQ0BDAILIAwoAogCIgcgCk8NAQsgDCgCACIKQSFJDQIMAQsgDEGQAmooAgAgB0EDdEEEEGcgDCgCACIKQSFJDQELIAxBCGooAgAgCkEDdEEEEGcLQQ0hBwsgBkHwJGokACAHC8cWATh/IwBBsCBrIgIkAAJAAkACQAJAAkACQAJAIAEoAgAiAyABKAIERw0AIAJBkAhqIAMQFCABKAIAIgQgAigCkAhHDQEgAigClAggAUEEaigCAGoiBSAEbCIGQX9MDQICQAJAAkAgBkUNAEEBIQcgBkEBEG0iCEUNBiAGIQkgBkGACE0NAQwCC0EBIQgLIAJBoBBqIAggBhBGGiACQawgakECaiACQaAQakECai0AADoAACACIAIvAKAQOwGsICACKACjECEKIAIoAKcQIQkgAkGwGGogAkGrEGpB+AcQRhpBACEHAkAgBkUNACAIIAZBARBnCyAKIQgLIAJBrBBqIAc6AAAgAkGgEGpBDWoiCyACLwGsIDsAACACQaAQakEUaiIMIAk2AgAgAkGgEGpBEGoiDSAINgIAIAJBrxBqIAJBriBqLQAAOgAAIAIgBjYCqBAgAiAFNgKkECACIAQ2AqAQIAJBuBBqIAJBsBhqQfgHEEYaIAEoAgAiDkUNBCABQQ1qIQ8gAkGQCGpBDWohEEEAIRFBASESIAFBBGohE0EIIRQgAkGQCGpBCGohFUGACCEWIAJBkAhqQRRqIRdBACEYDAULQYyIwABBJEH0tcQAEE0ACyACQbwYakEYNgIAIAJBtBBqQQI2AgAgAkEYNgK0GCACIAE2ArAYIAJCAjcCpBAgAkHUtcQANgKgECACIAJBkAhqNgK4GCACIAJBsBhqNgKwECACQaAQakHktcQAED8ACxByAAsgBkEBEGkAC0EAIQYMAQtBASEGCwNAAkACQAJAAkACQAJAAkACQAJAAkAgBg4CAAEBCwJAIAIgAkGgEGpBkAgQRiIGKAKYCCIIQYEISQ0AIAZBoAhqKAIAIAhBARBnCyAGKAIAIhtFDQUgBkENaiEcQQAhHUEBIR5BCCEfIAZBCGohIEGACCEhIAZBFGohIiAGQRBqISNBtpHAACEkQbiLwAAhJUH/ASEmQf4DISdBuI3AACEoQQEhKUEAISpBASEYDAELAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgGA4DAAECAgtBACEGAkAgEygCACIFRQ0AQQAhCCAFIQYDQCABQRRqKAIAIAEgFGooAgAiBCAEIBZLIgQbIgcgCCARIAZsaiIGTQ0FIAwoAgAgAkGgEGogFGooAgAiByAHIBZLIgcbIgogCCARIAIoAqQQbGoiCU0NBiANKAIAIAsgBxsgCWogAUEQaigCACAPIAQbIAZqLQAAOgAAIBMoAgAhBiAIIBJqIgggBUkNAAsLAkAgAigClAgiGUUNACAXKAIAIBUoAgAiCCAIIBZLIgUbIhogGSARbCIKTQ0LQQEhBEEAIQgDQCAMKAIAIAJBoBBqIBRqKAIAIgcgByAWSyIHGyIaIAYgCGogESACKAKkEGwiCWpNDQcgDSgCACALIAcbIAZqIAggCWpqIAJBkAhqQRBqKAIAIBAgBRsgCmotAAA6AAAgCCASaiIHIBlPDQEgAigClAggEWwiCSAEaiEKIAchCCAEIBJqIQQgFygCACAVKAIAIgUgBSAWSyIFGyIaIAkgB2oiB0sNAAwNCwsgESASaiIRIA5JDRFBACEGDBoLICIoAgAiKyAgKAIAIiwgLCAhSyIKGyIJIAIoAgQiBCAqbCItICpqIhhNDQsCQCAjKAIAIBwgChsiGSAYai0AAA0AIAQgKmwhCCAqIAQgKWxqIQZBASEHIAIoAgAhGgNAICogB2ogGk8NASAJIAZNDQcgCCAEaiEIIAcgHmohByAZIAZqIQUgBiAEaiEGIAUtAABFDQALIARFDQAgByAeRg0AIAkgLU0NCSAEICpsIQVBACEGA0AgCSAIIAZqIgdNDQggIygCACAcIAobIgkgBWogBmoiCi0AACEZIAogCSAIaiAGai0AADoAACAiKAIAICAoAgAiCSAJICFLIgkbIgogB00NCSAjKAIAIBwgCRsgCGogBmogGToAAAJAIAYgHmoiByAETw0AIAchBiAiKAIAICAoAgAiCSAJICFLIgobIgkgBSAHaiItSw0BDAsLCyACKAIEIgQgKmwgKmohGCAiKAIAISsgICgCACEsCyArICwgLCAhSyIHGyIKIBhNDQwCQCAjKAIAIgggHCAHGyAYai0AACIGIB5GDQAgBkUNAiAGICVqLQAAIgYgJnMgHSAGayAGGyIGICdPDQ4gBEUNACAKIAQgKmwiCU0NDyAGIChqLQAAIRlBASEIQQAhBgNAICMoAgAgHCAHGyAJaiIHIActAAAgH3QgGXIgJGotAAA6AAAgBiAeaiIGIARPDQEgAigCBCAqbCIFIAhqIQkgCCAeaiEIICIoAgAgICgCACIHIAcgIUsiBxsiCiAFIAZqIgVLDQAMEQsLICogHmoiLSACKAIAIixPDRQgLSEuQQAhBgwSCyAxRQ0SQQAhOUEBIQYMEQsgAEECOgAMICxBgQhJDRQgCCAsQQEQZwwUC0GUtcQAIAYgBxA6AAtBpLXEACAJIAoQOgALQaS1xAAgCSAGaiAIaiAaEDoAC0GUtcQAIAYgCRA6AAtBlLXEACAHIAkQOgALQaS1xAAgByAKEDoAC0GUtcQAIC0gCRA6AAsgCiEHC0GUtcQAIAcgGhA6AAtBlLXEACAYIAkQOgALQZS1xAAgGCAKEDoAC0GUtsQAIAZB/gMQOgALIAkhBQtBlLXEACAFIAoQOgALQQAhGEEBIQYMCAtBASEGDAcLA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgBg4CAAEBCyAiKAIAICAoAgAiBiAGICFLIgQbIgcgAigCBCIZIC5sICpqIgZNDQMCQCAjKAIAIBwgBBsgBmotAAAiGkUNACAZRQ0AIAcgGSAqbCIJTQ0GQQEhCEEAIQYgGSEFA0AgByAGIC4gBWxqIgVNDQMgIygCACAcIAQbIgQgBWoiByAHLQAAIBogH3QgBCAJai0AAHIgJGotAABzOgAAIAYgHmoiBiAZTw0BIAIoAgQiBSAqbCIKIAhqIQkgCCAeaiEIICIoAgAgICgCACIEIAQgIUsiBBsiByAKIAZqIgpLDQAMCAsLIC4gHmoiLiAsSQ0JDA0LIDYoAgAgNCgCACIGIAYgNUsiBBsiByACKAIEIhkgOWwgMWoiBk0NAwJAIDcoAgAgMCAEGyAGai0AACIaRQ0AIBlFDQAgByAZIDFsIglNDQdBASEIQQAhBiAZIQUDQCAHIAYgOSAFbGoiBU0NAyA3KAIAIDAgBBsiBCAFaiIHIActAAAgGiAzdCAEIAlqLQAAciA4ai0AAHM6AAAgBiAyaiIGIBlPDQEgAigCBCIFIDFsIgogCGohCSAIIDJqIQggNigCACA0KAIAIgQgBCA1SyIEGyIHIAogBmoiCksNAAwJCwsgOSAyaiI5IDFJDQkMCwtBpLXEACAFIAcQOgALQaS1xAAgBSAHEDoAC0GUtcQAIAYgBxA6AAtBlLXEACAGIAcQOgALIAkhCgtBlLXEACAKIAcQOgALIAkhCgtBlLXEACAKIAcQOgALQQAhBgwBC0EBIQYMAAsLIDEgMmoiMSAvTw0BQQIhGEEBIQYMBQsgKSAeaiEpIC0hKiAtIBtJDQIgAigCACIvRQ0AIAJBDWohMEEAITFBASEyQQghMyACQQhqITRBgAghNSACQRRqITYgAkEQaiE3QbaRwAAhOEECIRgMAwsgACACQQAgAyADIANBAXQQDiACKAIIIgZBgQhJDQAgAkEQaigCACAGQQEQZyACQbAgaiQADwsgAkGwIGokAA8LQQEhGEEBIQYMAQtBASEGDAALC/oKAg9/AX4jAEEgayIDJABBASEEAkAgAigCGEEiIAJBHGooAgAoAhARAAANAAJAAkAgAUUNACAAIAFqIQUgAkEYaiEGIAJBHGohByAAIQhBACEJQQAhCgJAA0AgCCELIAhBAWohDAJAAkAgCCwAACINQQBIDQAgDUH/AXEhDSAMIQgMAQsCQAJAIAwgBUYNACAMLQAAQT9xIQ4gCEECaiIIIQwMAQtBACEOIAUhCAsgDUEfcSEPAkACQAJAIA1B/wFxIg1B4AFJDQAgCCAFRg0BIAgtAABBP3EhECAIQQFqIgwhEQwCCyAOIA9BBnRyIQ0gDCEIDAILQQAhECAFIRELIBAgDkEGdHIhDgJAAkACQCANQfABSQ0AIBEgBUYNASARQQFqIQggES0AAEE/cSENDAILIA4gD0EMdHIhDSAMIQgMAgtBACENIAwhCAsgDkEGdCAPQRJ0QYCA8ABxciANciINQYCAxABGDQILQQIhDAJAAkACQAJAAkACQAJAAkACQCANQXdqIg9BHksNAEH0ACEOAkAgDw4fCAADAwQDAwMDAwMDAwMDAwMDAwMDAwMDAwIDAwMDAggLQe4AIQ4MBAsgDUHcAEcNAQsgDSEODAULQaC7xAAgDRAhRQ0CDAMLQfIAIQ4LDAILAkAgDUH//wNLDQAgDUGgm8QAQShB8JvEAEGvAkGfnsQAQbwCEBdFDQEMAwsCQCANQf//B0sNACANQdugxABBIUGdocQAQZ4BQbuixABB/QIQF0UNAQwDCyANQe+DOEsNACANQeKLdGpB4o0sSQ0AIA1Bn6h0akGfGEkNACANQd7idGpBDkkNACANQf7//wBxQZ7wCkYNACANQamydWpBKUkNACANQcuRdWpBCksNAgsgDUEBcmdBAnZBB3OtQoCAgIDQAIQhEkEDIQwgDSEOCyADIAE2AgQgAyAANgIAIAMgCTYCCCADIAo2AgwCQCAKIAlJDQACQCAJRQ0AIAkgAUYNACAJIAFPDQEgACAJaiwAAEG/f0wNAQsCQCAKRQ0AIAogAUYNACAKIAFPDQEgACAKaiwAAEG/f0wNAQsCQCAGKAIAIAAgCWogCiAJayAHKAIAKAIMEQYADQADQAJAAkACQAJAAkACQAJAIAxBAUYNAEHcACEJAkAgDEECRg0AIAxBA0cNBiASQiCIp0H/AXFBf2oiDEEESw0GAkAgDA4FAAYEBQMACyASQv////+PYIMhEkEDIQxB/QAhCQwHC0EBIQwMBgtBACEMIA4hCQwFCyASQv////+PYINCgICAgMAAhCESQQMhDAwECyASQv////+PYINCgICAgCCEIRJBAyEMQfsAIQkMAwsgEkL/////j2CDQoCAgIAwhCESQQMhDEH1ACEJDAILIA4gEqciD0ECdEEccXZBD3EiDEEwciAMQdcAaiAMQQpJGyEJAkAgD0UNACASQn98Qv////8PgyASQoCAgIBwg4QhEkEDIQwMAgsgEkL/////j2CDQoCAgIAQhCESQQMhDAwBC0EBIQwCQCANQYABSQ0AQQIhDCANQYAQSQ0AQQNBBCANQYCABEkbIQwLIAwgCmohCQwECyAGKAIAIAkgBygCACgCEBEAAEUNAAsLQQEhBAwGCyADIANBDGo2AhggAyADQQhqNgIUIAMgAzYCECADQRBqEFMACyAKIAtrIAhqIQogBSAIRw0ACwsgCUUNASAJIAFGDQECQCAJIAFPDQAgACAJaiwAAEG/f0oNAgsgACABIAkgARAEAAtBACEJCyACQRhqIgwoAgAgACAJaiABIAlrIAJBHGoiCigCACgCDBEGAA0AIAwoAgBBIiAKKAIAKAIQEQAAIQQLIANBIGokACAEC5wJAQp/IwBBwABrIgMkACADQSRqIAE2AgAgA0E0aiACQRRqKAIAIgQ2AgAgA0EDOgA4IANBLGogAigCECIFIARBA3RqNgIAIANCgICAgIAENwMIIAMgADYCIEEAIQYgA0EANgIYIANBADYCECADIAU2AjAgAyAFNgIoAkACQAJAAkACQCACKAIIIgdFDQAgAigCACEIIAIoAgQiCSACQQxqKAIAIgUgBSAJSxsiCkUNASAAIAgoAgAgCCgCBCABKAIMEQYADQIgCEEMaiEFIANBOGohASADQTRqIQsgA0Ew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QZeVxABBEBBKDAoLIAIgAUGGlcQAQREQSgwJCyACIAFB9JTEAEESEEoMCAsgAiABQeGUxABBExBKDAcLIAIgAUHPlMQAQRIQSgwGCyACIAFBvJTEAEETEEoMBQsgAiABQaqUxABBEhBKDAQLIAIgAUGXlMQAQRMQSgwDCyACIAFBjZTEAEEKEEoMAgsgAiABQfyTxABBERBKDAELIAIgAUHwk8QAQQwQSgsgAhArIQEgAkEQaiQAIAEL+QEBAn8jAEEQayIEJAAgBCABKAIAIgUoAgA2AgwCQAJAAkAgAkECaiICIAJsIgJBgBAgAkGAEEsbIgFBBCAEQQxqQYOCwABBwLLEABAMIgJFDQAgBSAEKAIMNgIADAELIARBg4LAACABQQQQMgJAAkAgBCgCAEUNACAFIAQoAgw2AgAMAQsgBCgCBCICIAQoAgw2AgggBCACNgIMIAFBBCAEQQxqQYOCwABBwLLEABAMIQIgBSAEKAIMNgIAIAINAQtBASEBDAELIAJCADcCBCACIAIgAUECdGpBAnI2AgBBACEBCyAAIAI2AgQgACABNgIAIARBEGokAAvmAQEEfyMAQTBrIgIkACABQQRqIQMCQCABKAIEDQAgASgCACEEIAJBADYCECACQgE3AwggAiACQQhqNgIUIAJBGGpBEGogBEEQaikCADcDACACQRhqQQhqIgUgBEEIaikCADcDACACIAQpAgA3AxggAkEUakG0t8QAIAJBGGoQAxogBSACKAIQNgIAIAIgAikDCDcDGAJAIAMoAgAiBEUNACABQQhqKAIAIgFFDQAgBCABQQEQZwsgAyACKQMYNwIAIANBCGogBSgCADYCAAsgAEHwt8QANgIEIAAgAzYCACACQTBqJAAL0wEBA38gAC0ACCEBAkAgACgCBCICRQ0AIAFB/wFxIQNBASEBAkAgAw0AAkAgACgCACIDLQAAQQRxRQ0AQQEhASADKAIYQd2axABBASADQRxqKAIAKAIMEQYADQEgAEEEaigCACECCwJAIAJBAUcNACAALQAJRQ0AQQEhASAAKAIAIgMoAhhB3JrEAEEBIANBHGooAgAoAgwRBgANAQsgACgCACIBKAIYQd6axABBASABQRxqKAIAKAIMEQYAIQELIABBCGogAToAAAsgAUH/AXFBAEcLuAEBAX8jAEEQayIEJAACQAJAIAFFDQAgBCABNgIEIAJFDQAgA0EESw0BIAJBA2pBAnZBf2oiAUH/AUsNASAAIAFBAnRqQQRqIgFFDQEgBCAANgIIIAQgASgCADYCDCAEQQRqIARBDGogBEEIakHwssQAEB8gASAEKAIMNgIACyAEQRBqJAAPCyAEIAAoAgA2AgwgBEEEaiAEQQxqQYOCwABB2LLEABAfIAAgBCgCDDYCACAEQRBqJAALjwEBA38jAEGAAWsiAiQAIAAoAgAhA0EAIQADQCACIABqQf8AaiADQQ9xIgRBMHIgBEHXAGogBEEKSRs6AAAgAEF/aiEAIANBBHYiAw0ACwJAIABBgAFqIgNBgQFPDQAgAUEBQZKZxABBAiACIABqQYABakEAIABrEAYhACACQYABaiQAIAAPCyADQYABEDsAC44BAQN/IwBBgAFrIgIkACAAKAIAIQNBACEAA0AgAiAAakH/AGogA0EPcSIEQTByIARBN2ogBEEKSRs6AAAgAEF/aiEAIANBBHYiAw0ACwJAIABBgAFqIgNBgQFPDQAgAUEBQZKZxABBAiACIABqQYABakEAIABrEAYhACACQYABaiQAIAAPCyADQYABEDsAC4sBAQV/AkAgACgCCCIBRQ0AIAAoAgAhAiABQQR0IQEDQAJAIAJBBGoiAygCAEUNAAJAIAIoAgAiBEUNACAEIAQoAgAiBUF/ajYCACAFQQFHDQAgAhBACyADEC8LIAJBEGohAiABQXBqIgENAAsLAkAgAEEEaigCACICRQ0AIAAoAgAgAkEEdEEEEGcLC4sBAQV/AkAgACgCCCIBRQ0AIAAoAgAhAiABQQR0IQEDQAJAIAJBBGoiAygCAEUNAAJAIAIoAgAiBEUNACAEIAQoAgAiBUF/ajYCACAFQQFHDQAgAhBBCyADEDALIAJBEGohAiABQXBqIgENAAsLAkAgAEEEaigCACICRQ0AIAAoAgAgAkEEdEEEEGcLC4cBAQJ/AkAgACgCBCICIAAoAggiA2sgAU8NAAJAAkAgAyABaiIBIANJDQAgAkEBdCIDIAEgASADSRsiAUEASA0AAkACQCACRQ0AIAAoAgAgAkEBIAEQYiICRQ0BDAMLIAFBARBsIgINAgsgAUEBEGkACxBvAAsgACACNgIAIABBBGogATYCAAsLcgACQEEAIAJBAnQiAiADQQN0QYCAAWoiAyADIAJJG0GHgARqIgJBEHZAACIDQRB0IANBf0YbIgNFDQAgA0IANwIEIAMgAyACQYCAfHFqQQJyNgIAIAAgAzYCBCAAQQA2AgAPCyAAIAM2AgQgAEEBNgIAC4EBAQF/IwBBwABrIgQkACAEIAE2AgwgBCAANgIIIAQgAzoAFCAEIAI2AhAgBEE8akERNgIAIARBLGpBAjYCACAEQQ82AjQgBEICNwIcIARBwLTEADYCGCAEIARBEGo2AjggBCAEQQhqNgIwIAQgBEEwajYCKCAEQRhqQdC0xAAQRAALewEBfyMAQTBrIgIkACACQRRqQSo2AgAgAkEqNgIMIAIgADYCCCACIABBBGo2AhAgAUEcaigCACEAIAEoAhghASACQSxqQQI2AgAgAkICNwIcIAJBmLjEADYCGCACIAJBCGo2AiggASAAIAJBGGoQAyEBIAJBMGokACABC3oBAX8jAEHAAGsiAyQAIAMgATYCDCADIAA2AgggAyACOgAXIANBPGpBATYCACADQSxqQQI2AgAgA0ECNgI0IANCAjcCHCADQaCyxAA2AhggAyADQRdqNgI4IAMgA0EIajYCMCADIANBMGo2AiggA0EYakGwssQAEEQAC3oBAX8jAEHAAGsiAyQAIAMgATYCDCADIAA2AgggAyACOgAXIANBPGpBDjYCACADQSxqQQI2AgAgA0EPNgI0IANCAjcCHCADQcC0xAA2AhggAyADQRdqNgI4IAMgA0EIajYCMCADIANBMGo2AiggA0EYakHQtMQAEEQAC3MBAX8jAEHAAGsiAiQAIAIgATYCDCACIAA2AgggAkE0akEQNgIAIAJBJGpBAjYCACACQQ82AiwgAkICNwIUIAJBwLTEADYCECACIAJBOGo2AjAgAiACQQhqNgIoIAIgAkEoajYCICACQRBqQdC0xAAQRAALcAIEfwF+IwBBMGsiASQAIAAQcBBZIQIgABBzEFohAyABQQhqIAIQaiABKQMIIQUgAhB0IQQgASACEHU2AhwgASAENgIYIAEgBTcDECABQQA2AiQgASADNgIgIAFBIGpB3LfEACAAEHMgAUEQahAnAAtvAQF/IwBBMGsiAiQAIAIgATYCBCACIAA2AgAgAkEsakEYNgIAIAJBHGpBAjYCACACQRg2AiQgAkICNwIMIAJB4LjEADYCCCACIAJBBGo2AiggAiACNgIgIAIgAkEgajYCGCACQQhqQfC4xAAQRAALbAEBfyMAQTBrIgMkACADIAI2AgQgAyABNgIAIANBLGpBGDYCACADQRxqQQI2AgAgA0EYNgIkIANCAjcCDCADQbi4xAA2AgggAyADNgIoIAMgA0EEajYCICADIANBIGo2AhggA0EIaiAAEEQAC28BAX8jAEEwayICJAAgAiABNgIEIAIgADYCACACQSxqQRg2AgAgAkEcakECNgIAIAJBGDYCJCACQgI3AgwgAkGAucQANgIIIAIgAkEEajYCKCACIAI2AiAgAiACQSBqNgIYIAJBCGpBkLnEABBEAAtjAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQQhqQRBqIAFBEGopAgA3AwAgAkEIakEIaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQbS3xAAgAkEIahADIQEgAkEgaiQAIAELaAIBfwN+IwBBMGsiASQAIAApAgghAiAAKQIQIQMgACkCACEEIAFBFGpBADYCACABIAQ3AxggAUGolsQANgIQIAFCATcCBCABIAFBGGo2AgAgASADNwMoIAEgAjcDICABIAFBIGoQRAALaAECfyABKAIAIQIgAUEANgIAAkACQCACRQ0AIAEoAgQhA0EIQQQQbCIBRQ0BIAEgAzYCBCABIAI2AgAgAEH0tMQANgIEIAAgATYCAA8LIABBhLXEADYCBCAAQQE2AgAPC0EIQQQQaQALYgEBfyMAQTBrIgIkACACQSBqIAEoAgAgASgCBCABKAIIIAEoAgwQVCACQRRqIAJBKGopAwA3AgAgAiAANgIIIAJBzLfEADYCBCACQcCVxAA2AgAgAiACKQMgNwIMIAIQOAALVgECfwJAIAAoAgAiAUEQaigCACICQYEISQ0AIAFBGGooAgAgAkEBEGcgACgCACEBCyABIAEoAgQiAkF/ajYCBAJAIAJBAUcNACAAKAIAQZgIQQQQZwsLVgECfwJAIAAoAgAiAUEQaigCACICQYEISQ0AIAFBGGooAgAgAkEBEGcgACgCACEBCyABIAEoAgQiAkF/ajYCBAJAIAJBAUcNACAAKAIAQZgIQQQQZwsLVQEBfwJAAkACQCABQYCAxABGDQBBASEEIAAoAhggASAAQRxqKAIAKAIQEQAADQELIAJFDQEgACgCGCACIAMgAEEcaigCACgCDBEGACEECyAEDwtBAAtIAQF/IwBBEGsiAiQAAkACQCAALQAAQQFHDQAgAiABQd2TxABBCRBKDAELIAIgAUHmk8QAQQoQSgsgAhArIQEgAkEQaiQAIAELSgIBfwF+IwBBIGsiAiQAIAEpAgAhAyACQRRqIAEpAgg3AgAgAiADNwIMIAIgADYCCCACQai4xAA2AgQgAkGolsQANgIAIAIQbgALLgACQCAAQXxLDQACQCAARQ0AIAAgAEF9SUECdBBsIgBFDQEgAA8LQQQPCxBxAAs2AQF/AkAgAkUNACAAIQMDQCADIAEtAAA6AAAgA0EBaiEDIAFBAWohASACQX9qIgINAAsLIAALNwEBfwJAQZjHxAAgAyACEBAiBEUNACAEIAAgAyABIAEgA0sbEEYaQZjHxAAgACABIAIQLAsgBAsxACAAKAIAIQACQCABEF9FDQAgACABEC0PCwJAIAEQYEUNACAAIAEQLg8LIAAgARBkCzwBAX9BACEAAkACQEEAKALIz0RBAUcNAEEAKALMz0QhAAwBC0EAQgE3A8jPRAtBACAANgLMz0QgAEEARws0ACAAIAEoAhggAiADIAFBHGooAgAoAgwRBgA6AAggACABNgIAIAAgA0U6AAkgAEEANgIECy8BAX8gACgCACIAIAIQMSAAIAAoAggiAyACajYCCCADIAAoAgBqIAEgAhBGGkEACywBAX8CQCACRQ0AIAAhAwNAIAMgAToAACADQQFqIQMgAkF/aiICDQALCyAACywBAX8jAEEQayIDJAAgAyABNgIMIAMgADYCCCADQQhqQeC0xABBACACECcACykBAX8jAEEQayICJAAgAiABQbCIwABBDhBKIAIQKyEBIAJBEGokACABCyYBAX8CQCAAKAIEIgFFDQAgAEEIaigCACIARQ0AIAEgAEEBEGcLCyUBAX8jAEEQayICJAAgAiABNgIMIAIgADYCCCACQQhqEIIBGgALIAACQEGYx8QAIAAgARAQIgFFDQAgAUEAIAAQTBoLIAELKgEBfyAAQfS0xABBhLXEACABKAIAIgIbNgIEIAAgAUHDhcAAIAIbNgIACyYBAX8gACgCACIBKAIAIAEoAgQgACgCBCgCACAAKAIIKAIAEAQACx4AIAAgBDYCDCAAIAM2AgggACACNgIEIAAgATYCAAsaACAAQgA3AgQgAEEENgIAIABBDGpCADcCAAscAQF/AkAgACgCBCIBRQ0AIAAoAgAgAUEBEGcLCxoBAX8gACABQQAoArjPRCICQRogAhsRBQAACxQAIAAgASACIAMgBEEBEABB/wFxCxUAAkAgAEUNACAADwtBnLfEABA9AAsVAAJAIABFDQAgAA8LQZy3xAAQPQALEgACQCABRQ0AIAAgAUEEEGcLCxAAIAAoAgAgACgCBCABEGsLEAAgACgCACAAKAIEIAEQawsQACABIAAoAgAgACgCBBAFCw0AIAAtAABBEHFBBHYLDQAgAC0AAEEgcUEFdgsPAEGYx8QAIAAgASACECwLDAAgACABIAIgAxBHCw4AIAAgASACQYCAAhATCw0AIAA1AgBBASABEBwLDQAgADUCAEEBIAEQHAsNAEGYx8QAIAAgARAQCwoAIAAgASACEGELDQBBw4XAAEEZIAEQAgsJACAAIAEQVwALDAAgACABKQIANwIACwoAIAIgACABEAULCAAgACABEGYLCAAgACABEFELBwAgABA4AAsKAEGAuMQAED0ACwcAIABBDGoLBQAQfwALBQAQbwALBwAgACgCCAsHACAAKAIICwcAIAAoAgwLBAAgAQsEAEEACwUAQYAECwQAQQELBwBBnM/EAAsMAELkrsKFl5uliBELDQBChJbbgd3goOPoAAsNAELNp7n04KW6rJV/Cw0AQs2ytoWB2Ij99wALAwAACwQAQQALBABBAAsDAAALDQBCzae59OCluqyVfwsCAAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsL7c+EgAADAEGAgMAAC8CxBGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWVhc3NlcnRpb24gZmFpbGVkOiBtaWQgPD0gbGVuc3JjL2xpYmNvcmUvc2xpY2UvbW9kLnJzYXNzZXJ0aW9uIGZhaWxlZDogY2h1bmtfc2l6ZSAhPSAwc3JjL2xpYi5ycwAAAAAAAGF0dGVtcHQgdG8gZGl2aWRlIGJ5IHplcm8AAAAJAAAACgAAAAsAAAAMAAAADQAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAAOiBzcmMvbGliY29yZS9yZXN1bHQucnNjYWxsZWQgYFJlc3VsdDo6dW53cmFwKClgIG9uIGFuIGBFcnJgIHZhbHVlYXNzZXJ0aW9uIGZhaWxlZDogY2h1bmtfc2l6ZSAhPSAwc3JjL2xpYmNvcmUvc2xpY2UvbW9kLnJzYXNzZXJ0aW9uIGZhaWxlZDogbWlkIDw9IGxlbgAAAAAAAAAAAAAAAAAvaG9tZS9uYXphci1wYy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zbWFsbHZlYy0wLjYuMTAvbGliLnJzAAAAAAAAAAAAAAAvaG9tZS9uYXphci1wYy8uY2FyZ28vZ2l0L2NoZWNrb3V0cy9yZWVkLXNvbG9tb24tZXJhc3VyZS0wNTcwOWMwMGRlZjE0NGQwLzg1ZjhkY2Ivc3JjL21hY3Jvcy5ycwAvaG9tZS9uYXphci1wYy8uY2FyZ28vZ2l0L2NoZWNrb3V0cy9yZWVkLXNvbG9tb24tZXJhc3VyZS0wNTcwOWMwMGRlZjE0NGQwLzg1ZjhkY2Ivc3JjL2xpYi5yczogc3JjL2xpYmNvcmUvcmVzdWx0LnJzUG9pc29uRXJyb3IgeyBpbm5lcjogLi4gfQAAAAAvaG9tZS9uYXphci1wYy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zbWFsbHZlYy0wLjYuMTAvbGliLnJzQ29sb21uIGNvdW50IG9uIGxlZnQgaXMgZGlmZmVyZW50IGZyb20gcm93IGNvdW50IG9uIHJpZ2h0LCBsaHMgOiAsIHJocyA6IC9ob21lL25hemFyLXBjLy5jYXJnby9naXQvY2hlY2tvdXRzL3JlZWQtc29sb21vbi1lcmFzdXJlLTA1NzA5YzAwZGVmMTQ0ZDAvODVmOGRjYi9zcmMvbWF0cml4LnJzTWF0cmljZXMgZG8gbm90IGhhdmUgdGhlIHNhbWUgcm93IGNvdW50LCBsaHMgOiBUcnlpbmcgdG8gaW52ZXJ0IGEgbm9uLXNxdWFyZSBtYXRyaXhTaW5ndWxhck1hdHJpeC9ob21lL25hemFyLXBjLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NtYWxsdmVjLTAuNi4xMC9saWIucnNh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YnN0ZC9zeXMvd2FzbS9tdXRleC5yc2Nhbm5vdCByZWN1cnNpdmVseSBhY3F1aXJlIG11dGV4Y2FsbGVkIGBSZXN1bHQ6OnVud3JhcCgpYCBvbiBhbiBgRXJyYCB2YWx1ZQAAAC9ydXN0Yy85MTg1NmVkNTJjNThhYTViYTY2YTAxNTM1NGQxY2M2OWU5Nzc5YmRmL3NyYy9saWJjb3JlL3NsaWNlL21vZC5ycy9ob21lL25hemFyLXBjLy5jYXJnby9naXQvY2hlY2tvdXRzL3JlZWQtc29sb21vbi1lcmFzdXJlLTA1NzA5YzAwZGVmMTQ0ZDAvODVmOGRjYi9zcmMvaW52ZXJzaW9uX3RyZWUucnNleHBsaWNpdCBwYW5pY05vdFNxdWFyZUFscmVhZHlTZXRJbnZhbGlkSW5kZXhJbnZhbGlkU2hhcmRGbGFnc0VtcHR5U2hhcmRUb29GZXdTaGFyZHNQcmVzZW50SW5jb3JyZWN0U2hhcmRTaXplVG9vTWFueUJ1ZmZlclNoYXJkc1Rvb0Zld0J1ZmZlclNoYXJkc1Rvb01hbnlQYXJpdHlTaGFyZHNUb29GZXdQYXJpdHlTaGFyZHNUb29NYW55RGF0YVNoYXJkc1Rvb0Zld0RhdGFTaGFyZHNUb29NYW55U2hhcmRzVG9vRmV3U2hhcmRzY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZXNyYy9saWJjb3JlL29wdGlvbi5yc3NyYy9saWJhbGxvYy9yYXdfdmVjLnJzY2FwYWNpdHkgb3ZlcmZsb3dgLi5pbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWVzcmMvbGliY29yZS9vcHRpb24ucnNzcmMvbGliY29yZS9zbGljZS9tb2QucnNpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggc2xpY2UgaW5kZXggc3RhcnRzIGF0ICBidXQgZW5kcyBhdCBzcmMvbGliY29yZS9zdHIvbW9kLnJzWy4uLl1ieXRlIGluZGV4ICBpcyBvdXQgb2YgYm91bmRzIG9mIGBiZWdp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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////+/tgAAAAAAAAAAAP8HAAAAAAD4//8AAAEAAAAAAAAAAAAAAMCfnz0AAAAAAgAAAP///wcAAAAAAAAAAAAAwP8BAAAAAAAA+A8guBIRAEoAAAAIFREAAAIAAAgXEQA3AAAAAAECAwQFBgcICQgKCwwNDg8QERITFAIVFhcYGRobHB0eHyACAgICAgICAgICIQICAgICAgICAgICAgICIiMkJSYCJwIoAgICKSorAiwtLi8wAgIxAgICMgICAgICAgICMwICNAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNQI2AjcCAgICAgICAjgCOQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICOjs8AgICAj0CAj4/QEFCQ0RFRgICAkcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICSAICAgICAgICAgICSQICAgICOwIAAQICAgIDAgICAgQCBQYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGYx8QAC7gIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPu/gIAABG5hbWUB8L+AgACNAQBKcmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjpyZWNvbnN0cnVjdF9pbnRlcm5hbDo6aGQ0MzhhY2JhNTQ1NzJiMzABP3JlZWRfc29sb21vbl9lcmFzdXJlOjptYXRyaXg6Ok1hdHJpeDo6aW52ZXJ0OjpoMThhNmNmZGNkNTJkYjA2ZgIxPHN0ciBhcyBjb3JlOjpmbXQ6OkRlYnVnPjo6Zm10OjpoZTExOWRiMWJmYWMxOGM2NwMjY29yZTo6Zm10Ojp3cml0ZTo6aDgyMmNkMjY0OGQ4ZWFjZjUELmNvcmU6OnN0cjo6c2xpY2VfZXJyb3JfZmFpbDo6aDZjZjI4OGMxZjcwZDI5YjIFLGNvcmU6OmZtdDo6Rm9ybWF0dGVyOjpwYWQ6Omg5NmM5ZDMyMjA3YjQyNTBhBjVjb3JlOjpmbXQ6OkZvcm1hdHRlcjo6cGFkX2ludGVncmFsOjpoYjkzNmU0N2EzMzRkN2U4MwdBcmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6TWF0cml4OjptdWx0aXBseTo6aGU3Y2Q4ODhmYjYzOGE5OWEIC3JlY29uc3RydWN0CUdyZWVkX3NvbG9tb25fZXJhc3VyZTo6UmVlZFNvbG9tb246OmNvZGVfc2luZ2xlX3NsaWNlOjpoNGQwODU3MDhlODgxMmY3MQpEcmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6TWF0cml4Ojp2YW5kZXJtb25kZTo6aDRlYmZmYjZjMTI5NjE4YzMLMjxjaGFyIGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6Omg4OTA4YjRhZmE5YTg4NWUzDC13ZWVfYWxsb2M6OmFsbG9jX2ZpcnN0X2ZpdDo6aDlhNTk4ZGQwMzljYmY2NzANBmVuY29kZQ5DcmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6TWF0cml4OjpzdWJfbWF0cml4OjpoN2RkMDlmODY1NWYwY2IyYg88cmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjplbmNvZGU6OmhlYjU0MGZlYWI2ZDQ2YTBjEFQ8d2VlX2FsbG9jOjpXZWVBbGxvYzwnc3RhdGljPiBhcyBjb3JlOjphbGxvYzo6R2xvYmFsQWxsb2M+OjphbGxvYzo6aDM0ODFhYWI1YjMxZWU4N2MRRXJlZWRfc29sb21vbl9lcmFzdXJlOjpSZWVkU29sb21vbjo6Z2V0X3Bhcml0eV9yb3dzOjpoNjc1ODJiMGYxNWNmMDBiNhJAcmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjplbmNvZGVfc2VwOjpoZDk1N2NiZGM3N2UzMzM2MxNBcmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjp3aXRoX3BwYXJhbTo6aDIyOWJkNzg5MWJjY2E0OWYUQXJlZWRfc29sb21vbl9lcmFzdXJlOjptYXRyaXg6Ok1hdHJpeDo6aWRlbnRpdHk6Omg4OWU0OTQyY2VlMmQyY2U0FT5yZWVkX3NvbG9tb25fZXJhc3VyZTo6Z2Fsb2lzOjptdWxfc2xpY2VfeG9yOjpoMDdlZGRkZmVjNWUyMjkwMBY6cmVlZF9zb2xvbW9uX2VyYXN1cmU6OmdhbG9pczo6bXVsX3NsaWNlOjpoZDQ3ZmUxNWJiOGZkMDM4ZRcyY29yZTo6dW5pY29kZTo6cHJpbnRhYmxlOjpjaGVjazo6aDFhOTVmZjk0ZmNiNzM4ZGIYUXJlZWRfc29sb21vbl9lcmFzdXJlOjppbnZlcnNpb25fdHJlZTo6SW52ZXJzaW9uTm9kZTo6Z2V0X2NoaWxkOjpoZTUzNDg4YmQzZDQwMmUyZBlbcmVlZF9zb2xvbW9uX2VyYXN1cmU6OmludmVyc2lvbl90cmVlOjpJbnZlcnNpb25UcmVlOjpnZXRfaW52ZXJ0ZWRfbWF0cml4OjpoZGMwODIyZTE3NWYxMWY5OBpLcmVlZF9zb2xvbW9uX2VyYXN1cmU6OmludmVyc2lvbl90cmVlOjpJbnZlcnNpb25UcmVlOjpuZXc6OmhkODk5YzdhYjE4MmUyZmFmGzs8Jm11dCBXIGFzIGNvcmU6OmZtdDo6V3JpdGU+Ojp3cml0ZV9jaGFyOjpoMjkzZDQ1NzA5NGFhZjY5YRwvY29yZTo6Zm10OjpudW06OmltcDo6Zm10X3U2NDo6aGMzOTNlMzM3YWI5YmFlOTkdS3JlZWRfc29sb21vbl9lcmFzdXJlOjppbnZlcnNpb25fdHJlZTo6SW52ZXJzaW9uTm9kZTo6bmV3OjpoNjk0ZmQ4Mzg5YTNkOGEwMh5JY29yZTo6Zm10OjpudW06OjxpbXBsIGNvcmU6OmZtdDo6RGVidWcgZm9yIHVzaXplPjo6Zm10OjpoNWQ0MDFjZDE0YTIwYzVhYx9Bd2VlX2FsbG9jOjpXZWVBbGxvYzo6ZGVhbGxvY19pbXBsOjp7e2Nsb3N1cmV9fTo6aGVjODBlODBjMGM1ODliODYgbDxzdGQ6OnBhbmlja2luZzo6Y29udGludWVfcGFuaWNfZm10OjpQYW5pY1BheWxvYWQ8J2E+IGFzIGNvcmU6OnBhbmljOjpCb3hNZVVwPjo6Ym94X21lX3VwOjpoOGQ1N2M2N2IwYzhmMTVmYyE9Y29yZTo6dW5pY29kZTo6Ym9vbF90cmllOjpCb29sVHJpZTo6bG9va3VwOjpoMDI5MmI2MmIxNjQ2MjNmNCIwPHNtYWxsdmVjOjpTbWFsbFZlYzxBPj46Omdyb3c6OmgzODNlYTZlM2IzYzgyN2UwIzxyZWVkX3NvbG9tb25fZXJhc3VyZTo6bWF0cml4OjpNYXRyaXg6Om5ldzo6aDMxNjA2NTFiNzI3Yjg5ZWEkMDxzbWFsbHZlYzo6U21hbGxWZWM8QT4+Ojpncm93OjpoZGExOTQ3ODY5ODI0MzNkMyUwPHNtYWxsdmVjOjpTbWFsbFZlYzxBPj46Omdyb3c6OmhiMWQ4NzE1MzE1N2M5YTk4Jl5yZWVkX3NvbG9tb25fZXJhc3VyZTo6aW52ZXJzaW9uX3RyZWU6OkludmVyc2lvblRyZWU6Omluc2VydF9pbnZlcnRlZF9tYXRyaXg6OmgyMWQ0YjUzZGJjMzNjMWIyJzdzdGQ6OnBhbmlja2luZzo6cnVzdF9wYW5pY193aXRoX2hvb2s6OmhiNzFkNWZlNGRjNmNlYmQzKFE8cmVlZF9zb2xvbW9uX2VyYXN1cmU6OmVycm9yczo6RXJyb3IgYXMgY29yZTo6Zm10OjpEZWJ1Zz46OmZtdDo6aGVlZmU4YTVhYjA1NThiYzkpgAE8d2VlX2FsbG9jOjpzaXplX2NsYXNzZXM6OlNpemVDbGFzc0FsbG9jUG9saWN5PCdhLCAnYj4gYXMgd2VlX2FsbG9jOjpBbGxvY1BvbGljeTwnYT4+OjpuZXdfY2VsbF9mb3JfZnJlZV9saXN0OjpoYjAwMWFhYjFmYmFmZTA3YSpmPHN0ZDo6cGFuaWNraW5nOjpjb250aW51ZV9wYW5pY19mbXQ6OlBhbmljUGF5bG9hZDwnYT4gYXMgY29yZTo6cGFuaWM6OkJveE1lVXA+OjpnZXQ6OmhlMTRjNjZkMzc3MWQ3YjhjKzpjb3JlOjpmbXQ6OmJ1aWxkZXJzOjpEZWJ1Z1R1cGxlOjpmaW5pc2g6OmgzNjg2NDljYzhiM2EwYzFlLFY8d2VlX2FsbG9jOjpXZWVBbGxvYzwnc3RhdGljPiBhcyBjb3JlOjphbGxvYzo6R2xvYmFsQWxsb2M+OjpkZWFsbG9jOjpoYjE0MGMxZWEyNzBmYjJhOS1KY29yZTo6Zm10OjpudW06OjxpbXBsIGNvcmU6OmZtdDo6TG93ZXJIZXggZm9yIGkzMj46OmZtdDo6aDZmNTM3MTU3ZjNiMjM2MjcuSmNvcmU6OmZtdDo6bnVtOjo8aW1wbCBjb3JlOjpmbXQ6OlVwcGVySGV4IGZvciBpMzI+OjpmbXQ6OmgzZDQzYzEzYzUyNzMyNzFjLzBjb3JlOjpwdHI6OnJlYWxfZHJvcF9pbl9wbGFjZTo6aDg1MTgyYWZlNzMxM2M2OWMwMGNvcmU6OnB0cjo6cmVhbF9kcm9wX2luX3BsYWNlOjpoY2Q4ZTRmYjhjMjUxZTJmMTEwPGFsbG9jOjp2ZWM6OlZlYzxUPj46OnJlc2VydmU6OmhhYzhiZWI2NTJmOTRiYjA4MmY8d2VlX2FsbG9jOjpMYXJnZUFsbG9jUG9saWN5IGFzIHdlZV9hbGxvYzo6QWxsb2NQb2xpY3k8J2E+Pjo6bmV3X2NlbGxfZm9yX2ZyZWVfbGlzdDo6aDNmMDA4ODlkMTM4ZWI3NmYzLmNvcmU6OnJlc3VsdDo6dW53cmFwX2ZhaWxlZDo6aGY5MmRkY2RlMGJkYTgwNWM0Sjxjb3JlOjpvcHM6OnJhbmdlOjpSYW5nZTxJZHg+IGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6OmhlMTkwOWJmY2Q5OWZkZjI2NS5jb3JlOjpyZXN1bHQ6OnVud3JhcF9mYWlsZWQ6OmhkNmJhMjEzNjFhN2M5YjRlNi5jb3JlOjpyZXN1bHQ6OnVud3JhcF9mYWlsZWQ6OmgwOWM3M2FkY2FmMzAzYTQ3Ny5jb3JlOjpyZXN1bHQ6OnVud3JhcF9mYWlsZWQ6OmhhNTE0ZmNkNzUxZGIzMTdlODVzdGQ6OnBhbmlja2luZzo6Y29udGludWVfcGFuaWNfZm10OjpoMWRhOWJlM2MwN2ZlZDk3OTk0Y29yZTo6c2xpY2U6OnNsaWNlX2luZGV4X2xlbl9mYWlsOjpoZjYyNjUyMDI2MWYwNDhmZTo2Y29yZTo6cGFuaWNraW5nOjpwYW5pY19ib3VuZHNfY2hlY2s6OmgyNzNlNDlhMzgwZDAxZmI3OzZjb3JlOjpzbGljZTo6c2xpY2VfaW5kZXhfb3JkZXJfZmFpbDo6aGRlYmNhY2YzNDk4MmJiNTI8OjwmbXV0IFcgYXMgY29yZTo6Zm10OjpXcml0ZT46OndyaXRlX2ZtdDo6aGI3ZmQ2NTIyZjg0MjE5M2Q9KWNvcmU6OnBhbmlja2luZzo6cGFuaWM6OmgzYzUxMmM3YzJiYjZkYTI1PmQ8c3RkOjpwYW5pY2tpbmc6OmJlZ2luX3BhbmljOjpQYW5pY1BheWxvYWQ8QT4gYXMgY29yZTo6cGFuaWM6OkJveE1lVXA+Ojpib3hfbWVfdXA6Omg1YmRjYmM1MDMwNzE1NjU1PzJzdGQ6OnBhbmlja2luZzo6YmVnaW5fcGFuaWNfZm10OjpoZjhmODM2MjQ5NWQyYWU4MEAzPGFsbG9jOjpzeW5jOjpBcmM8VD4+Ojpkcm9wX3Nsb3c6OmhkZmU1ZmRkMDYzNjMwZTcxQTM8YWxsb2M6OnN5bmM6OkFyYzxUPj46OmRyb3Bfc2xvdzo6aGQ4NTRhMTljMmU3MTRiMDhCQ2NvcmU6OmZtdDo6Rm9ybWF0dGVyOjpwYWRfaW50ZWdyYWw6OndyaXRlX3ByZWZpeDo6aGZkY2ZkMDc0YmUzNWM1ZTBDWTxyZWVkX3NvbG9tb25fZXJhc3VyZTo6aW52ZXJzaW9uX3RyZWU6OkVycm9yIGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6Omg4ODVlZTVkMGE4Mzg2NDNlRC1jb3JlOjpwYW5pY2tpbmc6OnBhbmljX2ZtdDo6aDQ3MmQ3NjZlNGRmZjcxYTJFEV9fd2JpbmRnZW5fbWFsbG9jRgZtZW1jcHlHDF9fcmdfcmVhbGxvY0gwPCZUIGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6OmgxM2JmNWJkYjM2Njg4ZTU1SSxzdGQ6OnBhbmlja2luZzo6cGFuaWNraW5nOjpoZDI1NjQ1YTczYTYwZjE0Yko0Y29yZTo6Zm10OjpGb3JtYXR0ZXI6OmRlYnVnX3R1cGxlOjpoOTczZTJhZTEzODkyNzZiYks6PCZtdXQgVyBhcyBjb3JlOjpmbXQ6OldyaXRlPjo6d3JpdGVfc3RyOjpoNjZiZDVkNDkzYTllNjhjNUwGbWVtc2V0TS5zdGQ6OnBhbmlja2luZzo6YmVnaW5fcGFuaWM6OmgyNDE4ZmE2ZmJiMTZlM2E4TlE8cmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6RXJyb3IgYXMgY29yZTo6Zm10OjpEZWJ1Zz46OmZtdDo6aDAwMGExZmQ5OTA0ZjYwNjlPMGNvcmU6OnB0cjo6cmVhbF9kcm9wX2luX3BsYWNlOjpoMWFkYmNiZmQ4YTQ5YzYzM1AKcnVzdF9wYW5pY1ERX19yZ19hbGxvY196ZXJvZWRSXjxzdGQ6OnBhbmlja2luZzo6YmVnaW5fcGFuaWM6OlBhbmljUGF5bG9hZDxBPiBhcyBjb3JlOjpwYW5pYzo6Qm94TWVVcD46OmdldDo6aDU4MDBjODBhYjY0MjA0ZTlTgAFjb3JlOjpzdHI6OnRyYWl0czo6PGltcGwgY29yZTo6c2xpY2U6OlNsaWNlSW5kZXg8c3RyPiBmb3IgY29yZTo6b3BzOjpyYW5nZTo6UmFuZ2U8dXNpemU+Pjo6aW5kZXg6Ont7Y2xvc3VyZX19OjpoNWE0YjljMjk5NTVhY2U0YlQ+Y29yZTo6cGFuaWM6OkxvY2F0aW9uOjppbnRlcm5hbF9jb25zdHJ1Y3Rvcjo6aGU2ZTU1MWIwOTBjZTM2NTJVOndhc21fYmluZGdlbjo6YW55cmVmOjpIRUFQX1NMQUI6Ol9faW5pdDo6aGRhYTQxNDMzYjlmOTNiZWRWMGNvcmU6OnB0cjo6cmVhbF9kcm9wX2luX3BsYWNlOjpoNGQ5ZmE0NjY4ZTMwMGM2YVcIcnVzdF9vb21YRnJlZWRfc29sb21vbl9lcmFzdXJlOjpSZWVkU29sb21vbjo6cmVjb25zdHJ1Y3RfZGF0YTo6aDc1YjE5Mjk5M2JhZDFlMGVZNDxjb3JlOjpvcHRpb246Ok9wdGlvbjxUPj46OnVud3JhcDo6aDBiN2QyYWM0ZjA3MzJkMDhaNDxjb3JlOjpvcHRpb246Ok9wdGlvbjxUPj46OnVud3JhcDo6aGY5Y2ViOGY2MmIwOTU1MDFbD19fd2JpbmRnZW5fZnJlZVwyPCZUIGFzIGNvcmU6OmZtdDo6RGlzcGxheT46OmZtdDo6aGFjMTkzZjNhNDI5MjQxZmJdMjwmVCBhcyBjb3JlOjpmbXQ6OkRpc3BsYXk+OjpmbXQ6OmhkZDFlMTI0NmNiMjQ4M2IzXjI8JlQgYXMgY29yZTo6Zm10OjpEaXNwbGF5Pjo6Zm10OjpoYWE4OTNlZjUwOTIyOWUwOF84Y29yZTo6Zm10OjpGb3JtYXR0ZXI6OmRlYnVnX2xvd2VyX2hleDo6aDA1ZTI5NmFiM2Y4YjFiYjdgOGNvcmU6OmZtdDo6Rm9ybWF0dGVyOjpkZWJ1Z191cHBlcl9oZXg6OmgwODUwNWQ1M2JiMDQxMDRmYQxfX3JnX2RlYWxsb2NiDl9fcnVzdF9yZWFsbG9jYzlyZWVkX3NvbG9tb25fZXJhc3VyZTo6UmVlZFNvbG9tb246Om5ldzo6aGRkYzdlMDAzYjIyODRlOWRkTmNvcmU6OmZtdDo6bnVtOjppbXA6OjxpbXBsIGNvcmU6OmZtdDo6RGlzcGxheSBmb3IgdTMyPjo6Zm10OjpoNjJmYzg5OTRmNGY1ZWRiM2U0Y29yZTo6Zm10OjpBcmd1bWVudFYxOjpzaG93X3VzaXplOjpoZWQ5MzI0ZGJlNjlkZmM0MWYKX19yZ19hbGxvY2cOX19ydXN0X2RlYWxsb2NoVTxzdGQ6OnN5c19jb21tb246OnBvaXNvbjo6UG9pc29uRXJyb3I8VD4gYXMgY29yZTo6Zm10OjpEZWJ1Zz46OmZtdDo6aGRlZDZkZjI5Y2FiMjIxNGRpM2FsbG9jOjphbGxvYzo6aGFuZGxlX2FsbG9jX2Vycm9yOjpoMmJmNDQ0ZjA0NzA0OWIwZWouY29yZTo6cGFuaWM6OkxvY2F0aW9uOjpmaWxlOjpoYTk5OTc1ZTA0YWJlYTI4N2szPHN0ciBhcyBjb3JlOjpmbXQ6OkRpc3BsYXk+OjpmbXQ6OmhiMTZhNjk5MTMwMDM0MDM0bAxfX3J1c3RfYWxsb2NtE19fcnVzdF9hbGxvY196ZXJvZWRuEXJ1c3RfYmVnaW5fdW53aW5kbzRhbGxvYzo6cmF3X3ZlYzo6Y2FwYWNpdHlfb3ZlcmZsb3c6OmhhM2ZmMjQ3Y2YxZDA3MmZhcDNjb3JlOjpwYW5pYzo6UGFuaWNJbmZvOjpsb2NhdGlvbjo6aGM4MmI2ZDgwMjQ3NmRmNTRxNXdhc21fYmluZGdlbjo6X19ydDo6bWFsbG9jX2ZhaWx1cmU6OmhjMTkwYjVkOWE2YTU3ODZmcks8YWxsb2M6OnJhd192ZWM6OlJhd1ZlYzxULCBBPj46OmFsbG9jYXRlX2luOjp7e2Nsb3N1cmV9fTo6aDIwMjQzMDAwMGY2ZjQwOThzMmNvcmU6OnBhbmljOjpQYW5pY0luZm86Om1lc3NhZ2U6OmhiZDE3NDJhZjNlYjE5MDI3dC5jb3JlOjpwYW5pYzo6TG9jYXRpb246OmxpbmU6OmgxOGZiY2VhYjJjNmQwMGNjdTBjb3JlOjpwYW5pYzo6TG9jYXRpb246OmNvbHVtbjo6aDk5N2FlM2RmYWVkYTc4MDh2dzx3ZWVfYWxsb2M6OnNpemVfY2xhc3Nlczo6U2l6ZUNsYXNzQWxsb2NQb2xpY3k8J2EsICdiPiBhcyB3ZWVfYWxsb2M6OkFsbG9jUG9saWN5PCdhPj46Om1pbl9jZWxsX3NpemU6Omg5MDFjMTQ1ZWY5ZDYxZmQ2d4oBPHdlZV9hbGxvYzo6c2l6ZV9jbGFzc2VzOjpTaXplQ2xhc3NBbGxvY1BvbGljeTwnYSwgJ2I+IGFzIHdlZV9hbGxvYzo6QWxsb2NQb2xpY3k8J2E+Pjo6c2hvdWxkX21lcmdlX2FkamFjZW50X2ZyZWVfY2VsbHM6Omg0MzgyZGZkYmJkMzFmM2E1eF08d2VlX2FsbG9jOjpMYXJnZUFsbG9jUG9saWN5IGFzIHdlZV9hbGxvYzo6QWxsb2NQb2xpY3k8J2E+Pjo6bWluX2NlbGxfc2l6ZTo6aDlmMWQ3MmEwODYzMGE2YjR5cDx3ZWVfYWxsb2M6OkxhcmdlQWxsb2NQb2xpY3kgYXMgd2VlX2FsbG9jOjpBbGxvY1BvbGljeTwnYT4+OjpzaG91bGRfbWVyZ2VfYWRqYWNlbnRfZnJlZV9jZWxsczo6aDQ2Njc2N2Q4ZjA4NmFjNjN6O3dhc21fYmluZGdlbjo6YW55cmVmOjpIRUFQX1NMQUI6Ol9fZ2V0aXQ6OmhkZGU3YmIwMjNkZWVkYTlmezE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg2YmQ3N2Y5NzE3ZGJjZjg5fDE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg4NDFmZDAyNTc5OWZkYjAwfTE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg3YzQ4MTk0MGYxMDFiYWVhfjE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6OmhjZDFhMTkzYmU2ZjFkNTQxfyZzdGQ6OnByb2Nlc3M6OmFib3J0OjpoZjYyMWVlNzUyNzY5MjhhYoABNXN0ZDo6c3lzX2NvbW1vbjo6bXV0ZXg6Ok11dGV4OjpuZXc6OmgwNzIyODJjNzE4YTQ0OWZhgQE1c3RkOjpzeXNfY29tbW9uOjpwb2lzb246OkZsYWc6Om5ldzo6aDIzY2JhMzU4ZjkyMzdjNTCCARJfX3J1c3Rfc3RhcnRfcGFuaWODATE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg3MDUwNjI4NzZkNzc5NWY4hAEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhiZmUxMDUwYzNiMmU2OTI0hQEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmgwMTQ2MGFlOTQyOGNiNTkwhgEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhiZmUxMDUwYzNiMmU2OTI0hwEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhjNjVmMTJiYTZiNDUxM2FmiAEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhlY2FkZTFjOWU1Nzk3YmE1iQEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmgyZWFkYzhmYzEzNzU4ZTA0igFWPHN0ZDo6c3lzX2NvbW1vbjo6dGhyZWFkX2xvY2FsOjpLZXkgYXMgY29yZTo6b3BzOjpkcm9wOjpEcm9wPjo6ZHJvcDo6aDg2ZDkzMjk5Mjg4NWIzODiLATdzdGQ6OmFsbG9jOjpkZWZhdWx0X2FsbG9jX2Vycm9yX2hvb2s6OmgxOTJmYjQ4YWM5NWUwNjE0jAEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6Omg5ZDIwYTQzNmU4OTMxNjg1AP+AgIAACXByb2R1Y2VycwIIbGFuZ3VhZ2UBBFJ1c3QEMjAxNQxwcm9jZXNzZWQtYnkDBXJ1c3RjHTEuMzQuMCAoOTE4NTZlZDUyIDIwMTktMDQtMTApBndhbHJ1cwYwLjExLjAMd2FzbS1iaW5kZ2VuEjAuMi40OSAoOTA2YWMxNTAwKQ==");
|
|
6564
6983
|
|
|
6565
|
-
// ../../packages/sdk/dist/chunk-
|
|
6984
|
+
// ../../packages/sdk/dist/chunk-NHWWORCH.mjs
|
|
6566
6985
|
var DEFAULT_CHUNK_SIZE_BYTES2 = 2 * 1024 * 1024;
|
|
6567
6986
|
|
|
6568
|
-
// ../../packages/sdk/dist/chunk-
|
|
6987
|
+
// ../../packages/sdk/dist/chunk-OQNP5QXH.mjs
|
|
6569
6988
|
import {
|
|
6570
|
-
AccountAddress as
|
|
6571
|
-
Aptos as Aptos4
|
|
6989
|
+
AccountAddress as AccountAddress5,
|
|
6990
|
+
Aptos as Aptos4,
|
|
6991
|
+
MoveVector
|
|
6572
6992
|
} from "@aptos-labs/ts-sdk";
|
|
6573
6993
|
var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
6574
6994
|
aptos;
|
|
@@ -6595,7 +7015,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6595
7015
|
*/
|
|
6596
7016
|
constructor(config) {
|
|
6597
7017
|
this.aptos = new Aptos4(getAptosConfig(config));
|
|
6598
|
-
this.deployer = config.deployer ??
|
|
7018
|
+
this.deployer = config.deployer ?? AccountAddress5.fromString(MICROPAYMENTS_DEPLOYER);
|
|
6599
7019
|
this.indexer = getShelbyIndexerClient(config);
|
|
6600
7020
|
}
|
|
6601
7021
|
/**
|
|
@@ -6664,7 +7084,8 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6664
7084
|
receiver: params.receiver,
|
|
6665
7085
|
expirationMicros: params.expirationMicros,
|
|
6666
7086
|
depositAmount: params.depositAmount,
|
|
6667
|
-
fungibleAssetAddress: params.fungibleAssetAddress
|
|
7087
|
+
fungibleAssetAddress: params.fungibleAssetAddress,
|
|
7088
|
+
publicKey: params.publicKey ?? params.sender.publicKey.toUint8Array()
|
|
6668
7089
|
}
|
|
6669
7090
|
),
|
|
6670
7091
|
sender: params.sender.accountAddress
|
|
@@ -6686,6 +7107,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6686
7107
|
* @param params.expirationMicros - The expiration of the micropayment channel.
|
|
6687
7108
|
* @param params.depositAmount - The amount of the asset locked to the channel.
|
|
6688
7109
|
* @param params.fungibleAssetAddress - The account address of the fungible asset.
|
|
7110
|
+
* @param params.publicKey - The Ed25519 public key bytes for the channel.
|
|
6689
7111
|
*
|
|
6690
7112
|
* @returns An Aptos transaction payload data object for the create_channel Move function.
|
|
6691
7113
|
*/
|
|
@@ -6696,7 +7118,8 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6696
7118
|
params.receiver,
|
|
6697
7119
|
params.expirationMicros,
|
|
6698
7120
|
params.depositAmount,
|
|
6699
|
-
params.fungibleAssetAddress
|
|
7121
|
+
params.fungibleAssetAddress,
|
|
7122
|
+
MoveVector.U8(params.publicKey)
|
|
6700
7123
|
]
|
|
6701
7124
|
};
|
|
6702
7125
|
}
|
|
@@ -6754,94 +7177,86 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6754
7177
|
}
|
|
6755
7178
|
/**
|
|
6756
7179
|
* Creates a micropayment that can be sent to a receiver.
|
|
7180
|
+
* The sender signs a WithdrawApproval message that authorizes the receiver
|
|
7181
|
+
* to withdraw funds from the micropayment channel.
|
|
6757
7182
|
*
|
|
6758
|
-
* @param params.sender - The account
|
|
6759
|
-
* @param params.receiver - The account that
|
|
6760
|
-
* @param params.amount - The amount to withdraw into the receiver's account.
|
|
6761
|
-
* @param params.paymentChannelId - The id of the payment channel.
|
|
6762
|
-
* @param params.sequenceNumber - The sequence number of the micropayment. These must be increasing to be able to store on chain.
|
|
7183
|
+
* @param params.sender - The account that owns the payment channel and signs the approval.
|
|
7184
|
+
* @param params.receiver - The account address that will receive funds.
|
|
6763
7185
|
* @param params.fungibleAssetAddress - The account address of the fungible asset.
|
|
6764
|
-
* @param params.
|
|
7186
|
+
* @param params.amount - The cumulative amount to authorize (not incremental).
|
|
7187
|
+
* @param params.paymentChannelId - The id of the payment channel.
|
|
7188
|
+
* @param params.sequenceNumber - The sequence number of the micropayment. Must be >= channel's next_withdrawn_sequence_number.
|
|
6765
7189
|
*
|
|
6766
|
-
* @returns
|
|
7190
|
+
* @returns A SenderBuiltMicropayment containing the signed approval.
|
|
6767
7191
|
*
|
|
6768
7192
|
* @example
|
|
6769
7193
|
* ```typescript
|
|
6770
|
-
* const senderBuiltMicropayment =
|
|
6771
|
-
* sender:
|
|
6772
|
-
* receiver:
|
|
6773
|
-
* amount: 1,
|
|
6774
|
-
* paymentChannelId: channelIdFromLookup,
|
|
6775
|
-
* sequenceNumber: localSequenceNumber,
|
|
7194
|
+
* const senderBuiltMicropayment = client.createMicropayment({
|
|
7195
|
+
* sender: senderAccount,
|
|
7196
|
+
* receiver: receiverAddress,
|
|
6776
7197
|
* fungibleAssetAddress: fungibleAssetAddress,
|
|
7198
|
+
* amount: 100,
|
|
7199
|
+
* paymentChannelId: channelId,
|
|
7200
|
+
* sequenceNumber: 1,
|
|
6777
7201
|
* });
|
|
6778
7202
|
* ```
|
|
6779
7203
|
*/
|
|
6780
|
-
|
|
6781
|
-
const
|
|
6782
|
-
|
|
6783
|
-
accountSequenceNumber: _unusedSequenceNumber,
|
|
6784
|
-
expireTimestamp: _unusedTimestamp,
|
|
6785
|
-
...restOptions
|
|
6786
|
-
} = params.options ?? {};
|
|
6787
|
-
const micropayment = await this.aptos.transaction.build.multiAgent({
|
|
6788
|
-
options: {
|
|
6789
|
-
...restOptions,
|
|
6790
|
-
replayProtectionNonce,
|
|
6791
|
-
expireTimestamp: Math.floor(Date.now() / 1e3 + 60)
|
|
6792
|
-
// 60 seconds from now
|
|
6793
|
-
},
|
|
6794
|
-
withFeePayer: true,
|
|
6795
|
-
data: _ShelbyMicropaymentChannelClient.createMicropaymentTransactionPayload(
|
|
6796
|
-
{
|
|
6797
|
-
deployer: this.deployer,
|
|
6798
|
-
amount: params.amount,
|
|
6799
|
-
paymentChannelId: params.paymentChannelId,
|
|
6800
|
-
sequenceNumber: params.sequenceNumber,
|
|
6801
|
-
fungibleAssetAddress: params.fungibleAssetAddress
|
|
6802
|
-
}
|
|
6803
|
-
),
|
|
7204
|
+
createMicropayment(params) {
|
|
7205
|
+
const message = SenderBuiltMicropayment.buildSignedMessage({
|
|
7206
|
+
deployer: this.deployer,
|
|
6804
7207
|
sender: params.sender.accountAddress,
|
|
6805
|
-
|
|
7208
|
+
receiver: params.receiver,
|
|
7209
|
+
fungibleAssetAddress: params.fungibleAssetAddress,
|
|
7210
|
+
amount: params.amount,
|
|
7211
|
+
paymentChannelId: params.paymentChannelId,
|
|
7212
|
+
sequenceNumber: params.sequenceNumber
|
|
6806
7213
|
});
|
|
7214
|
+
const signature = params.sender.sign(message);
|
|
6807
7215
|
return new SenderBuiltMicropayment(
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
7216
|
+
params.sender.accountAddress,
|
|
7217
|
+
params.receiver,
|
|
7218
|
+
BigInt(params.paymentChannelId),
|
|
7219
|
+
BigInt(params.amount),
|
|
7220
|
+
params.fungibleAssetAddress,
|
|
7221
|
+
BigInt(params.sequenceNumber),
|
|
7222
|
+
params.sender.publicKey.toUint8Array(),
|
|
7223
|
+
signature.toUint8Array(),
|
|
7224
|
+
this.deployer
|
|
6813
7225
|
);
|
|
6814
7226
|
}
|
|
6815
7227
|
/**
|
|
6816
|
-
* Creates a static payload for the receiver_withdraw Move function.
|
|
6817
|
-
*
|
|
6818
|
-
* This is a helper method for constructing the transaction payload without signing.
|
|
7228
|
+
* Creates a static payload for the receiver_withdraw Move function.
|
|
7229
|
+
* This is a helper method for constructing the transaction payload.
|
|
6819
7230
|
*
|
|
6820
7231
|
* @param params.deployer - Optional deployer account address. Defaults to MICROPAYMENTS_DEPLOYER.
|
|
6821
|
-
* @param params.
|
|
6822
|
-
* @param params.paymentChannelId - The payment channel id.
|
|
7232
|
+
* @param params.sender - The sender's account address.
|
|
6823
7233
|
* @param params.fungibleAssetAddress - The account address of the fungible asset.
|
|
7234
|
+
* @param params.amount - The cumulative amount authorized to withdraw.
|
|
7235
|
+
* @param params.paymentChannelId - The payment channel id.
|
|
7236
|
+
* @param params.sequenceNumber - The sequence number for this withdrawal.
|
|
7237
|
+
* @param params.signature - The Ed25519 signature bytes.
|
|
6824
7238
|
*
|
|
6825
|
-
* @returns An Aptos transaction payload data object for the
|
|
7239
|
+
* @returns An Aptos transaction payload data object for the receiver_withdraw Move function.
|
|
6826
7240
|
*/
|
|
6827
7241
|
static createMicropaymentTransactionPayload(params) {
|
|
6828
7242
|
return {
|
|
6829
7243
|
function: `${(params.deployer ?? MICROPAYMENTS_DEPLOYER).toString()}::micropayments::receiver_withdraw`,
|
|
6830
7244
|
functionArguments: [
|
|
7245
|
+
params.sender,
|
|
7246
|
+
params.fungibleAssetAddress,
|
|
6831
7247
|
params.amount,
|
|
6832
7248
|
params.paymentChannelId,
|
|
6833
7249
|
params.sequenceNumber,
|
|
6834
|
-
params.
|
|
7250
|
+
MoveVector.U8(params.signature)
|
|
6835
7251
|
]
|
|
6836
7252
|
};
|
|
6837
7253
|
}
|
|
6838
7254
|
/**
|
|
6839
|
-
* Withdraws funds from a micropayment channel as the receiver.
|
|
6840
|
-
*
|
|
7255
|
+
* Withdraws funds from a micropayment channel as the receiver.
|
|
7256
|
+
* The receiver submits the sender's signed approval to claim funds.
|
|
6841
7257
|
*
|
|
6842
|
-
* @param params.receiver - The receiver
|
|
6843
|
-
* @param params.
|
|
6844
|
-
* @param params.micropayment - The fee-paying transaction signature.
|
|
7258
|
+
* @param params.receiver - The receiver account that will sign and submit the transaction.
|
|
7259
|
+
* @param params.micropayment - The sender's signed micropayment approval.
|
|
6845
7260
|
* @param params.options - Optional transaction generation options.
|
|
6846
7261
|
*
|
|
6847
7262
|
* @returns An object containing the pending transaction.
|
|
@@ -6849,23 +7264,31 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6849
7264
|
* @example
|
|
6850
7265
|
* ```typescript
|
|
6851
7266
|
* const { transaction } = await client.receiverWithdraw({
|
|
6852
|
-
* receiver:
|
|
6853
|
-
* micropayment,
|
|
6854
|
-
* senderSignature,
|
|
7267
|
+
* receiver: receiverAccount,
|
|
7268
|
+
* micropayment: senderBuiltMicropayment,
|
|
6855
7269
|
* });
|
|
6856
7270
|
* ```
|
|
6857
7271
|
*/
|
|
6858
7272
|
async receiverWithdraw(params) {
|
|
6859
|
-
const
|
|
6860
|
-
|
|
6861
|
-
|
|
7273
|
+
const transaction = await this.aptos.transaction.build.simple({
|
|
7274
|
+
options: params.options,
|
|
7275
|
+
data: _ShelbyMicropaymentChannelClient.createMicropaymentTransactionPayload(
|
|
7276
|
+
{
|
|
7277
|
+
deployer: this.deployer,
|
|
7278
|
+
sender: params.micropayment.sender,
|
|
7279
|
+
fungibleAssetAddress: params.micropayment.fungibleAssetAddress,
|
|
7280
|
+
amount: params.micropayment.amount,
|
|
7281
|
+
paymentChannelId: params.micropayment.paymentChannelId,
|
|
7282
|
+
sequenceNumber: params.micropayment.sequenceNumber,
|
|
7283
|
+
signature: params.micropayment.signature
|
|
7284
|
+
}
|
|
7285
|
+
),
|
|
7286
|
+
sender: params.receiver.accountAddress
|
|
6862
7287
|
});
|
|
6863
7288
|
return {
|
|
6864
|
-
transaction: await this.aptos.
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
additionalSignersAuthenticators: [mySignature],
|
|
6868
|
-
feePayerAuthenticator: mySignature
|
|
7289
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
7290
|
+
signer: params.receiver,
|
|
7291
|
+
transaction
|
|
6869
7292
|
})
|
|
6870
7293
|
};
|
|
6871
7294
|
}
|
|
@@ -7001,7 +7424,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
7001
7424
|
* ```typescript
|
|
7002
7425
|
* const channelInfoVec = await client.getChannelInfo({
|
|
7003
7426
|
* sender: AccountAddress.fromString("0x1"),
|
|
7004
|
-
* receiver: AccountAddress.
|
|
7427
|
+
* receiver: AccountAddress.fromString("0x2"),
|
|
7005
7428
|
* });
|
|
7006
7429
|
* ```
|
|
7007
7430
|
*/
|
|
@@ -7020,10 +7443,14 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
7020
7443
|
const channelInfoArray = rawArray[0];
|
|
7021
7444
|
return channelInfoArray.map(
|
|
7022
7445
|
(channelInfo) => {
|
|
7446
|
+
const publicKeyHex = channelInfo.public_key.startsWith("0x") ? channelInfo.public_key.slice(2) : channelInfo.public_key;
|
|
7447
|
+
const publicKey = new Uint8Array(
|
|
7448
|
+
publicKeyHex.match(/.{1,2}/g)?.map((byte) => Number.parseInt(byte, 16)) ?? []
|
|
7449
|
+
);
|
|
7023
7450
|
return {
|
|
7024
7451
|
sender: params.sender,
|
|
7025
7452
|
receiver: params.receiver,
|
|
7026
|
-
fungibleAssetAddress:
|
|
7453
|
+
fungibleAssetAddress: normalizeAddress(
|
|
7027
7454
|
channelInfo.asset_metadata.inner
|
|
7028
7455
|
),
|
|
7029
7456
|
balance: Number(channelInfo.balance),
|
|
@@ -7035,31 +7462,36 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
7035
7462
|
paymentChannelId: Number(channelInfo.payment_channel_id),
|
|
7036
7463
|
receiverWithdrawnAmount: Number(
|
|
7037
7464
|
channelInfo.receiver_withdrawn_amount
|
|
7038
|
-
)
|
|
7465
|
+
),
|
|
7466
|
+
publicKey
|
|
7039
7467
|
};
|
|
7040
7468
|
}
|
|
7041
7469
|
);
|
|
7042
7470
|
}
|
|
7043
7471
|
};
|
|
7044
7472
|
|
|
7045
|
-
// ../../packages/sdk/dist/chunk-
|
|
7046
|
-
import { Network as
|
|
7047
|
-
var shelbyNetworks = [
|
|
7473
|
+
// ../../packages/sdk/dist/chunk-D6GQHO6G.mjs
|
|
7474
|
+
import { Network as Network4 } from "@aptos-labs/ts-sdk";
|
|
7475
|
+
var shelbyNetworks = [
|
|
7476
|
+
Network4.LOCAL,
|
|
7477
|
+
Network4.TESTNET,
|
|
7478
|
+
Network4.SHELBYNET
|
|
7479
|
+
];
|
|
7048
7480
|
|
|
7049
7481
|
// ../../packages/sdk/dist/chunk-BDSW5PHM.mjs
|
|
7050
|
-
import { Network as
|
|
7482
|
+
import { Network as Network5 } from "@aptos-labs/ts-sdk";
|
|
7051
7483
|
function getShelbyExplorerBaseUrl(network) {
|
|
7052
7484
|
const normalizedNetwork = network.toLowerCase();
|
|
7053
7485
|
switch (normalizedNetwork) {
|
|
7054
|
-
case
|
|
7486
|
+
case Network5.MAINNET.toLowerCase():
|
|
7055
7487
|
return "https://explorer.shelby.xyz/mainnet";
|
|
7056
|
-
case
|
|
7488
|
+
case Network5.TESTNET.toLowerCase():
|
|
7057
7489
|
return "https://explorer.shelby.xyz/testnet";
|
|
7058
|
-
case
|
|
7490
|
+
case Network5.DEVNET.toLowerCase():
|
|
7059
7491
|
return "https://explorer.shelby.xyz/devnet";
|
|
7060
|
-
case
|
|
7492
|
+
case Network5.LOCAL.toLowerCase():
|
|
7061
7493
|
return "https://explorer.shelby.xyz/local";
|
|
7062
|
-
case
|
|
7494
|
+
case Network5.SHELBYNET.toLowerCase():
|
|
7063
7495
|
return "https://explorer.shelby.xyz/shelbynet";
|
|
7064
7496
|
default:
|
|
7065
7497
|
return `https://explorer.shelby.xyz/${normalizedNetwork}`;
|
|
@@ -7070,20 +7502,40 @@ function getShelbyAccountExplorerUrl(network, accountAddress) {
|
|
|
7070
7502
|
return `${baseUrl}/account/${accountAddress}`;
|
|
7071
7503
|
}
|
|
7072
7504
|
|
|
7505
|
+
// ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
|
|
7506
|
+
var __defProp2 = Object.defineProperty;
|
|
7507
|
+
var __export = (target, all) => {
|
|
7508
|
+
for (var name2 in all)
|
|
7509
|
+
__defProp2(target, name2, { get: all[name2], enumerable: true });
|
|
7510
|
+
};
|
|
7511
|
+
|
|
7512
|
+
// ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
|
|
7513
|
+
var testUtil_exports = {};
|
|
7514
|
+
__export(testUtil_exports, {
|
|
7515
|
+
makeChunk: () => makeChunk
|
|
7516
|
+
});
|
|
7517
|
+
function makeChunk(n) {
|
|
7518
|
+
const c = Buffer.alloc(n);
|
|
7519
|
+
for (let i = 0; i < n; ++i) {
|
|
7520
|
+
c[i] = i % 256;
|
|
7521
|
+
}
|
|
7522
|
+
return c;
|
|
7523
|
+
}
|
|
7524
|
+
|
|
7073
7525
|
// ../../packages/sdk/dist/chunk-C6RQ3AEU.mjs
|
|
7074
|
-
import { Network as
|
|
7526
|
+
import { Network as Network6 } from "@aptos-labs/ts-sdk";
|
|
7075
7527
|
function getAptosExplorerBaseUrl(network) {
|
|
7076
7528
|
const normalizedNetwork = network.toLowerCase();
|
|
7077
7529
|
switch (normalizedNetwork) {
|
|
7078
|
-
case
|
|
7530
|
+
case Network6.MAINNET.toLowerCase():
|
|
7079
7531
|
return "https://explorer.aptoslabs.com";
|
|
7080
|
-
case
|
|
7532
|
+
case Network6.TESTNET.toLowerCase():
|
|
7081
7533
|
return "https://explorer.aptoslabs.com";
|
|
7082
|
-
case
|
|
7534
|
+
case Network6.DEVNET.toLowerCase():
|
|
7083
7535
|
return "https://explorer.aptoslabs.com";
|
|
7084
|
-
case
|
|
7536
|
+
case Network6.LOCAL.toLowerCase():
|
|
7085
7537
|
return "https://explorer.aptoslabs.com";
|
|
7086
|
-
case
|
|
7538
|
+
case Network6.SHELBYNET.toLowerCase():
|
|
7087
7539
|
return "https://explorer.aptoslabs.com";
|
|
7088
7540
|
default:
|
|
7089
7541
|
return "https://explorer.aptoslabs.com";
|
|
@@ -7092,15 +7544,15 @@ function getAptosExplorerBaseUrl(network) {
|
|
|
7092
7544
|
function getAptosExplorerNetworkParam(network) {
|
|
7093
7545
|
const normalizedNetwork = network.toLowerCase();
|
|
7094
7546
|
switch (normalizedNetwork) {
|
|
7095
|
-
case
|
|
7547
|
+
case Network6.MAINNET.toLowerCase():
|
|
7096
7548
|
return "mainnet";
|
|
7097
|
-
case
|
|
7549
|
+
case Network6.TESTNET.toLowerCase():
|
|
7098
7550
|
return "testnet";
|
|
7099
|
-
case
|
|
7551
|
+
case Network6.DEVNET.toLowerCase():
|
|
7100
7552
|
return "devnet";
|
|
7101
|
-
case
|
|
7553
|
+
case Network6.LOCAL.toLowerCase():
|
|
7102
7554
|
return "local";
|
|
7103
|
-
case
|
|
7555
|
+
case Network6.SHELBYNET.toLowerCase():
|
|
7104
7556
|
return "shelbynet";
|
|
7105
7557
|
default:
|
|
7106
7558
|
return normalizedNetwork;
|
|
@@ -7468,7 +7920,7 @@ function validateAccountName(name2, config) {
|
|
|
7468
7920
|
// src/utils/keys.ts
|
|
7469
7921
|
import {
|
|
7470
7922
|
Account,
|
|
7471
|
-
AccountAddress as
|
|
7923
|
+
AccountAddress as AccountAddress6,
|
|
7472
7924
|
Ed25519PrivateKey as Ed25519PrivateKey2,
|
|
7473
7925
|
Secp256k1PrivateKey,
|
|
7474
7926
|
SigningSchemeInput
|
|
@@ -7490,7 +7942,7 @@ function isValidEd25519PrivateKey(value) {
|
|
|
7490
7942
|
}
|
|
7491
7943
|
}
|
|
7492
7944
|
function isValidAddress(address) {
|
|
7493
|
-
return
|
|
7945
|
+
return AccountAddress6.isValid({ input: address }).valid;
|
|
7494
7946
|
}
|
|
7495
7947
|
var ED25519_NAME = "ed25519";
|
|
7496
7948
|
var SignatureSchemeSchema = z9.enum([ED25519_NAME]);
|
|
@@ -8140,7 +8592,7 @@ import { useState as useState5 } from "react";
|
|
|
8140
8592
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
8141
8593
|
|
|
8142
8594
|
// src/components/InitWizard.tsx
|
|
8143
|
-
import { Account as Account2, Ed25519PrivateKey as Ed25519PrivateKey3, Network as
|
|
8595
|
+
import { Account as Account2, Ed25519PrivateKey as Ed25519PrivateKey3, Network as Network8 } from "@aptos-labs/ts-sdk";
|
|
8144
8596
|
import { Box as Box6, Text as Text6 } from "ink";
|
|
8145
8597
|
import SelectInput3 from "ink-select-input";
|
|
8146
8598
|
import Spinner from "ink-spinner";
|
|
@@ -8149,12 +8601,12 @@ import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
|
8149
8601
|
|
|
8150
8602
|
// src/utils/balance.ts
|
|
8151
8603
|
import {
|
|
8152
|
-
AccountAddress as
|
|
8604
|
+
AccountAddress as AccountAddress7,
|
|
8153
8605
|
AptosApiError
|
|
8154
8606
|
} from "@aptos-labs/ts-sdk";
|
|
8155
8607
|
|
|
8156
8608
|
// src/utils/constants.ts
|
|
8157
|
-
import { APTOS_COIN, Network as
|
|
8609
|
+
import { APTOS_COIN, Network as Network7 } from "@aptos-labs/ts-sdk";
|
|
8158
8610
|
|
|
8159
8611
|
// src/utils/context-helpers.ts
|
|
8160
8612
|
import {
|
|
@@ -8183,15 +8635,16 @@ function createContextForNetwork(network) {
|
|
|
8183
8635
|
// src/utils/constants.ts
|
|
8184
8636
|
var DEFAULT_CONFIG = {
|
|
8185
8637
|
contexts: {
|
|
8186
|
-
[
|
|
8187
|
-
...createContextForNetwork(
|
|
8638
|
+
[Network7.LOCAL]: {
|
|
8639
|
+
...createContextForNetwork(Network7.LOCAL),
|
|
8188
8640
|
// Override shelby_network for local
|
|
8189
8641
|
shelby_network: { rpc_endpoint: "http://localhost:9090/" }
|
|
8190
8642
|
},
|
|
8191
|
-
[
|
|
8643
|
+
[Network7.SHELBYNET]: createContextForNetwork(Network7.SHELBYNET),
|
|
8644
|
+
[Network7.TESTNET]: createContextForNetwork(Network7.TESTNET)
|
|
8192
8645
|
},
|
|
8193
8646
|
accounts: {},
|
|
8194
|
-
default_context:
|
|
8647
|
+
default_context: Network7.SHELBYNET,
|
|
8195
8648
|
default_account: ""
|
|
8196
8649
|
};
|
|
8197
8650
|
var STANDARD_CONTEXT_NAMES = Object.keys(DEFAULT_CONFIG.contexts).join(
|
|
@@ -8236,10 +8689,10 @@ function resolveAccountAddress({
|
|
|
8236
8689
|
if (!isValidAddress(explicitAddress)) {
|
|
8237
8690
|
throw new InvalidAccountAddressError(explicitAddress);
|
|
8238
8691
|
}
|
|
8239
|
-
return
|
|
8692
|
+
return AccountAddress7.from(explicitAddress).toString();
|
|
8240
8693
|
}
|
|
8241
8694
|
if (derivedAddress) {
|
|
8242
|
-
return
|
|
8695
|
+
return AccountAddress7.from(derivedAddress).toString();
|
|
8243
8696
|
}
|
|
8244
8697
|
return void 0;
|
|
8245
8698
|
}
|
|
@@ -8248,7 +8701,7 @@ async function getBalanceWithFallback({
|
|
|
8248
8701
|
accountAddress,
|
|
8249
8702
|
target
|
|
8250
8703
|
}) {
|
|
8251
|
-
const addrString =
|
|
8704
|
+
const addrString = AccountAddress7.from(accountAddress).toString();
|
|
8252
8705
|
const assetType = assetTypeToString(target.asset);
|
|
8253
8706
|
try {
|
|
8254
8707
|
const balance = await aptos.getBalance({
|
|
@@ -8284,7 +8737,7 @@ async function resolveDecimals({
|
|
|
8284
8737
|
}
|
|
8285
8738
|
try {
|
|
8286
8739
|
const metadata = await aptos.getFungibleAssetMetadataByAssetType({
|
|
8287
|
-
assetType: typeof target.asset === "string" ? target.asset :
|
|
8740
|
+
assetType: typeof target.asset === "string" ? target.asset : AccountAddress7.from(target.asset).toString()
|
|
8288
8741
|
});
|
|
8289
8742
|
if (typeof metadata?.decimals === "number") {
|
|
8290
8743
|
return metadata.decimals;
|
|
@@ -8365,7 +8818,7 @@ function assetTypeToString(asset) {
|
|
|
8365
8818
|
if (typeof asset === "string") {
|
|
8366
8819
|
return asset;
|
|
8367
8820
|
}
|
|
8368
|
-
return
|
|
8821
|
+
return AccountAddress7.from(asset).toString();
|
|
8369
8822
|
}
|
|
8370
8823
|
|
|
8371
8824
|
// src/utils/cache.ts
|
|
@@ -8524,7 +8977,9 @@ async function checkForUpdatesAsync() {
|
|
|
8524
8977
|
var providerPromise;
|
|
8525
8978
|
function getErasureCodingProvider() {
|
|
8526
8979
|
if (!providerPromise) {
|
|
8527
|
-
providerPromise = ClayErasureCodingProvider.create(
|
|
8980
|
+
providerPromise = ClayErasureCodingProvider.create(
|
|
8981
|
+
defaultErasureCodingConfig()
|
|
8982
|
+
);
|
|
8528
8983
|
}
|
|
8529
8984
|
return providerPromise;
|
|
8530
8985
|
}
|
|
@@ -8869,9 +9324,9 @@ var InitWizard = ({
|
|
|
8869
9324
|
if (setupStandardContexts) {
|
|
8870
9325
|
const modifiedStandardContexts = { ...DEFAULT_CONFIG.contexts };
|
|
8871
9326
|
if (standardContextsApiKey) {
|
|
8872
|
-
if (modifiedStandardContexts[
|
|
8873
|
-
modifiedStandardContexts[
|
|
8874
|
-
...modifiedStandardContexts[
|
|
9327
|
+
if (modifiedStandardContexts[Network8.SHELBYNET]) {
|
|
9328
|
+
modifiedStandardContexts[Network8.SHELBYNET] = {
|
|
9329
|
+
...modifiedStandardContexts[Network8.SHELBYNET],
|
|
8875
9330
|
api_key: standardContextsApiKey
|
|
8876
9331
|
};
|
|
8877
9332
|
}
|
|
@@ -9058,7 +9513,7 @@ var InitWizard = ({
|
|
|
9058
9513
|
] }),
|
|
9059
9514
|
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
9060
9515
|
"Enter API Key for ",
|
|
9061
|
-
|
|
9516
|
+
Network8.SHELBYNET,
|
|
9062
9517
|
" (optional: press Enter to skip)"
|
|
9063
9518
|
] }),
|
|
9064
9519
|
/* @__PURE__ */ jsx8(
|
|
@@ -9535,7 +9990,8 @@ function accountCommand(program) {
|
|
|
9535
9990
|
columns: [
|
|
9536
9991
|
{ header: "Name", width: 30, flex: true },
|
|
9537
9992
|
{ header: "Size", width: 12 },
|
|
9538
|
-
{ header: "Expires", width: 25 }
|
|
9993
|
+
{ header: "Expires", width: 25 },
|
|
9994
|
+
{ header: "Status", width: 10 }
|
|
9539
9995
|
],
|
|
9540
9996
|
padding: 12
|
|
9541
9997
|
});
|
|
@@ -9552,7 +10008,8 @@ function accountCommand(program) {
|
|
|
9552
10008
|
minute: "2-digit",
|
|
9553
10009
|
hour12: true
|
|
9554
10010
|
});
|
|
9555
|
-
const
|
|
10011
|
+
const status = blob.isWritten ? "Written" : "Pending";
|
|
10012
|
+
const row = [displayName, formattedSize, formattedDate, status];
|
|
9556
10013
|
table.push(row.map((cell, i) => wrapCell(cell, i)));
|
|
9557
10014
|
}
|
|
9558
10015
|
console.log(table.toString());
|
|
@@ -10469,14 +10926,15 @@ import { z as z17 } from "zod";
|
|
|
10469
10926
|
|
|
10470
10927
|
// src/utils/micropayment-manager.ts
|
|
10471
10928
|
import crypto2 from "crypto";
|
|
10472
|
-
import { AccountAddress as
|
|
10929
|
+
import { AccountAddress as AccountAddress9 } from "@aptos-labs/ts-sdk";
|
|
10473
10930
|
|
|
10474
10931
|
// src/utils/micropayment-storage.ts
|
|
10475
10932
|
import os3 from "os";
|
|
10476
10933
|
import path5 from "path";
|
|
10477
10934
|
import {
|
|
10478
|
-
AccountAddress as
|
|
10479
|
-
Ed25519PublicKey
|
|
10935
|
+
AccountAddress as AccountAddress8,
|
|
10936
|
+
Ed25519PublicKey,
|
|
10937
|
+
Ed25519Signature
|
|
10480
10938
|
} from "@aptos-labs/ts-sdk";
|
|
10481
10939
|
import fs6 from "fs-extra";
|
|
10482
10940
|
var MICROPAYMENTS_DIR = path5.join(os3.homedir(), ".shelby", "micropayments");
|
|
@@ -10511,95 +10969,38 @@ function saveLastMicropayment(sender, receiver, asset, micropayment) {
|
|
|
10511
10969
|
fs6.writeFileSync(filePath, base64, "utf-8");
|
|
10512
10970
|
}
|
|
10513
10971
|
function extractMicropaymentParams(micropayment) {
|
|
10514
|
-
const rawTxn = micropayment.micropayment.rawTransaction;
|
|
10515
|
-
const payload = rawTxn.payload;
|
|
10516
|
-
const args = payload.entryFunction.args;
|
|
10517
|
-
const amountBytes = args[0].bcsToBytes();
|
|
10518
|
-
const paymentChannelIdBytes = args[1].bcsToBytes();
|
|
10519
|
-
const sequenceNumberBytes = args[2].bcsToBytes();
|
|
10520
|
-
const amount = Number(
|
|
10521
|
-
new DataView(amountBytes.buffer, amountBytes.byteOffset, 8).getBigUint64(
|
|
10522
|
-
0,
|
|
10523
|
-
true
|
|
10524
|
-
)
|
|
10525
|
-
);
|
|
10526
|
-
const paymentChannelId = Number(
|
|
10527
|
-
new DataView(
|
|
10528
|
-
paymentChannelIdBytes.buffer,
|
|
10529
|
-
paymentChannelIdBytes.byteOffset,
|
|
10530
|
-
8
|
|
10531
|
-
).getBigUint64(0, true)
|
|
10532
|
-
);
|
|
10533
|
-
const sequenceNumber = Number(
|
|
10534
|
-
new DataView(
|
|
10535
|
-
sequenceNumberBytes.buffer,
|
|
10536
|
-
sequenceNumberBytes.byteOffset,
|
|
10537
|
-
8
|
|
10538
|
-
).getBigUint64(0, true)
|
|
10539
|
-
);
|
|
10540
|
-
const fungibleAssetAddress = AccountAddress10.from(
|
|
10541
|
-
args[3].bcsToHex().toString()
|
|
10542
|
-
);
|
|
10543
10972
|
return {
|
|
10544
|
-
amount,
|
|
10545
|
-
paymentChannelId,
|
|
10546
|
-
sequenceNumber,
|
|
10547
|
-
fungibleAssetAddress
|
|
10973
|
+
amount: Number(micropayment.amount),
|
|
10974
|
+
paymentChannelId: Number(micropayment.paymentChannelId),
|
|
10975
|
+
sequenceNumber: Number(micropayment.sequenceNumber),
|
|
10976
|
+
fungibleAssetAddress: micropayment.fungibleAssetAddress
|
|
10548
10977
|
};
|
|
10549
10978
|
}
|
|
10550
|
-
function validateReceivedMicropayment(micropayment, expectedSender, expectedReceiver
|
|
10551
|
-
|
|
10552
|
-
const senderSignature = micropayment.senderSignature;
|
|
10553
|
-
if (!senderSignature.isEd25519()) {
|
|
10554
|
-
throw new Error("Invalid micropayment: signature is not Ed25519");
|
|
10555
|
-
}
|
|
10556
|
-
const senderPubKey = new Ed25519PublicKey(
|
|
10557
|
-
senderSignature.public_key.toString()
|
|
10558
|
-
);
|
|
10559
|
-
if (!senderPubKey.verifySignature({
|
|
10560
|
-
message: signingMessage,
|
|
10561
|
-
signature: senderSignature.signature
|
|
10562
|
-
})) {
|
|
10563
|
-
throw new Error("Invalid micropayment: signature verification failed");
|
|
10564
|
-
}
|
|
10565
|
-
const derivedAddress = senderPubKey.authKey().derivedAddress();
|
|
10566
|
-
if (!derivedAddress.equals(expectedSender)) {
|
|
10979
|
+
function validateReceivedMicropayment(micropayment, expectedSender, expectedReceiver) {
|
|
10980
|
+
if (!micropayment.sender.equals(expectedSender)) {
|
|
10567
10981
|
throw new Error(
|
|
10568
10982
|
"Invalid micropayment: sender address does not match expected sender"
|
|
10569
10983
|
);
|
|
10570
10984
|
}
|
|
10571
|
-
if (!
|
|
10572
|
-
throw new Error(
|
|
10573
|
-
"Invalid micropayment: transaction sender does not match expected sender"
|
|
10574
|
-
);
|
|
10575
|
-
}
|
|
10576
|
-
const isReceiverInSecondarySigners = micropayment.micropayment.secondarySignerAddresses.some(
|
|
10577
|
-
(addr) => addr.equals(expectedReceiver)
|
|
10578
|
-
);
|
|
10579
|
-
if (!isReceiverInSecondarySigners) {
|
|
10580
|
-
throw new Error(
|
|
10581
|
-
"Invalid micropayment: expected receiver not found in secondary signers"
|
|
10582
|
-
);
|
|
10583
|
-
}
|
|
10584
|
-
if (!("entryFunction" in rawTxn.payload)) {
|
|
10985
|
+
if (!micropayment.receiver.equals(expectedReceiver)) {
|
|
10585
10986
|
throw new Error(
|
|
10586
|
-
"Invalid micropayment:
|
|
10987
|
+
"Invalid micropayment: receiver address does not match expected receiver"
|
|
10587
10988
|
);
|
|
10588
10989
|
}
|
|
10589
|
-
|
|
10590
|
-
if (!AccountAddress10.from(entryFunction.module_name.address).equals(
|
|
10591
|
-
AccountAddress10.from(MICROPAYMENTS_DEPLOYER)
|
|
10592
|
-
)) {
|
|
10990
|
+
if (!micropayment.deployer.equals(AccountAddress8.from(MICROPAYMENTS_DEPLOYER))) {
|
|
10593
10991
|
throw new Error("Invalid micropayment: incorrect deployer address");
|
|
10594
10992
|
}
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
if (
|
|
10599
|
-
throw new Error("Invalid micropayment:
|
|
10993
|
+
const pubKey = new Ed25519PublicKey(micropayment.publicKey);
|
|
10994
|
+
const signature = new Ed25519Signature(micropayment.signature);
|
|
10995
|
+
const message = micropayment.getSignedMessage();
|
|
10996
|
+
if (!pubKey.verifySignature({ message, signature })) {
|
|
10997
|
+
throw new Error("Invalid micropayment: signature verification failed");
|
|
10600
10998
|
}
|
|
10601
|
-
|
|
10602
|
-
|
|
10999
|
+
const derivedAddress = pubKey.authKey().derivedAddress();
|
|
11000
|
+
if (!derivedAddress.equals(expectedSender)) {
|
|
11001
|
+
throw new Error(
|
|
11002
|
+
"Invalid micropayment: public key does not derive to expected sender address"
|
|
11003
|
+
);
|
|
10603
11004
|
}
|
|
10604
11005
|
}
|
|
10605
11006
|
|
|
@@ -10619,7 +11020,7 @@ var MicropaymentManager = class {
|
|
|
10619
11020
|
this.micropaymentClient = micropaymentClient;
|
|
10620
11021
|
this.sender = sender;
|
|
10621
11022
|
this.receiver = receiver;
|
|
10622
|
-
this.fungibleAssetAddress =
|
|
11023
|
+
this.fungibleAssetAddress = AccountAddress9.from(
|
|
10623
11024
|
SHELBYUSD_FA_METADATA_ADDRESS
|
|
10624
11025
|
);
|
|
10625
11026
|
}
|
|
@@ -10718,22 +11119,20 @@ var MicropaymentManager = class {
|
|
|
10718
11119
|
/**
|
|
10719
11120
|
* Creates a micropayment for the next request.
|
|
10720
11121
|
*/
|
|
10721
|
-
|
|
11122
|
+
createMicropayment() {
|
|
10722
11123
|
if (!this.channelInfo) {
|
|
10723
11124
|
throw new Error("Channel not initialized");
|
|
10724
11125
|
}
|
|
10725
11126
|
const newAmount = this.currentAmount + MICROPAYMENT_INCREMENT_PER_REQUEST;
|
|
10726
11127
|
const newSequenceNumber = this.nextSequenceNumber;
|
|
10727
|
-
|
|
11128
|
+
return this.micropaymentClient.createMicropayment({
|
|
10728
11129
|
sender: this.sender,
|
|
10729
11130
|
receiver: this.receiver,
|
|
10730
11131
|
amount: newAmount,
|
|
10731
11132
|
paymentChannelId: this.channelInfo.paymentChannelId,
|
|
10732
11133
|
sequenceNumber: newSequenceNumber,
|
|
10733
|
-
fungibleAssetAddress: this.fungibleAssetAddress
|
|
10734
|
-
options: { replayProtectionNonce: crypto2.randomInt(2 ** 24) }
|
|
11134
|
+
fungibleAssetAddress: this.fungibleAssetAddress
|
|
10735
11135
|
});
|
|
10736
|
-
return micropayment;
|
|
10737
11136
|
}
|
|
10738
11137
|
/**
|
|
10739
11138
|
* Called after a successful request to update local state.
|
|
@@ -10753,14 +11152,10 @@ var MicropaymentManager = class {
|
|
|
10753
11152
|
* Called when a stale error is received to update local state from the server's stored payment.
|
|
10754
11153
|
*/
|
|
10755
11154
|
onStaleError(storedMicropayment) {
|
|
10756
|
-
const signingMessage = this.micropaymentClient.aptos.getSigningMessage({
|
|
10757
|
-
transaction: storedMicropayment.micropayment
|
|
10758
|
-
});
|
|
10759
11155
|
validateReceivedMicropayment(
|
|
10760
11156
|
storedMicropayment,
|
|
10761
11157
|
this.sender.accountAddress,
|
|
10762
|
-
this.receiver
|
|
10763
|
-
signingMessage
|
|
11158
|
+
this.receiver
|
|
10764
11159
|
);
|
|
10765
11160
|
const params = extractMicropaymentParams(storedMicropayment);
|
|
10766
11161
|
this.currentAmount = params.amount;
|
|
@@ -10783,7 +11178,7 @@ async function createMicropaymentManager(context, sender) {
|
|
|
10783
11178
|
apiKey: context.api_key,
|
|
10784
11179
|
aptos: getAptosSettingsFromContext(context)
|
|
10785
11180
|
});
|
|
10786
|
-
const receiver =
|
|
11181
|
+
const receiver = AccountAddress9.from(receiverAddress);
|
|
10787
11182
|
const manager = new MicropaymentManager(micropaymentClient, sender, receiver);
|
|
10788
11183
|
await manager.initialize();
|
|
10789
11184
|
return manager;
|
|
@@ -11300,12 +11695,12 @@ function downloadCommand(program) {
|
|
|
11300
11695
|
}
|
|
11301
11696
|
|
|
11302
11697
|
// src/commands/faucet.tsx
|
|
11303
|
-
import { Network as
|
|
11698
|
+
import { Network as Network9 } from "@aptos-labs/ts-sdk";
|
|
11304
11699
|
import { Option as Option2 } from "@commander-js/extra-typings";
|
|
11305
11700
|
import { execaSync } from "execa";
|
|
11306
11701
|
import { z as z18 } from "zod";
|
|
11307
11702
|
var FaucetOptionsSchema = z18.object({
|
|
11308
|
-
network: z18.enum([
|
|
11703
|
+
network: z18.enum([Network9.SHELBYNET, Network9.TESTNET]).optional(),
|
|
11309
11704
|
open: z18.boolean().optional().default(true)
|
|
11310
11705
|
});
|
|
11311
11706
|
function faucetCommand(program) {
|
|
@@ -11313,7 +11708,7 @@ function faucetCommand(program) {
|
|
|
11313
11708
|
new Option2(
|
|
11314
11709
|
"--network <network>",
|
|
11315
11710
|
"Network to request tokens for (shelbynet)"
|
|
11316
|
-
).choices(Object.values(
|
|
11711
|
+
).choices(Object.values(Network9))
|
|
11317
11712
|
).addOption(
|
|
11318
11713
|
new Option2(
|
|
11319
11714
|
"--no-open",
|
|
@@ -11325,7 +11720,7 @@ function faucetCommand(program) {
|
|
|
11325
11720
|
const { config } = loadConfigOrExit(program.opts().configFile);
|
|
11326
11721
|
const accountName = program.opts().account || config.default_account;
|
|
11327
11722
|
const { account } = getCurrentAccount(config, accountName);
|
|
11328
|
-
const network = validatedOptions.network ||
|
|
11723
|
+
const network = validatedOptions.network || Network9.SHELBYNET;
|
|
11329
11724
|
if (network === "mainnet") {
|
|
11330
11725
|
throw new Error(
|
|
11331
11726
|
"\u274C No faucet available for mainnet. Mainnet tokens must be obtained through other means."
|
|
@@ -11387,7 +11782,7 @@ function openBrowser(url) {
|
|
|
11387
11782
|
|
|
11388
11783
|
// src/commands/init.tsx
|
|
11389
11784
|
import path7 from "path";
|
|
11390
|
-
import { Network as
|
|
11785
|
+
import { Network as Network10 } from "@aptos-labs/ts-sdk";
|
|
11391
11786
|
import fs8 from "fs-extra";
|
|
11392
11787
|
import { render as render4 } from "ink";
|
|
11393
11788
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
@@ -11459,7 +11854,7 @@ function initCommand(program) {
|
|
|
11459
11854
|
console.log(` Private key: ${generated.privateKey.toAIP80String()}`);
|
|
11460
11855
|
console.log("");
|
|
11461
11856
|
console.log(
|
|
11462
|
-
`\u2139\uFE0F To fund your new account on-chain (${
|
|
11857
|
+
`\u2139\uFE0F To fund your new account on-chain (${Network10.SHELBYNET} only), run:`
|
|
11463
11858
|
);
|
|
11464
11859
|
console.log(" \u{1F449} shelby faucet");
|
|
11465
11860
|
console.log("");
|
|
@@ -11490,7 +11885,7 @@ function initCommand(program) {
|
|
|
11490
11885
|
)) {
|
|
11491
11886
|
console.log("");
|
|
11492
11887
|
console.log(
|
|
11493
|
-
`\u2139\uFE0F To fund your new account on-chain (${
|
|
11888
|
+
`\u2139\uFE0F To fund your new account on-chain (${Network10.SHELBYNET} only), run:`
|
|
11494
11889
|
);
|
|
11495
11890
|
console.log(" \u{1F449} shelby faucet");
|
|
11496
11891
|
}
|