UNPKG

@airmoney-degn/controller-sdk

Version:

SDK for controlling AirMoney devices, providing button screen management, key event handling, and device communication capabilities

2 lines (1 loc) 16.9 kB
(function(r,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(r=typeof globalThis<"u"?globalThis:r||self,d(r.AirMoneyControllerSDK={}))})(this,function(r){"use strict";var X=Object.defineProperty;var Z=(r,d,l)=>d in r?X(r,d,{enumerable:!0,configurable:!0,writable:!0,value:l}):r[d]=l;var s=(r,d,l)=>Z(r,typeof d!="symbol"?d+"":d,l);class d{constructor(a){s(this,"baseURL");s(this,"serviceName");s(this,"createEndpoint",a=>[this.baseURL,a].join("/"));s(this,"createPayload",(a,e)=>({id:new Date().getTime().toString(),jsonrpc:"2.0",method:a,params:e}));this.baseURL=a,this.serviceName=this.constructor.name}async request(a){return await(await fetch(this.createEndpoint(""),{method:"POST",body:JSON.stringify(a),headers:{Accept:"application/json","Content-Type":"application/json"}})).json()}}const l=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=l(t.to)),t.value&&(a.value=l(t.value)),t.gasLimit&&(a.gasLimit=l(t.gasLimit)),t.gasPrice&&(a.gasPrice=l(t.gasPrice)),t.maxFeePerGas&&(a.maxFeePerGas=l(t.maxFeePerGas)),t.maxPriorityFeePerGas&&(a.maxPriorityFeePerGas=l(t.maxPriorityFeePerGas)),t.nonce&&(a.nonce=l(t.nonce)),t.chainId&&(a.chainId=l(t.chainId)),t.data&&(a.data=l(t.data)),t.type&&(a.type=l(t.type)),t.gas&&(a.gas=l(t.gas)),t.accessList&&(a.accessList=t.accessList.map(e=>({address:e.address?l(e.address):null,storageKeys:e.storageKeys.map(i=>l(i))}))),a};class R extends d{constructor(){super("http://localhost:5050");s(this,"signEvmMessage",async e=>{const i=this.createPayload("signEvmMessage",[e]);return await this.request(i)});s(this,"signEvmTransaction",async e=>{const i=this.createPayload("signEvmTransaction",[e]);return await this.request(i)});s(this,"signGeneralEvmTransaction",async e=>{const i=this.createPayload("signGeneralEvmTransaction",[e]);return await this.request(i)});s(this,"signEip712TypedData",async e=>{const i=this.createPayload("signEip712TypedData",[e]);return await this.request(i)});s(this,"verifyEip1271Signature",async e=>{const i=this.createPayload("verifyEip1271Signature",[e.rpcUrl,e.contractAddress,e.message,e.signature]);return await this.request(i)});s(this,"signSolanaMessage",async e=>{const i=this.createPayload("signSolanaMessage",[e]);return await this.request(i)});s(this,"signSolanaTransaction",async e=>{const i=this.createPayload("signSolanaTransaction",[e]);return await this.request(i)});s(this,"signEVMRawTransaction",async e=>{const i=b(e.rawTransaction),n=typeof e.chain_id=="number"?l(e.chain_id):e.chain_id;return await this.signGeneralEvmTransaction({address:e.address,typed_tx:i,chain_id:n,pin:e.pin})});s(this,"getDefaultEvmWallet",async()=>{const e=this.createPayload("getDefaultEvmWallet",[]);return await this.request(e)});s(this,"getDefaultSvmWallet",async()=>{const e=this.createPayload("getDefaultSvmWallet",[]);return await this.request(e)});s(this,"signBitcoinMessage",async e=>{const i=this.createPayload("signBitcoinMessage",[e]);return await this.request(i)});s(this,"verifyBitcoinSignature",async e=>{const i=this.createPayload("verifyBitcoinSignature",[e.address,e.message,e.signature]);return await this.request(i)});s(this,"signBitcoinTransaction",async e=>{const i=this.createPayload("signBitcoinTransaction",[e]);return await this.request(i)});s(this,"getDefaultBitcoinWallet",async()=>{const e=this.createPayload("getDefaultBitcoinWallet",[]);return await this.request(e)});s(this,"getDeviceStatus",async()=>{const e=this.createPayload("getDeviceStatus",[]);return await this.request(e)});s(this,"verifyPin",async e=>{const i=this.createPayload("verifyPin",[e]);return await this.request(i)})}}const M=t=>"result"in t,p=t=>"error"in t;var P=(t=>(t.Right="right",t.Left="left",t))(P||{}),c=(t=>(t.CoreUnhandled="CoreUnhandled",t.DisplayInvalidInput="DisplayInvalidInput",t.DisplayAssetLoad="DisplayAssetLoad",t.DisplayHardware="DisplayHardware",t.NetworkCommand="NetworkCommand",t.NetworkAuth="NetworkAuth",t.NetworkConfig="NetworkConfig",t.HapticInvalidAction="HapticInvalidAction",t.HapticHardware="HapticHardware",t.BluetoothControl="BluetoothControl",t.BluetoothData="BluetoothData",t.BrightnessFailure="BrightnessFailure",t.AudioFailure="AudioFailure",t.TelemetryRead="TelemetryRead",t.TelemetryRender="TelemetryRender",t.SessionParse="SessionParse",t.SessionStorage="SessionStorage",t.Unknown="Unknown",t))(c||{});const y="app-launcher",L=()=>{fetch("http://127.0.0.1:7070/background",{method:"GET"}).catch(t=>{console.error("Failed to return to launcher:",t)})},O=()=>{fetch("http://127.0.0.1:7070/reload",{method:"GET"}).catch(t=>{console.error("Failed to reload web app:",t)})},k=()=>window.location.protocol==="file:",B=()=>window.location.hostname.endsWith(".internal"),K=(t=y)=>{window.location.href=f(t)},E=(t=y,a)=>[f(t),a].filter(Boolean).join("/"),f=(t=y)=>`http://${t}.internal`,F=(t=y)=>E(t,"dapp-logo.png");let w=null;const _=async()=>{if(w)return w;try{const t=await fetch("/metadata.json");if(!t.ok)throw new Error("Failed to fetch metadata.json");const a=await t.json();return w=a,a}catch(t){throw new Error(`Failed to load metadata: ${t instanceof Error?t.message:"Unknown error"}`)}},C=async()=>{try{if(k())return"file";try{return(await _()).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}},A={enabled:!1,time:40},H=t=>t==="setImage"||t==="setAnimate",m=class m extends d{constructor(e){super("http://localhost:4040");s(this,"appName","");s(this,"isInitialized",!1);s(this,"throttleConfigs",{});s(this,"createThrottledMethod",(e,i)=>async(...n)=>{const o=this.throttleConfigs[i];if(!o||!o.enabled)return e.apply(this,n);const u=n[0].id.toString();return new Promise($=>{if(o.lastArgs.set(u,n),!o.timeouts.has(u)){const J=setTimeout(async()=>{try{const T=o.lastArgs.get(u);if(T){const Q=await e.apply(this,T);$(Q)}}finally{o.timeouts.delete(u),o.lastArgs.delete(u)}},o.time);o.timeouts.set(u,J)}})});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,"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"));s(this,"createImagePathParam",e=>{if(!this.appName)throw new Error("App name is required");return[this.appName,e].filter(Boolean).join("/")});e&&Object.entries(e).forEach(i=>{const n=i[0],o=i[1];H(n)&&(this.throttleConfigs[n]={enabled:o.throttleEnabled??A.enabled,time:o.throttleTime??A.time,timeouts:new Map,lastArgs:new Map})})}async request(e){const i=await super.request(e);if(p(i)){const n=m.ERROR_CODE_MAP.get(i.error.code);return{...i,type:(n==null?void 0:n.type)??c.Unknown,userMessage:(n==null?void 0:n.userMessage)||i.error.message||"Unknown error"}}return i}};s(m,"ERROR_CODE_MAP",new Map([[1e3,{type:c.CoreUnhandled,userMessage:"An unexpected system error occurred. Please try again."}],[2001,{type:c.DisplayInvalidInput,userMessage:"The parameter is invalid. Please check your input and try again."}],[2002,{type:c.DisplayAssetLoad,userMessage:"Unable to load or decode the image file. Please check that the image exists and is in a supported format."}],[2003,{type:c.DisplayHardware,userMessage:"Display hardware error. The display mutex or SPI communication failed. Please try again."}],[3001,{type:c.NetworkCommand,userMessage:"Network or system command execution failed. Please try again."}],[3002,{type:c.NetworkAuth,userMessage:"Wi-Fi authentication timed out. Please check your password and try again."}],[3003,{type:c.NetworkConfig,userMessage:"Failed to write network configuration. Please try again."}],[4001,{type:c.HapticInvalidAction,userMessage:"Invalid haptic action name. Please check your input and try again."}],[4002,{type:c.HapticHardware,userMessage:"Haptic hardware error occurred. Please try again."}],[5001,{type:c.BluetoothControl,userMessage:"Pairing service control failed. Please try again."}],[5002,{type:c.BluetoothData,userMessage:"Failed to read or parse Bluetooth device data. Please try again."}],[6001,{type:c.BrightnessFailure,userMessage:"Failed to adjust brightness. Hardware interaction error or missing device. Please try again."}],[6002,{type:c.AudioFailure,userMessage:"Audio operation failed. Hardware interaction error or missing ALSA device. Please try again."}],[7001,{type:c.TelemetryRead,userMessage:"Failed to read telemetry data. Power supply paths are unreadable. Please try again."}],[7002,{type:c.TelemetryRender,userMessage:"Failed to render telemetry data. Error composing status payload. Please try again."}],[8001,{type:c.SessionParse,userMessage:"Failed to parse session data. Invalid JSON format. Please try again."}],[8002,{type:c.SessionStorage,userMessage:"Session storage error. Filesystem read or write failed. Please try again."}]]));let g=m;const q=new g({setImage:{throttleEnabled:!0},setAnimate:{throttleEnabled:!0}}),v=t=>async(...a)=>{const e=await t(...a);if(p(e))throw new Error(e.error.message||"AMService error occurred");return e},z=v,G=v;var h=(t=>(t.LeftButton="ArrowLeft",t.RightButton="ArrowRight",t.CounterClockwiseRotary="]",t.ClockwiseRotary="[",t.RotaryButton="Enter",t.SideButton="ArrowUp",t.MuteSwitch="ArrowDown",t))(h||{});class N{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,"window",window);s(this,"keyUpEventName","keyup");s(this,"keyDownEventName","keydown");s(this,"getSortedCombinations",a=>{var i;return(i=(n=>this.config.combinations&&Object.entries(this.config.combinations).filter(([,o])=>o.includes(n)))(a))==null?void 0:i.sort(([,n],[,o])=>o.length-n.length)});s(this,"isCombinationComplete",(a,e)=>a[1].every(i=>this.activeKeys[i]===e));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,"getKeyFromEvent",a=>{let e=null;return a instanceof CustomEvent&&a.detail&&a.detail.key&&(e=a.detail.key),a instanceof KeyboardEvent&&(e=a.key),!e||!Object.values(h).includes(e)?null:e});s(this,"handleCombination",a=>{a[1].map(e=>{this.activeKeys[e]="pressed",clearTimeout(this.timers[e])}),this.notifyCallbacks({source:"air-money",type:"key-event",subType:"combinationdown",data:{keys:a[1],name:a[0]}}),this.debugLog("---> COMBINATION DOWN",a)});s(this,"onKeyDown",a=>{const e=this.getKeyFromEvent(a);if(e)switch(a.preventDefault(),this.activeKeys[e]){case"pressed":case"clicked":case"end":return;case"over":{Object.entries(this.activeKeys).filter(([,i])=>i==="over").forEach(([i])=>{this.notifyCallbacks({source:"air-money",type:"key-event",subType:"longpressdown",data:{key:i}}),this.debugLog("---> LONG PRESS DOWN",i)});return}case void 0:{const i=this.getSortedCombinations(e),n=i==null?void 0:i[0];if(this.activeKeys[e]="available",n&&this.isCombinationComplete(n,"available")){this.handleCombination(n);return}else i!=null&&i.length&&i.length>1&&(this.timers[e]=setTimeout(()=>{const o=i.find(u=>this.isCombinationComplete(u,"available"));o&&this.handleCombination(o)},this.config.threshold));this.timers[e]=setTimeout(()=>{this.notifyCallbacks({source:"air-money",type:"key-event",subType:"longpressdown",data:{key:e}}),this.debugLog("---> LONG PRESS DOWN",e),this.activeKeys[e]="over"},this.config.threshold);break}}});s(this,"onKeyUp",a=>{const e=this.getKeyFromEvent(a);if(e)switch(a.preventDefault(),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[e]);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),n=this.getSortedCombinations(e),o=n==null?void 0:n.find(u=>this.isCombinationComplete(u,"available"));o?this.handleCombination(o):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)):(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.getSortedCombinations(e),n=i==null?void 0:i.find(o=>this.isCombinationComplete(o,"pressed"));n&&(this.notifyCallbacks({source:"air-money",type:"key-event",subType:"combinationup",data:{keys:n[1],name:n[0]}}),this.debugLog("---> COMBINATION UP",n),n==null||n[1].map(o=>{delete this.activeKeys[o],clearTimeout(this.activeKeys[o])}));break}}});window&&(this.window=window),this.updateConfig(a),this.keyUpEventName=(a==null?void 0:a.keyUpEventName)||this.keyUpEventName,this.keyDownEventName=(a==null?void 0:a.keyDownEventName)||this.keyDownEventName}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&&(this.window.addEventListener(this.keyDownEventName,this.onKeyDown),this.window.addEventListener(this.keyUpEventName,this.onKeyUp))}off(a){a?this.callbacks=this.callbacks.filter(e=>e!==a):this.callbacks=[],this.callbacks.length===0&&(this.window.removeEventListener("keydown",this.onKeyDown),this.window.removeEventListener("keyup",this.onKeyUp))}getConfig(){return this.config}}class I{constructor(a){s(this,"keyEvent");s(this,"triggerConfigs",new Map);s(this,"listenerIdCounter",0);s(this,"isInitialized",!1);s(this,"debug",!1);s(this,"initialize",()=>{if(this.isInitialized)return;const a=e=>{this.handlePriorityEvent(e)};this.keyEvent.on(a),this.isInitialized=!0});s(this,"subscribe",a=>{this.initialize();const e=`listener_${++this.listenerIdCounter}`;return this.triggerConfigs.set(e,{...a,id:e}),e});s(this,"handlePriorityEvent",a=>{const e=Array.from(this.triggerConfigs.values()).sort((n,o)=>o.priority-n.priority),i=[];for(const n of e)for(const o of n.triggers)i.push(Object.assign(o,{name:n.name}));this.debug&&console.log("---> ALL TRIGGERS",i.map(n=>n.name));for(const n of i)if(n.condition(a)){this.debug&&console.log("---> TRIGGER",n.name),n.trigger(a);break}});s(this,"unsubscribe",a=>(this.triggerConfigs.delete(a),!0));s(this,"unsubscribeAll",()=>{this.triggerConfigs.clear()});s(this,"getKeyEventInstance",()=>this.keyEvent);s(this,"updateConfig",a=>{this.keyEvent.updateConfig(a)});s(this,"getConfig",()=>this.keyEvent.getConfig());s(this,"destroy",()=>{this.unsubscribeAll(),this.keyEvent.off(),this.isInitialized=!1});this.keyEvent=a.instance,this.debug=a.debug??!1}}const D=(t={})=>{const{combinations:a,...e}=t;return new N({combinations:{back:[h.LeftButton,h.RightButton],backToHome:[h.LeftButton,h.RightButton,h.SideButton],...a},...e})},W=(t={})=>{const{instance:a,...e}=t;return new I({instance:a??D(e),...e})},U=t=>!!(t==="true"||Number(t)),V=t=>t!==void 0?/^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$/.test(t):!1,S=t=>t.every(a=>a!==void 0),Y=t=>{if(S(t))return t};r.AMKey=h,r.AMServiceScreen=P,r.AMServiceUserErrorType=c,r.APP_LAUNCHER_NAME=y,r.AirMoneyCryptoService=R,r.AirMoneyKeyEvent=N,r.AirMoneyKeyEventManager=I,r.AirMoneyService=g,r.airmoneyService=q,r.airmoneyServiceErrorWrapper=G,r.backToHome=L,r.createDefaultKeyEvent=D,r.createDefaultKeyEventManager=W,r.cryptoServiceErrorWrapper=z,r.displayAsset=E,r.errorWrapper=v,r.getAppLink=f,r.getAppLogo=F,r.getAppName=C,r.goToApp=K,r.isAMServiceErrorResponse=p,r.isAMServiceSuccessResponse=M,r.isFileProtocol=k,r.isInDevice=B,r.isParamsValid=S,r.isValidNumber=V,r.normalizeEVMTransaction=b,r.reloadWebApp=O,r.serializeParams=Y,r.toBoolean=U,r.toHexString=l,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});