@ixo/asks-mcp 2.0.0-dev.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/asks-mcp.mjs +57 -35
  2. package/package.json +1 -1
package/dist/asks-mcp.mjs CHANGED
@@ -38786,9 +38786,9 @@ function nLength(n, nBitLength) {
38786
38786
  const nByteLength = Math.ceil(_nBitLength / 8);
38787
38787
  return { nBitLength: _nBitLength, nByteLength };
38788
38788
  }
38789
- function Field(ORDER2, opts = {}) {
38789
+ function Field(ORDER3, opts = {}) {
38790
38790
  Object.freeze(_Field.prototype);
38791
- return new _Field(ORDER2, opts);
38791
+ return new _Field(ORDER3, opts);
38792
38792
  }
38793
38793
  function FpSqrtEven(Fp2, elm) {
38794
38794
  validateField(Fp2);
@@ -38867,9 +38867,9 @@ var init_modular = __esm({
38867
38867
  ONE = _1n3;
38868
38868
  _lengths;
38869
38869
  _mod;
38870
- constructor(ORDER2, opts = {}) {
38871
- if (ORDER2 <= _1n3)
38872
- throw new Error("invalid field: expected ORDER > 1, got " + ORDER2);
38870
+ constructor(ORDER3, opts = {}) {
38871
+ if (ORDER3 <= _1n3)
38872
+ throw new Error("invalid field: expected ORDER > 1, got " + ORDER3);
38873
38873
  let _nbitLength = void 0;
38874
38874
  this.isLE = false;
38875
38875
  if (opts != null && typeof opts === "object") {
@@ -38884,10 +38884,10 @@ var init_modular = __esm({
38884
38884
  if (typeof opts.modFromBytes === "boolean")
38885
38885
  this._mod = opts.modFromBytes;
38886
38886
  }
38887
- const { nBitLength, nByteLength } = nLength(ORDER2, _nbitLength);
38887
+ const { nBitLength, nByteLength } = nLength(ORDER3, _nbitLength);
38888
38888
  if (nByteLength > 2048)
38889
38889
  throw new Error("invalid field: expected ORDER of <= 2048 bytes");
38890
- this.ORDER = ORDER2;
38890
+ this.ORDER = ORDER3;
38891
38891
  this.BITS = nBitLength;
38892
38892
  this.BYTES = nByteLength;
38893
38893
  Object.freeze(this);
@@ -38961,7 +38961,7 @@ var init_modular = __esm({
38961
38961
  }
38962
38962
  fromBytes(bytes3, skipValidation = false) {
38963
38963
  abytes5(bytes3);
38964
- const { _lengths: allowedLengths, BYTES, isLE: isLE3, ORDER: ORDER2, _mod: modFromBytes } = this;
38964
+ const { _lengths: allowedLengths, BYTES, isLE: isLE3, ORDER: ORDER3, _mod: modFromBytes } = this;
38965
38965
  if (allowedLengths) {
38966
38966
  if (bytes3.length < 1 || !allowedLengths.includes(bytes3.length) || bytes3.length > BYTES) {
38967
38967
  throw new Error("Field.fromBytes: expected " + allowedLengths + " bytes, got " + bytes3.length);
@@ -38974,7 +38974,7 @@ var init_modular = __esm({
38974
38974
  throw new Error("Field.fromBytes: expected " + BYTES + " bytes, got " + bytes3.length);
38975
38975
  let scalar = isLE3 ? bytesToNumberLE2(bytes3) : bytesToNumberBE(bytes3);
38976
38976
  if (modFromBytes)
38977
- scalar = mod2(scalar, ORDER2);
38977
+ scalar = mod2(scalar, ORDER3);
38978
38978
  if (!skipValidation) {
38979
38979
  if (!this.isValid(scalar))
38980
38980
  throw new Error("invalid field element: outside of range 0..ORDER");
@@ -266879,6 +266879,21 @@ var init_takeBack = __esm({
266879
266879
  }
266880
266880
  });
266881
266881
 
266882
+ // ../../app/lib/cashout/words.ts
266883
+ function waysFor(list7, country) {
266884
+ const shown2 = list7.filter((one) => one.reason !== "not_in_country");
266885
+ const fits = STRIPE_COUNTRIES.has(country) ? "stripe_bank" : "yellowcard_bank";
266886
+ const bank = shown2.filter((one) => one.method.endsWith("_bank")).sort((a, b) => Number(b.enabled !== false) - Number(a.enabled !== false) || Number(b.method === fits) - Number(a.method === fits))[0];
266887
+ return shown2.filter((one) => !one.method.endsWith("_bank") || one === bank);
266888
+ }
266889
+ var STRIPE_COUNTRIES;
266890
+ var init_words = __esm({
266891
+ "../../app/lib/cashout/words.ts"() {
266892
+ "use strict";
266893
+ STRIPE_COUNTRIES = new Set("AT BE BG CY CZ DE DK EE ES FI FR GR HR HU IE IS IT LI LT LU LV MT NL NO PL PT RO SE SI SK US GB CA CH".split(" "));
266894
+ }
266895
+ });
266896
+
266882
266897
  // src/cashout.ts
266883
266898
  var cashout_exports = {};
266884
266899
  __export(cashout_exports, {
@@ -266886,6 +266901,11 @@ __export(cashout_exports, {
266886
266901
  cashOutStatus: () => cashOutStatus,
266887
266902
  identityLine: () => identityLine
266888
266903
  });
266904
+ function whyOff(one) {
266905
+ if (one.enabled === false) return one.reason === "coming_soon" ? "coming soon" : "busy right now, try later";
266906
+ if (one.provider === "yellowcard-worker" || one.method.startsWith("yellowcard")) return "coming soon";
266907
+ return null;
266908
+ }
266889
266909
  async function call2(deps, path, body) {
266890
266910
  try {
266891
266911
  const response = await deps.fetch(`${deps.site.replace(/\/+$/, "")}${path}`, {
@@ -266926,38 +266946,38 @@ async function cashOut(deps, input) {
266926
266946
  if (!country || !/^[A-Z]{2}$/.test(country)) return [`You have $${available.toFixed(2)} to cash out.`, kycLine, 'Which country are you in? (Ask the person; then call cash_out with country, like "NG" or "DE".)'].filter(Boolean).join("\n");
266927
266947
  const info = await call2(deps, `/api/cashout/info?country=${country}`);
266928
266948
  if (info.status !== 200) return said3(info);
266929
- const methods = info.body.methods ?? [];
266949
+ const methods = waysFor(info.body.methods ?? [], country).filter((one) => WAYS[one.method]).sort((a, b) => ORDER2.indexOf(a.method) - ORDER2.indexOf(b.method));
266930
266950
  const fee = info.body.fee;
266931
- if (!methods.length) return `There's no way to cash out in ${country} yet.`;
266932
- const chosen2 = methods.find((one) => one.method === input.method);
266951
+ if (!methods.some((one) => !whyOff(one))) return `We can't send money to ${country} yet.`;
266952
+ const chosen2 = methods.find((one) => one.method === input.method && !whyOff(one));
266933
266953
  if (!chosen2)
266934
266954
  return [
266935
266955
  `You have $${available.toFixed(2)} to cash out. Ways to get paid in ${country}:`,
266936
- ...methods.map((one) => `- ${WAYS[one.method] ?? one.method} (method "${one.method}"): $${one.minUsd} to $${one.maxUsd}`),
266956
+ ...methods.map((one) => `- ${WAYS[one.method]} (method "${one.method}"): ${whyOff(one) ?? `$${one.minUsd ?? "0.00"}${one.maxUsd ? ` to $${one.maxUsd}` : ""}`}`),
266937
266957
  `Fee: ${fee?.bps ? `${fee.bps / 100}%` : "none"}${fee?.minUsd && Number(fee.minUsd) > 0 ? `, at least $${fee.minUsd}` : ""}.`,
266938
266958
  kycLine,
266939
266959
  "(Ask which way and how much; then call cash_out with method and amount_usd.)"
266940
266960
  ].filter(Boolean).join("\n");
266941
266961
  const amount3 = input.amount_usd?.trim().replace(/^\$/, "");
266942
- if (!amount3 || !/^\d+(\.\d{1,2})?$/.test(amount3)) return `How much do you want to cash out? You have $${available.toFixed(2)}; this way takes $${chosen2.minUsd} to $${chosen2.maxUsd}. (Then call cash_out with amount_usd, like "25".)`;
266962
+ if (!amount3 || !/^\d+(\.\d{1,2})?$/.test(amount3)) return `How much do you want to cash out? You have $${available.toFixed(2)}; this way takes $${chosen2.minUsd ?? "0.00"}${chosen2.maxUsd ? ` to $${chosen2.maxUsd}` : ""}. (Then call cash_out with amount_usd, like "25".)`;
266943
266963
  if (Number(amount3) > available) return `You have $${available.toFixed(2)} to cash out, less than $${amount3}. Pick a smaller amount.`;
266944
- if (Number(amount3) < Number(chosen2.minUsd)) return `The smallest you can cash out this way is $${chosen2.minUsd}.`;
266945
- if (Number(amount3) > Number(chosen2.maxUsd)) return `The largest you can cash out this way is $${chosen2.maxUsd}.`;
266964
+ if (chosen2.minUsd && Number(amount3) < Number(chosen2.minUsd)) return `The smallest you can cash out this way is $${chosen2.minUsd}.`;
266965
+ if (chosen2.maxUsd && Number(amount3) > Number(chosen2.maxUsd)) return `The largest you can cash out this way is $${chosen2.maxUsd}.`;
266946
266966
  const to = input.to?.trim();
266947
266967
  if (chosen2.fields.includes("address") && !(to && BASE_ADDRESS.test(to))) return "Which Base account should receive it? (Its address starts with 0x; then call cash_out with to.)";
266948
266968
  const quote = await signedCall(deps, "quote", { method: chosen2.method, country, amountUsd: amount3 });
266949
266969
  if (quote.status !== 201) return said3(quote);
266950
266970
  const q = quote.body;
266951
- const receive = `You'll receive $${q.receive?.amount ?? q.amountUsd}${q.receive?.currency && q.receive.currency !== "USD" ? ` in ${q.receive.currency}` : ""} (fee $${q.feeUsd ?? "0.00"}).`;
266971
+ const receive = `You'll receive $${q.receive?.amount ?? q.amountUsd} (fee $${q.feeUsd ?? "0.00"}).`;
266952
266972
  const named = chosen2.fields.includes("accountHolder") ? NAME_LINE : "";
266953
- if (!input.confirm) return [`Cash out $${q.amountUsd} by ${WAYS[chosen2.method] ?? chosen2.method}${to ? ` to ${to}` : ""}.`, receive, named, kycLine, "Nothing is sent yet. To go ahead, call cash_out again with the same answers and confirm: true."].filter(Boolean).join("\n");
266973
+ if (!input.confirm) return [`Cash out $${q.amountUsd}: ${WAYS[chosen2.method]}${to ? `, to ${to}` : ""}.`, receive, named, kycLine, "Nothing is sent yet. To go ahead, call cash_out again with the same answers and confirm: true."].filter(Boolean).join("\n");
266954
266974
  const link5 = new URL(`${deps.site.replace(/\/+$/, "")}/me/cash-out`);
266955
266975
  link5.searchParams.set("quote", String(q.quoteId));
266956
266976
  link5.searchParams.set("method", chosen2.method);
266957
266977
  link5.searchParams.set("amount", amount3);
266958
266978
  link5.searchParams.set("country", country);
266959
266979
  if (to) link5.searchParams.set("to", to);
266960
- return [receive, named, `Open this and confirm with one tap: ${link5.toString()}`, "Your money leaves only when you confirm there. I signed nothing. (Later, cash_out_status with the id that page shows says where it stands.)"].filter(Boolean).join("\n");
266980
+ return [receive, named, `Open this and tap Confirm: ${link5.toString()}`, "Your money leaves only when you confirm there. I sent nothing. (Later, cash_out_status with the id that page shows says where it stands.)"].filter(Boolean).join("\n");
266961
266981
  }
266962
266982
  async function cashOutStatus(deps, id) {
266963
266983
  const answer = await signedCall(deps, "status", { id });
@@ -266969,12 +266989,12 @@ async function cashOutStatus(deps, id) {
266969
266989
  switch (lapsed ? "expired" : v.state) {
266970
266990
  case "open":
266971
266991
  case "signing":
266972
- return `Not confirmed yet: open the confirm link and tap confirm (${money2}).`;
266992
+ return `Not confirmed yet: open the link and tap Confirm (${money2}).`;
266973
266993
  case "sent":
266974
- return "Confirmed. The payout is starting.";
266994
+ return "Confirmed. It's on its way.";
266975
266995
  case "expired":
266976
266996
  case "failed":
266977
- return "This cash-out expired before it was confirmed. Nothing was taken. Start a new one with cash_out.";
266997
+ return "This took too long, so it was stopped. Nothing was taken. Start a new one with cash_out.";
266978
266998
  case "converting":
266979
266999
  case "taking":
266980
267000
  case "paying":
@@ -266982,31 +267002,33 @@ async function cashOutStatus(deps, id) {
266982
267002
  case "paid":
266983
267003
  return `Paid: ${money2}.`;
266984
267004
  case "needs_attention":
266985
- return `Your payout didn't go through: ${v.reason ?? "the payout failed"}. Check your details or pick another way: ${v.fixUrl ?? ""}
266986
- ${NAME_LINE}`;
267005
+ return v.fixUrl ? `Something needs fixing: the money didn't reach you. Check your details or pick another way here: ${v.fixUrl}
267006
+ ${NAME_LINE}` : "Something needs fixing, and we're looking into it. Nothing to do on your side.";
266987
267007
  case "not_converted":
266988
267008
  case "cancelled":
266989
- return "This cash-out didn't go through, and nothing was taken.";
267009
+ return "It didn't go through, and nothing was taken.";
266990
267010
  case "refunded":
266991
- return "Your money was sent back to you.";
267011
+ return "Your money is back in your account.";
266992
267012
  default:
266993
- return `State: ${v.state ?? "unknown"}.`;
267013
+ return "We're still checking where it stands. Ask again in a minute.";
266994
267014
  }
266995
267015
  }
266996
- var WAYS, BASE_ADDRESS, NAME_LINE, said3;
267016
+ var WAYS, ORDER2, BASE_ADDRESS, NAME_LINE, said3;
266997
267017
  var init_cashout = __esm({
266998
267018
  "src/cashout.ts"() {
266999
267019
  "use strict";
267000
267020
  init_accountProof();
267001
267021
  init_inviteProof();
267022
+ init_words();
267002
267023
  WAYS = {
267003
- usdc_base: "Digital dollars to your own Base account (any country)",
267004
- stripe_bank: "Bank account, through Stripe",
267005
- yellowcard_bank: "Bank account, through Yellow Card",
267006
- yellowcard_momo: "Mobile money, through Yellow Card"
267024
+ stripe_bank: "To your bank account (through Stripe)",
267025
+ yellowcard_bank: "To your bank account (through Yellow Card)",
267026
+ yellowcard_momo: "To your mobile money (M-PESA, MTN and others)",
267027
+ usdc_base: "Digital dollars (USDC), to your own Base account (its address starts with 0x)"
267007
267028
  };
267029
+ ORDER2 = Object.keys(WAYS);
267008
267030
  BASE_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
267009
- NAME_LINE = "The payout account name must match the name on your ID.";
267031
+ NAME_LINE = "The name on the account must match the name on your ID.";
267010
267032
  said3 = (answer) => answer.status === 503 && answer.body.code === "not-open" ? "Cash-out isn't open on this network yet." : String(answer.body.error ?? `Cash-out refused this (${answer.status}).`);
267011
267033
  }
267012
267034
  });
@@ -292374,7 +292396,7 @@ import { randomBytes as randomBytes7 } from "node:crypto";
292374
292396
  // package.json
292375
292397
  var package_default = {
292376
292398
  name: "@ixo/asks-mcp",
292377
- version: "2.0.0-dev.6",
292399
+ version: "2.0.1",
292378
292400
  description: "The Openhands Network MCP server: read the board, answer asks, post work and get paid on the ixo chain, with a key of its own on your machine.",
292379
292401
  license: "Apache-2.0",
292380
292402
  repository: {
@@ -292598,7 +292620,7 @@ var TOOLS = {
292598
292620
  },
292599
292621
  cash_out: {
292600
292622
  title: "Cash out your earnings",
292601
- description: `Turn what the person earned into money: digital dollars to your own Base account, or a bank account where offered. One step per call: it reads what they have available, their LinkedIn and identity check, then asks the country, the way to get paid, the amount and (for a Base account) the address, and shows the quote in plain words ("You'll receive $X (fee $0)"). With confirm: true it gives ONE link: the person opens it and confirms with one tap; that page checks their identity and they sign there. Limits and fees come from IXO's cash-out service, never from here. No LinkedIn: say connect_linkedin first. Signs no money and holds no key of theirs.`,
292623
+ description: `Turn what the person earned into money: to their bank account, their mobile money, or "Digital dollars (USDC)" to their own Base account, where offered. Speak plainly to the person: no technical words. One step per call: it reads what they have available, their LinkedIn and identity check, then asks the country, the way to get paid (every way is listed; the ones they can't pick say why), the amount and (for digital dollars) the 0x address, and shows "You'll receive $X (fee $0)". With confirm: true it gives ONE link: the person opens it and taps Confirm there, where their identity is checked and they confirm in their sign-in app. Limits and fees come from IXO's cash-out service, never from here. No LinkedIn: say connect_linkedin first. Signs no money and holds no key of theirs.`,
292602
292624
  spends: false,
292603
292625
  hosted: false,
292604
292626
  annotations: acts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ixo/asks-mcp",
3
- "version": "2.0.0-dev.6",
3
+ "version": "2.0.1",
4
4
  "description": "The Openhands Network MCP server: read the board, answer asks, post work and get paid on the ixo chain, with a key of its own on your machine.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {