everything-dev 1.33.4 → 1.33.7

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/dist/near-cli.cjs CHANGED
@@ -13,12 +13,6 @@ var NearCliNotFoundError = class extends Error {
13
13
  super("NEAR CLI not found");
14
14
  }
15
15
  };
16
- var NearCliInstallError = class extends Error {
17
- _tag = "NearCliInstallError";
18
- constructor(message) {
19
- super(`Failed to install NEAR CLI: ${message}`);
20
- }
21
- };
22
16
  var NearTransactionError = class extends Error {
23
17
  _tag = "NearTransactionError";
24
18
  };
@@ -73,32 +67,25 @@ const checkNearCliInstalled = effect.Effect.tryPromise({
73
67
  },
74
68
  catch: () => /* @__PURE__ */ new Error("Failed to check NEAR CLI")
75
69
  });
76
- const installNearCli = effect.Effect.tryPromise({
77
- try: async () => {
78
- await (0, execa.execa)("sh", ["-c", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {
79
- stdin: "ignore",
80
- stdout: "inherit",
81
- stderr: "inherit"
82
- });
83
- },
84
- catch: (error) => {
85
- if (error instanceof Error && "exitCode" in error) return new NearCliInstallError(`Installer exited with code ${error.exitCode}`);
86
- return new NearCliInstallError(error instanceof Error ? error.message : String(error));
87
- }
88
- });
89
70
  async function runNearCommand(args) {
71
+ if (!process.stdin.isTTY) throw new NearTransactionError("No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
90
72
  await (0, execa.execa)("near", args, {
91
- stdin: "pipe",
73
+ stdin: "inherit",
92
74
  stdout: "inherit",
93
75
  stderr: "inherit"
94
76
  });
95
77
  }
78
+ function resolveNearSigningMode(privateKey) {
79
+ if (privateKey) return {
80
+ _tag: "privateKey",
81
+ privateKey
82
+ };
83
+ if (!process.stdin.isTTY) throw new NearTransactionError("No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
84
+ console.log(require_theme.colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
85
+ return { _tag: "interactiveKeychain" };
86
+ }
96
87
  const ensureNearCli = effect.Effect.gen(function* () {
97
88
  if (yield* checkNearCliInstalled) return;
98
- if (process.env.BOS_INSTALL_NEAR_CLI === "true") {
99
- yield* installNearCli;
100
- return;
101
- }
102
89
  console.log();
103
90
  console.log(" NEAR CLI not found");
104
91
  console.log();
@@ -106,7 +93,14 @@ const ensureNearCli = effect.Effect.gen(function* () {
106
93
  console.log();
107
94
  yield* effect.Effect.fail(new NearCliNotFoundError());
108
95
  });
109
- const executeTransaction = (config) => effect.Effect.gen(function* () {
96
+ function combineNearOutput(stdout, stderr) {
97
+ return [stdout, stderr].filter((value) => value && value.trim().length > 0).join("\n");
98
+ }
99
+ function extractTransactionHash(output) {
100
+ return output.match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
101
+ }
102
+ const executeTransaction = (config, signingMode) => effect.Effect.gen(function* () {
103
+ const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);
110
104
  const gas = (config.gas || "300Tgas").replace(/\s+/g, "");
111
105
  const deposit = (config.deposit || "0NEAR").replace(/\s+/g, "");
112
106
  const network = config.network || (config.account.endsWith(".testnet") ? "testnet" : "mainnet");
@@ -127,49 +121,48 @@ const executeTransaction = (config) => effect.Effect.gen(function* () {
127
121
  "network-config",
128
122
  network
129
123
  ];
130
- if (config.privateKey) args.push("sign-with-plaintext-private-key", config.privateKey, "send");
131
- else {
132
- if (!process.stdin.isTTY) throw new NearTransactionError("No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
133
- console.log(require_theme.colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
134
- args.push("sign-with-keychain", "send");
135
- }
136
- const txHashMatch = (yield* effect.Effect.tryPromise({
124
+ if (resolvedSigningMode._tag === "privateKey") args.push("sign-with-plaintext-private-key", resolvedSigningMode.privateKey, "send");
125
+ else args.push("sign-with-keychain", "send");
126
+ const output = yield* effect.Effect.tryPromise({
137
127
  try: async () => {
128
+ const isPrivateKeyMode = resolvedSigningMode._tag === "privateKey";
138
129
  const proc = (0, execa.execa)("near", args, {
139
- stdin: config.privateKey ? "ignore" : "inherit",
140
- stdout: "pipe",
141
- stderr: "pipe",
130
+ stdin: isPrivateKeyMode ? "ignore" : "inherit",
131
+ stdout: isPrivateKeyMode ? "pipe" : "inherit",
132
+ stderr: isPrivateKeyMode ? "pipe" : "inherit",
142
133
  reject: false,
143
134
  timeout: 300 * 1e3
144
135
  });
145
- let stdout = "";
146
- let stderr = "";
147
- proc.stdout?.on("data", (chunk) => {
148
- stdout += chunk.toString();
149
- process.stdout.write(chunk);
150
- });
151
- proc.stderr?.on("data", (chunk) => {
152
- stderr += chunk.toString();
153
- process.stderr.write(chunk);
154
- });
136
+ if (isPrivateKeyMode) {
137
+ proc.stdout?.on("data", (chunk) => {
138
+ process.stdout.write(chunk);
139
+ });
140
+ proc.stderr?.on("data", (chunk) => {
141
+ process.stderr.write(chunk);
142
+ });
143
+ }
155
144
  const result = await proc;
156
- const combined = `${stdout}\n${stderr}`;
157
- const txHashMatch = combined.match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
145
+ const combined = combineNearOutput(result.stdout, result.stderr);
146
+ const txHash = extractTransactionHash(combined);
158
147
  const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);
159
148
  const hasTransactionFailed = /Transaction failed/i.test(combined);
160
- const softSuccess = Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;
149
+ const softSuccess = Boolean(txHash) && hasCodeDoesNotExist && hasTransactionFailed;
161
150
  if (result.exitCode === 0 || softSuccess) {
162
- if (softSuccess) console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);
163
- return combined;
151
+ if (softSuccess) console.log(` ${txHash} — FastDATA CodeDoesNotExist (expected)`);
152
+ return {
153
+ success: true,
154
+ txHash,
155
+ output: combined || void 0
156
+ };
164
157
  }
165
- throw new NearTransactionError(result.stderr || `Transaction failed with code ${result.exitCode}`);
158
+ throw new NearTransactionError(combined || `Transaction failed with code ${result.exitCode}`);
166
159
  },
167
160
  catch: (error) => error
168
- })).match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
169
- if (!txHashMatch?.[1]) throw new NearTransactionError("Transaction hash missing from NEAR CLI output");
161
+ });
170
162
  return {
171
163
  success: true,
172
- txHash: txHashMatch[1]
164
+ txHash: output.txHash,
165
+ output: output.output
173
166
  };
174
167
  });
175
168
  async function addFunctionCallAccessKey(config) {
@@ -199,4 +192,5 @@ async function addFunctionCallAccessKey(config) {
199
192
  exports.addFunctionCallAccessKey = addFunctionCallAccessKey;
200
193
  exports.ensureNearCli = ensureNearCli;
201
194
  exports.executeTransaction = executeTransaction;
195
+ exports.resolveNearSigningMode = resolveNearSigningMode;
202
196
  //# sourceMappingURL=near-cli.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"near-cli.cjs","names":["Effect","colors"],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: boolean;\n txHash?: string;\n error?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearCliInstallError extends Error {\n readonly _tag = \"NearCliInstallError\";\n constructor(message: string) {\n super(`Failed to install NEAR CLI: ${message}`);\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nconst installNearCli = Effect.tryPromise({\n try: async () => {\n await execa(\"sh\", [\"-c\", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {\n stdin: \"ignore\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n },\n catch: (error) => {\n if (error instanceof Error && \"exitCode\" in error) {\n return new NearCliInstallError(\n `Installer exited with code ${(error as { exitCode: number }).exitCode}`,\n );\n }\n return new NearCliInstallError(error instanceof Error ? error.message : String(error));\n },\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n await execa(\"near\", args, { stdin: \"pipe\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n if (process.env.BOS_INSTALL_NEAR_CLI === \"true\") {\n yield* installNearCli;\n return;\n }\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (config.privateKey) {\n args.push(\"sign-with-plaintext-private-key\", config.privateKey, \"send\");\n } else {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const proc = execa(\"near\", args, {\n stdin: config.privateKey ? \"ignore\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString();\n process.stdout.write(chunk);\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n process.stderr.write(chunk);\n });\n\n const result = await proc;\n const combined = `${stdout}\\n${stderr}`;\n const txHashMatch = combined.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess =\n Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);\n }\n return combined;\n }\n\n throw new NearTransactionError(\n result.stderr || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n const txHashMatch = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n if (!txHashMatch?.[1]) {\n throw new NearTransactionError(\"Transaction hash missing from NEAR CLI output\");\n }\n\n return {\n success: true,\n txHash: txHashMatch[1],\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":";;;;;;;AAoCA,MAAM,gBAAgB;AACtB,MAAM,kBAAkB;AAExB,IAAa,uBAAb,cAA0C,MAAM;CAC9C,AAAS,OAAO;CAChB,cAAc;AACZ,QAAM,qBAAqB;;;AAI/B,IAAa,sBAAb,cAAyC,MAAM;CAC7C,AAAS,OAAO;CAChB,YAAY,SAAiB;AAC3B,QAAM,+BAA+B,UAAU;;;AAInD,IAAa,uBAAb,cAA0C,MAAM;CAC9C,AAAS,OAAO;;AAGlB,SAAS,iBAAiB,OAA2B;CACnD,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,IAAI;AAC9D,QAAO,IAAI,WAAW,OAAO,KAAK,YAAY,SAAS,CAAC;;AAG1D,SAAS,aAAa,OAA2B;AAC/C,KAAI,MAAM,WAAW,EAAG,QAAO;CAE/B,MAAM,SAAmB,CAAC,EAAE;AAC5B,MAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,QAAQ;AACZ,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAS,OAAO,MAAO;AACvB,UAAO,KAAK,QAAQ;AACpB,WAAQ,KAAK,MAAM,QAAQ,GAAG;;AAEhC,SAAO,QAAQ,GAAG;AAChB,UAAO,KAAK,QAAQ,GAAG;AACvB,WAAQ,KAAK,MAAM,QAAQ,GAAG;;;CAIlC,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,MACjB,KAAI,SAAS,EAAG,WAAU,gBAAgB;KACrC;AAGP,MAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,IACtC,WAAU,gBAAgB,OAAO;AAGnC,QAAO;;AAGT,SAAgB,sBAAmC;CACjD,MAAM,EAAE,WAAW,oDAAmC,UAAU;CAChE,MAAM,YAAY,UAAU,OAAO,EAAE,QAAQ,OAAO,CAAC;CACrD,MAAM,aAAa,WAAW,OAAO,EAAE,QAAQ,OAAO,CAAC;AAEvD,KAAI,CAAC,UAAU,KAAK,CAAC,WAAW,EAC9B,OAAM,IAAI,MAAM,kCAAkC;CAGpD,MAAM,cAAc,iBAAiB,UAAU,EAAE;CACjD,MAAM,cAAc,iBAAiB,WAAW,EAAE;CAClD,MAAM,cAAc,IAAI,WAAW,YAAY,SAAS,YAAY,OAAO;AAC3E,aAAY,IAAI,aAAa,EAAE;AAC/B,aAAY,IAAI,aAAa,YAAY,OAAO;AAEhD,QAAO;EACL,WAAW,WAAW,aAAa,YAAY;EAC/C,YAAY,WAAW,aAAa,YAAY;EACjD;;AAGH,MAAM,wBAAwBA,cAAO,WAAW;CAC9C,KAAK,YAAY;AACf,MAAI;AACF,0BAAY,QAAQ,CAAC,YAAY,EAAE,EAAE,OAAO,QAAQ,CAAC;AACrD,UAAO;UACD;AACN,UAAO;;;CAGX,6BAAa,IAAI,MAAM,2BAA2B;CACnD,CAAC;AAEF,MAAM,iBAAiBA,cAAO,WAAW;CACvC,KAAK,YAAY;AACf,yBAAY,MAAM,CAAC,MAAM,yCAAyC,cAAc,OAAO,EAAE;GACvF,OAAO;GACP,QAAQ;GACR,QAAQ;GACT,CAAC;;CAEJ,QAAQ,UAAU;AAChB,MAAI,iBAAiB,SAAS,cAAc,MAC1C,QAAO,IAAI,oBACT,8BAA+B,MAA+B,WAC/D;AAEH,SAAO,IAAI,oBAAoB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;;CAEzF,CAAC;AAEF,eAAe,eAAe,MAA+B;AAC3D,wBAAY,QAAQ,MAAM;EAAE,OAAO;EAAQ,QAAQ;EAAW,QAAQ;EAAW,CAAC;;AAGpF,MAAa,gBAAgBA,cAAO,IAAI,aAAa;AAEnD,KAAI,OADuB,sBACV;AAEjB,KAAI,QAAQ,IAAI,yBAAyB,QAAQ;AAC/C,SAAO;AACP;;AAGF,SAAQ,KAAK;AACb,SAAQ,IAAI,uBAAuB;AAEnC,SAAQ,KAAK;AACb,SAAQ,IAAI,gEAAgE,cAAc,OAAO;AACjG,SAAQ,KAAK;AACb,QAAOA,cAAO,KAAK,IAAI,sBAAsB,CAAC;EAC9C;AAEF,MAAa,sBACX,WAEAA,cAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAO,OAAO,WAAW,QAAQ,QAAQ,GAAG;CACzD,MAAM,WAAW,OAAO,WAAW,SAAS,QAAQ,QAAQ,GAAG;CAC/D,MAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,SAAS,WAAW,GAAG,YAAY;CAErF,MAAM,OAAO;EACX;EACA;EACA;EACA,OAAO;EACP,OAAO;EACP;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;EACD;AAED,KAAI,OAAO,WACT,MAAK,KAAK,mCAAmC,OAAO,YAAY,OAAO;MAClE;AACL,MAAI,CAAC,QAAQ,MAAM,MACjB,OAAM,IAAI,qBACR,gIACD;AAEH,UAAQ,IACNC,qBAAO,OACL,qFACD,CACF;AACD,OAAK,KAAK,sBAAsB,OAAO;;CAgDzC,MAAM,eAAc,OA7CED,cAAO,WAAW;EACtC,KAAK,YAAY;GACf,MAAM,wBAAa,QAAQ,MAAM;IAC/B,OAAO,OAAO,aAAa,WAAW;IACtC,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS,MAAS;IACnB,CAAC;GAEF,IAAI,SAAS;GACb,IAAI,SAAS;AAEb,QAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,cAAU,MAAM,UAAU;AAC1B,YAAQ,OAAO,MAAM,MAAM;KAC3B;AAEF,QAAK,QAAQ,GAAG,SAAS,UAAkB;AACzC,cAAU,MAAM,UAAU;AAC1B,YAAQ,OAAO,MAAM,MAAM;KAC3B;GAEF,MAAM,SAAS,MAAM;GACrB,MAAM,WAAW,GAAG,OAAO,IAAI;GAC/B,MAAM,cAAc,SAAS,MAAM,oCAAoC;GACvE,MAAM,sBAAsB,oBAAoB,KAAK,SAAS;GAC9D,MAAM,uBAAuB,sBAAsB,KAAK,SAAS;GACjE,MAAM,cACJ,QAAQ,cAAc,GAAG,IAAI,uBAAuB;AAEtD,OAAI,OAAO,aAAa,KAAK,aAAa;AACxC,QAAI,YACF,SAAQ,IAAI,KAAK,cAAc,GAAG,yCAAyC;AAE7E,WAAO;;AAGT,SAAM,IAAI,qBACR,OAAO,UAAU,gCAAgC,OAAO,WACzD;;EAEH,QAAQ,UAAU;EACnB,CAAC,EAEyB,MAAM,oCAAoC;AACrE,KAAI,CAAC,cAAc,GACjB,OAAM,IAAI,qBAAqB,gDAAgD;AAGjF,QAAO;EACL,SAAS;EACT,QAAQ,YAAY;EACrB;EACD;AAEJ,eAAsB,yBACpB,QACsB;CACtB,MAAM,UAAU,qBAAqB;AAoBrC,OAAM,eAAe;EAlBnB;EACA;EACA,OAAO;EACP;EACA;EACA,OAAO;EACP;EACA,OAAO;EACP;EACA,OAAO,cAAc,KAAK,KAAK;EAC/B;EACA,QAAQ;EACR;EACA,OAAO,YAAY,OAAO,QAAQ,SAAS,WAAW,GAAG,YAAY;EACrE;EACA;EAGuB,CAAC;AAC1B,QAAO"}
1
+ {"version":3,"file":"near-cli.cjs","names":["Effect","colors"],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: true;\n txHash?: string;\n output?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nexport type NearSigningMode =\n | { _tag: \"privateKey\"; privateKey: string }\n | { _tag: \"interactiveKeychain\" };\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n await execa(\"near\", args, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport function resolveNearSigningMode(privateKey?: string): NearSigningMode {\n if (privateKey) {\n return { _tag: \"privateKey\", privateKey };\n }\n\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n return { _tag: \"interactiveKeychain\" };\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nfunction combineNearOutput(stdout?: string, stderr?: string): string {\n return [stdout, stderr].filter((value) => value && value.trim().length > 0).join(\"\\n\");\n}\n\nfunction extractTransactionHash(output: string): string | undefined {\n const match = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n signingMode?: NearSigningMode,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (resolvedSigningMode._tag === \"privateKey\") {\n args.push(\"sign-with-plaintext-private-key\", resolvedSigningMode.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const isPrivateKeyMode = resolvedSigningMode._tag === \"privateKey\";\n const proc = execa(\"near\", args, {\n stdin: isPrivateKeyMode ? \"ignore\" : \"inherit\",\n stdout: isPrivateKeyMode ? \"pipe\" : \"inherit\",\n stderr: isPrivateKeyMode ? \"pipe\" : \"inherit\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n if (isPrivateKeyMode) {\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(chunk);\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n }\n\n const result = await proc;\n const combined = combineNearOutput(result.stdout, result.stderr);\n const txHash = extractTransactionHash(combined);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess = Boolean(txHash) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHash} — FastDATA CodeDoesNotExist (expected)`);\n }\n return {\n success: true,\n txHash,\n output: combined || undefined,\n };\n }\n\n throw new NearTransactionError(\n combined || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n return {\n success: true,\n txHash: output.txHash,\n output: output.output,\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
package/dist/near-cli.mjs CHANGED
@@ -12,12 +12,6 @@ var NearCliNotFoundError = class extends Error {
12
12
  super("NEAR CLI not found");
13
13
  }
14
14
  };
15
- var NearCliInstallError = class extends Error {
16
- _tag = "NearCliInstallError";
17
- constructor(message) {
18
- super(`Failed to install NEAR CLI: ${message}`);
19
- }
20
- };
21
15
  var NearTransactionError = class extends Error {
22
16
  _tag = "NearTransactionError";
23
17
  };
@@ -72,32 +66,25 @@ const checkNearCliInstalled = Effect.tryPromise({
72
66
  },
73
67
  catch: () => /* @__PURE__ */ new Error("Failed to check NEAR CLI")
74
68
  });
75
- const installNearCli = Effect.tryPromise({
76
- try: async () => {
77
- await execa("sh", ["-c", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {
78
- stdin: "ignore",
79
- stdout: "inherit",
80
- stderr: "inherit"
81
- });
82
- },
83
- catch: (error) => {
84
- if (error instanceof Error && "exitCode" in error) return new NearCliInstallError(`Installer exited with code ${error.exitCode}`);
85
- return new NearCliInstallError(error instanceof Error ? error.message : String(error));
86
- }
87
- });
88
69
  async function runNearCommand(args) {
70
+ if (!process.stdin.isTTY) throw new NearTransactionError("No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
89
71
  await execa("near", args, {
90
- stdin: "pipe",
72
+ stdin: "inherit",
91
73
  stdout: "inherit",
92
74
  stderr: "inherit"
93
75
  });
94
76
  }
77
+ function resolveNearSigningMode(privateKey) {
78
+ if (privateKey) return {
79
+ _tag: "privateKey",
80
+ privateKey
81
+ };
82
+ if (!process.stdin.isTTY) throw new NearTransactionError("No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
83
+ console.log(colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
84
+ return { _tag: "interactiveKeychain" };
85
+ }
95
86
  const ensureNearCli = Effect.gen(function* () {
96
87
  if (yield* checkNearCliInstalled) return;
97
- if (process.env.BOS_INSTALL_NEAR_CLI === "true") {
98
- yield* installNearCli;
99
- return;
100
- }
101
88
  console.log();
102
89
  console.log(" NEAR CLI not found");
103
90
  console.log();
@@ -105,7 +92,14 @@ const ensureNearCli = Effect.gen(function* () {
105
92
  console.log();
106
93
  yield* Effect.fail(new NearCliNotFoundError());
107
94
  });
108
- const executeTransaction = (config) => Effect.gen(function* () {
95
+ function combineNearOutput(stdout, stderr) {
96
+ return [stdout, stderr].filter((value) => value && value.trim().length > 0).join("\n");
97
+ }
98
+ function extractTransactionHash(output) {
99
+ return output.match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
100
+ }
101
+ const executeTransaction = (config, signingMode) => Effect.gen(function* () {
102
+ const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);
109
103
  const gas = (config.gas || "300Tgas").replace(/\s+/g, "");
110
104
  const deposit = (config.deposit || "0NEAR").replace(/\s+/g, "");
111
105
  const network = config.network || (config.account.endsWith(".testnet") ? "testnet" : "mainnet");
@@ -126,49 +120,48 @@ const executeTransaction = (config) => Effect.gen(function* () {
126
120
  "network-config",
127
121
  network
128
122
  ];
129
- if (config.privateKey) args.push("sign-with-plaintext-private-key", config.privateKey, "send");
130
- else {
131
- if (!process.stdin.isTTY) throw new NearTransactionError("No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
132
- console.log(colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
133
- args.push("sign-with-keychain", "send");
134
- }
135
- const txHashMatch = (yield* Effect.tryPromise({
123
+ if (resolvedSigningMode._tag === "privateKey") args.push("sign-with-plaintext-private-key", resolvedSigningMode.privateKey, "send");
124
+ else args.push("sign-with-keychain", "send");
125
+ const output = yield* Effect.tryPromise({
136
126
  try: async () => {
127
+ const isPrivateKeyMode = resolvedSigningMode._tag === "privateKey";
137
128
  const proc = execa("near", args, {
138
- stdin: config.privateKey ? "ignore" : "inherit",
139
- stdout: "pipe",
140
- stderr: "pipe",
129
+ stdin: isPrivateKeyMode ? "ignore" : "inherit",
130
+ stdout: isPrivateKeyMode ? "pipe" : "inherit",
131
+ stderr: isPrivateKeyMode ? "pipe" : "inherit",
141
132
  reject: false,
142
133
  timeout: 300 * 1e3
143
134
  });
144
- let stdout = "";
145
- let stderr = "";
146
- proc.stdout?.on("data", (chunk) => {
147
- stdout += chunk.toString();
148
- process.stdout.write(chunk);
149
- });
150
- proc.stderr?.on("data", (chunk) => {
151
- stderr += chunk.toString();
152
- process.stderr.write(chunk);
153
- });
135
+ if (isPrivateKeyMode) {
136
+ proc.stdout?.on("data", (chunk) => {
137
+ process.stdout.write(chunk);
138
+ });
139
+ proc.stderr?.on("data", (chunk) => {
140
+ process.stderr.write(chunk);
141
+ });
142
+ }
154
143
  const result = await proc;
155
- const combined = `${stdout}\n${stderr}`;
156
- const txHashMatch = combined.match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
144
+ const combined = combineNearOutput(result.stdout, result.stderr);
145
+ const txHash = extractTransactionHash(combined);
157
146
  const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);
158
147
  const hasTransactionFailed = /Transaction failed/i.test(combined);
159
- const softSuccess = Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;
148
+ const softSuccess = Boolean(txHash) && hasCodeDoesNotExist && hasTransactionFailed;
160
149
  if (result.exitCode === 0 || softSuccess) {
161
- if (softSuccess) console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);
162
- return combined;
150
+ if (softSuccess) console.log(` ${txHash} — FastDATA CodeDoesNotExist (expected)`);
151
+ return {
152
+ success: true,
153
+ txHash,
154
+ output: combined || void 0
155
+ };
163
156
  }
164
- throw new NearTransactionError(result.stderr || `Transaction failed with code ${result.exitCode}`);
157
+ throw new NearTransactionError(combined || `Transaction failed with code ${result.exitCode}`);
165
158
  },
166
159
  catch: (error) => error
167
- })).match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
168
- if (!txHashMatch?.[1]) throw new NearTransactionError("Transaction hash missing from NEAR CLI output");
160
+ });
169
161
  return {
170
162
  success: true,
171
- txHash: txHashMatch[1]
163
+ txHash: output.txHash,
164
+ output: output.output
172
165
  };
173
166
  });
174
167
  async function addFunctionCallAccessKey(config) {
@@ -195,5 +188,5 @@ async function addFunctionCallAccessKey(config) {
195
188
  }
196
189
 
197
190
  //#endregion
198
- export { addFunctionCallAccessKey, ensureNearCli, executeTransaction };
191
+ export { addFunctionCallAccessKey, ensureNearCli, executeTransaction, resolveNearSigningMode };
199
192
  //# sourceMappingURL=near-cli.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"near-cli.mjs","names":[],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: boolean;\n txHash?: string;\n error?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearCliInstallError extends Error {\n readonly _tag = \"NearCliInstallError\";\n constructor(message: string) {\n super(`Failed to install NEAR CLI: ${message}`);\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nconst installNearCli = Effect.tryPromise({\n try: async () => {\n await execa(\"sh\", [\"-c\", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {\n stdin: \"ignore\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n },\n catch: (error) => {\n if (error instanceof Error && \"exitCode\" in error) {\n return new NearCliInstallError(\n `Installer exited with code ${(error as { exitCode: number }).exitCode}`,\n );\n }\n return new NearCliInstallError(error instanceof Error ? error.message : String(error));\n },\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n await execa(\"near\", args, { stdin: \"pipe\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n if (process.env.BOS_INSTALL_NEAR_CLI === \"true\") {\n yield* installNearCli;\n return;\n }\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (config.privateKey) {\n args.push(\"sign-with-plaintext-private-key\", config.privateKey, \"send\");\n } else {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const proc = execa(\"near\", args, {\n stdin: config.privateKey ? \"ignore\" : \"inherit\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString();\n process.stdout.write(chunk);\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString();\n process.stderr.write(chunk);\n });\n\n const result = await proc;\n const combined = `${stdout}\\n${stderr}`;\n const txHashMatch = combined.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess =\n Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);\n }\n return combined;\n }\n\n throw new NearTransactionError(\n result.stderr || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n const txHashMatch = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n if (!txHashMatch?.[1]) {\n throw new NearTransactionError(\"Transaction hash missing from NEAR CLI output\");\n }\n\n return {\n success: true,\n txHash: txHashMatch[1],\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"near-cli.mjs","names":[],"sources":["../src/near-cli.ts"],"sourcesContent":["import { generateKeyPairSync } from \"node:crypto\";\nimport { Effect } from \"effect\";\nimport { execa } from \"execa\";\nimport { colors } from \"./utils/theme\";\n\nexport interface NearTransactionConfig {\n account: string;\n contract: string;\n method: string;\n argsBase64: string;\n network?: \"mainnet\" | \"testnet\";\n privateKey?: string;\n gas?: string;\n deposit?: string;\n}\n\nexport interface NearTransactionResult {\n success: true;\n txHash?: string;\n output?: string;\n}\n\nexport interface NearKeyPair {\n publicKey: string;\n privateKey: string;\n}\n\nexport interface FunctionCallAccessKeyConfig {\n account: string;\n contract: string;\n allowance: string;\n functionNames: string[];\n network?: \"mainnet\" | \"testnet\";\n}\n\nconst NEAR_CLI_VERSION = \"0.23.5\";\nconst INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v${NEAR_CLI_VERSION}/near-cli-rs-installer.sh`;\nconst BASE58_ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n\nexport class NearCliNotFoundError extends Error {\n readonly _tag = \"NearCliNotFoundError\";\n constructor() {\n super(\"NEAR CLI not found\");\n }\n}\n\nexport class NearTransactionError extends Error {\n readonly _tag = \"NearTransactionError\";\n}\n\nexport type NearSigningMode =\n | { _tag: \"privateKey\"; privateKey: string }\n | { _tag: \"interactiveKeychain\" };\n\nfunction base64UrlToBytes(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n}\n\nfunction base58Encode(input: Uint8Array): string {\n if (input.length === 0) return \"\";\n\n const digits: number[] = [0];\n for (const byte of input) {\n let carry = byte;\n for (let i = 0; i < digits.length; i++) {\n carry += digits[i]! << 8;\n digits[i] = carry % 58;\n carry = Math.floor(carry / 58);\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = Math.floor(carry / 58);\n }\n }\n\n let output = \"\";\n for (const byte of input) {\n if (byte === 0) output += BASE58_ALPHABET[0];\n else break;\n }\n\n for (let i = digits.length - 1; i >= 0; i--) {\n output += BASE58_ALPHABET[digits[i]!]!;\n }\n\n return output;\n}\n\nexport function generateNearKeyPair(): NearKeyPair {\n const { publicKey, privateKey } = generateKeyPairSync(\"ed25519\");\n const publicJwk = publicKey.export({ format: \"jwk\" }) as JsonWebKey;\n const privateJwk = privateKey.export({ format: \"jwk\" }) as JsonWebKey;\n\n if (!publicJwk.x || !privateJwk.d) {\n throw new Error(\"Failed to generate NEAR keypair\");\n }\n\n const publicBytes = base64UrlToBytes(publicJwk.x);\n const privateSeed = base64UrlToBytes(privateJwk.d);\n const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length);\n secretBytes.set(privateSeed, 0);\n secretBytes.set(publicBytes, privateSeed.length);\n\n return {\n publicKey: `ed25519:${base58Encode(publicBytes)}`,\n privateKey: `ed25519:${base58Encode(secretBytes)}`,\n };\n}\n\nconst checkNearCliInstalled = Effect.tryPromise({\n try: async () => {\n try {\n await execa(\"near\", [\"--version\"], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n },\n catch: () => new Error(\"Failed to check NEAR CLI\"),\n});\n\nasync function runNearCommand(args: string[]): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n await execa(\"near\", args, { stdin: \"inherit\", stdout: \"inherit\", stderr: \"inherit\" });\n}\n\nexport function resolveNearSigningMode(privateKey?: string): NearSigningMode {\n if (privateKey) {\n return { _tag: \"privateKey\", privateKey };\n }\n\n if (!process.stdin.isTTY) {\n throw new NearTransactionError(\n \"No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.\",\n );\n }\n\n console.log(\n colors.yellow(\n \" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing.\",\n ),\n );\n return { _tag: \"interactiveKeychain\" };\n}\n\nexport const ensureNearCli = Effect.gen(function* () {\n const isInstalled = yield* checkNearCliInstalled;\n if (isInstalled) return;\n\n console.log();\n console.log(\" NEAR CLI not found\");\n\n console.log();\n console.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`);\n console.log();\n yield* Effect.fail(new NearCliNotFoundError());\n});\n\nfunction combineNearOutput(stdout?: string, stderr?: string): string {\n return [stdout, stderr].filter((value) => value && value.trim().length > 0).join(\"\\n\");\n}\n\nfunction extractTransactionHash(output: string): string | undefined {\n const match = output.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n return match?.[1];\n}\n\nexport const executeTransaction = (\n config: NearTransactionConfig,\n signingMode?: NearSigningMode,\n): Effect.Effect<NearTransactionResult, Error> =>\n Effect.gen(function* () {\n const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);\n const gas = (config.gas || \"300Tgas\").replace(/\\s+/g, \"\");\n const deposit = (config.deposit || \"0NEAR\").replace(/\\s+/g, \"\");\n const network = config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\");\n\n const args = [\n \"contract\",\n \"call-function\",\n \"as-transaction\",\n config.contract,\n config.method,\n \"base64-args\",\n config.argsBase64,\n \"prepaid-gas\",\n gas,\n \"attached-deposit\",\n deposit,\n \"sign-as\",\n config.account,\n \"network-config\",\n network,\n ];\n\n if (resolvedSigningMode._tag === \"privateKey\") {\n args.push(\"sign-with-plaintext-private-key\", resolvedSigningMode.privateKey, \"send\");\n } else {\n args.push(\"sign-with-keychain\", \"send\");\n }\n\n const output = yield* Effect.tryPromise({\n try: async () => {\n const isPrivateKeyMode = resolvedSigningMode._tag === \"privateKey\";\n const proc = execa(\"near\", args, {\n stdin: isPrivateKeyMode ? \"ignore\" : \"inherit\",\n stdout: isPrivateKeyMode ? \"pipe\" : \"inherit\",\n stderr: isPrivateKeyMode ? \"pipe\" : \"inherit\",\n reject: false,\n timeout: 5 * 60 * 1000,\n });\n\n if (isPrivateKeyMode) {\n proc.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(chunk);\n });\n\n proc.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(chunk);\n });\n }\n\n const result = await proc;\n const combined = combineNearOutput(result.stdout, result.stderr);\n const txHash = extractTransactionHash(combined);\n const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);\n const hasTransactionFailed = /Transaction failed/i.test(combined);\n const softSuccess = Boolean(txHash) && hasCodeDoesNotExist && hasTransactionFailed;\n\n if (result.exitCode === 0 || softSuccess) {\n if (softSuccess) {\n console.log(` ${txHash} — FastDATA CodeDoesNotExist (expected)`);\n }\n return {\n success: true,\n txHash,\n output: combined || undefined,\n };\n }\n\n throw new NearTransactionError(\n combined || `Transaction failed with code ${result.exitCode}`,\n );\n },\n catch: (error) => error as Error,\n });\n\n return {\n success: true,\n txHash: output.txHash,\n output: output.output,\n };\n });\n\nexport async function addFunctionCallAccessKey(\n config: FunctionCallAccessKeyConfig,\n): Promise<NearKeyPair> {\n const keyPair = generateNearKeyPair();\n const args = [\n \"account\",\n \"add-key\",\n config.account,\n \"grant-function-call-access\",\n \"--allowance\",\n config.allowance,\n \"--contract-account-id\",\n config.contract,\n \"--function-names\",\n config.functionNames.join(\", \"),\n \"use-manually-provided-public-key\",\n keyPair.publicKey,\n \"network-config\",\n config.network || (config.account.endsWith(\".testnet\") ? \"testnet\" : \"mainnet\"),\n \"sign-with-keychain\",\n \"send\",\n ];\n\n await runNearCommand(args);\n return keyPair;\n}\n"],"mappings":"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"}
package/dist/plugin.cjs CHANGED
@@ -214,8 +214,10 @@ function sleep(ms) {
214
214
  return new Promise((resolve) => setTimeout(resolve, ms));
215
215
  }
216
216
  async function waitForPublishedConfig(opts) {
217
- const timeoutMs = opts.timeoutMs ?? 12e4;
218
- const intervalMs = opts.intervalMs ?? 3e3;
217
+ const envTimeoutMs = Number(node_process.default.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);
218
+ const envIntervalMs = Number(node_process.default.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);
219
+ const timeoutMs = opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : void 0) ?? 12e4;
220
+ const intervalMs = opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : void 0) ?? 3e3;
219
221
  const startedAt = Date.now();
220
222
  let lastError;
221
223
  while (Date.now() - startedAt < timeoutMs) {
@@ -1354,18 +1356,23 @@ async function publishToFastKv(input) {
1354
1356
  const payload = JSON.stringify(registryEntries);
1355
1357
  const argsBase64 = Buffer.from(payload).toString("base64");
1356
1358
  const privateKey = input.privateKey || node_process.default.env.NEAR_PRIVATE_KEY || node_process.default.env.BOS_NEAR_PRIVATE_KEY;
1357
- if (!privateKey) {
1358
- if (!node_process.default.stdin.isTTY) return {
1359
+ let signingMode;
1360
+ try {
1361
+ signingMode = require_near_cli.resolveNearSigningMode(privateKey);
1362
+ } catch (error) {
1363
+ return {
1359
1364
  status: "error",
1360
1365
  registryUrl,
1361
- error: "No private key provided and no TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally."
1366
+ error: error instanceof Error ? error.message : "Unknown error"
1362
1367
  };
1363
- console.log(require_theme.colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
1364
1368
  }
1365
1369
  console.log();
1366
- console.log(` Publishing to ${require_theme.colors.cyan(registryUrl)}...`);
1370
+ console.log(" Publishing to:");
1371
+ console.log(` ${require_theme.colors.cyan(registryUrl)}`);
1367
1372
  try {
1373
+ console.log(" Ensuring NEAR CLI...");
1368
1374
  await effect.Effect.runPromise(require_near_cli.ensureNearCli);
1375
+ console.log(" NEAR CLI ready");
1369
1376
  let txHash;
1370
1377
  console.log(` Submitting transaction on ${network}...`);
1371
1378
  try {
@@ -1375,10 +1382,10 @@ async function publishToFastKv(input) {
1375
1382
  method: "__fastdata_kv",
1376
1383
  argsBase64,
1377
1384
  network,
1378
- privateKey,
1385
+ privateKey: signingMode._tag === "privateKey" ? signingMode.privateKey : void 0,
1379
1386
  gas: "300Tgas",
1380
1387
  deposit: "0NEAR"
1381
- }))).txHash;
1388
+ }, signingMode))).txHash;
1382
1389
  if (txHash) console.log(` Transaction submitted: ${require_theme.colors.dim(txHash)}`);
1383
1390
  } catch (error) {
1384
1391
  txHash = extractTransactionHash(error);