@shelby-protocol/cli 0.0.6 → 0.0.8
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 +1879 -1506
- package/package.json +20 -18
package/bin/entry.js
CHANGED
|
@@ -4,409 +4,1064 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// package.json
|
|
7
|
-
var version = "0.0.
|
|
7
|
+
var version = "0.0.8";
|
|
8
8
|
|
|
9
|
-
// src/commands/
|
|
10
|
-
import {
|
|
9
|
+
// src/commands/account.tsx
|
|
10
|
+
import { Hex as Hex3 } from "@aptos-labs/ts-sdk";
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
// ../../packages/sdk/dist/chunk-OTBLZL2S.mjs
|
|
13
|
+
import { AccountAddress } from "@aptos-labs/ts-sdk";
|
|
14
|
+
var createBlobKey = (params) => {
|
|
15
|
+
return `@${AccountAddress.from(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
|
|
16
|
+
};
|
|
16
17
|
|
|
17
|
-
//
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return account;
|
|
31
|
-
}
|
|
32
|
-
function isValidEd25519PrivateKey(value) {
|
|
18
|
+
// ../../packages/sdk/dist/chunk-5Z3RVWU3.mjs
|
|
19
|
+
import { Hex } from "@aptos-labs/ts-sdk";
|
|
20
|
+
async function* readInChunks(input, chunkSize) {
|
|
21
|
+
let idx = 0;
|
|
22
|
+
if (Buffer.isBuffer(input)) {
|
|
23
|
+
for (let offset = 0; offset < input.length; offset += chunkSize) {
|
|
24
|
+
yield [idx++, Buffer.from(input.subarray(offset, offset + chunkSize))];
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const reader = input.getReader();
|
|
29
|
+
let buffer = new Uint8Array(chunkSize);
|
|
30
|
+
let bufferWriteOffset = 0;
|
|
33
31
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
while (true) {
|
|
33
|
+
const { value, done } = await reader.read();
|
|
34
|
+
if (done) break;
|
|
35
|
+
if (value === void 0) continue;
|
|
36
|
+
let srcOffset = 0;
|
|
37
|
+
while (srcOffset < value.length) {
|
|
38
|
+
const remainingCapacity = chunkSize - bufferWriteOffset;
|
|
39
|
+
const bytesToCopy = Math.min(
|
|
40
|
+
remainingCapacity,
|
|
41
|
+
value.length - srcOffset
|
|
42
|
+
);
|
|
43
|
+
buffer.set(
|
|
44
|
+
value.subarray(srcOffset, srcOffset + bytesToCopy),
|
|
45
|
+
bufferWriteOffset
|
|
46
|
+
);
|
|
47
|
+
bufferWriteOffset += bytesToCopy;
|
|
48
|
+
srcOffset += bytesToCopy;
|
|
49
|
+
if (bufferWriteOffset >= chunkSize) {
|
|
50
|
+
yield [idx++, Buffer.from(buffer)];
|
|
51
|
+
buffer = new Uint8Array(chunkSize);
|
|
52
|
+
bufferWriteOffset = 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} finally {
|
|
57
|
+
reader.releaseLock();
|
|
58
|
+
}
|
|
59
|
+
if (bufferWriteOffset > 0) {
|
|
60
|
+
yield [idx++, Buffer.from(buffer.subarray(0, bufferWriteOffset))];
|
|
38
61
|
}
|
|
39
62
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
63
|
+
function zeroPadBuffer(buffer, desiredLength) {
|
|
64
|
+
if (buffer.length >= desiredLength) {
|
|
65
|
+
return buffer;
|
|
66
|
+
}
|
|
67
|
+
const paddedBuffer = Buffer.alloc(desiredLength);
|
|
68
|
+
buffer.copy(paddedBuffer);
|
|
69
|
+
return paddedBuffer;
|
|
42
70
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
async function concatHashes(parts) {
|
|
72
|
+
const combined = Buffer.concat(
|
|
73
|
+
parts.map((part) => Hex.fromHexInput(part).toUint8Array())
|
|
74
|
+
);
|
|
75
|
+
return Hex.fromHexInput(
|
|
76
|
+
new Uint8Array(await crypto.subtle.digest("SHA-256", combined))
|
|
77
|
+
);
|
|
47
78
|
}
|
|
48
79
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
var AccountWizard = ({ onComplete }) => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
80
|
+
// ../../packages/reed-solomon/dist/index.mjs
|
|
81
|
+
var __toBinaryNode = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
|
|
82
|
+
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==");
|
|
83
|
+
var ReedSolomonErasure = class _ReedSolomonErasure {
|
|
84
|
+
constructor(exports) {
|
|
85
|
+
this.exports = exports;
|
|
86
|
+
}
|
|
87
|
+
static RESULT_OK = 0;
|
|
88
|
+
static RESULT_ERROR_TOO_FEW_SHARDS = 1;
|
|
89
|
+
static RESULT_ERROR_TOO_MANY_SHARDS = 2;
|
|
90
|
+
static RESULT_ERROR_TOO_FEW_DATA_SHARDS = 3;
|
|
91
|
+
static RESULT_ERROR_TOO_MANY_DATA_SHARDS = 4;
|
|
92
|
+
static RESULT_ERROR_TOO_FEW_PARITY_SHARDS = 5;
|
|
93
|
+
static RESULT_ERROR_TOO_MANY_PARITY_SHARDS = 6;
|
|
94
|
+
static RESULT_ERROR_TOO_FEW_BUFFER_SHARDS = 7;
|
|
95
|
+
static RESULT_ERROR_TOO_MANY_BUFFER_SHARDS = 8;
|
|
96
|
+
static RESULT_ERROR_INCORRECT_SHARD_SIZE = 9;
|
|
97
|
+
static RESULT_ERROR_TOO_FEW_SHARDS_PRESENT = 10;
|
|
98
|
+
static RESULT_ERROR_EMPTY_SHARD = 11;
|
|
99
|
+
static RESULT_ERROR_INVALID_SHARD_FLAGS = 12;
|
|
100
|
+
static RESULT_ERROR_INVALID_INDEX = 13;
|
|
101
|
+
static fromBytes(bytes) {
|
|
102
|
+
const module = new WebAssembly.Module(bytes);
|
|
103
|
+
const instance = new WebAssembly.Instance(module);
|
|
104
|
+
return new _ReedSolomonErasure(
|
|
105
|
+
instance.exports
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
memoryCache = null;
|
|
109
|
+
/**
|
|
110
|
+
* Takes a contiguous array of bytes that contain space for `data_shards + parity_shards` shards with `data_shards` shards containing data and fills
|
|
111
|
+
* additional `parity_shards` with parity information that can be later used to reconstruct data in case of corruption
|
|
112
|
+
*
|
|
113
|
+
* @param shards
|
|
114
|
+
* @param dataShards
|
|
115
|
+
* @param parityShards
|
|
116
|
+
*
|
|
117
|
+
* @returns One of `RESULT_*` constants; if `RESULT_OK` then parity shards were updated in `shards` in-place
|
|
118
|
+
*/
|
|
119
|
+
encode(shards, dataShards, parityShards) {
|
|
120
|
+
const exports = this.exports;
|
|
121
|
+
const shardsLength = shards.length;
|
|
122
|
+
const shardsPointer = exports.__wbindgen_malloc(shardsLength);
|
|
123
|
+
this.getUint8Memory().set(shards, shardsPointer);
|
|
124
|
+
const shardSize = shardsLength / (dataShards + parityShards);
|
|
125
|
+
const result = exports.encode(
|
|
126
|
+
shardsPointer,
|
|
127
|
+
shardsLength,
|
|
128
|
+
dataShards,
|
|
129
|
+
parityShards
|
|
130
|
+
);
|
|
131
|
+
if (result === _ReedSolomonErasure.RESULT_OK) {
|
|
132
|
+
shards.set(
|
|
133
|
+
this.getUint8Memory().subarray(
|
|
134
|
+
shardsPointer + shardSize * dataShards,
|
|
135
|
+
shardsPointer + shardsLength
|
|
136
|
+
),
|
|
137
|
+
shardSize * dataShards
|
|
138
|
+
);
|
|
63
139
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
67
|
-
/* @__PURE__ */ jsx(Text, { children: "Account name?" }),
|
|
68
|
-
/* @__PURE__ */ jsx(
|
|
69
|
-
TextInput,
|
|
70
|
-
{
|
|
71
|
-
value: name2,
|
|
72
|
-
onChange: setName,
|
|
73
|
-
onSubmit: () => setStep("address")
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
] });
|
|
140
|
+
exports.__wbindgen_free(shardsPointer, shardsLength);
|
|
141
|
+
return result;
|
|
77
142
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Takes a contiguous array of bytes that contain `data_shards + parity_shards` shards and tries to reconstruct data shards if they are broken and whenever
|
|
145
|
+
* possible using information from `shards_available` (contains `data_shards + parity_shards` boolean values, each of which is either `true` if shard is not
|
|
146
|
+
* corrupted or `false` if it is)
|
|
147
|
+
*
|
|
148
|
+
* @param shards
|
|
149
|
+
* @param dataShards
|
|
150
|
+
* @param parityShards
|
|
151
|
+
* @param shardsAvailable
|
|
152
|
+
*
|
|
153
|
+
* @returns One of `RESULT_*` constants; if `RESULT_OK` then data shards were reconstructed in `shards` in-place
|
|
154
|
+
*/
|
|
155
|
+
reconstruct(shards, dataShards, parityShards, shardsAvailable) {
|
|
156
|
+
const exports = this.exports;
|
|
157
|
+
const shardsLength = shards.length;
|
|
158
|
+
const shardsPointer = exports.__wbindgen_malloc(shardsLength);
|
|
159
|
+
this.getUint8Memory().set(shards, shardsPointer);
|
|
160
|
+
const shardsAvailableLength = shardsAvailable.length;
|
|
161
|
+
const shardsAvailablePointer = exports.__wbindgen_malloc(
|
|
162
|
+
shardsAvailableLength
|
|
163
|
+
);
|
|
164
|
+
this.getUint8Memory().set(
|
|
165
|
+
shardsAvailable.map((value) => value ? 1 : 0),
|
|
166
|
+
shardsAvailablePointer
|
|
167
|
+
);
|
|
168
|
+
const shardSize = shardsLength / (dataShards + parityShards);
|
|
169
|
+
const result = exports.reconstruct(
|
|
170
|
+
shardsPointer,
|
|
171
|
+
shardsLength,
|
|
172
|
+
dataShards,
|
|
173
|
+
parityShards,
|
|
174
|
+
shardsAvailablePointer,
|
|
175
|
+
shardsAvailableLength
|
|
176
|
+
);
|
|
177
|
+
if (result === _ReedSolomonErasure.RESULT_OK) {
|
|
178
|
+
shards.set(
|
|
179
|
+
this.getUint8Memory().subarray(
|
|
180
|
+
shardsPointer,
|
|
181
|
+
shardsPointer + shardSize * dataShards
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
exports.__wbindgen_free(shardsPointer, shardsLength);
|
|
186
|
+
exports.__wbindgen_free(shardsAvailablePointer, shardsAvailableLength);
|
|
187
|
+
return result;
|
|
90
188
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
onChange: setPrivateKey,
|
|
99
|
-
onSubmit: () => {
|
|
100
|
-
if (!privateKey) {
|
|
101
|
-
const acct = generateEd25519Account();
|
|
102
|
-
setPrivateKey(acct.privateKey.toAIP80String());
|
|
103
|
-
setAddress((prev) => prev || acct.accountAddress.toString());
|
|
104
|
-
}
|
|
105
|
-
setStep("done");
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
)
|
|
109
|
-
] });
|
|
189
|
+
getUint8Memory() {
|
|
190
|
+
let cachegetUint8Memory = this.memoryCache;
|
|
191
|
+
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== this.exports.memory.buffer) {
|
|
192
|
+
cachegetUint8Memory = new Uint8Array(this.exports.memory.buffer);
|
|
193
|
+
this.memoryCache = cachegetUint8Memory;
|
|
194
|
+
}
|
|
195
|
+
return cachegetUint8Memory;
|
|
110
196
|
}
|
|
111
|
-
return null;
|
|
112
197
|
};
|
|
198
|
+
function createWasmReedSolomonBinding() {
|
|
199
|
+
return ReedSolomonErasure.fromBytes(reed_solomon_erasure_bg_default);
|
|
200
|
+
}
|
|
113
201
|
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const [aptosNetwork, setAptosNetwork] = useState2("mainnet");
|
|
132
|
-
const [setupAccount, setSetupAccount] = useState2(false);
|
|
133
|
-
const [accountName, setAccountName] = useState2("alice");
|
|
134
|
-
const [signatureScheme, setSignatureScheme] = useState2("ed25519");
|
|
135
|
-
const [privateKey, setPrivateKey] = useState2("");
|
|
136
|
-
const [address, setAddress] = useState2("");
|
|
137
|
-
const [generatedKey, setGeneratedKey] = useState2("");
|
|
138
|
-
const [generatedAddress, setGeneratedAddress] = useState2("");
|
|
139
|
-
useEffect2(() => {
|
|
140
|
-
if (step === "checkAptos") {
|
|
141
|
-
try {
|
|
142
|
-
const aptosVersion = execSync("aptos --version").toString().trim();
|
|
143
|
-
if (aptosVersion.includes("aptos")) {
|
|
144
|
-
setAptosFound(true);
|
|
145
|
-
}
|
|
146
|
-
} catch (error) {
|
|
147
|
-
}
|
|
148
|
-
setStep("standardContexts");
|
|
149
|
-
}
|
|
150
|
-
}, [step]);
|
|
151
|
-
useEffect2(() => {
|
|
152
|
-
if (step === "complete") {
|
|
153
|
-
const config = {
|
|
154
|
-
contexts: {},
|
|
155
|
-
accounts: {},
|
|
156
|
-
default_context: setupStandardContexts ? "devnet" : customContextName,
|
|
157
|
-
default_account: setupAccount ? accountName : "default_account"
|
|
158
|
-
};
|
|
159
|
-
if (setupStandardContexts) {
|
|
160
|
-
config.contexts.local = {
|
|
161
|
-
aptos_network: "local",
|
|
162
|
-
shelby_rpc_endpoint: "http://localhost:9090"
|
|
163
|
-
};
|
|
164
|
-
config.contexts.devnet = {
|
|
165
|
-
aptos_network: "devnet",
|
|
166
|
-
shelby_rpc_endpoint: "https://shelby.rpc.devnet.example.com"
|
|
167
|
-
};
|
|
168
|
-
config.contexts.testnet = {
|
|
169
|
-
aptos_network: "testnet",
|
|
170
|
-
shelby_rpc_endpoint: "https://shelby.rpc.testnet.example.com"
|
|
171
|
-
};
|
|
172
|
-
config.contexts.mainnet = {
|
|
173
|
-
aptos_network: "mainnet",
|
|
174
|
-
shelby_rpc_endpoint: "https://shelby.rpc.mainnet.example.com"
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
if (setupCustomContext) {
|
|
178
|
-
config.contexts[customContextName] = {
|
|
179
|
-
aptos_network: aptosNetwork,
|
|
180
|
-
shelby_rpc_endpoint: shelbyRpcEndpoint
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
if (setupAccount) {
|
|
184
|
-
const finalPrivateKey = privateKey || generatedKey;
|
|
185
|
-
const finalAddress = address || generatedAddress;
|
|
186
|
-
config.accounts[accountName] = {
|
|
187
|
-
private_key: finalPrivateKey,
|
|
188
|
-
address: finalAddress
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
onComplete(config);
|
|
192
|
-
}
|
|
193
|
-
}, [step]);
|
|
194
|
-
if (step === "checkAptos") {
|
|
195
|
-
return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
196
|
-
/* @__PURE__ */ jsx2(Spinner, { type: "dots" }),
|
|
197
|
-
" Checking for Aptos CLI >v7.2.0..."
|
|
198
|
-
] }) });
|
|
199
|
-
}
|
|
200
|
-
if (step === "standardContexts") {
|
|
201
|
-
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
202
|
-
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
203
|
-
"\u2714 Checking for Aptos CLI >v7.2.0...",
|
|
204
|
-
" ",
|
|
205
|
-
aptosFound ? "found" : "not found"
|
|
206
|
-
] }),
|
|
207
|
-
/* @__PURE__ */ jsx2(Text2, { children: "Do you want to set up standard contexts (devnet, testnet, mainnet)?" }),
|
|
208
|
-
/* @__PURE__ */ jsx2(
|
|
209
|
-
SelectInput,
|
|
210
|
-
{
|
|
211
|
-
items: [
|
|
212
|
-
{ label: "Yes", value: true },
|
|
213
|
-
{ label: "No", value: false }
|
|
214
|
-
],
|
|
215
|
-
onSelect: (item) => {
|
|
216
|
-
setSetupStandardContexts(item.value);
|
|
217
|
-
setStep("customContext");
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
)
|
|
221
|
-
] });
|
|
202
|
+
// ../../packages/sdk/dist/chunk-P7BVGLTV.mjs
|
|
203
|
+
function erasureEncode(data, k, m) {
|
|
204
|
+
const rawShardSize = Math.ceil(data.length / k);
|
|
205
|
+
const shardSize = Math.ceil(rawShardSize / 8) * 8;
|
|
206
|
+
const dataSize = shardSize * k;
|
|
207
|
+
const paritySize = shardSize * m;
|
|
208
|
+
const reedSolomon = createWasmReedSolomonBinding();
|
|
209
|
+
const dataBuf = Buffer.alloc(dataSize);
|
|
210
|
+
data.copy(dataBuf, 0);
|
|
211
|
+
const shards = new Uint8Array(dataSize + paritySize);
|
|
212
|
+
shards.set(new Uint8Array(dataBuf), 0);
|
|
213
|
+
reedSolomon.encode(shards, k, m);
|
|
214
|
+
const res = [];
|
|
215
|
+
for (let i = 0; i < k; i++) {
|
|
216
|
+
res.push(
|
|
217
|
+
Buffer.from(shards.slice(i * shardSize, i * shardSize + shardSize))
|
|
218
|
+
);
|
|
222
219
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
" ",
|
|
228
|
-
aptosFound ? "found" : "not found"
|
|
229
|
-
] }),
|
|
230
|
-
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
231
|
-
"\u2714 Do you want to set up standard contexts (devnet, testnet, mainnet)?",
|
|
232
|
-
" ",
|
|
233
|
-
setupStandardContexts ? "Yes" : "No"
|
|
234
|
-
] }),
|
|
235
|
-
/* @__PURE__ */ jsx2(Text2, { children: "Do you want to set up a custom context?" }),
|
|
236
|
-
/* @__PURE__ */ jsx2(
|
|
237
|
-
SelectInput,
|
|
238
|
-
{
|
|
239
|
-
items: [
|
|
240
|
-
{ label: "Yes", value: true },
|
|
241
|
-
{ label: "No", value: false }
|
|
242
|
-
],
|
|
243
|
-
onSelect: (item) => {
|
|
244
|
-
setSetupCustomContext(item.value);
|
|
245
|
-
if (item.value) {
|
|
246
|
-
setStep("customContextDetails");
|
|
247
|
-
} else {
|
|
248
|
-
setStep("setupAccount");
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
220
|
+
for (let j = 0; j < m; j++) {
|
|
221
|
+
res.push(
|
|
222
|
+
Buffer.from(
|
|
223
|
+
shards.slice((k + j) * shardSize, (k + j) * shardSize + shardSize)
|
|
252
224
|
)
|
|
253
|
-
|
|
225
|
+
);
|
|
254
226
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
227
|
+
return new Promise((resolve2) => resolve2(res));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ../../packages/sdk/dist/chunk-NUQZDY3N.mjs
|
|
231
|
+
var DEFAULT_SHELBY_BASE_URL = "https://api.shelby.dev";
|
|
232
|
+
var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
|
|
233
|
+
var ERASURE_K = 10;
|
|
234
|
+
var ERASURE_M = 6;
|
|
235
|
+
var CHUNKSET_SIZE_BYTES = 10 * 1024 * 1024;
|
|
236
|
+
function getChunksetSizeBytes() {
|
|
237
|
+
return CHUNKSET_SIZE_BYTES;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ../../packages/sdk/dist/chunk-6CBXBS3X.mjs
|
|
241
|
+
import { AccountAddress as AccountAddress2 } from "@aptos-labs/ts-sdk";
|
|
242
|
+
import { z } from "zod";
|
|
243
|
+
var BlobNameSchema = z.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name) => !name.endsWith("/"), {
|
|
244
|
+
message: "Blob name cannot end with a slash"
|
|
245
|
+
});
|
|
246
|
+
function roundSize(size) {
|
|
247
|
+
let ret = 0;
|
|
248
|
+
let remain = size;
|
|
249
|
+
while (remain > 0) {
|
|
250
|
+
ret += getChunksetSizeBytes();
|
|
251
|
+
remain -= getChunksetSizeBytes();
|
|
268
252
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
253
|
+
return ret;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ../../packages/sdk/dist/chunk-27CPX5O2.mjs
|
|
257
|
+
import { z as z2 } from "zod";
|
|
258
|
+
var ChunksetCommitmentSchema = z2.object({
|
|
259
|
+
// Chunkset root (vector commitment of child chunks)
|
|
260
|
+
chunkset_root: z2.string().nullable(),
|
|
261
|
+
// the size is known statically from the current configuration
|
|
262
|
+
chunk_commitments: z2.array(z2.string())
|
|
263
|
+
}).refine(
|
|
264
|
+
(data) => {
|
|
265
|
+
return data.chunk_commitments.length === ERASURE_K + ERASURE_M;
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
message: `Chunkset must have exactly ${ERASURE_K + ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${ERASURE_K} + ${ERASURE_M})`,
|
|
269
|
+
path: ["chunk_commitments"]
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
function expectedTotalChunksets(rawSize) {
|
|
273
|
+
return roundSize(rawSize) / getChunksetSizeBytes();
|
|
274
|
+
}
|
|
275
|
+
var BlobCommitmentsSchema = z2.object({
|
|
276
|
+
schema_version: z2.string(),
|
|
277
|
+
raw_data_size: z2.number(),
|
|
278
|
+
// FIXME I am not sure about this being here, or if it should be somewhere else
|
|
279
|
+
blob_merkle_root: z2.string(),
|
|
280
|
+
chunkset_commitments: z2.array(ChunksetCommitmentSchema)
|
|
281
|
+
}).refine(
|
|
282
|
+
(data) => {
|
|
283
|
+
return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
message: "Total chunkset count mismatches with raw data size",
|
|
287
|
+
// FIXME put more details in here
|
|
288
|
+
path: ["chunkset_commitments"]
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
async function generateCommitments(fullData, onChunk, options) {
|
|
292
|
+
const chunksetCommitments = [];
|
|
293
|
+
const chunksetCommitmentHashes = [];
|
|
294
|
+
let rawDataSize = 0;
|
|
295
|
+
const chunksetGen = readInChunks(
|
|
296
|
+
fullData,
|
|
297
|
+
options?.chunksetSize ?? getChunksetSizeBytes()
|
|
298
|
+
);
|
|
299
|
+
for await (const [chunksetIdx, chunksetData] of chunksetGen) {
|
|
300
|
+
const chunkCommitments = [];
|
|
301
|
+
rawDataSize += chunksetData.length;
|
|
302
|
+
const paddedChunksetData = zeroPadBuffer(
|
|
303
|
+
chunksetData,
|
|
304
|
+
options?.chunksetSize ?? getChunksetSizeBytes()
|
|
305
|
+
);
|
|
306
|
+
const chunks = await erasureEncode(
|
|
307
|
+
paddedChunksetData,
|
|
308
|
+
options?.erasureK ?? ERASURE_K,
|
|
309
|
+
options?.erasureM ?? ERASURE_M
|
|
310
|
+
);
|
|
311
|
+
let chunkIdx = 0;
|
|
312
|
+
for (const chunkData of chunks) {
|
|
313
|
+
if (onChunk !== void 0) {
|
|
314
|
+
await onChunk(chunksetIdx, chunkIdx, chunkData);
|
|
315
|
+
}
|
|
316
|
+
const chunkHash = await concatHashes([chunkData]);
|
|
317
|
+
chunkCommitments.push(chunkHash);
|
|
318
|
+
chunkIdx += 1;
|
|
319
|
+
}
|
|
320
|
+
const h = await concatHashes(
|
|
321
|
+
chunkCommitments.map((chunk) => chunk.toUint8Array())
|
|
322
|
+
);
|
|
323
|
+
chunksetCommitments.push({
|
|
324
|
+
chunkset_root: h.toString(),
|
|
325
|
+
chunk_commitments: chunkCommitments.map((chunk) => chunk.toString())
|
|
326
|
+
});
|
|
327
|
+
chunksetCommitmentHashes.push(h);
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
schema_version: "1.3",
|
|
331
|
+
raw_data_size: rawDataSize,
|
|
332
|
+
blob_merkle_root: (await concatHashes(
|
|
333
|
+
chunksetCommitmentHashes.map((chunk) => chunk.toUint8Array())
|
|
334
|
+
)).toString(),
|
|
335
|
+
chunkset_commitments: chunksetCommitments
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ../../packages/sdk/dist/chunk-BRCI47CW.mjs
|
|
340
|
+
import {
|
|
341
|
+
AccountAddress as AccountAddress3,
|
|
342
|
+
Aptos,
|
|
343
|
+
Hex as Hex2,
|
|
344
|
+
MoveVector
|
|
345
|
+
} from "@aptos-labs/ts-sdk";
|
|
346
|
+
var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
347
|
+
aptos;
|
|
348
|
+
deployer;
|
|
349
|
+
/**
|
|
350
|
+
* The ShelbyBlobClient is used to interact with the Shelby contract on the Aptos blockchain. This
|
|
351
|
+
* includes functions like writing blob commitments, confirming chunks, and retrieving blob metadata.
|
|
352
|
+
*
|
|
353
|
+
* @param config.aptos.config - The Aptos config.
|
|
354
|
+
* @param config.shelbyDeployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
|
|
359
|
+
* const blobClient = new ShelbyBlobClient({ aptos });
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
constructor(config) {
|
|
363
|
+
this.aptos = new Aptos(config.aptos.config);
|
|
364
|
+
this.deployer = config.shelby?.deployer ?? AccountAddress3.fromString(SHELBY_DEPLOYER);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Retrieves the blob metadata from the blockchain. If it does not exist,
|
|
368
|
+
* returns `undefined`.
|
|
369
|
+
*
|
|
370
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
371
|
+
* @param params.name - The name of the blob (e.g. "foo/bar")
|
|
372
|
+
* @returns The blob metadata.
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```typescript
|
|
376
|
+
* const metadata = await client.getBlobMetadata({
|
|
377
|
+
* account: AccountAddress.fromString("0x1"),
|
|
378
|
+
* name: "foo/bar.txt",
|
|
379
|
+
* });
|
|
380
|
+
* ```
|
|
381
|
+
*/
|
|
382
|
+
async getBlobMetadata(params) {
|
|
383
|
+
try {
|
|
384
|
+
const rawMetadata = await this.aptos.view({
|
|
385
|
+
payload: {
|
|
386
|
+
function: `${this.deployer.toString()}::global_metadata::get_blob_metadata`,
|
|
387
|
+
functionArguments: [
|
|
388
|
+
createBlobKey({
|
|
389
|
+
account: params.account,
|
|
390
|
+
blobName: params.name
|
|
391
|
+
})
|
|
392
|
+
]
|
|
282
393
|
}
|
|
283
|
-
)
|
|
284
|
-
|
|
394
|
+
});
|
|
395
|
+
if (!rawMetadata?.[0]?.vec?.[0]) {
|
|
396
|
+
return void 0;
|
|
397
|
+
}
|
|
398
|
+
const metadata = rawMetadata[0].vec[0];
|
|
399
|
+
return {
|
|
400
|
+
blobMerkleRoot: Hex2.fromHexInput(
|
|
401
|
+
metadata.blob_commitment
|
|
402
|
+
).toUint8Array(),
|
|
403
|
+
owner: AccountAddress3.fromString(metadata.owner),
|
|
404
|
+
name: params.name,
|
|
405
|
+
size: metadata.blob_size,
|
|
406
|
+
encoding: {
|
|
407
|
+
variant: "clay",
|
|
408
|
+
// TODO
|
|
409
|
+
erasureK: 10,
|
|
410
|
+
erasureM: 6,
|
|
411
|
+
chunksetSize: 10 * 1024 * 1024
|
|
412
|
+
},
|
|
413
|
+
expirationMicros: metadata.expiration_micros
|
|
414
|
+
};
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
417
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
|
|
418
|
+
return void 0;
|
|
419
|
+
}
|
|
420
|
+
throw error;
|
|
421
|
+
}
|
|
285
422
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
423
|
+
/**
|
|
424
|
+
* Retrieves all the blobs and their metadata for an account from the
|
|
425
|
+
* blockchain.
|
|
426
|
+
*
|
|
427
|
+
* @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
|
|
428
|
+
* @returns The blob metadata for all the blobs for the account.
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```typescript
|
|
432
|
+
* // BlobMetadata[]
|
|
433
|
+
* const blobs = await client.getAccountBlobs({
|
|
434
|
+
* account: AccountAddress.fromString("0x1"),
|
|
435
|
+
* });
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
getAccountBlobs(_params) {
|
|
439
|
+
throw new Error("Not implemented");
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Retrieves the blob chunks for a given blob from the blockchain. The blob chunk will contain
|
|
443
|
+
* the commitment, the storage provider location, and the status of the chunk (stored or pending).
|
|
444
|
+
*
|
|
445
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
446
|
+
* @param params.name - The name of the blob (e.g. "foo/bar")
|
|
447
|
+
* @returns The chunks that make up the blob.
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* ```typescript
|
|
451
|
+
* // BlobChunk[]
|
|
452
|
+
* const chunks = await client.getBlobChunks({
|
|
453
|
+
* account: AccountAddress.fromString("0x1"),
|
|
454
|
+
* name: "foo/bar.txt",
|
|
455
|
+
* });
|
|
456
|
+
*
|
|
457
|
+
* const isStored = chunks.every((c) => c.location.variant === "stored");
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
getBlobChunks(_params) {
|
|
461
|
+
throw new Error("Not implemented");
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Writes the blob commitments to the blockchain.
|
|
465
|
+
*
|
|
466
|
+
* If `data` is provided instead of `blobCommitments`, the data will be encoded into commitments before being written
|
|
467
|
+
* to the blockchain.
|
|
468
|
+
*
|
|
469
|
+
* @param params.signer - The account that is signing the transaction.
|
|
470
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
471
|
+
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
472
|
+
* @param params.options - Additional options for transaction building and encoding.
|
|
473
|
+
* @param params.blobCommitments - The blob commitments to write to the blockchain (required if `data` is not provided).
|
|
474
|
+
* @param params.data - The data to encode into commitments before writing to the blockchain (required if `blobCommitments` is not provided).
|
|
475
|
+
*
|
|
476
|
+
* @returns The blob commitments and the pending transaction.
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* ```typescript
|
|
480
|
+
* const blobCommitments = await generateCommitments(data);
|
|
481
|
+
*
|
|
482
|
+
* const { transaction } = await client.registerBlob({
|
|
483
|
+
* account: signer,
|
|
484
|
+
* blobName: "foo/bar.txt",
|
|
485
|
+
* blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
486
|
+
* size: data.length,
|
|
487
|
+
* expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
|
|
488
|
+
* });
|
|
489
|
+
* ```
|
|
490
|
+
*/
|
|
491
|
+
async registerBlob(params) {
|
|
492
|
+
const transaction = await this.aptos.transaction.build.simple({
|
|
493
|
+
...params.options?.build,
|
|
494
|
+
data: _ShelbyBlobClient.createWriteBlobCommitmentsPayload({
|
|
495
|
+
deployer: this.deployer,
|
|
496
|
+
account: params.account.accountAddress,
|
|
497
|
+
blobName: params.blobName,
|
|
498
|
+
blobSize: params.size,
|
|
499
|
+
blobMerkleRoot: params.blobMerkleRoot,
|
|
500
|
+
num_chunksets: expectedTotalChunksets(params.size),
|
|
501
|
+
expirationMicros: params.expirationMicros
|
|
502
|
+
}),
|
|
503
|
+
sender: params.account.accountAddress
|
|
504
|
+
});
|
|
505
|
+
return {
|
|
506
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
507
|
+
signer: params.account,
|
|
508
|
+
transaction
|
|
509
|
+
})
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Confirms an array of signed chunk commitments for a blob. Once all chunks for a blob are confirmed, the blob is
|
|
514
|
+
* considered "stored" and can be retrieved by RPC nodes.
|
|
515
|
+
*
|
|
516
|
+
* @param params.signer - The account that is signing the transaction.
|
|
517
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
518
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
519
|
+
* @param params.signedChunksetChunkCommitments - The signed chunk commitments, signed by their storage provider.
|
|
520
|
+
* @param params.options - Additional options for transaction building and encoding.
|
|
521
|
+
*
|
|
522
|
+
* @returns The pending transaction response.
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```typescript
|
|
526
|
+
* const { transaction } = await client.confirmBlobChunks({
|
|
527
|
+
* signer,
|
|
528
|
+
* account: AccountAddress.fromString("0x1"),
|
|
529
|
+
* blobName: "foo/bar.txt",
|
|
530
|
+
* signedChunksetChunkCommitments,
|
|
531
|
+
* });
|
|
532
|
+
* ```
|
|
533
|
+
*/
|
|
534
|
+
async confirmBlobChunks(params) {
|
|
535
|
+
const transaction = await this.aptos.transaction.build.simple({
|
|
536
|
+
...params.options?.build,
|
|
537
|
+
data: _ShelbyBlobClient.createConfirmBlobChunksPayload({
|
|
538
|
+
deployer: this.deployer,
|
|
539
|
+
account: params.account,
|
|
540
|
+
blobName: params.blobName,
|
|
541
|
+
signedChunksetChunkCommitments: params.signedChunksetChunkCommitments
|
|
542
|
+
}),
|
|
543
|
+
sender: params.signer.accountAddress
|
|
544
|
+
});
|
|
545
|
+
return {
|
|
546
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
547
|
+
signer: params.signer,
|
|
548
|
+
transaction
|
|
549
|
+
})
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Creates a transaction payload to write blob commitments to the blockchain.
|
|
554
|
+
*
|
|
555
|
+
* @param params.deployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
|
|
556
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
557
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
558
|
+
* @param params.blobMerkleRoot - The blob merkle root.
|
|
559
|
+
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
560
|
+
* @param params.size - The size of the blob in bytes.
|
|
561
|
+
*
|
|
562
|
+
* @see https://github.com/JumpCrypto/shelby/blob/e009607aad330ccddb08d80bf9addfaadae7972b/move/prototype/move/sources/prototype_interface.move#L211-L220
|
|
563
|
+
*/
|
|
564
|
+
static createWriteBlobCommitmentsPayload(params) {
|
|
565
|
+
return {
|
|
566
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::global_metadata::register_blob`,
|
|
567
|
+
functionArguments: [
|
|
568
|
+
params.blobName,
|
|
569
|
+
params.expirationMicros,
|
|
570
|
+
MoveVector.U8(params.blobMerkleRoot),
|
|
571
|
+
params.num_chunksets,
|
|
572
|
+
params.blobSize,
|
|
573
|
+
0,
|
|
574
|
+
// payment tier
|
|
575
|
+
0
|
|
576
|
+
// encoding
|
|
577
|
+
]
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Creates a transaction payload to confirm the chunks of a blob.
|
|
582
|
+
*
|
|
583
|
+
* @param params.deployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
|
|
584
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
585
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
586
|
+
* @param params.signedChunksetChunkCommitments - The signed chunk commitments, signed by their storage provider.
|
|
587
|
+
*
|
|
588
|
+
* @see https://github.com/JumpCrypto/shelby/blob/e009607aad330ccddb08d80bf9addfaadae7972b/move/prototype/move/sources/prototype_interface.move#L343-L349
|
|
589
|
+
*/
|
|
590
|
+
static createConfirmBlobChunksPayload(params) {
|
|
591
|
+
return {
|
|
592
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::prototype_interface::write_complete`,
|
|
593
|
+
functionArguments: [
|
|
594
|
+
createBlobKey({
|
|
595
|
+
account: params.account,
|
|
596
|
+
blobName: params.blobName
|
|
597
|
+
}),
|
|
598
|
+
params.signedChunksetChunkCommitments.map(
|
|
599
|
+
(chunkset) => chunkset.map((chunk) => AccountAddress3.from(chunk.provider))
|
|
600
|
+
),
|
|
601
|
+
params.signedChunksetChunkCommitments.map(
|
|
602
|
+
(chunkset) => chunkset.map((chunk) => MoveVector.U8(chunk.signedCommitment))
|
|
603
|
+
),
|
|
604
|
+
true
|
|
605
|
+
]
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
|
|
611
|
+
function sleep(ms) {
|
|
612
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// ../../packages/sdk/dist/chunk-7KAW6I42.mjs
|
|
616
|
+
import { AccountAddress as AccountAddress4 } from "@aptos-labs/ts-sdk";
|
|
617
|
+
function encodeURIComponentKeepSlashes(str) {
|
|
618
|
+
return encodeURIComponent(str).replace(/%2F/g, "/");
|
|
619
|
+
}
|
|
620
|
+
var ShelbyRPCClient = class {
|
|
621
|
+
baseUrl;
|
|
622
|
+
/**
|
|
623
|
+
* The ShelbyRPCClient is used to interact with the Shelby RPC node. This
|
|
624
|
+
* includes functions like uploading blobs after they have been committed to the
|
|
625
|
+
* blockchain and downloading blobs.
|
|
626
|
+
*
|
|
627
|
+
* @param config.aptos.config - The Aptos config.
|
|
628
|
+
* @param config.shelby.baseUrl - The base URL of the Shelby RPC node.
|
|
629
|
+
*
|
|
630
|
+
* @example
|
|
631
|
+
* ```typescript
|
|
632
|
+
* const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
|
|
633
|
+
* const client = new ShelbyRPCClient({ aptos, shelby: { baseUrl: "https://api.shelby.dev" } });
|
|
634
|
+
* ```
|
|
635
|
+
*/
|
|
636
|
+
constructor(config) {
|
|
637
|
+
this.baseUrl = config.shelby?.baseUrl ?? DEFAULT_SHELBY_BASE_URL;
|
|
638
|
+
}
|
|
639
|
+
async #uploadPart(uploadId, partIdx, partData) {
|
|
640
|
+
const nRetries = 5;
|
|
641
|
+
for (let i = 0; i < nRetries; ++i) {
|
|
642
|
+
const partResponse = await fetch(
|
|
643
|
+
`${this.baseUrl}/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
|
|
295
644
|
{
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
645
|
+
method: "PUT",
|
|
646
|
+
headers: {
|
|
647
|
+
"Content-Type": "application/octet-stream"
|
|
648
|
+
},
|
|
649
|
+
body: partData
|
|
299
650
|
}
|
|
300
|
-
)
|
|
301
|
-
|
|
651
|
+
);
|
|
652
|
+
if (partResponse.ok) return;
|
|
653
|
+
if (i < nRetries - 1) {
|
|
654
|
+
const delay = 2 ** i * 100;
|
|
655
|
+
await sleep(delay);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
throw new Error(`Failed to upload part ${partIdx}.`);
|
|
302
659
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
660
|
+
async #putBlobMultipart(account, blobName, blobData, partSize = 5 * 1024 * 1024) {
|
|
661
|
+
const startResponse = await fetch(`${this.baseUrl}/v1/multipart-uploads`, {
|
|
662
|
+
method: "POST",
|
|
663
|
+
headers: {
|
|
664
|
+
"Content-Type": "application/json"
|
|
665
|
+
},
|
|
666
|
+
body: JSON.stringify({
|
|
667
|
+
rawAccount: account.toString(),
|
|
668
|
+
rawBlobName: blobName,
|
|
669
|
+
rawPartSize: partSize
|
|
670
|
+
})
|
|
671
|
+
});
|
|
672
|
+
if (!startResponse.ok) {
|
|
673
|
+
let errorBodyText = "Could not read error body";
|
|
674
|
+
try {
|
|
675
|
+
errorBodyText = await startResponse.text();
|
|
676
|
+
} catch (_e) {
|
|
677
|
+
}
|
|
678
|
+
throw new Error(
|
|
679
|
+
`Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
const { uploadId } = await startResponse.json();
|
|
683
|
+
const totalParts = Math.ceil(blobData.length / partSize);
|
|
684
|
+
for (let partIdx = 0; partIdx < totalParts; partIdx++) {
|
|
685
|
+
const start = partIdx * partSize;
|
|
686
|
+
const end = Math.min(start + partSize, blobData.length);
|
|
687
|
+
const partData = blobData.slice(start, end);
|
|
688
|
+
await this.#uploadPart(uploadId, partIdx, partData);
|
|
689
|
+
}
|
|
690
|
+
const completeResponse = await fetch(
|
|
691
|
+
`${this.baseUrl}/v1/multipart-uploads/${uploadId}/complete`,
|
|
692
|
+
{
|
|
693
|
+
method: "POST",
|
|
694
|
+
headers: {
|
|
695
|
+
"Content-Type": "application/json"
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
);
|
|
699
|
+
if (!completeResponse.ok) {
|
|
700
|
+
let errorBodyText = "Could not read error body";
|
|
701
|
+
try {
|
|
702
|
+
errorBodyText = await completeResponse.text();
|
|
703
|
+
} catch (_e) {
|
|
704
|
+
}
|
|
705
|
+
throw new Error(
|
|
706
|
+
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Uploads blob data to the Shelby RPC node to be stored and confirmed by storage providers. This should be performed after the blob
|
|
712
|
+
* commitments have been written to the blockchain.
|
|
713
|
+
*
|
|
714
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
715
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
716
|
+
* @param params.blobData - The data to upload.
|
|
717
|
+
*
|
|
718
|
+
* @example
|
|
719
|
+
* ```typescript
|
|
720
|
+
* const blobData = new TextEncoder().encode("Hello, world!");
|
|
721
|
+
*
|
|
722
|
+
* await client.putBlob({ account, blobName: "foo/bar.txt", blobData });
|
|
723
|
+
* ```
|
|
724
|
+
*/
|
|
725
|
+
async putBlob(params) {
|
|
726
|
+
BlobNameSchema.parse(params.blobName);
|
|
727
|
+
await this.#putBlobMultipart(
|
|
728
|
+
params.account,
|
|
729
|
+
params.blobName,
|
|
730
|
+
params.blobData
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
// FIXME make this possible to stream in put ^^^
|
|
734
|
+
/**
|
|
735
|
+
* Downloads a blob from the Shelby RPC node.
|
|
736
|
+
*
|
|
737
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
738
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
739
|
+
* @param params.range - The range of the blob to download.
|
|
740
|
+
*
|
|
741
|
+
* @returns A `ShelbyBlob` object containing the blob data.
|
|
742
|
+
*
|
|
743
|
+
* @example
|
|
744
|
+
* ```typescript
|
|
745
|
+
* const blob = await client.getBlob({
|
|
746
|
+
* account,
|
|
747
|
+
* blobName: "foo/bar.txt",
|
|
748
|
+
* });
|
|
749
|
+
* ```
|
|
750
|
+
*/
|
|
751
|
+
async getBlob(params) {
|
|
752
|
+
BlobNameSchema.parse(params.blobName);
|
|
753
|
+
const url = `${this.baseUrl}/v1/blobs/${params.account.toString()}/${encodeURIComponentKeepSlashes(params.blobName)}`;
|
|
754
|
+
const requestInit = {};
|
|
755
|
+
if (params.range !== void 0) {
|
|
756
|
+
const headers = new Headers();
|
|
757
|
+
const { start, end } = params.range;
|
|
758
|
+
if (end === void 0) {
|
|
759
|
+
headers.set("Range", `bytes=${start}-`);
|
|
760
|
+
} else {
|
|
761
|
+
if (end < start) {
|
|
762
|
+
throw new Error("Range end cannot be less than start.");
|
|
763
|
+
}
|
|
764
|
+
headers.set("Range", `bytes=${start}-${end}`);
|
|
765
|
+
}
|
|
766
|
+
requestInit.headers = headers;
|
|
767
|
+
}
|
|
768
|
+
const response = await fetch(url, requestInit);
|
|
769
|
+
if (!response.ok) {
|
|
770
|
+
throw new Error(
|
|
771
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
if (!response.body) {
|
|
775
|
+
throw new Error("Response body is null");
|
|
776
|
+
}
|
|
777
|
+
const contentLengthHeader = response.headers.get("content-length");
|
|
778
|
+
if (contentLengthHeader === null) {
|
|
779
|
+
throw new Error(
|
|
780
|
+
"Response did not have content-length header, which is required"
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
|
|
784
|
+
if (Number.isNaN(expectedContentLength)) {
|
|
785
|
+
throw new Error(
|
|
786
|
+
`Invalid content-length header received: ${contentLengthHeader}`
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
const validatingStream = new ReadableStream({
|
|
790
|
+
start(controller) {
|
|
791
|
+
const maybeReader = response.body?.getReader();
|
|
792
|
+
if (!maybeReader) {
|
|
793
|
+
controller.error(new Error("Response body reader is unavailable"));
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
const reader = maybeReader;
|
|
797
|
+
let bytesReceived = 0;
|
|
798
|
+
function pump() {
|
|
799
|
+
return reader.read().then(({ done, value }) => {
|
|
800
|
+
if (done) {
|
|
801
|
+
if (bytesReceived !== expectedContentLength) {
|
|
802
|
+
controller.error(
|
|
803
|
+
new Error(
|
|
804
|
+
`Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
|
|
805
|
+
)
|
|
806
|
+
);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
controller.close();
|
|
810
|
+
return;
|
|
319
811
|
}
|
|
320
|
-
|
|
812
|
+
bytesReceived += value.byteLength;
|
|
813
|
+
controller.enqueue(value);
|
|
814
|
+
return pump();
|
|
815
|
+
}).catch((error) => {
|
|
816
|
+
controller.error(error);
|
|
817
|
+
});
|
|
321
818
|
}
|
|
322
|
-
|
|
323
|
-
|
|
819
|
+
return pump();
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
return {
|
|
823
|
+
account: AccountAddress4.from(params.account),
|
|
824
|
+
name: params.blobName,
|
|
825
|
+
readable: validatingStream,
|
|
826
|
+
contentLength: expectedContentLength
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
// ../../packages/sdk/dist/chunk-WHZVCCJD.mjs
|
|
832
|
+
import {
|
|
833
|
+
Aptos as Aptos2
|
|
834
|
+
} from "@aptos-labs/ts-sdk";
|
|
835
|
+
var ShelbyClient = class {
|
|
836
|
+
/**
|
|
837
|
+
* The coordination client is used to interact with the Aptos blockchain which handles the commitments
|
|
838
|
+
* and metadata for blobs.
|
|
839
|
+
*/
|
|
840
|
+
coordination;
|
|
841
|
+
/**
|
|
842
|
+
* The RPC client is used to interact with the Shelby RPC node which can be responsible for storing,
|
|
843
|
+
* confirming, and retrieving blobs from the storage layer.
|
|
844
|
+
*/
|
|
845
|
+
rpc;
|
|
846
|
+
/**
|
|
847
|
+
* The configuration for the Shelby client.
|
|
848
|
+
*/
|
|
849
|
+
config;
|
|
850
|
+
/**
|
|
851
|
+
* The Aptos client.
|
|
852
|
+
*/
|
|
853
|
+
aptos;
|
|
854
|
+
/**
|
|
855
|
+
* The base class for Shelby clients
|
|
856
|
+
*
|
|
857
|
+
* @param config.aptos.config - The Aptos config.
|
|
858
|
+
* @param config.shelby.baseUrl - The base URL of the Shelby RPC node. If not provided, the default base URL will be used.
|
|
859
|
+
*/
|
|
860
|
+
constructor(config) {
|
|
861
|
+
this.config = config;
|
|
862
|
+
this.aptos = new Aptos2(this.config.aptos.config);
|
|
863
|
+
this.coordination = new ShelbyBlobClient(config);
|
|
864
|
+
this.rpc = new ShelbyRPCClient(config);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* The base URL for the Shelby RPC node.
|
|
868
|
+
*/
|
|
869
|
+
get baseUrl() {
|
|
870
|
+
return this.config.shelby?.baseUrl ?? DEFAULT_SHELBY_BASE_URL;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Uploads a blob to the Shelby network.
|
|
874
|
+
*
|
|
875
|
+
* @param params.blobData - The data to upload.
|
|
876
|
+
* @param params.signer - The signer of the transaction.
|
|
877
|
+
* @param params.blobName - The name of the blob.
|
|
878
|
+
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
879
|
+
* @param params.options - The options for the upload.
|
|
880
|
+
*
|
|
881
|
+
* @returns The transaction and generated blob commitments.
|
|
882
|
+
*/
|
|
883
|
+
async upload(params) {
|
|
884
|
+
await generateCommitments(
|
|
885
|
+
params.blobData,
|
|
886
|
+
void 0,
|
|
887
|
+
params.options?.encoding
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Downloads a blob from the Shelby RPC node.
|
|
892
|
+
*
|
|
893
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
894
|
+
* @param params.blobName - The name of the blob (e.g. "foo/bar")
|
|
895
|
+
* @param params.range - The range of the blob to download.
|
|
896
|
+
*
|
|
897
|
+
* @returns A `ShelbyBlob` object containing the blob data.
|
|
898
|
+
*
|
|
899
|
+
* @example
|
|
900
|
+
* ```typescript
|
|
901
|
+
* const blob = await client.download({
|
|
902
|
+
* account,
|
|
903
|
+
* blobName: "foo/bar.txt",
|
|
904
|
+
* });
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
907
|
+
async download(params) {
|
|
908
|
+
return await this.rpc.getBlob(params);
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
// ../../packages/sdk/dist/chunk-YVPHW2RN.mjs
|
|
913
|
+
var ShelbyNodeClient = class extends ShelbyClient {
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
// ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
|
|
917
|
+
var __defProp = Object.defineProperty;
|
|
918
|
+
var __export = (target, all) => {
|
|
919
|
+
for (var name in all)
|
|
920
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
// ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
|
|
924
|
+
var testUtil_exports = {};
|
|
925
|
+
__export(testUtil_exports, {
|
|
926
|
+
makeChunk: () => makeChunk
|
|
927
|
+
});
|
|
928
|
+
function makeChunk(n) {
|
|
929
|
+
const c = Buffer.alloc(n);
|
|
930
|
+
for (let i = 0; i < n; ++i) {
|
|
931
|
+
c[i] = i % 256;
|
|
932
|
+
}
|
|
933
|
+
return c;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// src/commands/account.tsx
|
|
937
|
+
import Table from "cli-table3";
|
|
938
|
+
import { render } from "ink";
|
|
939
|
+
import { z as z6 } from "zod";
|
|
940
|
+
|
|
941
|
+
// src/components/AccountWizard.tsx
|
|
942
|
+
import { Box, Text } from "ink";
|
|
943
|
+
import TextInput from "ink-text-input";
|
|
944
|
+
import { useEffect, useState } from "react";
|
|
945
|
+
|
|
946
|
+
// src/utils/keys.ts
|
|
947
|
+
import {
|
|
948
|
+
Account,
|
|
949
|
+
AccountAddress as AccountAddress5,
|
|
950
|
+
Ed25519PrivateKey,
|
|
951
|
+
Secp256k1PrivateKey,
|
|
952
|
+
SigningSchemeInput
|
|
953
|
+
} from "@aptos-labs/ts-sdk";
|
|
954
|
+
function generateEd25519Account() {
|
|
955
|
+
const account = Account.generate({
|
|
956
|
+
scheme: SigningSchemeInput.Ed25519,
|
|
957
|
+
legacy: true
|
|
958
|
+
});
|
|
959
|
+
return account;
|
|
960
|
+
}
|
|
961
|
+
function isValidEd25519PrivateKey(value) {
|
|
962
|
+
try {
|
|
963
|
+
new Ed25519PrivateKey(value);
|
|
964
|
+
return true;
|
|
965
|
+
} catch {
|
|
966
|
+
return false;
|
|
324
967
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
968
|
+
}
|
|
969
|
+
function isValidAddress(address) {
|
|
970
|
+
return AccountAddress5.isValid({ input: address }).valid;
|
|
971
|
+
}
|
|
972
|
+
var SECP256K1_NAME = "secp256k1";
|
|
973
|
+
var ED25519_NAME = "ed25519";
|
|
974
|
+
function isValidScheme(scheme) {
|
|
975
|
+
return SECP256K1_NAME === scheme || ED25519_NAME === scheme;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// src/components/AccountWizard.tsx
|
|
979
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
980
|
+
var AccountWizard = ({ onComplete }) => {
|
|
981
|
+
const [step, setStep] = useState("name");
|
|
982
|
+
const [name, setName] = useState("");
|
|
983
|
+
const [address, setAddress] = useState("");
|
|
984
|
+
const [privateKey, setPrivateKey] = useState("");
|
|
985
|
+
useEffect(() => {
|
|
986
|
+
if (step === "done") {
|
|
987
|
+
onComplete({
|
|
988
|
+
name,
|
|
989
|
+
address: address || void 0,
|
|
990
|
+
privateKey
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
}, [onComplete, step, name, address, privateKey]);
|
|
994
|
+
if (step === "name") {
|
|
995
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
996
|
+
/* @__PURE__ */ jsx(Text, { children: "Account name?" }),
|
|
997
|
+
/* @__PURE__ */ jsx(
|
|
998
|
+
TextInput,
|
|
331
999
|
{
|
|
332
|
-
value:
|
|
333
|
-
onChange:
|
|
334
|
-
onSubmit: () => setStep("
|
|
1000
|
+
value: name,
|
|
1001
|
+
onChange: setName,
|
|
1002
|
+
onSubmit: () => setStep("address")
|
|
335
1003
|
}
|
|
336
1004
|
)
|
|
337
1005
|
] });
|
|
338
1006
|
}
|
|
339
|
-
if (step === "
|
|
340
|
-
return /* @__PURE__ */
|
|
341
|
-
/* @__PURE__ */
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
] }),
|
|
345
|
-
/* @__PURE__ */ jsx2(Text2, { children: "Signature scheme? (ed25519)" }),
|
|
346
|
-
/* @__PURE__ */ jsx2(
|
|
347
|
-
SelectInput,
|
|
1007
|
+
if (step === "address") {
|
|
1008
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1009
|
+
/* @__PURE__ */ jsx(Text, { children: "Address (optional)?" }),
|
|
1010
|
+
/* @__PURE__ */ jsx(
|
|
1011
|
+
TextInput,
|
|
348
1012
|
{
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
],
|
|
353
|
-
onSelect: (item) => {
|
|
354
|
-
setSignatureScheme(item.value);
|
|
355
|
-
setStep("privateKey");
|
|
356
|
-
}
|
|
1013
|
+
value: address,
|
|
1014
|
+
onChange: setAddress,
|
|
1015
|
+
onSubmit: () => setStep("key")
|
|
357
1016
|
}
|
|
358
1017
|
)
|
|
359
1018
|
] });
|
|
360
1019
|
}
|
|
361
|
-
if (step === "
|
|
362
|
-
return /* @__PURE__ */
|
|
363
|
-
/* @__PURE__ */
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
] }),
|
|
367
|
-
/* @__PURE__ */ jsx2(Text2, { children: "Private key? (leave blank to generate new key)" }),
|
|
368
|
-
/* @__PURE__ */ jsx2(
|
|
369
|
-
TextInput2,
|
|
1020
|
+
if (step === "key") {
|
|
1021
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
1022
|
+
/* @__PURE__ */ jsx(Text, { children: "Paste private key or leave blank to generate" }),
|
|
1023
|
+
/* @__PURE__ */ jsx(
|
|
1024
|
+
TextInput,
|
|
370
1025
|
{
|
|
371
1026
|
value: privateKey,
|
|
372
1027
|
onChange: setPrivateKey,
|
|
373
1028
|
onSubmit: () => {
|
|
374
1029
|
if (!privateKey) {
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
1030
|
+
const acct = generateEd25519Account();
|
|
1031
|
+
setPrivateKey(acct.privateKey.toAIP80String());
|
|
1032
|
+
setAddress((prev) => prev || acct.accountAddress.toString());
|
|
378
1033
|
}
|
|
379
|
-
setStep("
|
|
1034
|
+
setStep("done");
|
|
380
1035
|
}
|
|
381
1036
|
}
|
|
382
1037
|
)
|
|
383
1038
|
] });
|
|
384
1039
|
}
|
|
385
|
-
return
|
|
1040
|
+
return null;
|
|
386
1041
|
};
|
|
387
1042
|
|
|
388
1043
|
// src/components/ContextWizard.tsx
|
|
389
|
-
import { Box as
|
|
390
|
-
import
|
|
391
|
-
import { useEffect as
|
|
392
|
-
import { jsx as
|
|
1044
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
1045
|
+
import TextInput2 from "ink-text-input";
|
|
1046
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1047
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
393
1048
|
var ContextWizard = ({ onComplete }) => {
|
|
394
|
-
const [step, setStep] =
|
|
395
|
-
const [
|
|
396
|
-
const [shelbyRpcEndpoint, setShelbyRpcEndpoint] =
|
|
397
|
-
const [aptosNetwork, setAptosNetwork] =
|
|
398
|
-
|
|
1049
|
+
const [step, setStep] = useState2("name");
|
|
1050
|
+
const [name, setName] = useState2("");
|
|
1051
|
+
const [shelbyRpcEndpoint, setShelbyRpcEndpoint] = useState2("");
|
|
1052
|
+
const [aptosNetwork, setAptosNetwork] = useState2("");
|
|
1053
|
+
useEffect2(() => {
|
|
399
1054
|
if (step === "done") {
|
|
400
|
-
onComplete({ name
|
|
1055
|
+
onComplete({ name, shelbyRpcEndpoint, aptosNetwork });
|
|
401
1056
|
}
|
|
402
|
-
}, [step,
|
|
1057
|
+
}, [step, name, shelbyRpcEndpoint, aptosNetwork, onComplete]);
|
|
403
1058
|
if (step === "name") {
|
|
404
|
-
return /* @__PURE__ */
|
|
405
|
-
/* @__PURE__ */
|
|
406
|
-
/* @__PURE__ */
|
|
407
|
-
|
|
1059
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
1060
|
+
/* @__PURE__ */ jsx2(Text2, { children: "Context name?" }),
|
|
1061
|
+
/* @__PURE__ */ jsx2(
|
|
1062
|
+
TextInput2,
|
|
408
1063
|
{
|
|
409
|
-
value:
|
|
1064
|
+
value: name,
|
|
410
1065
|
onChange: setName,
|
|
411
1066
|
onSubmit: () => setStep("shelbyRpc")
|
|
412
1067
|
}
|
|
@@ -414,377 +1069,101 @@ var ContextWizard = ({ onComplete }) => {
|
|
|
414
1069
|
] });
|
|
415
1070
|
}
|
|
416
1071
|
if (step === "shelbyRpc") {
|
|
417
|
-
return /* @__PURE__ */
|
|
418
|
-
/* @__PURE__ */
|
|
419
|
-
/* @__PURE__ */
|
|
420
|
-
|
|
421
|
-
{
|
|
422
|
-
value: shelbyRpcEndpoint,
|
|
423
|
-
placeholder: "https://shelby.rpc.devnet.example.com",
|
|
424
|
-
onChange: setShelbyRpcEndpoint,
|
|
425
|
-
onSubmit: () => setStep("aptosApi")
|
|
426
|
-
}
|
|
427
|
-
)
|
|
428
|
-
] });
|
|
429
|
-
}
|
|
430
|
-
if (step === "aptosApi") {
|
|
431
|
-
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
432
|
-
/* @__PURE__ */ jsx3(Text3, { children: "Aptos API endpoint?" }),
|
|
433
|
-
/* @__PURE__ */ jsx3(
|
|
434
|
-
TextInput3,
|
|
435
|
-
{
|
|
436
|
-
value: aptosNetwork,
|
|
437
|
-
placeholder: "devnet",
|
|
438
|
-
onChange: setAptosNetwork,
|
|
439
|
-
onSubmit: () => setStep("done")
|
|
440
|
-
}
|
|
441
|
-
)
|
|
442
|
-
] });
|
|
443
|
-
}
|
|
444
|
-
return null;
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
// src/components/UpdateContextWizard.tsx
|
|
448
|
-
import { Box as Box4, Text as Text4 } from "ink";
|
|
449
|
-
import TextInput4 from "ink-text-input";
|
|
450
|
-
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
451
|
-
|
|
452
|
-
// src/schemas/AptosNetworkSchema.ts
|
|
453
|
-
import { z } from "zod";
|
|
454
|
-
var AptosNetworkSchema = z.enum([
|
|
455
|
-
"mainnet",
|
|
456
|
-
"testnet",
|
|
457
|
-
"devnet",
|
|
458
|
-
"local"
|
|
459
|
-
]);
|
|
460
|
-
|
|
461
|
-
// src/schemas/EndpointSchema.ts
|
|
462
|
-
import { z as z2 } from "zod";
|
|
463
|
-
var EndpointSchema = z2.string().url("Must be a valid URL");
|
|
464
|
-
|
|
465
|
-
// src/components/UpdateContextWizard.tsx
|
|
466
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
467
|
-
var UpdateContextWizard = ({
|
|
468
|
-
contextName,
|
|
469
|
-
currentShelbyRpc,
|
|
470
|
-
currentAptosNetwork,
|
|
471
|
-
onComplete
|
|
472
|
-
}) => {
|
|
473
|
-
const [step, setStep] = useState4("shelbyRpc");
|
|
474
|
-
const [shelbyRpcEndpoint, setShelbyRpcEndpoint] = useState4(currentShelbyRpc);
|
|
475
|
-
const [aptosNetwork, setAptosNetwork] = useState4(currentAptosNetwork);
|
|
476
|
-
const [error, setError] = useState4("");
|
|
477
|
-
useEffect4(() => {
|
|
478
|
-
if (step === "done") {
|
|
479
|
-
const updates = {};
|
|
480
|
-
if (shelbyRpcEndpoint !== currentShelbyRpc) {
|
|
481
|
-
updates.shelbyRpcEndpoint = shelbyRpcEndpoint;
|
|
482
|
-
}
|
|
483
|
-
if (aptosNetwork !== currentAptosNetwork) {
|
|
484
|
-
updates.aptosNetwork = aptosNetwork;
|
|
485
|
-
}
|
|
486
|
-
onComplete(updates);
|
|
487
|
-
}
|
|
488
|
-
}, [
|
|
489
|
-
step,
|
|
490
|
-
shelbyRpcEndpoint,
|
|
491
|
-
aptosNetwork,
|
|
492
|
-
currentShelbyRpc,
|
|
493
|
-
currentAptosNetwork,
|
|
494
|
-
onComplete
|
|
495
|
-
]);
|
|
496
|
-
if (step === "shelbyRpc") {
|
|
497
|
-
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
498
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
499
|
-
"Updating context: ",
|
|
500
|
-
contextName
|
|
501
|
-
] }),
|
|
502
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
503
|
-
"Shelby RPC endpoint? (current: ",
|
|
504
|
-
currentShelbyRpc,
|
|
505
|
-
")"
|
|
506
|
-
] }),
|
|
507
|
-
error && /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
508
|
-
"Error: ",
|
|
509
|
-
error
|
|
510
|
-
] }),
|
|
511
|
-
/* @__PURE__ */ jsx4(
|
|
512
|
-
TextInput4,
|
|
1072
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
1073
|
+
/* @__PURE__ */ jsx2(Text2, { children: "Shelby RPC endpoint?" }),
|
|
1074
|
+
/* @__PURE__ */ jsx2(
|
|
1075
|
+
TextInput2,
|
|
513
1076
|
{
|
|
514
|
-
value: shelbyRpcEndpoint,
|
|
515
|
-
placeholder:
|
|
516
|
-
onChange:
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
setError("");
|
|
529
|
-
setStep("aptosApi");
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
),
|
|
533
|
-
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Press Enter to continue" })
|
|
534
|
-
] });
|
|
535
|
-
}
|
|
536
|
-
if (step === "aptosApi") {
|
|
537
|
-
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
538
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
539
|
-
"Aptos network? (current: ",
|
|
540
|
-
currentAptosNetwork,
|
|
541
|
-
")"
|
|
542
|
-
] }),
|
|
543
|
-
error && /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
544
|
-
"Error: ",
|
|
545
|
-
error
|
|
546
|
-
] }),
|
|
547
|
-
/* @__PURE__ */ jsx4(
|
|
548
|
-
TextInput4,
|
|
1077
|
+
value: shelbyRpcEndpoint,
|
|
1078
|
+
placeholder: "https://shelby.rpc.devnet.example.com",
|
|
1079
|
+
onChange: setShelbyRpcEndpoint,
|
|
1080
|
+
onSubmit: () => setStep("aptosApi")
|
|
1081
|
+
}
|
|
1082
|
+
)
|
|
1083
|
+
] });
|
|
1084
|
+
}
|
|
1085
|
+
if (step === "aptosApi") {
|
|
1086
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
1087
|
+
/* @__PURE__ */ jsx2(Text2, { children: "Aptos API endpoint?" }),
|
|
1088
|
+
/* @__PURE__ */ jsx2(
|
|
1089
|
+
TextInput2,
|
|
549
1090
|
{
|
|
550
1091
|
value: aptosNetwork,
|
|
551
|
-
placeholder:
|
|
552
|
-
onChange:
|
|
553
|
-
|
|
554
|
-
setError("");
|
|
555
|
-
},
|
|
556
|
-
onSubmit: () => {
|
|
557
|
-
if (aptosNetwork && aptosNetwork !== currentAptosNetwork) {
|
|
558
|
-
const result = AptosNetworkSchema.safeParse(aptosNetwork);
|
|
559
|
-
if (!result.success) {
|
|
560
|
-
setError("Must be one of: mainnet, testnet, devnet, local");
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
setError("");
|
|
565
|
-
setStep("done");
|
|
566
|
-
}
|
|
1092
|
+
placeholder: "devnet",
|
|
1093
|
+
onChange: setAptosNetwork,
|
|
1094
|
+
onSubmit: () => setStep("done")
|
|
567
1095
|
}
|
|
568
|
-
)
|
|
569
|
-
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Valid options: mainnet, testnet, devnet, local" }),
|
|
570
|
-
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Press Enter to save changes" })
|
|
1096
|
+
)
|
|
571
1097
|
] });
|
|
572
1098
|
}
|
|
573
1099
|
return null;
|
|
574
1100
|
};
|
|
575
1101
|
|
|
576
|
-
// src/
|
|
577
|
-
import
|
|
578
|
-
import
|
|
579
|
-
import
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
Ed25519PrivateKey as Ed25519PrivateKey2,
|
|
583
|
-
NetworkToNetworkName
|
|
584
|
-
} from "@aptos-labs/ts-sdk";
|
|
585
|
-
import fs from "fs-extra";
|
|
586
|
-
import YAML from "yaml";
|
|
587
|
-
import { z as z3 } from "zod";
|
|
588
|
-
|
|
589
|
-
// tests/utils/mockConfig.ts
|
|
590
|
-
var mockAccountAlice = generateEd25519Account();
|
|
591
|
-
var mockAccountBob = generateEd25519Account();
|
|
592
|
-
var mockConfig = {
|
|
593
|
-
contexts: {
|
|
594
|
-
devnet: {
|
|
595
|
-
aptos_network: "devnet",
|
|
596
|
-
shelby_rpc_endpoint: "https://shelby.rpc.devnet.example.com"
|
|
597
|
-
},
|
|
598
|
-
testnet: {
|
|
599
|
-
aptos_network: "testnet",
|
|
600
|
-
shelby_rpc_endpoint: "https://shelby.rpc.testnet.example.com"
|
|
601
|
-
},
|
|
602
|
-
mainnet: {
|
|
603
|
-
aptos_network: "mainnet",
|
|
604
|
-
shelby_rpc_endpoint: "https://shelby.rpc.mainnet.example.com"
|
|
605
|
-
}
|
|
606
|
-
},
|
|
607
|
-
accounts: {
|
|
608
|
-
alice: {
|
|
609
|
-
address: mockAccountAlice.accountAddress.toString(),
|
|
610
|
-
private_key: mockAccountAlice.privateKey.toAIP80String()
|
|
611
|
-
},
|
|
612
|
-
bob: {
|
|
613
|
-
private_key: mockAccountBob.privateKey.toAIP80String(),
|
|
614
|
-
address: mockAccountBob.accountAddress.toString()
|
|
615
|
-
}
|
|
616
|
-
},
|
|
617
|
-
default_context: "devnet",
|
|
618
|
-
default_account: "alice"
|
|
619
|
-
};
|
|
620
|
-
|
|
621
|
-
// src/utils/constants.ts
|
|
622
|
-
var DEFAULT_CONFIG_PATH = "~/.shelby/config.yaml";
|
|
1102
|
+
// src/components/InitWizard.tsx
|
|
1103
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
1104
|
+
import SelectInput from "ink-select-input";
|
|
1105
|
+
import Spinner from "ink-spinner";
|
|
1106
|
+
import TextInput3 from "ink-text-input";
|
|
1107
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
623
1108
|
|
|
624
|
-
// src/utils/
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
var ConfigSchema = z3.object({
|
|
630
|
-
contexts: z3.record(ContextSchema),
|
|
631
|
-
accounts: z3.record(
|
|
632
|
-
z3.object({
|
|
633
|
-
address: z3.string().optional(),
|
|
634
|
-
private_key: z3.string({ message: "private_key must be provided" })
|
|
635
|
-
})
|
|
636
|
-
),
|
|
637
|
-
default_context: z3.string(),
|
|
638
|
-
default_account: z3.string()
|
|
639
|
-
});
|
|
640
|
-
function resolveConfigPath(configPath) {
|
|
641
|
-
if (configPath.startsWith("~")) {
|
|
642
|
-
return path.join(os.homedir(), configPath.slice(1));
|
|
643
|
-
}
|
|
644
|
-
return configPath;
|
|
645
|
-
}
|
|
646
|
-
function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
647
|
-
const resolvedPath = resolveConfigPath(configPath);
|
|
648
|
-
const dir = path.dirname(resolvedPath);
|
|
649
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
650
|
-
fs.mkdirpSync(dir);
|
|
651
|
-
const yamlText = YAML.stringify(mockConfig);
|
|
652
|
-
fs.writeFileSync(resolvedPath, yamlText, "utf8");
|
|
653
|
-
return mockConfig;
|
|
654
|
-
}
|
|
655
|
-
const raw = fs.readFileSync(resolvedPath, "utf8");
|
|
656
|
-
let parsed;
|
|
657
|
-
try {
|
|
658
|
-
parsed = YAML.parse(raw);
|
|
659
|
-
} catch {
|
|
660
|
-
throw new Error("Invalid config file");
|
|
661
|
-
}
|
|
1109
|
+
// src/utils/version.ts
|
|
1110
|
+
import { execSync } from "child_process";
|
|
1111
|
+
import semver from "semver";
|
|
1112
|
+
var MIN_APTOS_CLI_VERSION = "7.6.0";
|
|
1113
|
+
function getAptosCliVersion() {
|
|
662
1114
|
try {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
function saveConfig(config, configPath = "~/.shelby/config.yaml") {
|
|
669
|
-
const resolvedPath = resolveConfigPath(configPath);
|
|
670
|
-
fs.mkdirpSync(path.dirname(resolvedPath));
|
|
671
|
-
ConfigSchema.parse(config);
|
|
672
|
-
fs.writeFileSync(resolvedPath, YAML.stringify(config), "utf8");
|
|
673
|
-
}
|
|
674
|
-
function getCurrentAccount(config, accountName) {
|
|
675
|
-
const name2 = accountName || config.default_account;
|
|
676
|
-
if (!name2) {
|
|
677
|
-
throw new Error(`Account with name '${name2}' not found in config`);
|
|
678
|
-
}
|
|
679
|
-
const account = config.accounts[name2];
|
|
680
|
-
if (!account) {
|
|
681
|
-
throw new Error(`Account '${name2}' not found in config`);
|
|
682
|
-
}
|
|
683
|
-
let privateKey;
|
|
684
|
-
if (account.private_key) {
|
|
685
|
-
privateKey = account.private_key;
|
|
686
|
-
} else {
|
|
687
|
-
throw new Error(`No private key found for account '${name2}'`);
|
|
688
|
-
}
|
|
689
|
-
return {
|
|
690
|
-
address: account.address,
|
|
691
|
-
privateKey,
|
|
692
|
-
account: new Ed25519Account({
|
|
693
|
-
privateKey: new Ed25519PrivateKey2(privateKey)
|
|
694
|
-
})
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
function getCurrentShelbyConfig(config, opts = {
|
|
698
|
-
context: config.default_context
|
|
699
|
-
}) {
|
|
700
|
-
const { context } = opts;
|
|
701
|
-
const selectedContext = config.contexts[context ?? config.default_context];
|
|
702
|
-
if (!selectedContext) {
|
|
703
|
-
throw new Error(
|
|
704
|
-
`Context '${context ?? config.default_context}' not found in config`
|
|
1115
|
+
const aptosVersionOutput = execSync("aptos --version").toString().trim();
|
|
1116
|
+
const versionMatch = aptosVersionOutput.match(
|
|
1117
|
+
/aptos (\d+\.\d+\.\d+(?:-[\w.-]+)?)/
|
|
705
1118
|
);
|
|
1119
|
+
return versionMatch ? versionMatch[1] : null;
|
|
1120
|
+
} catch (_error) {
|
|
1121
|
+
return null;
|
|
706
1122
|
}
|
|
707
|
-
const aptosNetwork = NetworkToNetworkName[selectedContext.aptos_network];
|
|
708
|
-
if (!aptosNetwork) {
|
|
709
|
-
throw new Error(`Invalid Aptos network: ${selectedContext.aptos_network}`);
|
|
710
|
-
}
|
|
711
|
-
return {
|
|
712
|
-
aptos: { config: new AptosConfig({ network: aptosNetwork }) },
|
|
713
|
-
shelby: { baseUrl: selectedContext.shelby_rpc_endpoint }
|
|
714
|
-
};
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// src/utils/paths.ts
|
|
718
|
-
import path2 from "path";
|
|
719
|
-
function normBlobName(pathModule, inputDirectoryName, filename, blobPrefix) {
|
|
720
|
-
const blobNameWithoutInputDir = pathModule.relative(
|
|
721
|
-
inputDirectoryName,
|
|
722
|
-
filename
|
|
723
|
-
);
|
|
724
|
-
const blobNameWithPrefix = pathModule.join(
|
|
725
|
-
blobPrefix,
|
|
726
|
-
blobNameWithoutInputDir
|
|
727
|
-
);
|
|
728
|
-
const blobNameNormalized = pathModule.normalize(blobNameWithPrefix);
|
|
729
|
-
const parts = blobNameNormalized.split(pathModule.sep);
|
|
730
|
-
return path2.posix.join(...parts);
|
|
731
1123
|
}
|
|
732
|
-
function
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
}
|
|
736
|
-
if (!blobName.startsWith(blobPrefix)) {
|
|
737
|
-
throw new Error(
|
|
738
|
-
`Blob name '${blobName}' does not start with prefix '${blobPrefix}'`
|
|
739
|
-
);
|
|
740
|
-
}
|
|
741
|
-
const relativePath = blobName.slice(blobPrefix.length);
|
|
742
|
-
const pathParts = relativePath.split("/").filter((part) => part.length > 0);
|
|
743
|
-
if (pathParts.length === 0) {
|
|
744
|
-
return outputPrefix;
|
|
745
|
-
}
|
|
746
|
-
return pathModule.join(outputPrefix, ...pathParts);
|
|
1124
|
+
function getAptosCliVersionInfo(minVersion = MIN_APTOS_CLI_VERSION) {
|
|
1125
|
+
const version2 = getAptosCliVersion();
|
|
1126
|
+
const meetsRequirement = version2 ? semver.gte(version2, minVersion) : false;
|
|
1127
|
+
return { version: version2, meetsRequirement };
|
|
747
1128
|
}
|
|
748
1129
|
|
|
749
|
-
// src/
|
|
750
|
-
import { jsx as
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
)
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
"
|
|
760
|
-
|
|
761
|
-
)
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
)
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
)
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
}
|
|
787
|
-
if (options.setupDefaultContexts) {
|
|
1130
|
+
// src/components/InitWizard.tsx
|
|
1131
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1132
|
+
var InitWizard = ({ onComplete }) => {
|
|
1133
|
+
const [step, setStep] = useState3("checkAptos");
|
|
1134
|
+
const [aptosCliMeetsRequirement, setAptosCliMeetsRequirement] = useState3(false);
|
|
1135
|
+
const [aptosCliVersion, setAptosCliVersion] = useState3(null);
|
|
1136
|
+
const [setupStandardContexts, setSetupStandardContexts] = useState3(false);
|
|
1137
|
+
const [setupCustomContext, setSetupCustomContext] = useState3(false);
|
|
1138
|
+
const [customContextName, setCustomContextName] = useState3("staging");
|
|
1139
|
+
const [shelbyRpcEndpoint, setShelbyRpcEndpoint] = useState3(
|
|
1140
|
+
"https://shelby.rpc.staging.example.com"
|
|
1141
|
+
);
|
|
1142
|
+
const [aptosNetwork, setAptosNetwork] = useState3("mainnet");
|
|
1143
|
+
const [setupAccount, setSetupAccount] = useState3(false);
|
|
1144
|
+
const [accountName, setAccountName] = useState3("alice");
|
|
1145
|
+
const [signatureScheme, setSignatureScheme] = useState3("ed25519");
|
|
1146
|
+
const [privateKey, setPrivateKey] = useState3("");
|
|
1147
|
+
const [address, _setAddress] = useState3("");
|
|
1148
|
+
const [generatedKey, setGeneratedKey] = useState3("");
|
|
1149
|
+
const [generatedAddress, setGeneratedAddress] = useState3("");
|
|
1150
|
+
useEffect3(() => {
|
|
1151
|
+
if (step === "checkAptos") {
|
|
1152
|
+
const { version: version2, meetsRequirement } = getAptosCliVersionInfo();
|
|
1153
|
+
setAptosCliVersion(version2);
|
|
1154
|
+
setAptosCliMeetsRequirement(meetsRequirement);
|
|
1155
|
+
setStep("standardContexts");
|
|
1156
|
+
}
|
|
1157
|
+
}, [step]);
|
|
1158
|
+
useEffect3(() => {
|
|
1159
|
+
if (step === "complete") {
|
|
1160
|
+
const config = {
|
|
1161
|
+
contexts: {},
|
|
1162
|
+
accounts: {},
|
|
1163
|
+
default_context: setupStandardContexts ? "devnet" : customContextName,
|
|
1164
|
+
default_account: setupAccount ? accountName : "default_account"
|
|
1165
|
+
};
|
|
1166
|
+
if (setupStandardContexts) {
|
|
788
1167
|
config.contexts.local = {
|
|
789
1168
|
aptos_network: "local",
|
|
790
1169
|
shelby_rpc_endpoint: "http://localhost:9090"
|
|
@@ -802,712 +1181,535 @@ function initCommand(program) {
|
|
|
802
1181
|
shelby_rpc_endpoint: "https://shelby.rpc.mainnet.example.com"
|
|
803
1182
|
};
|
|
804
1183
|
}
|
|
805
|
-
if (
|
|
806
|
-
config.contexts[
|
|
807
|
-
aptos_network:
|
|
808
|
-
shelby_rpc_endpoint:
|
|
1184
|
+
if (setupCustomContext) {
|
|
1185
|
+
config.contexts[customContextName] = {
|
|
1186
|
+
aptos_network: aptosNetwork,
|
|
1187
|
+
shelby_rpc_endpoint: shelbyRpcEndpoint
|
|
809
1188
|
};
|
|
810
1189
|
}
|
|
811
|
-
if (
|
|
812
|
-
|
|
813
|
-
|
|
1190
|
+
if (setupAccount) {
|
|
1191
|
+
const finalPrivateKey = privateKey || generatedKey;
|
|
1192
|
+
const finalAddress = address || generatedAddress;
|
|
1193
|
+
config.accounts[accountName] = {
|
|
1194
|
+
private_key: finalPrivateKey,
|
|
1195
|
+
address: finalAddress
|
|
814
1196
|
};
|
|
815
1197
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1198
|
+
onComplete(config);
|
|
1199
|
+
}
|
|
1200
|
+
}, [step]);
|
|
1201
|
+
if (step === "checkAptos") {
|
|
1202
|
+
return /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1203
|
+
/* @__PURE__ */ jsx3(Spinner, { type: "dots" }),
|
|
1204
|
+
" Checking for Aptos CLI >=v",
|
|
1205
|
+
MIN_APTOS_CLI_VERSION,
|
|
1206
|
+
"..."
|
|
1207
|
+
] }) });
|
|
1208
|
+
}
|
|
1209
|
+
if (step === "standardContexts") {
|
|
1210
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1211
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1212
|
+
"\u2714 Checking for Aptos CLI >=v",
|
|
1213
|
+
MIN_APTOS_CLI_VERSION,
|
|
1214
|
+
"...",
|
|
1215
|
+
" ",
|
|
1216
|
+
aptosCliMeetsRequirement ? "found" : "not found"
|
|
1217
|
+
] }),
|
|
1218
|
+
!aptosCliMeetsRequirement && aptosCliVersion && /* @__PURE__ */ jsxs3(Text3, { color: "yellow", children: [
|
|
1219
|
+
"Warning: Found Aptos CLI v",
|
|
1220
|
+
aptosCliVersion,
|
|
1221
|
+
", but v",
|
|
1222
|
+
MIN_APTOS_CLI_VERSION,
|
|
1223
|
+
" or higher is required. Please update."
|
|
1224
|
+
] }),
|
|
1225
|
+
!aptosCliMeetsRequirement && !aptosCliVersion && /* @__PURE__ */ jsx3(Text3, { color: "yellow", children: "Warning: Aptos CLI not found. Please install." }),
|
|
1226
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Do you want to set up standard contexts (devnet, testnet, mainnet)?" }),
|
|
1227
|
+
/* @__PURE__ */ jsx3(
|
|
1228
|
+
SelectInput,
|
|
1229
|
+
{
|
|
1230
|
+
items: [
|
|
1231
|
+
{ label: "Yes", value: true },
|
|
1232
|
+
{ label: "No", value: false }
|
|
1233
|
+
],
|
|
1234
|
+
onSelect: (item) => {
|
|
1235
|
+
setSetupStandardContexts(item.value);
|
|
1236
|
+
setStep("customContext");
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
)
|
|
1240
|
+
] });
|
|
1241
|
+
}
|
|
1242
|
+
if (step === "customContext") {
|
|
1243
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1244
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1245
|
+
"\u2714 Checking for Aptos CLI >=v",
|
|
1246
|
+
MIN_APTOS_CLI_VERSION,
|
|
1247
|
+
"...",
|
|
1248
|
+
" ",
|
|
1249
|
+
aptosCliMeetsRequirement ? "found" : "not found"
|
|
1250
|
+
] }),
|
|
1251
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1252
|
+
"\u2714 Do you want to set up standard contexts (devnet, testnet, mainnet)?",
|
|
1253
|
+
" ",
|
|
1254
|
+
setupStandardContexts ? "Yes" : "No"
|
|
1255
|
+
] }),
|
|
1256
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Do you want to set up a custom context?" }),
|
|
1257
|
+
/* @__PURE__ */ jsx3(
|
|
1258
|
+
SelectInput,
|
|
1259
|
+
{
|
|
1260
|
+
items: [
|
|
1261
|
+
{ label: "Yes", value: true },
|
|
1262
|
+
{ label: "No", value: false }
|
|
1263
|
+
],
|
|
1264
|
+
onSelect: (item) => {
|
|
1265
|
+
setSetupCustomContext(item.value);
|
|
1266
|
+
if (item.value) {
|
|
1267
|
+
setStep("customContextDetails");
|
|
1268
|
+
} else {
|
|
1269
|
+
setStep("setupAccount");
|
|
845
1270
|
}
|
|
846
1271
|
}
|
|
847
|
-
|
|
848
|
-
)
|
|
849
|
-
}
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
// src/commands/account.tsx
|
|
854
|
-
import { Hex as Hex2 } from "@aptos-labs/ts-sdk";
|
|
855
|
-
import { Aptos as Aptos3 } from "@aptos-labs/ts-sdk";
|
|
856
|
-
|
|
857
|
-
// ../../packages/sdk/dist/chunk-7ZRA6VJT.mjs
|
|
858
|
-
import { Aptos } from "@aptos-labs/ts-sdk";
|
|
859
|
-
var ShelbyClient = class {
|
|
860
|
-
config;
|
|
861
|
-
#aptos;
|
|
862
|
-
constructor(config) {
|
|
863
|
-
this.config = config;
|
|
864
|
-
this.#aptos = new Aptos(this.config.aptos.config);
|
|
1272
|
+
}
|
|
1273
|
+
)
|
|
1274
|
+
] });
|
|
865
1275
|
}
|
|
866
|
-
|
|
867
|
-
return
|
|
1276
|
+
if (step === "customContextDetails") {
|
|
1277
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1278
|
+
/* @__PURE__ */ jsx3(Text3, { children: "\u2714 Do you want to set up a custom context? Yes" }),
|
|
1279
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Context name? (default: staging)" }),
|
|
1280
|
+
/* @__PURE__ */ jsx3(
|
|
1281
|
+
TextInput3,
|
|
1282
|
+
{
|
|
1283
|
+
value: customContextName,
|
|
1284
|
+
onChange: setCustomContextName,
|
|
1285
|
+
onSubmit: () => setStep("shelbyRpcEndpoint")
|
|
1286
|
+
}
|
|
1287
|
+
)
|
|
1288
|
+
] });
|
|
868
1289
|
}
|
|
869
|
-
|
|
870
|
-
return
|
|
1290
|
+
if (step === "shelbyRpcEndpoint") {
|
|
1291
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1292
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1293
|
+
"\u2714 Context name? ",
|
|
1294
|
+
customContextName
|
|
1295
|
+
] }),
|
|
1296
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Shelby RPC endpoint? (default: https://shelby.rpc.staging.example.com)" }),
|
|
1297
|
+
/* @__PURE__ */ jsx3(
|
|
1298
|
+
TextInput3,
|
|
1299
|
+
{
|
|
1300
|
+
value: shelbyRpcEndpoint,
|
|
1301
|
+
onChange: setShelbyRpcEndpoint,
|
|
1302
|
+
onSubmit: () => setStep("aptosNetwork")
|
|
1303
|
+
}
|
|
1304
|
+
)
|
|
1305
|
+
] });
|
|
871
1306
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
});
|
|
889
|
-
function roundSize(size) {
|
|
890
|
-
let ret = 0;
|
|
891
|
-
let remain = size;
|
|
892
|
-
while (remain > 0) {
|
|
893
|
-
ret += getChunksetSizeBytes();
|
|
894
|
-
remain -= getChunksetSizeBytes();
|
|
1307
|
+
if (step === "aptosNetwork") {
|
|
1308
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1309
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1310
|
+
"\u2714 Shelby RPC endpoint? ",
|
|
1311
|
+
shelbyRpcEndpoint
|
|
1312
|
+
] }),
|
|
1313
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Aptos network? (default: mainnet)" }),
|
|
1314
|
+
/* @__PURE__ */ jsx3(
|
|
1315
|
+
TextInput3,
|
|
1316
|
+
{
|
|
1317
|
+
value: aptosNetwork,
|
|
1318
|
+
onChange: setAptosNetwork,
|
|
1319
|
+
onSubmit: () => setStep("setupAccount")
|
|
1320
|
+
}
|
|
1321
|
+
)
|
|
1322
|
+
] });
|
|
895
1323
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
function encodeURIComponentKeepSlashes(str) {
|
|
902
|
-
return encodeURIComponent(str).replace(/%2F/g, "/");
|
|
903
|
-
}
|
|
904
|
-
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
905
|
-
var ShelbyNodeClient = class extends ShelbyClient {
|
|
906
|
-
async #uploadPart(uploadId, partIdx, partData) {
|
|
907
|
-
const nRetries = 5;
|
|
908
|
-
for (let i = 0; i < nRetries; ++i) {
|
|
909
|
-
const partResponse = await fetch(
|
|
910
|
-
`${this.baseUrl}/api/v1/multipartUpload/uploadPart/${uploadId}/${partIdx}`,
|
|
1324
|
+
if (step === "setupAccount") {
|
|
1325
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1326
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Create or update an account now?" }),
|
|
1327
|
+
/* @__PURE__ */ jsx3(
|
|
1328
|
+
SelectInput,
|
|
911
1329
|
{
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
"
|
|
915
|
-
|
|
916
|
-
|
|
1330
|
+
items: [
|
|
1331
|
+
{ label: "Yes", value: true },
|
|
1332
|
+
{ label: "No", value: false }
|
|
1333
|
+
],
|
|
1334
|
+
onSelect: (item) => {
|
|
1335
|
+
setSetupAccount(item.value);
|
|
1336
|
+
if (item.value) {
|
|
1337
|
+
setStep("accountName");
|
|
1338
|
+
} else {
|
|
1339
|
+
setStep("complete");
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
917
1342
|
}
|
|
918
|
-
)
|
|
919
|
-
|
|
920
|
-
if (i < nRetries - 1) {
|
|
921
|
-
const delay = 2 ** i * 100;
|
|
922
|
-
await sleep(delay);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
throw new Error(`Failed to upload part ${partIdx}.`);
|
|
1343
|
+
)
|
|
1344
|
+
] });
|
|
926
1345
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
{
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
}
|
|
960
|
-
const completeResponse = await fetch(
|
|
961
|
-
`${this.baseUrl}/api/v1/multipartUpload/complete/${uploadId}`,
|
|
962
|
-
{
|
|
963
|
-
method: "POST",
|
|
964
|
-
headers: {
|
|
965
|
-
"Content-Type": "application/json"
|
|
1346
|
+
if (step === "accountName") {
|
|
1347
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1348
|
+
/* @__PURE__ */ jsx3(Text3, { children: "\u2714 Create or update an account now? Yes" }),
|
|
1349
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Account name? (default: alice)" }),
|
|
1350
|
+
/* @__PURE__ */ jsx3(
|
|
1351
|
+
TextInput3,
|
|
1352
|
+
{
|
|
1353
|
+
value: accountName,
|
|
1354
|
+
onChange: setAccountName,
|
|
1355
|
+
onSubmit: () => setStep("signatureScheme")
|
|
1356
|
+
}
|
|
1357
|
+
)
|
|
1358
|
+
] });
|
|
1359
|
+
}
|
|
1360
|
+
if (step === "signatureScheme") {
|
|
1361
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1362
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1363
|
+
"\u2714 Account name? ",
|
|
1364
|
+
accountName
|
|
1365
|
+
] }),
|
|
1366
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Signature scheme? (ed25519)" }),
|
|
1367
|
+
/* @__PURE__ */ jsx3(
|
|
1368
|
+
SelectInput,
|
|
1369
|
+
{
|
|
1370
|
+
items: [
|
|
1371
|
+
{ label: ED25519_NAME, value: ED25519_NAME }
|
|
1372
|
+
// { label: SECP256K1_NAME, value: SECP256K1_NAME },
|
|
1373
|
+
],
|
|
1374
|
+
onSelect: (item) => {
|
|
1375
|
+
setSignatureScheme(item.value);
|
|
1376
|
+
setStep("privateKey");
|
|
1377
|
+
}
|
|
966
1378
|
}
|
|
967
|
-
|
|
968
|
-
);
|
|
969
|
-
if (!completeResponse.ok) {
|
|
970
|
-
let errorBodyText = "Could not read error body";
|
|
971
|
-
try {
|
|
972
|
-
errorBodyText = await completeResponse.text();
|
|
973
|
-
} catch (e) {
|
|
974
|
-
}
|
|
975
|
-
throw new Error(
|
|
976
|
-
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
977
|
-
);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
async putBlob(account, blobName, blobData) {
|
|
981
|
-
BlobNameSchema.parse(blobName);
|
|
982
|
-
await this.#putBlobMultipart(account, blobName, blobData);
|
|
1379
|
+
)
|
|
1380
|
+
] });
|
|
983
1381
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1382
|
+
if (step === "privateKey") {
|
|
1383
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1384
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1385
|
+
"\u2714 Signature scheme? ",
|
|
1386
|
+
signatureScheme
|
|
1387
|
+
] }),
|
|
1388
|
+
/* @__PURE__ */ jsx3(Text3, { children: "Private key? (leave blank to generate new key)" }),
|
|
1389
|
+
/* @__PURE__ */ jsx3(
|
|
1390
|
+
TextInput3,
|
|
1391
|
+
{
|
|
1392
|
+
value: privateKey,
|
|
1393
|
+
onChange: setPrivateKey,
|
|
1394
|
+
onSubmit: () => {
|
|
1395
|
+
if (!privateKey) {
|
|
1396
|
+
const newKey = generateEd25519Account();
|
|
1397
|
+
setGeneratedKey(newKey.privateKey.toAIP80String());
|
|
1398
|
+
setGeneratedAddress(newKey.accountAddress.toString());
|
|
1399
|
+
}
|
|
1400
|
+
setStep("complete");
|
|
1401
|
+
}
|
|
997
1402
|
}
|
|
998
|
-
|
|
1403
|
+
)
|
|
1404
|
+
] });
|
|
1405
|
+
}
|
|
1406
|
+
return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text3, { children: "\u2705 Configuration complete!" }) });
|
|
1407
|
+
};
|
|
1408
|
+
|
|
1409
|
+
// src/components/UpdateContextWizard.tsx
|
|
1410
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
1411
|
+
import TextInput4 from "ink-text-input";
|
|
1412
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
1413
|
+
|
|
1414
|
+
// src/schemas/AptosNetworkSchema.ts
|
|
1415
|
+
import { z as z3 } from "zod";
|
|
1416
|
+
var AptosNetworkSchema = z3.enum([
|
|
1417
|
+
"mainnet",
|
|
1418
|
+
"testnet",
|
|
1419
|
+
"devnet",
|
|
1420
|
+
"local"
|
|
1421
|
+
]);
|
|
1422
|
+
|
|
1423
|
+
// src/schemas/EndpointSchema.ts
|
|
1424
|
+
import { z as z4 } from "zod";
|
|
1425
|
+
var EndpointSchema = z4.string().url("Must be a valid URL");
|
|
1426
|
+
|
|
1427
|
+
// src/components/UpdateContextWizard.tsx
|
|
1428
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1429
|
+
var UpdateContextWizard = ({
|
|
1430
|
+
contextName,
|
|
1431
|
+
currentShelbyRpc,
|
|
1432
|
+
currentAptosNetwork,
|
|
1433
|
+
onComplete
|
|
1434
|
+
}) => {
|
|
1435
|
+
const [step, setStep] = useState4("shelbyRpc");
|
|
1436
|
+
const [shelbyRpcEndpoint, setShelbyRpcEndpoint] = useState4(currentShelbyRpc);
|
|
1437
|
+
const [aptosNetwork, setAptosNetwork] = useState4(currentAptosNetwork);
|
|
1438
|
+
const [error, setError] = useState4("");
|
|
1439
|
+
useEffect4(() => {
|
|
1440
|
+
if (step === "done") {
|
|
1441
|
+
const updates = {};
|
|
1442
|
+
if (shelbyRpcEndpoint !== currentShelbyRpc) {
|
|
1443
|
+
updates.shelbyRpcEndpoint = shelbyRpcEndpoint;
|
|
999
1444
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
throw new Error(
|
|
1005
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
1006
|
-
);
|
|
1007
|
-
}
|
|
1008
|
-
if (!response.body) {
|
|
1009
|
-
throw new Error("Response body is null");
|
|
1010
|
-
}
|
|
1011
|
-
const contentLengthHeader = response.headers.get("content-length");
|
|
1012
|
-
if (contentLengthHeader === null) {
|
|
1013
|
-
throw new Error(
|
|
1014
|
-
"Response did not have content-length header, which is required"
|
|
1015
|
-
);
|
|
1016
|
-
}
|
|
1017
|
-
const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
|
|
1018
|
-
if (Number.isNaN(expectedContentLength)) {
|
|
1019
|
-
throw new Error(
|
|
1020
|
-
`Invalid content-length header received: ${contentLengthHeader}`
|
|
1021
|
-
);
|
|
1445
|
+
if (aptosNetwork !== currentAptosNetwork) {
|
|
1446
|
+
updates.aptosNetwork = aptosNetwork;
|
|
1447
|
+
}
|
|
1448
|
+
onComplete(updates);
|
|
1022
1449
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1450
|
+
}, [
|
|
1451
|
+
step,
|
|
1452
|
+
shelbyRpcEndpoint,
|
|
1453
|
+
aptosNetwork,
|
|
1454
|
+
currentShelbyRpc,
|
|
1455
|
+
currentAptosNetwork,
|
|
1456
|
+
onComplete
|
|
1457
|
+
]);
|
|
1458
|
+
if (step === "shelbyRpc") {
|
|
1459
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1460
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1461
|
+
"Updating context: ",
|
|
1462
|
+
contextName
|
|
1463
|
+
] }),
|
|
1464
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1465
|
+
"Shelby RPC endpoint? (current: ",
|
|
1466
|
+
currentShelbyRpc,
|
|
1467
|
+
")"
|
|
1468
|
+
] }),
|
|
1469
|
+
error && /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
1470
|
+
"Error: ",
|
|
1471
|
+
error
|
|
1472
|
+
] }),
|
|
1473
|
+
/* @__PURE__ */ jsx4(
|
|
1474
|
+
TextInput4,
|
|
1475
|
+
{
|
|
1476
|
+
value: shelbyRpcEndpoint,
|
|
1477
|
+
placeholder: currentShelbyRpc,
|
|
1478
|
+
onChange: (value) => {
|
|
1479
|
+
setShelbyRpcEndpoint(value);
|
|
1480
|
+
setError("");
|
|
1481
|
+
},
|
|
1482
|
+
onSubmit: () => {
|
|
1483
|
+
if (shelbyRpcEndpoint && shelbyRpcEndpoint !== currentShelbyRpc) {
|
|
1484
|
+
const result = EndpointSchema.safeParse(shelbyRpcEndpoint);
|
|
1485
|
+
if (!result.success) {
|
|
1486
|
+
setError(result.error.errors[0].message);
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
setError("");
|
|
1491
|
+
setStep("aptosApi");
|
|
1033
1492
|
}
|
|
1034
|
-
} catch (error) {
|
|
1035
|
-
this.destroy(error);
|
|
1036
1493
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1494
|
+
),
|
|
1495
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Press Enter to continue" })
|
|
1496
|
+
] });
|
|
1497
|
+
}
|
|
1498
|
+
if (step === "aptosApi") {
|
|
1499
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1500
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
1501
|
+
"Aptos network? (current: ",
|
|
1502
|
+
currentAptosNetwork,
|
|
1503
|
+
")"
|
|
1504
|
+
] }),
|
|
1505
|
+
error && /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
1506
|
+
"Error: ",
|
|
1507
|
+
error
|
|
1508
|
+
] }),
|
|
1509
|
+
/* @__PURE__ */ jsx4(
|
|
1510
|
+
TextInput4,
|
|
1511
|
+
{
|
|
1512
|
+
value: aptosNetwork,
|
|
1513
|
+
placeholder: currentAptosNetwork,
|
|
1514
|
+
onChange: (value) => {
|
|
1515
|
+
setAptosNetwork(value);
|
|
1516
|
+
setError("");
|
|
1517
|
+
},
|
|
1518
|
+
onSubmit: () => {
|
|
1519
|
+
if (aptosNetwork && aptosNetwork !== currentAptosNetwork) {
|
|
1520
|
+
const result = AptosNetworkSchema.safeParse(aptosNetwork);
|
|
1521
|
+
if (!result.success) {
|
|
1522
|
+
setError("Must be one of: mainnet, testnet, devnet, local");
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
setError("");
|
|
1527
|
+
setStep("done");
|
|
1528
|
+
}
|
|
1053
1529
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
stream: validationTransform,
|
|
1059
|
-
contentLength: expectedContentLength
|
|
1060
|
-
};
|
|
1530
|
+
),
|
|
1531
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Valid options: mainnet, testnet, devnet, local" }),
|
|
1532
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "Press Enter to save changes" })
|
|
1533
|
+
] });
|
|
1061
1534
|
}
|
|
1535
|
+
return null;
|
|
1062
1536
|
};
|
|
1063
1537
|
|
|
1064
|
-
//
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
// ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
|
|
1078
|
-
var __defProp = Object.defineProperty;
|
|
1079
|
-
var __export = (target, all) => {
|
|
1080
|
-
for (var name2 in all)
|
|
1081
|
-
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
1082
|
-
};
|
|
1538
|
+
// src/utils/config.ts
|
|
1539
|
+
import os from "os";
|
|
1540
|
+
import path from "path";
|
|
1541
|
+
import {
|
|
1542
|
+
AptosConfig,
|
|
1543
|
+
Ed25519Account,
|
|
1544
|
+
Ed25519PrivateKey as Ed25519PrivateKey2,
|
|
1545
|
+
NetworkToNetworkName
|
|
1546
|
+
} from "@aptos-labs/ts-sdk";
|
|
1547
|
+
import fs from "fs-extra";
|
|
1548
|
+
import YAML from "yaml";
|
|
1549
|
+
import { z as z5 } from "zod";
|
|
1083
1550
|
|
|
1084
|
-
//
|
|
1085
|
-
|
|
1086
|
-
var
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
);
|
|
1111
|
-
const chunkSize = Math.max(64, deterministicRand);
|
|
1112
|
-
const bytesToPush = Math.min(chunkSize, len - position);
|
|
1113
|
-
this.push(Buffer.from(data.subarray(position, position + bytesToPush)));
|
|
1114
|
-
position += bytesToPush;
|
|
1551
|
+
// tests/utils/mockConfig.ts
|
|
1552
|
+
var mockAccountAlice = generateEd25519Account();
|
|
1553
|
+
var mockAccountBob = generateEd25519Account();
|
|
1554
|
+
var mockConfig = {
|
|
1555
|
+
contexts: {
|
|
1556
|
+
devnet: {
|
|
1557
|
+
aptos_network: "devnet",
|
|
1558
|
+
shelby_rpc_endpoint: "https://shelby.rpc.devnet.example.com"
|
|
1559
|
+
},
|
|
1560
|
+
testnet: {
|
|
1561
|
+
aptos_network: "testnet",
|
|
1562
|
+
shelby_rpc_endpoint: "https://shelby.rpc.testnet.example.com"
|
|
1563
|
+
},
|
|
1564
|
+
mainnet: {
|
|
1565
|
+
aptos_network: "mainnet",
|
|
1566
|
+
shelby_rpc_endpoint: "https://shelby.rpc.mainnet.example.com"
|
|
1567
|
+
}
|
|
1568
|
+
},
|
|
1569
|
+
accounts: {
|
|
1570
|
+
alice: {
|
|
1571
|
+
address: mockAccountAlice.accountAddress.toString(),
|
|
1572
|
+
private_key: mockAccountAlice.privateKey.toAIP80String()
|
|
1573
|
+
},
|
|
1574
|
+
bob: {
|
|
1575
|
+
private_key: mockAccountBob.privateKey.toAIP80String(),
|
|
1576
|
+
address: mockAccountBob.accountAddress.toString()
|
|
1115
1577
|
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1578
|
+
},
|
|
1579
|
+
default_context: "devnet",
|
|
1580
|
+
default_account: "alice"
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
// src/utils/constants.ts
|
|
1584
|
+
var DEFAULT_CONFIG_PATH = "~/.shelby/config.yaml";
|
|
1118
1585
|
|
|
1119
|
-
//
|
|
1120
|
-
var
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
zeroPadBuffer: () => zeroPadBuffer
|
|
1586
|
+
// src/utils/config.ts
|
|
1587
|
+
var ContextSchema = z5.object({
|
|
1588
|
+
aptos_network: AptosNetworkSchema,
|
|
1589
|
+
shelby_rpc_endpoint: EndpointSchema
|
|
1124
1590
|
});
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
buffer = Buffer.alloc(chunkSize);
|
|
1140
|
-
bufferWriteOffset = 0;
|
|
1141
|
-
}
|
|
1142
|
-
bufferRemain = chunkSize - bufferWriteOffset;
|
|
1143
|
-
st = ed;
|
|
1144
|
-
ed = Math.min(readableChunk.length, st + bufferRemain);
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
if (bufferWriteOffset > 0) {
|
|
1148
|
-
yield [idx++, buffer.subarray(0, bufferWriteOffset)];
|
|
1591
|
+
var ConfigSchema = z5.object({
|
|
1592
|
+
contexts: z5.record(ContextSchema),
|
|
1593
|
+
accounts: z5.record(
|
|
1594
|
+
z5.object({
|
|
1595
|
+
address: z5.string().optional(),
|
|
1596
|
+
private_key: z5.string({ message: "private_key must be provided" })
|
|
1597
|
+
})
|
|
1598
|
+
),
|
|
1599
|
+
default_context: z5.string(),
|
|
1600
|
+
default_account: z5.string()
|
|
1601
|
+
});
|
|
1602
|
+
function resolveConfigPath(configPath) {
|
|
1603
|
+
if (configPath.startsWith("~")) {
|
|
1604
|
+
return path.join(os.homedir(), configPath.slice(1));
|
|
1149
1605
|
}
|
|
1606
|
+
return configPath;
|
|
1150
1607
|
}
|
|
1151
|
-
function
|
|
1152
|
-
|
|
1153
|
-
|
|
1608
|
+
function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
1609
|
+
const resolvedPath = resolveConfigPath(configPath);
|
|
1610
|
+
const dir = path.dirname(resolvedPath);
|
|
1611
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
1612
|
+
fs.mkdirpSync(dir);
|
|
1613
|
+
const yamlText = YAML.stringify(mockConfig);
|
|
1614
|
+
fs.writeFileSync(resolvedPath, yamlText, "utf8");
|
|
1615
|
+
return mockConfig;
|
|
1154
1616
|
}
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
return paddedBuffer;
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
// ../../packages/sdk/dist/chunk-USIL76JP.mjs
|
|
1161
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
1162
|
-
|
|
1163
|
-
// ../../packages/reed-solomon/dist/index.mjs
|
|
1164
|
-
import { createRequire } from "module";
|
|
1165
|
-
import { dirname, join } from "path";
|
|
1166
|
-
import { fileURLToPath } from "url";
|
|
1167
|
-
var require2 = createRequire(import.meta.url);
|
|
1168
|
-
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1169
|
-
var RS;
|
|
1170
|
-
try {
|
|
1617
|
+
const raw = fs.readFileSync(resolvedPath, "utf8");
|
|
1618
|
+
let parsed;
|
|
1171
1619
|
try {
|
|
1172
|
-
|
|
1620
|
+
parsed = YAML.parse(raw);
|
|
1173
1621
|
} catch {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1622
|
+
throw new Error("Invalid config file");
|
|
1623
|
+
}
|
|
1624
|
+
try {
|
|
1625
|
+
return ConfigSchema.parse(parsed);
|
|
1626
|
+
} catch (err) {
|
|
1627
|
+
throw new Error(`Invalid config file: ${err.message}`);
|
|
1179
1628
|
}
|
|
1180
|
-
} catch {
|
|
1181
|
-
RS = require2("@ronomon/reed-solomon");
|
|
1182
1629
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
let sources = 0;
|
|
1194
|
-
for (let i = 0; i < k; i++) sources |= 1 << i;
|
|
1195
|
-
let targets = 0;
|
|
1196
|
-
for (let i = k; i < k + m; i++) targets |= 1 << i;
|
|
1197
|
-
const context = RS.create(k, m);
|
|
1198
|
-
await new Promise((resolve2, reject) => {
|
|
1199
|
-
RS.encode(
|
|
1200
|
-
context,
|
|
1201
|
-
sources,
|
|
1202
|
-
targets,
|
|
1203
|
-
dataBuf,
|
|
1204
|
-
0,
|
|
1205
|
-
dataSize,
|
|
1206
|
-
parityBuf,
|
|
1207
|
-
0,
|
|
1208
|
-
paritySize,
|
|
1209
|
-
(err) => err ? reject(err) : resolve2()
|
|
1210
|
-
);
|
|
1211
|
-
});
|
|
1212
|
-
const shards = [];
|
|
1213
|
-
for (let i = 0; i < k; i++) {
|
|
1214
|
-
shards.push(dataBuf.slice(i * shardSize, i * shardSize + shardSize));
|
|
1630
|
+
function saveConfig(config, configPath = "~/.shelby/config.yaml") {
|
|
1631
|
+
const resolvedPath = resolveConfigPath(configPath);
|
|
1632
|
+
fs.mkdirpSync(path.dirname(resolvedPath));
|
|
1633
|
+
ConfigSchema.parse(config);
|
|
1634
|
+
fs.writeFileSync(resolvedPath, YAML.stringify(config), "utf8");
|
|
1635
|
+
}
|
|
1636
|
+
function getCurrentAccount(config, accountName) {
|
|
1637
|
+
const name = accountName || config.default_account;
|
|
1638
|
+
if (!name) {
|
|
1639
|
+
throw new Error(`Account with name '${name}' not found in config`);
|
|
1215
1640
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1641
|
+
const account = config.accounts[name];
|
|
1642
|
+
if (!account) {
|
|
1643
|
+
throw new Error(`Account '${name}' not found in config`);
|
|
1218
1644
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1645
|
+
let privateKey;
|
|
1646
|
+
if (account.private_key) {
|
|
1647
|
+
privateKey = account.private_key;
|
|
1648
|
+
} else {
|
|
1649
|
+
throw new Error(`No private key found for account '${name}'`);
|
|
1650
|
+
}
|
|
1651
|
+
return {
|
|
1652
|
+
address: account.address,
|
|
1653
|
+
privateKey,
|
|
1654
|
+
account: new Ed25519Account({
|
|
1655
|
+
privateKey: new Ed25519PrivateKey2(privateKey)
|
|
1656
|
+
})
|
|
1657
|
+
};
|
|
1227
1658
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
);
|
|
1237
|
-
for await (let [chunksetIdx, chunksetData] of chunksetGen) {
|
|
1238
|
-
const chunkCommitments = [];
|
|
1239
|
-
rawDataSize += chunksetData.length;
|
|
1240
|
-
chunksetData = zeroPadBuffer(
|
|
1241
|
-
chunksetData,
|
|
1242
|
-
options?.chunksetSize ?? getChunksetSizeBytes()
|
|
1243
|
-
);
|
|
1244
|
-
const chunks = await erasureEncode(
|
|
1245
|
-
chunksetData,
|
|
1246
|
-
options?.erasureK ?? ERASURE_K,
|
|
1247
|
-
options?.erasureM ?? ERASURE_M
|
|
1659
|
+
function getCurrentShelbyConfig(config, opts = {
|
|
1660
|
+
context: config.default_context
|
|
1661
|
+
}) {
|
|
1662
|
+
const { context } = opts;
|
|
1663
|
+
const selectedContext = config.contexts[context ?? config.default_context];
|
|
1664
|
+
if (!selectedContext) {
|
|
1665
|
+
throw new Error(
|
|
1666
|
+
`Context '${context ?? config.default_context}' not found in config`
|
|
1248
1667
|
);
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
}
|
|
1254
|
-
const chunkHash = createHash("sha256").update(chunkData);
|
|
1255
|
-
chunkCommitments.push(chunkHash);
|
|
1256
|
-
chunkIdx += 1;
|
|
1257
|
-
}
|
|
1258
|
-
const h = concatHashes(chunkCommitments);
|
|
1259
|
-
chunksetCommitments.push({
|
|
1260
|
-
chunkset_root: `0x${h.copy().digest("hex")}`,
|
|
1261
|
-
chunk_commitments: chunkCommitments.map((buffer) => buffer.digest("hex"))
|
|
1262
|
-
});
|
|
1263
|
-
blobCommitment.update(chunksetData);
|
|
1264
|
-
chunksetCommitmentHashes.push(h);
|
|
1668
|
+
}
|
|
1669
|
+
const aptosNetwork = NetworkToNetworkName[selectedContext.aptos_network];
|
|
1670
|
+
if (!aptosNetwork) {
|
|
1671
|
+
throw new Error(`Invalid Aptos network: ${selectedContext.aptos_network}`);
|
|
1265
1672
|
}
|
|
1266
1673
|
return {
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
blob_merkle_root: `0x${concatHashes(chunksetCommitmentHashes).digest("hex")}`,
|
|
1270
|
-
chunkset_commitments: chunksetCommitments
|
|
1674
|
+
aptos: { config: new AptosConfig({ network: aptosNetwork }) },
|
|
1675
|
+
shelby: { baseUrl: selectedContext.shelby_rpc_endpoint }
|
|
1271
1676
|
};
|
|
1272
1677
|
}
|
|
1273
1678
|
|
|
1274
|
-
//
|
|
1275
|
-
import
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
async getBlobMetadata(params) {
|
|
1294
|
-
try {
|
|
1295
|
-
const rawMetadata = await this.aptos.view({
|
|
1296
|
-
payload: {
|
|
1297
|
-
function: `${this.deployer.toString()}::prototype_interface::get_metadata`,
|
|
1298
|
-
functionArguments: [
|
|
1299
|
-
_ShelbyBlobClient.createBlobKey(params.account, params.name)
|
|
1300
|
-
]
|
|
1301
|
-
}
|
|
1302
|
-
});
|
|
1303
|
-
const metadata = rawMetadata[0];
|
|
1304
|
-
return {
|
|
1305
|
-
blobMerkleRoot: Hex.fromHexInput(
|
|
1306
|
-
metadata.blob_merkle_root
|
|
1307
|
-
).toUint8Array(),
|
|
1308
|
-
owner: AccountAddress3.fromString(metadata.owner),
|
|
1309
|
-
name: metadata.name,
|
|
1310
|
-
size: metadata.size,
|
|
1311
|
-
encoding: {
|
|
1312
|
-
variant: "clay",
|
|
1313
|
-
erasureK: metadata.encoding.num_data_chunks,
|
|
1314
|
-
erasureM: metadata.encoding.num_parity_chunks,
|
|
1315
|
-
chunksetSize: metadata.encoding.chunkset_size
|
|
1316
|
-
},
|
|
1317
|
-
expirationMicros: metadata.expiration_micros
|
|
1318
|
-
};
|
|
1319
|
-
} catch (error) {
|
|
1320
|
-
if (error instanceof AptosApiError && error.data?.message?.includes("sub_status: Some(404)")) {
|
|
1321
|
-
return void 0;
|
|
1322
|
-
}
|
|
1323
|
-
throw error;
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
async getAccountBlobs(params) {
|
|
1327
|
-
const rawBlobMetadatas = await this.aptos.view({
|
|
1328
|
-
payload: {
|
|
1329
|
-
function: `${this.deployer.toString()}::prototype_interface::get_blobs_for_owner`,
|
|
1330
|
-
functionArguments: [params.account.toString()]
|
|
1331
|
-
}
|
|
1332
|
-
});
|
|
1333
|
-
return rawBlobMetadatas[0].map((blob) => ({
|
|
1334
|
-
blobMerkleRoot: Hex.fromHexInput(blob.blob_merkle_root).toUint8Array(),
|
|
1335
|
-
owner: AccountAddress3.fromString(blob.owner),
|
|
1336
|
-
name: blob.name,
|
|
1337
|
-
size: blob.size,
|
|
1338
|
-
encoding: {
|
|
1339
|
-
variant: "clay",
|
|
1340
|
-
erasureK: blob.encoding.num_data_chunks,
|
|
1341
|
-
erasureM: blob.encoding.num_parity_chunks,
|
|
1342
|
-
chunksetSize: blob.encoding.chunkset_size
|
|
1343
|
-
},
|
|
1344
|
-
expirationMicros: blob.expiration_micros
|
|
1345
|
-
}));
|
|
1346
|
-
}
|
|
1347
|
-
/**
|
|
1348
|
-
* Queries the blockchain for the chunks pertaining to a given blob.
|
|
1349
|
-
*
|
|
1350
|
-
* @param account - The account namespace the blob is stored in (e.g. "0x1")
|
|
1351
|
-
* @param name - The name of the blob (e.g. "foo/bar")
|
|
1352
|
-
* @returns The chunks that make up the blob.
|
|
1353
|
-
*/
|
|
1354
|
-
async getBlobChunks(params) {
|
|
1355
|
-
const chunks = await this.aptos.view({
|
|
1356
|
-
payload: {
|
|
1357
|
-
function: `${this.deployer.toString()}::prototype_interface::get_chunks`,
|
|
1358
|
-
functionArguments: [
|
|
1359
|
-
_ShelbyBlobClient.createBlobKey(params.account, params.name)
|
|
1360
|
-
]
|
|
1361
|
-
}
|
|
1362
|
-
});
|
|
1363
|
-
return chunks[0].map((c) => ({
|
|
1364
|
-
commitment: Hex.fromHexInput(c.commitment).toUint8Array(),
|
|
1365
|
-
location: {
|
|
1366
|
-
variant: c.location.__variant__ === "Stored" ? "stored" : "pending",
|
|
1367
|
-
provider: AccountAddress3.fromString(c.location.provider)
|
|
1368
|
-
}
|
|
1369
|
-
}));
|
|
1370
|
-
}
|
|
1371
|
-
async writeBlobCommitments(params) {
|
|
1372
|
-
let blobCommitments;
|
|
1373
|
-
if ("blobCommitments" in params) {
|
|
1374
|
-
blobCommitments = params.blobCommitments;
|
|
1375
|
-
} else {
|
|
1376
|
-
blobCommitments = await generateCommitments(
|
|
1377
|
-
Readable3.from(params.data),
|
|
1378
|
-
void 0,
|
|
1379
|
-
params.options?.encoding
|
|
1380
|
-
);
|
|
1381
|
-
}
|
|
1382
|
-
const transaction = await this.aptos.transaction.build.simple({
|
|
1383
|
-
...params.options?.build,
|
|
1384
|
-
data: _ShelbyBlobClient.createWriteBlobCommitmentsPayload({
|
|
1385
|
-
deployer: this.deployer,
|
|
1386
|
-
account: params.account.accountAddress,
|
|
1387
|
-
blobName: params.blobName,
|
|
1388
|
-
blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
1389
|
-
chunksetChunkCommitments: blobCommitments.chunkset_commitments.map(
|
|
1390
|
-
(chunkset) => chunkset.chunk_commitments
|
|
1391
|
-
),
|
|
1392
|
-
size: blobCommitments.raw_data_size,
|
|
1393
|
-
lifetime: params.lifetime
|
|
1394
|
-
// FIXME rename?
|
|
1395
|
-
}),
|
|
1396
|
-
sender: params.account.accountAddress
|
|
1397
|
-
});
|
|
1398
|
-
return {
|
|
1399
|
-
blobCommitments,
|
|
1400
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
1401
|
-
signer: params.account,
|
|
1402
|
-
transaction
|
|
1403
|
-
})
|
|
1404
|
-
};
|
|
1405
|
-
}
|
|
1406
|
-
async confirmBlobChunks(params) {
|
|
1407
|
-
const transaction = await this.aptos.transaction.build.simple({
|
|
1408
|
-
...params.options?.build,
|
|
1409
|
-
data: _ShelbyBlobClient.createConfirmBlobChunksPayload({
|
|
1410
|
-
deployer: this.deployer,
|
|
1411
|
-
account: params.account,
|
|
1412
|
-
blobName: params.blobName,
|
|
1413
|
-
signedChunksetChunkCommitments: params.signedChunksetChunkCommitments
|
|
1414
|
-
}),
|
|
1415
|
-
sender: params.signer.accountAddress
|
|
1416
|
-
});
|
|
1417
|
-
return {
|
|
1418
|
-
transaction: await this.aptos.signAndSubmitTransaction({
|
|
1419
|
-
signer: params.signer,
|
|
1420
|
-
transaction
|
|
1421
|
-
})
|
|
1422
|
-
};
|
|
1423
|
-
}
|
|
1424
|
-
/**
|
|
1425
|
-
* Creates a transaction payload to write blob commitments to the blockchain.
|
|
1426
|
-
*
|
|
1427
|
-
* @see https://github.com/JumpCrypto/shelby/blob/e009607aad330ccddb08d80bf9addfaadae7972b/move/prototype/move/sources/prototype_interface.move#L211-L220
|
|
1428
|
-
*/
|
|
1429
|
-
static createWriteBlobCommitmentsPayload(params) {
|
|
1430
|
-
return {
|
|
1431
|
-
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::prototype_interface::write_commitments`,
|
|
1432
|
-
functionArguments: [
|
|
1433
|
-
_ShelbyBlobClient.createBlobKey(params.account, params.blobName),
|
|
1434
|
-
params.size,
|
|
1435
|
-
MoveVector.U8(params.blobMerkleRoot),
|
|
1436
|
-
params.chunksetChunkCommitments.map(
|
|
1437
|
-
(chunkset) => chunkset.map((chunkCommitment) => MoveVector.U8(chunkCommitment))
|
|
1438
|
-
),
|
|
1439
|
-
params.lifetime ?? 0,
|
|
1440
|
-
true
|
|
1441
|
-
]
|
|
1442
|
-
};
|
|
1443
|
-
}
|
|
1444
|
-
/**
|
|
1445
|
-
* Creates a transaction payload to confirm the chunks of a blob.
|
|
1446
|
-
*
|
|
1447
|
-
* @see https://github.com/JumpCrypto/shelby/blob/e009607aad330ccddb08d80bf9addfaadae7972b/move/prototype/move/sources/prototype_interface.move#L343-L349
|
|
1448
|
-
*/
|
|
1449
|
-
static createConfirmBlobChunksPayload(params) {
|
|
1450
|
-
return {
|
|
1451
|
-
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::prototype_interface::write_complete`,
|
|
1452
|
-
functionArguments: [
|
|
1453
|
-
_ShelbyBlobClient.createBlobKey(params.account, params.blobName),
|
|
1454
|
-
params.signedChunksetChunkCommitments.map(
|
|
1455
|
-
(chunkset) => chunkset.map((chunk) => AccountAddress3.from(chunk.provider))
|
|
1456
|
-
),
|
|
1457
|
-
params.signedChunksetChunkCommitments.map(
|
|
1458
|
-
(chunkset) => chunkset.map((chunk) => MoveVector.U8(chunk.signedCommitment))
|
|
1459
|
-
),
|
|
1460
|
-
true
|
|
1461
|
-
]
|
|
1462
|
-
};
|
|
1679
|
+
// src/utils/paths.ts
|
|
1680
|
+
import path2 from "path";
|
|
1681
|
+
function normBlobName(pathModule, inputDirectoryName, filename, blobPrefix) {
|
|
1682
|
+
const blobNameWithoutInputDir = pathModule.relative(
|
|
1683
|
+
inputDirectoryName,
|
|
1684
|
+
filename
|
|
1685
|
+
);
|
|
1686
|
+
const blobNameWithPrefix = pathModule.join(
|
|
1687
|
+
blobPrefix,
|
|
1688
|
+
blobNameWithoutInputDir
|
|
1689
|
+
);
|
|
1690
|
+
const blobNameNormalized = pathModule.normalize(blobNameWithPrefix);
|
|
1691
|
+
const parts = blobNameNormalized.split(pathModule.sep);
|
|
1692
|
+
return path2.posix.join(...parts);
|
|
1693
|
+
}
|
|
1694
|
+
function denormBlobName(pathModule, blobPrefix, blobName, outputPrefix) {
|
|
1695
|
+
if (!pathModule.isAbsolute(outputPrefix)) {
|
|
1696
|
+
throw new Error(`Output prefix '${outputPrefix}' must be an absolute path`);
|
|
1463
1697
|
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
var ChunksetCommitmentSchema = z5.object({
|
|
1469
|
-
// Chunkset root (vector commitment of child chunks)
|
|
1470
|
-
chunkset_root: z5.string().nullable(),
|
|
1471
|
-
// the size is known statically from the current configuration
|
|
1472
|
-
chunk_commitments: z5.array(z5.string())
|
|
1473
|
-
}).refine(
|
|
1474
|
-
(data) => {
|
|
1475
|
-
return data.chunk_commitments.length === ERASURE_K + ERASURE_M;
|
|
1476
|
-
},
|
|
1477
|
-
{
|
|
1478
|
-
message: `Chunkset must have exactly ${ERASURE_K + ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${ERASURE_K} + ${ERASURE_M})`,
|
|
1479
|
-
path: ["chunk_commitments"]
|
|
1698
|
+
if (!blobName.startsWith(blobPrefix)) {
|
|
1699
|
+
throw new Error(
|
|
1700
|
+
`Blob name '${blobName}' does not start with prefix '${blobPrefix}'`
|
|
1701
|
+
);
|
|
1480
1702
|
}
|
|
1481
|
-
);
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
var BlobCommitmentsSchema = z5.object({
|
|
1486
|
-
schema_version: z5.string(),
|
|
1487
|
-
raw_data_size: z5.number(),
|
|
1488
|
-
// FIXME I am not sure about this being here, or if it should be somewhere else
|
|
1489
|
-
// I deleted the blob_commitment. What's the difference?
|
|
1490
|
-
blob_merkle_root: z5.string(),
|
|
1491
|
-
chunkset_commitments: z5.array(ChunksetCommitmentSchema)
|
|
1492
|
-
}).refine(
|
|
1493
|
-
(data) => {
|
|
1494
|
-
return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
|
|
1495
|
-
},
|
|
1496
|
-
{
|
|
1497
|
-
message: "Total chunkset count mismatches with raw data size",
|
|
1498
|
-
// FIXME put more details in here
|
|
1499
|
-
path: ["chunkset_commitments"]
|
|
1703
|
+
const relativePath = blobName.slice(blobPrefix.length);
|
|
1704
|
+
const pathParts = relativePath.split("/").filter((part) => part.length > 0);
|
|
1705
|
+
if (pathParts.length === 0) {
|
|
1706
|
+
return outputPrefix;
|
|
1500
1707
|
}
|
|
1501
|
-
);
|
|
1502
|
-
|
|
1503
|
-
// ../../packages/sdk/dist/chunk-IS2JVNMO.mjs
|
|
1504
|
-
import { hashValues } from "@aptos-labs/ts-sdk";
|
|
1708
|
+
return pathModule.join(outputPrefix, ...pathParts);
|
|
1709
|
+
}
|
|
1505
1710
|
|
|
1506
1711
|
// src/commands/account.tsx
|
|
1507
|
-
import
|
|
1508
|
-
import { render as render2 } from "ink";
|
|
1509
|
-
import { z as z6 } from "zod";
|
|
1510
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1712
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1511
1713
|
var CreateAccountOptionsSchema = z6.object({
|
|
1512
1714
|
name: z6.string().optional(),
|
|
1513
1715
|
privateKey: z6.string().optional(),
|
|
@@ -1532,8 +1734,8 @@ function accountCommand(program) {
|
|
|
1532
1734
|
"Aptos account address (hex-encoded)"
|
|
1533
1735
|
).action((options) => {
|
|
1534
1736
|
CreateAccountOptionsSchema.parse(options);
|
|
1535
|
-
const { name
|
|
1536
|
-
const allPresent =
|
|
1737
|
+
const { name, privateKey, address, scheme } = options;
|
|
1738
|
+
const allPresent = name && privateKey && address && scheme;
|
|
1537
1739
|
const configPath = program.opts().configFile;
|
|
1538
1740
|
let config;
|
|
1539
1741
|
try {
|
|
@@ -1545,33 +1747,33 @@ function accountCommand(program) {
|
|
|
1545
1747
|
}
|
|
1546
1748
|
if (allPresent) {
|
|
1547
1749
|
if (isValidAddress(address) && isValidEd25519PrivateKey(privateKey) && isValidScheme(scheme)) {
|
|
1548
|
-
config.accounts[
|
|
1750
|
+
config.accounts[name] = {
|
|
1549
1751
|
private_key: privateKey
|
|
1550
1752
|
};
|
|
1551
1753
|
if (options.address) {
|
|
1552
|
-
config.accounts[
|
|
1754
|
+
config.accounts[name].address = address;
|
|
1553
1755
|
}
|
|
1554
1756
|
} else {
|
|
1555
1757
|
throw new Error("Error invalid account address or private key");
|
|
1556
1758
|
}
|
|
1557
1759
|
} else {
|
|
1558
1760
|
try {
|
|
1559
|
-
const { unmount } =
|
|
1560
|
-
/* @__PURE__ */
|
|
1761
|
+
const { unmount } = render(
|
|
1762
|
+
/* @__PURE__ */ jsx5(
|
|
1561
1763
|
AccountWizard,
|
|
1562
1764
|
{
|
|
1563
1765
|
onComplete: ({
|
|
1564
|
-
name:
|
|
1766
|
+
name: name2,
|
|
1565
1767
|
address: address2,
|
|
1566
1768
|
privateKey: privateKey2
|
|
1567
1769
|
}) => {
|
|
1568
|
-
config.accounts[
|
|
1770
|
+
config.accounts[name2] = {
|
|
1569
1771
|
private_key: privateKey2,
|
|
1570
1772
|
address: address2
|
|
1571
1773
|
};
|
|
1572
1774
|
saveConfig(config, configPath);
|
|
1573
1775
|
console.log(
|
|
1574
|
-
`\u2705 Account ${
|
|
1776
|
+
`\u2705 Account ${name2} saved to ${resolveConfigPath(configPath)}`
|
|
1575
1777
|
);
|
|
1576
1778
|
unmount();
|
|
1577
1779
|
}
|
|
@@ -1600,11 +1802,11 @@ function accountCommand(program) {
|
|
|
1600
1802
|
style: { head: ["cyan"] },
|
|
1601
1803
|
colWidths: [20, 68, 22]
|
|
1602
1804
|
});
|
|
1603
|
-
for (const [
|
|
1805
|
+
for (const [name, { address, private_key }] of Object.entries(
|
|
1604
1806
|
config.accounts
|
|
1605
1807
|
)) {
|
|
1606
|
-
const isDefault =
|
|
1607
|
-
const displayName =
|
|
1808
|
+
const isDefault = name === config.default_account ? " (default)" : "";
|
|
1809
|
+
const displayName = name + isDefault;
|
|
1608
1810
|
const maskedKey = private_key ? `${private_key.slice(0, 20)}...` : "";
|
|
1609
1811
|
table.push([displayName, address || "", maskedKey]);
|
|
1610
1812
|
}
|
|
@@ -1667,12 +1869,11 @@ function accountCommand(program) {
|
|
|
1667
1869
|
context: program.opts().context
|
|
1668
1870
|
});
|
|
1669
1871
|
const activeAccount = getCurrentAccount(config, accountName).account;
|
|
1670
|
-
const
|
|
1671
|
-
const blobClient = new ShelbyBlobClient({ aptos });
|
|
1872
|
+
const shelbyClient = new ShelbyNodeClient(shelbyConfig);
|
|
1672
1873
|
console.log(
|
|
1673
1874
|
`\u{1F50D} Retrieving blobs for ${accountName} (${activeAccount.accountAddress.toString()})`
|
|
1674
1875
|
);
|
|
1675
|
-
const blobs = await
|
|
1876
|
+
const blobs = await shelbyClient.coordination.getAccountBlobs({
|
|
1676
1877
|
account: activeAccount.accountAddress
|
|
1677
1878
|
});
|
|
1678
1879
|
console.log(
|
|
@@ -1696,7 +1897,7 @@ function accountCommand(program) {
|
|
|
1696
1897
|
table.push([
|
|
1697
1898
|
blob.name,
|
|
1698
1899
|
blob.size.toString(),
|
|
1699
|
-
|
|
1900
|
+
Hex3.fromHexInput(blob.blobMerkleRoot).toString(),
|
|
1700
1901
|
blob.encoding.variant,
|
|
1701
1902
|
blob.encoding.erasureK.toString(),
|
|
1702
1903
|
blob.encoding.erasureM.toString(),
|
|
@@ -1718,18 +1919,60 @@ function accountCommand(program) {
|
|
|
1718
1919
|
});
|
|
1719
1920
|
}
|
|
1720
1921
|
|
|
1922
|
+
// src/commands/commitment.ts
|
|
1923
|
+
import * as fs2 from "fs";
|
|
1924
|
+
import * as fsP from "fs/promises";
|
|
1925
|
+
import { Readable } from "stream";
|
|
1926
|
+
import { z as z7 } from "zod";
|
|
1927
|
+
var CommitmentOptionsSchema = z7.object({
|
|
1928
|
+
input: z7.string().nonempty("`--input` is required").refine(
|
|
1929
|
+
async (path5) => {
|
|
1930
|
+
const stat4 = await fsP.stat(path5);
|
|
1931
|
+
return stat4.isFile();
|
|
1932
|
+
},
|
|
1933
|
+
{
|
|
1934
|
+
message: "`--input` must be a file"
|
|
1935
|
+
}
|
|
1936
|
+
),
|
|
1937
|
+
output: z7.string().nonempty("`--output` is required")
|
|
1938
|
+
});
|
|
1939
|
+
function commitmentCommand(program) {
|
|
1940
|
+
program.command("commitment").description(
|
|
1941
|
+
"Compute commitments for a file place into an output JSON file. Intended for debugging and introspection."
|
|
1942
|
+
).requiredOption("-i, --input <path>", "Path to a file").requiredOption("-o, --output <path>", "Path to a file").action(async (rawOptions) => {
|
|
1943
|
+
const validatedOptions = await CommitmentOptionsSchema.parseAsync(rawOptions);
|
|
1944
|
+
const input = fs2.createReadStream(validatedOptions.input);
|
|
1945
|
+
const commitment = await generateCommitments(Readable.toWeb(input));
|
|
1946
|
+
await fsP.writeFile(validatedOptions.output, JSON.stringify(commitment));
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1721
1950
|
// src/commands/context.tsx
|
|
1722
1951
|
import Table2 from "cli-table3";
|
|
1723
|
-
import { render as
|
|
1724
|
-
import { z as
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1952
|
+
import { render as render2 } from "ink";
|
|
1953
|
+
import { z as z8 } from "zod";
|
|
1954
|
+
|
|
1955
|
+
// src/utils/url.ts
|
|
1956
|
+
function sanitizeRpcUrl(urlString) {
|
|
1957
|
+
const url = new URL(urlString);
|
|
1958
|
+
if (url.pathname === "/") {
|
|
1959
|
+
let result = `${url.protocol}//${url.host}`;
|
|
1960
|
+
if (url.search) result += url.search;
|
|
1961
|
+
if (url.hash) result += url.hash;
|
|
1962
|
+
return result;
|
|
1963
|
+
}
|
|
1964
|
+
return url.toString();
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
// src/commands/context.tsx
|
|
1968
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1969
|
+
var CreateContextOptionsSchema = z8.object({
|
|
1970
|
+
name: z8.string().optional(),
|
|
1728
1971
|
shelbyRpcEndpoint: EndpointSchema.optional(),
|
|
1729
1972
|
aptosNetwork: AptosNetworkSchema.optional()
|
|
1730
1973
|
// TODO: Add support for custom endpoints objects
|
|
1731
1974
|
});
|
|
1732
|
-
var UpdateContextOptionsSchema =
|
|
1975
|
+
var UpdateContextOptionsSchema = z8.object({
|
|
1733
1976
|
shelbyRpcEndpoint: EndpointSchema.optional(),
|
|
1734
1977
|
aptosNetwork: AptosNetworkSchema.optional()
|
|
1735
1978
|
// TODO: Add support for custom endpoints objects
|
|
@@ -1738,43 +1981,45 @@ function contextCommand(program) {
|
|
|
1738
1981
|
const context = program.command("context").description("Manage network contexts (Shelby RPC & Aptos endpoints)");
|
|
1739
1982
|
context.command("create").description("Create a new context").option("--name <context-name>", "Name of the context").option("--shelby-rpc-endpoint <url>", "URL of the Shelby RPC service").option("--aptos-network <network>", "Aptos network").action((options) => {
|
|
1740
1983
|
CreateContextOptionsSchema.parse(options);
|
|
1741
|
-
const { name
|
|
1984
|
+
const { name, shelbyRpcEndpoint, aptosNetwork } = options;
|
|
1742
1985
|
const configPath = program.opts().configFile;
|
|
1743
1986
|
let config;
|
|
1744
1987
|
try {
|
|
1745
1988
|
config = loadConfig(configPath);
|
|
1746
|
-
} catch (
|
|
1989
|
+
} catch (_error) {
|
|
1747
1990
|
config = {
|
|
1748
1991
|
contexts: {},
|
|
1749
1992
|
accounts: {},
|
|
1750
|
-
default_context:
|
|
1993
|
+
default_context: name || "",
|
|
1751
1994
|
default_account: "default_account"
|
|
1752
1995
|
};
|
|
1753
1996
|
}
|
|
1754
|
-
if (
|
|
1755
|
-
|
|
1756
|
-
|
|
1997
|
+
if (name && shelbyRpcEndpoint && aptosNetwork) {
|
|
1998
|
+
const cleanedShelbyRpcEndpoint = sanitizeRpcUrl(shelbyRpcEndpoint);
|
|
1999
|
+
config.contexts[name] = {
|
|
2000
|
+
shelby_rpc_endpoint: cleanedShelbyRpcEndpoint,
|
|
1757
2001
|
aptos_network: aptosNetwork
|
|
1758
2002
|
};
|
|
1759
2003
|
saveConfig(config, configPath);
|
|
1760
|
-
console.log(`\u2705 Context '${
|
|
2004
|
+
console.log(`\u2705 Context '${name}' created successfully`);
|
|
1761
2005
|
return;
|
|
1762
2006
|
}
|
|
1763
|
-
const { unmount } =
|
|
1764
|
-
/* @__PURE__ */
|
|
2007
|
+
const { unmount } = render2(
|
|
2008
|
+
/* @__PURE__ */ jsx6(
|
|
1765
2009
|
ContextWizard,
|
|
1766
2010
|
{
|
|
1767
2011
|
onComplete: ({
|
|
1768
|
-
name:
|
|
2012
|
+
name: name2,
|
|
1769
2013
|
shelbyRpcEndpoint: shelbyRpcEndpoint2,
|
|
1770
2014
|
aptosNetwork: aptosNetwork2
|
|
1771
2015
|
}) => {
|
|
1772
|
-
|
|
1773
|
-
|
|
2016
|
+
const cleanedShelbyRpcEndpoint = sanitizeRpcUrl(shelbyRpcEndpoint2);
|
|
2017
|
+
config.contexts[name2] = {
|
|
2018
|
+
shelby_rpc_endpoint: cleanedShelbyRpcEndpoint,
|
|
1774
2019
|
aptos_network: aptosNetwork2
|
|
1775
2020
|
};
|
|
1776
2021
|
saveConfig(config, configPath);
|
|
1777
|
-
console.log(`\u2705 Context '${
|
|
2022
|
+
console.log(`\u2705 Context '${name2}' created successfully`);
|
|
1778
2023
|
unmount();
|
|
1779
2024
|
process.exit(0);
|
|
1780
2025
|
}
|
|
@@ -1800,7 +2045,7 @@ function contextCommand(program) {
|
|
|
1800
2045
|
const currentContext = config.contexts[contextName];
|
|
1801
2046
|
if (shelbyRpcEndpoint || aptosNetwork) {
|
|
1802
2047
|
if (shelbyRpcEndpoint) {
|
|
1803
|
-
config.contexts[contextName].shelby_rpc_endpoint = shelbyRpcEndpoint;
|
|
2048
|
+
config.contexts[contextName].shelby_rpc_endpoint = sanitizeRpcUrl(shelbyRpcEndpoint);
|
|
1804
2049
|
}
|
|
1805
2050
|
if (aptosNetwork) {
|
|
1806
2051
|
config.contexts[contextName].aptos_network = aptosNetwork;
|
|
@@ -1809,8 +2054,8 @@ function contextCommand(program) {
|
|
|
1809
2054
|
console.log(`\u2705 Context '${contextName}' updated successfully`);
|
|
1810
2055
|
return;
|
|
1811
2056
|
}
|
|
1812
|
-
const { unmount } =
|
|
1813
|
-
/* @__PURE__ */
|
|
2057
|
+
const { unmount } = render2(
|
|
2058
|
+
/* @__PURE__ */ jsx6(
|
|
1814
2059
|
UpdateContextWizard,
|
|
1815
2060
|
{
|
|
1816
2061
|
contextName,
|
|
@@ -1821,7 +2066,7 @@ function contextCommand(program) {
|
|
|
1821
2066
|
aptosNetwork: aptosNetwork2
|
|
1822
2067
|
}) => {
|
|
1823
2068
|
if (shelbyRpcEndpoint2) {
|
|
1824
|
-
config.contexts[contextName].shelby_rpc_endpoint = shelbyRpcEndpoint2;
|
|
2069
|
+
config.contexts[contextName].shelby_rpc_endpoint = sanitizeRpcUrl(shelbyRpcEndpoint2);
|
|
1825
2070
|
}
|
|
1826
2071
|
if (aptosNetwork2) {
|
|
1827
2072
|
config.contexts[contextName].aptos_network = aptosNetwork2;
|
|
@@ -1908,22 +2153,21 @@ function contextCommand(program) {
|
|
|
1908
2153
|
|
|
1909
2154
|
// src/commands/download.tsx
|
|
1910
2155
|
import * as fsS from "fs";
|
|
1911
|
-
import * as
|
|
2156
|
+
import * as fs3 from "fs/promises";
|
|
1912
2157
|
import * as path3 from "path";
|
|
1913
|
-
import {
|
|
2158
|
+
import { Readable as Readable2, Transform } from "stream";
|
|
1914
2159
|
import { pipeline } from "stream/promises";
|
|
1915
|
-
import { Aptos as Aptos4 } from "@aptos-labs/ts-sdk";
|
|
1916
2160
|
import ora from "ora";
|
|
1917
|
-
import { z as
|
|
2161
|
+
import { z as z9 } from "zod";
|
|
1918
2162
|
var denormBlobName2 = (a, b, c) => denormBlobName(path3, a, b, c);
|
|
1919
2163
|
var endsWithDirectorySeparator = (filePath) => {
|
|
1920
2164
|
return filePath.endsWith("/") || filePath.endsWith("\\") || filePath.endsWith(path3.sep);
|
|
1921
2165
|
};
|
|
1922
|
-
var DownloadOptionsSchema =
|
|
1923
|
-
input:
|
|
1924
|
-
output:
|
|
1925
|
-
recursive:
|
|
1926
|
-
force:
|
|
2166
|
+
var DownloadOptionsSchema = z9.object({
|
|
2167
|
+
input: z9.string().min(1, "Input must be a valid blob name or directory prefix").describe("Blob name or directory prefix to download"),
|
|
2168
|
+
output: z9.string().min(1, "Output must be a valid filepath").describe("Local path where to save the downloaded content"),
|
|
2169
|
+
recursive: z9.boolean().default(false).describe("Download assuming canonical directory layout and recurse"),
|
|
2170
|
+
force: z9.boolean().default(false).describe("Overwrite the output if it already exists")
|
|
1927
2171
|
}).refine(
|
|
1928
2172
|
(data) => {
|
|
1929
2173
|
if (data.recursive) {
|
|
@@ -1952,7 +2196,7 @@ var DownloadOptionsSchema = z8.object({
|
|
|
1952
2196
|
async function validateOutput(options) {
|
|
1953
2197
|
const parentDir = path3.dirname(options.output);
|
|
1954
2198
|
try {
|
|
1955
|
-
const parentStats = await
|
|
2199
|
+
const parentStats = await fs3.stat(parentDir);
|
|
1956
2200
|
if (!parentStats.isDirectory()) {
|
|
1957
2201
|
throw new Error(
|
|
1958
2202
|
`Parent path '${parentDir}' exists but is not a directory. Cannot create output ${options.recursive ? "directory" : "file"} '${options.output}'.`
|
|
@@ -1969,7 +2213,7 @@ async function validateOutput(options) {
|
|
|
1969
2213
|
if (options.force) return;
|
|
1970
2214
|
let outputStats;
|
|
1971
2215
|
try {
|
|
1972
|
-
outputStats = await
|
|
2216
|
+
outputStats = await fs3.stat(options.output);
|
|
1973
2217
|
} catch (error) {
|
|
1974
2218
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
1975
2219
|
return;
|
|
@@ -1988,7 +2232,7 @@ async function validateOutput(options) {
|
|
|
1988
2232
|
);
|
|
1989
2233
|
}
|
|
1990
2234
|
if (options.recursive) {
|
|
1991
|
-
const entries = await
|
|
2235
|
+
const entries = await fs3.readdir(options.output);
|
|
1992
2236
|
if (entries.length > 0) {
|
|
1993
2237
|
throw new Error(
|
|
1994
2238
|
`Directory '${options.output}' exists and is not empty. Use --force to overwrite or choose an empty directory.`
|
|
@@ -2000,10 +2244,12 @@ async function validateOutput(options) {
|
|
|
2000
2244
|
);
|
|
2001
2245
|
}
|
|
2002
2246
|
}
|
|
2003
|
-
async function createFileList(options, nodeClient,
|
|
2247
|
+
async function createFileList(options, nodeClient, account) {
|
|
2004
2248
|
const matchingBlobList = [];
|
|
2005
2249
|
if (options.recursive) {
|
|
2006
|
-
const allBlobs = await
|
|
2250
|
+
const allBlobs = await nodeClient.coordination.getAccountBlobs({
|
|
2251
|
+
account
|
|
2252
|
+
});
|
|
2007
2253
|
for (const blobMd of allBlobs) {
|
|
2008
2254
|
if (!blobMd.name.startsWith(options.input)) continue;
|
|
2009
2255
|
matchingBlobList.push(blobMd);
|
|
@@ -2014,12 +2260,12 @@ async function createFileList(options, nodeClient, blobClient, account) {
|
|
|
2014
2260
|
);
|
|
2015
2261
|
}
|
|
2016
2262
|
} else {
|
|
2017
|
-
const md = await
|
|
2263
|
+
const md = await nodeClient.coordination.getBlobMetadata({
|
|
2018
2264
|
account,
|
|
2019
2265
|
name: options.input
|
|
2020
2266
|
});
|
|
2021
2267
|
if (md === void 0) {
|
|
2022
|
-
throw new Error(`Could not find a blob with name ${
|
|
2268
|
+
throw new Error(`Could not find a blob with name ${options.input}`);
|
|
2023
2269
|
}
|
|
2024
2270
|
matchingBlobList.push(md);
|
|
2025
2271
|
}
|
|
@@ -2042,7 +2288,7 @@ async function createOutputDirectories(fileList) {
|
|
|
2042
2288
|
}
|
|
2043
2289
|
for (const dir of uniqueDirectories) {
|
|
2044
2290
|
try {
|
|
2045
|
-
await
|
|
2291
|
+
await fs3.mkdir(dir, { recursive: true });
|
|
2046
2292
|
} catch (error) {
|
|
2047
2293
|
throw new Error(
|
|
2048
2294
|
`Failed to create directory '${dir}': ${error instanceof Error ? error.message : error}`
|
|
@@ -2053,7 +2299,7 @@ async function createOutputDirectories(fileList) {
|
|
|
2053
2299
|
function createProgressTransform(totalBytes, reporter) {
|
|
2054
2300
|
const startTime = performance.now();
|
|
2055
2301
|
let bytesDownloaded = 0;
|
|
2056
|
-
return new
|
|
2302
|
+
return new Transform({
|
|
2057
2303
|
transform(chunk, _, callback) {
|
|
2058
2304
|
bytesDownloaded += chunk.length;
|
|
2059
2305
|
const now = performance.now();
|
|
@@ -2102,13 +2348,10 @@ function downloadCommand(program) {
|
|
|
2102
2348
|
config,
|
|
2103
2349
|
program.opts().account
|
|
2104
2350
|
).account;
|
|
2105
|
-
const aptos = new Aptos4(shelbyConfig.aptos.config);
|
|
2106
2351
|
const nodeClient = new ShelbyNodeClient(shelbyConfig);
|
|
2107
|
-
const blobClient = new ShelbyBlobClient({ aptos });
|
|
2108
2352
|
const fileList = await createFileList(
|
|
2109
2353
|
options,
|
|
2110
2354
|
nodeClient,
|
|
2111
|
-
blobClient,
|
|
2112
2355
|
activeAccount.accountAddress
|
|
2113
2356
|
);
|
|
2114
2357
|
for (const fileEntry of fileList) {
|
|
@@ -2118,7 +2361,7 @@ function downloadCommand(program) {
|
|
|
2118
2361
|
}
|
|
2119
2362
|
if (options.force) {
|
|
2120
2363
|
console.log(`--force was set, so deleting ${options.output}`);
|
|
2121
|
-
await
|
|
2364
|
+
await fs3.rm(options.output, { recursive: true, force: true });
|
|
2122
2365
|
}
|
|
2123
2366
|
const handleSigint = () => {
|
|
2124
2367
|
spinner.fail("Quitting due to ctrl-C / SIGINT...");
|
|
@@ -2143,15 +2386,16 @@ function downloadCommand(program) {
|
|
|
2143
2386
|
};
|
|
2144
2387
|
for (const fileEntry of fileList) {
|
|
2145
2388
|
const out = fsS.createWriteStream(fileEntry.filename);
|
|
2146
|
-
const {
|
|
2147
|
-
activeAccount.accountAddress,
|
|
2148
|
-
fileEntry.blobname
|
|
2149
|
-
);
|
|
2389
|
+
const { readable } = await nodeClient.rpc.getBlob({
|
|
2390
|
+
account: activeAccount.accountAddress,
|
|
2391
|
+
blobName: fileEntry.blobname
|
|
2392
|
+
});
|
|
2150
2393
|
const reporter = (filePercent, rateMiB) => {
|
|
2151
2394
|
spinner.text = `Downloading ${fileEntry.blobname}, ${filePercent}% at ${rateMiB} MiB/s .. (Overall: ${formatProgressPercent()}%, ${formatProgressRate()} MiB/s)`;
|
|
2152
2395
|
};
|
|
2396
|
+
const nodeStream = Readable2.fromWeb(readable);
|
|
2153
2397
|
await pipeline(
|
|
2154
|
-
|
|
2398
|
+
nodeStream,
|
|
2155
2399
|
createProgressTransform(fileEntry.sizeBytes, reporter),
|
|
2156
2400
|
out
|
|
2157
2401
|
);
|
|
@@ -2164,16 +2408,196 @@ function downloadCommand(program) {
|
|
|
2164
2408
|
);
|
|
2165
2409
|
}
|
|
2166
2410
|
|
|
2411
|
+
// src/commands/faucet.tsx
|
|
2412
|
+
import { execaSync } from "execa";
|
|
2413
|
+
import { z as z10 } from "zod";
|
|
2414
|
+
var FaucetOptionsSchema = z10.object({
|
|
2415
|
+
network: z10.enum(["devnet", "testnet", "mainnet"]).optional(),
|
|
2416
|
+
"no-open": z10.boolean().optional().default(false)
|
|
2417
|
+
});
|
|
2418
|
+
function faucetCommand(program) {
|
|
2419
|
+
program.command("faucet").description("Open the Shelby faucet web page to request tokens").option(
|
|
2420
|
+
"--network <network>",
|
|
2421
|
+
"Network to request tokens for (devnet, testnet)"
|
|
2422
|
+
).option("--no-open", "Don't automatically open browser, just print the URL").action((options) => {
|
|
2423
|
+
try {
|
|
2424
|
+
const validatedOptions = FaucetOptionsSchema.parse(options);
|
|
2425
|
+
const configPath = program.opts().configFile;
|
|
2426
|
+
const config = loadConfig(configPath);
|
|
2427
|
+
const accountName = program.opts().account || config.default_account;
|
|
2428
|
+
const { account } = getCurrentAccount(config, accountName);
|
|
2429
|
+
const network = validatedOptions.network || "devnet";
|
|
2430
|
+
if (network === "mainnet") {
|
|
2431
|
+
throw new Error(
|
|
2432
|
+
"\u274C No faucet available for mainnet. Mainnet tokens must be obtained through other means."
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
const faucetUrl = new URL("https://docs.shelby.xyz/docs/faucet");
|
|
2436
|
+
faucetUrl.searchParams.set(
|
|
2437
|
+
"address",
|
|
2438
|
+
account.accountAddress.toString()
|
|
2439
|
+
);
|
|
2440
|
+
faucetUrl.searchParams.set("network", network);
|
|
2441
|
+
const urlString = faucetUrl.toString();
|
|
2442
|
+
if (validatedOptions["no-open"]) {
|
|
2443
|
+
console.log("\u{1F310} Faucet URL:");
|
|
2444
|
+
console.log(urlString);
|
|
2445
|
+
console.log(
|
|
2446
|
+
"\nCopy and paste this URL into your browser to request tokens."
|
|
2447
|
+
);
|
|
2448
|
+
} else {
|
|
2449
|
+
console.log(`\u{1F4A7} Opening Shelby faucet for ${network}...`);
|
|
2450
|
+
console.log(
|
|
2451
|
+
`\u{1F3E6} Pre-filled address: ${account.accountAddress.toString()}`
|
|
2452
|
+
);
|
|
2453
|
+
try {
|
|
2454
|
+
openBrowser(urlString);
|
|
2455
|
+
console.log("\u2705 Browser opened successfully!");
|
|
2456
|
+
} catch (_error) {
|
|
2457
|
+
console.log("\u274C Failed to open browser automatically.");
|
|
2458
|
+
console.log("\u{1F310} Please copy and open this URL manually:");
|
|
2459
|
+
console.log(urlString);
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
} catch (error) {
|
|
2463
|
+
console.error(
|
|
2464
|
+
`\u274C Faucet command failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2465
|
+
);
|
|
2466
|
+
process.exit(1);
|
|
2467
|
+
}
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
function openBrowser(url) {
|
|
2471
|
+
const platform = process.platform;
|
|
2472
|
+
try {
|
|
2473
|
+
if (platform === "darwin") {
|
|
2474
|
+
execaSync("open", [url]);
|
|
2475
|
+
} else if (platform === "win32") {
|
|
2476
|
+
execaSync("start", [url], { shell: true });
|
|
2477
|
+
} else {
|
|
2478
|
+
execaSync("xdg-open", [url]);
|
|
2479
|
+
}
|
|
2480
|
+
} catch (error) {
|
|
2481
|
+
throw new Error(
|
|
2482
|
+
`Failed to open browser: ${error instanceof Error ? error.message : String(error)}`
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
// src/commands/init.tsx
|
|
2488
|
+
import { render as render3 } from "ink";
|
|
2489
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2490
|
+
function initCommand(program) {
|
|
2491
|
+
program.command("init").description(
|
|
2492
|
+
"Bootstrap your Shelby config via an interactive wizard or flags"
|
|
2493
|
+
).option(
|
|
2494
|
+
"--setup-default-contexts",
|
|
2495
|
+
"Create devnet, testnet, mainnet contexts",
|
|
2496
|
+
false
|
|
2497
|
+
).option("--context <name>", "Custom context name").option(
|
|
2498
|
+
"--shelby-rpc-endpoint <url>",
|
|
2499
|
+
"Shelby RPC endpoint for this context"
|
|
2500
|
+
).option(
|
|
2501
|
+
"--aptos-api-endpoint <url>",
|
|
2502
|
+
"Aptos REST API endpoint for this context"
|
|
2503
|
+
).option(
|
|
2504
|
+
"--account <name>",
|
|
2505
|
+
"Account name to create/update",
|
|
2506
|
+
"default_account"
|
|
2507
|
+
).option(
|
|
2508
|
+
"--signature-scheme <scheme>",
|
|
2509
|
+
// "Signature scheme (ed25519 or secp256k1)",
|
|
2510
|
+
"Signature scheme (ed25519)",
|
|
2511
|
+
ED25519_NAME
|
|
2512
|
+
).option("--private-key <key>", "Raw private key").action((options) => {
|
|
2513
|
+
const configPath = program.opts().configFile || "~/.shelby/config.yaml";
|
|
2514
|
+
if (options.setupDefaultContexts || options.context && options.shelbyRpcEndpoint && options.aptosNetwork) {
|
|
2515
|
+
let config;
|
|
2516
|
+
try {
|
|
2517
|
+
config = loadConfig(configPath);
|
|
2518
|
+
} catch (_error) {
|
|
2519
|
+
config = {
|
|
2520
|
+
contexts: {},
|
|
2521
|
+
accounts: {},
|
|
2522
|
+
default_context: options.setupDefaultContexts ? "devnet" : options.context,
|
|
2523
|
+
default_account: options.account
|
|
2524
|
+
};
|
|
2525
|
+
}
|
|
2526
|
+
if (options.setupDefaultContexts) {
|
|
2527
|
+
config.contexts.local = {
|
|
2528
|
+
aptos_network: "local",
|
|
2529
|
+
shelby_rpc_endpoint: "http://localhost:9090"
|
|
2530
|
+
};
|
|
2531
|
+
config.contexts.devnet = {
|
|
2532
|
+
aptos_network: "devnet",
|
|
2533
|
+
shelby_rpc_endpoint: "https://shelby.rpc.devnet.example.com"
|
|
2534
|
+
};
|
|
2535
|
+
config.contexts.testnet = {
|
|
2536
|
+
aptos_network: "testnet",
|
|
2537
|
+
shelby_rpc_endpoint: "https://shelby.rpc.testnet.example.com"
|
|
2538
|
+
};
|
|
2539
|
+
config.contexts.mainnet = {
|
|
2540
|
+
aptos_network: "mainnet",
|
|
2541
|
+
shelby_rpc_endpoint: "https://shelby.rpc.mainnet.example.com"
|
|
2542
|
+
};
|
|
2543
|
+
}
|
|
2544
|
+
if (options.context && options.shelbyRpcEndpoint && options.aptosNetwork) {
|
|
2545
|
+
config.contexts[options.context] = {
|
|
2546
|
+
aptos_network: options.aptosNetwork,
|
|
2547
|
+
shelby_rpc_endpoint: options.shelbyRpcEndpoint
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2550
|
+
if (options.privateKey) {
|
|
2551
|
+
config.accounts[options.account] = {
|
|
2552
|
+
private_key: options.privateKey
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
saveConfig(config, configPath);
|
|
2556
|
+
console.log(
|
|
2557
|
+
`\u2705 Configuration saved to ${resolveConfigPath(configPath)}`
|
|
2558
|
+
);
|
|
2559
|
+
} else {
|
|
2560
|
+
const { unmount } = render3(
|
|
2561
|
+
/* @__PURE__ */ jsx7(
|
|
2562
|
+
InitWizard,
|
|
2563
|
+
{
|
|
2564
|
+
onComplete: (config) => {
|
|
2565
|
+
saveConfig(config, configPath);
|
|
2566
|
+
console.log(
|
|
2567
|
+
`\u2705 Configuration saved to ${resolveConfigPath(configPath)}`
|
|
2568
|
+
);
|
|
2569
|
+
if (config.default_account && config.accounts[config.default_account]?.private_key?.startsWith("ed25519-priv-")) {
|
|
2570
|
+
console.log(
|
|
2571
|
+
"\n\u2139\uFE0F To fund your new account on-chain (devnet/testnet only):"
|
|
2572
|
+
);
|
|
2573
|
+
console.log(" 1. Import the private key into Aptos CLI:");
|
|
2574
|
+
console.log(
|
|
2575
|
+
` aptos init --profile ${config.default_account} --private-key ${config.accounts[config.default_account].private_key} --network ${config.default_context}`
|
|
2576
|
+
);
|
|
2577
|
+
console.log(" 2. Run the faucet:");
|
|
2578
|
+
console.log(
|
|
2579
|
+
` aptos account fund-with-faucet --profile ${config.default_account}`
|
|
2580
|
+
);
|
|
2581
|
+
}
|
|
2582
|
+
unmount();
|
|
2583
|
+
process.exit(0);
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
)
|
|
2587
|
+
);
|
|
2588
|
+
}
|
|
2589
|
+
});
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2167
2592
|
// src/commands/upload.tsx
|
|
2168
|
-
import * as
|
|
2593
|
+
import * as fs4 from "fs/promises";
|
|
2169
2594
|
import * as path4 from "path";
|
|
2170
|
-
import {
|
|
2171
|
-
import { Aptos as Aptos5 } from "@aptos-labs/ts-sdk";
|
|
2595
|
+
import { Aptos as Aptos3 } from "@aptos-labs/ts-sdk";
|
|
2172
2596
|
import { glob } from "glob";
|
|
2173
|
-
import { Box as Box5,
|
|
2597
|
+
import { Box as Box5, render as render4, Text as Text5 } from "ink";
|
|
2174
2598
|
import SelectInput2 from "ink-select-input";
|
|
2175
2599
|
import ora2 from "ora";
|
|
2176
|
-
import { z as
|
|
2600
|
+
import { z as z11 } from "zod";
|
|
2177
2601
|
|
|
2178
2602
|
// src/utils/errors.ts
|
|
2179
2603
|
var ERROR_CODES = {
|
|
@@ -2246,7 +2670,7 @@ var handleError = (error) => {
|
|
|
2246
2670
|
// src/commands/upload.tsx
|
|
2247
2671
|
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2248
2672
|
var normBlobName2 = (i, f, b) => normBlobName(path4, i, f, b);
|
|
2249
|
-
var flexibleDateSchema =
|
|
2673
|
+
var flexibleDateSchema = z11.string().transform((val) => {
|
|
2250
2674
|
if (/^\d+$/.test(val)) {
|
|
2251
2675
|
const timestamp = Number.parseInt(val, 10);
|
|
2252
2676
|
if (timestamp > 0 && timestamp < 4102444800) {
|
|
@@ -2259,18 +2683,18 @@ var flexibleDateSchema = z9.string().transform((val) => {
|
|
|
2259
2683
|
}
|
|
2260
2684
|
return ret;
|
|
2261
2685
|
});
|
|
2262
|
-
var UploadOptionsSchema =
|
|
2263
|
-
input:
|
|
2264
|
-
output:
|
|
2686
|
+
var UploadOptionsSchema = z11.object({
|
|
2687
|
+
input: z11.string().nonempty("`--input` is required"),
|
|
2688
|
+
output: z11.string().nonempty("`output` is required"),
|
|
2265
2689
|
expiration: flexibleDateSchema,
|
|
2266
|
-
recursive:
|
|
2267
|
-
assumeYes:
|
|
2268
|
-
outputCommitments:
|
|
2690
|
+
recursive: z11.boolean().optional().default(false),
|
|
2691
|
+
assumeYes: z11.boolean().optional().default(false),
|
|
2692
|
+
outputCommitments: z11.string().optional()
|
|
2269
2693
|
}).superRefine(async (data, ctx) => {
|
|
2270
|
-
const stats = await
|
|
2694
|
+
const stats = await fs4.stat(data.input);
|
|
2271
2695
|
if (!stats.isFile() && !stats.isDirectory()) {
|
|
2272
2696
|
ctx.addIssue({
|
|
2273
|
-
code:
|
|
2697
|
+
code: z11.ZodIssueCode.custom,
|
|
2274
2698
|
message: "`--input` must be a file or a directory",
|
|
2275
2699
|
path: ["input"]
|
|
2276
2700
|
});
|
|
@@ -2279,7 +2703,7 @@ var UploadOptionsSchema = z9.object({
|
|
|
2279
2703
|
if (stats.isDirectory()) {
|
|
2280
2704
|
if (!data.output.endsWith("/")) {
|
|
2281
2705
|
ctx.addIssue({
|
|
2282
|
-
code:
|
|
2706
|
+
code: z11.ZodIssueCode.custom,
|
|
2283
2707
|
message: "When input is a directory, output must end with '/'",
|
|
2284
2708
|
path: ["output"]
|
|
2285
2709
|
});
|
|
@@ -2288,7 +2712,7 @@ var UploadOptionsSchema = z9.object({
|
|
|
2288
2712
|
const blobNameResult = BlobNameSchema.safeParse(data.output);
|
|
2289
2713
|
if (!blobNameResult.success) {
|
|
2290
2714
|
ctx.addIssue({
|
|
2291
|
-
code:
|
|
2715
|
+
code: z11.ZodIssueCode.custom,
|
|
2292
2716
|
message: "When input is a file, output must be a valid blob name (cannot end with '/')",
|
|
2293
2717
|
path: ["output"]
|
|
2294
2718
|
});
|
|
@@ -2296,7 +2720,7 @@ var UploadOptionsSchema = z9.object({
|
|
|
2296
2720
|
}
|
|
2297
2721
|
});
|
|
2298
2722
|
async function createFilelist(options) {
|
|
2299
|
-
const stats = await
|
|
2723
|
+
const stats = await fs4.stat(options.input);
|
|
2300
2724
|
if (stats.isFile()) {
|
|
2301
2725
|
const blobname = normBlobName2(options.input, options.input, options.output);
|
|
2302
2726
|
const blobNameValidation = BlobNameSchema.safeParse(blobname);
|
|
@@ -2317,7 +2741,7 @@ async function createFilelist(options) {
|
|
|
2317
2741
|
nodir: true
|
|
2318
2742
|
});
|
|
2319
2743
|
for await (const file of result) {
|
|
2320
|
-
const stats2 = await
|
|
2744
|
+
const stats2 = await fs4.stat(file);
|
|
2321
2745
|
const blobname = normBlobName2(options.input, file, options.output);
|
|
2322
2746
|
const blobNameValidation = BlobNameSchema.safeParse(blobname);
|
|
2323
2747
|
if (!blobNameValidation.success) {
|
|
@@ -2407,13 +2831,12 @@ function uploadCommand(program) {
|
|
|
2407
2831
|
const shelbyConfig = getCurrentShelbyConfig(config, {
|
|
2408
2832
|
context: program.opts().context
|
|
2409
2833
|
});
|
|
2410
|
-
const shelbyNodeClient = new ShelbyNodeClient(shelbyConfig);
|
|
2411
2834
|
const activeAccount = getCurrentAccount(
|
|
2412
2835
|
config,
|
|
2413
2836
|
program.opts().account
|
|
2414
2837
|
).account;
|
|
2415
|
-
const aptos = new
|
|
2416
|
-
const
|
|
2838
|
+
const aptos = new Aptos3(shelbyConfig.aptos.config);
|
|
2839
|
+
const shelbyClient = new ShelbyNodeClient(shelbyConfig);
|
|
2417
2840
|
const handleSigint = () => {
|
|
2418
2841
|
spinner.fail("Quitting due to ctrl-C / SIGINT...");
|
|
2419
2842
|
process.exit(1);
|
|
@@ -2441,30 +2864,29 @@ function uploadCommand(program) {
|
|
|
2441
2864
|
for (const entry of filelist) {
|
|
2442
2865
|
totalSize += entry.sizeBytes;
|
|
2443
2866
|
}
|
|
2444
|
-
|
|
2867
|
+
const hasUploadedBlob = false;
|
|
2445
2868
|
for (const entry of filelist) {
|
|
2446
2869
|
spinner.text = `Reading ${entry.filename}.. (Overall: ${formatProgressPercent()}%, ${formatProgressRate()} MiB/s)`;
|
|
2447
2870
|
try {
|
|
2448
|
-
const blobData = await
|
|
2871
|
+
const blobData = await fs4.readFile(entry.filename);
|
|
2449
2872
|
if (blobData.length !== entry.sizeBytes) {
|
|
2450
2873
|
throw new Error(
|
|
2451
2874
|
`Size of file ${entry.filename} changed after initial scan. Original size was ${entry.sizeBytes} but it is now ${blobData.length}`
|
|
2452
2875
|
);
|
|
2453
2876
|
}
|
|
2454
2877
|
spinner.text = `Committing ${entry.filename} to L1.. (Overall: ${formatProgressPercent()}%, ${formatProgressRate()} MiB/s)`;
|
|
2455
|
-
const existingBlobMetadata = await
|
|
2878
|
+
const existingBlobMetadata = await shelbyClient.coordination.getBlobMetadata({
|
|
2456
2879
|
account: activeAccount.accountAddress,
|
|
2457
2880
|
name: entry.blobname
|
|
2458
2881
|
});
|
|
2459
|
-
const blobCommitments = await generateCommitments(
|
|
2460
|
-
Readable4.from(blobData)
|
|
2461
|
-
);
|
|
2882
|
+
const blobCommitments = await generateCommitments(blobData);
|
|
2462
2883
|
if (!existingBlobMetadata) {
|
|
2463
|
-
const { transaction: pendingWriteBlobCommitmentsTransaction } = await
|
|
2884
|
+
const { transaction: pendingWriteBlobCommitmentsTransaction } = await shelbyClient.coordination.registerBlob({
|
|
2464
2885
|
account: activeAccount,
|
|
2465
2886
|
blobName: entry.blobname,
|
|
2466
|
-
|
|
2467
|
-
|
|
2887
|
+
blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
2888
|
+
size: blobData.length,
|
|
2889
|
+
expirationMicros: validatedOptions.expiration.getTime() * 1e3
|
|
2468
2890
|
});
|
|
2469
2891
|
await aptos.waitForTransaction({
|
|
2470
2892
|
transactionHash: pendingWriteBlobCommitmentsTransaction.hash
|
|
@@ -2475,29 +2897,6 @@ function uploadCommand(program) {
|
|
|
2475
2897
|
if (validatedOptions.outputCommitments) {
|
|
2476
2898
|
outputCommitments[entry.filename] = blobCommitments;
|
|
2477
2899
|
}
|
|
2478
|
-
const existingBlobChunks = await shelbyBlobClient.getBlobChunks({
|
|
2479
|
-
account: activeAccount.accountAddress,
|
|
2480
|
-
name: entry.blobname
|
|
2481
|
-
});
|
|
2482
|
-
if (existingBlobChunks.length === 0) {
|
|
2483
|
-
console.error(
|
|
2484
|
-
`Blob ${entry.blobname} does not exist on L1, an error occurred when uploading commitments...`
|
|
2485
|
-
);
|
|
2486
|
-
process.exit(1);
|
|
2487
|
-
}
|
|
2488
|
-
if (!existingBlobChunks.every(
|
|
2489
|
-
(chunk) => chunk.location.variant === "stored"
|
|
2490
|
-
)) {
|
|
2491
|
-
spinner.text = `Uploading ${entry.filename} to Shelby RPC.. (Overall: ${formatProgressPercent()}%, ${formatProgressRate()} MiB/s)`;
|
|
2492
|
-
await shelbyNodeClient.putBlob(
|
|
2493
|
-
activeAccount.accountAddress,
|
|
2494
|
-
entry.blobname,
|
|
2495
|
-
blobData
|
|
2496
|
-
);
|
|
2497
|
-
hasUploadedBlob = true;
|
|
2498
|
-
} else {
|
|
2499
|
-
spinner.text = "All blob chunks have been stored on L1, skipping upload to Shelby RPC...";
|
|
2500
|
-
}
|
|
2501
2900
|
amountUploaded += blobData.length;
|
|
2502
2901
|
} catch (error) {
|
|
2503
2902
|
const { displayMessage } = handleError(error);
|
|
@@ -2506,7 +2905,7 @@ function uploadCommand(program) {
|
|
|
2506
2905
|
}
|
|
2507
2906
|
}
|
|
2508
2907
|
if (validatedOptions.outputCommitments) {
|
|
2509
|
-
await
|
|
2908
|
+
await fs4.writeFile(
|
|
2510
2909
|
validatedOptions.outputCommitments,
|
|
2511
2910
|
JSON.stringify(outputCommitments)
|
|
2512
2911
|
);
|
|
@@ -2521,33 +2920,6 @@ function uploadCommand(program) {
|
|
|
2521
2920
|
});
|
|
2522
2921
|
}
|
|
2523
2922
|
|
|
2524
|
-
// src/commands/commitment.ts
|
|
2525
|
-
import * as fs4 from "fs";
|
|
2526
|
-
import * as fsP from "fs/promises";
|
|
2527
|
-
import { z as z10 } from "zod";
|
|
2528
|
-
var CommitmentOptionsSchema = z10.object({
|
|
2529
|
-
input: z10.string().nonempty("`--input` is required").refine(
|
|
2530
|
-
async (path5) => {
|
|
2531
|
-
const stat4 = await fsP.stat(path5);
|
|
2532
|
-
return stat4.isFile();
|
|
2533
|
-
},
|
|
2534
|
-
{
|
|
2535
|
-
message: "`--input` must be a file"
|
|
2536
|
-
}
|
|
2537
|
-
),
|
|
2538
|
-
output: z10.string().nonempty("`--output` is required")
|
|
2539
|
-
});
|
|
2540
|
-
function commitmentCommand(program) {
|
|
2541
|
-
program.command("commitment").description(
|
|
2542
|
-
"Compute commitments for a file place into an output JSON file. Intended for debugging and introspection."
|
|
2543
|
-
).requiredOption("-i, --input <path>", "Path to a file").requiredOption("-o, --output <path>", "Path to a file").action(async (rawOptions) => {
|
|
2544
|
-
const validatedOptions = await CommitmentOptionsSchema.parseAsync(rawOptions);
|
|
2545
|
-
const input = fs4.createReadStream(validatedOptions.input);
|
|
2546
|
-
const commitment = await generateCommitments(input);
|
|
2547
|
-
await fsP.writeFile(validatedOptions.output, JSON.stringify(commitment));
|
|
2548
|
-
});
|
|
2549
|
-
}
|
|
2550
|
-
|
|
2551
2923
|
// src/cli.tsx
|
|
2552
2924
|
function createProgram() {
|
|
2553
2925
|
const config = loadConfig();
|
|
@@ -2571,6 +2943,7 @@ function createProgram() {
|
|
|
2571
2943
|
accountCommand(program);
|
|
2572
2944
|
contextCommand(program);
|
|
2573
2945
|
downloadCommand(program);
|
|
2946
|
+
faucetCommand(program);
|
|
2574
2947
|
uploadCommand(program);
|
|
2575
2948
|
commitmentCommand(program);
|
|
2576
2949
|
return program;
|