@silvana-one/coordination 1.0.15
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/LICENSE +201 -0
- package/README.md +1 -0
- package/dist/node/agent.d.ts +93 -0
- package/dist/node/agent.js +278 -0
- package/dist/node/agent.js.map +1 -0
- package/dist/node/base58/base58.d.ts +5 -0
- package/dist/node/base58/base58.js +108 -0
- package/dist/node/base58/base58.js.map +1 -0
- package/dist/node/base58/bigint-helpers.d.ts +24 -0
- package/dist/node/base58/bigint-helpers.js +214 -0
- package/dist/node/base58/bigint-helpers.js.map +1 -0
- package/dist/node/base58/index.d.ts +2 -0
- package/dist/node/base58/index.js +3 -0
- package/dist/node/base58/index.js.map +1 -0
- package/dist/node/base58/public-key.d.ts +4 -0
- package/dist/node/base58/public-key.js +7 -0
- package/dist/node/base58/public-key.js.map +1 -0
- package/dist/node/base58/signature.d.ts +3 -0
- package/dist/node/base58/signature.js +65 -0
- package/dist/node/base58/signature.js.map +1 -0
- package/dist/node/base58/versions.d.ts +11 -0
- package/dist/node/base58/versions.js +12 -0
- package/dist/node/base58/versions.js.map +1 -0
- package/dist/node/execute.d.ts +16 -0
- package/dist/node/execute.js +142 -0
- package/dist/node/execute.js.map +1 -0
- package/dist/node/fetch.d.ts +8 -0
- package/dist/node/fetch.js +41 -0
- package/dist/node/fetch.js.map +1 -0
- package/dist/node/index.cjs +878 -0
- package/dist/node/index.d.ts +9 -0
- package/dist/node/index.js +10 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/mvr.d.ts +14 -0
- package/dist/node/mvr.js +70 -0
- package/dist/node/mvr.js.map +1 -0
- package/dist/node/publish.d.ts +9 -0
- package/dist/node/publish.js +40 -0
- package/dist/node/publish.js.map +1 -0
- package/dist/node/sleep.d.ts +1 -0
- package/dist/node/sleep.js +4 -0
- package/dist/node/sleep.js.map +1 -0
- package/dist/node/sui-client.d.ts +4 -0
- package/dist/node/sui-client.js +39 -0
- package/dist/node/sui-client.js.map +1 -0
- package/dist/node/types.d.ts +4 -0
- package/dist/node/types.js +2 -0
- package/dist/node/types.js.map +1 -0
- package/dist/node/upgrade.d.ts +13 -0
- package/dist/node/upgrade.js +51 -0
- package/dist/node/upgrade.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/tsconfig.web.tsbuildinfo +1 -0
- package/dist/web/agent.d.ts +93 -0
- package/dist/web/agent.js +278 -0
- package/dist/web/agent.js.map +1 -0
- package/dist/web/base58/base58.d.ts +5 -0
- package/dist/web/base58/base58.js +108 -0
- package/dist/web/base58/base58.js.map +1 -0
- package/dist/web/base58/bigint-helpers.d.ts +24 -0
- package/dist/web/base58/bigint-helpers.js +214 -0
- package/dist/web/base58/bigint-helpers.js.map +1 -0
- package/dist/web/base58/index.d.ts +2 -0
- package/dist/web/base58/index.js +3 -0
- package/dist/web/base58/index.js.map +1 -0
- package/dist/web/base58/public-key.d.ts +4 -0
- package/dist/web/base58/public-key.js +7 -0
- package/dist/web/base58/public-key.js.map +1 -0
- package/dist/web/base58/signature.d.ts +3 -0
- package/dist/web/base58/signature.js +65 -0
- package/dist/web/base58/signature.js.map +1 -0
- package/dist/web/base58/versions.d.ts +11 -0
- package/dist/web/base58/versions.js +12 -0
- package/dist/web/base58/versions.js.map +1 -0
- package/dist/web/execute.d.ts +16 -0
- package/dist/web/execute.js +142 -0
- package/dist/web/execute.js.map +1 -0
- package/dist/web/fetch.d.ts +8 -0
- package/dist/web/fetch.js +41 -0
- package/dist/web/fetch.js.map +1 -0
- package/dist/web/index.d.ts +9 -0
- package/dist/web/index.js +10 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/mvr.d.ts +14 -0
- package/dist/web/mvr.js +70 -0
- package/dist/web/mvr.js.map +1 -0
- package/dist/web/publish.d.ts +9 -0
- package/dist/web/publish.js +40 -0
- package/dist/web/publish.js.map +1 -0
- package/dist/web/sleep.d.ts +1 -0
- package/dist/web/sleep.js +4 -0
- package/dist/web/sleep.js.map +1 -0
- package/dist/web/sui-client.d.ts +4 -0
- package/dist/web/sui-client.js +39 -0
- package/dist/web/sui-client.js.map +1 -0
- package/dist/web/types.d.ts +4 -0
- package/dist/web/types.js +2 -0
- package/dist/web/types.js.map +1 -0
- package/dist/web/upgrade.d.ts +13 -0
- package/dist/web/upgrade.js +51 -0
- package/dist/web/upgrade.js.map +1 -0
- package/package.json +59 -0
- package/src/agent.ts +437 -0
- package/src/base58/base58.ts +121 -0
- package/src/base58/bigint-helpers.ts +236 -0
- package/src/base58/index.ts +2 -0
- package/src/base58/public-key.ts +13 -0
- package/src/base58/signature.ts +89 -0
- package/src/base58/versions.ts +12 -0
- package/src/execute.ts +176 -0
- package/src/fetch.ts +54 -0
- package/src/index.ts +9 -0
- package/src/mvr.ts +99 -0
- package/src/publish.ts +54 -0
- package/src/sleep.ts +3 -0
- package/src/sui-client.ts +42 -0
- package/src/types.ts +4 -0
- package/src/upgrade.ts +78 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
export {
|
|
2
|
+
changeBase,
|
|
3
|
+
bytesToBigInt,
|
|
4
|
+
bigIntToBytes,
|
|
5
|
+
bigIntToBits,
|
|
6
|
+
parseHexString32,
|
|
7
|
+
log2,
|
|
8
|
+
max,
|
|
9
|
+
abs,
|
|
10
|
+
sign,
|
|
11
|
+
bytesToBigint32,
|
|
12
|
+
bigintToBytes32,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function bytesToBigint32(bytes: Uint8Array) {
|
|
16
|
+
let words = new BigUint64Array(bytes.buffer, bytes.byteOffset, 4);
|
|
17
|
+
return words[0] | (words[1] << 64n) | (words[2] << 128n) | (words[3] << 192n);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const mask64 = (1n << 64n) - 1n;
|
|
21
|
+
|
|
22
|
+
function bigintToBytes32(x: bigint, bytes: Uint8Array): Uint8Array {
|
|
23
|
+
let words = new BigUint64Array(bytes.buffer, bytes.byteOffset, 4);
|
|
24
|
+
words[0] = x & mask64;
|
|
25
|
+
words[1] = (x >> 64n) & mask64;
|
|
26
|
+
words[2] = (x >> 128n) & mask64;
|
|
27
|
+
words[3] = x >> 192n;
|
|
28
|
+
return bytes;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bytesToBigInt(bytes: Uint8Array | number[]) {
|
|
32
|
+
let x = 0n;
|
|
33
|
+
let bitPosition = 0n;
|
|
34
|
+
for (let byte of bytes) {
|
|
35
|
+
x += BigInt(byte) << bitPosition;
|
|
36
|
+
bitPosition += 8n;
|
|
37
|
+
}
|
|
38
|
+
return x;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let hexToNum: { [hexCharCode: number]: number } = {};
|
|
42
|
+
for (let i = 0; i < 16; i++) hexToNum[i.toString(16).charCodeAt(0)] = i;
|
|
43
|
+
let encoder = new TextEncoder();
|
|
44
|
+
|
|
45
|
+
const tmpBytes = new Uint8Array(64);
|
|
46
|
+
|
|
47
|
+
function parseHexString32(input: string) {
|
|
48
|
+
// Parse the bytes explicitly, Bigint endianness is wrong
|
|
49
|
+
encoder.encodeInto(input, tmpBytes);
|
|
50
|
+
for (let j = 0; j < 32; j++) {
|
|
51
|
+
let n1 = hexToNum[tmpBytes[2 * j]];
|
|
52
|
+
let n0 = hexToNum[tmpBytes[2 * j + 1]];
|
|
53
|
+
tmpBytes[j] = (n1 << 4) | n0;
|
|
54
|
+
}
|
|
55
|
+
return bytesToBigint32(tmpBytes);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Transforms bigint to little-endian array of bytes (numbers between 0 and 255) of a given length.
|
|
60
|
+
* Throws an error if the bigint doesn't fit in the given number of bytes.
|
|
61
|
+
*/
|
|
62
|
+
function bigIntToBytes(x: bigint, length?: number) {
|
|
63
|
+
if (x < 0n) {
|
|
64
|
+
throw Error(`bigIntToBytes: negative numbers are not supported, got ${x}`);
|
|
65
|
+
}
|
|
66
|
+
if (length === undefined) return bigintToBytesFlexible(x);
|
|
67
|
+
let bytes: number[] = Array(length);
|
|
68
|
+
for (let i = 0; i < length; i++, x >>= 8n) {
|
|
69
|
+
bytes[i] = Number(x & 0xffn);
|
|
70
|
+
}
|
|
71
|
+
if (x > 0n) {
|
|
72
|
+
throw Error(`bigIntToBytes: input does not fit in ${length} bytes`);
|
|
73
|
+
}
|
|
74
|
+
return bytes;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function bigintToBytesFlexible(x: bigint) {
|
|
78
|
+
let bytes: number[] = [];
|
|
79
|
+
for (; x > 0n; x >>= 8n) {
|
|
80
|
+
bytes.push(Number(x & 0xffn));
|
|
81
|
+
}
|
|
82
|
+
return bytes;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Transforms bigint to little-endian array of bits (booleans).
|
|
87
|
+
* The length of the bit array is determined as needed.
|
|
88
|
+
*/
|
|
89
|
+
function bigIntToBits(x: bigint) {
|
|
90
|
+
if (x < 0n) {
|
|
91
|
+
throw Error(`bigIntToBits: negative numbers are not supported, got ${x}`);
|
|
92
|
+
}
|
|
93
|
+
let bits: boolean[] = [];
|
|
94
|
+
for (; x > 0n; x >>= 1n) {
|
|
95
|
+
let bit = !!(x & 1n);
|
|
96
|
+
bits.push(bit);
|
|
97
|
+
}
|
|
98
|
+
return bits;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function changeBase(digits: bigint[], base: bigint, newBase: bigint) {
|
|
102
|
+
// 1. accumulate digits into one gigantic bigint `x`
|
|
103
|
+
let x = fromBase(digits, base);
|
|
104
|
+
// 2. compute new digits from `x`
|
|
105
|
+
let newDigits = toBase(x, newBase);
|
|
106
|
+
return newDigits;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* the algorithm for toBase / fromBase is more complicated than it naively has to be,
|
|
111
|
+
* but that is for performance reasons.
|
|
112
|
+
*
|
|
113
|
+
* we'll explain it for `fromBase`. this function is about taking an array of digits
|
|
114
|
+
* `[x0, ..., xn]`
|
|
115
|
+
* and returning the integer (bigint) that has those digits in the given `base`:
|
|
116
|
+
* ```
|
|
117
|
+
* let x = x0 + x1*base + x2*base**2 + ... + xn*base**n
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* naively, we could just accumulate digits from left to right:
|
|
121
|
+
* ```
|
|
122
|
+
* let x = 0n;
|
|
123
|
+
* let p = 1n;
|
|
124
|
+
* for (let i=0; i<n; i++) {
|
|
125
|
+
* x += X[i] * p;
|
|
126
|
+
* p *= base;
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* in the ith step, `p = base**i` which is multiplied with `xi` and added to the sum.
|
|
131
|
+
* however, note that this algorithm is `O(n^2)`: let `l = log2(base)`. the base power `p` is a bigint of bit length `i*l`,
|
|
132
|
+
* which is multiplied by a "small" number `xi` (length l), which takes `O(i)` time in every step.
|
|
133
|
+
* since this is done for `i = 0,...,n`, we end up with an `O(n^2)` algorithm.
|
|
134
|
+
*
|
|
135
|
+
* HOWEVER, it turns out that there are fast multiplication algorithms, and JS bigints have them built in!
|
|
136
|
+
* the Schönhage-Strassen algorithm (implemented in the V8 engine, see https://github.com/v8/v8/blob/main/src/bigint/mul-fft.cc)
|
|
137
|
+
* can multiply two n-bit numbers in time `O(n log(n) loglog(n))`, when n is large.
|
|
138
|
+
*
|
|
139
|
+
* to take advantage of asymptotically fast multiplication, we need to re-structure our algorithm such that it multiplies roughly equal-sized
|
|
140
|
+
* numbers with each other (there is no asymptotic boost for multiplying a small with a large number). so, what we do is to go from the
|
|
141
|
+
* original digit array to arrays of successively larger digits:
|
|
142
|
+
* ```
|
|
143
|
+
* step 0: step 1: step 2:
|
|
144
|
+
* [x0, x1, x2, x3, ...] -> [x0 + base*x1, x2 + base*x3, ...] -> [x0 + base*x1 + base^2*(x2 + base*x3), ...] -> ...
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* ...until after a log(n) number of steps we end up with a single "digit" which is equal to the entire sum.
|
|
148
|
+
*
|
|
149
|
+
* in the ith step, we multiply `n/2^i` pairs of numbers of bit length `2^i*l`. each of these multiplications takes
|
|
150
|
+
* time `O(2^i log(2^i) loglog(2^i))`. if we bound that with `O(2^i log(n) loglog(n))`, we get a runtime bounded by
|
|
151
|
+
* ```
|
|
152
|
+
* O(n/2^i * 2^i log(n) loglog(n)) = O(n log(n) loglog(n))
|
|
153
|
+
* ```
|
|
154
|
+
* in each step. Since we have `log(n)` steps, the result is `O(n log(n)^2 loglog(n))`.
|
|
155
|
+
*
|
|
156
|
+
* empirically, this method is a huge improvement over the naive `O(n^2)` algorithm and scales much better with n (the number of digits).
|
|
157
|
+
*
|
|
158
|
+
* similar conclusions hold for `toBase`.
|
|
159
|
+
*/
|
|
160
|
+
function fromBase(digits: bigint[], base: bigint) {
|
|
161
|
+
if (base <= 0n) throw Error("fromBase: base must be positive");
|
|
162
|
+
// compute powers base, base^2, base^4, ..., base^(2^k)
|
|
163
|
+
// with largest k s.t. n = 2^k < digits.length
|
|
164
|
+
let basePowers = [];
|
|
165
|
+
for (let power = base, n = 1; n < digits.length; power **= 2n, n *= 2) {
|
|
166
|
+
basePowers.push(power);
|
|
167
|
+
}
|
|
168
|
+
let k = basePowers.length;
|
|
169
|
+
// pad digits array with zeros s.t. digits.length === 2^k
|
|
170
|
+
digits = digits.concat(Array(2 ** k - digits.length).fill(0n));
|
|
171
|
+
// accumulate [x0, x1, x2, x3, ...] -> [x0 + base*x1, x2 + base*x3, ...] -> [x0 + base*x1 + base^2*(x2 + base*x3), ...] -> ...
|
|
172
|
+
// until we end up with a single element
|
|
173
|
+
for (let i = 0; i < k; i++) {
|
|
174
|
+
let newDigits = Array(digits.length >> 1);
|
|
175
|
+
let basePower = basePowers[i];
|
|
176
|
+
for (let j = 0; j < newDigits.length; j++) {
|
|
177
|
+
newDigits[j] = digits[2 * j] + basePower * digits[2 * j + 1];
|
|
178
|
+
}
|
|
179
|
+
digits = newDigits;
|
|
180
|
+
}
|
|
181
|
+
console.assert(digits.length === 1);
|
|
182
|
+
let [digit] = digits;
|
|
183
|
+
return digit;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function toBase(x: bigint, base: bigint) {
|
|
187
|
+
if (base <= 0n) throw Error("toBase: base must be positive");
|
|
188
|
+
// compute powers base, base^2, base^4, ..., base^(2^k)
|
|
189
|
+
// with largest k s.t. base^(2^k) < x
|
|
190
|
+
let basePowers = [];
|
|
191
|
+
for (let power = base; power < x; power **= 2n) {
|
|
192
|
+
basePowers.push(power);
|
|
193
|
+
}
|
|
194
|
+
let digits = [x]; // single digit w.r.t base^(2^(k+1))
|
|
195
|
+
// successively split digits w.r.t. base^(2^j) into digits w.r.t. base^(2^(j-1))
|
|
196
|
+
// until we arrive at digits w.r.t. base
|
|
197
|
+
let k = basePowers.length;
|
|
198
|
+
for (let i = 0; i < k; i++) {
|
|
199
|
+
let newDigits = Array(2 * digits.length);
|
|
200
|
+
let basePower = basePowers[k - 1 - i];
|
|
201
|
+
for (let j = 0; j < digits.length; j++) {
|
|
202
|
+
let x = digits[j];
|
|
203
|
+
let high = x / basePower;
|
|
204
|
+
newDigits[2 * j + 1] = high;
|
|
205
|
+
newDigits[2 * j] = x - high * basePower;
|
|
206
|
+
}
|
|
207
|
+
digits = newDigits;
|
|
208
|
+
}
|
|
209
|
+
// pop "leading" zero digits
|
|
210
|
+
while (digits[digits.length - 1] === 0n) {
|
|
211
|
+
digits.pop();
|
|
212
|
+
}
|
|
213
|
+
return digits;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* ceil(log2(n))
|
|
218
|
+
* = smallest k such that n <= 2^k
|
|
219
|
+
*/
|
|
220
|
+
function log2(n: number | bigint) {
|
|
221
|
+
if (typeof n === "number") n = BigInt(n);
|
|
222
|
+
if (n === 1n) return 0;
|
|
223
|
+
return (n - 1n).toString(2).length;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function max(a: bigint, b: bigint) {
|
|
227
|
+
return a > b ? a : b;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function abs(x: bigint) {
|
|
231
|
+
return x < 0n ? -x : x;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function sign(x: bigint): 1n | -1n {
|
|
235
|
+
return x >= 0 ? 1n : -1n;
|
|
236
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { toBase58Check, toBytesWithVersionNumber } from "./base58.js";
|
|
2
|
+
import { versionNumbers, versionBytes } from "./versions.js";
|
|
3
|
+
|
|
4
|
+
export function convertFieldsToPublicKey(fields: {
|
|
5
|
+
x: bigint;
|
|
6
|
+
isOdd: boolean;
|
|
7
|
+
}): string {
|
|
8
|
+
let bytes = toBytesWithVersionNumber(
|
|
9
|
+
[fields.x, fields.isOdd ? 1n : 0n],
|
|
10
|
+
versionNumbers.publicKey
|
|
11
|
+
);
|
|
12
|
+
return toBase58Check(bytes, versionBytes.publicKey);
|
|
13
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { MinaSignature } from "../types.js";
|
|
2
|
+
import { fromBase58Check, toBase58Check } from "./base58.js";
|
|
3
|
+
import { versionNumbers, versionBytes } from "./versions.js";
|
|
4
|
+
|
|
5
|
+
type NonNegativeInteger<T extends number> = number extends T
|
|
6
|
+
? never
|
|
7
|
+
: `${T}` extends `-${string}` | `${string}.${string}` | `${string}e-${string}`
|
|
8
|
+
? never
|
|
9
|
+
: T;
|
|
10
|
+
|
|
11
|
+
function assertNonNegativeInteger(n: number, message: string) {
|
|
12
|
+
if (!Number.isInteger(n) || n < 0) throw Error(message);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function bytesToBigInt(bytes: number[]) {
|
|
16
|
+
let x = 0n;
|
|
17
|
+
let bitPosition = 0n;
|
|
18
|
+
for (let byte of bytes) {
|
|
19
|
+
x += BigInt(byte) << bitPosition;
|
|
20
|
+
bitPosition += 8n;
|
|
21
|
+
}
|
|
22
|
+
return x;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function readBytesInternal(bytes: number[], start: number) {
|
|
26
|
+
const rBytes = bytes.slice(start, start + 32);
|
|
27
|
+
const sBytes = bytes.slice(start + 32, start + 64);
|
|
28
|
+
const r = bytesToBigInt(rBytes);
|
|
29
|
+
const s = bytesToBigInt(sBytes);
|
|
30
|
+
return { r, s };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function readBytes(bytes: number[], offset: number, versionNumber: number) {
|
|
34
|
+
let version = bytes[offset++];
|
|
35
|
+
if (version !== versionNumber) {
|
|
36
|
+
throw Error(
|
|
37
|
+
`fromBytes: Invalid version byte. Expected ${versionNumber}, got ${version}.`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return readBytesInternal(bytes, offset);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let readBytes_ = <N extends number>(
|
|
44
|
+
bytes: number[],
|
|
45
|
+
offset: NonNegativeInteger<N>
|
|
46
|
+
) => {
|
|
47
|
+
assertNonNegativeInteger(offset, "readBytes: offset must be integer >= 0");
|
|
48
|
+
if (offset >= bytes.length)
|
|
49
|
+
throw Error("readBytes: offset must be within bytes length");
|
|
50
|
+
return readBytes(bytes, offset, versionNumbers.signature);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function fromBytes(bytes: number[]): MinaSignature {
|
|
54
|
+
return readBytes_(bytes, 0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function toBytes(signature: MinaSignature): number[] {
|
|
58
|
+
const result = new Array<number>(65);
|
|
59
|
+
result[0] = versionNumbers.signature;
|
|
60
|
+
|
|
61
|
+
// Convert r to bytes
|
|
62
|
+
let r = signature.r;
|
|
63
|
+
for (let i = 0; i < 32; i++) {
|
|
64
|
+
result[i + 1] = Number(r & 0xffn);
|
|
65
|
+
r >>= 8n;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Convert s to bytes
|
|
69
|
+
let s = signature.s;
|
|
70
|
+
for (let i = 0; i < 32; i++) {
|
|
71
|
+
result[i + 33] = Number(s & 0xffn);
|
|
72
|
+
s >>= 8n;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function convertMinaSignatureFromBase58(
|
|
79
|
+
signature: string
|
|
80
|
+
): MinaSignature {
|
|
81
|
+
const bytes = fromBase58Check(signature, versionBytes.signature);
|
|
82
|
+
const minaSignature = fromBytes(bytes);
|
|
83
|
+
return minaSignature;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function convertMinaSignatureToBase58(signature: MinaSignature): string {
|
|
87
|
+
const bytes = toBytes(signature);
|
|
88
|
+
return toBase58Check(bytes, versionBytes.signature);
|
|
89
|
+
}
|
package/src/execute.ts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { SuiEvent, SuiTransactionBlockResponse } from "@mysten/sui/client";
|
|
2
|
+
import {
|
|
3
|
+
ParallelTransactionExecutor,
|
|
4
|
+
Transaction,
|
|
5
|
+
} from "@mysten/sui/transactions";
|
|
6
|
+
import { Secp256k1Keypair } from "@mysten/sui/keypairs/secp256k1";
|
|
7
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
|
|
8
|
+
import { suiClient } from "./sui-client.js";
|
|
9
|
+
import { nanoid } from "nanoid";
|
|
10
|
+
import { sleep } from "./sleep.js";
|
|
11
|
+
|
|
12
|
+
const executors: { [key: string]: ParallelTransactionExecutor } = {};
|
|
13
|
+
const locks: { [key: string]: string | undefined } = {};
|
|
14
|
+
|
|
15
|
+
const LOCK_TIMEOUT = 1000 * 60 * 2; // 5 minutes
|
|
16
|
+
|
|
17
|
+
async function getLock(address: string): Promise<string | undefined> {
|
|
18
|
+
const id = nanoid();
|
|
19
|
+
let locked = false;
|
|
20
|
+
const start = Date.now();
|
|
21
|
+
while (!locked && Date.now() - start < LOCK_TIMEOUT) {
|
|
22
|
+
if (locks[address]) {
|
|
23
|
+
await sleep(Math.floor(Math.random() * 10) + 10);
|
|
24
|
+
} else {
|
|
25
|
+
locks[address] = id;
|
|
26
|
+
await sleep(10);
|
|
27
|
+
if (locks[address] === id) {
|
|
28
|
+
locked = true;
|
|
29
|
+
return id;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function releaseLock(params: { address: string; id: string }) {
|
|
37
|
+
const { address, id } = params;
|
|
38
|
+
if (locks[address] === id) {
|
|
39
|
+
locks[address] = undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getExecutor(keyPair: Secp256k1Keypair | Ed25519Keypair) {
|
|
44
|
+
const keyPairId = keyPair.toSuiAddress();
|
|
45
|
+
if (!executors[keyPairId]) {
|
|
46
|
+
executors[keyPairId] = new ParallelTransactionExecutor({
|
|
47
|
+
client: suiClient,
|
|
48
|
+
signer: keyPair,
|
|
49
|
+
initialCoinBalance: 500_000_000n,
|
|
50
|
+
minimumCoinBalance: 300_000_000n,
|
|
51
|
+
maxPoolSize: 5,
|
|
52
|
+
});
|
|
53
|
+
locks[keyPairId] = undefined;
|
|
54
|
+
}
|
|
55
|
+
return executors[keyPairId];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function executeTx(params: {
|
|
59
|
+
tx: Transaction;
|
|
60
|
+
keyPair: Secp256k1Keypair | Ed25519Keypair;
|
|
61
|
+
useParallelExecutor?: boolean;
|
|
62
|
+
showErrors?: boolean;
|
|
63
|
+
}): Promise<
|
|
64
|
+
| {
|
|
65
|
+
tx: SuiTransactionBlockResponse;
|
|
66
|
+
digest: string;
|
|
67
|
+
events: object;
|
|
68
|
+
executeTime: number;
|
|
69
|
+
}
|
|
70
|
+
| undefined
|
|
71
|
+
> {
|
|
72
|
+
let lockId: string | undefined;
|
|
73
|
+
let address: string | undefined;
|
|
74
|
+
try {
|
|
75
|
+
const {
|
|
76
|
+
tx,
|
|
77
|
+
keyPair,
|
|
78
|
+
useParallelExecutor = false,
|
|
79
|
+
showErrors = true,
|
|
80
|
+
} = params;
|
|
81
|
+
let executedTx: SuiTransactionBlockResponse;
|
|
82
|
+
let start = 0;
|
|
83
|
+
let end = 0;
|
|
84
|
+
if (useParallelExecutor) {
|
|
85
|
+
address = keyPair.toSuiAddress();
|
|
86
|
+
lockId = await getLock(address);
|
|
87
|
+
if (!lockId) {
|
|
88
|
+
throw new Error("Failed to get lock");
|
|
89
|
+
}
|
|
90
|
+
start = Date.now();
|
|
91
|
+
const executor = getExecutor(keyPair);
|
|
92
|
+
executedTx = (
|
|
93
|
+
await executor.executeTransaction(tx, {
|
|
94
|
+
showEffects: true,
|
|
95
|
+
showObjectChanges: true,
|
|
96
|
+
showInput: true,
|
|
97
|
+
showEvents: true,
|
|
98
|
+
showBalanceChanges: true,
|
|
99
|
+
})
|
|
100
|
+
).data;
|
|
101
|
+
end = Date.now();
|
|
102
|
+
await waitTx(executedTx.digest);
|
|
103
|
+
await sleep(1000);
|
|
104
|
+
await releaseLock({ address: address, id: lockId });
|
|
105
|
+
} else {
|
|
106
|
+
address = keyPair.toSuiAddress();
|
|
107
|
+
lockId = await getLock(address);
|
|
108
|
+
if (!lockId) {
|
|
109
|
+
throw new Error("Failed to get lock");
|
|
110
|
+
}
|
|
111
|
+
const signedTx = await tx.sign({
|
|
112
|
+
signer: keyPair,
|
|
113
|
+
client: suiClient,
|
|
114
|
+
});
|
|
115
|
+
start = Date.now();
|
|
116
|
+
// const dryRun = await suiClient.devInspectTransactionBlock({
|
|
117
|
+
// sender: keypair.toSuiAddress(),
|
|
118
|
+
// transactionBlock: signedTx.bytes
|
|
119
|
+
// });
|
|
120
|
+
// dryRun.effects.gasUsed.computationCost
|
|
121
|
+
// const gasPrice = await suiClient.getReferenceGasPrice();
|
|
122
|
+
|
|
123
|
+
executedTx = await suiClient.executeTransactionBlock({
|
|
124
|
+
transactionBlock: signedTx.bytes,
|
|
125
|
+
signature: signedTx.signature,
|
|
126
|
+
options: {
|
|
127
|
+
showEffects: true,
|
|
128
|
+
showObjectChanges: true,
|
|
129
|
+
showInput: true,
|
|
130
|
+
showEvents: true,
|
|
131
|
+
showBalanceChanges: true,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
end = Date.now();
|
|
135
|
+
await releaseLock({ address, id: lockId });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (executedTx?.effects?.status?.status === "failure") {
|
|
139
|
+
if (showErrors) {
|
|
140
|
+
console.log(
|
|
141
|
+
`Errors for tx ${executedTx.digest}:`,
|
|
142
|
+
executedTx?.effects?.status?.error
|
|
143
|
+
);
|
|
144
|
+
throw new Error(`tx execution failed: ${executedTx.digest}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
tx: executedTx,
|
|
149
|
+
digest: executedTx.digest,
|
|
150
|
+
events: (executedTx?.events as SuiEvent[])?.[0]?.parsedJson as object,
|
|
151
|
+
executeTime: end - start,
|
|
152
|
+
};
|
|
153
|
+
} catch (error: any) {
|
|
154
|
+
if (lockId && address) {
|
|
155
|
+
await releaseLock({ address, id: lockId });
|
|
156
|
+
}
|
|
157
|
+
console.error("Error in executeTx", error.message);
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export async function waitTx(digest: string) {
|
|
163
|
+
console.time(`wait sui tx`);
|
|
164
|
+
const txWaitResult = await suiClient.waitForTransaction({
|
|
165
|
+
digest,
|
|
166
|
+
options: {
|
|
167
|
+
showEffects: true,
|
|
168
|
+
showObjectChanges: true,
|
|
169
|
+
showInput: true,
|
|
170
|
+
showEvents: true,
|
|
171
|
+
showBalanceChanges: true,
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
console.timeEnd(`wait sui tx`);
|
|
175
|
+
return txWaitResult;
|
|
176
|
+
}
|
package/src/fetch.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { suiClient } from "./sui-client.js";
|
|
2
|
+
|
|
3
|
+
export async function fetchSuiObject(objectID: string) {
|
|
4
|
+
const data = await suiClient.getObject({
|
|
5
|
+
id: objectID,
|
|
6
|
+
options: {
|
|
7
|
+
showContent: true,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
return data;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function fetchSuiDynamicField(params: {
|
|
14
|
+
objectID?: string;
|
|
15
|
+
parentID?: string;
|
|
16
|
+
fieldName: string;
|
|
17
|
+
type: string;
|
|
18
|
+
key: string;
|
|
19
|
+
}): Promise<object | undefined> {
|
|
20
|
+
try {
|
|
21
|
+
const { objectID, parentID, fieldName, type, key } = params;
|
|
22
|
+
|
|
23
|
+
if (!objectID && !parentID) {
|
|
24
|
+
console.error("objectID or parentID is required");
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
let id = parentID;
|
|
28
|
+
if (objectID && !parentID) {
|
|
29
|
+
const suiObject = (await fetchSuiObject(objectID)) as any;
|
|
30
|
+
|
|
31
|
+
id = (suiObject?.data?.content?.fields?.[fieldName] as any)?.fields?.id
|
|
32
|
+
?.id;
|
|
33
|
+
}
|
|
34
|
+
if (!id) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const field = await suiClient.getDynamicFieldObject({
|
|
39
|
+
parentId: id,
|
|
40
|
+
name: {
|
|
41
|
+
type,
|
|
42
|
+
value: key,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return (field.data?.content as any)?.fields as object;
|
|
47
|
+
} catch (error: any) {
|
|
48
|
+
console.error(
|
|
49
|
+
"fetchSuiDynamicField: Error fetching dynamic field",
|
|
50
|
+
error?.message
|
|
51
|
+
);
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./base58/index.js";
|
|
2
|
+
export * from "./execute.js";
|
|
3
|
+
export * from "./publish.js";
|
|
4
|
+
export * from "./sui-client.js";
|
|
5
|
+
export * from "./sleep.js";
|
|
6
|
+
export * from "./upgrade.js";
|
|
7
|
+
export * from "./mvr.js";
|
|
8
|
+
export * from "./agent.js";
|
|
9
|
+
export * from "./fetch.js";
|
package/src/mvr.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
2
|
+
|
|
3
|
+
export function publishToMVR(params: {
|
|
4
|
+
mvrName: string; // e.g. @suins/core
|
|
5
|
+
upgradeCap: string;
|
|
6
|
+
packageName: string;
|
|
7
|
+
safeAddress: string;
|
|
8
|
+
}): Transaction {
|
|
9
|
+
const { upgradeCap, packageName, mvrName, safeAddress } = params;
|
|
10
|
+
const transaction = new Transaction();
|
|
11
|
+
|
|
12
|
+
const packageInfo = transaction.moveCall({
|
|
13
|
+
target: `@mvr/metadata::package_info::new`,
|
|
14
|
+
arguments: [transaction.object(upgradeCap)],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// We also need to create the visual representation of our "info" object.
|
|
18
|
+
// You can also call `@mvr/metadata::display::new` instead,
|
|
19
|
+
// that allows customizing the colors of your metadata object!
|
|
20
|
+
const display = transaction.moveCall({
|
|
21
|
+
target: `@mvr/metadata::display::default`,
|
|
22
|
+
arguments: [transaction.pure.string(packageName)],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Set that display object to our info object.
|
|
26
|
+
transaction.moveCall({
|
|
27
|
+
target: `@mvr/metadata::package_info::set_display`,
|
|
28
|
+
arguments: [transaction.object(packageInfo), display],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Set the default for the packageInfo, which enables reverse resolution for that network
|
|
32
|
+
// See details in reverse resolution section
|
|
33
|
+
transaction.moveCall({
|
|
34
|
+
target: "@mvr/metadata::package_info::set_metadata",
|
|
35
|
+
arguments: [
|
|
36
|
+
transaction.object(packageInfo),
|
|
37
|
+
transaction.pure.string("default"),
|
|
38
|
+
transaction.pure.string(mvrName),
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Optionally unset the metadata for the packageInfo
|
|
43
|
+
// transaction.moveCall({
|
|
44
|
+
// target: "@mvr/metadata::package_info::unset_metadata",
|
|
45
|
+
// arguments: [
|
|
46
|
+
// transaction.object(packageInfo),
|
|
47
|
+
// transaction.pure.string("default"),
|
|
48
|
+
// ],
|
|
49
|
+
// });
|
|
50
|
+
|
|
51
|
+
// transfer the `PackageInfo` object to a safe address.
|
|
52
|
+
transaction.moveCall({
|
|
53
|
+
target: `@mvr/metadata::package_info::transfer`,
|
|
54
|
+
arguments: [
|
|
55
|
+
transaction.object(packageInfo),
|
|
56
|
+
transaction.pure.address(safeAddress),
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return transaction;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function publishCodeToMVR(params: {
|
|
64
|
+
packageInfo: string;
|
|
65
|
+
gitRepository: string; // e.g. https://github.com/mystenlabs/mvr
|
|
66
|
+
gitSubdirectory: string; // e.g. packages/mvr
|
|
67
|
+
gitCommitHash: string; // e.g. 636d22d6bc4195afec9a1c0a8563b61fc813acfc
|
|
68
|
+
version: number;
|
|
69
|
+
}): Transaction {
|
|
70
|
+
const {
|
|
71
|
+
packageInfo,
|
|
72
|
+
gitRepository,
|
|
73
|
+
gitSubdirectory,
|
|
74
|
+
gitCommitHash,
|
|
75
|
+
version,
|
|
76
|
+
} = params;
|
|
77
|
+
|
|
78
|
+
const transaction = new Transaction();
|
|
79
|
+
|
|
80
|
+
const git = transaction.moveCall({
|
|
81
|
+
target: `@mvr/metadata::git::new`,
|
|
82
|
+
arguments: [
|
|
83
|
+
transaction.pure.string(gitRepository),
|
|
84
|
+
transaction.pure.string(gitSubdirectory),
|
|
85
|
+
transaction.pure.string(gitCommitHash),
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
transaction.moveCall({
|
|
90
|
+
target: `@mvr/metadata::package_info::set_git_versioning`,
|
|
91
|
+
arguments: [
|
|
92
|
+
transaction.object(packageInfo),
|
|
93
|
+
transaction.pure.u64(version),
|
|
94
|
+
git,
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return transaction;
|
|
99
|
+
}
|