@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.
- package/dist/asks-mcp.mjs +57 -35
- 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(
|
|
38789
|
+
function Field(ORDER3, opts = {}) {
|
|
38790
38790
|
Object.freeze(_Field.prototype);
|
|
38791
|
-
return new _Field(
|
|
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(
|
|
38871
|
-
if (
|
|
38872
|
-
throw new Error("invalid field: expected ORDER > 1, got " +
|
|
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(
|
|
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 =
|
|
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:
|
|
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,
|
|
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.
|
|
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]
|
|
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}
|
|
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}
|
|
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
|
|
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
|
|
266992
|
+
return `Not confirmed yet: open the link and tap Confirm (${money2}).`;
|
|
266973
266993
|
case "sent":
|
|
266974
|
-
return "Confirmed.
|
|
266994
|
+
return "Confirmed. It's on its way.";
|
|
266975
266995
|
case "expired":
|
|
266976
266996
|
case "failed":
|
|
266977
|
-
return "This
|
|
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
|
|
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 "
|
|
267009
|
+
return "It didn't go through, and nothing was taken.";
|
|
266990
267010
|
case "refunded":
|
|
266991
|
-
return "Your money
|
|
267011
|
+
return "Your money is back in your account.";
|
|
266992
267012
|
default:
|
|
266993
|
-
return
|
|
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
|
-
|
|
267004
|
-
|
|
267005
|
-
|
|
267006
|
-
|
|
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
|
|
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.
|
|
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:
|
|
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.
|
|
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": {
|