@airmoney-degn/controller-sdk
Version:
SDK for controlling AirMoney devices, providing button screen management, key event handling, and device communication capabilities
582 lines (581 loc) • 20.7 kB
JavaScript
var P = Object.defineProperty;
var k = (t, a, e) => a in t ? P(t, a, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[a] = e;
var s = (t, a, e) => k(t, typeof a != "symbol" ? a + "" : a, e);
var u = /* @__PURE__ */ ((t) => (t.LeftButton = "ArrowLeft", t.RightButton = "ArrowRight", t.CounterClockwiseRotary = "]", t.ClockwiseRotary = "[", t.RotaryButton = "Enter", t.SideButton = "ArrowUp", t.MuteSwitch = "ArrowDown", t))(u || {});
class O {
constructor(a) {
s(this, "config", {
threshold: 300,
combinations: void 0,
doubleClicks: void 0,
debug: !1
});
s(this, "activeKeys", {});
s(this, "timers", {});
s(this, "callbacks", []);
s(this, "getCombination", (a) => this.config.combinations && Object.entries(this.config.combinations).find(([, e]) => e.includes(a)));
s(this, "getDoubleClick", (a) => this.config.doubleClicks && Object.entries(this.config.doubleClicks).find(([, e]) => e === a));
s(this, "debugLog", (...a) => {
this.config.debug && console.log(...a);
});
s(this, "onKeyDown", (a) => {
if (!Object.values(u).includes(a.key)) return;
a.preventDefault();
const e = a.key;
switch (this.activeKeys[a.key]) {
case "pressed":
case "clicked":
case "end":
return;
case "over": {
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "longpressdown",
data: {
key: e
}
}), this.debugLog("---> LONG PRESS DOWN", e);
return;
}
case void 0: {
const i = this.getCombination(e);
if (i && i[1].filter((r) => r !== a.key).every((r) => this.activeKeys[r] === "available")) {
i[1].map((r) => {
this.activeKeys[r] = "pressed", clearTimeout(this.timers[r]);
}), this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "combinationdown",
data: {
keys: i[1],
name: i[0]
}
}), this.debugLog("---> COMBINATION DOWN", i);
return;
}
this.activeKeys[a.key] = "available", this.timers[a.key] = setTimeout(() => {
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "longpressdown",
data: {
key: e
}
}), this.debugLog("---> LONG PRESS DOWN", e), this.activeKeys[a.key] = "over";
}, this.config.threshold);
break;
}
}
});
s(this, "onKeyUp", (a) => {
if (!Object.values(u).includes(a.key)) return;
a.preventDefault();
const e = a.key;
switch (this.activeKeys[e]) {
case "clicked": {
const i = this.getDoubleClick(e);
i && (this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "doubleclick",
data: {
key: e,
name: i[0]
}
}), this.debugLog("---> DOUBLE CLICK", i), clearTimeout(this.timers[e]), delete this.activeKeys[a.key]);
break;
}
case "over": {
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "longpressup",
data: {
key: e
}
}), this.debugLog("---> LONG PRESS UP", e), clearTimeout(this.timers[e]), delete this.activeKeys[e];
break;
}
case "available": {
const i = this.getDoubleClick(e), r = this.getCombination(e);
if (i)
this.activeKeys[e] = "clicked", clearTimeout(this.timers[e]), this.timers[e] = setTimeout(() => {
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "press",
data: {
key: e
}
}), this.debugLog("---> PRESS", e), delete this.activeKeys[e];
}, this.config.threshold);
else if (r) {
if (!r[1].filter((l) => l !== e).every((l) => this.activeKeys[l] === "available")) {
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "press",
data: {
key: e
}
}), this.debugLog("---> PRESS (immediate, combination not completed)", e), clearTimeout(this.timers[e]), delete this.activeKeys[e];
break;
}
} else
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "press",
data: {
key: e
}
}), this.debugLog("---> PRESS", e), clearTimeout(this.timers[e]), delete this.activeKeys[e];
break;
}
case "pressed": {
const i = this.getCombination(e);
this.notifyCallbacks({
source: "air-money",
type: "key-event",
subType: "combinationup",
data: {
keys: i[1],
name: i[0]
}
}), this.debugLog("---> COMBINATION UP", i), i == null || i[1].map((r) => {
delete this.activeKeys[r], clearTimeout(this.activeKeys[r]);
});
break;
}
}
});
s(this, "onSimulatorMessage", (a) => {
a.data.source === "air-money" && a.data.type === "key-event" && this.notifyCallbacks(a.data);
});
this.updateConfig(a);
}
updateConfig(a) {
Object.assign(this.config, a);
}
notifyCallbacks(a) {
this.callbacks.forEach((e) => e(a));
}
on(a) {
this.callbacks.push(a), this.callbacks.length === 1 && (window.addEventListener("keydown", this.onKeyDown), window.addEventListener("keyup", this.onKeyUp), window.addEventListener("message", this.onSimulatorMessage));
}
off(a) {
a ? this.callbacks = this.callbacks.filter((e) => e !== a) : this.callbacks = [], this.callbacks.length === 0 && (window.removeEventListener("keydown", this.onKeyDown), window.removeEventListener("keyup", this.onKeyUp), window.removeEventListener("message", this.onSimulatorMessage));
}
getConfig() {
return this.config;
}
}
class g {
constructor(a) {
s(this, "baseURL");
s(this, "createEndpoint", (a) => [this.baseURL, a].join("/"));
s(this, "createPayload", (a, e) => ({
id: (/* @__PURE__ */ new Date()).getTime().toString(),
jsonrpc: "2.0",
method: a,
params: e
}));
s(this, "request", async (a) => await (await fetch(this.createEndpoint(""), {
method: "POST",
body: JSON.stringify(a),
headers: {
Accept: "application/json",
"Content-Type": "application/json"
}
})).json());
this.baseURL = a;
}
}
const o = (t) => {
if (typeof t == "bigint" || typeof t == "number")
return `0x${t.toString(16)}`;
if (typeof t == "string")
return t.startsWith("0x") ? t : `0x${t}`;
throw new Error("Invalid input");
}, b = (t) => {
const a = {};
return t.to && (a.to = o(t.to)), t.value && (a.value = o(t.value)), t.gasLimit && (a.gasLimit = o(t.gasLimit)), t.gasPrice && (a.gasPrice = o(t.gasPrice)), t.maxFeePerGas && (a.maxFeePerGas = o(t.maxFeePerGas)), t.maxPriorityFeePerGas && (a.maxPriorityFeePerGas = o(t.maxPriorityFeePerGas)), t.nonce && (a.nonce = o(t.nonce)), t.chainId && (a.chainId = o(t.chainId)), t.data && (a.data = o(t.data)), t.type && (a.type = o(t.type)), t.gas && (a.gas = o(t.gas)), t.accessList && (a.accessList = t.accessList.map((e) => ({
address: e.address ? o(e.address) : null,
storageKeys: e.storageKeys.map((i) => o(i))
}))), a;
};
class q extends g {
constructor() {
super("http://localhost:5050");
// EVM Operations
s(this, "generateEvmWallet", async () => {
const e = this.createPayload("generateEvmWallet", []);
return await this.request(e);
});
s(this, "listEvmWallets", async () => {
const e = this.createPayload("listEvmWallets", []);
return await this.request(e);
});
s(this, "signEvmMessage", async (e) => {
const i = this.createPayload("signEvmMessage", [e.address, e.message]);
return await this.request(i);
});
s(this, "signEvmTransaction", async (e) => {
const i = this.createPayload("signEvmTransaction", [e.address, e.transaction, e.chainId]);
return await this.request(i);
});
s(this, "signGeneralEvmTransaction", async (e) => {
const i = this.createPayload("signGeneralEvmTransaction", [
e.address,
e.transaction,
e.chainId
]);
return await this.request(i);
});
// Solana Operations
s(this, "generateSolanaWallet", async () => {
const e = this.createPayload("generateSolanaWallet", []);
return await this.request(e);
});
s(this, "listSolanaWallets", async () => {
const e = this.createPayload("listSolanaWallets", []);
return await this.request(e);
});
s(this, "signSolanaMessage", async (e) => {
const i = this.createPayload("signSolanaMessage", [e.address, e.message]);
return await this.request(i);
});
s(this, "signSolanaTransaction", async (e) => {
const i = this.createPayload("signSolanaTransaction", [e]);
return await this.request(i);
});
s(this, "restoreSvmWallet", async (e) => {
const i = this.createPayload("restoreSvmWallet", [e.mnemonic, e.passphrase || ""]);
return await this.request(i);
});
s(this, "signEVMRawTransaction", async (e) => {
const i = b(e.rawTransaction), r = typeof e.chainId == "number" ? o(e.chainId) : e.chainId;
return await this.signGeneralEvmTransaction({
address: e.address,
transaction: i,
chainId: r
});
});
}
}
const h = "app-launcher", U = () => {
const t = new URLSearchParams();
t.set("from", window.location.origin);
const a = y(h) + "?" + t.toString();
window.location.href = a;
}, E = () => window.location.protocol === "file:", W = (t = h) => {
window.location.href = y(t);
}, S = (t = h, a) => [y(t), a].filter(Boolean).join("/"), y = (t = h) => `http://${t}.internal`, D = (t = h) => S(t, "dapp-logo.png");
let d = null;
const A = async () => {
if (d)
return d;
try {
const t = await fetch("/metadata.json");
if (!t.ok)
throw new Error("Failed to fetch metadata.json");
const a = await t.json();
return d = a, a;
} catch (t) {
throw new Error(`Failed to load metadata: ${t instanceof Error ? t.message : "Unknown error"}`);
}
}, C = async () => {
try {
if (E())
return "file";
try {
return (await A()).name;
} catch {
throw new Error("Could not determine application identifier in unbundled environment");
}
} catch {
if (window.AIRMONEY_APP_ID === void 0)
throw new Error("Neither metadata.json nor AIRMONEY_APP_ID is available");
return window.AIRMONEY_APP_ID;
}
}, f = {
enabled: !1,
time: 40
}, I = (t) => t === "setImage" || t === "setAnimate";
class T extends g {
constructor(e) {
super("http://localhost:4040");
s(this, "appName", "");
s(this, "assetsPath", "assets");
s(this, "isInitialized", !1);
s(this, "throttleConfigs", {});
s(this, "createThrottledMethod", (e, i) => async (...r) => {
const n = this.throttleConfigs[i];
if (!n || !n.enabled)
return e.apply(this, r);
const c = r[0].id.toString();
return new Promise((l) => {
if (n.lastArgs.set(c, r), !n.timeouts.has(c)) {
const w = setTimeout(async () => {
try {
const p = n.lastArgs.get(c);
if (p) {
const v = await e.apply(this, p);
l(v);
}
} finally {
n.timeouts.delete(c), n.lastArgs.delete(c);
}
}, n.time);
n.timeouts.set(c, w);
}
});
});
s(this, "initialize", async () => {
if (!this.isInitialized && !this.appName) {
try {
this.appName = await C();
} catch {
if (window.AIRMONEY_APP_ID === void 0)
throw new Error("Neither identifier from metadata.json nor AIRMONEY_APP_ID is available");
this.appName = window.AIRMONEY_APP_ID;
}
if (!this.appName)
throw new Error("Neither identifier from metadata.json nor AIRMONEY_APP_ID is available");
this.isInitialized = !0;
}
});
s(this, "ensureInitialized", async () => {
this.isInitialized || await this.initialize();
});
s(this, "scanWifi", async () => {
const e = this.createPayload("scanWifi", []);
return await this.request(e);
});
s(this, "connectWifi", async (e) => {
const i = this.createPayload("connectWifi", [e.ssid, e.password]);
return await this.request(i);
});
s(this, "managePairing", async (e) => {
const i = this.createPayload("managePairing", [e]);
return await this.request(i);
});
s(this, "getPairingStatus", async () => {
const e = this.createPayload("getPairingStatus", []);
return await this.request(e);
});
s(this, "getBatteryStatus", async () => {
const e = this.createPayload("getBatteryStatus", []);
return await this.request(e);
});
s(this, "getTemperatureStatus", async () => {
const e = this.createPayload("getTemperatureStatus", []);
return await this.request(e);
});
s(this, "getBrightness", async () => {
const e = this.createPayload("getBrightness", []);
return await this.request(e);
});
s(this, "setBrightness", async (e) => {
const i = this.createPayload("setBrightness", [e]);
return await this.request(i);
});
s(this, "getVolume", async () => {
const e = this.createPayload("getVolume", []);
return await this.request(e);
});
s(this, "setVolume", async (e) => {
const i = this.createPayload("setVolume", [e]);
return await this.request(i);
});
s(this, "getWifiStatus", async () => {
const e = this.createPayload("getWifiStatus", []);
return await this.request(e);
});
s(this, "setImage", this.createThrottledMethod(
async (e) => {
await this.ensureInitialized();
const i = this.createPayload("setImage", [
this.createImagePathParam(e.imageName),
e.id
]);
return await this.request(i);
},
"setImage"
));
s(this, "setAnimate", this.createThrottledMethod(
async (e) => {
await this.ensureInitialized();
const i = this.createPayload("setAnimate", [
this.createImagePathParam(e.imageName),
e.id
]);
return await this.request(i);
},
"setAnimate"
));
/**
* @deprecated MPC functionality is deprecated and will be removed in a future version
*/
s(this, "setMPC", async (e, i) => {
const r = this.createPayload("setMpcSession", [e, i]);
return await this.request(r);
});
/**
* @deprecated MPC functionality is deprecated and will be removed in a future version
*/
s(this, "getMPC", async (e) => {
const i = this.createPayload("setMpcSession", [e]);
return await this.request(i);
});
s(this, "getHapticEffects", async () => {
const e = this.createPayload("getHapticEffects", []);
return await this.request(e);
});
s(this, "getHapticConfig", async () => {
const e = this.createPayload("getHapticConfig", []);
return await this.request(e);
});
s(this, "setHapticEffect", async (e) => {
const i = this.createPayload("setHapticEffect", [e.action, e.effectId]);
return await this.request(i);
});
s(this, "createImagePathParam", (e) => {
if (!this.appName)
throw new Error("App name is required");
return [this.appName, this.assetsPath, e].filter(Boolean).join("/");
});
e && Object.entries(e).forEach((i) => {
const r = i[0], n = i[1];
I(r) && (this.throttleConfigs[r] = {
enabled: n.throttleEnabled ?? f.enabled,
time: n.throttleTime ?? f.time,
timeouts: /* @__PURE__ */ new Map(),
lastArgs: /* @__PURE__ */ new Map()
});
});
}
}
const K = new T({
setImage: {
throttleEnabled: !0
},
setAnimate: {
throttleEnabled: !0
}
});
class x {
constructor() {
s(this, "baseURL", "http://localhost:6060");
s(this, "createEndpoint", (a) => `${this.baseURL}${a}`);
s(this, "get", async (a) => {
try {
const e = await fetch(this.createEndpoint(a), {
method: "GET",
headers: {
Accept: "application/json"
}
});
if (!e.ok) {
const c = await e.text();
throw new Error(`HTTP error ${e.status}: ${c}`);
}
const i = e.headers.get("content-type"), r = await e.text();
if (!r)
return null;
let n;
if (i != null && i.includes("application/json"))
try {
n = JSON.parse(r);
} catch {
throw new Error(`Invalid JSON response: ${r.substring(0, 100)}...`);
}
else
try {
n = JSON.parse(r);
} catch {
return r;
}
if (n == null)
throw new Error("Empty response received");
return n;
} catch (e) {
throw e instanceof Error ? new Error(`Update service error: ${e.message}`) : new Error("Unknown error occurred while fetching data");
}
});
s(this, "appVersions", async () => await this.get("/app/versions"));
s(this, "appCheck", async (a) => await this.get(`/app/${a}/version`));
s(this, "appUpdate", async (a) => await this.get(`/app/${a}/update`));
s(this, "serviceVersion", async () => await this.get("/service/version"));
s(this, "serviceCheck", async () => await this.get("/service/check"));
s(this, "serviceUpdate", async () => await this.get("/service/update"));
s(this, "firmwareVersion", async () => await this.get("/firmware/version"));
s(this, "internetCheck", async () => await this.get("/internet/check"));
s(this, "appList", async () => await this.get("/app/list"));
s(this, "appRefresh", async (a) => await this.get(`/app/${a}/refresh`));
s(this, "appRemove", async (a) => await this.get(`/app/${a}/remove`));
}
}
var _ = /* @__PURE__ */ ((t) => (t.Right = "right", t.Left = "left", t))(_ || {});
const B = {
balance_effect: "Balance action",
depin_effect: "Depin action",
left_effect: "Left button press",
right_effect: "Right button press",
rotary_click_effect: "Rotary encoder click",
rotary_turn_effect: "Rotary encoder turning",
shift_effect: "Shift action"
}, $ = {
balance_effect: "balance",
depin_effect: "depin",
left_effect: "left",
right_effect: "right",
rotary_click_effect: "rotary_click",
rotary_turn_effect: "rotary_turn",
shift_effect: "shift"
}, G = (t) => !!(t === "true" || Number(t)), H = (t) => t !== void 0 ? /^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$/.test(t) : !1, N = (t) => t.every((a) => a !== void 0), z = (t) => {
if (N(t)) return t;
}, F = (t) => "result" in t, L = (t) => "error" in t, V = (t) => t.status === !0, M = (t) => t.status === !1, m = (t) => async (...a) => {
const e = await t(...a);
if (L(e))
throw new Error(e.error.message || "AMService error occurred");
return e;
}, Y = (t) => async (...a) => {
const e = await t(...a);
if (M(e))
throw new Error(e.error || "AMUpdateService error occurred");
return e;
}, J = m, Q = m;
export {
u as AMKey,
_ as AMServiceScreen,
$ as AM_HAPTIC_ACTION_MAP,
B as AM_HAPTIC_ACTION_NAME_MAP,
h as APP_LAUNCHER_NAME,
q as AirMoneyCryptoService,
O as AirMoneyKeyEvent,
T as AirMoneyService,
x as AirMoneyUpdateService,
K as airmoneyService,
Q as airmoneyServiceErrorWrapper,
U as backToHome,
J as cryptoServiceErrorWrapper,
S as displayAsset,
m as errorWrapper,
y as getAppLink,
D as getAppLogo,
W as goToApp,
L as isAMServiceErrorResponse,
F as isAMServiceSuccessResponse,
M as isAMUpdateServiceErrorResponse,
V as isAMUpdateServiceSuccessResponse,
E as isFileProtocol,
N as isParamsValid,
H as isValidNumber,
b as normalizeEVMTransaction,
z as serializeParams,
G as toBoolean,
o as toHexString,
Y as updateServiceErrorWrapper
};