near-kit 0.0.0 → 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.
- package/LICENSE +21 -0
- package/README.md +371 -2
- package/dist/contracts/contract.d.ts +63 -0
- package/dist/contracts/contract.d.ts.map +1 -0
- package/dist/contracts/contract.js +42 -0
- package/dist/contracts/contract.js.map +1 -0
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +5 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/core/actions.d.ts +193 -0
- package/dist/core/actions.d.ts.map +1 -0
- package/dist/core/actions.js +195 -0
- package/dist/core/actions.js.map +1 -0
- package/dist/core/config-schemas.d.ts +179 -0
- package/dist/core/config-schemas.d.ts.map +1 -0
- package/dist/core/config-schemas.js +169 -0
- package/dist/core/config-schemas.js.map +1 -0
- package/dist/core/constants.d.ts +43 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +49 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/near.d.ts +301 -0
- package/dist/core/near.d.ts.map +1 -0
- package/dist/core/near.js +504 -0
- package/dist/core/near.js.map +1 -0
- package/dist/core/nonce-manager.d.ts +39 -0
- package/dist/core/nonce-manager.d.ts.map +1 -0
- package/dist/core/nonce-manager.js +73 -0
- package/dist/core/nonce-manager.js.map +1 -0
- package/dist/core/rpc/rpc-error-handler.d.ts +60 -0
- package/dist/core/rpc/rpc-error-handler.d.ts.map +1 -0
- package/dist/core/rpc/rpc-error-handler.js +324 -0
- package/dist/core/rpc/rpc-error-handler.js.map +1 -0
- package/dist/core/rpc/rpc-schemas.d.ts +1812 -0
- package/dist/core/rpc/rpc-schemas.d.ts.map +1 -0
- package/dist/core/rpc/rpc-schemas.js +424 -0
- package/dist/core/rpc/rpc-schemas.js.map +1 -0
- package/dist/core/rpc/rpc.d.ts +117 -0
- package/dist/core/rpc/rpc.d.ts.map +1 -0
- package/dist/core/rpc/rpc.js +325 -0
- package/dist/core/rpc/rpc.js.map +1 -0
- package/dist/core/schema.d.ts +1188 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +396 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/transaction.d.ts +390 -0
- package/dist/core/transaction.d.ts.map +1 -0
- package/dist/core/transaction.js +649 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/types.d.ts +271 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/errors/index.d.ts +226 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +366 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/keys/credential-schemas.d.ts +98 -0
- package/dist/keys/credential-schemas.d.ts.map +1 -0
- package/dist/keys/credential-schemas.js +128 -0
- package/dist/keys/credential-schemas.js.map +1 -0
- package/dist/keys/file-keystore.d.ts +130 -0
- package/dist/keys/file-keystore.d.ts.map +1 -0
- package/dist/keys/file-keystore.js +266 -0
- package/dist/keys/file-keystore.js.map +1 -0
- package/dist/keys/in-memory-keystore.d.ts +71 -0
- package/dist/keys/in-memory-keystore.d.ts.map +1 -0
- package/dist/keys/in-memory-keystore.js +85 -0
- package/dist/keys/in-memory-keystore.js.map +1 -0
- package/dist/keys/index.d.ts +12 -0
- package/dist/keys/index.d.ts.map +1 -0
- package/dist/keys/index.js +18 -0
- package/dist/keys/index.js.map +1 -0
- package/dist/keys/native-keystore.d.ts +111 -0
- package/dist/keys/native-keystore.d.ts.map +1 -0
- package/dist/keys/native-keystore.js +167 -0
- package/dist/keys/native-keystore.js.map +1 -0
- package/dist/sandbox/index.d.ts +6 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/sandbox.d.ts +55 -0
- package/dist/sandbox/sandbox.d.ts.map +1 -0
- package/dist/sandbox/sandbox.js +341 -0
- package/dist/sandbox/sandbox.js.map +1 -0
- package/dist/utils/amount.d.ts +76 -0
- package/dist/utils/amount.d.ts.map +1 -0
- package/dist/utils/amount.js +137 -0
- package/dist/utils/amount.js.map +1 -0
- package/dist/utils/gas.d.ts +69 -0
- package/dist/utils/gas.d.ts.map +1 -0
- package/dist/utils/gas.js +92 -0
- package/dist/utils/gas.js.map +1 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +14 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/key.d.ts +117 -0
- package/dist/utils/key.d.ts.map +1 -0
- package/dist/utils/key.js +270 -0
- package/dist/utils/key.js.map +1 -0
- package/dist/utils/nep413.d.ts +97 -0
- package/dist/utils/nep413.d.ts.map +1 -0
- package/dist/utils/nep413.js +154 -0
- package/dist/utils/nep413.js.map +1 -0
- package/dist/utils/validation.d.ts +114 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +150 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/wallets/adapters.d.ts +119 -0
- package/dist/wallets/adapters.d.ts.map +1 -0
- package/dist/wallets/adapters.js +267 -0
- package/dist/wallets/adapters.js.map +1 -0
- package/dist/wallets/index.d.ts +11 -0
- package/dist/wallets/index.d.ts.map +1 -0
- package/dist/wallets/index.js +2 -0
- package/dist/wallets/index.js.map +1 -0
- package/dist/wallets/types.d.ts +99 -0
- package/dist/wallets/types.d.ts.map +1 -0
- package/dist/wallets/types.js +10 -0
- package/dist/wallets/types.js.map +1 -0
- package/package.json +78 -7
- package/index.js +0 -1
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NEAR Sandbox - Local testing environment
|
|
3
|
+
*
|
|
4
|
+
* Simple, explicit API for running a local NEAR node for testing.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import { mkdir, mkdtemp, readFile, rm } from "node:fs/promises";
|
|
9
|
+
import { createServer } from "node:net";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { Readable } from "node:stream";
|
|
13
|
+
import { pipeline } from "node:stream/promises";
|
|
14
|
+
import * as tar from "tar";
|
|
15
|
+
const DEFAULT_VERSION = "2.9.0";
|
|
16
|
+
const BINARY_NAME = "near-sandbox";
|
|
17
|
+
const ARCHIVE_NAME = "near-sandbox.tar.gz";
|
|
18
|
+
const DOWNLOAD_BASE = "https://s3-us-west-1.amazonaws.com/build.nearprotocol.com/nearcore";
|
|
19
|
+
const STARTUP_TIMEOUT = 60000;
|
|
20
|
+
const DOWNLOAD_TIMEOUT = 120000;
|
|
21
|
+
/**
|
|
22
|
+
* NEAR Sandbox instance
|
|
23
|
+
*
|
|
24
|
+
* Manages a local NEAR node for testing. Automatically cleans up on stop().
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const sandbox = await Sandbox.start();
|
|
29
|
+
* const near = new Near({ network: sandbox });
|
|
30
|
+
* // ... run tests
|
|
31
|
+
* await sandbox.stop();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export class Sandbox {
|
|
35
|
+
constructor(rpcUrl, networkId, rootAccount, homeDir, childProcess) {
|
|
36
|
+
this.rpcUrl = rpcUrl;
|
|
37
|
+
this.networkId = networkId;
|
|
38
|
+
this.rootAccount = rootAccount;
|
|
39
|
+
this.homeDir = homeDir;
|
|
40
|
+
this.process = childProcess;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Start a new sandbox instance
|
|
44
|
+
*
|
|
45
|
+
* Downloads the sandbox binary if needed, initializes a temporary directory,
|
|
46
|
+
* and starts the sandbox process.
|
|
47
|
+
*
|
|
48
|
+
* @param options - Optional configuration
|
|
49
|
+
* @returns Promise resolving to a running Sandbox instance
|
|
50
|
+
*/
|
|
51
|
+
static async start(options = {}) {
|
|
52
|
+
const version = options.version ?? DEFAULT_VERSION;
|
|
53
|
+
const detached = options.detached ?? true;
|
|
54
|
+
// 1. Ensure binary is available
|
|
55
|
+
const binaryPath = await ensureBinary(version);
|
|
56
|
+
// 2. Create temporary home directory
|
|
57
|
+
const homeDir = await mkdtemp(path.join(os.tmpdir(), "near-sandbox-"));
|
|
58
|
+
// 3. Initialize sandbox
|
|
59
|
+
await runInit(binaryPath, homeDir);
|
|
60
|
+
// 4. Read validator key
|
|
61
|
+
const validatorKey = await loadValidatorKey(homeDir);
|
|
62
|
+
const rootAccount = {
|
|
63
|
+
id: validatorKey.account_id,
|
|
64
|
+
secretKey: validatorKey.secret_key ?? validatorKey.private_key ?? "",
|
|
65
|
+
};
|
|
66
|
+
// 5. Start sandbox process
|
|
67
|
+
const port = await findAvailablePort();
|
|
68
|
+
const networkPort = port + 1;
|
|
69
|
+
const childProcess = spawn(binaryPath, [
|
|
70
|
+
"--home",
|
|
71
|
+
homeDir,
|
|
72
|
+
"run",
|
|
73
|
+
"--rpc-addr",
|
|
74
|
+
`0.0.0.0:${port}`,
|
|
75
|
+
"--network-addr",
|
|
76
|
+
`0.0.0.0:${networkPort}`,
|
|
77
|
+
], {
|
|
78
|
+
detached,
|
|
79
|
+
stdio: detached ? "ignore" : "pipe",
|
|
80
|
+
});
|
|
81
|
+
if (!childProcess.pid) {
|
|
82
|
+
throw new Error("Failed to start sandbox: no PID");
|
|
83
|
+
}
|
|
84
|
+
if (detached) {
|
|
85
|
+
childProcess.unref();
|
|
86
|
+
}
|
|
87
|
+
const rpcUrl = `http://127.0.0.1:${port}`;
|
|
88
|
+
// 6. Wait for RPC to be ready
|
|
89
|
+
await waitForReady(rpcUrl);
|
|
90
|
+
return new Sandbox(rpcUrl, "localnet", rootAccount, homeDir, childProcess);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Stop the sandbox and clean up
|
|
94
|
+
*
|
|
95
|
+
* Kills the sandbox process and removes temporary files.
|
|
96
|
+
*/
|
|
97
|
+
async stop() {
|
|
98
|
+
if (this.process?.pid) {
|
|
99
|
+
const pid = this.process.pid;
|
|
100
|
+
try {
|
|
101
|
+
// Try to kill process group first (for detached processes)
|
|
102
|
+
process.kill(-pid, "SIGTERM");
|
|
103
|
+
await sleep(100);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Try direct kill
|
|
107
|
+
try {
|
|
108
|
+
process.kill(pid, "SIGTERM");
|
|
109
|
+
await sleep(100);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Try SIGKILL as last resort
|
|
113
|
+
try {
|
|
114
|
+
process.kill(pid, "SIGKILL");
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Process already dead
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
this.process = undefined;
|
|
122
|
+
}
|
|
123
|
+
// Clean up temporary directory
|
|
124
|
+
try {
|
|
125
|
+
await rm(this.homeDir, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Ignore cleanup errors
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// ==================== Helper Functions ====================
|
|
133
|
+
/**
|
|
134
|
+
* Get platform identifier for downloading correct binary.
|
|
135
|
+
* @internal
|
|
136
|
+
*/
|
|
137
|
+
function getPlatformId() {
|
|
138
|
+
const system = os.platform();
|
|
139
|
+
const arch = os.arch();
|
|
140
|
+
const platform = system === "darwin" ? "Darwin" : "Linux";
|
|
141
|
+
const normalizedArch = arch === "x64" ? "x86_64" : arch;
|
|
142
|
+
if (!["x86_64", "arm64"].includes(normalizedArch)) {
|
|
143
|
+
throw new Error(`Unsupported architecture: ${arch}`);
|
|
144
|
+
}
|
|
145
|
+
if (system !== "darwin" && system !== "linux") {
|
|
146
|
+
throw new Error(`Unsupported platform: ${system}`);
|
|
147
|
+
}
|
|
148
|
+
return { system: platform, arch: normalizedArch };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get directory for storing sandbox binaries.
|
|
152
|
+
* @internal
|
|
153
|
+
*/
|
|
154
|
+
function getBinaryDir() {
|
|
155
|
+
const dir = path.join(os.homedir(), ".near-kit", "sandbox", "bin");
|
|
156
|
+
return dir;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Download and extract sandbox binary.
|
|
160
|
+
* @internal
|
|
161
|
+
*/
|
|
162
|
+
async function downloadBinary(version) {
|
|
163
|
+
const { system, arch } = getPlatformId();
|
|
164
|
+
const destDir = getBinaryDir();
|
|
165
|
+
const filename = `${BINARY_NAME}-${version}`;
|
|
166
|
+
const dest = path.join(destDir, filename);
|
|
167
|
+
// Return if already exists
|
|
168
|
+
if (fs.existsSync(dest)) {
|
|
169
|
+
return dest;
|
|
170
|
+
}
|
|
171
|
+
const url = `${DOWNLOAD_BASE}/${system}-${arch}/${version}/${ARCHIVE_NAME}`;
|
|
172
|
+
const tmpDir = await mkdtemp(path.join(os.tmpdir(), "near-sandbox-download-"));
|
|
173
|
+
try {
|
|
174
|
+
const archivePath = path.join(tmpDir, ARCHIVE_NAME);
|
|
175
|
+
// Download with timeout
|
|
176
|
+
const controller = new AbortController();
|
|
177
|
+
const timeout = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT);
|
|
178
|
+
try {
|
|
179
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
182
|
+
}
|
|
183
|
+
if (!response.body) {
|
|
184
|
+
throw new Error("Response body is null");
|
|
185
|
+
}
|
|
186
|
+
const stream = fs.createWriteStream(archivePath);
|
|
187
|
+
// Convert DOM ReadableStream to Node.js ReadableStream
|
|
188
|
+
await pipeline(Readable.fromWeb(response.body), stream);
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
clearTimeout(timeout);
|
|
192
|
+
}
|
|
193
|
+
// Extract archive (strip=1 removes top-level directory)
|
|
194
|
+
await tar.x({ file: archivePath, cwd: tmpDir, strip: 1 });
|
|
195
|
+
const extracted = path.join(tmpDir, BINARY_NAME);
|
|
196
|
+
if (!fs.existsSync(extracted)) {
|
|
197
|
+
throw new Error(`Binary ${BINARY_NAME} not found in archive`);
|
|
198
|
+
}
|
|
199
|
+
// Move to final location and make executable
|
|
200
|
+
await mkdir(path.dirname(dest), { recursive: true });
|
|
201
|
+
await fs.promises.rename(extracted, dest);
|
|
202
|
+
await fs.promises.chmod(dest, 0o755);
|
|
203
|
+
return dest;
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
throw new Error(`Failed to download binary from ${url}: ${error}`);
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Ensure binary is available and return its path.
|
|
214
|
+
* @internal
|
|
215
|
+
*/
|
|
216
|
+
async function ensureBinary(version) {
|
|
217
|
+
return await downloadBinary(version);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Run sandbox init command.
|
|
221
|
+
* @internal
|
|
222
|
+
*/
|
|
223
|
+
async function runInit(binaryPath, homeDir) {
|
|
224
|
+
const args = ["--home", homeDir, "init", "--chain-id", "localnet"];
|
|
225
|
+
return new Promise((resolve, reject) => {
|
|
226
|
+
const child = spawn(binaryPath, args, { stdio: "pipe" });
|
|
227
|
+
let stderr = "";
|
|
228
|
+
child.stderr?.on("data", (data) => {
|
|
229
|
+
stderr += data.toString();
|
|
230
|
+
});
|
|
231
|
+
child.on("exit", (code) => {
|
|
232
|
+
if (code === 0) {
|
|
233
|
+
resolve();
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// Provide helpful error message for common issues
|
|
237
|
+
let errorMsg = `Sandbox init failed with code ${code}: ${stderr}`;
|
|
238
|
+
if (stderr.includes("file descriptor limit")) {
|
|
239
|
+
errorMsg +=
|
|
240
|
+
"\n\n" +
|
|
241
|
+
"The sandbox requires at least 65,535 file descriptors.\n" +
|
|
242
|
+
"Current limit can be checked with: ulimit -n\n\n" +
|
|
243
|
+
"To fix on Linux, add to /etc/security/limits.conf:\n" +
|
|
244
|
+
" * soft nofile 65535\n" +
|
|
245
|
+
" * hard nofile 65535\n\n" +
|
|
246
|
+
"To fix on macOS:\n" +
|
|
247
|
+
" sudo launchctl limit maxfiles 65536 200000\n\n" +
|
|
248
|
+
"For Docker, add: --ulimit nofile=65535:65535\n\n" +
|
|
249
|
+
"See: https://github.com/r-near/near-kit/blob/main/src/sandbox/README.md";
|
|
250
|
+
}
|
|
251
|
+
reject(new Error(errorMsg));
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
child.on("error", reject);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Load validator key from sandbox home directory.
|
|
259
|
+
* @internal
|
|
260
|
+
*/
|
|
261
|
+
async function loadValidatorKey(homeDir) {
|
|
262
|
+
const keyPath = path.join(homeDir, "validator_key.json");
|
|
263
|
+
try {
|
|
264
|
+
const data = await readFile(keyPath, "utf8");
|
|
265
|
+
return JSON.parse(data);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
throw new Error(`Failed to read validator key from ${keyPath}: ${error}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Find an available port by letting the OS choose.
|
|
273
|
+
* @internal
|
|
274
|
+
*/
|
|
275
|
+
async function findAvailablePort() {
|
|
276
|
+
return new Promise((resolve, reject) => {
|
|
277
|
+
const server = createServer();
|
|
278
|
+
server.on("error", reject);
|
|
279
|
+
server.listen(0, "127.0.0.1", () => {
|
|
280
|
+
const address = server.address();
|
|
281
|
+
if (!address || typeof address === "string") {
|
|
282
|
+
reject(new Error("Failed to get port"));
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const port = address.port;
|
|
286
|
+
server.close(() => {
|
|
287
|
+
resolve(port);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Ping sandbox RPC endpoint to check if it's ready.
|
|
294
|
+
* @internal
|
|
295
|
+
*/
|
|
296
|
+
async function pingRpc(url, timeoutMs = 1000) {
|
|
297
|
+
const controller = new AbortController();
|
|
298
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
299
|
+
try {
|
|
300
|
+
const response = await fetch(url, {
|
|
301
|
+
method: "POST",
|
|
302
|
+
headers: { "Content-Type": "application/json" },
|
|
303
|
+
body: JSON.stringify({
|
|
304
|
+
jsonrpc: "2.0",
|
|
305
|
+
id: "status",
|
|
306
|
+
method: "status",
|
|
307
|
+
params: [],
|
|
308
|
+
}),
|
|
309
|
+
signal: controller.signal,
|
|
310
|
+
});
|
|
311
|
+
return response.ok;
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
finally {
|
|
317
|
+
clearTimeout(timeout);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Wait for sandbox to be ready.
|
|
322
|
+
* @internal
|
|
323
|
+
*/
|
|
324
|
+
async function waitForReady(rpcUrl, timeout = STARTUP_TIMEOUT) {
|
|
325
|
+
const start = Date.now();
|
|
326
|
+
while (Date.now() - start < timeout) {
|
|
327
|
+
if (await pingRpc(rpcUrl)) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
await sleep(500);
|
|
331
|
+
}
|
|
332
|
+
throw new Error(`Sandbox failed to start within ${timeout}ms`);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Sleep helper.
|
|
336
|
+
* @internal
|
|
337
|
+
*/
|
|
338
|
+
function sleep(ms) {
|
|
339
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/sandbox/sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amount utilities for NEAR tokens.
|
|
3
|
+
*
|
|
4
|
+
* All amounts must specify units explicitly:
|
|
5
|
+
* - `Amount.NEAR(10)` → `"10 NEAR"`
|
|
6
|
+
* - `Amount.yocto(1000n)` → `"1000 yocto"`
|
|
7
|
+
* - `"10 NEAR"` (string literal)
|
|
8
|
+
* - `"1000 yocto"` (string literal)
|
|
9
|
+
* - `1000n` (bigint literal, treated as yoctoNEAR)
|
|
10
|
+
*
|
|
11
|
+
* No bare numbers are accepted in order to prevent accidental unit confusion.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Amount input type - must be a string with unit specification or bigint.
|
|
15
|
+
*
|
|
16
|
+
* Accepts:
|
|
17
|
+
* - Literal strings: "10 NEAR", "10.5 NEAR", "1000 yocto"
|
|
18
|
+
* - Constructor output: Amount.NEAR(10), Amount.yocto(1000n)
|
|
19
|
+
* - Raw bigint: 1000000n (interpreted as yoctoNEAR)
|
|
20
|
+
*
|
|
21
|
+
* For variables, use 'as const' to preserve literal type:
|
|
22
|
+
* @example
|
|
23
|
+
* const amount = "10 NEAR" as const
|
|
24
|
+
* const yocto = 1000000n // Direct bigint is treated as yoctoNEAR
|
|
25
|
+
*/
|
|
26
|
+
export type AmountInput = `${number} NEAR` | `${number}.${number} NEAR` | `${number} yocto` | ReturnType<typeof Amount.NEAR> | ReturnType<typeof Amount.yocto> | bigint;
|
|
27
|
+
/**
|
|
28
|
+
* Amount namespace - explicit constructors for NEAR values.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* Amount.NEAR(10) // "10 NEAR"
|
|
32
|
+
* Amount.NEAR(10.5) // "10.5 NEAR"
|
|
33
|
+
* Amount.NEAR("10.5") // "10.5 NEAR"
|
|
34
|
+
* Amount.yocto(1000000n) // "1000000 yocto"
|
|
35
|
+
* Amount.yocto("1000000") // "1000000 yocto"
|
|
36
|
+
*/
|
|
37
|
+
export declare const Amount: {
|
|
38
|
+
/**
|
|
39
|
+
* Create a NEAR amount.
|
|
40
|
+
* @param value - Amount in NEAR.
|
|
41
|
+
* @returns Formatted string `"X NEAR"`.
|
|
42
|
+
*/
|
|
43
|
+
readonly NEAR: (value: number | string) => string;
|
|
44
|
+
/**
|
|
45
|
+
* Create a yoctoNEAR amount (10^-24 NEAR).
|
|
46
|
+
* @param value - Amount in yoctoNEAR.
|
|
47
|
+
* @returns Formatted string `"X yocto"`.
|
|
48
|
+
*/
|
|
49
|
+
readonly yocto: (value: bigint | string) => string;
|
|
50
|
+
/**
|
|
51
|
+
* Common amount constants.
|
|
52
|
+
*/
|
|
53
|
+
readonly ZERO: "0 yocto";
|
|
54
|
+
readonly ONE_NEAR: "1 NEAR";
|
|
55
|
+
readonly ONE_YOCTO: "1 yocto";
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Parse amount to yoctoNEAR.
|
|
59
|
+
*
|
|
60
|
+
* @param amount - Amount with unit (e.g., `"10 NEAR"`, `"1000 yocto"`) or bigint (treated as yoctoNEAR).
|
|
61
|
+
* @returns Amount in yoctoNEAR as a string.
|
|
62
|
+
* @throws Error If the format is invalid or ambiguous (e.g. bare numbers).
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseAmount(amount: AmountInput): string;
|
|
65
|
+
/**
|
|
66
|
+
* Format yoctoNEAR to human-readable NEAR
|
|
67
|
+
* @param yocto - Amount in yoctoNEAR
|
|
68
|
+
* @param options - Formatting options
|
|
69
|
+
* @returns Formatted string (e.g., "10.50 NEAR")
|
|
70
|
+
*/
|
|
71
|
+
export declare function formatAmount(yocto: string | bigint, options?: {
|
|
72
|
+
precision?: number;
|
|
73
|
+
includeSuffix?: boolean;
|
|
74
|
+
trimZeros?: boolean;
|
|
75
|
+
}): string;
|
|
76
|
+
//# sourceMappingURL=amount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount.d.ts","sourceRoot":"","sources":["../../src/utils/amount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,WAAW,GACnB,GAAG,MAAM,OAAO,GAChB,GAAG,MAAM,IAAI,MAAM,OAAO,GAC1B,GAAG,MAAM,QAAQ,GACjB,UAAU,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,GAC9B,UAAU,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,GAC/B,MAAM,CAAA;AAEV;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;IACjB;;;;OAIG;2BACS,MAAM,GAAG,MAAM,KAAG,MAAM;IAIpC;;;;OAIG;4BACU,MAAM,GAAG,MAAM,KAAG,MAAM;IAIrC;;OAEG;;;;CAIK,CAAA;AAEV;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CA+CvD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GACA,MAAM,CA4BR"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amount utilities for NEAR tokens.
|
|
3
|
+
*
|
|
4
|
+
* All amounts must specify units explicitly:
|
|
5
|
+
* - `Amount.NEAR(10)` → `"10 NEAR"`
|
|
6
|
+
* - `Amount.yocto(1000n)` → `"1000 yocto"`
|
|
7
|
+
* - `"10 NEAR"` (string literal)
|
|
8
|
+
* - `"1000 yocto"` (string literal)
|
|
9
|
+
* - `1000n` (bigint literal, treated as yoctoNEAR)
|
|
10
|
+
*
|
|
11
|
+
* No bare numbers are accepted in order to prevent accidental unit confusion.
|
|
12
|
+
*/
|
|
13
|
+
import { YOCTO_PER_NEAR } from "../core/constants.js";
|
|
14
|
+
/**
|
|
15
|
+
* Amount namespace - explicit constructors for NEAR values.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* Amount.NEAR(10) // "10 NEAR"
|
|
19
|
+
* Amount.NEAR(10.5) // "10.5 NEAR"
|
|
20
|
+
* Amount.NEAR("10.5") // "10.5 NEAR"
|
|
21
|
+
* Amount.yocto(1000000n) // "1000000 yocto"
|
|
22
|
+
* Amount.yocto("1000000") // "1000000 yocto"
|
|
23
|
+
*/
|
|
24
|
+
export const Amount = {
|
|
25
|
+
/**
|
|
26
|
+
* Create a NEAR amount.
|
|
27
|
+
* @param value - Amount in NEAR.
|
|
28
|
+
* @returns Formatted string `"X NEAR"`.
|
|
29
|
+
*/
|
|
30
|
+
NEAR(value) {
|
|
31
|
+
return `${value} NEAR`;
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Create a yoctoNEAR amount (10^-24 NEAR).
|
|
35
|
+
* @param value - Amount in yoctoNEAR.
|
|
36
|
+
* @returns Formatted string `"X yocto"`.
|
|
37
|
+
*/
|
|
38
|
+
yocto(value) {
|
|
39
|
+
return `${value} yocto`;
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Common amount constants.
|
|
43
|
+
*/
|
|
44
|
+
ZERO: "0 yocto",
|
|
45
|
+
ONE_NEAR: "1 NEAR",
|
|
46
|
+
ONE_YOCTO: "1 yocto",
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Parse amount to yoctoNEAR.
|
|
50
|
+
*
|
|
51
|
+
* @param amount - Amount with unit (e.g., `"10 NEAR"`, `"1000 yocto"`) or bigint (treated as yoctoNEAR).
|
|
52
|
+
* @returns Amount in yoctoNEAR as a string.
|
|
53
|
+
* @throws Error If the format is invalid or ambiguous (e.g. bare numbers).
|
|
54
|
+
*/
|
|
55
|
+
export function parseAmount(amount) {
|
|
56
|
+
// Handle bigint directly (treated as yoctoNEAR)
|
|
57
|
+
if (typeof amount === "bigint") {
|
|
58
|
+
return amount.toString();
|
|
59
|
+
}
|
|
60
|
+
const trimmed = amount.trim();
|
|
61
|
+
// Parse "X NEAR" format (case insensitive)
|
|
62
|
+
const nearMatch = trimmed.match(/^([\d.]+)\s+NEAR$/i);
|
|
63
|
+
if (nearMatch) {
|
|
64
|
+
// Safe to use non-null assertion after match check
|
|
65
|
+
// biome-ignore lint/style/noNonNullAssertion: regex capture group guaranteed to exist when match succeeds
|
|
66
|
+
const value = nearMatch[1];
|
|
67
|
+
return parseNearToYocto(value);
|
|
68
|
+
}
|
|
69
|
+
// Parse "X yocto" format
|
|
70
|
+
const yoctoMatch = trimmed.match(/^(\d+)\s+yocto$/i);
|
|
71
|
+
if (yoctoMatch) {
|
|
72
|
+
// Safe to use non-null assertion after match check
|
|
73
|
+
// biome-ignore lint/style/noNonNullAssertion: regex capture group guaranteed to exist when match succeeds
|
|
74
|
+
return yoctoMatch[1];
|
|
75
|
+
}
|
|
76
|
+
// Common mistake: bare number
|
|
77
|
+
if (/^[\d.]+$/.test(trimmed)) {
|
|
78
|
+
throw new Error(`Ambiguous amount: "${amount}". Did you mean "${amount} NEAR"?\n` +
|
|
79
|
+
` - Use Amount.NEAR(${amount}) for NEAR\n` +
|
|
80
|
+
` - Use Amount.yocto(${amount}n) for yoctoNEAR\n` +
|
|
81
|
+
` - Or write "${amount} NEAR" or "${amount} yocto"\n` +
|
|
82
|
+
` - Or pass ${amount}n as bigint for yoctoNEAR\n` +
|
|
83
|
+
`\n` +
|
|
84
|
+
`💡 TypeScript tip: Use 'as const' for variables:\n` +
|
|
85
|
+
` const amount = "10 NEAR" as const`);
|
|
86
|
+
}
|
|
87
|
+
// Invalid format
|
|
88
|
+
throw new Error(`Invalid amount format: "${amount}"\n` +
|
|
89
|
+
`Expected formats:\n` +
|
|
90
|
+
` - "10 NEAR" or Amount.NEAR(10)\n` +
|
|
91
|
+
` - "1000000 yocto" or Amount.yocto(1000000n)\n` +
|
|
92
|
+
` - 1000000n (bigint, treated as yoctoNEAR)`);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Format yoctoNEAR to human-readable NEAR
|
|
96
|
+
* @param yocto - Amount in yoctoNEAR
|
|
97
|
+
* @param options - Formatting options
|
|
98
|
+
* @returns Formatted string (e.g., "10.50 NEAR")
|
|
99
|
+
*/
|
|
100
|
+
export function formatAmount(yocto, options) {
|
|
101
|
+
const { precision = 2, includeSuffix = true, trimZeros = false, } = options || {};
|
|
102
|
+
const amount = typeof yocto === "string" ? BigInt(yocto) : yocto;
|
|
103
|
+
const wholePart = amount / YOCTO_PER_NEAR;
|
|
104
|
+
const fracPart = amount % YOCTO_PER_NEAR;
|
|
105
|
+
let result;
|
|
106
|
+
if (fracPart === BigInt(0)) {
|
|
107
|
+
result = wholePart.toString();
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const fracStr = fracPart.toString().padStart(24, "0");
|
|
111
|
+
let decimals = fracStr.substring(0, precision);
|
|
112
|
+
if (trimZeros) {
|
|
113
|
+
decimals = decimals.replace(/0+$/, "");
|
|
114
|
+
}
|
|
115
|
+
result = decimals ? `${wholePart}.${decimals}` : wholePart.toString();
|
|
116
|
+
}
|
|
117
|
+
return includeSuffix ? `${result} NEAR` : result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Internal: Parse NEAR value to yoctoNEAR
|
|
121
|
+
* Note: The caller (parseAmount) already validates the format with the same regex,
|
|
122
|
+
* so the value is guaranteed to match [\d.]+ pattern when it reaches this function.
|
|
123
|
+
*/
|
|
124
|
+
function parseNearToYocto(value) {
|
|
125
|
+
// Split into whole and fractional parts
|
|
126
|
+
const parts = value.split(".");
|
|
127
|
+
const wholePart = parts[0] || "0";
|
|
128
|
+
const fracPart = (parts[1] || "").padEnd(24, "0").substring(0, 24);
|
|
129
|
+
// Check for negative values
|
|
130
|
+
if (wholePart.startsWith("-")) {
|
|
131
|
+
throw new Error("NEAR amount must be non-negative");
|
|
132
|
+
}
|
|
133
|
+
// Convert to yoctoNEAR
|
|
134
|
+
const yocto = BigInt(wholePart) * YOCTO_PER_NEAR + BigInt(fracPart);
|
|
135
|
+
return yocto.toString();
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=amount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount.js","sourceRoot":"","sources":["../../src/utils/amount.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gas utilities for NEAR transactions.
|
|
3
|
+
*
|
|
4
|
+
* Gas amounts should specify units explicitly:
|
|
5
|
+
* - `Gas.Tgas(30)` → `"30 Tgas"`
|
|
6
|
+
* - `"30 Tgas"` (string literal)
|
|
7
|
+
*
|
|
8
|
+
* Raw gas units (e.g. `"30000000000000"`) are also supported for advanced use cases.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Gas input type - string with unit specification.
|
|
12
|
+
*
|
|
13
|
+
* Accepts:
|
|
14
|
+
* - Literal strings: "30 Tgas", "30.5 Tgas"
|
|
15
|
+
* - Raw gas strings: "30000000000000"
|
|
16
|
+
* - Constructor output: Gas.Tgas(30)
|
|
17
|
+
*
|
|
18
|
+
* For variables, use 'as const' to preserve literal type:
|
|
19
|
+
* @example
|
|
20
|
+
* const gas = "30 Tgas" as const
|
|
21
|
+
*/
|
|
22
|
+
export type GasInput = `${number} Tgas` | `${number}.${number} Tgas` | `${number}` | ReturnType<typeof Gas.Tgas>;
|
|
23
|
+
/**
|
|
24
|
+
* Gas namespace - explicit constructors.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* Gas.Tgas(30) // "30 Tgas"
|
|
28
|
+
* Gas.Tgas(300) // "300 Tgas"
|
|
29
|
+
*/
|
|
30
|
+
export declare const Gas: {
|
|
31
|
+
/**
|
|
32
|
+
* Create gas amount in TGas (teragas).
|
|
33
|
+
* @param value - Amount in TGas.
|
|
34
|
+
*/
|
|
35
|
+
readonly Tgas: (value: number | string) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Common gas amounts.
|
|
38
|
+
*/
|
|
39
|
+
readonly DEFAULT: "30 Tgas";
|
|
40
|
+
readonly MAX: "300 Tgas";
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Parse gas string to raw gas units.
|
|
44
|
+
*
|
|
45
|
+
* @param gas - Gas with unit (e.g., `"30 Tgas"`) or raw gas number.
|
|
46
|
+
* @returns Gas in raw units as a string.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseGas(gas: GasInput | number): string;
|
|
49
|
+
/**
|
|
50
|
+
* Format gas to TGas.
|
|
51
|
+
*
|
|
52
|
+
* @param gas - Gas in raw units.
|
|
53
|
+
* @param precision - Decimal places (default: 2).
|
|
54
|
+
* @returns Formatted gas with `' Tgas'` suffix.
|
|
55
|
+
*/
|
|
56
|
+
export declare function formatGas(gas: string | bigint, precision?: number): string;
|
|
57
|
+
/**
|
|
58
|
+
* Convert TGas to raw gas units.
|
|
59
|
+
* @param tgas - Amount in TGas.
|
|
60
|
+
* @returns Gas amount as string.
|
|
61
|
+
*/
|
|
62
|
+
export declare function toGas(tgas: number): string;
|
|
63
|
+
/**
|
|
64
|
+
* Convert raw gas to TGas.
|
|
65
|
+
* @param gas - Gas amount in raw units.
|
|
66
|
+
* @returns Amount in TGas.
|
|
67
|
+
*/
|
|
68
|
+
export declare function toTGas(gas: string | bigint): number;
|
|
69
|
+
//# sourceMappingURL=gas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gas.d.ts","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,QAAQ,GAChB,GAAG,MAAM,OAAO,GAChB,GAAG,MAAM,IAAI,MAAM,OAAO,GAC1B,GAAG,MAAM,EAAE,GACX,UAAU,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAA;AAE/B;;;;;;GAMG;AACH,eAAO,MAAM,GAAG;IACd;;;OAGG;2BACS,MAAM,GAAG,MAAM,KAAG,MAAM;IAIpC;;OAEG;;;CAGK,CAAA;AAEV;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CA6BvD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,SAAI,GAAG,MAAM,CAIrE;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGnD"}
|