everything-dev 1.33.4 → 1.33.6

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
@@ -87,12 +87,22 @@ const installNearCli = effect.Effect.tryPromise({
87
87
  }
88
88
  });
89
89
  async function runNearCommand(args) {
90
+ if (!process.stdin.isTTY) throw new NearTransactionError("No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
90
91
  await (0, execa.execa)("near", args, {
91
- stdin: "pipe",
92
+ stdin: "inherit",
92
93
  stdout: "inherit",
93
94
  stderr: "inherit"
94
95
  });
95
96
  }
97
+ function resolveNearSigningMode(privateKey) {
98
+ if (privateKey) return {
99
+ _tag: "privateKey",
100
+ privateKey
101
+ };
102
+ 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.");
103
+ console.log(require_theme.colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
104
+ return { _tag: "interactiveKeychain" };
105
+ }
96
106
  const ensureNearCli = effect.Effect.gen(function* () {
97
107
  if (yield* checkNearCliInstalled) return;
98
108
  if (process.env.BOS_INSTALL_NEAR_CLI === "true") {
@@ -106,7 +116,14 @@ const ensureNearCli = effect.Effect.gen(function* () {
106
116
  console.log();
107
117
  yield* effect.Effect.fail(new NearCliNotFoundError());
108
118
  });
109
- const executeTransaction = (config) => effect.Effect.gen(function* () {
119
+ function combineNearOutput(stdout, stderr) {
120
+ return [stdout, stderr].filter((value) => value && value.trim().length > 0).join("\n");
121
+ }
122
+ function extractTransactionHash(output) {
123
+ return output.match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
124
+ }
125
+ const executeTransaction = (config, signingMode) => effect.Effect.gen(function* () {
126
+ const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);
110
127
  const gas = (config.gas || "300Tgas").replace(/\s+/g, "");
111
128
  const deposit = (config.deposit || "0NEAR").replace(/\s+/g, "");
112
129
  const network = config.network || (config.account.endsWith(".testnet") ? "testnet" : "mainnet");
@@ -127,49 +144,48 @@ const executeTransaction = (config) => effect.Effect.gen(function* () {
127
144
  "network-config",
128
145
  network
129
146
  ];
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({
147
+ if (resolvedSigningMode._tag === "privateKey") args.push("sign-with-plaintext-private-key", resolvedSigningMode.privateKey, "send");
148
+ else args.push("sign-with-keychain", "send");
149
+ const output = yield* effect.Effect.tryPromise({
137
150
  try: async () => {
151
+ const isPrivateKeyMode = resolvedSigningMode._tag === "privateKey";
138
152
  const proc = (0, execa.execa)("near", args, {
139
- stdin: config.privateKey ? "ignore" : "inherit",
140
- stdout: "pipe",
141
- stderr: "pipe",
153
+ stdin: isPrivateKeyMode ? "ignore" : "inherit",
154
+ stdout: isPrivateKeyMode ? "pipe" : "inherit",
155
+ stderr: isPrivateKeyMode ? "pipe" : "inherit",
142
156
  reject: false,
143
157
  timeout: 300 * 1e3
144
158
  });
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
- });
159
+ if (isPrivateKeyMode) {
160
+ proc.stdout?.on("data", (chunk) => {
161
+ process.stdout.write(chunk);
162
+ });
163
+ proc.stderr?.on("data", (chunk) => {
164
+ process.stderr.write(chunk);
165
+ });
166
+ }
155
167
  const result = await proc;
156
- const combined = `${stdout}\n${stderr}`;
157
- const txHashMatch = combined.match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
168
+ const combined = combineNearOutput(result.stdout, result.stderr);
169
+ const txHash = extractTransactionHash(combined);
158
170
  const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);
159
171
  const hasTransactionFailed = /Transaction failed/i.test(combined);
160
- const softSuccess = Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;
172
+ const softSuccess = Boolean(txHash) && hasCodeDoesNotExist && hasTransactionFailed;
161
173
  if (result.exitCode === 0 || softSuccess) {
162
- if (softSuccess) console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);
163
- return combined;
174
+ if (softSuccess) console.log(` ${txHash} — FastDATA CodeDoesNotExist (expected)`);
175
+ return {
176
+ success: true,
177
+ txHash,
178
+ output: combined || void 0
179
+ };
164
180
  }
165
- throw new NearTransactionError(result.stderr || `Transaction failed with code ${result.exitCode}`);
181
+ throw new NearTransactionError(combined || `Transaction failed with code ${result.exitCode}`);
166
182
  },
167
183
  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");
184
+ });
170
185
  return {
171
186
  success: true,
172
- txHash: txHashMatch[1]
187
+ txHash: output.txHash,
188
+ output: output.output
173
189
  };
174
190
  });
175
191
  async function addFunctionCallAccessKey(config) {
@@ -199,4 +215,5 @@ async function addFunctionCallAccessKey(config) {
199
215
  exports.addFunctionCallAccessKey = addFunctionCallAccessKey;
200
216
  exports.ensureNearCli = ensureNearCli;
201
217
  exports.executeTransaction = executeTransaction;
218
+ exports.resolveNearSigningMode = resolveNearSigningMode;
202
219
  //# 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 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\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\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 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 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\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
@@ -86,12 +86,22 @@ const installNearCli = Effect.tryPromise({
86
86
  }
87
87
  });
88
88
  async function runNearCommand(args) {
89
+ if (!process.stdin.isTTY) throw new NearTransactionError("No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally.");
89
90
  await execa("near", args, {
90
- stdin: "pipe",
91
+ stdin: "inherit",
91
92
  stdout: "inherit",
92
93
  stderr: "inherit"
93
94
  });
94
95
  }
96
+ function resolveNearSigningMode(privateKey) {
97
+ if (privateKey) return {
98
+ _tag: "privateKey",
99
+ privateKey
100
+ };
101
+ 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.");
102
+ console.log(colors.yellow(" Warning: No NEAR_PRIVATE_KEY set — falling back to interactive keychain signing."));
103
+ return { _tag: "interactiveKeychain" };
104
+ }
95
105
  const ensureNearCli = Effect.gen(function* () {
96
106
  if (yield* checkNearCliInstalled) return;
97
107
  if (process.env.BOS_INSTALL_NEAR_CLI === "true") {
@@ -105,7 +115,14 @@ const ensureNearCli = Effect.gen(function* () {
105
115
  console.log();
106
116
  yield* Effect.fail(new NearCliNotFoundError());
107
117
  });
108
- const executeTransaction = (config) => Effect.gen(function* () {
118
+ function combineNearOutput(stdout, stderr) {
119
+ return [stdout, stderr].filter((value) => value && value.trim().length > 0).join("\n");
120
+ }
121
+ function extractTransactionHash(output) {
122
+ return output.match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
123
+ }
124
+ const executeTransaction = (config, signingMode) => Effect.gen(function* () {
125
+ const resolvedSigningMode = signingMode ?? resolveNearSigningMode(config.privateKey);
109
126
  const gas = (config.gas || "300Tgas").replace(/\s+/g, "");
110
127
  const deposit = (config.deposit || "0NEAR").replace(/\s+/g, "");
111
128
  const network = config.network || (config.account.endsWith(".testnet") ? "testnet" : "mainnet");
@@ -126,49 +143,48 @@ const executeTransaction = (config) => Effect.gen(function* () {
126
143
  "network-config",
127
144
  network
128
145
  ];
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({
146
+ if (resolvedSigningMode._tag === "privateKey") args.push("sign-with-plaintext-private-key", resolvedSigningMode.privateKey, "send");
147
+ else args.push("sign-with-keychain", "send");
148
+ const output = yield* Effect.tryPromise({
136
149
  try: async () => {
150
+ const isPrivateKeyMode = resolvedSigningMode._tag === "privateKey";
137
151
  const proc = execa("near", args, {
138
- stdin: config.privateKey ? "ignore" : "inherit",
139
- stdout: "pipe",
140
- stderr: "pipe",
152
+ stdin: isPrivateKeyMode ? "ignore" : "inherit",
153
+ stdout: isPrivateKeyMode ? "pipe" : "inherit",
154
+ stderr: isPrivateKeyMode ? "pipe" : "inherit",
141
155
  reject: false,
142
156
  timeout: 300 * 1e3
143
157
  });
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
- });
158
+ if (isPrivateKeyMode) {
159
+ proc.stdout?.on("data", (chunk) => {
160
+ process.stdout.write(chunk);
161
+ });
162
+ proc.stderr?.on("data", (chunk) => {
163
+ process.stderr.write(chunk);
164
+ });
165
+ }
154
166
  const result = await proc;
155
- const combined = `${stdout}\n${stderr}`;
156
- const txHashMatch = combined.match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
167
+ const combined = combineNearOutput(result.stdout, result.stderr);
168
+ const txHash = extractTransactionHash(combined);
157
169
  const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);
158
170
  const hasTransactionFailed = /Transaction failed/i.test(combined);
159
- const softSuccess = Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;
171
+ const softSuccess = Boolean(txHash) && hasCodeDoesNotExist && hasTransactionFailed;
160
172
  if (result.exitCode === 0 || softSuccess) {
161
- if (softSuccess) console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);
162
- return combined;
173
+ if (softSuccess) console.log(` ${txHash} — FastDATA CodeDoesNotExist (expected)`);
174
+ return {
175
+ success: true,
176
+ txHash,
177
+ output: combined || void 0
178
+ };
163
179
  }
164
- throw new NearTransactionError(result.stderr || `Transaction failed with code ${result.exitCode}`);
180
+ throw new NearTransactionError(combined || `Transaction failed with code ${result.exitCode}`);
165
181
  },
166
182
  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");
183
+ });
169
184
  return {
170
185
  success: true,
171
- txHash: txHashMatch[1]
186
+ txHash: output.txHash,
187
+ output: output.output
172
188
  };
173
189
  });
174
190
  async function addFunctionCallAccessKey(config) {
@@ -195,5 +211,5 @@ async function addFunctionCallAccessKey(config) {
195
211
  }
196
212
 
197
213
  //#endregion
198
- export { addFunctionCallAccessKey, ensureNearCli, executeTransaction };
214
+ export { addFunctionCallAccessKey, ensureNearCli, executeTransaction, resolveNearSigningMode };
199
215
  //# 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 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\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\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 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 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\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,16 +1356,19 @@ 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 {
1368
1373
  await effect.Effect.runPromise(require_near_cli.ensureNearCli);
1369
1374
  let txHash;
@@ -1375,10 +1380,10 @@ async function publishToFastKv(input) {
1375
1380
  method: "__fastdata_kv",
1376
1381
  argsBase64,
1377
1382
  network,
1378
- privateKey,
1383
+ privateKey: signingMode._tag === "privateKey" ? signingMode.privateKey : void 0,
1379
1384
  gas: "300Tgas",
1380
1385
  deposit: "0NEAR"
1381
- }))).txHash;
1386
+ }, signingMode))).txHash;
1382
1387
  if (txHash) console.log(` Transaction submitted: ${require_theme.colors.dim(txHash)}`);
1383
1388
  } catch (error) {
1384
1389
  txHash = extractTransactionHash(error);