@silvana-one/storage 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +1 -0
  2. package/dist/node/base64/bigint.d.ts +6 -0
  3. package/dist/node/base64/bigint.js +83 -0
  4. package/dist/node/base64/bigint.js.map +1 -0
  5. package/dist/node/base64/field.d.ts +5 -0
  6. package/dist/node/base64/field.js +29 -0
  7. package/dist/node/base64/field.js.map +1 -0
  8. package/dist/node/base64/index.d.ts +2 -0
  9. package/dist/node/base64/index.js +3 -0
  10. package/dist/node/base64/index.js.map +1 -0
  11. package/dist/node/index.cjs +735 -0
  12. package/dist/node/index.d.ts +5 -0
  13. package/dist/node/index.js +6 -0
  14. package/dist/node/index.js.map +1 -0
  15. package/dist/node/indexed-map/index.d.ts +1 -0
  16. package/dist/node/indexed-map/index.js +2 -0
  17. package/dist/node/indexed-map/index.js.map +1 -0
  18. package/dist/node/indexed-map/indexed-map.d.ts +39 -0
  19. package/dist/node/indexed-map/indexed-map.js +125 -0
  20. package/dist/node/indexed-map/indexed-map.js.map +1 -0
  21. package/dist/node/storage/index.d.ts +3 -0
  22. package/dist/node/storage/index.js +4 -0
  23. package/dist/node/storage/index.js.map +1 -0
  24. package/dist/node/storage/ipfs.d.ts +5 -0
  25. package/dist/node/storage/ipfs.js +16 -0
  26. package/dist/node/storage/ipfs.js.map +1 -0
  27. package/dist/node/storage/pinata.d.ts +6 -0
  28. package/dist/node/storage/pinata.js +40 -0
  29. package/dist/node/storage/pinata.js.map +1 -0
  30. package/dist/node/storage/storage.d.ts +78 -0
  31. package/dist/node/storage/storage.js +60 -0
  32. package/dist/node/storage/storage.js.map +1 -0
  33. package/dist/node/util/index.d.ts +1 -0
  34. package/dist/node/util/index.js +2 -0
  35. package/dist/node/util/index.js.map +1 -0
  36. package/dist/node/util/sleep.d.ts +1 -0
  37. package/dist/node/util/sleep.js +4 -0
  38. package/dist/node/util/sleep.js.map +1 -0
  39. package/dist/node/whitelist/index.d.ts +2 -0
  40. package/dist/node/whitelist/index.js +3 -0
  41. package/dist/node/whitelist/index.js.map +1 -0
  42. package/dist/node/whitelist/offchain-map.d.ts +352 -0
  43. package/dist/node/whitelist/offchain-map.js +247 -0
  44. package/dist/node/whitelist/offchain-map.js.map +1 -0
  45. package/dist/node/whitelist/whitelist.d.ts +122 -0
  46. package/dist/node/whitelist/whitelist.js +98 -0
  47. package/dist/node/whitelist/whitelist.js.map +1 -0
  48. package/dist/tsconfig.tsbuildinfo +1 -0
  49. package/dist/tsconfig.web.tsbuildinfo +1 -0
  50. package/dist/web/base64/bigint.d.ts +6 -0
  51. package/dist/web/base64/bigint.js +83 -0
  52. package/dist/web/base64/bigint.js.map +1 -0
  53. package/dist/web/base64/field.d.ts +5 -0
  54. package/dist/web/base64/field.js +29 -0
  55. package/dist/web/base64/field.js.map +1 -0
  56. package/dist/web/base64/index.d.ts +2 -0
  57. package/dist/web/base64/index.js +3 -0
  58. package/dist/web/base64/index.js.map +1 -0
  59. package/dist/web/index.d.ts +5 -0
  60. package/dist/web/index.js +6 -0
  61. package/dist/web/index.js.map +1 -0
  62. package/dist/web/indexed-map/index.d.ts +1 -0
  63. package/dist/web/indexed-map/index.js +2 -0
  64. package/dist/web/indexed-map/index.js.map +1 -0
  65. package/dist/web/indexed-map/indexed-map.d.ts +39 -0
  66. package/dist/web/indexed-map/indexed-map.js +125 -0
  67. package/dist/web/indexed-map/indexed-map.js.map +1 -0
  68. package/dist/web/storage/index.d.ts +3 -0
  69. package/dist/web/storage/index.js +4 -0
  70. package/dist/web/storage/index.js.map +1 -0
  71. package/dist/web/storage/ipfs.d.ts +5 -0
  72. package/dist/web/storage/ipfs.js +16 -0
  73. package/dist/web/storage/ipfs.js.map +1 -0
  74. package/dist/web/storage/pinata.d.ts +6 -0
  75. package/dist/web/storage/pinata.js +40 -0
  76. package/dist/web/storage/pinata.js.map +1 -0
  77. package/dist/web/storage/storage.d.ts +78 -0
  78. package/dist/web/storage/storage.js +60 -0
  79. package/dist/web/storage/storage.js.map +1 -0
  80. package/dist/web/util/index.d.ts +1 -0
  81. package/dist/web/util/index.js +2 -0
  82. package/dist/web/util/index.js.map +1 -0
  83. package/dist/web/util/sleep.d.ts +1 -0
  84. package/dist/web/util/sleep.js +4 -0
  85. package/dist/web/util/sleep.js.map +1 -0
  86. package/dist/web/whitelist/index.d.ts +2 -0
  87. package/dist/web/whitelist/index.js +3 -0
  88. package/dist/web/whitelist/index.js.map +1 -0
  89. package/dist/web/whitelist/offchain-map.d.ts +352 -0
  90. package/dist/web/whitelist/offchain-map.js +247 -0
  91. package/dist/web/whitelist/offchain-map.js.map +1 -0
  92. package/dist/web/whitelist/whitelist.d.ts +122 -0
  93. package/dist/web/whitelist/whitelist.js +98 -0
  94. package/dist/web/whitelist/whitelist.js.map +1 -0
  95. package/package.json +60 -0
  96. package/src/base64/bigint.ts +87 -0
  97. package/src/base64/field.ts +34 -0
  98. package/src/base64/index.ts +2 -0
  99. package/src/index.ts +5 -0
  100. package/src/indexed-map/index.ts +1 -0
  101. package/src/indexed-map/indexed-map.ts +189 -0
  102. package/src/storage/index.ts +3 -0
  103. package/src/storage/ipfs.ts +20 -0
  104. package/src/storage/pinata.ts +56 -0
  105. package/src/storage/storage.ts +65 -0
  106. package/src/util/index.ts +1 -0
  107. package/src/util/sleep.ts +3 -0
  108. package/src/whitelist/index.ts +2 -0
  109. package/src/whitelist/offchain-map.ts +341 -0
  110. package/src/whitelist/whitelist.ts +139 -0
@@ -0,0 +1,122 @@
1
+ import { Field, Option, PublicKey, UInt64, Bool } from "o1js";
2
+ import { OffChainList, OffchainMapOption, OffchainMapSerialized } from "./offchain-map.js";
3
+ declare const UInt64Option_base: Omit<import("node_modules/o1js/dist/node/lib/provable/types/provable-intf.js").Provable<Option<UInt64, bigint>, bigint | undefined>, "fromFields"> & {
4
+ fromFields: (fields: import("node_modules/o1js/dist/node/lib/provable/field.js").Field[]) => Option<UInt64, bigint>;
5
+ } & (new (option: {
6
+ isSome: Bool;
7
+ value: UInt64;
8
+ }) => Option<UInt64, bigint>) & {
9
+ fromValue(value: bigint | UInt64 | {
10
+ isSome: boolean | Bool;
11
+ value: bigint | UInt64;
12
+ } | undefined): Option<UInt64, bigint>;
13
+ from(value?: bigint | UInt64 | undefined): Option<UInt64, bigint>;
14
+ none(): Option<UInt64, bigint>;
15
+ };
16
+ export declare class UInt64Option extends UInt64Option_base {
17
+ }
18
+ export declare class WhitelistedAddress {
19
+ address: PublicKey | string;
20
+ amount?: UInt64 | number;
21
+ }
22
+ declare const Whitelist_base: (new (value: {
23
+ list: OffChainList;
24
+ }) => {
25
+ list: OffChainList;
26
+ }) & {
27
+ _isStruct: true;
28
+ } & Omit<import("node_modules/o1js/dist/node/lib/provable/types/provable-intf.js").Provable<{
29
+ list: OffChainList;
30
+ }, {
31
+ list: {
32
+ root: bigint;
33
+ storage: {
34
+ url: bigint[];
35
+ };
36
+ };
37
+ }>, "fromFields"> & {
38
+ fromFields: (fields: import("node_modules/o1js/dist/node/lib/provable/field.js").Field[]) => {
39
+ list: OffChainList;
40
+ };
41
+ } & {
42
+ fromValue: (value: {
43
+ list: OffChainList | {
44
+ root: string | number | bigint | import("node_modules/o1js/dist/node/lib/provable/field.js").Field;
45
+ storage: import("../index.js").Storage | {
46
+ url: import("node_modules/o1js/dist/node/lib/provable/field.js").Field[] | bigint[];
47
+ };
48
+ };
49
+ }) => {
50
+ list: OffChainList;
51
+ };
52
+ toInput: (x: {
53
+ list: OffChainList;
54
+ }) => {
55
+ fields?: Field[] | undefined;
56
+ packed?: [Field, number][] | undefined;
57
+ };
58
+ toJSON: (x: {
59
+ list: OffChainList;
60
+ }) => {
61
+ list: {
62
+ root: string;
63
+ storage: {
64
+ url: string[];
65
+ };
66
+ };
67
+ };
68
+ fromJSON: (x: {
69
+ list: {
70
+ root: string;
71
+ storage: {
72
+ url: string[];
73
+ };
74
+ };
75
+ }) => {
76
+ list: OffChainList;
77
+ };
78
+ empty: () => {
79
+ list: OffChainList;
80
+ };
81
+ };
82
+ export declare class Whitelist extends Whitelist_base {
83
+ isNone(): Bool;
84
+ isSome(): Bool;
85
+ load(): Promise<OffchainMapOption>;
86
+ /**
87
+ * The function fetches a whitelisted amount associated with a given address using a map and returns it
88
+ * as a UInt64Option.
89
+ * @param {PublicKey} address - The `address` parameter is of type `PublicKey`,
90
+ * used to retrieve a whitelisted amount for the given address.
91
+ * @returns The `fetchWhitelistedAmount` function returns a `Promise` that resolves to a `UInt64Option`
92
+ * object. This object contains a `value` property representing the amount retrieved from a map based
93
+ * on the provided address. The `isSome` property indicates whether the value is present or not.
94
+ * The value is not present if the whitelist is NOT empty and the address is NOT whitelisted.
95
+ * The value is present if the whitelist is NOT empty or the address IS whitelisted.
96
+ * The value is present and equals to UInt64.MAXINT() if the whitelist IS empty.
97
+ */
98
+ getWhitelistedAmount(address: PublicKey, name?: string): Promise<UInt64Option>;
99
+ static empty(): Whitelist;
100
+ /**
101
+ * Creates a new whitelist and pins it to IPFS.
102
+ * @param params - The parameters for creating the whitelist.
103
+ * @returns A new `Whitelist` instance.
104
+ */
105
+ static create(params: {
106
+ list: WhitelistedAddress[];
107
+ name?: string;
108
+ filename?: string;
109
+ keyvalues?: object;
110
+ timeout?: number;
111
+ attempts?: number;
112
+ auth?: string;
113
+ pin?: boolean;
114
+ json?: OffchainMapSerialized;
115
+ }): Promise<{
116
+ whitelist: Whitelist;
117
+ json: OffchainMapSerialized;
118
+ }>;
119
+ toString(): string;
120
+ static fromString(str: string): Whitelist;
121
+ }
122
+ export {};
@@ -0,0 +1,98 @@
1
+ import { Struct, Option, PublicKey, UInt64, Poseidon } from "o1js";
2
+ import { OffChainList, OffchainMap, } from "./offchain-map.js";
3
+ export class UInt64Option extends Option(UInt64) {
4
+ }
5
+ export class WhitelistedAddress {
6
+ }
7
+ export class Whitelist extends Struct({
8
+ list: OffChainList,
9
+ }) {
10
+ isNone() {
11
+ return this.list.isNone();
12
+ }
13
+ isSome() {
14
+ return this.list.isSome();
15
+ }
16
+ async load() {
17
+ return this.list.load();
18
+ }
19
+ /**
20
+ * The function fetches a whitelisted amount associated with a given address using a map and returns it
21
+ * as a UInt64Option.
22
+ * @param {PublicKey} address - The `address` parameter is of type `PublicKey`,
23
+ * used to retrieve a whitelisted amount for the given address.
24
+ * @returns The `fetchWhitelistedAmount` function returns a `Promise` that resolves to a `UInt64Option`
25
+ * object. This object contains a `value` property representing the amount retrieved from a map based
26
+ * on the provided address. The `isSome` property indicates whether the value is present or not.
27
+ * The value is not present if the whitelist is NOT empty and the address is NOT whitelisted.
28
+ * The value is present if the whitelist is NOT empty or the address IS whitelisted.
29
+ * The value is present and equals to UInt64.MAXINT() if the whitelist IS empty.
30
+ */
31
+ async getWhitelistedAmount(address, name = "whitelist") {
32
+ const map = await this.list.load(name);
33
+ const key = Poseidon.hashPacked(PublicKey, address);
34
+ const value = map.orElse(new OffchainMap()).getOption(key);
35
+ const valueField = value.orElse(UInt64.MAXINT().value);
36
+ valueField.assertLessThanOrEqual(UInt64.MAXINT().value);
37
+ const amount = UInt64.Unsafe.fromField(valueField);
38
+ return new UInt64Option({
39
+ value: amount,
40
+ isSome: value.isSome.or(this.isNone()),
41
+ });
42
+ }
43
+ static empty() {
44
+ return new Whitelist({
45
+ list: OffChainList.empty(),
46
+ });
47
+ }
48
+ /**
49
+ * Creates a new whitelist and pins it to IPFS.
50
+ * @param params - The parameters for creating the whitelist.
51
+ * @returns A new `Whitelist` instance.
52
+ */
53
+ static async create(params) {
54
+ const { name = "whitelist", filename = "whitelist.json", keyvalues, timeout, attempts, auth, pin = true, json: initialJson = {}, } = params;
55
+ function parseAddress(address) {
56
+ return typeof address === "string"
57
+ ? PublicKey.fromBase58(address)
58
+ : address;
59
+ }
60
+ function parseAmount(amount) {
61
+ if (amount === undefined)
62
+ return UInt64.zero;
63
+ return typeof amount === "number"
64
+ ? UInt64.from(Math.round(amount))
65
+ : amount;
66
+ }
67
+ const entries = params.list.map((item) => ({
68
+ address: parseAddress(item.address),
69
+ amount: parseAmount(item.amount),
70
+ }));
71
+ const { list, json } = await OffChainList.create({
72
+ list: entries.map((item) => ({
73
+ key: Poseidon.hashPacked(PublicKey, item.address),
74
+ value: item.amount.value,
75
+ })),
76
+ data: entries.map((item) => ({
77
+ address: item.address.toBase58(),
78
+ amount: Number(item.amount.toBigInt()),
79
+ })),
80
+ name,
81
+ filename,
82
+ keyvalues,
83
+ timeout,
84
+ attempts,
85
+ auth,
86
+ pin,
87
+ json: initialJson,
88
+ });
89
+ return { whitelist: new Whitelist({ list }), json };
90
+ }
91
+ toString() {
92
+ return this.list.toString();
93
+ }
94
+ static fromString(str) {
95
+ return new Whitelist({ list: OffChainList.fromString(str) });
96
+ }
97
+ }
98
+ //# sourceMappingURL=whitelist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whitelist.js","sourceRoot":"","sources":["../../../src/whitelist/whitelist.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@silvana-one/storage",
3
+ "description": "Silvana Storage Library",
4
+ "version": "0.1.0",
5
+ "author": "DFST",
6
+ "bugs": "https://github.com/SilvanaOne/silvana-lib/issues",
7
+ "dependencies": {
8
+ "tslib": "^2.8.1"
9
+ },
10
+ "devDependencies": {
11
+ "@types/node": "^22.10.2",
12
+ "esbuild": "^0.24.0",
13
+ "o1js": "^2.2.0",
14
+ "typescript": "^5.7.2"
15
+ },
16
+ "engines": {
17
+ "node": ">=20.0.0"
18
+ },
19
+ "exports": {
20
+ "types": "./dist/node/index.d.ts",
21
+ "node": {
22
+ "import": "./dist/node/index.js",
23
+ "require": "./dist/node/index.cjs"
24
+ },
25
+ "browser": "./dist/web/index.js",
26
+ "default": "./dist/web/index.js"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "src",
31
+ "package.json",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "homepage": "https://docs.silvana.one",
36
+ "keywords": [
37
+ "cloud",
38
+ "mina-protocol",
39
+ "silvana",
40
+ "whitelist",
41
+ "proving",
42
+ "storage",
43
+ "typescript"
44
+ ],
45
+ "license": "Apache-2.0",
46
+ "main": "dist/web/index.js",
47
+ "peerDependencies": {
48
+ "o1js": "^2.2.0"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "repository": "SilvanaOne/silvana-lib.git",
54
+ "scripts": {
55
+ "build": "rm -rf dist && tsc && tsc --build tsconfig.web.json && node build-cjs.js",
56
+ "release": "npm publish --access public"
57
+ },
58
+ "type": "module",
59
+ "types": "./dist/node/index.d.ts"
60
+ }
@@ -0,0 +1,87 @@
1
+ // URL friendly base64 encoding
2
+ const TABLE =
3
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
4
+
5
+ export function bigintToBase56(value: bigint): string {
6
+ const digits = toBase(value, 56n);
7
+ //console.log("digits:", digits);
8
+ const str = digits.map((x) => TABLE[Number(x)]).join("");
9
+ //console.log("str:", str);
10
+ return str;
11
+ }
12
+
13
+ export function bigintFromBase56(str: string): bigint {
14
+ const base56Digits = str.split("").map((x) => BigInt(TABLE.indexOf(x)));
15
+ const x = fromBase(base56Digits, 56n);
16
+ return x;
17
+ }
18
+
19
+ export function bigintToBase64(value: bigint): string {
20
+ const digits = toBase(value, 64n);
21
+ //console.log("digits:", digits);
22
+ const str = digits.map((x) => TABLE[Number(x)]).join("");
23
+ //console.log("str:", str);
24
+ return str;
25
+ }
26
+
27
+ export function bigintFromBase64(str: string): bigint {
28
+ const base64Digits = str.split("").map((x) => BigInt(TABLE.indexOf(x)));
29
+ const x = fromBase(base64Digits, 64n);
30
+ return x;
31
+ }
32
+
33
+ export function fromBase(digits: bigint[], base: bigint) {
34
+ if (base <= 0n) throw Error("fromBase: base must be positive");
35
+ // compute powers base, base^2, base^4, ..., base^(2^k)
36
+ // with largest k s.t. n = 2^k < digits.length
37
+ let basePowers = [];
38
+ for (let power = base, n = 1; n < digits.length; power **= 2n, n *= 2) {
39
+ basePowers.push(power);
40
+ }
41
+ let k = basePowers.length;
42
+ // pad digits array with zeros s.t. digits.length === 2^k
43
+ digits = digits.concat(Array(2 ** k - digits.length).fill(0n));
44
+ // accumulate [x0, x1, x2, x3, ...] -> [x0 + base*x1, x2 + base*x3, ...] -> [x0 + base*x1 + base^2*(x2 + base*x3), ...] -> ...
45
+ // until we end up with a single element
46
+ for (let i = 0; i < k; i++) {
47
+ let newDigits = Array(digits.length >> 1);
48
+ let basePower = basePowers[i];
49
+ for (let j = 0; j < newDigits.length; j++) {
50
+ newDigits[j] = digits[2 * j] + basePower * digits[2 * j + 1];
51
+ }
52
+ digits = newDigits;
53
+ }
54
+ console.assert(digits.length === 1);
55
+ let [digit] = digits;
56
+ return digit;
57
+ }
58
+
59
+ export function toBase(x: bigint, base: bigint) {
60
+ if (base <= 0n) throw Error("toBase: base must be positive");
61
+ // compute powers base, base^2, base^4, ..., base^(2^k)
62
+ // with largest k s.t. base^(2^k) < x
63
+ let basePowers = [];
64
+ for (let power = base; power <= x; power **= 2n) {
65
+ basePowers.push(power);
66
+ }
67
+ let digits = [x]; // single digit w.r.t base^(2^(k+1))
68
+ // successively split digits w.r.t. base^(2^j) into digits w.r.t. base^(2^(j-1))
69
+ // until we arrive at digits w.r.t. base
70
+ let k = basePowers.length;
71
+ for (let i = 0; i < k; i++) {
72
+ let newDigits = Array(2 * digits.length);
73
+ let basePower = basePowers[k - 1 - i];
74
+ for (let j = 0; j < digits.length; j++) {
75
+ let x = digits[j];
76
+ let high = x / basePower;
77
+ newDigits[2 * j + 1] = high;
78
+ newDigits[2 * j] = x - high * basePower;
79
+ }
80
+ digits = newDigits;
81
+ }
82
+ // pop "leading" zero digits
83
+ while (digits[digits.length - 1] === 0n) {
84
+ digits.pop();
85
+ }
86
+ return digits;
87
+ }
@@ -0,0 +1,34 @@
1
+ import { Field } from "o1js";
2
+ import { toBase, fromBase } from "./bigint.js";
3
+
4
+ // URL friendly base64 encoding
5
+ const TABLE =
6
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
7
+
8
+ export function fieldToBase56(field: Field): string {
9
+ const digits = toBase(field.toBigInt(), 56n);
10
+ //console.log("digits:", digits);
11
+ const str = digits.map((x) => TABLE[Number(x)]).join("");
12
+ //console.log("str:", str);
13
+ return str;
14
+ }
15
+
16
+ export function fieldFromBase56(str: string): Field {
17
+ const base56Digits = str.split("").map((x) => BigInt(TABLE.indexOf(x)));
18
+ const x = fromBase(base56Digits, 56n);
19
+ return Field(x);
20
+ }
21
+
22
+ export function fieldToBase64(field: Field): string {
23
+ const digits = toBase(field.toBigInt(), 64n);
24
+ //console.log("digits:", digits);
25
+ const str = digits.map((x) => TABLE[Number(x)]).join("");
26
+ //console.log("str:", str);
27
+ return str;
28
+ }
29
+
30
+ export function fieldFromBase64(str: string): Field {
31
+ const base64Digits = str.split("").map((x) => BigInt(TABLE.indexOf(x)));
32
+ const x = fromBase(base64Digits, 64n);
33
+ return Field(x);
34
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./bigint.js";
2
+ export * from "./field.js";
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./base64/index.js";
2
+ export * from "./indexed-map/index.js";
3
+ export * from "./storage/index.js";
4
+ export * from "./util/index.js";
5
+ export * from "./whitelist/index.js";
@@ -0,0 +1 @@
1
+ export * from "./indexed-map.js";
@@ -0,0 +1,189 @@
1
+ import { Experimental, Field } from "o1js";
2
+ import { bigintToBase64, bigintFromBase64 } from "../base64/bigint.js";
3
+ import { sleep } from "../util/sleep.js";
4
+ import { pinJSON } from "../storage/pinata.js";
5
+
6
+ const { IndexedMerkleMap } = Experimental;
7
+ type IndexedMerkleMap = Experimental.IndexedMerkleMap;
8
+
9
+ export interface IndexedMapSerialized {
10
+ height: number;
11
+ root: string;
12
+ length: string;
13
+ nodes: string;
14
+ sortedLeaves: string;
15
+ }
16
+
17
+ export type IndexedMapSerializedJson = {
18
+ [key: string]: { map: IndexedMapSerialized };
19
+ };
20
+
21
+ export async function loadIndexedMerkleMap(params: {
22
+ url: string;
23
+ type: ReturnType<typeof IndexedMerkleMap>;
24
+ name?: string;
25
+ timeout?: number;
26
+ attempts?: number;
27
+ }) {
28
+ const {
29
+ url,
30
+ type,
31
+ name = "indexed-map",
32
+ timeout = 60000,
33
+ attempts = 5,
34
+ } = params;
35
+ let attempt = 0;
36
+ const start = Date.now();
37
+ let response = await fetch(url);
38
+ while (!response.ok && attempt < attempts && Date.now() - start < timeout) {
39
+ attempt++;
40
+ await sleep(5000 * attempt); // handle rate limiting
41
+ response = await fetch(url);
42
+ }
43
+ if (!response.ok) {
44
+ throw new Error("Failed to fetch IndexedMerkleMap");
45
+ }
46
+
47
+ const json = await response.json();
48
+ const serializedIndexedMap = (json as unknown as IndexedMapSerializedJson)[
49
+ name
50
+ ].map;
51
+ if (!serializedIndexedMap)
52
+ throw new Error("wrong IndexedMerkleMap json format");
53
+ const map = deserializeIndexedMerkleMapInternal({
54
+ serializedIndexedMap,
55
+ type,
56
+ });
57
+ if (!map) {
58
+ throw new Error("Failed to deserialize whitelist");
59
+ }
60
+ return map;
61
+ }
62
+
63
+ export async function saveIndexedMerkleMap(params: {
64
+ map: IndexedMerkleMap;
65
+ name?: string;
66
+ filename?: string;
67
+ keyvalues?: { key: string; value: string }[];
68
+ auth: string;
69
+ }): Promise<string | undefined> {
70
+ const {
71
+ map,
72
+ name = "indexed-map",
73
+ keyvalues,
74
+ auth,
75
+ filename = "indexed-map",
76
+ } = params;
77
+ const serialized = serializeIndexedMap(map);
78
+ const json: IndexedMapSerializedJson = { [name]: { map: serialized } };
79
+ const ipfsHash = await pinJSON({
80
+ data: json,
81
+ name: filename,
82
+ keyvalues,
83
+ auth,
84
+ });
85
+ return ipfsHash;
86
+ }
87
+
88
+ export function serializeIndexedMap(
89
+ map: IndexedMerkleMap
90
+ ): IndexedMapSerialized {
91
+ return {
92
+ height: map.height,
93
+ root: map.root.toJSON(),
94
+ length: map.length.toJSON(),
95
+ nodes: JSON.stringify(map.data.get().nodes, (_, v) =>
96
+ typeof v === "bigint" ? "n" + bigintToBase64(v) : v
97
+ ),
98
+ sortedLeaves: JSON.stringify(
99
+ map.data
100
+ .get()
101
+ .sortedLeaves.map((v) => [
102
+ bigintToBase64(v.key),
103
+ bigintToBase64(v.nextKey),
104
+ bigintToBase64(v.value),
105
+ bigintToBase64(BigInt(v.index)),
106
+ ])
107
+ ),
108
+ };
109
+ }
110
+
111
+ export function deserializeIndexedMerkleMap(params: {
112
+ serializedIndexedMap: IndexedMapSerialized;
113
+ type?: ReturnType<typeof IndexedMerkleMap>;
114
+ }): InstanceType<ReturnType<typeof IndexedMerkleMap>> | undefined {
115
+ try {
116
+ const { serializedIndexedMap, type } = params;
117
+ return deserializeIndexedMerkleMapInternal({
118
+ serializedIndexedMap,
119
+ type: type ?? IndexedMerkleMap(serializedIndexedMap.height),
120
+ });
121
+ } catch (error: any) {
122
+ console.error("Error deserializing map:", error?.message ?? error);
123
+ return undefined;
124
+ }
125
+ }
126
+
127
+ export function parseIndexedMapSerialized(
128
+ serializedMap: string
129
+ ): IndexedMapSerialized {
130
+ const json = JSON.parse(serializedMap);
131
+ if (
132
+ json.height === undefined ||
133
+ json.root === undefined ||
134
+ json.length === undefined ||
135
+ json.nodes === undefined ||
136
+ json.sortedLeaves === undefined
137
+ )
138
+ throw new Error("wrong IndexedMerkleMap json format");
139
+ if (typeof json.height !== "number")
140
+ throw new Error("wrong IndexedMerkleMap height format");
141
+ if (typeof json.root !== "string")
142
+ throw new Error("wrong IndexedMerkleMap root format");
143
+ if (typeof json.length !== "string")
144
+ throw new Error("wrong IndexedMerkleMap length format");
145
+ if (typeof json.nodes !== "string")
146
+ throw new Error("wrong IndexedMerkleMap nodes format");
147
+ if (typeof json.sortedLeaves !== "string")
148
+ throw new Error("wrong IndexedMerkleMap sortedLeaves format");
149
+ return json;
150
+ }
151
+
152
+ function deserializeIndexedMerkleMapInternal(params: {
153
+ serializedIndexedMap: IndexedMapSerialized;
154
+ type: ReturnType<typeof IndexedMerkleMap>;
155
+ }): InstanceType<ReturnType<typeof IndexedMerkleMap>> {
156
+ const { serializedIndexedMap, type } = params;
157
+ const map = new type();
158
+ if (serializedIndexedMap.height !== map.height) {
159
+ throw new Error("wrong IndexedMap height");
160
+ }
161
+ const nodes = JSON.parse(serializedIndexedMap.nodes, (_, v) => {
162
+ // Check if the value is a string that represents a BigInt
163
+ if (typeof v === "string" && v[0] === "n") {
164
+ // Remove the first 'n' and convert the string to a BigInt
165
+ return bigintFromBase64(v.slice(1));
166
+ }
167
+ return v;
168
+ });
169
+ const sortedLeaves = JSON.parse(serializedIndexedMap.sortedLeaves).map(
170
+ (row: any) => {
171
+ return {
172
+ key: bigintFromBase64(row[0]),
173
+ nextKey: bigintFromBase64(row[1]),
174
+ value: bigintFromBase64(row[2]),
175
+ index: Number(bigintFromBase64(row[3])),
176
+ };
177
+ }
178
+ );
179
+
180
+ map.root = Field.fromJSON(serializedIndexedMap.root);
181
+ map.length = Field.fromJSON(serializedIndexedMap.length);
182
+ map.data.updateAsProver(() => {
183
+ return {
184
+ nodes: nodes.map((row: any) => [...row]),
185
+ sortedLeaves: [...sortedLeaves],
186
+ };
187
+ });
188
+ return map;
189
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./ipfs.js";
2
+ export * from "./pinata.js";
3
+ export * from "./storage.js";
@@ -0,0 +1,20 @@
1
+ export function createIpfsURL(params: {
2
+ hash: string;
3
+ gateway?: string;
4
+ apiToken?: string;
5
+ }): string {
6
+ let { hash, gateway, apiToken } = params;
7
+ gateway ??=
8
+ process.env.PINATA_IPFS_GATEWAY ??
9
+ process.env.NEXT_PUBLIC_PINATA_IPFS_GATEWAY ??
10
+ process.env.REACT_APP_PINATA_IPFS_GATEWAY;
11
+ apiToken ??=
12
+ process.env.PINATA_GATEWAY_TOKEN ??
13
+ process.env.NEXT_PUBLIC_PINATA_GATEWAY_TOKEN ??
14
+ process.env.REACT_APP_PINATA_GATEWAY_TOKEN;
15
+
16
+ if (!gateway) {
17
+ gateway = "https://gateway.pinata.cloud/ipfs/";
18
+ }
19
+ return gateway + hash + (apiToken ? "?pinataGatewayToken=" + apiToken : "");
20
+ }