ixo-oracles-cli 1.0.5 → 1.1.0
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/cli.js +11 -11
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{cancel as ye,intro as sr,isCancel as ot,log as _,outro as ar,select as st,spinner as cr}from"@clack/prompts";import P from"process";var F=class{commands;constructor(){this.commands=new Map}register(e){this.commands.set(e.name,e)}get(e){return this.commands.get(e)}getAll(){return Array.from(this.commands.values())}getCommandOptions(){return this.getAll().map(e=>({value:e.name,label:e.name,hint:e.description}))}};import*as m from"@clack/prompts";import{select as lt}from"@clack/prompts";import{z as se}from"zod";var T=async r=>{let e=await lt({message:"Select network: (default: devnet)",options:[{value:"mainnet",label:"Mainnet"},{value:"testnet",label:"Testnet"},{value:"devnet",label:"Devnet"}],initialValue:"devnet",maxItems:1});return r.addValue("network",e),e},ve={mainnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d",testnet:"did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb",devnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d"},v={devnet:"https://devmx.ixo.earth",testnet:"https://testmx.ixo.earth",mainnet:"https://mx.ixo.earth"},M={devnet:"https://rooms.bot.devmx.ixo.earth",testnet:"https://rooms.bot.testmx.ixo.earth",mainnet:"https://rooms.bot.mx.ixo.earth"};var Re={devnet:"https://ixo-portal.vercel.app",testnet:"https://ixo-portal.vercel.app",mainnet:"https://ixo-portal.vercel.app"},N={mainnet:"https://impacthub.ixo.world/rpc/",testnet:"https://testnet.ixo.earth/rpc/",devnet:"https://devnet.ixo.earth/rpc/"},w=(r,e="This field is required")=>{let i=se.string().min(1,e).safeParse(r);if(!i.success)return i.error.message},X=(r,e="This url is required or a valid URL")=>{let i=se.url(e).safeParse(r);if(!i.success)return i.error.message},Ee=(r,e="This number is required")=>{let i=se.number().min(1,e).safeParse(r);if(!i.success)return i.error.message};import{isCancel as Bt,log as y,spinner as Vt,text as qt}from"@clack/prompts";import{customMessages as Ye,ixo as R,utils as ue}from"@ixo/impactxclient-sdk";import{utils as ge}from"@ixo/impactxclient-sdk";import{createMatrixApiClient as _t}from"@ixo/matrixclient-sdk";import{sha256 as At}from"@cosmjs/crypto";import{encrypt as bt}from"eciesjs";import{ClientEvent as Pt,createClient as de}from"matrix-js-sdk";import Ot from"md5";var $=new Map;function dt(r){return $.get(r)instanceof Uint8Array}function mt(r){return $.get(r)}function ae(){$.clear()}async function Se({keys:r}){let e=Object.keys(r),t=e.find(dt);if(console.info("[] getSecretStorageKey",r,e,t),!t)return null;let i=mt(t);return[t,i]}function Ae(r,e,t){$.set(r,t)}import{Bip39 as Ie,EnglishMnemonic as Te,Secp256k1 as ce,sha256 as ut,Slip10 as Ne,Slip10Curve as ke,stringToPath as Ue}from"@cosmjs/crypto";import{DirectSecp256k1HdWallet as ft}from"@cosmjs/proto-signing";import{createQueryClient as Le,createSigningClient as ht,customMessages as wt,ixo as yt,utils as xt}from"@ixo/impactxclient-sdk";import{createCipheriv as Ct,randomBytes as vt}from"crypto";import{createQueryClient as vr,createRegistry as pt,utils as gt}from"@ixo/impactxclient-sdk";function D(r){try{return gt.proto.fromTimestamp(r).getTime()}catch{return}}var B={BasicAllowance:"/cosmos.feegrant.v1beta1.BasicAllowance",PeriodicAllowance:"/cosmos.feegrant.v1beta1.PeriodicAllowance"};var be=r=>{let e=pt();return(r??[]).map(t=>{let i=t.allowance,n=e.decode(i);switch(i.typeUrl){case B.BasicAllowance:return{granter:t.granter,grantee:t.grantee,type:B.BasicAllowance,expiration:n.expiration?D(n.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};case B.PeriodicAllowance:return{granter:t.granter,grantee:t.grantee,type:B.PeriodicAllowance,expiration:n.basic?.expiration?D(n.basic.expiration):null,limit:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};default:return{type:i.typeUrl,granter:t.granter,grantee:t.grantee,expiration:n.expiration?D(n.expiration):n.basic?.expiration?D(n.basic.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:n.allowedMessages}}})},Pe=r=>{if(r==null)return!1;let e=typeof r=="object"?D(r):r;return e==null?!0:e<Date.now()},Oe=r=>r==null?!1:(typeof r=="object"?Number(r?.amount??0):typeof r=="string"?Number(r??0):r)<=5e-4;async function le(r,e){if(!e)throw new Error("Network parameter is required but was undefined");console.log(`\u{1F50D} Checking IID document for DID: ${r} on network: ${e}`);let t=N[e];if(!t)throw new Error(`Invalid network: ${e}. Valid networks are: ${Object.keys(N).join(", ")}`);console.log(`\u{1F517} Using RPC URL: ${t}`);try{return!!(await(await Le(t)).ixo.iid.v1beta1.iidDocument({id:r}))?.iidDocument?.id}catch(i){if(i.message?.includes("did document not found")||i.message?.includes("(22)"))return!1;throw console.error("Error checking IID document:",i),i}}async function Me(r,e,t){try{let i=await t.getAccounts(),{address:n,pubkey:o}=i[0]??{},s=await Rt(n,e),a=s?.length?be(s)?.find(c=>!!c&&!Pe(c.expiration)&&!Oe(c.limit))?.granter:void 0,l={typeUrl:"/ixo.iid.v1beta1.MsgCreateIidDocument",value:yt.iid.v1beta1.MsgCreateIidDocument.fromPartial({id:r,verifications:wt.iid.createIidVerificationMethods({did:r,pubkey:o,address:n,controller:r,type:"secp"}),signer:n,controllers:[r]})};await Et({offlineSigner:t,messages:[l],feegrantGranter:a,network:e})}catch(i){throw console.error(i),i}}async function Rt(r,e){try{let t=N[e];if(!t)throw new Error(`Invalid network: ${e}`);return(await(await Le(t)).cosmos.feegrant.v1beta1.allowances({grantee:r}))?.allowances??[]}catch(t){console.error("queryAddressAllowances::",t.message);return}}var Et=async({offlineSigner:r,messages:e,memo:t="Signing with Mnemonic Demo",feegrantGranter:i,network:n})=>{let o=N[n];if(!o)throw new Error(`Invalid network: ${n}`);let s=await ht(o,r),a=await r.getAccounts(),{address:l}=a[0]??{},c=await s.simulate(l,e,t),f=(c>5e4?c:(e??[]).length*5e5)*1.7,A=St(f),x={amount:[{denom:"uixo",amount:String(Math.round(A.average))}],gas:String(Math.round(f)),granter:i},C=await s.signAndBroadcast(l,e,x,t,void 0);if(!!C.code)throw new Error(`Error when broadcasting tx ${C.transactionHash} at height ${C.height}. Code: ${C.code}; Raw log: ${C.rawLog}`)},St=r=>{let e={low:.02,average:.035,high:.045},t=r<.01?.01:r;return{low:t*e.low,average:t*e.average,high:t*e.high}},V=r=>new Promise(e=>setTimeout(e,r));function De(r,e){let t=vt(16),i=Ct("aes-256-cbc",Buffer.from(e.padEnd(32)),t),n=i.update(r);return n=Buffer.concat([n,i.final()]),t.toString("hex")+":"+n.toString("hex")}var We=async r=>{let e=await ft.fromMnemonic(r,{prefix:"ixo"}),t=(await e.getAccounts())[0],i=await Ie.mnemonicToSeed(new Te(r)),n=Ue("m/44'/118'/0'/0/0"),s=Ne.derivePath(ke.Secp256k1,i,n).privkey,a=await ce.makeKeypair(s),l=ce.compressPubkey(a.pubkey);return{mnemonic:r,did:xt.did.generateSecpDid(t.address),baseAccount:t,async getAccounts(){return await e.getAccounts()},async signDirect(p,f){return await e.signDirect(p,f)},async sign(p){try{let f=await Ie.mnemonicToSeed(new Te(r)),A=Ue("m/44'/118'/0'/0/0"),{privkey:x}=Ne.derivePath(ke.Secp256k1,f,A),C=new Uint8Array(Buffer.from(p,"base64")),re=ut(C);return(await ce.createSignature(re,x)).toFixedLength().slice(0,64)}catch(f){throw console.error("Error during signature creation:",f),f}}}};var It="/.well-known/matrix/client",me=async({homeServerUrl:r,username:e,password:t,deviceName:i},n=!1)=>{let o=r,s=e,a=s.match(/^@(.+):(.+\..+)$/);a&&(s=a[1],o=a[2],o=n?o:await Dt(o));try{let l=je(o),c=await l.login("m.login.password",{identifier:{type:"m.id.user",user:Wt(s)},password:t,initial_device_display_name:i});return{accessToken:c.access_token,deviceId:c.device_id,userId:c.user_id,baseUrl:n?o:c?.well_known?.["m.homeserver"]?.base_url||l.baseUrl}}catch(l){let c=l.message;throw c==="Unknown message"&&(c="Please check your credentials"),console.error("mxLogin::",c),new Error(c)}};async function Tt(r){let e=await fetch(`${M[r]}/public-key`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error("Failed to fetch public key for encryption");return await e.json()}function Nt(r){let e={timestamp:new Date().toISOString(),address:r,service:"matrix",type:"create-account"},t=Buffer.from(JSON.stringify(e)).toString("base64");return{challenge:e,challengeBase64:t}}function kt(r,e){let t=new Uint8Array(Buffer.from(e,"hex")),i=new Uint8Array(Buffer.from(r,"utf8")),n=bt(t,i);return Array.from(n,o=>o.toString(16).padStart(2,"0")).join("")}async function Ut(r,e,t,i,n){let o=await Tt(n),s=kt(e,o.publicKey),a={address:r,encryptedPassword:s,publicKeyFingerprint:o.fingerprint,secpResult:{signature:t,challenge:i}},l=await fetch(`${M[n]}/user/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok){let c=await l.json();throw new Error(c.error||"Failed to create user account")}return await l.json()}async function Ke(r,e,t,i,n){try{let{challengeBase64:o}=Nt(r),s=await i.sign(o),a=Buffer.from(s).toString("base64");if(!(await Ut(r,e,a,o,n)).success)throw new Error("Failed to create matrix account via API");let c=v[n],p=pe(r);return await me({homeServerUrl:c,username:p,password:e,deviceName:t})}catch(o){throw console.error("mxRegisterWithSecp error:",o),o}}async function _e({homeServerUrl:r,username:e}){let t=je(r);try{return!!await t.isUsernameAvailable(e)}catch{return!1}}function je(r){if(!r)throw new Error("Home server URL is required to instantiate matrix client");return de({baseUrl:r})}async function Fe({homeServerUrl:r,accessToken:e,userId:t,deviceId:i}){if(console.log("createMatrixClient::",{homeServerUrl:r,accessToken:e,userId:t,deviceId:i}),!r||!e||!t||!i)throw new Error("Login to Matrix account before trying to instantiate Matrix client.");let n=de({baseUrl:r,accessToken:e,userId:t,deviceId:i,timelineSupport:!0,cryptoCallbacks:{getSecretStorageKey:Se,cacheSecretStorageKey:Ae},verificationMethods:["m.sas.v1"]});return await n.initRustCrypto({useIndexedDB:!1}),n.setMaxListeners(20),await n.startClient({lazyLoadMembers:!0,includeArchivedRooms:!1}),await new Promise((o,s)=>{let a={NULL:()=>{console.info("[NULL] state")},SYNCING:()=>{},PREPARED:()=>{console.info(`[PREPARED] state: user ${t}`),o()},RECONNECTING:()=>{console.info("[RECONNECTING] state")},CATCHUP:()=>{console.info("[CATCHUP] state")},ERROR:()=>{s(new Error("[ERROR] state: starting matrix client"))},STOPPED:()=>{console.info("[STOPPED] state")}};n.on(Pt.Sync,l=>{a[l]()})}),n}async function Xe({mxClient:r,baseUrl:e,accessToken:t,userId:i,deviceId:n}){let o=r;o||(o=de({baseUrl:e,accessToken:t,userId:i,deviceId:n})),o&&(o.stopClient(),await o.logout().catch(console.error),o.clearStores())}function $e(r){let e=r.getAccountData("m.cross_signing.master");return console.log("hasCrossSigningAccountData::masterKeyData",e),!!e}async function Be(r,{securityPhrase:e,password:t,forceReset:i=!1,skipBootstrapSecureStorage:n=!1}){i&&ae();let o=r.getCrypto();if(!o)throw new Error("Failed to setup matrix cross signing - failed to get matrix crypto api");if(!n){let a=await o.createRecoveryKeyFromPassphrase(e);ae(),await o.bootstrapSecretStorage({createSecretStorageKey:async()=>a,setupNewSecretStorage:i})}let s=r.getUserId();return await o.bootstrapCrossSigning({authUploadDeviceSigningKeys:async function(a){await a(Kt({userId:s,password:t}))},setupNewCrossSigning:i}),await o.resetKeyBackup(),await V(300),!!r.getAccountData("m.cross_signing.master")}function pe(r){if(!r)throw new Error("Address is required to generate matrix username");return"did-ixo-"+r}function Ve(r){return Buffer.from(Ot(r.replace(/ /g,""))).toString("base64").slice(0,24)}function qe(r){let e=At(new TextEncoder().encode(r.replace(/ /g,"")));return Buffer.from(e).toString("base64").slice(0,32)}function Lt(r){return r.replace(/^(https?:\/\/)/,"").replace(/\/$/,"")}function Mt(r,e=""){return"did-ixo-"+r+e}function Ge(r,e){return"#"+Mt(r)+":"+Lt(e)}async function Dt(r){let e="https://";/^https?:\/\//.test(r)&&(e="");let t=`${e}${r}${It}`;try{let o=(await(await fetch(t,{method:"GET"})).json())["m.homeserver"]?.base_url;if(o===void 0)throw new Error;return o}catch{return`${e}${r}`}}function Wt(r){return(r.indexOf("@")===0?r.substring(1):r).trim()}function Kt({userId:r,password:e}){return{type:"m.login.password",password:e,identifier:{type:"m.id.user",user:r}}}var He="Oracles CLI";async function q({pin:r,oracleName:e,network:t,oracleAvatarUrl:i},n){try{let o=ge.mnemonic.generateMnemonic(),s=await We(o),a=s.baseAccount.address;console.log("\u2705 Wallet created:",a),await n(a);let l=ge.did.generateSecpDid(a),c=await le(l,t);if(console.log("\u2705 DID exists:",c),!c&&(console.log("\u2705 DID does not exist, creating..."),await Me(l,t,s),console.log("\u2705 DID created, waiting 500ms..."),await V(500),console.log("\u2705 Checking if DID exists..."),!await le(l,t)))throw new Error("Failed to create DID document");console.log("\u2705 DID created:",l);let p=ge.mnemonic.generateMnemonic(12),f=v[t],A=pe(a),x=Ve(p),C=qe(p);if(!await _e({homeServerUrl:f,username:A}))throw new Error("Matrix account already exists");let h=await Ke(a,x,He,s,t);if(!h?.accessToken)throw new Error("Failed to register matrix account");console.log("\u2705 Matrix account created:",h.userId);let O=await Fe({homeServerUrl:f,accessToken:h.accessToken,userId:h.userId,deviceId:h.deviceId});try{await Promise.all([O.setDisplayName(e),O.setAvatarUrl(i)])}catch(I){console.error("Failed to set display name or avatar url:",I)}let j=_t({homeServerUrl:f,accessToken:h.accessToken}),ie=$e(O);if(!ie&&(ie=await Be(O,{securityPhrase:C,password:x,forceReset:!0}),!ie))throw new Error("Failed to setup cross signing");console.log("\u2705 Matrix cross-signing setup completed");let at=Ge(a,h.baseUrl),E=(await j.room.v1beta1.queryId(at).catch(()=>{}))?.room_id??"";if(!E){let I=await fetch(`${M[t]}/room/source`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:l,userMatrixId:h.userId})});if(!I.ok)throw new Error("Failed to create matrix room");if(E=(await I.json()).roomId,!E)throw new Error("Failed to create user matrix room")}let ne=await j.room.v1beta1.listJoinedMembers(E).catch(()=>{}),oe=!!ne?.joined?.[h.userId];if(!oe){if(!(await j.room.v1beta1.join(E)).room_id)throw new Error("Failed to join matrix room");if(ne=await j.room.v1beta1.listJoinedMembers(E),oe=!!ne?.joined?.[h.userId],!oe)throw new Error("Failed to join matrix room")}console.log("\u2705 Matrix room created/joined:",E);let ct=De(p,r),Ce=await fetch(`${f}/_matrix/client/r0/rooms/${E}/state/ixo.room.state.secure/encrypted_mnemonic`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${h.accessToken}`},body:JSON.stringify({encrypted_mnemonic:ct})});if(!Ce.ok)throw new Error("Failed to store encrypted mnemonic in matrix room");return await Ce.json(),console.log("\u2705 Encrypted Matrix mnemonic stored in room"),await Xe({mxClient:O,baseUrl:f,accessToken:h.accessToken,userId:h.userId,deviceId:h.deviceId}),{address:a,did:l,mnemonic:o,matrixUserId:h.userId,matrixRoomId:E,matrixMnemonic:p,matrixPassword:x,matrixAccessToken:h.accessToken,matrixRecoveryPhrase:C,pin:r,matrixDeviceName:He}}catch(o){throw console.error("Simplified registration failed:",o),o}}import{createMatrixApiClient as Xt,utils as $t}from"@ixo/matrixclient-sdk";import{CID as jt}from"multiformats";import{base64 as Ft}from"multiformats/bases/base64";import*as ze from"multiformats/hashes/sha2";async function Je(r){let e=r.startsWith("m")?r:"m"+r,t=Ft.decode(e),i=await ze.sha256.digest(t);return jt.create(1,85,i).toString()}function Qe(r){let e=new TextEncoder().encode(r);return btoa(String.fromCharCode(...Array.from(e)))}var W=async({data:r,fileName:e,config:t,wallet:i})=>{let n=Xt({homeServerUrl:v[t.getValue("network")??"devnet"],accessToken:i?.matrix?.accessToken??""}),o=JSON.stringify(r),s=Buffer.from(o,"utf8"),a=e+".json",c=await n.media.v1beta1.upload(a,"application/ld+json",s),p=$t.mxc.mxcUrlToHttp(v[t.getValue("network")??"devnet"],c.content_uri);if(!p)throw new Error("Failed to upload file to Matrix");let f=JSON.stringify(r),A=Qe(f),x=await Je(A);return{encrypted:"false",cid:x,proof:x,serviceEndpoint:p,mxc:c.content_uri}};var G=class{constructor(e,t){this.config=t;if(!e.did||!e.pubKey||!e.address||!e.algo)throw new Error("Wallet not found");this.wallet=e,this.MsgCreateEntityParams.value.verification=[...Ye.iid.createIidVerificationMethods({did:e.did,pubkey:new Uint8Array(Buffer.from(e.pubKey)),address:e.address,controller:e.did,type:e.algo==="ed25519"?"ed":"secp"})],this.MsgCreateEntityParams.value.context=[],this.MsgCreateEntityParams.value.controller=[e.did],this.MsgCreateEntityParams.value.ownerAddress=e.address,this.MsgCreateEntityParams.value.ownerDid=e.did,this.MsgCreateEntityParams.value.service.push(R.iid.v1beta1.Service.fromPartial({id:"{id}#matrix",type:"Matrix",serviceEndpoint:"devmx.ixo.earth"})),this.MsgCreateEntityParams.value.relayerNode=ve[this.config.getValue("network")??"devnet"]}wallet;MsgCreateEntityParams={typeUrl:"/ixo.entity.v1beta1.MsgCreateEntity",value:R.entity.v1beta1.MsgCreateEntity.fromPartial({entityType:"oracle",context:[],entityStatus:0,verification:[],controller:[],ownerAddress:"",ownerDid:"",relayerNode:"",service:[],linkedResource:[],accordedRight:[],linkedEntity:[],linkedClaim:[],startDate:ue.proto.toTimestamp(new Date),endDate:ue.proto.toTimestamp(new Date(Date.now()+100*365*24*60*60*1e3))})};addLinkedAccounts({oracleAccountAddress:e}){if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client or wallet not found");let n=[{devnet:"did:ixo:ixo17w9u5uk4qjyjgeyqfpnp92jwy58faey9vvp3ar",testnet:"did:ixo:ixo14vjrckltpngugp03tcasfgh5qakey9n3sgm6y2",mainnet:"did:ixo:ixo1d39eutxdc0e8mnp0fmzqjdy6aaf26s9hzrk33r"}[this.config.getValue("network")],`did:ixo:${e}`].map(o=>R.iid.v1beta1.LinkedEntity.fromPartial({id:o,type:"agent",relationship:"admin",service:"matrix"}));this.MsgCreateEntityParams.value.linkedEntity=n}async createAuthZConfig({oracleAccountAddress:e,oracleName:t,entityDid:i}){let o=await W({data:{"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":i,"@type":"@id"}}],"@type":"Service","@id":"oracle:OracleAuthorization",name:"OracleAuthorization",description:"OracleAuthorization",serviceType:"OracleClaimAuthorizationService",requiredPermissions:["/ixo.claims.v1beta1.MsgCreateClaimAuthorization"],granteeAddress:e,granterAddress:"",oracleName:t},fileName:"authz",config:this.config,wallet:this.wallet});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#orz",type:"oracleAuthZConfig",proof:o.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Orale AuthZ Config",serviceEndpoint:o.serviceEndpoint})}async createFeesConfig({entityDid:e,price:t}){let n=await W({data:{"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":e,"@type":"@id"}}],"@type":"Service","@id":"oracle:ServiceFeeModel",name:"Pricing",description:"Pricing",serviceType:"",offers:{"@type":"Offer",priceCurrency:"uixo",priceSpecification:{"@type":"PaymentChargeSpecification",priceCurrency:"uixo",price:t,unitCode:"MON",billingIncrement:1,billingPeriod:"P1M",priceType:"Subscription",maxPrice:t},eligibleQuantity:{"@type":"QuantitativeValue",value:1,unitCode:"MON"}}},fileName:"fees",config:this.config,wallet:this.wallet});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#fee",type:"pricingList",proof:n.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Pricing List",serviceEndpoint:n.serviceEndpoint})}async createOracleConfigFiles({oracleName:e,entityDid:t,price:i,oracleAccountAddress:n}){let o=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!o)throw new Error("SignX client or wallet not found");let a=(await Promise.all([this.createAuthZConfig({oracleName:e,entityDid:t,oracleAccountAddress:n}),this.createFeesConfig({entityDid:t,price:i})])).map(p=>({typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:R.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:t,linkedResource:R.iid.v1beta1.LinkedResource.fromPartial({id:p.id,description:p.description,type:p.type,proof:p.proof,mediaType:p.mediaType,encrypted:p.encrypted,serviceEndpoint:p.serviceEndpoint}),signer:o})}));y.info("Sign to edit the entity and add the config files");let l=await this.wallet.signXClient.transact(a,this.wallet.wallet);return this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(l)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction()}async addPage({content:e,title:t}){let n=await W({data:{title:t,blocks:[{id:"title-block",type:"heading",props:{textColor:"default",backgroundColor:"default",textAlignment:"left"},content:[{type:"text",text:t,styles:{}}]},{id:"content-block",type:"paragraph",props:{textColor:"default",backgroundColor:"default",textAlignment:"left"},content:[{type:"text",text:e,styles:{}}]}]},fileName:"page",config:this.config,wallet:this.wallet}),o={id:"{id}#pag",type:"Settings",description:"Page",mediaType:"application/json",serviceEndpoint:n.serviceEndpoint,proof:n.proof,encrypted:"false",right:""};this.MsgCreateEntityParams.value.linkedResource.push(R.iid.v1beta1.LinkedResource.fromPartial(o))}async addProfile({orgName:e,name:t,logo:i,coverImage:n,location:o,description:s}){let l=await W({data:{"@context":{ixo:"https://w3id.org/ixo/ns/protocol/","@id":"@type",type:"@type","@protected":!1},id:"ixo:entity#profile",type:"profile",orgName:e,name:t,image:n,logo:i,brand:e,location:o,description:s},fileName:"profile",config:this.config,wallet:this.wallet}),c={id:"{id}#pro",type:"Settings",description:"Profile",mediaType:"application/json",serviceEndpoint:l.serviceEndpoint,proof:l.proof,encrypted:"false",right:""};this.MsgCreateEntityParams.value.linkedResource.push(R.iid.v1beta1.LinkedResource.fromPartial(c))}async addServices(e){this.MsgCreateEntityParams.value.service.push(...e.map(t=>R.iid.v1beta1.Service.fromPartial(t)))}async setParentProtocol(e){this.MsgCreateEntityParams.value.context.push(...Ye.iid.createAgentIidContext([{key:"class",val:e}]))}returnExecutableMsg(){return this.MsgCreateEntityParams}async execute(e){y.info("Adding page"),await this.addPage(e.page),y.info("Adding profile"),await this.addProfile(e.profile),y.info("Adding services"),await this.addServices(e.services),y.info("Adding parent protocol"),await this.setParentProtocol(e.parentProtocol);let t=this.returnExecutableMsg();if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client not found");y.info("Creating Oracle Wallet and Matrix Account");let i=await qt({message:"Enter a PIN to secure your Matrix Vault:",initialValue:"",defaultValue:"",validate(c){return w(c,"PIN is required")}});Bt(i)&&(y.error("User cancelled"),process.exit(1));let n=await q({pin:i,oracleName:e.oracleConfig.oracleName,network:this.config.getValue("network"),oracleAvatarUrl:e.profile.logo},async c=>{await this.wallet.sendTokens(c,25e4)});this.addLinkedAccounts({oracleAccountAddress:n.address}),y.info("Sign this transaction to create the entity");let o=await this.wallet.signXClient.transact([t],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(o)),await this.wallet.signXClient.pollNextTransaction();let s=await this.wallet.signXClient.awaitTransaction();y.success("Entity created -- wait to attach the required config files");let a=ue.common.getValueFromEvents(s,"wasm","token_id");await this.createOracleConfigFiles({oracleName:e.oracleConfig.oracleName,price:e.oracleConfig.price,oracleAccountAddress:n.address,entityDid:a}),y.success("Entity created -- config files attached");let l=Vt();l.start("Creating Entity Matrix Room..."),l.stop("Room created -- room joined"),y.warn("Please save the following information in a secure location as it is not stored:"),y.info("ORACLE ACCOUNT DETAILS");for(let c in n)y.info(`${c}: ${n[c]}`);return this.config.addValue("registerUserResult",n),this.config.addValue("entityDid",a),a}};var k=class{constructor(e,t){this.wallet=e;this.config=t;this.createEntity=new G(this.wallet,this.config)}name="create-entity";description="Create an entity";createEntity;async execute(){this.config.getValue("network")||await T(this.config);let t=await m.group({oracleName:()=>m.text({message:"What is the name of the oracle?",initialValue:"My oracle",validate(s){return w(s,"Oracle name is required")}}),oraclePrice:()=>m.text({message:"What is the price of the oracle in IXO CREDITS?",initialValue:"100",validate(s){return Ee(parseInt(s),"Oracle price is required and must be a number")}}),page:()=>m.group({title:()=>m.text({message:"What is the title of the oracle entity page?",initialValue:"AI Agent Oracle",validate(s){return w(s,"Title is required")}}),content:()=>m.text({message:"What is the content of the oracle entity page?",initialValue:"### Oracle built to help u with daily tasks",validate(s){return w(s,"Content is required")}})}),profile:()=>m.group({orgName:()=>m.text({message:"What is the name of the organization?",initialValue:"IXO",validate(s){return w(s,"Organization name is required")}}),name:()=>m.text({message:"What is the name of the profile?",initialValue:"My oracle",validate(s){return w(s,"Profile name is required")}}),logo:({results:s})=>m.text({message:"What is the logo of the profile?",initialValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${s?.name??"IXO"}`,defaultValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${s?.name??"IXO"}`,validate(a){return a?X(a,"Logo is required or a valid URL"):`https://api.dicebear.com/8.x/bottts/svg?seed=${s?.name??"IXO"}`}}),coverImage:({results:s})=>m.text({message:"What is the cover image of the profile?",initialValue:s.logo,defaultValue:s.logo,validate(a){return a?X(a,"Cover image is required or a valid URL"):s.logo}}),location:()=>m.text({message:"What is the location of your domain?",initialValue:"New York, NY",validate(s){return w(s,"Location is required")}}),description:()=>m.text({message:"What is the description of the entity (profile)?",initialValue:"We are a company that helps you with daily tasks",validate(s){return w(s,"Description is required")}})}),parentProtocol:()=>m.select({message:"What is the parent protocol of the entity?",options:[{value:"did:ixo:entity:1a76366f16570483cea72b111b27fd78",label:"IXO Oracle Protocol",hint:"default protocol"}],initialValue:"did:ixo:entity:1a76366f16570483cea72b111b27fd78"}),apiUrl:()=>m.text({message:"What is the API URL of the oracle?",initialValue:"http://localhost:4000",validate(s){return X(s,"API URL is required or a valid URL")}})},{onCancel:()=>{m.cancel("Operation cancelled."),process.exit(0)}}),i=await this.createEntity.execute({oracleConfig:{oracleName:t.oracleName,price:parseInt(t.oraclePrice)},page:t.page,profile:{orgName:t.profile.orgName,name:t.profile.name,logo:t.profile.logo,coverImage:t.profile.coverImage,location:t.profile.location,description:t.profile.description},services:[{id:"{id}#api",serviceEndpoint:t.apiUrl,type:"oracleService"},{id:"{id}#ws",serviceEndpoint:t.apiUrl,type:"wsService"}],parentProtocol:t.parentProtocol});m.log.info(`API for the oracle is: ${t.apiUrl} | You can change this after you deploy the oracle`);let o=`${Re[this.config.getValue("network")??"devnet"]}/oracle/${i}/overview`;return m.log.info(`Oracle created successfully: ${i}`),m.log.info(`Oracle URL: ${o}`),{success:!0,data:`Entity created successfully: ${i}`}}};import*as S from"@clack/prompts";var H=class{constructor(e,t){this.wallet=e;this.config=t}name="create-user";description="Create a new user";async execute(){let e=this.config.getValue("network");e||await T(this.config);let t=await S.text({message:"Enter your PIN",initialValue:"",validate(o){return w(o,"PIN is required")}});S.isCancel(t)&&(S.log.error("User cancelled"),process.exit(1));let i=await S.text({message:"Enter your oracle name",initialValue:"My oracle",validate(o){return w(o,"Oracle name is required")}});return S.isCancel(i)&&(S.log.error("User cancelled"),process.exit(1)),{success:!0,data:await q({pin:t,oracleName:i,network:e,oracleAvatarUrl:`https://api.dicebear.com/8.x/bottts/svg?seed=${i}`},async o=>{await this.wallet.sendTokens(o,15e4)})}}};var K=class{constructor(e){this.registry=e}name="help";description="Show help information and available commands";async execute(){return{success:!0,data:`
|
|
2
|
+
import{cancel as be,intro as wr,isCancel as gt,log as K,outro as yr,select as ut,spinner as xr}from"@clack/prompts";import O from"process";var B=class{commands;constructor(){this.commands=new Map}register(e){this.commands.set(e.name,e)}get(e){return this.commands.get(e)}getAll(){return Array.from(this.commands.values())}getCommandOptions(){return this.getAll().map(e=>({value:e.name,label:e.name,hint:e.description}))}};import*as u from"@clack/prompts";import{select as xt}from"@clack/prompts";import{z as k}from"zod";var I=async r=>{let e=await xt({message:"Select network: (default: devnet)",options:[{value:"mainnet",label:"Mainnet"},{value:"testnet",label:"Testnet"},{value:"devnet",label:"Devnet"}],initialValue:"devnet",maxItems:1});return r.addValue("network",e),e},Te={mainnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d",testnet:"did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb",devnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d"},V={devnet:"https://devmx.ixo.earth",testnet:"https://testmx.ixo.earth",mainnet:"https://mx.ixo.earth"};var Pe={devnet:"https://ixo-portal.vercel.app",testnet:"https://ixo-portal.vercel.app",mainnet:"https://ixo-portal.vercel.app"},$={mainnet:"https://impacthub.ixo.world/rpc/",testnet:"https://testnet.ixo.earth/rpc/",devnet:"https://devnet.ixo.earth/rpc/"},Ue={devnet:"https://domain-indexer.devnet.ixo.earth/index",testnet:"https://domain-indexer.testnet.ixo.earth/index",mainnet:"https://domain-indexer.ixo.earth/index"},T=(r,e="This field is required")=>{let i=k.string().min(1,e).safeParse(r);if(!i.success)return i.error.message},ge=r=>{let t=k.string().regex(/^did:ixo:entity:[a-f0-9]{32}$/,"Invalid entity DID").safeParse(r);if(!t.success)return t.error.message},q=(r,e="This url is required or a valid URL")=>{let i=k.url(e).safeParse(r);if(!i.success)return i.error.message},Oe=(r,e="This number is required")=>{let i=k.number().min(1,e).safeParse(r);if(!i.success)return i.error.message},H=r=>{let t=k.string().min(1,"PIN is required").refine(i=>/^\d{6}$/.test(i),"PIN must be exactly 6 digits").safeParse(r);if(!t.success)return t.error.issues[0]?.message??"Invalid PIN"},G=r=>{let t=k.string().min(1,"Matrix homeserver URL is required").refine(i=>/^https?:\/\//.test(i),"Must start with http:// or https://").refine(i=>!i.endsWith("/"),"Must not end with a trailing slash").safeParse(r);if(!t.success)return t.error.issues[0]?.message??"Invalid Matrix URL"};function ke(r){let e=new URL(r),t=e.hostname,i=e.protocol;return{homeServerUrl:r,roomBotUrl:`${i}//rooms.bot.${t}`,stateBotUrl:`${i}//state.bot.${t}`,bidsBotUrl:`${i}//bids.bot.${t}`,claimsBotUrl:`${i}//claims.bot.${t}`}}import{isCancel as tr,log as w,spinner as rr,text as ir}from"@clack/prompts";import{customMessages as st,ixo as R,utils as Ce}from"@ixo/impactxclient-sdk";import{sha256 as Lt}from"@cosmjs/crypto";import{encrypt as Mt}from"eciesjs";import{ClientEvent as Wt,createClient as we}from"matrix-js-sdk";import $t from"md5";var z=new Map;function vt(r){return z.get(r)instanceof Uint8Array}function Ct(r){return z.get(r)}function ue(){z.clear()}async function Ne({keys:r}){let e=Object.keys(r),t=e.find(vt);if(console.info("[] getSecretStorageKey",r,e,t),!t)return null;let i=Ct(t);return[t,i]}function De(r,e,t){z.set(r,t)}import{Bip39 as $e,EnglishMnemonic as _e,Secp256k1 as fe,sha256 as Et,Slip10 as Xe,Slip10Curve as je,stringToPath as Ke}from"@cosmjs/crypto";import{DirectSecp256k1HdWallet as bt}from"@cosmjs/proto-signing";import{createQueryClient as Fe,createSigningClient as At,customMessages as It,ixo as Tt,utils as Pt}from"@ixo/impactxclient-sdk";import{createCipheriv as Ut,randomBytes as Ot}from"crypto";import{createRegistry as Rt,utils as St}from"@ixo/impactxclient-sdk";function _(r){try{return St.proto.fromTimestamp(r).getTime()}catch{return}}var J={BasicAllowance:"/cosmos.feegrant.v1beta1.BasicAllowance",PeriodicAllowance:"/cosmos.feegrant.v1beta1.PeriodicAllowance"},Le=r=>{let e=Rt();return(r??[]).map(t=>{let i=t.allowance,n=e.decode(i);switch(i.typeUrl){case J.BasicAllowance:return{granter:t.granter,grantee:t.grantee,type:J.BasicAllowance,expiration:n.expiration?_(n.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};case J.PeriodicAllowance:return{granter:t.granter,grantee:t.grantee,type:J.PeriodicAllowance,expiration:n.basic?.expiration?_(n.basic.expiration):null,limit:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};default:return{type:i.typeUrl,granter:t.granter,grantee:t.grantee,expiration:n.expiration?_(n.expiration):n.basic?.expiration?_(n.basic.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:n.allowedMessages}}})},Me=r=>{if(r==null)return!1;let e=typeof r=="object"?_(r):r;return e==null?!0:e<Date.now()},We=r=>r==null?!1:(typeof r=="object"?Number(r?.amount??0):typeof r=="string"?Number(r??0):r)<=5e-4;async function he(r,e){if(!e)throw new Error("Network parameter is required but was undefined");console.log(`\u{1F50D} Checking IID document for DID: ${r} on network: ${e}`);let t=$[e];if(!t)throw new Error(`Invalid network: ${e}. Valid networks are: ${Object.keys($).join(", ")}`);console.log(`\u{1F517} Using RPC URL: ${t}`);try{return!!(await(await Fe(t)).ixo.iid.v1beta1.iidDocument({id:r}))?.iidDocument?.id}catch(i){if(i.message?.includes("did document not found")||i.message?.includes("(22)"))return!1;throw console.error("Error checking IID document:",i),i}}async function Be(r,e,t,i){try{let n=await t.getAccounts(),{address:o,pubkey:s}=n[0]??{},a=await kt(o,e),c=a?.length?Le(a)?.find(d=>!!d&&!Me(d.expiration)&&!We(d.limit))?.granter:void 0,l={typeUrl:"/ixo.iid.v1beta1.MsgCreateIidDocument",value:Tt.iid.v1beta1.MsgCreateIidDocument.fromPartial({id:r,verifications:It.iid.createIidVerificationMethods({did:r,pubkey:s,address:o,controller:r,type:"secp"}),signer:o,controllers:[r],...i?.length?{services:i}:{}})};await Nt({offlineSigner:t,messages:[l],feegrantGranter:c,network:e})}catch(n){throw console.error(n),n}}async function kt(r,e){try{let t=$[e];if(!t)throw new Error(`Invalid network: ${e}`);return(await(await Fe(t)).cosmos.feegrant.v1beta1.allowances({grantee:r}))?.allowances??[]}catch(t){console.error("queryAddressAllowances::",t.message);return}}var Nt=async({offlineSigner:r,messages:e,memo:t="Signing with Mnemonic Demo",feegrantGranter:i,network:n})=>{let o=$[n];if(!o)throw new Error(`Invalid network: ${n}`);let s=await At(o,r),a=await r.getAccounts(),{address:c}=a[0]??{},l=await s.simulate(c,e,t),m=(l>5e4?l:(e??[]).length*5e5)*1.7,g=Dt(m),v={amount:[{denom:"uixo",amount:String(Math.round(g.average))}],gas:String(Math.round(m)),granter:i},y=await s.signAndBroadcast(c,e,v,t,void 0);if(!!y.code)throw new Error(`Error when broadcasting tx ${y.transactionHash} at height ${y.height}. Code: ${y.code}; Raw log: ${y.rawLog}`)},Dt=r=>{let e={low:.02,average:.035,high:.045},t=r<.01?.01:r;return{low:t*e.low,average:t*e.average,high:t*e.high}},Q=r=>new Promise(e=>setTimeout(e,r));function Ve(r,e){let t=Ot(16),i=Ut("aes-256-cbc",Buffer.from(e.padEnd(32)),t),n=i.update(r);return n=Buffer.concat([n,i.final()]),t.toString("hex")+":"+n.toString("hex")}var qe=async r=>{let e=await bt.fromMnemonic(r,{prefix:"ixo"}),t=(await e.getAccounts())[0],i=await $e.mnemonicToSeed(new _e(r)),n=Ke("m/44'/118'/0'/0/0"),s=Xe.derivePath(je.Secp256k1,i,n).privkey,a=await fe.makeKeypair(s),c=fe.compressPubkey(a.pubkey);return{mnemonic:r,did:Pt.did.generateSecpDid(t.address),baseAccount:t,async getAccounts(){return await e.getAccounts()},async signDirect(d,m){return await e.signDirect(d,m)},async sign(d){try{let m=await $e.mnemonicToSeed(new _e(r)),g=Ke("m/44'/118'/0'/0/0"),{privkey:v}=Xe.derivePath(je.Secp256k1,m,g),y=new Uint8Array(Buffer.from(d,"base64")),A=Et(y);return(await fe.createSignature(A,v)).toFixedLength().slice(0,64)}catch(m){throw console.error("Error during signature creation:",m),m}}}};var _t="/.well-known/matrix/client",ye=async({homeServerUrl:r,username:e,password:t,deviceName:i},n=!1)=>{let o=r,s=e,a=s.match(/^@(.+):(.+\..+)$/);a&&(s=a[1],o=a[2],o=n?o:await qt(o));try{let c=ze(o),l=await c.login("m.login.password",{identifier:{type:"m.id.user",user:Ht(s)},password:t,initial_device_display_name:i});return{accessToken:l.access_token,deviceId:l.device_id,userId:l.user_id,baseUrl:n?o:l?.well_known?.["m.homeserver"]?.base_url||c.baseUrl}}catch(c){let l=c.message;throw l==="Unknown message"&&(l="Please check your credentials"),console.error("mxLogin::",l),new Error(l)}};async function Xt(r){let e=await fetch(`${r}/public-key`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error("Failed to fetch public key for encryption");return await e.json()}function jt(r){let e={timestamp:new Date().toISOString(),address:r,service:"matrix",type:"create-account"},t=Buffer.from(JSON.stringify(e)).toString("base64");return{challenge:e,challengeBase64:t}}function Kt(r,e){let t=new Uint8Array(Buffer.from(e,"hex")),i=new Uint8Array(Buffer.from(r,"utf8")),n=Mt(t,i);return Array.from(n,o=>o.toString(16).padStart(2,"0")).join("")}async function Ft(r,e,t,i,n,o){let s=await Xt(o),a=Kt(e,s.publicKey),c={address:r,encryptedPassword:a,publicKeyFingerprint:s.fingerprint,secpResult:{signature:t,challenge:i}},l=await fetch(`${o}/user/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let d=await l.text(),m=`Failed to create user account (HTTP ${l.status})`;try{let g=JSON.parse(d);m=g.error||g.message||g.detail||d}catch{m=d||m}throw console.error(`Room bot error [${l.status}]: ${d}`),new Error(m)}return await l.json()}async function He(r,e,t,i,n,o){try{let{challengeBase64:s}=jt(r),a=await i.sign(s),c=Buffer.from(a).toString("base64");if(!(await Ft(r,e,c,s,n,o)).success)throw new Error("Failed to create matrix account via API");let d=xe(r);return await ye({homeServerUrl:n,username:d,password:e,deviceName:t})}catch(s){throw console.error("mxRegisterWithSecp error:",s),s}}async function Ge({homeServerUrl:r,username:e}){let t=ze(r);try{return!!await t.isUsernameAvailable(e)}catch{return!1}}function ze(r){if(!r)throw new Error("Home server URL is required to instantiate matrix client");return we({baseUrl:r})}async function Je({homeServerUrl:r,accessToken:e,userId:t,deviceId:i}){if(console.log("createMatrixClient::",{homeServerUrl:r,accessToken:e,userId:t,deviceId:i}),!r||!e||!t||!i)throw new Error("Login to Matrix account before trying to instantiate Matrix client.");let n=we({baseUrl:r,accessToken:e,userId:t,deviceId:i,timelineSupport:!0,cryptoCallbacks:{getSecretStorageKey:Ne,cacheSecretStorageKey:De},verificationMethods:["m.sas.v1"]});return await n.initRustCrypto({useIndexedDB:!1}),n.setMaxListeners(20),await n.startClient({lazyLoadMembers:!0,includeArchivedRooms:!1}),await new Promise((o,s)=>{let a={NULL:()=>{console.info("[NULL] state")},SYNCING:()=>{},PREPARED:()=>{console.info(`[PREPARED] state: user ${t}`),o()},RECONNECTING:()=>{console.info("[RECONNECTING] state")},CATCHUP:()=>{console.info("[CATCHUP] state")},ERROR:()=>{s(new Error("[ERROR] state: starting matrix client"))},STOPPED:()=>{console.info("[STOPPED] state")}};n.on(Wt.Sync,c=>{a[c]()})}),n}async function Y({mxClient:r,baseUrl:e,accessToken:t,userId:i,deviceId:n}){let o=r;o||(o=we({baseUrl:e,accessToken:t,userId:i,deviceId:n})),o&&(o.stopClient(),await o.logout().catch(console.error),o.clearStores())}function Qe(r){let e=r.getAccountData("m.cross_signing.master");return console.log("hasCrossSigningAccountData::masterKeyData",e),!!e}async function Ye(r,{securityPhrase:e,password:t,forceReset:i=!1,skipBootstrapSecureStorage:n=!1}){i&&ue();let o=r.getCrypto();if(!o)throw new Error("Failed to setup matrix cross signing - failed to get matrix crypto api");if(!n){let a=await o.createRecoveryKeyFromPassphrase(e);ue(),await o.bootstrapSecretStorage({createSecretStorageKey:async()=>a,setupNewSecretStorage:i})}let s=r.getUserId();return await o.bootstrapCrossSigning({authUploadDeviceSigningKeys:async function(a){await a(Gt({userId:s,password:t}))},setupNewCrossSigning:i}),await o.resetKeyBackup(),await Q(300),!!r.getAccountData("m.cross_signing.master")}function xe(r){if(!r)throw new Error("Address is required to generate matrix username");return"did-ixo-"+r}function Ze(r){return Buffer.from($t(r.replace(/ /g,""))).toString("base64").slice(0,24)}function et(r){let e=Lt(new TextEncoder().encode(r.replace(/ /g,"")));return Buffer.from(e).toString("base64").slice(0,32)}function Bt(r){return r.replace(/^(https?:\/\/)/,"").replace(/\/$/,"")}function Vt(r,e=""){return"did-ixo-"+r+e}function tt(r,e){return"#"+Vt(r)+":"+Bt(e)}async function qt(r){let e="https://";/^https?:\/\//.test(r)&&(e="");let t=`${e}${r}${_t}`;try{let o=(await(await fetch(t,{method:"GET"})).json())["m.homeserver"]?.base_url;if(o===void 0)throw new Error;return o}catch{return`${e}${r}`}}function Ht(r){return(r.indexOf("@")===0?r.substring(1):r).trim()}function Gt({userId:r,password:e}){return{type:"m.login.password",password:e,identifier:{type:"m.id.user",user:r}}}import{ixo as zt,utils as ve}from"@ixo/impactxclient-sdk";import{createMatrixApiClient as Jt}from"@ixo/matrixclient-sdk";var rt="Oracles CLI";async function Z({pin:r,oracleName:e,network:t,oracleAvatarUrl:i,matrixHomeServerUrl:n},o){try{let{homeServerUrl:s,roomBotUrl:a}=ke(n),c=ve.mnemonic.generateMnemonic(),l=await qe(c),d=l.baseAccount.address;console.log("\u2705 Wallet created:",d),await o(d);let m=ve.did.generateSecpDid(d),g=await he(m,t);if(console.log("\u2705 DID exists:",g),!g){console.log("\u2705 DID does not exist, creating...");let P=zt.iid.v1beta1.Service.fromPartial({id:`${m}#matrix`,type:"MatrixHomeServer",serviceEndpoint:s});if(await Be(m,t,l,[P]),console.log("\u2705 DID created, waiting 500ms..."),await Q(500),console.log("\u2705 Checking if DID exists..."),!await he(m,t))throw new Error("Failed to create DID document")}console.log("\u2705 DID created:",m);let v=ve.mnemonic.generateMnemonic(12),y=xe(d),A=Ze(v),le=et(v);if(!await Ge({homeServerUrl:s,username:y}))throw new Error("Matrix account already exists");let C=await He(d,A,rt,l,s,a);if(!C?.accessToken)throw new Error("Failed to register matrix account");console.log("\u2705 Matrix account created:",C.userId);let W=await Je({homeServerUrl:s,accessToken:C.accessToken,userId:C.userId,deviceId:C.deviceId});try{await Promise.all([W.setDisplayName(e),W.setAvatarUrl(i)])}catch(P){console.error("Failed to set display name or avatar url:",P)}let F=Jt({homeServerUrl:s,accessToken:C.accessToken}),de=Qe(W);if(!de&&(de=await Ye(W,{securityPhrase:le,password:A,forceReset:!0}),!de))throw new Error("Failed to setup cross signing");console.log("\u2705 Matrix cross-signing setup completed");let ht=tt(d,C.baseUrl),E=(await F.room.v1beta1.queryId(ht).catch(()=>{}))?.room_id??"";if(!E){let P=await fetch(`${a}/room/source`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:m,userMatrixId:C.userId})});if(!P.ok)throw new Error("Failed to create matrix room");if(E=(await P.json()).roomId,!E)throw new Error("Failed to create user matrix room")}let me=await F.room.v1beta1.listJoinedMembers(E).catch(()=>{}),pe=!!me?.joined?.[C.userId];if(!pe){if(!(await F.room.v1beta1.join(E)).room_id)throw new Error("Failed to join matrix room");if(me=await F.room.v1beta1.listJoinedMembers(E),pe=!!me?.joined?.[C.userId],!pe)throw new Error("Failed to join matrix room")}console.log("\u2705 Matrix room created/joined:",E);let wt=Ve(v,r),Ie=await fetch(`${s}/_matrix/client/v3/rooms/${E}/state/ixo.room.state.secure/encrypted_mnemonic`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${C.accessToken}`},body:JSON.stringify({encrypted_mnemonic:wt})});if(!Ie.ok)throw new Error("Failed to store encrypted mnemonic in matrix room");return await Ie.json(),console.log("\u2705 Encrypted Matrix mnemonic stored in room"),W.stopClient(),{address:d,did:m,mnemonic:c,matrixUserId:C.userId,matrixRoomId:E,matrixMnemonic:v,matrixPassword:A,matrixAccessToken:C.accessToken,matrixRecoveryPhrase:le,matrixHomeServerUrl:s,pin:r,matrixDeviceName:rt}}catch(s){throw console.error("Simplified registration failed:",s),s}}import{createMatrixApiClient as Zt,utils as er}from"@ixo/matrixclient-sdk";import{CID as Qt}from"multiformats";import{base64 as Yt}from"multiformats/bases/base64";import*as it from"multiformats/hashes/sha2";async function nt(r){let e=r.startsWith("m")?r:"m"+r,t=Yt.decode(e),i=await it.sha256.digest(t);return Qt.create(1,85,i).toString()}function ot(r){let e=new TextEncoder().encode(r);return btoa(String.fromCharCode(...Array.from(e)))}var X=async({data:r,fileName:e,homeServerUrl:t,accessToken:i})=>{let n=Zt({homeServerUrl:t,accessToken:i}),o=JSON.stringify(r),s=Buffer.from(o,"utf8"),a=e+".json",l=await n.media.v1beta1.upload(a,"application/ld+json",s),d=er.mxc.mxcUrlToHttp(t,l.content_uri);if(!d)throw new Error("Failed to upload file to Matrix");let m=JSON.stringify(r),g=ot(m),v=await nt(g);return{encrypted:"false",cid:v,proof:v,serviceEndpoint:d,mxc:l.content_uri}};var N=class{constructor(e,t){this.config=t;if(!e.did||!e.pubKey||!e.address||!e.algo)throw new Error("Wallet not found");this.wallet=e}wallet;buildMsgCreateEntity(e){return{typeUrl:"/ixo.entity.v1beta1.MsgCreateEntity",value:R.entity.v1beta1.MsgCreateEntity.fromPartial({entityType:"oracle",context:[],entityStatus:0,verification:[...st.iid.createIidVerificationMethods({did:this.wallet.did,pubkey:new Uint8Array(Buffer.from(this.wallet.pubKey)),address:this.wallet.address,controller:this.wallet.did,type:this.wallet.algo==="ed25519"?"ed":"secp"})],controller:[this.wallet.did],ownerAddress:this.wallet.address,ownerDid:this.wallet.did,relayerNode:Te[this.config.getValue("network")??"devnet"],service:[R.iid.v1beta1.Service.fromPartial({id:"{id}#matrix",type:"MatrixHomeServer",serviceEndpoint:e})],linkedResource:[],accordedRight:[],linkedEntity:[],linkedClaim:[],startDate:Ce.proto.toTimestamp(new Date),endDate:Ce.proto.toTimestamp(new Date(Date.now()+31536e8))})}}addLinkedAccounts(e,{oracleAccountAddress:t}){if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client or wallet not found");let o=[{devnet:"did:ixo:ixo17w9u5uk4qjyjgeyqfpnp92jwy58faey9vvp3ar",testnet:"did:ixo:ixo14vjrckltpngugp03tcasfgh5qakey9n3sgm6y2",mainnet:"did:ixo:ixo1d39eutxdc0e8mnp0fmzqjdy6aaf26s9hzrk33r"}[this.config.getValue("network")],`did:ixo:${t}`].map(s=>R.iid.v1beta1.LinkedEntity.fromPartial({id:s,type:"agent",relationship:"admin",service:"matrix"}));e.value.linkedEntity=o}async createAuthZConfig({oracleAccountAddress:e,oracleName:t,entityDid:i,homeServerUrl:n,accessToken:o}){let a=await X({data:{"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":i,"@type":"@id"}}],"@type":"Service","@id":"oracle:OracleAuthorization",name:"OracleAuthorization",description:"OracleAuthorization",serviceType:"OracleClaimAuthorizationService",requiredPermissions:["/ixo.claims.v1beta1.MsgCreateClaimAuthorization"],granteeAddress:e,granterAddress:"",oracleName:t},fileName:"authz",homeServerUrl:n,accessToken:o});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#orz",type:"oracleAuthZConfig",proof:a.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Orale AuthZ Config",serviceEndpoint:a.serviceEndpoint})}async createFeesConfig({entityDid:e,price:t,denom:i,homeServerUrl:n,accessToken:o}){let s={"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":e,"@type":"@id"}}],"@type":"Service","@id":"oracle:ServiceFeeModel",name:"Pricing",description:"Pricing",serviceType:"",offers:{"@type":"Offer",priceCurrency:i,priceSpecification:{"@type":"PaymentChargeSpecification",priceCurrency:i,price:t*1e3,unitCode:"MON",billingIncrement:1,billingPeriod:"P1M",priceType:"Subscription",maxPrice:t},eligibleQuantity:{"@type":"QuantitativeValue",value:1,unitCode:"MON"}}},a=await X({data:s,fileName:"fees",homeServerUrl:n,accessToken:o});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#fee",type:"pricingList",proof:a.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Pricing List",serviceEndpoint:a.serviceEndpoint})}async addControllerToEntity(e,t){let i=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!i)throw new Error("SignX client or wallet not found");let n={typeUrl:"/ixo.iid.v1beta1.MsgAddController",value:R.iid.v1beta1.MsgAddController.fromPartial({id:e,controllerDid:t,signer:i})};w.info(`Sign to add controller ${t} to entity ${e}`);let o=await this.wallet.signXClient.transact([n],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(o)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),w.success(`Controller ${t} added to entity ${e}`)}async createOracleConfigFiles({oracleName:e,entityDid:t,price:i,oracleAccountAddress:n,homeServerUrl:o,accessToken:s}){let a=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!a)throw new Error("SignX client or wallet not found");let l=(await Promise.all([this.createAuthZConfig({oracleName:e,entityDid:t,oracleAccountAddress:n,homeServerUrl:o,accessToken:s}),this.createFeesConfig({entityDid:t,price:i,denom:this.config.getValue("network")==="devnet"?"uixo":"ibc/6BBE9BD4246F8E04948D5A4EEE7164B2630263B9EBB5E7DC5F0A46C62A2FF97B",homeServerUrl:o,accessToken:s})])).map(g=>({typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:R.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:t,linkedResource:R.iid.v1beta1.LinkedResource.fromPartial({id:g.id,description:g.description,type:g.type,proof:g.proof,mediaType:g.mediaType,encrypted:g.encrypted,serviceEndpoint:g.serviceEndpoint}),signer:a})}));w.info("Sign to edit the entity and add the config files");let d=await this.wallet.signXClient.transact(l,this.wallet.wallet);return this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(d)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction()}async createDomainCard({profile:e,entityDid:t,homeServerUrl:i,accessToken:n}){let o=new Date().toISOString(),s={"@context":["https://www.w3.org/ns/credentials/v2","https://w3id.org/ixo/context/v1",{schema:"https://schema.org/",ixo:"https://w3id.org/ixo/vocab/v1",prov:"http://www.w3.org/ns/prov#",proj:"https://linked.data.gov.au/def/project#",xsd:"http://www.w3.org/2001/XMLSchema#",id:"@id",type:"@type","ixo:vector":{"@container":"@list","@type":"xsd:double"},"@protected":!0}],id:`${t}#dmn`,type:["VerifiableCredential","ixo:DomainCard"],issuer:{id:this.wallet.did},validFrom:o,credentialSchema:{id:"https://github.com/ixoworld/domainCards/schemas/ixo-domain-card-1.json",type:"JsonSchema"},credentialSubject:{id:t,type:["ixo:oracle"],additionalType:["schema:Organization"],name:e.name,alternateName:e.orgName!==e.name?[e.orgName]:void 0,description:e.description,logo:{type:"schema:ImageObject",id:e.logo,contentUrl:e.logo},image:[{type:"schema:ImageObject",id:e.coverImage,contentUrl:e.coverImage}],address:{type:"schema:PostalAddress",addressLocality:e.location},...e.url?{url:e.url}:{}}},a=await X({data:s,fileName:"domainCard",homeServerUrl:i,accessToken:n});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#dmn",type:"domainCard",proof:a.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Domain Card",serviceEndpoint:a.serviceEndpoint})}async addProfile({orgName:e,name:t,logo:i,coverImage:n,location:o,description:s,homeServerUrl:a,accessToken:c}){let d=await X({data:{"@context":{ixo:"https://w3id.org/ixo/ns/protocol/","@id":"@type",type:"@type","@protected":!1},id:"ixo:entity#profile",type:"profile",orgName:e,name:t,image:n,logo:i,brand:e,location:o,description:s},fileName:"profile",homeServerUrl:a,accessToken:c});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#pro",type:"Settings",description:"Profile",mediaType:"application/json",serviceEndpoint:d.serviceEndpoint,proof:d.proof,encrypted:"false",right:""})}addServices(e,t){e.value.service.push(...t.map(i=>R.iid.v1beta1.Service.fromPartial(i)))}setParentProtocol(e,t){e.value.context.push(...st.iid.createAgentIidContext([{key:"class",val:t}]))}async submitToDomainIndexer(e){let t=this.config.getValue("network")??"devnet",i=Ue[t];try{let n=await fetch(i,{method:"POST",headers:{accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({did:e})});if(!n.ok){let o=await n.text();w.warn(`Failed to submit to domain indexer: ${n.status} ${o}`);return}w.success("Domain card submitted to domain indexer")}catch(n){w.warn(`Error submitting to domain indexer: ${n instanceof Error?n.message:String(n)}`)}}async execute(e){if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client not found");let{matrixHomeServerUrl:t}=e;w.info("Creating Oracle Wallet and Matrix Account");let i=await ir({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(y){return H(y)}});tr(i)&&(w.error("User cancelled"),process.exit(1));let n=await Z({pin:i,oracleName:e.oracleConfig.oracleName,network:this.config.getValue("network"),oracleAvatarUrl:e.profile.logo,matrixHomeServerUrl:t},async y=>{await this.wallet.sendTokens(y,25e4)}),o=n.matrixHomeServerUrl,s=n.matrixAccessToken;w.info("Adding profile");let a=await this.addProfile({...e.profile,homeServerUrl:o,accessToken:s}),c=this.buildMsgCreateEntity(t);c.value.linkedResource.push(a),w.info("Adding services"),this.addServices(c,e.services),w.info("Adding parent protocol"),this.setParentProtocol(c,e.parentProtocol),this.addLinkedAccounts(c,{oracleAccountAddress:n.address}),w.info("Sign this transaction to create the entity");let l=await this.wallet.signXClient.transact([c],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(l)),await this.wallet.signXClient.pollNextTransaction();let d=await this.wallet.signXClient.awaitTransaction();w.success("Entity created -- wait to attach the required config files");let m=Ce.common.getValueFromEvents(d,"wasm","token_id");w.info("Creating domain card");let g=await this.createDomainCard({profile:e.profile,entityDid:m,homeServerUrl:o,accessToken:s});if(this.wallet.wallet?.address){let y={typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:R.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:m,linkedResource:R.iid.v1beta1.LinkedResource.fromPartial({id:g.id,description:g.description,type:g.type,proof:g.proof,mediaType:g.mediaType,encrypted:g.encrypted,serviceEndpoint:g.serviceEndpoint}),signer:this.wallet.wallet.address})};w.info("Sign to add domain card to the entity");let A=await this.wallet.signXClient.transact([y],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(A)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),w.success("Domain card added to entity")}await this.createOracleConfigFiles({oracleName:e.oracleConfig.oracleName,price:e.oracleConfig.price,oracleAccountAddress:n.address,entityDid:m,homeServerUrl:o,accessToken:s}),w.success("Entity created -- config files attached"),await Y({baseUrl:o,accessToken:s,userId:n.matrixUserId,deviceId:""});let v=rr();v.start("Creating Entity Matrix Room..."),v.stop("Room created -- room joined"),w.warn("Please save the following information in a secure location as it is not stored:"),w.info("ORACLE ACCOUNT DETAILS");for(let y in n)w.info(`${y}: ${n[y]}`);return this.config.addValue("registerUserResult",n),this.config.addValue("entityDid",m),this.config.addValue("oracleMatrixHomeServerUrl",t),w.info("Submitting domain card to domain indexer"),await this.submitToDomainIndexer(m),m}};var D=class{constructor(e,t){this.wallet=e;this.config=t}name="create-entity";description="Create an entity";async execute(){this.config.getValue("network")||await I(this.config);let t=this.wallet.matrixHomeServer??V[this.config.getValue("network")??"devnet"],i=await u.group({matrixHomeServerUrl:()=>u.text({message:"Matrix homeserver URL for the oracle:",initialValue:t,defaultValue:t,validate(c){return G(c)}}),oracleName:()=>u.text({message:"What is the name of the oracle?",initialValue:"My oracle",validate(c){return T(c,"Oracle name is required")}}),oraclePrice:()=>u.text({message:"What is the price of the oracle in IXO CREDITS?",initialValue:"100",validate(c){return Oe(parseInt(c??""),"Oracle price is required and must be a number")}}),profile:()=>u.group({orgName:()=>u.text({message:"What is the name of the organization?",initialValue:"IXO",validate(c){return T(c,"Organization name is required")}}),name:()=>u.text({message:"What is the name of the profile?",initialValue:"My oracle",validate(c){return T(c,"Profile name is required")}}),logo:({results:c})=>u.text({message:"What is the logo of the profile?",initialValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`,defaultValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`,validate(l){return l?q(l,"Logo is required or a valid URL"):`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`}}),coverImage:({results:c})=>u.text({message:"What is the cover image of the profile?",initialValue:c.logo,defaultValue:c.logo,validate(l){return l?q(l,"Cover image is required or a valid URL"):c.logo}}),location:()=>u.text({message:"What is the location of your domain?",initialValue:"New York, NY",validate(c){return T(c,"Location is required")}}),description:()=>u.text({message:"What is the description of the entity (profile)?",initialValue:"We are a company that helps you with daily tasks",validate(c){return T(c,"Description is required")}}),url:()=>u.text({message:"What is the website URL of the oracle? (optional, press Enter to skip)",placeholder:"https://your-oracle-website.com"})}),parentProtocol:()=>u.select({message:"What is the parent protocol of the entity?",options:[{value:"did:ixo:entity:1a76366f16570483cea72b111b27fd78",label:"IXO Oracle Protocol",hint:"default protocol"}],initialValue:"did:ixo:entity:1a76366f16570483cea72b111b27fd78"}),apiUrl:()=>u.text({message:"What is the API URL of the oracle?",initialValue:"http://localhost:4000",validate(c){return q(c,"API URL is required or a valid URL")}})},{onCancel:()=>{u.cancel("Operation cancelled."),process.exit(0)}}),o=await new N(this.wallet,this.config).execute({oracleConfig:{oracleName:i.oracleName,price:parseInt(i.oraclePrice)},profile:{orgName:i.profile.orgName,name:i.profile.name,logo:i.profile.logo,coverImage:i.profile.coverImage,location:i.profile.location,description:i.profile.description,...i.profile.url?{url:i.profile.url}:{}},services:[{id:"{id}#api",serviceEndpoint:i.apiUrl,type:"oracleService"},{id:"{id}#ws",serviceEndpoint:i.apiUrl,type:"wsService"}],parentProtocol:i.parentProtocol,matrixHomeServerUrl:i.matrixHomeServerUrl});u.log.info(`API for the oracle is: ${i.apiUrl} | You can change this after you deploy the oracle`);let a=`${Pe[this.config.getValue("network")??"devnet"]}/oracle/${o}/overview`;return u.log.info(`Oracle created successfully: ${o}`),u.log.info(`Oracle URL: ${a}`),{success:!0,data:`Entity created successfully: ${o}`}}};import*as S from"@clack/prompts";var ee=class{constructor(e,t){this.wallet=e;this.config=t}name="create-user";description="Create a new user";async execute(){let e=this.config.getValue("network");e||await I(this.config);let t=this.wallet.matrixHomeServer??V[this.config.getValue("network")??"devnet"],i=await S.text({message:"Matrix homeserver URL:",initialValue:t,defaultValue:t,validate(a){return G(a)}});S.isCancel(i)&&(S.log.error("User cancelled"),process.exit(1));let n=await S.text({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(a){return H(a)}});S.isCancel(n)&&(S.log.error("User cancelled"),process.exit(1));let o=await S.text({message:"Enter your oracle name",initialValue:"My oracle",validate(a){return T(a,"Oracle name is required")}});S.isCancel(o)&&(S.log.error("User cancelled"),process.exit(1));let s=await Z({pin:n,oracleName:o,network:this.config.getValue("network")??e,oracleAvatarUrl:`https://api.dicebear.com/8.x/bottts/svg?seed=${o}`,matrixHomeServerUrl:i},async a=>{await this.wallet.sendTokens(a,15e4)});return await Y({baseUrl:s.matrixHomeServerUrl,accessToken:s.matrixAccessToken,userId:s.matrixUserId,deviceId:""}),{success:!0,data:s}}};var j=class{constructor(e){this.registry=e}name="help";description="Show help information and available commands";async execute(){return{success:!0,data:`
|
|
3
3
|
IXO Oracles CLI - Help
|
|
4
4
|
|
|
5
5
|
USAGE:
|
|
@@ -19,13 +19,13 @@ OPTIONS:
|
|
|
19
19
|
--help, -h Show help information
|
|
20
20
|
|
|
21
21
|
For more information, visit: https://github.com/ixoworld/ixo-oracles-cli
|
|
22
|
-
`}}};import*as
|
|
23
|
-
PORT=4000
|
|
22
|
+
`}}};import*as p from"@clack/prompts";import{existsSync as te}from"fs";import L from"path";import lt from"simple-git";import Re from"fs";import at from"path";var ct=async r=>{let e=r.getOrThrow("oracleMatrixHomeServerUrl"),t=await ye({homeServerUrl:e,username:r.getOrThrow("registerUserResult").matrixUserId,password:r.getOrThrow("registerUserResult").matrixPassword,deviceName:r.getOrThrow("registerUserResult").matrixDeviceName}),i=r.getOrThrow("projectPath"),n=at.join(i,"apps","app",".env");console.log("Creating .env file at:",n),console.log("Project path:",i);let o=at.dirname(n);Re.existsSync(o)||(console.log("Creating directory:",o),Re.mkdirSync(o,{recursive:!0}));let s=`
|
|
23
|
+
PORT=4000
|
|
24
24
|
ORACLE_NAME=${r.getValue("projectName")}
|
|
25
25
|
|
|
26
26
|
# Matrix
|
|
27
|
-
MATRIX_BASE_URL=${
|
|
28
|
-
MATRIX_ORACLE_ADMIN_ACCESS_TOKEN=${
|
|
27
|
+
MATRIX_BASE_URL=${e}
|
|
28
|
+
MATRIX_ORACLE_ADMIN_ACCESS_TOKEN=${t.accessToken}
|
|
29
29
|
MATRIX_ORACLE_ADMIN_PASSWORD=${r.getOrThrow("registerUserResult").matrixPassword}
|
|
30
30
|
MATRIX_ORACLE_ADMIN_USER_ID=${r.getOrThrow("registerUserResult").matrixUserId}
|
|
31
31
|
MATRIX_RECOVERY_PHRASE=${r.getOrThrow("registerUserResult").matrixRecoveryPhrase}
|
|
@@ -48,21 +48,21 @@ ORACLE_DID=${r.getOrThrow("registerUserResult").did}
|
|
|
48
48
|
ORACLE_MNEMONIC=${r.getOrThrow("registerUserResult").mnemonic}
|
|
49
49
|
MATRIX_VAULT_PIN=${r.getOrThrow("registerUserResult").pin}
|
|
50
50
|
ENTITY_DID=${r.getOrThrow("entityDid")}
|
|
51
|
-
`;try{
|
|
51
|
+
`;try{Re.writeFileSync(n,s),console.log("\u2705 .env file created successfully at:",n)}catch(a){throw console.error("\u274C Failed to create .env file:",a),a}};var re=class{constructor(e,t){this.config=e;this.wallet=t}name="init";description="Initialize Project";async getProjectInput(){let e=await p.text({message:"What is your project named?",placeholder:"my-ixo-project",validate(o){if(!o)return"Project name is required"}});p.isCancel(e)&&(p.cancel("Operation cancelled."),process.exit(0));let t=String(e),i,n;return t.includes("/")||t.includes("\\")?(i=t,n=L.basename(t)):(n=t,i=L.join(process.cwd(),n)),this.isValidProjectName(n)||(p.note("Invalid project name. Using a valid name instead.","Warning"),n=this.sanitizeProjectName(n),i=L.join(L.dirname(i),n)),{projectPath:i,projectName:n}}isValidProjectName(e){return/^[a-zA-Z][a-zA-Z0-9-_]*$/.test(e)&&e.length>0&&e.length<=50}sanitizeProjectName(e){return e.replace(/[^a-zA-Z0-9-_]/g,"-").replace(/^-+|-+$/g,"").toLowerCase().substring(0,50)}async confirmProjectCreation(e,t){if(te(e)){let o=await p.confirm({message:`Directory "${e}" already exists. Do you want to overwrite it?`,initialValue:!1});return p.isCancel(o)&&(p.cancel("Operation cancelled."),process.exit(0)),o}let n=await p.confirm({message:`Create IXO project "${t}" in "${e}"?`,initialValue:!0});return p.isCancel(n)&&(p.cancel("Operation cancelled."),process.exit(0)),n}async selectRepo(){let e=await p.select({message:"Select a template to clone",options:[{value:"git@github.com:ixoworld/ixo-oracles-boilerplate.git",label:"IXO Oracles (Default)"},{label:"Custom template",value:"custom"}]});if(p.isCancel(e)&&(p.cancel("Operation cancelled."),process.exit(0)),e==="custom"){let t=await p.text({message:"Enter the custom template URL"});return p.isCancel(t)&&(p.cancel("Operation cancelled."),process.exit(0)),t}return e}async cloneRepo(e,t,i=!1){let n=lt(),o=p.spinner();try{if(o.start("Cloning repository..."),i&&te(t)){let{rmSync:l}=await import("fs");l(t,{recursive:!0,force:!0})}await n.clone(e,t);let s=L.join(t,".git");if(te(s)){let{rmSync:l}=await import("fs");l(s,{recursive:!0,force:!0})}await lt(t).init(),o.stop("Repository cloned successfully"),p.log.info("Creating Oracle Entity and Matrix Account"),(await new D(this.wallet,this.config).execute()).success?p.log.info("Oracle Entity and Matrix Account created successfully"):p.log.error("Failed to create Oracle Entity and Matrix Account"),await ct(this.config),p.log.success(`
|
|
52
52
|
\u2705 IXO project created successfully!
|
|
53
53
|
|
|
54
54
|
\u{1F4C1} Location: ${t}
|
|
55
55
|
\u{1F680} Next steps:
|
|
56
|
-
cd ${
|
|
56
|
+
cd ${L.basename(t)}
|
|
57
57
|
pnpm install
|
|
58
58
|
pnpm build
|
|
59
59
|
cd apps/app
|
|
60
|
-
pnpm start:dev`)}catch(s){throw o.stop("Failed to clone repository"),s}}async execute(){try{let{projectPath:e,projectName:t}=await this.getProjectInput();if(!await this.confirmProjectCreation(e,t))return{success:!1,data:"Project creation cancelled"};this.config.addValue("projectPath",e),this.config.addValue("projectName",t);let n=await this.selectRepo();this.config.addValue("repo",n);let o=
|
|
61
|
-
`+" ".repeat(5)+"\u{1F510} "+t),console.log(" ".repeat(5)+"\u{1F4F1} Scan with IXO app"),console.log(" ".repeat(5)+"\u2501".repeat(30)),
|
|
62
|
-
`)}displayQRCode(e){this.displayStyledQRCode(e,"Login with SignX")}async awaitLogin(){return new Promise((e,t)=>{try{this.signXClient.on(
|
|
60
|
+
pnpm start:dev`)}catch(s){throw o.stop("Failed to clone repository"),s}}async execute(){try{let{projectPath:e,projectName:t}=await this.getProjectInput();if(!await this.confirmProjectCreation(e,t))return{success:!1,data:"Project creation cancelled"};this.config.addValue("projectPath",e),this.config.addValue("projectName",t);let n=await this.selectRepo();this.config.addValue("repo",n);let o=te(e);return await this.cloneRepo(n,e,o),{success:!0,data:`Project "${t}" created successfully in "${e}"`}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Unknown error occurred"}}}};import{confirm as nr}from"@clack/prompts";var ie=class{constructor(e){this.wallet=e}name="logout";description="Logout command";async execute(){return await nr({message:"Are you sure you want to logout?",initialValue:!1})?(await this.wallet.clearWallet(),{success:!0,data:"Logged out successfully"}):{success:!1,error:"Logout cancelled"}}};import{toHex as or}from"@cosmjs/encoding";import{createRegistry as sr}from"@ixo/impactxclient-sdk";import{SignX as dt,SIGN_X_LOGIN_ERROR as ar,SIGN_X_LOGIN_SUCCESS as cr,SIGN_X_TRANSACT_ERROR as lr,SIGN_X_TRANSACT_SUCCESS as dr}from"@ixo/signx-sdk";import mr from"qrcode-terminal";var mt={devnet:"https://signx.devnet.ixo.earth",testnet:"https://signx.testnet.ixo.earth",mainnet:"https://signx.ixo.earth"},M=class{signXClient;_loginData;get loginData(){return this._loginData}static loadFromWallet(e){return new dt({endpoint:mt[e.network],sitename:"IXO Oracles CLI",network:e.network})}constructor(e){this.signXClient=new dt({endpoint:mt[e],sitename:"IXO Oracles CLI",network:e})}async login(){let e=await this.signXClient.login({pollingInterval:2e3,matrix:!0});return this._loginData=e,e}displayStyledQRCode(e,t){let i=typeof e=="string"?e:JSON.stringify(e);console.log(`
|
|
61
|
+
`+" ".repeat(5)+"\u{1F510} "+t),console.log(" ".repeat(5)+"\u{1F4F1} Scan with IXO app"),console.log(" ".repeat(5)+"\u2501".repeat(30)),mr.generate(i,{small:!0}),console.log(" ".repeat(5)+`\u23F3 Waiting...
|
|
62
|
+
`)}displayQRCode(e){this.displayStyledQRCode(e,"Login with SignX")}async awaitLogin(){return new Promise((e,t)=>{try{this.signXClient.on(cr,i=>{if(!i.data){t(new Error("Login failed"));return}if(!i.data.matrix){t(new Error("Matrix login failed"));return}e(i.data)}),this.signXClient.on(ar,i=>{console.log("Login error:",i),t(i)})}catch(i){console.error("Error in connecting:",i),t(i)}})}async transact(e,t,i){let n=sr();return this.signXClient.transact({address:t.address,did:t.did,pubkey:t.pubKey,timestamp:new Date().toISOString(),transactions:[{sequence:1,txBodyHex:or(n.encodeTxBody({messages:e,memo:i||""}))}]})}async awaitTransaction(){return new Promise((e,t)=>{try{this.signXClient.on(dr,i=>{e(i.data)}),this.signXClient.on(lr,i=>{t(i)})}catch(i){console.error("Error in connecting:",i),t(i)}})}async pollNextTransaction(){return this.signXClient.pollNextTransaction()}displayTransactionQRCode(e){this.displayStyledQRCode(e,"SIGNX TRANSACTION")}};var ne=class{constructor(e,t){this.wallet=e;this.config=t}name="signx-login";description="Login with SignX wallet";async execute(){try{let e=await I(this.config),t=new M(e),i=await t.login();t.displayQRCode(i);let n=await t.awaitLogin();return this.wallet.setWallet(n),this.wallet.setSignXClient(t),{success:!0,data:{message:"Successfully logged in with SignX!",wallet:{address:n.address,did:n.did,name:n.name}}}}catch(e){return{success:!1,error:e instanceof Error?`SignX login failed: ${e.message}`:"Unknown error"}}}};import*as x from"@clack/prompts";var oe=class{constructor(e,t){this.wallet=e;this.config=t;this.createEntity=new N(this.wallet,this.config)}name="update-entity";description="Update an entity (add controllers, etc.)";createEntity;async execute(){this.config.getValue("network")||await I(this.config);let t=await x.group({entityDid:()=>x.text({message:"What is the DID of the entity you want to update?",initialValue:this.config.getValue("entityDid")?.toString()??"",validate(i){return ge(i)}}),action:()=>x.select({message:"What would you like to do?",options:[{value:"add-controller",label:"Add Controller",hint:"Add a new controller DID to the entity"}],initialValue:"add-controller"}),controllerDid:async({results:i})=>{if(i.action!=="add-controller")throw new Error("Unknown action");let n=await x.text({message:"What is the DID of the controller you want to add?",validate(o){return ge(o)}});return x.isCancel(n)&&(x.cancel("Operation cancelled."),process.exit(0)),n}},{onCancel:()=>{x.cancel("Operation cancelled."),process.exit(0)}});try{if(t.action==="add-controller"&&typeof t.controllerDid=="string"){let i=t.controllerDid,n=t.entityDid;return x.log.info(`Adding controller ${i} to entity ${n}`),await this.createEntity.addControllerToEntity(n,i),x.log.success(`Controller ${i} successfully added to entity ${n}`),{success:!0,data:`Controller ${i} added to entity ${n}`}}return{success:!1,error:"Unknown action"}}catch(i){return{success:!1,error:i instanceof Error?i.message:String(i)}}}};var Se=class extends Error{constructor(t,i="CLI_ERROR",n){super(t);this.code=i;this.suggestions=n;this.name="CLIError"}};function se(r){r instanceof Se&&(console.error(`
|
|
63
63
|
\u274C ${r.name}: ${r.message}`),r.suggestions?.length&&(console.error(`
|
|
64
64
|
Suggestions:`),r.suggestions.forEach(e=>console.error(` \u2022 ${e}`))),process.exit(1)),r instanceof Error&&(console.error(`
|
|
65
65
|
\u274C Unexpected Error: ${r.message}`),r.stack&&(console.error(`
|
|
66
66
|
Stack trace:`),console.error(r.stack)),process.exit(1)),console.error(`
|
|
67
|
-
\u274C Unknown error occurred
|
|
67
|
+
\u274C Unknown error occurred`,r),process.exit(1)}var ae=class r{config={};static instance;constructor(){}static getInstance(){return r.instance||(r.instance=new r),r.instance}addValue(e,t){this.config[e]=t}getValue(e){return this.config[e]}getOrThrow(e){let t=this.getValue(e);if(!t)throw new Error(`Value ${e} is not set`);return t}getConfig(){return this.config}deleteValue(e){delete this.config[e]}};import{log as b}from"@clack/prompts";import{cosmos as pt}from"@ixo/impactxclient-sdk";import{existsSync as Ee,readFileSync as pr,writeFileSync as gr}from"fs";import{unlink as ur}from"fs/promises";import fr from"os";import hr from"path";var U=hr.join(fr.homedir(),".wallet.json"),ce=class{wallet;signXClient;config;constructor(e){this.config=e,this.loadWallet()}setSignXClient(e){this.signXClient=e}loadWallet(){if(Ee(U))try{let e=pr(U,"utf8");if(this.wallet=JSON.parse(e),!this.wallet.matrix?.userId||!this.wallet.matrix.userId.includes(":")){b.warning("Wallet is missing valid Matrix credentials. Please re-authenticate via SignX."),this.wallet=void 0;return}let t=this.wallet.network;if(!t){let i=this.wallet.matrix.userId.split(":")[1];if(t={"devmx.ixo.earth":"devnet","testmx.ixo.earth":"testnet","mx.ixo.earth":"mainnet"}[i],!t)throw new Error(`Cannot determine network from matrix domain: ${i}`);this.wallet.network=t}this.config.addValue("network",t),this.setSignXClient(new M(t)),b.success(`Welcome back, ${this.wallet.name}!`),b.info(`Network: ${t}`)}catch(e){b.warning(`Failed to load wallet file: ${e instanceof Error?e.message:String(e)}`),this.wallet=void 0}else b.warning("No wallet file found")}setWallet(e){try{this.wallet=e;let t=JSON.stringify(e,null,2);gr(U,t,"utf8"),b.success(`Wallet saved successfully to: ${U}`)}catch(t){throw b.error(`Failed to save wallet: ${t instanceof Error?t.message:String(t)}`),new Error("Failed to save wallet file")}}checkWalletExists(){return Ee(U)&&this.wallet!==void 0}async clearWallet(){this.wallet=void 0;try{Ee(U)&&(await ur(U),b.success("Wallet file deleted successfully"))}catch(e){b.error(`Failed to delete wallet file: ${e instanceof Error?e.message:String(e)}`)}}get did(){return this.wallet?.did}get address(){return this.wallet?.address}get name(){return this.wallet?.name}get pubKey(){return this.wallet?.pubKey}get algo(){return this.wallet?.algo}get matrix(){return this.wallet?.matrix}get matrixHomeServer(){let e=this.wallet?.matrix?.userId;return!e||!e.includes(":")?void 0:`https://${e.split(":")[1]}`}reloadWallet(){this.loadWallet()}async sendTokens(e,t){if(!this.address||!this.signXClient||!this.wallet)throw new Error("Wallet not loaded");let i={typeUrl:"/cosmos.bank.v1beta1.MsgSend",value:pt.bank.v1beta1.MsgSend.fromPartial({fromAddress:this.address,toAddress:e,amount:[pt.base.v1beta1.Coin.fromPartial({amount:t.toString(),denom:"uixo"})]})},n=await this.signXClient?.transact([i],this.wallet);return this.signXClient?.displayTransactionQRCode(JSON.stringify(n)),await this.signXClient?.pollNextTransaction(),await this.signXClient?.awaitTransaction()}};var Ae=class{registry;config;wallet;constructor(){this.registry=new B,this.config=ae.getInstance(),this.wallet=new ce(this.config)}registerCommands(){this.registry.register(new re(this.config,this.wallet)),this.registry.register(new D(this.wallet,this.config)),this.registry.register(new oe(this.wallet,this.config)),this.registry.register(new ee(this.wallet,this.config)),this.registry.register(new ie(this.wallet)),this.registry.register(new j(this.registry))}async showHelp(){this.wallet.setWallet({address:"0x0000000000000000000000000000000000000000",algo:"secp",did:"did:ixo:entity:1a76366f16570483cea72b111b27fd78",network:"devnet",name:"My oracle",pubKey:"0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",ledgered:!1,matrix:{accessToken:"",userId:"0x0000000000000000000000000000000000000000",address:"",roomId:""}}),this.registerCommands();let t=await new j(this.registry).execute();t.success&&t.data&&console.log(t.data)}async handleAuthentication(){if(!this.wallet.checkWalletExists()){let e=await ut({message:"Login with SignX",options:[{value:"login",label:"Login"},{value:"exit",label:"Exit"}]});switch(gt(e)&&(be("Operation cancelled."),O.exit(0)),String(e)){case"login":{(await new ne(this.wallet,this.config).execute()).success&&K.success("Login successful");return}case"exit":{be("Operation cancelled."),O.exit(0);return}default:throw new Error(`Unknown command: ${e}`)}}}async executeCommand(e){let t=this.registry.get(e);if(!t)throw new Error(`Unknown command: ${e}`);let i=xr();i.start(`Executing ${t.name}...`);let n=await t.execute();i.stop(`${t.name} completed`),n.success?(K.success(`${t.name} completed successfully!`),n.data&&K.info(JSON.stringify(n.data,null,2))):K.error(`${t.name} failed: ${n.error}`)}async interactiveMode(){wr("IXO CLI"),K.warn("Keep your IXO Mobile App open while running the CLI; So u do not interrupt the signX session"),await this.handleAuthentication(),this.registerCommands();let e=await ut({message:`Welcome ${this.wallet.name}, what would you like to do?`,options:[...this.registry.getCommandOptions()],initialValue:"init"});gt(e)&&(be("Operation cancelled."),O.exit(0)),await this.executeCommand(String(e))}async argumentMode(e){let t=e[0];if(!t){await this.interactiveMode();return}if(t==="--init"){await this.handleAuthentication(),this.registerCommands(),await this.executeCommand("init");return}if(t==="--help"||t==="-h"){await this.showHelp();return}await this.handleAuthentication(),this.registerCommands(),await this.executeCommand(t)}async run(e){try{let t=e.slice(2);t.length===0?await this.interactiveMode():await this.argumentMode(t)}catch(t){se(t)}yr("Thanks for using IXO CLI!"),O.exit(0)}};O.on("uncaughtException",se);O.on("unhandledRejection",se);var vr=new Ae;vr.run(O.argv);
|
|
68
68
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/index.ts","../src/commands/create-entity-command.ts","../src/utils/common.ts","../src/utils/entity.ts","../src/utils/account/simplifiedRegistration.ts","../src/utils/account/matrix.ts","../src/utils/account/secretStorageKeys.ts","../src/utils/account/utils.ts","../src/utils/account/feegrant.ts","../src/utils/matrix/upload-to-matrix.ts","../src/utils/createCIDFromBase64.ts","../src/commands/create-user-command.ts","../src/commands/help.command.ts","../src/commands/init.command.ts","../src/utils/create-project-env-file.ts","../src/commands/logout.commands.ts","../src/utils/signx/signx.ts","../src/commands/signX.commands.ts","../src/utils/errors.ts","../src/utils/runtime-config.ts","../src/utils/wallet.ts"],"sourcesContent":["import { cancel, intro, isCancel, log, outro, select, spinner } from '@clack/prompts';\nimport process from 'node:process';\nimport { CommandRegistry } from './commands';\nimport { CreateEntityCommand } from './commands/create-entity-command';\nimport { CreateUserCommand } from './commands/create-user-command';\nimport { HelpCommand } from './commands/help.command';\nimport { InitCommand } from './commands/init.command';\nimport { LogoutCommand } from './commands/logout.commands';\nimport { SignXLoginCommand } from './commands/signX.commands';\nimport { handleError } from './utils/errors';\nimport { RuntimeConfig } from './utils/runtime-config';\nimport { Wallet } from './utils/wallet';\n\nclass CLIManager {\n private registry: CommandRegistry;\n private config: RuntimeConfig;\n private wallet: Wallet;\n\n constructor() {\n this.registry = new CommandRegistry();\n this.config = RuntimeConfig.getInstance();\n this.wallet = new Wallet();\n }\n\n private registerCommands(): void {\n this.registry.register(new InitCommand(this.config, this.wallet));\n this.registry.register(new CreateEntityCommand(this.wallet, this.config));\n this.registry.register(new CreateUserCommand(this.wallet, this.config));\n this.registry.register(new LogoutCommand(this.wallet));\n this.registry.register(new HelpCommand(this.registry));\n }\n\n private async showHelp(): Promise<void> {\n // add fake wallet to the config\n this.wallet.setWallet({\n address: '0x0000000000000000000000000000000000000000',\n algo: 'secp',\n did: 'did:ixo:entity:1a76366f16570483cea72b111b27fd78',\n network: 'devnet',\n name: 'My oracle',\n pubKey:\n '0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',\n ledgered: false,\n matrix: {\n accessToken: '',\n userId: '0x0000000000000000000000000000000000000000',\n address: '',\n roomId: '',\n },\n });\n this.registerCommands();\n const helpCommand = new HelpCommand(this.registry);\n const result = await helpCommand.execute();\n if (result.success && result.data) {\n console.log(result.data);\n }\n }\n\n private async handleAuthentication(): Promise<void> {\n if (!this.wallet.checkWalletExists()) {\n const login = await select({\n message: 'Login with SignX',\n options: [\n { value: 'login', label: 'Login' },\n { value: 'exit', label: 'Exit' },\n ],\n });\n\n if (isCancel(login)) {\n cancel('Operation cancelled.');\n process.exit(0);\n }\n\n switch (String(login)) {\n case 'login': {\n const loginCommand = new SignXLoginCommand(this.wallet, this.config);\n const result = await loginCommand.execute();\n if (result.success) {\n log.success('Login successful');\n }\n return;\n }\n case 'exit': {\n cancel('Operation cancelled.');\n process.exit(0);\n return;\n }\n default: {\n throw new Error(`Unknown command: ${login}`);\n }\n }\n }\n }\n\n private async executeCommand(commandName: string): Promise<void> {\n const command = this.registry.get(commandName);\n if (!command) {\n throw new Error(`Unknown command: ${commandName}`);\n }\n\n const s = spinner();\n s.start(`Executing ${command.name}...`);\n\n const result = await command.execute();\n s.stop(`${command.name} completed`);\n\n if (result.success) {\n log.success(`${command.name} completed successfully!`);\n if (result.data) {\n log.info(JSON.stringify(result.data, null, 2));\n }\n } else {\n log.error(`${command.name} failed: ${result.error}`);\n }\n }\n\n private async interactiveMode(): Promise<void> {\n intro('IXO CLI');\n log.warn('Keep your IXO Mobile App open while running the CLI; So u do not interrupt the signX session');\n\n await this.handleAuthentication();\n this.registerCommands();\n\n const action = await select({\n message: `Welcome ${this.wallet.name}, what would you like to do?`,\n options: [...this.registry.getCommandOptions()],\n initialValue: 'init',\n });\n\n if (isCancel(action)) {\n cancel('Operation cancelled.');\n process.exit(0);\n }\n\n await this.executeCommand(String(action));\n }\n\n private async argumentMode(args: string[]): Promise<void> {\n const command = args[0];\n\n if (!command) {\n await this.interactiveMode();\n return;\n }\n\n // Handle special flags\n if (command === '--init') {\n await this.handleAuthentication();\n this.registerCommands();\n await this.executeCommand('init');\n return;\n }\n\n // Handle help\n if (command === '--help' || command === '-h') {\n await this.showHelp();\n return;\n }\n\n // Handle direct command execution\n await this.handleAuthentication();\n this.registerCommands();\n await this.executeCommand(command);\n }\n\n async run(args: string[]): Promise<void> {\n try {\n // Remove the first two args (node path and script path)\n const userArgs = args.slice(2);\n\n if (userArgs.length === 0) {\n await this.interactiveMode();\n } else {\n await this.argumentMode(userArgs);\n }\n } catch (error) {\n handleError(error);\n }\n\n outro('Thanks for using IXO CLI!');\n process.exit(0);\n }\n}\n\n// Handle uncaught errors\nprocess.on('uncaughtException', handleError);\nprocess.on('unhandledRejection', handleError);\n\n// Start the CLI\nconst cli = new CLIManager();\nvoid cli.run(process.argv);\n","import { CLIResult } from '../types';\n\nexport interface Command {\n name: string;\n description: string;\n execute: (...args: any[]) => Promise<CLIResult>;\n}\n\nexport class CommandRegistry {\n private commands: Map<string, Command>;\n\n constructor() {\n this.commands = new Map();\n }\n\n register(command: Command): void {\n this.commands.set(command.name, command);\n }\n\n get(name: string): Command | undefined {\n return this.commands.get(name);\n }\n\n getAll(): Command[] {\n return Array.from(this.commands.values());\n }\n\n getCommandOptions() {\n return this.getAll().map((cmd) => ({\n value: cmd.name,\n label: cmd.name,\n hint: cmd.description,\n }));\n }\n}\n","import * as p from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport { checkRequiredNumber, checkRequiredString, checkRequiredURL, PORTAL_URL, selectNetwork } from '../utils/common';\nimport { CreateEntity } from '../utils/entity';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\n\nexport class CreateEntityCommand implements Command {\n name = 'create-entity';\n description = 'Create an entity';\n private readonly createEntity: CreateEntity;\n\n constructor(private wallet: Wallet, private config: RuntimeConfig) {\n this.createEntity = new CreateEntity(this.wallet, this.config);\n }\n\n async execute(): Promise<CLIResult> {\n const network = this.config.getValue('network') as NETWORK;\n if (!network) {\n await selectNetwork(this.config);\n }\n const results = await p.group(\n {\n oracleName: () =>\n p.text({\n message: 'What is the name of the oracle?',\n initialValue: 'My oracle',\n validate(value) {\n return checkRequiredString(value, 'Oracle name is required');\n },\n }),\n oraclePrice: () =>\n p.text({\n message: 'What is the price of the oracle in IXO CREDITS?',\n initialValue: '100',\n validate(value) {\n return checkRequiredNumber(parseInt(value), 'Oracle price is required and must be a number');\n },\n }),\n page: () =>\n p.group({\n title: () =>\n p.text({\n message: 'What is the title of the oracle entity page?',\n initialValue: 'AI Agent Oracle',\n validate(value) {\n return checkRequiredString(value, 'Title is required');\n },\n }),\n content: () =>\n p.text({\n message: 'What is the content of the oracle entity page?',\n initialValue: '### Oracle built to help u with daily tasks',\n validate(value) {\n return checkRequiredString(value, 'Content is required');\n },\n }),\n }),\n profile: () =>\n p.group({\n orgName: () =>\n p.text({\n message: 'What is the name of the organization?',\n initialValue: 'IXO',\n validate(value) {\n return checkRequiredString(value, 'Organization name is required');\n },\n }),\n name: () =>\n p.text({\n message: 'What is the name of the profile?',\n initialValue: 'My oracle',\n validate(value) {\n return checkRequiredString(value, 'Profile name is required');\n },\n }),\n logo: ({ results }) =>\n p.text({\n message: 'What is the logo of the profile?',\n initialValue: `https://api.dicebear.com/8.x/bottts/svg?seed=${results?.name ?? 'IXO'}`,\n defaultValue: `https://api.dicebear.com/8.x/bottts/svg?seed=${results?.name ?? 'IXO'}`,\n validate(value) {\n if (!value) return `https://api.dicebear.com/8.x/bottts/svg?seed=${results?.name ?? 'IXO'}`;\n return checkRequiredURL(value, 'Logo is required or a valid URL');\n },\n }),\n coverImage: ({ results }) =>\n p.text({\n message: 'What is the cover image of the profile?',\n initialValue: results.logo as string,\n defaultValue: results.logo as string,\n validate(value) {\n if (!value) return results.logo as string;\n return checkRequiredURL(value, 'Cover image is required or a valid URL');\n },\n }),\n location: () =>\n p.text({\n message: 'What is the location of your domain?',\n initialValue: 'New York, NY',\n validate(value) {\n return checkRequiredString(value, 'Location is required');\n },\n }),\n description: () =>\n p.text({\n message: 'What is the description of the entity (profile)?',\n initialValue: 'We are a company that helps you with daily tasks',\n validate(value) {\n return checkRequiredString(value, 'Description is required');\n },\n }),\n }),\n parentProtocol: () =>\n p.select({\n message: 'What is the parent protocol of the entity?',\n options: [\n {\n value: 'did:ixo:entity:1a76366f16570483cea72b111b27fd78',\n label: 'IXO Oracle Protocol',\n hint: 'default protocol',\n },\n ],\n initialValue: 'did:ixo:entity:1a76366f16570483cea72b111b27fd78',\n }),\n apiUrl: () =>\n p.text({\n message: 'What is the API URL of the oracle?',\n initialValue: 'http://localhost:4000',\n validate(value) {\n return checkRequiredURL(value, 'API URL is required or a valid URL');\n },\n }),\n },\n {\n // On Cancel callback that wraps the group\n // So if the user cancels one of the prompts in the group this function will be called\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n const did = await this.createEntity.execute({\n oracleConfig: {\n oracleName: results.oracleName,\n price: parseInt(results.oraclePrice),\n },\n page: results.page,\n profile: {\n orgName: results.profile.orgName,\n name: results.profile.name,\n logo: results.profile.logo as string,\n coverImage: results.profile.coverImage as string,\n location: results.profile.location,\n description: results.profile.description,\n },\n services: [\n {\n id: '{id}#api',\n serviceEndpoint: results.apiUrl,\n type: 'oracleService',\n },\n {\n id: '{id}#ws',\n serviceEndpoint: results.apiUrl,\n type: 'wsService',\n },\n ],\n parentProtocol: results.parentProtocol,\n });\n\n p.log.info(`API for the oracle is: ${results.apiUrl} | You can change this after you deploy the oracle`);\n\n // add to portal\n const portalBaseUrl = PORTAL_URL[(this.config.getValue('network') as NETWORK) ?? 'devnet'];\n\n const portalUrl = `${portalBaseUrl}/oracle/${did}/overview`;\n\n p.log.info(`Oracle created successfully: ${did}`);\n p.log.info(`Oracle URL: ${portalUrl}`);\n\n return {\n success: true,\n data: `Entity created successfully: ${did}`,\n };\n }\n}\n","import { select } from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { z } from 'zod';\nimport { RuntimeConfig } from './runtime-config';\n\nexport const selectNetwork = async (config: RuntimeConfig) => {\n const network = await select({\n message: 'Select network: (default: devnet)',\n options: [\n { value: 'mainnet', label: 'Mainnet' },\n { value: 'testnet', label: 'Testnet' },\n { value: 'devnet', label: 'Devnet' },\n ],\n initialValue: 'devnet',\n maxItems: 1,\n });\n\n config.addValue('network', network as NETWORK);\n\n return network as NETWORK;\n};\n\nexport const RELAYER_NODE_DID = {\n mainnet: 'did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d',\n testnet: 'did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb',\n devnet: 'did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d',\n};\n\nexport const MatrixHomeServerUrl: Record<NETWORK, string> = {\n devnet: 'https://devmx.ixo.earth',\n testnet: 'https://testmx.ixo.earth',\n mainnet: 'https://mx.ixo.earth',\n};\n\nexport const MatrixRoomBotServerUrl: Record<NETWORK, string> = {\n devnet: 'https://rooms.bot.devmx.ixo.earth',\n testnet: 'https://rooms.bot.testmx.ixo.earth',\n mainnet: 'https://rooms.bot.mx.ixo.earth',\n};\n\nexport const MatrixBotHomeServerUrl: Record<NETWORK, string> = {\n devnet: 'https://state.bot.devmx.ixo.earth',\n testnet: 'https://state.bot.testmx.ixo.earth',\n mainnet: 'https://state.bot.mx.ixo.earth',\n};\nexport const PORTAL_URL = {\n devnet: 'https://ixo-portal.vercel.app',\n testnet: 'https://ixo-portal.vercel.app',\n mainnet: 'https://ixo-portal.vercel.app',\n};\n\nexport const CHAIN_RPC = {\n mainnet: 'https://impacthub.ixo.world/rpc/',\n testnet: 'https://testnet.ixo.earth/rpc/',\n devnet: 'https://devnet.ixo.earth/rpc/',\n};\n\nexport const checkRequiredString = (value: string, message = 'This field is required') => {\n const schema = z.string().min(1, message);\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n\nexport const checkRequiredURL = (value: string, message = 'This url is required or a valid URL') => {\n const schema = z.url(message);\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n\nexport const checkRequiredNumber = (value: number, message = 'This number is required') => {\n const schema = z.number().min(1, message);\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n","import { isCancel, log, spinner, text } from '@clack/prompts';\nimport { customMessages, ixo, utils } from '@ixo/impactxclient-sdk';\nimport { LinkedResource, Service } from '@ixo/impactxclient-sdk/types/codegen/ixo/iid/v1beta1/types';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { registerUserSimplified, SimplifiedRegistrationResult } from './account/simplifiedRegistration';\nimport { checkRequiredString, RELAYER_NODE_DID } from './common';\nimport { publicUpload } from './matrix/upload-to-matrix';\nimport { RuntimeConfig } from './runtime-config';\nimport { Wallet } from './wallet';\n\ninterface BlockNoteBlock {\n id: string;\n type: string;\n props: {\n textColor: string;\n backgroundColor: string;\n textAlignment: string;\n level?: number;\n };\n content: Array<{\n type: string;\n text: string;\n styles: Record<string, any>;\n }>;\n children?: any[];\n}\ninterface BlockNotePage {\n title: string;\n blocks: BlockNoteBlock[] | null;\n}\n\ninterface CreateEntityParams {\n profile: {\n orgName: string;\n name: string;\n logo: string;\n coverImage: string;\n location: string;\n description: string;\n };\n page: {\n title: string;\n content: string;\n };\n services: Service[];\n parentProtocol: string;\n oracleConfig: {\n oracleName: string;\n price: number;\n };\n}\n\nexport class CreateEntity {\n private readonly wallet: Wallet;\n constructor(wallet: Wallet, private config: RuntimeConfig) {\n if (!wallet.did || !wallet.pubKey || !wallet.address || !wallet.algo) {\n throw new Error('Wallet not found');\n }\n this.wallet = wallet;\n this.MsgCreateEntityParams.value.verification = [\n ...customMessages.iid.createIidVerificationMethods({\n did: wallet.did,\n pubkey: new Uint8Array(Buffer.from(wallet.pubKey)),\n address: wallet.address,\n controller: wallet.did,\n type: wallet.algo === 'ed25519' ? 'ed' : 'secp',\n }),\n ];\n\n this.MsgCreateEntityParams.value.context = [];\n this.MsgCreateEntityParams.value.controller = [wallet.did];\n this.MsgCreateEntityParams.value.ownerAddress = wallet.address;\n this.MsgCreateEntityParams.value.ownerDid = wallet.did;\n this.MsgCreateEntityParams.value.service.push(\n ixo.iid.v1beta1.Service.fromPartial({\n id: '{id}#matrix',\n type: 'Matrix',\n serviceEndpoint: 'devmx.ixo.earth',\n })\n );\n\n this.MsgCreateEntityParams.value.relayerNode =\n RELAYER_NODE_DID[(this.config.getValue('network') as NETWORK) ?? 'devnet'];\n }\n private MsgCreateEntityParams = {\n typeUrl: '/ixo.entity.v1beta1.MsgCreateEntity',\n value: ixo.entity.v1beta1.MsgCreateEntity.fromPartial({\n entityType: 'oracle',\n context: [],\n entityStatus: 0,\n verification: [],\n controller: [],\n ownerAddress: '',\n ownerDid: '',\n relayerNode: '',\n service: [],\n linkedResource: [],\n accordedRight: [],\n linkedEntity: [],\n linkedClaim: [],\n startDate: utils.proto.toTimestamp(new Date()),\n endDate: utils.proto.toTimestamp(new Date(Date.now() + 100 * 365 * 24 * 60 * 60 * 1000)),\n }),\n };\n public addLinkedAccounts({ oracleAccountAddress }: { oracleAccountAddress: string }) {\n if (!this.wallet.signXClient || !this.wallet.wallet) {\n throw new Error('SignX client or wallet not found');\n }\n const memoryEngineByNetwork = {\n devnet: 'did:ixo:ixo17w9u5uk4qjyjgeyqfpnp92jwy58faey9vvp3ar',\n testnet: 'did:ixo:ixo14vjrckltpngugp03tcasfgh5qakey9n3sgm6y2',\n mainnet: 'did:ixo:ixo1d39eutxdc0e8mnp0fmzqjdy6aaf26s9hzrk33r',\n }[this.config.getValue('network') as NETWORK];\n\n const accounts = [memoryEngineByNetwork, `did:ixo:${oracleAccountAddress}`];\n const linkedAccounts = accounts.map((account) =>\n ixo.iid.v1beta1.LinkedEntity.fromPartial({\n id: account,\n type: 'agent',\n relationship: 'admin',\n service: 'matrix',\n })\n );\n\n this.MsgCreateEntityParams.value.linkedEntity = linkedAccounts;\n }\n private async createAuthZConfig({\n oracleAccountAddress,\n oracleName,\n entityDid,\n }: {\n oracleAccountAddress: string;\n oracleName: string;\n entityDid: string;\n }): Promise<LinkedResource> {\n const config = {\n '@context': [\n 'https://schema.org',\n {\n ixo: 'https://w3id.org/ixo/context/v1',\n oracle: {\n '@id': entityDid,\n '@type': '@id',\n },\n },\n ],\n '@type': 'Service',\n '@id': 'oracle:OracleAuthorization',\n name: 'OracleAuthorization',\n description: 'OracleAuthorization',\n serviceType: 'OracleClaimAuthorizationService',\n requiredPermissions: ['/ixo.claims.v1beta1.MsgCreateClaimAuthorization'],\n granteeAddress: oracleAccountAddress,\n granterAddress: '',\n oracleName: oracleName,\n };\n const response = await publicUpload({\n data: config,\n fileName: 'authz',\n config: this.config,\n wallet: this.wallet,\n });\n\n return ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: '{id}#orz',\n type: 'oracleAuthZConfig',\n proof: response.proof,\n right: '',\n encrypted: 'false',\n mediaType: 'application/json',\n description: 'Orale AuthZ Config',\n serviceEndpoint: response.serviceEndpoint,\n });\n }\n\n /**\n * Create Fees Config\n * @param entityDid\n * @param price\n *\n * The fees config is used to set the pricing for the oracle -- this config is fetched by the Frontend and any client to use the pricing for the oracle and grant max amount permissions\n */\n private async createFeesConfig({ entityDid, price }: { entityDid: string; price: number }): Promise<LinkedResource> {\n const config = {\n '@context': [\n 'https://schema.org',\n {\n ixo: 'https://w3id.org/ixo/context/v1',\n oracle: {\n '@id': entityDid,\n '@type': '@id',\n },\n },\n ],\n '@type': 'Service',\n '@id': 'oracle:ServiceFeeModel',\n name: 'Pricing',\n description: 'Pricing',\n serviceType: '',\n offers: {\n '@type': 'Offer',\n priceCurrency: 'uixo',\n priceSpecification: {\n '@type': 'PaymentChargeSpecification',\n priceCurrency: 'uixo',\n price: price,\n unitCode: 'MON',\n billingIncrement: 1,\n billingPeriod: 'P1M',\n priceType: 'Subscription',\n maxPrice: price,\n },\n eligibleQuantity: {\n '@type': 'QuantitativeValue',\n value: 1,\n unitCode: 'MON',\n },\n },\n };\n const response = await publicUpload({\n data: config,\n fileName: 'fees',\n config: this.config,\n wallet: this.wallet,\n });\n return ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: '{id}#fee',\n type: 'pricingList',\n proof: response.proof,\n right: '',\n encrypted: 'false',\n mediaType: 'application/json',\n description: 'Pricing List',\n serviceEndpoint: response.serviceEndpoint,\n });\n }\n\n /**\n * Create Oracle Config Files\n * @param oracleAccountAddress\n * @param oracleName\n * @param entityDid\n * @param price\n *\n * Using this after the entity is created to upload the config files to the entity using it's did\n * this will do entity update to add the config files to the entity\n */\n private async createOracleConfigFiles({\n oracleName,\n entityDid,\n price,\n oracleAccountAddress,\n }: CreateEntityParams['oracleConfig'] & { entityDid: string; oracleAccountAddress: string }) {\n const walletAddress = this.wallet.wallet?.address;\n\n if (!this.wallet.signXClient || !this.wallet.wallet || !walletAddress) {\n throw new Error('SignX client or wallet not found');\n }\n\n const resources = await Promise.all([\n this.createAuthZConfig({\n oracleName,\n entityDid,\n oracleAccountAddress,\n }),\n this.createFeesConfig({\n entityDid,\n price,\n }),\n ]);\n const linkedResourcesMsgs = resources.map((resource) => ({\n typeUrl: '/ixo.iid.v1beta1.MsgAddLinkedResource',\n value: ixo.iid.v1beta1.MsgAddLinkedResource.fromPartial({\n id: entityDid,\n linkedResource: ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: resource.id,\n description: resource.description,\n type: resource.type,\n proof: resource.proof,\n mediaType: resource.mediaType,\n encrypted: resource.encrypted,\n serviceEndpoint: resource.serviceEndpoint,\n }),\n signer: walletAddress,\n }),\n }));\n\n // sign and send the msgs\n log.info('Sign to edit the entity and add the config files');\n const tx = await this.wallet.signXClient.transact(linkedResourcesMsgs, this.wallet.wallet);\n this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(tx));\n await this.wallet.signXClient.pollNextTransaction();\n const response = await this.wallet.signXClient.awaitTransaction();\n return response;\n }\n\n private async addPage({ content, title }: CreateEntityParams['page']) {\n const blockNotePage: BlockNotePage = {\n title,\n blocks: [\n {\n id: 'title-block',\n type: 'heading',\n props: { textColor: 'default', backgroundColor: 'default', textAlignment: 'left' },\n content: [{ type: 'text', text: title, styles: {} }],\n },\n {\n id: 'content-block',\n type: 'paragraph',\n props: {\n textColor: 'default',\n backgroundColor: 'default',\n textAlignment: 'left',\n },\n content: [{ type: 'text', text: content, styles: {} }],\n },\n ],\n };\n\n const response = await publicUpload({\n data: blockNotePage,\n fileName: 'page',\n config: this.config,\n wallet: this.wallet,\n });\n\n const pageResource = {\n id: '{id}#pag',\n type: 'Settings',\n description: 'Page',\n mediaType: 'application/json',\n serviceEndpoint: response.serviceEndpoint,\n proof: response.proof,\n encrypted: 'false',\n right: '',\n };\n this.MsgCreateEntityParams.value.linkedResource.push(ixo.iid.v1beta1.LinkedResource.fromPartial(pageResource));\n }\n\n private async addProfile({ orgName, name, logo, coverImage, location, description }: CreateEntityParams['profile']) {\n const profileData = {\n '@context': {\n ixo: 'https://w3id.org/ixo/ns/protocol/',\n '@id': '@type',\n type: '@type',\n '@protected': false,\n },\n id: 'ixo:entity#profile',\n type: 'profile',\n orgName,\n name,\n image: coverImage,\n logo,\n brand: orgName,\n location,\n description,\n };\n\n const response = await publicUpload({\n data: profileData,\n fileName: 'profile',\n config: this.config,\n wallet: this.wallet,\n });\n\n const profileResource = {\n id: '{id}#pro',\n type: 'Settings',\n description: 'Profile',\n mediaType: 'application/json',\n serviceEndpoint: response.serviceEndpoint,\n proof: response.proof,\n encrypted: 'false',\n right: '',\n };\n this.MsgCreateEntityParams.value.linkedResource.push(ixo.iid.v1beta1.LinkedResource.fromPartial(profileResource));\n }\n\n private async addServices(services: Service[]) {\n this.MsgCreateEntityParams.value.service.push(\n ...services.map((service) => ixo.iid.v1beta1.Service.fromPartial(service))\n );\n }\n\n private async setParentProtocol(parentProtocol: string) {\n this.MsgCreateEntityParams.value.context.push(\n ...customMessages.iid.createAgentIidContext([{ key: 'class', val: parentProtocol }])\n );\n }\n\n public returnExecutableMsg() {\n return this.MsgCreateEntityParams;\n }\n\n public async execute(params: CreateEntityParams): Promise<string> {\n log.info('Adding page');\n await this.addPage(params.page);\n log.info('Adding profile');\n await this.addProfile(params.profile);\n log.info('Adding services');\n await this.addServices(params.services);\n log.info('Adding parent protocol');\n await this.setParentProtocol(params.parentProtocol);\n\n const msg = this.returnExecutableMsg();\n if (!this.wallet.signXClient || !this.wallet.wallet) {\n throw new Error('SignX client not found');\n }\n\n log.info('Creating Oracle Wallet and Matrix Account');\n const pin = await text({\n message: 'Enter a PIN to secure your Matrix Vault:',\n initialValue: '',\n defaultValue: '',\n validate(value) {\n return checkRequiredString(value, 'PIN is required');\n },\n });\n if (isCancel(pin)) {\n log.error('User cancelled');\n process.exit(1);\n }\n const registerResult = await registerUserSimplified(\n {\n pin,\n oracleName: params.oracleConfig.oracleName,\n network: this.config.getValue('network') as NETWORK,\n oracleAvatarUrl: params.profile.logo,\n },\n async (address) => {\n await this.wallet.sendTokens(address, 250_000); // 250,000 uixo = 0.25 IXO;\n }\n );\n\n this.addLinkedAccounts({\n oracleAccountAddress: registerResult.address,\n });\n\n log.info('Sign this transaction to create the entity');\n const tx = await this.wallet.signXClient.transact([msg], this.wallet.wallet);\n this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(tx));\n await this.wallet.signXClient.pollNextTransaction();\n\n // Wait for transaction completion\n const response = await this.wallet.signXClient.awaitTransaction();\n log.success('Entity created -- wait to attach the required config files');\n\n // upload resources\n const did = utils.common.getValueFromEvents(response as any, 'wasm', 'token_id');\n await this.createOracleConfigFiles({\n oracleName: params.oracleConfig.oracleName,\n price: params.oracleConfig.price,\n oracleAccountAddress: registerResult.address,\n entityDid: did,\n });\n log.success('Entity created -- config files attached');\n\n const s = spinner();\n s.start('Creating Entity Matrix Room...');\n s.stop('Room created -- room joined');\n log.warn('Please save the following information in a secure location as it is not stored:');\n log.info(`ORACLE ACCOUNT DETAILS`);\n\n for (const key in registerResult) {\n log.info(`${key}: ${registerResult[key as keyof SimplifiedRegistrationResult]}`);\n }\n this.config.addValue('registerUserResult', registerResult);\n this.config.addValue('entityDid', did);\n return did;\n }\n}\n","import { utils } from '@ixo/impactxclient-sdk';\nimport { createMatrixApiClient } from '@ixo/matrixclient-sdk';\n\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { MatrixHomeServerUrl, MatrixRoomBotServerUrl } from '../common';\nimport {\n checkIsUsernameAvailable,\n createMatrixClient,\n generatePassphraseFromMnemonic,\n generatePasswordFromMnemonic,\n generateUsernameFromAddress,\n generateUserRoomAliasFromAddress,\n hasCrossSigningAccountData,\n logoutMatrixClient,\n mxRegisterWithSecp,\n setupCrossSigning,\n} from './matrix';\nimport { checkIidDocumentExists, createIidDocument, delay, encrypt, getSecpClient } from './utils';\n\nexport interface SimplifiedRegistrationResult {\n address: string;\n did: string;\n mnemonic: string;\n matrixUserId: string;\n matrixRoomId: string;\n matrixMnemonic: string;\n matrixPassword: string;\n matrixAccessToken: string;\n matrixRecoveryPhrase: string;\n pin: string;\n matrixDeviceName: string;\n}\n\nconst DEVICE_NAME = 'Oracles CLI';\n/**\n * Simplified user registration flow without email verification or passkey authentication\n * Includes: wallet creation, DID creation, Matrix account with secp auth, Matrix room setup, encrypted mnemonic storage\n * @param pin - User PIN for encrypting Matrix mnemonic\n * @returns Registration result with wallet and Matrix account details\n */\nexport async function registerUserSimplified(\n {\n pin,\n oracleName,\n network,\n oracleAvatarUrl,\n }: {\n pin: string;\n oracleName: string;\n network: NETWORK;\n oracleAvatarUrl: string;\n },\n transferTokens: (address: string) => Promise<void>\n): Promise<SimplifiedRegistrationResult> {\n try {\n // =================================================================================================\n // 1. CREATE WALLET\n // =================================================================================================\n const mnemonic = utils.mnemonic.generateMnemonic();\n const wallet = await getSecpClient(mnemonic);\n const address = wallet.baseAccount.address;\n console.log('✅ Wallet created:', address);\n\n // transfer tokens\n await transferTokens(address);\n\n // =================================================================================================\n // 2. DID CREATION\n // =================================================================================================\n const did = utils.did.generateSecpDid(address);\n const didExists = await checkIidDocumentExists(did, network);\n console.log('✅ DID exists:', didExists);\n if (!didExists) {\n console.log('✅ DID does not exist, creating...');\n await createIidDocument(did, network, wallet);\n console.log('✅ DID created, waiting 500ms...');\n await delay(500);\n console.log('✅ Checking if DID exists...');\n const didExistsAfterCreation = await checkIidDocumentExists(did, network);\n if (!didExistsAfterCreation) {\n throw new Error('Failed to create DID document');\n }\n }\n console.log('✅ DID created:', did);\n\n // =================================================================================================\n // 3. MATRIX ACCOUNT CREATION\n // =================================================================================================\n const mxMnemonic = utils.mnemonic.generateMnemonic(12);\n const homeServerUrl = MatrixHomeServerUrl[network];\n const mxUsername = generateUsernameFromAddress(address);\n const mxPassword = generatePasswordFromMnemonic(mxMnemonic);\n const mxPassphrase = generatePassphraseFromMnemonic(mxMnemonic);\n\n // Check if username is available\n const isUsernameAvailable = await checkIsUsernameAvailable({\n homeServerUrl: homeServerUrl,\n username: mxUsername,\n });\n if (!isUsernameAvailable) {\n throw new Error('Matrix account already exists');\n }\n\n // Clear any residual matrix data\n // await logoutMatrixClient({ baseUrl: homeServerUrl, accessToken: '', userId: '', deviceId: '' });\n\n // Register using secp256k1 signature (not passkey)\n const account = await mxRegisterWithSecp(address, mxPassword, DEVICE_NAME, wallet, network);\n if (!account?.accessToken) {\n throw new Error('Failed to register matrix account');\n }\n console.log('✅ Matrix account created:', account.userId);\n\n // =================================================================================================\n // 4. MATRIX CLIENT SETUP\n // =================================================================================================\n const mxClient = await createMatrixClient({\n homeServerUrl,\n accessToken: account.accessToken,\n userId: account.userId,\n deviceId: account.deviceId,\n });\n\n try {\n await Promise.all([mxClient.setDisplayName(oracleName), mxClient.setAvatarUrl(oracleAvatarUrl)]);\n } catch (error) {\n console.error('Failed to set display name or avatar url:', error);\n }\n\n const matrixApiClient = createMatrixApiClient({\n homeServerUrl: homeServerUrl,\n accessToken: account.accessToken,\n });\n\n // Setup cross signing\n let hasCrossSigning = hasCrossSigningAccountData(mxClient);\n if (!hasCrossSigning) {\n hasCrossSigning = await setupCrossSigning(mxClient, {\n securityPhrase: mxPassphrase,\n password: mxPassword,\n forceReset: true,\n });\n if (!hasCrossSigning) {\n throw new Error('Failed to setup cross signing');\n }\n }\n console.log('✅ Matrix cross-signing setup completed');\n\n // =================================================================================================\n // 5. MATRIX ROOM CREATION/JOIN\n // =================================================================================================\n const mxRoomAlias = generateUserRoomAliasFromAddress(address, account.baseUrl);\n const queryIdResponse = await matrixApiClient.room.v1beta1.queryId(mxRoomAlias).catch(() => undefined);\n let roomId: string = queryIdResponse?.room_id ?? '';\n\n if (!roomId) {\n // Create room via bot\n const response = await fetch(`${MatrixRoomBotServerUrl[network]}/room/source`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n did: did,\n userMatrixId: account.userId,\n }),\n });\n if (!response.ok) {\n throw new Error('Failed to create matrix room');\n }\n const data = (await response.json()) as { roomId: string };\n roomId = data.roomId;\n if (!roomId) {\n throw new Error('Failed to create user matrix room');\n }\n }\n\n // Ensure room is joined\n let joinedMembers = await matrixApiClient.room.v1beta1.listJoinedMembers(roomId).catch(() => undefined);\n let joined = !!joinedMembers?.joined?.[account.userId];\n if (!joined) {\n const joinResponse = await matrixApiClient.room.v1beta1.join(roomId);\n if (!joinResponse.room_id) {\n throw new Error('Failed to join matrix room');\n }\n joinedMembers = await matrixApiClient.room.v1beta1.listJoinedMembers(roomId);\n joined = !!joinedMembers?.joined?.[account.userId];\n if (!joined) {\n throw new Error('Failed to join matrix room');\n }\n }\n console.log('✅ Matrix room created/joined:', roomId);\n\n // =================================================================================================\n // 6. ENCRYPT AND STORE MATRIX MNEMONIC\n // =================================================================================================\n const encryptedMnemonic = encrypt(mxMnemonic, pin);\n const storeEncryptedMnemonicResponse = await fetch(\n `${homeServerUrl}/_matrix/client/r0/rooms/${roomId}/state/ixo.room.state.secure/encrypted_mnemonic`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${account.accessToken as string}`,\n },\n body: JSON.stringify({\n encrypted_mnemonic: encryptedMnemonic,\n }),\n }\n );\n if (!storeEncryptedMnemonicResponse.ok) {\n throw new Error('Failed to store encrypted mnemonic in matrix room');\n }\n await storeEncryptedMnemonicResponse.json();\n console.log('✅ Encrypted Matrix mnemonic stored in room');\n\n // =================================================================================================\n // 7. LOGOUT MATRIX CLIENT\n // =================================================================================================\n await logoutMatrixClient({\n mxClient,\n baseUrl: homeServerUrl,\n accessToken: account.accessToken,\n userId: account.userId,\n deviceId: account.deviceId,\n });\n\n // =================================================================================================\n // 7. RETURN REGISTRATION RESULT\n // =================================================================================================\n return {\n address: address,\n did: did,\n mnemonic: mnemonic, // Wallet mnemonic - store securely!\n matrixUserId: account.userId,\n matrixRoomId: roomId,\n matrixMnemonic: mxMnemonic, // Matrix mnemonic - also store securely!\n matrixPassword: mxPassword,\n matrixAccessToken: account.accessToken,\n matrixRecoveryPhrase: mxPassphrase,\n pin: pin,\n matrixDeviceName: DEVICE_NAME,\n };\n } catch (error) {\n console.error('Simplified registration failed:', error);\n throw error;\n }\n}\n","import { sha256 } from '@cosmjs/crypto';\nimport { encrypt as eciesEncrypt } from 'eciesjs';\nimport { ClientEvent, createClient, MatrixClient } from 'matrix-js-sdk';\nimport { CryptoApi } from 'matrix-js-sdk/lib/crypto-api';\nimport md5 from 'md5';\n\n// import cons from '@constants/matrix';\n// import { isAuthenticated, secret } from '@utils/secrets';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { MatrixHomeServerUrl, MatrixRoomBotServerUrl } from '../common';\nimport { cacheSecretStorageKey, clearSecretStorageKeys, getSecretStorageKey } from './secretStorageKeys';\nimport { delay } from './utils';\n\nconst WELL_KNOWN_URI = '/.well-known/matrix/client';\n\n// =================================================================================================\n// AUTH\n// =================================================================================================\ninterface AuthResponse {\n accessToken: string;\n deviceId: string;\n userId: string;\n baseUrl: string;\n}\nexport const mxLogin = async (\n {\n homeServerUrl,\n username,\n password,\n deviceName,\n }: { homeServerUrl: string; username: string; password: string; deviceName: string },\n localMatrix = false\n) => {\n let mxHomeServerUrl = homeServerUrl;\n let mxUsername = username;\n const mxIdMatch = mxUsername.match(/^@(.+):(.+\\..+)$/);\n if (mxIdMatch) {\n mxUsername = mxIdMatch[1] as string;\n mxHomeServerUrl = mxIdMatch[2] as string;\n mxHomeServerUrl = localMatrix ? mxHomeServerUrl : await getBaseUrl(mxHomeServerUrl);\n }\n\n try {\n const client = createTemporaryClient(mxHomeServerUrl);\n const response = await client.login('m.login.password', {\n identifier: {\n type: 'm.id.user',\n user: normalizeUsername(mxUsername),\n },\n password,\n initial_device_display_name: deviceName,\n });\n const data: AuthResponse = {\n accessToken: response.access_token,\n deviceId: response.device_id,\n userId: response.user_id,\n baseUrl: localMatrix ? mxHomeServerUrl : response?.well_known?.['m.homeserver']?.base_url || client.baseUrl,\n };\n return data;\n } catch (error) {\n let msg = (error as any).message;\n if (msg === 'Unknown message') {\n msg = 'Please check your credentials';\n }\n console.error(`mxLogin::`, msg);\n throw new Error(msg);\n }\n};\n\n// =================================================================================================\n// NEW API-BASED REGISTRATION\n// =================================================================================================\n\ninterface PublicKeyResponse {\n publicKey: string;\n fingerprint: string;\n algorithm: string;\n usage: string;\n}\n\ninterface UserCreationChallenge {\n timestamp: string;\n address: string;\n service: string;\n type: string;\n}\n\ninterface UserCreationRequest {\n address: string;\n encryptedPassword: string;\n publicKeyFingerprint: string;\n authnResult?: any;\n secpResult?: {\n signature: string;\n challenge: string;\n };\n}\n\ninterface UserCreationResponse {\n success: boolean;\n matrixUserId: string;\n address: string;\n message: string;\n}\n\n/**\n * Fetch the public key for password encryption from the user creation API\n * @returns Public key information for encryption\n */\nexport async function getPublicKeyForEncryption(network: NETWORK): Promise<PublicKeyResponse> {\n const response = await fetch(`${MatrixRoomBotServerUrl[network]}/public-key`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error('Failed to fetch public key for encryption');\n }\n\n const data = (await response.json()) as PublicKeyResponse;\n return data;\n}\n\n/**\n * Create a structured challenge for user creation\n * @param address The user's address (without did:ixo: prefix)\n * @returns The challenge object and its base64 representation\n */\nexport function createUserCreationChallenge(address: string): {\n challenge: UserCreationChallenge;\n challengeBase64: string;\n} {\n const challenge: UserCreationChallenge = {\n timestamp: new Date().toISOString(),\n address: address,\n service: 'matrix',\n type: 'create-account',\n };\n\n const challengeBase64 = Buffer.from(JSON.stringify(challenge)).toString('base64');\n\n return { challenge, challengeBase64 };\n}\n\n/**\n * Encrypt password using ECIES with the provided public key\n * @param password The password to encrypt\n * @param publicKey The public key in hex format\n * @returns The encrypted password in hex format\n */\nexport function encryptPasswordWithECIES(password: string, publicKey: string): string {\n const publicKeyBytes = new Uint8Array(Buffer.from(publicKey, 'hex'));\n const passwordBytes = new Uint8Array(Buffer.from(password, 'utf8'));\n const encryptedPassword = eciesEncrypt(publicKeyBytes, passwordBytes);\n return Array.from(encryptedPassword, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Create user account using WebAuthn/Passkey authentication\n * @param address The user's address\n * @param password The matrix password\n * @param authnResult The WebAuthn assertion result\n * @returns The user creation response\n */\nexport async function createUserAccountWithPasskey(\n address: string,\n password: string,\n authnResult: any,\n network: NETWORK\n): Promise<UserCreationResponse> {\n const publicKeyInfo = await getPublicKeyForEncryption(network);\n const encryptedPassword = encryptPasswordWithECIES(password, publicKeyInfo.publicKey);\n\n const request: UserCreationRequest = {\n address,\n encryptedPassword,\n publicKeyFingerprint: publicKeyInfo.fingerprint,\n authnResult,\n };\n\n const response = await fetch(`${MatrixRoomBotServerUrl[network]}/user/create`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as { error: string };\n throw new Error(errorData.error || 'Failed to create user account');\n }\n\n return (await response.json()) as UserCreationResponse;\n}\n\n/**\n * Create user account using secp256k1 signature authentication\n * @param address The user's address\n * @param password The matrix password\n * @param signature The secp256k1 signature (base64)\n * @param challenge The challenge that was signed (base64)\n * @returns The user creation response\n */\nexport async function createUserAccountWithSecp(\n address: string,\n password: string,\n signature: string,\n challenge: string,\n network: NETWORK\n): Promise<UserCreationResponse> {\n const publicKeyInfo = await getPublicKeyForEncryption(network);\n const encryptedPassword = encryptPasswordWithECIES(password, publicKeyInfo.publicKey);\n\n const request: UserCreationRequest = {\n address,\n encryptedPassword,\n publicKeyFingerprint: publicKeyInfo.fingerprint,\n secpResult: {\n signature,\n challenge,\n },\n };\n\n const response = await fetch(`${MatrixRoomBotServerUrl[network]}/user/create`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const errorData = (await response.json()) as { error: string };\n throw new Error(errorData.error || 'Failed to create user account');\n }\n\n return (await response.json()) as UserCreationResponse;\n}\n\n// =================================================================================================\n// UPDATED REGISTRATION FUNCTIONS\n// =================================================================================================\n\n/**\n * Register matrix account using the new API with WebAuthn/Passkey authentication\n * @param address The user's address\n * @param password The matrix password\n * @param authnResult The WebAuthn assertion result\n * @returns AuthResponse with access token and user details\n */\nexport async function mxRegisterWithPasskey(\n address: string,\n password: string,\n authnResult: any,\n deviceName: string,\n network: NETWORK\n): Promise<AuthResponse> {\n try {\n const userCreationResult = await createUserAccountWithPasskey(address, password, authnResult, network);\n\n if (!userCreationResult.success) {\n throw new Error('Failed to create matrix account via API');\n }\n\n // Now login to get the access token\n const homeServerUrl = MatrixHomeServerUrl[network];\n const username = generateUsernameFromAddress(address);\n\n const loginResult = await mxLogin({\n homeServerUrl,\n username,\n password,\n deviceName,\n });\n\n return loginResult;\n } catch (error) {\n console.error('mxRegisterWithPasskey error:', error);\n throw error;\n }\n}\n\n/**\n * Register matrix account using the new API with secp256k1 signature authentication\n * @param address The user's address\n * @param password The matrix password\n * @param wallet The secp wallet for signing\n * @returns AuthResponse with access token and user details\n */\nexport async function mxRegisterWithSecp(\n address: string,\n password: string,\n deviceName: string,\n wallet: { sign: (message: string) => Promise<Uint8Array> },\n network: NETWORK\n): Promise<AuthResponse> {\n try {\n // Create challenge and sign it\n const { challengeBase64 } = createUserCreationChallenge(address);\n const signatureBytes = await wallet.sign(challengeBase64);\n const signature = Buffer.from(signatureBytes).toString('base64');\n\n const userCreationResult = await createUserAccountWithSecp(address, password, signature, challengeBase64, network);\n\n if (!userCreationResult.success) {\n throw new Error('Failed to create matrix account via API');\n }\n\n // Now login to get the access token\n const homeServerUrl = MatrixHomeServerUrl[network];\n const username = generateUsernameFromAddress(address);\n\n const loginResult = await mxLogin({\n homeServerUrl,\n username,\n password,\n deviceName,\n });\n\n return loginResult;\n } catch (error) {\n console.error('mxRegisterWithSecp error:', error);\n throw error;\n }\n}\n\n// =================================================================================================\n// UPDATED LEGACY REGISTRATION (DEPRECATED)\n// =================================================================================================\n\n// Keep the old functions for backward compatibility but mark as deprecated\nasync function getRegisterFlow(homeServerUrl: string) {\n try {\n const client = createTemporaryClient(homeServerUrl);\n // @ts-ignore\n const [registerResponse] = await Promise.allSettled([client.register()]);\n const registerFlow = registerResponse.status === 'rejected' ? registerResponse?.reason?.data : undefined;\n console.log('registerFlow', registerFlow);\n if (registerFlow === undefined) {\n throw new Error('Failed to setup home server config.');\n }\n return registerFlow;\n } catch (error) {\n if ((error as any).data) {\n console.log('registerFlow', (error as any).data);\n return (error as any).data;\n }\n throw new Error('Failed to get matrix register flow.');\n }\n}\n\nexport async function loginOrRegisterMatrixAccount({\n homeServerUrl,\n username,\n password,\n wallet,\n accessToken,\n deviceName,\n network,\n}: {\n homeServerUrl: string;\n username: string;\n password: string;\n accessToken?: string;\n wallet?: { sign: (message: string) => Promise<Uint8Array>; baseAccount: { address: string } };\n deviceName: string;\n network: NETWORK;\n}) {\n const isAuthenticated = !!accessToken;\n let isUsernameAvailable = await checkIsUsernameAvailable({ homeServerUrl, username });\n let res: AuthResponse | undefined;\n if (isUsernameAvailable && wallet) {\n // Use new API-based registration with secp256k1 authentication\n res = await mxRegisterWithSecp(wallet.baseAccount.address, password, deviceName, wallet, network);\n if (!res?.accessToken) {\n throw new Error('Failed to register matrix account');\n }\n console.log('mxRegisterWithSecp', res);\n }\n if (!isAuthenticated) {\n res = await mxLogin({\n homeServerUrl,\n username,\n password,\n deviceName,\n });\n if (!res?.accessToken) {\n throw new Error('Failed to login to matrix account');\n }\n console.log('mxLogin', res);\n }\n return res;\n}\n\nexport async function checkIsUsernameAvailable({\n homeServerUrl,\n username,\n}: {\n homeServerUrl: string;\n username: string;\n}) {\n const client = createTemporaryClient(homeServerUrl);\n try {\n const isUsernameAvailable = await client.isUsernameAvailable(username);\n return !!isUsernameAvailable;\n } catch (error) {\n return false;\n }\n}\n\n// =================================================================================================\n// CLIENT\n// =================================================================================================\n/**\n * Creates a temporary matrix client, used for matrix login or registration to get access tokens\n * @param homeServerUrl - the home server url to instantiate the matrix client\n * @returns matrix client\n */\nexport function createTemporaryClient(homeServerUrl: string) {\n if (!homeServerUrl) {\n throw new Error('Home server URL is required to instantiate matrix client');\n }\n return createClient({\n baseUrl: homeServerUrl,\n });\n}\n\nexport async function createMatrixClient({\n homeServerUrl,\n accessToken,\n userId,\n deviceId,\n}: {\n homeServerUrl: string;\n accessToken: string;\n userId: string;\n deviceId: string;\n}) {\n console.log('createMatrixClient::', { homeServerUrl, accessToken, userId, deviceId });\n\n if (!homeServerUrl || !accessToken || !userId || !deviceId) {\n throw new Error('Login to Matrix account before trying to instantiate Matrix client.');\n }\n\n // const indexedDBStore = new IndexedDBStore({\n // indexedDB: global.indexedDB,\n // dbName: 'matrix-sync-store',\n // });\n // const legacyCryptoStore = new IndexedDBCryptoStore()\n\n const mxClient = createClient({\n baseUrl: homeServerUrl,\n accessToken,\n userId,\n // store: indexedDBStore,\n // cryptoStore: legacyCryptoStore,\n deviceId,\n timelineSupport: true,\n cryptoCallbacks: {\n getSecretStorageKey: getSecretStorageKey,\n cacheSecretStorageKey: cacheSecretStorageKey,\n },\n verificationMethods: ['m.sas.v1'],\n });\n // await indexedDBStore.startup();\n await mxClient.initRustCrypto({\n useIndexedDB: false,\n });\n // mxClient.setGlobalErrorOnUnknownDevices(false);\n mxClient.setMaxListeners(20);\n // const filter = new Filter(userId);\n // filter.setDefinition({\n // room: {\n // state: {\n // lazy_load_members: true,\n // types: [],\n // },\n // timeline: {\n // types: [],\n // },\n // },\n // // Disable unnecessary features\n // presence: {\n // types: [], // No presence updates needed\n // },\n // account_data: {\n // types: ['m.cross_signing.master'], // No account data needed\n // },\n // });\n await mxClient.startClient({\n lazyLoadMembers: true,\n // initialSyncLimit: 1,\n includeArchivedRooms: false,\n // pollTimeout: 2 * 60 * 1000, // poll every 2 minutes\n // filter: filter,\n });\n await new Promise<void>((resolve, reject) => {\n const sync = {\n NULL: () => {\n console.info('[NULL] state');\n },\n SYNCING: () => {\n void 0;\n },\n PREPARED: () => {\n console.info(`[PREPARED] state: user ${userId}`);\n resolve();\n },\n RECONNECTING: () => {\n console.info('[RECONNECTING] state');\n },\n CATCHUP: () => {\n console.info('[CATCHUP] state');\n },\n ERROR: () => {\n reject(new Error('[ERROR] state: starting matrix client'));\n },\n STOPPED: () => {\n console.info('[STOPPED] state');\n },\n };\n mxClient.on(ClientEvent.Sync, (state) => {\n sync[state]();\n });\n });\n return mxClient;\n}\n\nexport async function logoutMatrixClient({\n mxClient,\n baseUrl,\n accessToken,\n userId,\n deviceId,\n}: {\n mxClient?: MatrixClient;\n baseUrl: string;\n accessToken: string;\n userId: string;\n deviceId: string;\n}) {\n let client = mxClient;\n if (!client) {\n client = createClient({\n baseUrl: baseUrl,\n accessToken,\n userId,\n deviceId,\n });\n }\n if (client) {\n client.stopClient();\n await client.logout().catch(console.error);\n client.clearStores();\n }\n}\n\n// =================================================================================================\n// CROSS SIGNING\n// =================================================================================================\n/**\n * Check if the user has cross-signing account data.\n * @param {MatrixClient} mxClient - The matrix client to check.\n * @returns {boolean} True if the user has cross-signing account data, otherwise false.\n */\nexport function hasCrossSigningAccountData(mxClient: MatrixClient): boolean {\n const masterKeyData = mxClient.getAccountData('m.cross_signing.master');\n console.log('hasCrossSigningAccountData::masterKeyData', masterKeyData);\n return !!masterKeyData;\n}\n\n/**\n * Setup cross signing and secret storage for the current user\n * @param {MatrixClient} mxClient - The matrix client to setup cross signing for\n * @param {string} securityPhrase - the security phrase to use for secret storage\n * @param {string} password - the password for the matrix account\n * @param {boolean} forceReset - if to force reset the cross signing keys (NB, only do if you know what you are doing!!!)\n * @param {boolean} skipBootstrapSS - if to skip bootstrapping secret storage\n * @returns {boolean} True if the cross signing was setup successfully, otherwise false.\n */\nexport async function setupCrossSigning(\n mxClient: MatrixClient,\n {\n securityPhrase,\n password,\n forceReset = false,\n skipBootstrapSecureStorage = false,\n }: { securityPhrase: string; password: string; forceReset?: boolean; skipBootstrapSecureStorage?: boolean }\n): Promise<boolean> {\n if (forceReset) {\n clearSecretStorageKeys();\n }\n\n const mxCrypto = mxClient.getCrypto() as CryptoApi;\n if (!mxCrypto) {\n throw new Error('Failed to setup matrix cross signing - failed to get matrix crypto api');\n }\n if (!skipBootstrapSecureStorage) {\n const recoveryKey = await mxCrypto.createRecoveryKeyFromPassphrase(securityPhrase);\n clearSecretStorageKeys();\n await mxCrypto.bootstrapSecretStorage({\n createSecretStorageKey: async () => recoveryKey!,\n setupNewSecretStorage: forceReset,\n });\n }\n const userId = mxClient.getUserId()!;\n await mxCrypto.bootstrapCrossSigning({\n authUploadDeviceSigningKeys: async function (makeRequest) {\n await makeRequest(getAuthId({ userId, password }));\n },\n setupNewCrossSigning: forceReset,\n });\n await mxCrypto.resetKeyBackup();\n\n await delay(300);\n\n return !!mxClient.getAccountData('m.cross_signing.master');\n}\n\n// =================================================================================================\n// GENERAL\n// =================================================================================================\n/**\n * Generates a username from an address, used for matrix login, generated an account did\n * @param {string} address - the address to generate the username from\n * @returns {string} username\n */\nexport function generateUsernameFromAddress(address: string): string {\n if (!address) {\n throw new Error('Address is required to generate matrix username');\n }\n return 'did-ixo-' + address;\n}\n\n/**\n * Generates a password from a mnemonic, used for matrix login, generated using the first 24 bytes of the base64 encoded md5 hash of the mnemonic\n * @param {string} mnemonic - the mnemonic to generate the password from\n * @returns {string} password\n */\nexport function generatePasswordFromMnemonic(mnemonic: string): string {\n const base64 = Buffer.from(md5(mnemonic.replace(/ /g, ''))).toString('base64');\n return base64.slice(0, 24);\n}\n\n/**\n * Generates a recovery phrase from a mnemonic, used for matrix recovery, generated using the first 32 bytes of the base64 encoded sha256 hash of the mnemonic\n * @param {string} mnemonic - the mnemonic to generate the recovery phrase from\n * @returns {string} recoveryPhrase\n */\nexport function generateRecoveryPhraseFromMnemonic(mnemonic: string): string {\n const hash = sha256(new TextEncoder().encode(mnemonic.replace(/ /g, '')));\n const base64 = Buffer.from(hash).toString('base64');\n return base64.slice(0, 32);\n}\n\n/**\n * Extracts the home server URL from a user ID.\n * @param {string} userId - The user ID to extract the homeserver URL from.\n * @returns {string} The homeserver URL.\n */\nexport function extractHomeServerUrlFromUserId(userId: string): string {\n const parts = userId.split(':');\n if (parts.length < 2) {\n throw new Error('Invalid userId');\n }\n return parts.slice(1).join(':');\n}\n\n/**\n * Generates a recovery phrase from a mnemonic, used for matrix recovery, generated using the first 32 bytes of the base64 encoded sha256 hash of the mnemonic\n * @param {string} mnemonic - the mnemonic to generate the recovery phrase from\n * @returns {string} passphrase\n */\nexport function generatePassphraseFromMnemonic(mnemonic: string): string {\n const hash = sha256(new TextEncoder().encode(mnemonic.replace(/ /g, '')));\n const base64 = Buffer.from(hash).toString('base64');\n return base64.slice(0, 32);\n}\n\n/**\n * Cleans a home server URL by removing protocol and trailing slashes\n * @param {string} homeServer - the homeserver URL to clean\n * @returns {string} cleaned homeserver URL\n */\nexport function cleanMatrixHomeServerUrl(homeServer: string): string {\n return homeServer.replace(/^(https?:\\/\\/)/, '').replace(/\\/$/, '');\n}\n\n/**\n * Generates a room name from an account address, used for matrix user room where user can manage their own data\n * @param {string} address - the address of the user\n * @param {string} postpend - the postpend of the room name (for testing)\n * @returns {string} roomName\n */\nexport function generateUserRoomNameFromAddress(address: string, postpend = ''): string {\n return 'did-ixo-' + address + postpend;\n}\n\n/**\n * Generates a room alias from an account address, used for matrix user room where user can manage their own data\n * @param {string} address - the address of the user\n * @param {string} postpend - the postpend of the room alias (for testing)\n * @returns {string} roomAlias\n */\nexport function generateUserRoomAliasFromAddress(address: string, homeServerUrl: string): string {\n return '#' + generateUserRoomNameFromAddress(address) + ':' + cleanMatrixHomeServerUrl(homeServerUrl);\n}\n\n/**\n * Get the base URL for a given servername.\n * @param servername The servername to get the base URL for.\n * @returns The base URL for the servername.\n */\nexport async function getBaseUrl(servername: string): Promise<string> {\n let protocol = 'https://';\n if (/^https?:\\/\\//.test(servername)) {\n protocol = '';\n }\n const serverDiscoveryUrl = `${protocol}${servername}${WELL_KNOWN_URI}`;\n try {\n const response = await fetch(serverDiscoveryUrl, { method: 'GET' });\n const result = await response.json();\n const baseUrl = (result as { 'm.homeserver': { base_url: string } })['m.homeserver']?.base_url;\n if (baseUrl === undefined) {\n throw new Error();\n }\n return baseUrl;\n } catch (e) {\n return `${protocol}${servername}`;\n }\n}\n\n/**\n * Normalize a username by removing leading '@' and trimming whitespace.\n * @param {string} rawUsername - The raw username to normalize.\n * @returns {string} The normalized username.\n */\nexport function normalizeUsername(rawUsername: string): string {\n const noLeadingAt = rawUsername.indexOf('@') === 0 ? rawUsername.substring(1) : rawUsername;\n return noLeadingAt.trim();\n}\n\n/**\n * Generates the authentication identifier for matrix login\n * @param {string} password - the password for the matrix account\n * @returns {object} authId - the authentication identifier\n */\nexport function getAuthId({ userId, password }: { userId: string; password: string }): {\n type: string;\n password: string;\n identifier: { type: string; user: string };\n} {\n return {\n type: 'm.login.password',\n password,\n identifier: {\n type: 'm.id.user',\n user: userId,\n },\n };\n}\n","const secretStorageKeys = new Map();\n\nexport function storePrivateKey(keyId: string, privateKey: Uint8Array) {\n if (privateKey instanceof Uint8Array === false) {\n throw new Error('Unable to store, privateKey is invalid.');\n }\n\n secretStorageKeys.set(keyId, privateKey);\n}\n\nexport function hasPrivateKey(keyId: string) {\n return secretStorageKeys.get(keyId) instanceof Uint8Array;\n}\n\nexport function getPrivateKey(keyId: string) {\n return secretStorageKeys.get(keyId);\n}\n\nexport function deletePrivateKey(keyId: string) {\n secretStorageKeys.delete(keyId);\n}\n\nexport function clearSecretStorageKeys() {\n secretStorageKeys.clear();\n}\n\nexport async function getSecretStorageKey({ keys }: { keys: any }): Promise<[string, Uint8Array] | null> {\n const keyIds = Object.keys(keys);\n const keyId = keyIds.find(hasPrivateKey);\n console.info('[] getSecretStorageKey', keys, keyIds, keyId);\n\n if (!keyId) {\n return null;\n }\n\n const privateKey = getPrivateKey(keyId);\n\n return [keyId, privateKey];\n}\n\nexport function cacheSecretStorageKey(keyId: string, keyInfo: any, privateKey: Uint8Array) {\n secretStorageKeys.set(keyId, privateKey);\n}\n","import { Bip39, EnglishMnemonic, Secp256k1, sha256, Slip10, Slip10Curve, stringToPath } from '@cosmjs/crypto';\nimport { AccountData, DirectSecp256k1HdWallet, OfflineSigner } from '@cosmjs/proto-signing';\nimport { createQueryClient, createSigningClient, customMessages, ixo, utils } from '@ixo/impactxclient-sdk';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { createCipheriv, randomBytes } from 'crypto';\nimport { CHAIN_RPC } from '../common';\nimport { decodeGrants, isAllowanceExpired, isAllowanceLimitReached } from './feegrant';\n/**\n * Checks if an iid document (did) exists\n * @param did - The did to check for\n * @returns True if the iid document exists, false otherwise\n */\nexport async function checkIidDocumentExists(did: string, network: NETWORK) {\n if (!network) {\n throw new Error('Network parameter is required but was undefined');\n }\n\n console.log(`🔍 Checking IID document for DID: ${did} on network: ${network}`);\n\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}. Valid networks are: ${Object.keys(CHAIN_RPC).join(', ')}`);\n }\n\n console.log(`🔗 Using RPC URL: ${url}`);\n\n try {\n const queryClient = await createQueryClient(url);\n const iidDocumentResponse = await queryClient.ixo.iid.v1beta1.iidDocument({ id: did });\n if (!iidDocumentResponse?.iidDocument?.id) {\n return false;\n }\n return true;\n } catch (error) {\n if ((error as Error).message?.includes('did document not found') || (error as Error).message?.includes('(22)')) {\n return false;\n }\n console.error('Error checking IID document:', error);\n throw error;\n }\n}\n\n/**\n * Creates an iid document (did)\n * Must be signed by base account mnemonic (not passkey signer)\n * @param did - The did to create iid document for\n * @param offlineSigner - The offline signer to use to create iid document\n */\nexport async function createIidDocument(did: string, network: NETWORK, offlineSigner: OfflineSigner) {\n try {\n const accounts = await offlineSigner.getAccounts();\n const { address, pubkey } = (accounts[0] ?? {}) as AccountData;\n const allowances = await queryAddressAllowances(address, network);\n const feegrantGranter = allowances?.length\n ? decodeGrants(allowances)?.find(\n (allowance) =>\n !!allowance &&\n !isAllowanceExpired(allowance.expiration as number) &&\n !isAllowanceLimitReached(allowance.limit)\n )?.granter\n : undefined;\n const trx = {\n typeUrl: '/ixo.iid.v1beta1.MsgCreateIidDocument',\n value: ixo.iid.v1beta1.MsgCreateIidDocument.fromPartial({\n id: did,\n verifications: customMessages.iid.createIidVerificationMethods({\n did: did,\n pubkey: pubkey,\n address: address,\n controller: did,\n type: 'secp',\n }),\n signer: address,\n controllers: [did],\n }),\n };\n // if (!feegrantGranter) {\n // throw new Error('No feegrant granter found');\n // }\n await signAndBroadcastWithMnemonic({\n offlineSigner: offlineSigner,\n messages: [trx],\n feegrantGranter: feegrantGranter as string,\n network,\n });\n } catch (error) {\n console.error(error);\n throw error;\n }\n}\n\nexport async function queryAddressAllowances(address: string, network: NETWORK) {\n try {\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}`);\n }\n const queryClient = await createQueryClient(url);\n const allowancesResponse = await queryClient.cosmos.feegrant.v1beta1.allowances({\n grantee: address,\n });\n return allowancesResponse?.allowances ?? [];\n } catch (error) {\n console.error('queryAddressAllowances::', (error as Error).message);\n return undefined;\n }\n}\n\n/**\n * Signs and broadcasts a transaction with a mnemonic\n * @param offlineSigner - The offline signer\n * @param messages - The messages to sign and broadcast\n * @param memo - The memo for the transaction\n * @param feegrantGranter - The granter for the transaction\n * @returns The deliver tx response\n */\nexport const signAndBroadcastWithMnemonic = async ({\n offlineSigner,\n messages,\n memo = 'Signing with Mnemonic Demo',\n feegrantGranter,\n network,\n}: {\n offlineSigner: OfflineSigner;\n messages: any[];\n memo?: string;\n feegrantGranter: string;\n network: NETWORK;\n}) => {\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}`);\n }\n const signingClient = await createSigningClient(url, offlineSigner);\n const accounts = await offlineSigner.getAccounts();\n const { address } = (accounts[0] ?? {}) as AccountData;\n\n const simGas = await signingClient.simulate(address, messages, memo);\n const gasUsed = simGas > 50000 ? simGas : (messages ?? []).length * 500000;\n const gas = gasUsed * 1.7;\n const gasOptions = calculateTrxGasOptions(gas);\n const fee = {\n amount: [\n {\n denom: 'uixo',\n amount: String(Math.round(gasOptions.average)),\n },\n ],\n gas: String(Math.round(gas)),\n granter: feegrantGranter,\n };\n const result = await signingClient.signAndBroadcast(address, messages, fee, memo, undefined);\n const isDeliverTxFailure = !!result.code;\n if (isDeliverTxFailure) {\n throw new Error(\n `Error when broadcasting tx ${result.transactionHash} at height ${result.height}. Code: ${result.code}; Raw log: ${result.rawLog}`\n );\n }\n};\n\nconst calculateTrxGasOptions = (gasUsed: number) => {\n const gasPriceStep = {\n low: 0.02,\n average: 0.035,\n high: 0.045,\n };\n const gas = gasUsed < 0.01 ? 0.01 : gasUsed;\n const gasOptions = {\n low: gas * gasPriceStep.low,\n average: gas * gasPriceStep.average,\n high: gas * gasPriceStep.high,\n };\n\n return gasOptions;\n};\n\nexport const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nexport function encrypt(text: string, password: string) {\n const iv = randomBytes(16);\n\n const cipher = createCipheriv('aes-256-cbc', Buffer.from(password.padEnd(32)), iv);\n let encrypted = cipher.update(text);\n encrypted = Buffer.concat([encrypted, cipher.final()]);\n return iv.toString('hex') + ':' + encrypted.toString('hex');\n}\n\nexport type SecpClient = Awaited<ReturnType<typeof getSecpClient>>;\nexport const getSecpClient = async (mnemonic: string) => {\n const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {\n prefix: 'ixo',\n });\n const account = (await wallet.getAccounts())[0];\n\n // Debug: Derive and verify keys manually for comparison\n const seed = await Bip39.mnemonicToSeed(new EnglishMnemonic(mnemonic));\n const hdPath = stringToPath(\"m/44'/118'/0'/0/0\");\n const slip10Result = Slip10.derivePath(Slip10Curve.Secp256k1, seed, hdPath);\n const privkey = slip10Result.privkey;\n // Derive the compressed public key from the private key\n const keypair = await Secp256k1.makeKeypair(privkey);\n const compressedPubkey = Secp256k1.compressPubkey(keypair.pubkey);\n // Log keys and addresses for comparison\n // console.log({\n // walletPubkey: account!.pubkey ? Buffer.from(account!.pubkey).toString('hex') : 'not available',\n // derivedPubkey: Buffer.from(compressedPubkey).toString('hex'),\n // });\n\n const secpClient = {\n mnemonic,\n did: utils.did.generateSecpDid(account!.address),\n baseAccount: account!,\n\n async getAccounts() {\n return (await wallet.getAccounts()) as AccountData[];\n },\n\n async signDirect(signerAddress: any, signDoc: any) {\n return await wallet.signDirect(signerAddress, signDoc);\n },\n\n /**\n * Sign a message with the secp256k1 private key derived from the mnemonic\n * @param message - The message to sign (usually a challenge string - base64 encoded)\n * @returns The signature as a Uint8Array\n */\n async sign(message: string): Promise<Uint8Array> {\n // Use the wallet's signDirect method to ensure consistent signing\n try {\n // Derive keypair from mnemonic directly\n const seed = await Bip39.mnemonicToSeed(new EnglishMnemonic(mnemonic));\n\n // NOTE: need to do checking here if it produces matched address to signed in one, maybe user is using a different derivation path\n // Use the standard Cosmos HD path (m/44'/118'/0'/0/0)\n const hdPath = stringToPath(\"m/44'/118'/0'/0/0\");\n\n // Derive the private key using SLIP-10\n const { privkey } = Slip10.derivePath(Slip10Curve.Secp256k1, seed, hdPath);\n\n // For the challenge (base64 encoded string), decode to get the original bytes\n const challengeBytes = new Uint8Array(Buffer.from(message, 'base64'));\n\n // Hash the challenge bytes using SHA-256\n const messageHash = sha256(challengeBytes);\n\n // Sign the hash with the derived private key\n const signature = await Secp256k1.createSignature(messageHash, privkey);\n\n // Get the fixed-length signature, which is r (32 bytes) | s (32 bytes) | recovery param (1 byte)\n const fixedLengthSignature = signature.toFixedLength();\n\n // Remove the recovery parameter byte (last byte) to get only r and s\n // This gives us exactly 64 bytes which is what the verification expects\n return fixedLengthSignature.slice(0, 64);\n } catch (error) {\n console.error('Error during signature creation:', error);\n throw error;\n }\n },\n };\n\n return secpClient;\n};\n","import { Coin, DecodeObject } from '@cosmjs/proto-signing';\nimport { createQueryClient, createRegistry, utils } from '@ixo/impactxclient-sdk';\nimport { Grant } from '@ixo/impactxclient-sdk/types/codegen/cosmos/feegrant/v1beta1/feegrant';\nimport { Timestamp } from '@ixo/impactxclient-sdk/types/codegen/google/protobuf/timestamp';\n\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { CHAIN_RPC } from '../common';\n\n/**\n * Converts a timestamp object to a timestamp\n * @param timestamp - The timestamp object to convert\n * @returns The timestamp\n */\nexport function convertTimestampObjectToTimestamp(timestamp: Timestamp): number | undefined {\n try {\n const date = utils.proto.fromTimestamp(timestamp);\n\n return date.getTime();\n } catch (error) {\n return undefined;\n }\n}\n\nexport enum FeegrantTypes {\n BASIC_ALLOWANCE = 'BasicAllowance',\n PERIODIC_ALLOWANCE = 'PeriodicAllowance',\n}\n\nexport const FEEGRANT_TYPES: Record<FeegrantTypes, string> = {\n BasicAllowance: '/cosmos.feegrant.v1beta1.BasicAllowance',\n PeriodicAllowance: '/cosmos.feegrant.v1beta1.PeriodicAllowance',\n};\n\n/**\n * Queries the address allowances from the IXO blockchain\n * @param address - The address to query allowances for\n * @returns The allowances for the address\n */\nexport async function queryAddressAllowances(address: string, network: NETWORK) {\n try {\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}`);\n }\n const queryClient = await createQueryClient(url);\n const allowancesResponse = await queryClient.cosmos.feegrant.v1beta1.allowances({\n grantee: address,\n });\n return allowancesResponse?.allowances ?? [];\n } catch (error) {\n console.error('queryAddressAllowances::', (error as Error).message);\n return undefined;\n }\n}\n\n/**\n * Checks if the address has a valid feegrant (not expired yet and limit not reached yet)\n * @param address - The address to check feegrant for\n * @returns True if the address has a valid feegrant, false otherwise\n */\nexport async function checkAddressFeegrant(address: string, network: NETWORK) {\n try {\n const allowancesResponse = await queryAddressAllowances(address, network);\n console.log('allowancesResponse', allowancesResponse);\n if (!allowancesResponse?.length) {\n return false;\n }\n const allowances = decodeGrants(allowancesResponse);\n return allowances.some(\n (allowance) =>\n !!allowance && !isAllowanceExpired(allowance.expiration as number) && !isAllowanceLimitReached(allowance.limit)\n );\n } catch (error) {\n console.error('checkAddressFeegrant::', (error as Error).message);\n throw error;\n }\n}\n\n/**\n * Decodes the grant values from the the user's list of allowances\n * @param grants - The grants to decode\n * @returns The decoded grants\n */\nexport const decodeGrants = (grants: Grant[]) => {\n const registry = createRegistry();\n\n return (grants ?? []).map((grant) => {\n const allowance = grant.allowance as DecodeObject;\n const decodedAllowance = registry.decode(allowance);\n // decodedAllowance.\n switch (allowance.typeUrl) {\n case FEEGRANT_TYPES.BasicAllowance:\n return {\n granter: grant.granter,\n grantee: grant.grantee,\n type: FEEGRANT_TYPES.BasicAllowance,\n expiration: decodedAllowance.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.expiration)\n : null,\n limit: decodedAllowance.spendLimit?.length\n ? decodedAllowance.spendLimit.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : null,\n msgs: [],\n };\n case FEEGRANT_TYPES.PeriodicAllowance:\n return {\n granter: grant.granter,\n grantee: grant.grantee,\n type: FEEGRANT_TYPES.PeriodicAllowance,\n expiration: decodedAllowance.basic?.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.basic.expiration)\n : null,\n limit: decodedAllowance?.periodCanSpend\n ? decodedAllowance?.periodCanSpend?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : decodedAllowance?.basic?.spendLimit?.length\n ? decodedAllowance?.basic?.spendLimit?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : null,\n msgs: [],\n };\n default:\n return {\n type: allowance.typeUrl,\n granter: grant.granter,\n grantee: grant.grantee,\n expiration: decodedAllowance.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.expiration)\n : decodedAllowance.basic?.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.basic.expiration)\n : null,\n limit: decodedAllowance.spendLimit?.length\n ? decodedAllowance.spendLimit.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : decodedAllowance?.periodCanSpend\n ? decodedAllowance?.periodCanSpend?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : decodedAllowance?.basic?.spendLimit?.length\n ? decodedAllowance?.basic?.spendLimit?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : null,\n msgs: decodedAllowance.allowedMessages,\n };\n }\n });\n};\n\n/**\n * Checks if the allowance has expired\n * @param expiration - The expiration of the allowance\n * @returns True if the allowance has expired, false otherwise\n */\nexport const isAllowanceExpired = (expiration: number | Timestamp) => {\n if (expiration === null || expiration === undefined) {\n return false;\n }\n const expirationTimestamp =\n typeof expiration === 'object' ? convertTimestampObjectToTimestamp(expiration) : expiration;\n if (expirationTimestamp === undefined || expirationTimestamp === null) {\n // failed to decode or convert - assume expired\n return true;\n }\n return expirationTimestamp < Date.now();\n};\n\n/**\n * Checks if the allowance limit has been reached\n * @param limit - The limit of the allowance\n * @returns True if the allowance limit has been reached, false otherwise\n */\nexport const isAllowanceLimitReached = (limit: number | string | Coin) => {\n if (limit === null || limit === undefined) {\n return false;\n }\n const limitAmount =\n typeof limit === 'object' ? Number(limit?.amount ?? 0) : typeof limit === 'string' ? Number(limit ?? 0) : limit;\n return limitAmount <= 0.0005;\n};\n","import { createMatrixApiClient, utils as mxUtils } from '@ixo/matrixclient-sdk';\nimport { UploadContentType } from '@ixo/matrixclient-sdk/types/api/media/v1beta1';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { MatrixHomeServerUrl } from '../common';\nimport { createCIDFromBase64, jsonToBase64 } from '../createCIDFromBase64';\nimport { RuntimeConfig } from '../runtime-config';\nimport { Wallet } from '../wallet';\n\nexport const publicUpload = async ({\n data,\n fileName,\n config,\n wallet,\n}: {\n data: object;\n fileName: string;\n config: RuntimeConfig;\n wallet: Wallet;\n}) => {\n const matrixAPIClient = createMatrixApiClient({\n homeServerUrl: MatrixHomeServerUrl[(config.getValue('network') as NETWORK) ?? 'devnet'],\n accessToken: wallet?.matrix?.accessToken ?? '',\n });\n\n // Create a simple Buffer instead of using File - this works reliably with node-fetch\n const fileContent = JSON.stringify(data);\n const fileBuffer = Buffer.from(fileContent, 'utf8');\n const fullFileName = fileName + '.json';\n const contentType = 'application/ld+json';\n\n // Pass the buffer directly - node-fetch can handle this reliably in all environments\n const response = await matrixAPIClient.media.v1beta1.upload(\n fullFileName,\n contentType as UploadContentType,\n fileBuffer\n );\n const httpUrl = mxUtils.mxc.mxcUrlToHttp(\n MatrixHomeServerUrl[(config.getValue('network') as NETWORK) ?? 'devnet'], // homeServerUrl\n response.content_uri // the mxc url\n );\n\n if (!httpUrl) {\n throw new Error('Failed to upload file to Matrix');\n }\n\n const jsonString = JSON.stringify(data);\n const base64String = jsonToBase64(jsonString);\n const cid = await createCIDFromBase64(base64String);\n\n return {\n encrypted: 'false',\n cid,\n proof: cid,\n serviceEndpoint: httpUrl,\n mxc: response.content_uri,\n };\n};\n","import { CID } from 'multiformats';\nimport { base64 } from 'multiformats/bases/base64';\nimport * as mfsha2 from 'multiformats/hashes/sha2';\n\nexport async function createCIDFromBase64(base64String: string): Promise<string> {\n // Add 'm' prefix if not present\n const multibaseString = base64String.startsWith('m') ? base64String : 'm' + base64String;\n\n // Decode base64 to bytes\n const bytes = base64.decode(multibaseString);\n\n // Create SHA-256 hash of the bytes\n const hash = await mfsha2.sha256.digest(bytes);\n\n // Create CID (using SHA-256 and RAW codec)\n const cid = CID.create(1, 0x55, hash);\n\n return cid.toString();\n}\n\nexport function jsonToBase64(jsonString: string): string {\n const uint8Array = new TextEncoder().encode(jsonString);\n return btoa(String.fromCharCode(...Array.from(uint8Array)));\n}\n","import * as p from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport { registerUserSimplified } from '../utils/account/simplifiedRegistration';\nimport { checkRequiredString, selectNetwork } from '../utils/common';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\n\nexport class CreateUserCommand implements Command {\n name = 'create-user';\n description = 'Create a new user';\n constructor(private wallet: Wallet, private config: RuntimeConfig) {}\n async execute(): Promise<CLIResult> {\n const network = this.config.getValue('network') as NETWORK;\n if (!network) {\n await selectNetwork(this.config);\n }\n const pin = await p.text({\n message: 'Enter your PIN',\n initialValue: '',\n validate(value) {\n return checkRequiredString(value, 'PIN is required');\n },\n });\n if (p.isCancel(pin)) {\n p.log.error('User cancelled');\n process.exit(1);\n }\n const oracleName = await p.text({\n message: 'Enter your oracle name',\n initialValue: 'My oracle',\n validate(value) {\n return checkRequiredString(value, 'Oracle name is required');\n },\n });\n if (p.isCancel(oracleName)) {\n p.log.error('User cancelled');\n process.exit(1);\n }\n const user = await registerUserSimplified(\n {\n pin,\n oracleName,\n network,\n oracleAvatarUrl: `https://api.dicebear.com/8.x/bottts/svg?seed=${oracleName}`,\n },\n async (address) => {\n await this.wallet.sendTokens(address, 150_000); // 150,000 uixo = 0.15 IXO;\n }\n );\n return { success: true, data: user };\n }\n}\n","import { CLIResult } from '../types';\nimport { Command, CommandRegistry } from './index';\n\nexport class HelpCommand implements Command {\n name = 'help';\n description = 'Show help information and available commands';\n\n constructor(private registry: CommandRegistry) {}\n\n async execute(): Promise<CLIResult> {\n const commands = this.registry.getAll();\n\n const helpText = `\nIXO Oracles CLI - Help\n\nUSAGE:\n oracles-cli [command] [options]\n\nCOMMANDS:\n${commands.map((cmd) => ` ${cmd.name.padEnd(15)} ${cmd.description}`).join('\\n')}\n\nEXAMPLES:\n oracles-cli --init Initialize a new IXO Oracle project\n oracles-cli Launch interactive menu\n oracles-cli help Show this help message\n\nOPTIONS:\n --init Initialize a new project (shortcut)\n --help, -h Show help information\n\nFor more information, visit: https://github.com/ixoworld/ixo-oracles-cli\n`;\n\n return {\n success: true,\n data: helpText,\n };\n }\n}\n","import * as p from '@clack/prompts';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport simpleGit from 'simple-git';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport { createProjectEnvFile } from '../utils/create-project-env-file';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\nimport { CreateEntityCommand } from './create-entity-command';\n\nexport class InitCommand implements Command {\n name = 'init';\n description = 'Initialize Project';\n\n constructor(private readonly config: RuntimeConfig, private readonly wallet: Wallet) {}\n\n private async getProjectInput(): Promise<{ projectPath: string; projectName: string }> {\n // Get the input from user (could be path, name, or both)\n const input = await p.text({\n message: 'What is your project named?',\n placeholder: 'my-ixo-project',\n validate(value) {\n if (!value) {\n return 'Project name is required';\n }\n return undefined;\n },\n });\n\n if (p.isCancel(input)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n // Parse the input to determine if it's a path, name, or both\n const inputStr = String(input);\n let projectPath: string;\n let projectName: string;\n\n // Check if input contains path separators (is a path)\n if (inputStr.includes('/') || inputStr.includes('\\\\')) {\n // Input is a path\n projectPath = inputStr;\n projectName = path.basename(inputStr);\n } else {\n // Input is just a name, create in current directory\n projectName = inputStr;\n projectPath = path.join(process.cwd(), projectName);\n }\n\n // Ensure the project name is valid\n if (!this.isValidProjectName(projectName)) {\n p.note('Invalid project name. Using a valid name instead.', 'Warning');\n projectName = this.sanitizeProjectName(projectName);\n projectPath = path.join(path.dirname(projectPath), projectName);\n }\n\n return { projectPath, projectName };\n }\n\n private isValidProjectName(name: string): boolean {\n // Check if name is valid (no special characters, starts with letter, etc.)\n const validNameRegex = /^[a-zA-Z][a-zA-Z0-9-_]*$/;\n return validNameRegex.test(name) && name.length > 0 && name.length <= 50;\n }\n\n private sanitizeProjectName(name: string): string {\n // Convert invalid characters to valid ones\n return name\n .replace(/[^a-zA-Z0-9-_]/g, '-')\n .replace(/^-+|-+$/g, '') // Remove leading/trailing dashes\n .toLowerCase()\n .substring(0, 50);\n }\n\n private async confirmProjectCreation(projectPath: string, projectName: string): Promise<boolean> {\n const isDirExists = existsSync(projectPath);\n\n if (isDirExists) {\n const overwrite = await p.confirm({\n message: `Directory \"${projectPath}\" already exists. Do you want to overwrite it?`,\n initialValue: false,\n });\n\n if (p.isCancel(overwrite)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n return overwrite;\n }\n\n // Show confirmation for new project\n const confirm = await p.confirm({\n message: `Create IXO project \"${projectName}\" in \"${projectPath}\"?`,\n initialValue: true,\n });\n\n if (p.isCancel(confirm)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n return confirm;\n }\n\n private async selectRepo() {\n const repo = await p.select({\n message: 'Select a template to clone',\n options: [\n {\n value: 'git@github.com:ixoworld/ixo-oracles-boilerplate.git',\n label: 'IXO Oracles (Default)',\n },\n {\n label: 'Custom template',\n value: 'custom',\n },\n ],\n });\n\n if (p.isCancel(repo)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n if (repo === 'custom') {\n const customRepo = await p.text({\n message: 'Enter the custom template URL',\n });\n\n if (p.isCancel(customRepo)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n return customRepo;\n }\n\n return repo;\n }\n\n private async cloneRepo(repo: string, projectPath: string, shouldOverwrite: boolean = false) {\n const git = simpleGit();\n const cloneSpinner = p.spinner();\n\n try {\n cloneSpinner.start('Cloning repository...');\n\n // If overwriting, remove the existing directory first\n if (shouldOverwrite && existsSync(projectPath)) {\n const { rmSync } = await import('fs');\n rmSync(projectPath, { recursive: true, force: true });\n }\n\n // Create directory if it doesn't exist\n\n await git.clone(repo, projectPath);\n\n // Clean repo and create new git\n const gitFolder = path.join(projectPath, '.git');\n if (existsSync(gitFolder)) {\n const { rmSync } = await import('fs');\n rmSync(gitFolder, { recursive: true, force: true });\n }\n await simpleGit(projectPath).init();\n\n cloneSpinner.stop('Repository cloned successfully');\n\n p.log.info('Creating Oracle Entity and Matrix Account');\n const command = new CreateEntityCommand(this.wallet, this.config);\n const result = await command.execute();\n if (result.success) {\n p.log.info('Oracle Entity and Matrix Account created successfully');\n } else {\n p.log.error('Failed to create Oracle Entity and Matrix Account');\n }\n\n await createProjectEnvFile(this.config);\n // Show success message with next steps\n p.log.success(\n `\\n✅ IXO project created successfully!\\n\\n` +\n `📁 Location: ${projectPath}\\n` +\n `🚀 Next steps:\\n` +\n ` cd ${path.basename(projectPath)}\\n` +\n ` pnpm install\\n` +\n ` pnpm build \\n` +\n ` cd apps/app\\n` +\n ` pnpm start:dev`\n );\n } catch (error) {\n cloneSpinner.stop('Failed to clone repository');\n throw error;\n }\n }\n\n async execute(): Promise<CLIResult> {\n try {\n // Get project input (path and/or name)\n const { projectPath, projectName } = await this.getProjectInput();\n\n // Confirm project creation\n const shouldProceed = await this.confirmProjectCreation(projectPath, projectName);\n\n if (!shouldProceed) {\n return { success: false, data: 'Project creation cancelled' };\n }\n\n // Store in config\n this.config.addValue('projectPath', projectPath);\n this.config.addValue('projectName', projectName);\n\n // Select repository template\n const repo = await this.selectRepo();\n this.config.addValue('repo', repo);\n\n // Check if we need to overwrite\n const shouldOverwrite = existsSync(projectPath);\n\n // Clone the repository\n await this.cloneRepo(repo, projectPath, shouldOverwrite);\n\n return {\n success: true,\n data: `Project \"${projectName}\" created successfully in \"${projectPath}\"`,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { mxLogin } from './account/matrix';\nimport { MatrixHomeServerUrl } from './common';\nimport { RuntimeConfig } from './runtime-config';\nexport const createProjectEnvFile = async (config: RuntimeConfig) => {\n const freshMx = await mxLogin({\n homeServerUrl: MatrixHomeServerUrl[config.getOrThrow('network')],\n username: config.getOrThrow('registerUserResult').matrixUserId,\n password: config.getOrThrow('registerUserResult').matrixPassword,\n deviceName: config.getOrThrow('registerUserResult').matrixDeviceName,\n });\n const network = config.getOrThrow('network');\n const projectPath = config.getOrThrow('projectPath');\n const envFile = path.join(projectPath, 'apps', 'app', '.env');\n\n console.log('Creating .env file at:', envFile);\n console.log('Project path:', projectPath);\n\n // Ensure the directory exists\n const envDir = path.dirname(envFile);\n if (!fs.existsSync(envDir)) {\n console.log('Creating directory:', envDir);\n fs.mkdirSync(envDir, { recursive: true });\n }\n const envContent = `\nPORT=4000 \nORACLE_NAME=${config.getValue('projectName')}\n\n# Matrix\nMATRIX_BASE_URL=${MatrixHomeServerUrl[network]}\nMATRIX_ORACLE_ADMIN_ACCESS_TOKEN=${freshMx.accessToken}\nMATRIX_ORACLE_ADMIN_PASSWORD=${config.getOrThrow('registerUserResult').matrixPassword}\nMATRIX_ORACLE_ADMIN_USER_ID=${config.getOrThrow('registerUserResult').matrixUserId}\nMATRIX_RECOVERY_PHRASE=${config.getOrThrow('registerUserResult').matrixRecoveryPhrase}\n\n# OPENAI\nOPENAI_API_KEY=\n\n# Langfuse\nLANGFUSE_PUBLIC_KEY=\nLANGFUSE_SECRET_KEY=\nLANGFUSE_HOST=https://cloud.langfuse.com\n\nOPEN_ROUTER_API_KEY=\"sk-\"\n\n\n### NOT REQUIRED FOR THE APP BUT SAVE THEM IN SAFE PLACE\n# ORACLE ACCOUNT DETAILS\nORACLE_ADDRESS=${config.getOrThrow('registerUserResult').address}\nORACLE_DID=${config.getOrThrow('registerUserResult').did}\nORACLE_MNEMONIC=${config.getOrThrow('registerUserResult').mnemonic}\nMATRIX_VAULT_PIN=${config.getOrThrow('registerUserResult').pin}\nENTITY_DID=${config.getOrThrow('entityDid')}\n`;\n try {\n fs.writeFileSync(envFile, envContent);\n console.log('✅ .env file created successfully at:', envFile);\n } catch (error) {\n console.error('❌ Failed to create .env file:', error);\n throw error;\n }\n};\n","import { confirm } from '@clack/prompts';\nimport { CLIResult } from '../types';\nimport { Wallet } from '../utils/wallet';\nimport { Command } from './index';\n\nexport class LogoutCommand implements Command {\n name = 'logout';\n description = 'Logout command';\n\n constructor(private wallet: Wallet) {}\n\n async execute(): Promise<CLIResult> {\n const shouldClear = await confirm({\n message: 'Are you sure you want to logout?',\n initialValue: false,\n });\n if (shouldClear) {\n await this.wallet.clearWallet();\n return {\n success: true,\n data: 'Logged out successfully',\n };\n }\n return {\n success: false,\n error: 'Logout cancelled',\n };\n }\n}\n","'use server';\nimport { toHex } from '@cosmjs/encoding';\nimport { EncodeObject } from '@cosmjs/proto-signing';\nimport { createRegistry } from '@ixo/impactxclient-sdk';\nimport {\n SignX as IxoSignX,\n SIGN_X_LOGIN_ERROR,\n SIGN_X_LOGIN_SUCCESS,\n SIGN_X_TRANSACT_ERROR,\n SIGN_X_TRANSACT_SUCCESS,\n} from '@ixo/signx-sdk';\nimport { LOGIN_DATA } from '@ixo/signx-sdk/types/types/transact';\nimport qrcode from 'qrcode-terminal';\nimport { WalletProps } from './types';\n\nconst SignXEndpoints = {\n devnet: 'https://signx.devnet.ixo.earth',\n testnet: 'https://signx.testnet.ixo.earth',\n mainnet: 'https://signx.ixo.earth',\n};\n\nexport class SignXClient {\n private readonly signXClient: IxoSignX;\n private _loginData?: LOGIN_DATA;\n public get loginData() {\n return this._loginData;\n }\n\n static loadFromWallet(wallet: WalletProps) {\n return new IxoSignX({\n endpoint: SignXEndpoints[wallet.network],\n sitename: 'IXO Oracles CLI',\n network: wallet.network,\n });\n }\n\n constructor(chainNetwork: keyof typeof SignXEndpoints) {\n this.signXClient = new IxoSignX({\n endpoint: SignXEndpoints[chainNetwork],\n sitename: 'IXO Oracles CLI',\n network: chainNetwork,\n });\n }\n\n async login() {\n const loginData = await this.signXClient.login({ pollingInterval: 2000, matrix: true });\n this._loginData = loginData;\n return loginData;\n }\n\n private displayStyledQRCode(qrCodeData: string | LOGIN_DATA, title: string) {\n const qrCodeStr = typeof qrCodeData === 'string' ? qrCodeData : JSON.stringify(qrCodeData);\n\n // Display title with emoji\n console.log('\\n' + ' '.repeat(5) + '🔐 ' + title);\n console.log(' '.repeat(5) + '📱 Scan with IXO app');\n console.log(' '.repeat(5) + '━'.repeat(30));\n\n // Generate very compact QR code\n qrcode.generate(qrCodeStr, {\n small: true,\n });\n console.log(' '.repeat(5) + '⏳ Waiting...\\n');\n }\n\n public displayQRCode(qrCodeData: string | LOGIN_DATA) {\n this.displayStyledQRCode(qrCodeData, 'Login with SignX');\n }\n\n async awaitLogin() {\n return new Promise<WalletProps>((resolve, reject) => {\n try {\n this.signXClient.on(SIGN_X_LOGIN_SUCCESS, (response: { data: WalletProps }) => {\n if (!response.data) {\n reject(new Error('Login failed'));\n return;\n }\n if (!response.data.matrix) {\n reject(new Error('Matrix login failed'));\n return;\n }\n resolve(response.data); // Resolve the promise with the login success data\n });\n\n this.signXClient.on(SIGN_X_LOGIN_ERROR, (error) => {\n console.log('Login error:', error);\n reject(error); // Reject the promise with the login error\n });\n\n // Use loginRequest data to show QR code to user for scanning by mobile app\n } catch (error) {\n console.error('Error in connecting:', error);\n reject(error); // Reject the promise with any other errors\n }\n });\n }\n\n async transact(messages: readonly EncodeObject[], wallet: WalletProps, memo?: string) {\n const registry = createRegistry();\n\n return this.signXClient.transact({\n address: wallet.address,\n did: wallet.did,\n pubkey: wallet.pubKey,\n timestamp: new Date().toISOString(),\n transactions: [\n {\n sequence: 1,\n txBodyHex: toHex(registry.encodeTxBody({ messages: messages, memo: memo || '' })),\n },\n ],\n });\n }\n\n async awaitTransaction() {\n return new Promise((resolve, reject) => {\n try {\n this.signXClient.on(SIGN_X_TRANSACT_SUCCESS, (result) => {\n resolve(result.data); // Resolve the promise with the login success data\n });\n\n this.signXClient.on(SIGN_X_TRANSACT_ERROR, (error) => {\n reject(error); // Reject the promise with the login error\n });\n // Use loginRequest data to show QR code to user for scanning by mobile app\n } catch (error) {\n console.error('Error in connecting:', error);\n reject(error); // Reject the promise with any other errors\n }\n });\n }\n\n async pollNextTransaction() {\n return this.signXClient.pollNextTransaction();\n }\n\n displayTransactionQRCode(qrCodeData: string) {\n this.displayStyledQRCode(qrCodeData, 'SIGNX TRANSACTION');\n }\n}\n","import { CLIResult } from '../types';\nimport { selectNetwork } from '../utils/common';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { SignXClient } from '../utils/signx/signx';\nimport { Wallet } from '../utils/wallet';\nimport { Command } from './index';\n\nexport class SignXLoginCommand implements Command {\n name = 'signx-login';\n description = 'Login with SignX wallet';\n\n constructor(private wallet: Wallet, private config: RuntimeConfig) {}\n\n async execute(): Promise<CLIResult> {\n try {\n // Select network and create SignX client\n const network = await selectNetwork(this.config);\n const signXClient = new SignXClient(network);\n\n // Start login process\n const loginData = await signXClient.login();\n\n // Display QR code for user to scan\n signXClient.displayQRCode(loginData);\n\n // Wait for login completion\n const loginResult = await signXClient.awaitLogin();\n this.wallet.setWallet(loginResult);\n this.wallet.setSignXClient(signXClient);\n return {\n success: true,\n data: {\n message: 'Successfully logged in with SignX!',\n wallet: {\n address: loginResult.address,\n did: loginResult.did,\n name: loginResult.name,\n },\n },\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? `SignX login failed: ${error.message}` : 'Unknown error',\n };\n }\n }\n}\n","export class CLIError extends Error {\n constructor(message: string, public code: string = 'CLI_ERROR', public suggestions?: string[]) {\n super(message);\n this.name = 'CLIError';\n }\n}\n\nexport class ConfigError extends CLIError {\n constructor(message: string, suggestions?: string[]) {\n super(message, 'CONFIG_ERROR', suggestions);\n this.name = 'ConfigError';\n }\n}\n\nexport class NetworkError extends CLIError {\n constructor(message: string, suggestions?: string[]) {\n super(message, 'NETWORK_ERROR', suggestions);\n this.name = 'NetworkError';\n }\n}\n\nexport class ValidationError extends CLIError {\n constructor(message: string, suggestions?: string[]) {\n super(message, 'VALIDATION_ERROR', suggestions);\n this.name = 'ValidationError';\n }\n}\n\nexport function handleError(error: unknown): never {\n if (error instanceof CLIError) {\n console.error(`\\n❌ ${error.name}: ${error.message}`);\n if (error.suggestions?.length) {\n console.error('\\nSuggestions:');\n error.suggestions.forEach((suggestion) => console.error(` • ${suggestion}`));\n }\n process.exit(1);\n }\n\n if (error instanceof Error) {\n console.error(`\\n❌ Unexpected Error: ${error.message}`);\n if (error.stack) {\n console.error('\\nStack trace:');\n console.error(error.stack);\n }\n process.exit(1);\n }\n\n console.error('\\n❌ Unknown error occurred');\n process.exit(1);\n}\n","import { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { SimplifiedRegistrationResult } from './account/simplifiedRegistration';\n\ninterface Config {\n authZFile: string;\n feesFile: string;\n projectPath: string;\n projectName: string;\n entityDid: string;\n network: NETWORK;\n repo: string;\n registerUserResult: SimplifiedRegistrationResult & {\n matrixDeviceName: string;\n };\n}\n\nexport class RuntimeConfig {\n private config: Partial<Config> = {};\n private static instance: RuntimeConfig;\n private constructor() {}\n\n public static getInstance(): RuntimeConfig {\n if (!RuntimeConfig.instance) {\n RuntimeConfig.instance = new RuntimeConfig();\n }\n return RuntimeConfig.instance;\n }\n\n public addValue<K extends keyof Config>(key: K, value: Config[K]) {\n this.config[key] = value;\n }\n\n public getValue(key: keyof Config) {\n return this.config[key];\n }\n\n public getOrThrow<K extends keyof Config>(key: K): Config[K] {\n const value = this.getValue(key);\n if (!value) {\n throw new Error(`Value ${key} is not set`);\n }\n return value as Config[K];\n }\n\n public getConfig() {\n return this.config;\n }\n\n public deleteValue(key: keyof Config) {\n delete this.config[key];\n }\n}\n","import { cosmos } from '@ixo/impactxclient-sdk';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { unlink } from 'fs/promises';\nimport os from 'os';\nimport path from 'path';\nimport { SignXClient } from './signx/signx';\nimport { WalletProps } from './signx/types';\n\n// Use hidden .wallet.json file in user's home directory\nconst WALLET_PATH = path.join(os.homedir(), '.wallet.json');\n\n// for dev make it here\n// const WALLET_PATH = path.join(__dirname, '.wallet.json');\n\nexport class Wallet {\n public wallet: WalletProps | undefined;\n public signXClient?: SignXClient;\n\n constructor() {\n this.loadWallet();\n }\n\n public setSignXClient(signXClient: SignXClient) {\n this.signXClient = signXClient;\n }\n\n private loadWallet() {\n if (existsSync(WALLET_PATH)) {\n try {\n const walletData = readFileSync(WALLET_PATH, 'utf8');\n this.wallet = JSON.parse(walletData) as WalletProps;\n // set signx client\n this.setSignXClient(new SignXClient(this.wallet.network ?? 'devnet'));\n console.log('Wallet loaded successfully');\n } catch (error) {\n console.warn('Failed to load wallet file:', error);\n this.wallet = undefined;\n }\n } else {\n console.log('No wallet file found');\n }\n }\n\n setWallet(wallet: WalletProps) {\n try {\n this.wallet = wallet;\n const walletJson = JSON.stringify(wallet, null, 2);\n writeFileSync(WALLET_PATH, walletJson, 'utf8');\n console.log('Wallet saved successfully to:', WALLET_PATH);\n } catch (error) {\n console.error('Failed to save wallet:', error);\n throw new Error('Failed to save wallet file');\n }\n }\n\n public checkWalletExists() {\n return existsSync(WALLET_PATH) && this.wallet !== undefined;\n }\n\n public async clearWallet() {\n this.wallet = undefined;\n try {\n if (existsSync(WALLET_PATH)) {\n await unlink(WALLET_PATH);\n console.log('Wallet file deleted successfully');\n }\n } catch (error) {\n console.error('Failed to delete wallet file:', error);\n }\n }\n\n get did() {\n return this.wallet?.did;\n }\n\n get address() {\n return this.wallet?.address;\n }\n\n get name() {\n return this.wallet?.name;\n }\n\n get pubKey() {\n return this.wallet?.pubKey;\n }\n\n get algo() {\n return this.wallet?.algo;\n }\n\n get matrix() {\n return this.wallet?.matrix;\n }\n\n public reloadWallet() {\n this.loadWallet();\n }\n\n async sendTokens(address: string, amount: number) {\n if (!this.address || !this.signXClient || !this.wallet) {\n throw new Error('Wallet not loaded');\n }\n const sendTokensToUserMsg = {\n typeUrl: '/cosmos.bank.v1beta1.MsgSend',\n value: cosmos.bank.v1beta1.MsgSend.fromPartial({\n fromAddress: this.address,\n toAddress: address,\n amount: [\n cosmos.base.v1beta1.Coin.fromPartial({\n amount: amount.toString(),\n denom: 'uixo',\n }),\n ],\n }),\n };\n const tx = await this.signXClient?.transact([sendTokensToUserMsg], this.wallet);\n this.signXClient?.displayTransactionQRCode(JSON.stringify(tx));\n await this.signXClient?.pollNextTransaction();\n const response = await this.signXClient?.awaitTransaction();\n return response;\n }\n}\n"],"mappings":"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","names":["cancel","intro","isCancel","log","outro","select","spinner","process","CommandRegistry","command","name","cmd","p","select","z","selectNetwork","config","network","RELAYER_NODE_DID","MatrixHomeServerUrl","MatrixRoomBotServerUrl","PORTAL_URL","CHAIN_RPC","checkRequiredString","value","message","result","z","checkRequiredURL","checkRequiredNumber","isCancel","log","spinner","text","customMessages","ixo","utils","utils","createMatrixApiClient","sha256","eciesEncrypt","ClientEvent","createClient","md5","secretStorageKeys","hasPrivateKey","keyId","secretStorageKeys","getPrivateKey","clearSecretStorageKeys","secretStorageKeys","getSecretStorageKey","keys","keyIds","keyId","hasPrivateKey","privateKey","getPrivateKey","cacheSecretStorageKey","keyInfo","Bip39","EnglishMnemonic","Secp256k1","sha256","Slip10","Slip10Curve","stringToPath","DirectSecp256k1HdWallet","createQueryClient","createSigningClient","customMessages","ixo","utils","createCipheriv","randomBytes","createQueryClient","createRegistry","utils","convertTimestampObjectToTimestamp","timestamp","utils","FEEGRANT_TYPES","decodeGrants","grants","registry","createRegistry","grant","allowance","decodedAllowance","FEEGRANT_TYPES","convertTimestampObjectToTimestamp","limit","isAllowanceExpired","expiration","expirationTimestamp","isAllowanceLimitReached","checkIidDocumentExists","did","network","url","CHAIN_RPC","createQueryClient","error","createIidDocument","offlineSigner","accounts","address","pubkey","allowances","queryAddressAllowances","feegrantGranter","decodeGrants","allowance","isAllowanceExpired","isAllowanceLimitReached","trx","ixo","customMessages","signAndBroadcastWithMnemonic","messages","memo","signingClient","createSigningClient","simGas","gas","gasOptions","calculateTrxGasOptions","fee","result","gasUsed","gasPriceStep","delay","ms","resolve","encrypt","text","password","iv","randomBytes","cipher","createCipheriv","encrypted","getSecpClient","mnemonic","wallet","DirectSecp256k1HdWallet","account","seed","Bip39","EnglishMnemonic","hdPath","stringToPath","privkey","Slip10","Slip10Curve","keypair","Secp256k1","compressedPubkey","utils","signerAddress","signDoc","message","challengeBytes","messageHash","sha256","WELL_KNOWN_URI","mxLogin","homeServerUrl","username","password","deviceName","localMatrix","mxHomeServerUrl","mxUsername","mxIdMatch","getBaseUrl","client","createTemporaryClient","response","normalizeUsername","error","msg","getPublicKeyForEncryption","network","MatrixRoomBotServerUrl","createUserCreationChallenge","address","challenge","challengeBase64","encryptPasswordWithECIES","publicKey","publicKeyBytes","passwordBytes","encryptedPassword","eciesEncrypt","byte","createUserAccountWithSecp","address","password","signature","challenge","network","publicKeyInfo","getPublicKeyForEncryption","encryptedPassword","encryptPasswordWithECIES","request","response","MatrixRoomBotServerUrl","errorData","mxRegisterWithSecp","address","password","deviceName","wallet","network","challengeBase64","createUserCreationChallenge","signatureBytes","signature","createUserAccountWithSecp","homeServerUrl","MatrixHomeServerUrl","username","generateUsernameFromAddress","mxLogin","error","checkIsUsernameAvailable","homeServerUrl","username","client","createTemporaryClient","createClient","createMatrixClient","accessToken","userId","deviceId","mxClient","getSecretStorageKey","cacheSecretStorageKey","resolve","reject","sync","ClientEvent","state","logoutMatrixClient","baseUrl","hasCrossSigningAccountData","masterKeyData","setupCrossSigning","securityPhrase","password","forceReset","skipBootstrapSecureStorage","clearSecretStorageKeys","mxCrypto","recoveryKey","makeRequest","getAuthId","delay","generateUsernameFromAddress","address","generatePasswordFromMnemonic","mnemonic","md5","generatePassphraseFromMnemonic","mnemonic","hash","sha256","cleanMatrixHomeServerUrl","homeServer","generateUserRoomNameFromAddress","address","postpend","generateUserRoomAliasFromAddress","homeServerUrl","getBaseUrl","servername","protocol","serverDiscoveryUrl","WELL_KNOWN_URI","baseUrl","normalizeUsername","rawUsername","getAuthId","userId","password","DEVICE_NAME","registerUserSimplified","pin","oracleName","network","oracleAvatarUrl","transferTokens","mnemonic","utils","wallet","getSecpClient","address","did","didExists","checkIidDocumentExists","createIidDocument","delay","mxMnemonic","homeServerUrl","MatrixHomeServerUrl","mxUsername","generateUsernameFromAddress","mxPassword","generatePasswordFromMnemonic","mxPassphrase","generatePassphraseFromMnemonic","checkIsUsernameAvailable","account","mxRegisterWithSecp","mxClient","createMatrixClient","error","matrixApiClient","createMatrixApiClient","hasCrossSigning","hasCrossSigningAccountData","setupCrossSigning","mxRoomAlias","generateUserRoomAliasFromAddress","roomId","response","MatrixRoomBotServerUrl","joinedMembers","joined","encryptedMnemonic","encrypt","storeEncryptedMnemonicResponse","logoutMatrixClient","createMatrixApiClient","mxUtils","CID","base64","mfsha2","createCIDFromBase64","base64String","multibaseString","bytes","hash","jsonToBase64","jsonString","uint8Array","publicUpload","data","fileName","config","wallet","matrixAPIClient","createMatrixApiClient","MatrixHomeServerUrl","fileContent","fileBuffer","fullFileName","response","httpUrl","mxUtils","jsonString","base64String","jsonToBase64","cid","createCIDFromBase64","CreateEntity","wallet","config","customMessages","ixo","RELAYER_NODE_DID","utils","oracleAccountAddress","linkedAccounts","account","oracleName","entityDid","response","publicUpload","price","walletAddress","linkedResourcesMsgs","resource","log","tx","content","title","pageResource","orgName","name","logo","coverImage","location","description","profileResource","services","service","parentProtocol","params","msg","pin","text","value","checkRequiredString","isCancel","registerResult","registerUserSimplified","address","did","s","spinner","key","CreateEntityCommand","wallet","config","CreateEntity","selectNetwork","results","value","checkRequiredString","checkRequiredNumber","checkRequiredURL","did","portalUrl","PORTAL_URL","p","CreateUserCommand","wallet","config","network","selectNetwork","pin","value","checkRequiredString","oracleName","registerUserSimplified","address","HelpCommand","registry","cmd","p","existsSync","path","simpleGit","fs","path","createProjectEnvFile","config","freshMx","mxLogin","MatrixHomeServerUrl","network","projectPath","envFile","path","envDir","fs","envContent","error","InitCommand","config","wallet","input","value","inputStr","projectPath","projectName","path","name","existsSync","overwrite","confirm","repo","customRepo","shouldOverwrite","git","simpleGit","cloneSpinner","rmSync","gitFolder","CreateEntityCommand","createProjectEnvFile","error","confirm","LogoutCommand","wallet","toHex","createRegistry","IxoSignX","SIGN_X_LOGIN_ERROR","SIGN_X_LOGIN_SUCCESS","SIGN_X_TRANSACT_ERROR","SIGN_X_TRANSACT_SUCCESS","qrcode","SignXEndpoints","SignXClient","wallet","chainNetwork","loginData","qrCodeData","title","qrCodeStr","resolve","reject","response","error","messages","memo","registry","result","SignXLoginCommand","wallet","config","network","selectNetwork","signXClient","SignXClient","loginData","loginResult","error","CLIError","message","code","suggestions","handleError","error","CLIError","suggestion","RuntimeConfig","_RuntimeConfig","key","value","cosmos","existsSync","readFileSync","writeFileSync","unlink","os","path","WALLET_PATH","path","os","Wallet","signXClient","existsSync","walletData","readFileSync","SignXClient","error","wallet","walletJson","writeFileSync","unlink","address","amount","sendTokensToUserMsg","cosmos","tx","CLIManager","CommandRegistry","RuntimeConfig","Wallet","InitCommand","CreateEntityCommand","CreateUserCommand","LogoutCommand","HelpCommand","result","login","select","isCancel","cancel","process","SignXLoginCommand","log","commandName","command","s","spinner","intro","action","args","userArgs","error","handleError","outro","cli"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/index.ts","../src/commands/create-entity-command.ts","../src/utils/common.ts","../src/utils/entity.ts","../src/utils/account/matrix.ts","../src/utils/account/secretStorageKeys.ts","../src/utils/account/utils.ts","../src/utils/account/feegrant.ts","../src/utils/account/simplifiedRegistration.ts","../src/utils/matrix/upload-to-matrix.ts","../src/utils/createCIDFromBase64.ts","../src/commands/create-user-command.ts","../src/commands/help.command.ts","../src/commands/init.command.ts","../src/utils/create-project-env-file.ts","../src/commands/logout.commands.ts","../src/utils/signx/signx.ts","../src/commands/signX.commands.ts","../src/commands/update-entity-command.ts","../src/utils/errors.ts","../src/utils/runtime-config.ts","../src/utils/wallet.ts"],"sourcesContent":["import { cancel, intro, isCancel, log, outro, select, spinner } from '@clack/prompts';\nimport process from 'node:process';\nimport { CommandRegistry } from './commands';\nimport { CreateEntityCommand } from './commands/create-entity-command';\nimport { CreateUserCommand } from './commands/create-user-command';\nimport { HelpCommand } from './commands/help.command';\nimport { InitCommand } from './commands/init.command';\nimport { LogoutCommand } from './commands/logout.commands';\nimport { SignXLoginCommand } from './commands/signX.commands';\nimport { UpdateEntityCommand } from './commands/update-entity-command';\nimport { handleError } from './utils/errors';\nimport { RuntimeConfig } from './utils/runtime-config';\nimport { Wallet } from './utils/wallet';\n\nclass CLIManager {\n private registry: CommandRegistry;\n private config: RuntimeConfig;\n private wallet: Wallet;\n\n constructor() {\n this.registry = new CommandRegistry();\n this.config = RuntimeConfig.getInstance();\n this.wallet = new Wallet(this.config);\n }\n\n private registerCommands(): void {\n this.registry.register(new InitCommand(this.config, this.wallet));\n this.registry.register(new CreateEntityCommand(this.wallet, this.config));\n this.registry.register(new UpdateEntityCommand(this.wallet, this.config));\n this.registry.register(new CreateUserCommand(this.wallet, this.config));\n this.registry.register(new LogoutCommand(this.wallet));\n this.registry.register(new HelpCommand(this.registry));\n }\n\n private async showHelp(): Promise<void> {\n // add fake wallet to the config\n this.wallet.setWallet({\n address: '0x0000000000000000000000000000000000000000',\n algo: 'secp',\n did: 'did:ixo:entity:1a76366f16570483cea72b111b27fd78',\n network: 'devnet',\n name: 'My oracle',\n pubKey:\n '0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',\n ledgered: false,\n matrix: {\n accessToken: '',\n userId: '0x0000000000000000000000000000000000000000',\n address: '',\n roomId: '',\n },\n });\n this.registerCommands();\n const helpCommand = new HelpCommand(this.registry);\n const result = await helpCommand.execute();\n if (result.success && result.data) {\n console.log(result.data);\n }\n }\n\n private async handleAuthentication(): Promise<void> {\n if (!this.wallet.checkWalletExists()) {\n const login = await select({\n message: 'Login with SignX',\n options: [\n { value: 'login', label: 'Login' },\n { value: 'exit', label: 'Exit' },\n ],\n });\n\n if (isCancel(login)) {\n cancel('Operation cancelled.');\n process.exit(0);\n }\n\n switch (String(login)) {\n case 'login': {\n const loginCommand = new SignXLoginCommand(this.wallet, this.config);\n const result = await loginCommand.execute();\n if (result.success) {\n log.success('Login successful');\n }\n return;\n }\n case 'exit': {\n cancel('Operation cancelled.');\n process.exit(0);\n return;\n }\n default: {\n throw new Error(`Unknown command: ${login}`);\n }\n }\n }\n }\n\n private async executeCommand(commandName: string): Promise<void> {\n const command = this.registry.get(commandName);\n if (!command) {\n throw new Error(`Unknown command: ${commandName}`);\n }\n\n const s = spinner();\n s.start(`Executing ${command.name}...`);\n\n const result = await command.execute();\n s.stop(`${command.name} completed`);\n\n if (result.success) {\n log.success(`${command.name} completed successfully!`);\n if (result.data) {\n log.info(JSON.stringify(result.data, null, 2));\n }\n } else {\n log.error(`${command.name} failed: ${result.error}`);\n }\n }\n\n private async interactiveMode(): Promise<void> {\n intro('IXO CLI');\n log.warn('Keep your IXO Mobile App open while running the CLI; So u do not interrupt the signX session');\n\n await this.handleAuthentication();\n this.registerCommands();\n\n const action = await select({\n message: `Welcome ${this.wallet.name}, what would you like to do?`,\n options: [...this.registry.getCommandOptions()],\n initialValue: 'init',\n });\n\n if (isCancel(action)) {\n cancel('Operation cancelled.');\n process.exit(0);\n }\n\n await this.executeCommand(String(action));\n }\n\n private async argumentMode(args: string[]): Promise<void> {\n const command = args[0];\n\n if (!command) {\n await this.interactiveMode();\n return;\n }\n\n // Handle special flags\n if (command === '--init') {\n await this.handleAuthentication();\n this.registerCommands();\n await this.executeCommand('init');\n return;\n }\n\n // Handle help\n if (command === '--help' || command === '-h') {\n await this.showHelp();\n return;\n }\n\n // Handle direct command execution\n await this.handleAuthentication();\n this.registerCommands();\n await this.executeCommand(command);\n }\n\n async run(args: string[]): Promise<void> {\n try {\n // Remove the first two args (node path and script path)\n const userArgs = args.slice(2);\n\n if (userArgs.length === 0) {\n await this.interactiveMode();\n } else {\n await this.argumentMode(userArgs);\n }\n } catch (error) {\n handleError(error);\n }\n\n outro('Thanks for using IXO CLI!');\n process.exit(0);\n }\n}\n\n// Handle uncaught errors\nprocess.on('uncaughtException', handleError);\nprocess.on('unhandledRejection', handleError);\n\n// Start the CLI\nconst cli = new CLIManager();\nvoid cli.run(process.argv);\n","import { CLIResult } from '../types';\n\nexport interface Command {\n name: string;\n description: string;\n execute: (...args: any[]) => Promise<CLIResult>;\n}\n\nexport class CommandRegistry {\n private commands: Map<string, Command>;\n\n constructor() {\n this.commands = new Map();\n }\n\n register(command: Command): void {\n this.commands.set(command.name, command);\n }\n\n get(name: string): Command | undefined {\n return this.commands.get(name);\n }\n\n getAll(): Command[] {\n return Array.from(this.commands.values());\n }\n\n getCommandOptions() {\n return this.getAll().map((cmd) => ({\n value: cmd.name,\n label: cmd.name,\n hint: cmd.description,\n }));\n }\n}\n","import * as p from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport {\n checkRequiredMatrixUrl,\n checkRequiredNumber,\n checkRequiredString,\n checkRequiredURL,\n MatrixHomeServerUrl,\n PORTAL_URL,\n selectNetwork,\n} from '../utils/common';\nimport { CreateEntity } from '../utils/entity';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\n\nexport class CreateEntityCommand implements Command {\n name = 'create-entity';\n description = 'Create an entity';\n\n constructor(private wallet: Wallet, private config: RuntimeConfig) {}\n\n async execute(): Promise<CLIResult> {\n const network = this.config.getValue('network') as NETWORK;\n if (!network) {\n await selectNetwork(this.config);\n }\n\n // Determine default Matrix homeserver URL from wallet or static map\n const defaultMatrixUrl =\n this.wallet.matrixHomeServer ?? MatrixHomeServerUrl[(this.config.getValue('network') as NETWORK) ?? 'devnet'];\n\n const results = await p.group(\n {\n matrixHomeServerUrl: () =>\n p.text({\n message: 'Matrix homeserver URL for the oracle:',\n initialValue: defaultMatrixUrl,\n defaultValue: defaultMatrixUrl,\n validate(value) {\n return checkRequiredMatrixUrl(value);\n },\n }),\n oracleName: () =>\n p.text({\n message: 'What is the name of the oracle?',\n initialValue: 'My oracle',\n validate(value) {\n return checkRequiredString(value, 'Oracle name is required');\n },\n }),\n oraclePrice: () =>\n p.text({\n message: 'What is the price of the oracle in IXO CREDITS?',\n initialValue: '100',\n validate(value) {\n return checkRequiredNumber(parseInt(value ?? ''), 'Oracle price is required and must be a number');\n },\n }),\n profile: () =>\n p.group({\n orgName: () =>\n p.text({\n message: 'What is the name of the organization?',\n initialValue: 'IXO',\n validate(value) {\n return checkRequiredString(value, 'Organization name is required');\n },\n }),\n name: () =>\n p.text({\n message: 'What is the name of the profile?',\n initialValue: 'My oracle',\n validate(value) {\n return checkRequiredString(value, 'Profile name is required');\n },\n }),\n logo: ({ results }) =>\n p.text({\n message: 'What is the logo of the profile?',\n initialValue: `https://api.dicebear.com/8.x/bottts/svg?seed=${results?.name ?? 'IXO'}`,\n defaultValue: `https://api.dicebear.com/8.x/bottts/svg?seed=${results?.name ?? 'IXO'}`,\n validate(value) {\n if (!value) return `https://api.dicebear.com/8.x/bottts/svg?seed=${results?.name ?? 'IXO'}`;\n return checkRequiredURL(value, 'Logo is required or a valid URL');\n },\n }),\n coverImage: ({ results }) =>\n p.text({\n message: 'What is the cover image of the profile?',\n initialValue: results.logo as string,\n defaultValue: results.logo as string,\n validate(value) {\n if (!value) return results.logo as string;\n return checkRequiredURL(value, 'Cover image is required or a valid URL');\n },\n }),\n location: () =>\n p.text({\n message: 'What is the location of your domain?',\n initialValue: 'New York, NY',\n validate(value) {\n return checkRequiredString(value, 'Location is required');\n },\n }),\n description: () =>\n p.text({\n message: 'What is the description of the entity (profile)?',\n initialValue: 'We are a company that helps you with daily tasks',\n validate(value) {\n return checkRequiredString(value, 'Description is required');\n },\n }),\n url: () =>\n p.text({\n message: 'What is the website URL of the oracle? (optional, press Enter to skip)',\n placeholder: 'https://your-oracle-website.com',\n }),\n }),\n parentProtocol: () =>\n p.select({\n message: 'What is the parent protocol of the entity?',\n options: [\n {\n value: 'did:ixo:entity:1a76366f16570483cea72b111b27fd78',\n label: 'IXO Oracle Protocol',\n hint: 'default protocol',\n },\n ],\n initialValue: 'did:ixo:entity:1a76366f16570483cea72b111b27fd78',\n }),\n apiUrl: () =>\n p.text({\n message: 'What is the API URL of the oracle?',\n initialValue: 'http://localhost:4000',\n validate(value) {\n return checkRequiredURL(value, 'API URL is required or a valid URL');\n },\n }),\n },\n {\n // On Cancel callback that wraps the group\n // So if the user cancels one of the prompts in the group this function will be called\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n // Defer CreateEntity construction to execute() so matrixHomeServerUrl can be used\n const createEntity = new CreateEntity(this.wallet, this.config);\n\n const did = await createEntity.execute({\n oracleConfig: {\n oracleName: results.oracleName,\n price: parseInt(results.oraclePrice),\n },\n profile: {\n orgName: results.profile.orgName,\n name: results.profile.name,\n logo: results.profile.logo as string,\n coverImage: results.profile.coverImage as string,\n location: results.profile.location,\n description: results.profile.description,\n ...(results.profile.url ? { url: results.profile.url } : {}),\n },\n services: [\n {\n id: '{id}#api',\n serviceEndpoint: results.apiUrl,\n type: 'oracleService',\n },\n {\n id: '{id}#ws',\n serviceEndpoint: results.apiUrl,\n type: 'wsService',\n },\n ],\n parentProtocol: results.parentProtocol,\n matrixHomeServerUrl: results.matrixHomeServerUrl,\n });\n\n p.log.info(`API for the oracle is: ${results.apiUrl} | You can change this after you deploy the oracle`);\n\n // add to portal\n const portalBaseUrl = PORTAL_URL[(this.config.getValue('network') as NETWORK) ?? 'devnet'];\n\n const portalUrl = `${portalBaseUrl}/oracle/${did}/overview`;\n\n p.log.info(`Oracle created successfully: ${did}`);\n p.log.info(`Oracle URL: ${portalUrl}`);\n\n return {\n success: true,\n data: `Entity created successfully: ${did}`,\n };\n }\n}\n","import { select } from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { z } from 'zod';\nimport { RuntimeConfig } from './runtime-config';\n\nexport const selectNetwork = async (config: RuntimeConfig) => {\n const network = await select({\n message: 'Select network: (default: devnet)',\n options: [\n { value: 'mainnet', label: 'Mainnet' },\n { value: 'testnet', label: 'Testnet' },\n { value: 'devnet', label: 'Devnet' },\n ],\n initialValue: 'devnet',\n maxItems: 1,\n });\n\n config.addValue('network', network as NETWORK);\n\n return network as NETWORK;\n};\n\nexport const RELAYER_NODE_DID = {\n mainnet: 'did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d',\n testnet: 'did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb',\n devnet: 'did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d',\n};\n\nexport const MatrixHomeServerUrl: Record<NETWORK, string> = {\n devnet: 'https://devmx.ixo.earth',\n testnet: 'https://testmx.ixo.earth',\n mainnet: 'https://mx.ixo.earth',\n};\n\nexport const MatrixRoomBotServerUrl: Record<NETWORK, string> = {\n devnet: 'https://rooms.bot.devmx.ixo.earth',\n testnet: 'https://rooms.bot.testmx.ixo.earth',\n mainnet: 'https://rooms.bot.mx.ixo.earth',\n};\n\nexport const MatrixBotHomeServerUrl: Record<NETWORK, string> = {\n devnet: 'https://state.bot.devmx.ixo.earth',\n testnet: 'https://state.bot.testmx.ixo.earth',\n mainnet: 'https://state.bot.mx.ixo.earth',\n};\nexport const PORTAL_URL = {\n devnet: 'https://ixo-portal.vercel.app',\n testnet: 'https://ixo-portal.vercel.app',\n mainnet: 'https://ixo-portal.vercel.app',\n};\n\nexport const CHAIN_RPC = {\n mainnet: 'https://impacthub.ixo.world/rpc/',\n testnet: 'https://testnet.ixo.earth/rpc/',\n devnet: 'https://devnet.ixo.earth/rpc/',\n};\n\nexport const DOMAIN_INDEXER_URL: Record<NETWORK, string> = {\n devnet: 'https://domain-indexer.devnet.ixo.earth/index',\n testnet: 'https://domain-indexer.testnet.ixo.earth/index',\n mainnet: 'https://domain-indexer.ixo.earth/index',\n};\n\nexport const checkRequiredString = (value: string | undefined, message = 'This field is required') => {\n const schema = z.string().min(1, message);\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n\nexport const checkIsEntityDid = (value: string | undefined) => {\n const schema = z.string().regex(/^did:ixo:entity:[a-f0-9]{32}$/, 'Invalid entity DID');\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n\nexport const checkRequiredURL = (value: string | undefined, message = 'This url is required or a valid URL') => {\n const schema = z.url(message);\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n\nexport const checkRequiredNumber = (value: number, message = 'This number is required') => {\n const schema = z.number().min(1, message);\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.message;\n }\n return undefined;\n};\n\nexport const checkRequiredPin = (value: string | undefined) => {\n const schema = z\n .string()\n .min(1, 'PIN is required')\n .refine((v) => /^\\d{6}$/.test(v), 'PIN must be exactly 6 digits');\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.issues[0]?.message ?? 'Invalid PIN';\n }\n return undefined;\n};\n\nexport const checkRequiredMatrixUrl = (value: string | undefined) => {\n const schema = z\n .string()\n .min(1, 'Matrix homeserver URL is required')\n .refine((v) => /^https?:\\/\\//.test(v), 'Must start with http:// or https://')\n .refine((v) => !v.endsWith('/'), 'Must not end with a trailing slash');\n const result = schema.safeParse(value);\n if (!result.success) {\n return result.error.issues[0]?.message ?? 'Invalid Matrix URL';\n }\n return undefined;\n};\n\nexport interface MatrixUrls {\n homeServerUrl: string;\n roomBotUrl: string;\n stateBotUrl: string;\n bidsBotUrl: string;\n claimsBotUrl: string;\n}\n\n/**\n * Derives all Matrix bot URLs from a homeserver URL using subdomain convention.\n * e.g. https://devmx.ixo.earth → https://rooms.bot.devmx.ixo.earth\n */\nexport function deriveMatrixUrls(homeServerUrl: string): MatrixUrls {\n const url = new URL(homeServerUrl);\n const domain = url.hostname;\n const protocol = url.protocol;\n\n return {\n homeServerUrl,\n roomBotUrl: `${protocol}//rooms.bot.${domain}`,\n stateBotUrl: `${protocol}//state.bot.${domain}`,\n bidsBotUrl: `${protocol}//bids.bot.${domain}`,\n claimsBotUrl: `${protocol}//claims.bot.${domain}`,\n };\n}\n","import { isCancel, log, spinner, text } from '@clack/prompts';\nimport { customMessages, ixo, utils } from '@ixo/impactxclient-sdk';\nimport { LinkedResource, Service } from '@ixo/impactxclient-sdk/types/codegen/ixo/iid/v1beta1/types';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { logoutMatrixClient } from './account/matrix';\nimport { registerUserSimplified, SimplifiedRegistrationResult } from './account/simplifiedRegistration';\nimport { checkRequiredPin, DOMAIN_INDEXER_URL, RELAYER_NODE_DID } from './common';\nimport { publicUpload } from './matrix/upload-to-matrix';\nimport { RuntimeConfig } from './runtime-config';\nimport { Wallet } from './wallet';\n\ninterface CreateEntityParams {\n profile: {\n orgName: string;\n name: string;\n logo: string;\n coverImage: string;\n location: string;\n description: string;\n url?: string;\n };\n services: Service[];\n parentProtocol: string;\n oracleConfig: {\n oracleName: string;\n price: number;\n };\n matrixHomeServerUrl: string;\n}\ntype Denom = 'uixo' | 'ibc/6BBE9BD4246F8E04948D5A4EEE7164B2630263B9EBB5E7DC5F0A46C62A2FF97B';\n\nexport class CreateEntity {\n private readonly wallet: Wallet;\n constructor(wallet: Wallet, private config: RuntimeConfig) {\n if (!wallet.did || !wallet.pubKey || !wallet.address || !wallet.algo) {\n throw new Error('Wallet not found');\n }\n this.wallet = wallet;\n }\n\n private buildMsgCreateEntity(matrixHomeServerUrl: string) {\n const msg = {\n typeUrl: '/ixo.entity.v1beta1.MsgCreateEntity',\n value: ixo.entity.v1beta1.MsgCreateEntity.fromPartial({\n entityType: 'oracle',\n context: [],\n entityStatus: 0,\n verification: [\n ...customMessages.iid.createIidVerificationMethods({\n did: this.wallet.did!,\n pubkey: new Uint8Array(Buffer.from(this.wallet.pubKey!)),\n address: this.wallet.address!,\n controller: this.wallet.did!,\n type: this.wallet.algo === 'ed25519' ? 'ed' : 'secp',\n }),\n ],\n controller: [this.wallet.did!],\n ownerAddress: this.wallet.address!,\n ownerDid: this.wallet.did!,\n relayerNode: RELAYER_NODE_DID[(this.config.getValue('network') as NETWORK) ?? 'devnet'],\n service: [\n ixo.iid.v1beta1.Service.fromPartial({\n id: '{id}#matrix',\n type: 'MatrixHomeServer',\n serviceEndpoint: matrixHomeServerUrl,\n }),\n ],\n linkedResource: [],\n accordedRight: [],\n linkedEntity: [],\n linkedClaim: [],\n startDate: utils.proto.toTimestamp(new Date()),\n endDate: utils.proto.toTimestamp(new Date(Date.now() + 100 * 365 * 24 * 60 * 60 * 1000)),\n }),\n };\n return msg;\n }\n\n public addLinkedAccounts(\n msg: ReturnType<typeof this.buildMsgCreateEntity>,\n { oracleAccountAddress }: { oracleAccountAddress: string }\n ) {\n if (!this.wallet.signXClient || !this.wallet.wallet) {\n throw new Error('SignX client or wallet not found');\n }\n const memoryEngineByNetwork = {\n devnet: 'did:ixo:ixo17w9u5uk4qjyjgeyqfpnp92jwy58faey9vvp3ar',\n testnet: 'did:ixo:ixo14vjrckltpngugp03tcasfgh5qakey9n3sgm6y2',\n mainnet: 'did:ixo:ixo1d39eutxdc0e8mnp0fmzqjdy6aaf26s9hzrk33r',\n }[this.config.getValue('network') as NETWORK];\n\n const accounts = [memoryEngineByNetwork, `did:ixo:${oracleAccountAddress}`];\n const linkedAccounts = accounts.map((account) =>\n ixo.iid.v1beta1.LinkedEntity.fromPartial({\n id: account,\n type: 'agent',\n relationship: 'admin',\n service: 'matrix',\n })\n );\n\n msg.value.linkedEntity = linkedAccounts;\n }\n\n private async createAuthZConfig({\n oracleAccountAddress,\n oracleName,\n entityDid,\n homeServerUrl,\n accessToken,\n }: {\n oracleAccountAddress: string;\n oracleName: string;\n entityDid: string;\n homeServerUrl: string;\n accessToken: string;\n }): Promise<LinkedResource> {\n const config = {\n '@context': [\n 'https://schema.org',\n {\n ixo: 'https://w3id.org/ixo/context/v1',\n oracle: {\n '@id': entityDid,\n '@type': '@id',\n },\n },\n ],\n '@type': 'Service',\n '@id': 'oracle:OracleAuthorization',\n name: 'OracleAuthorization',\n description: 'OracleAuthorization',\n serviceType: 'OracleClaimAuthorizationService',\n requiredPermissions: ['/ixo.claims.v1beta1.MsgCreateClaimAuthorization'],\n granteeAddress: oracleAccountAddress,\n granterAddress: '',\n oracleName: oracleName,\n };\n const response = await publicUpload({\n data: config,\n fileName: 'authz',\n homeServerUrl,\n accessToken,\n });\n\n return ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: '{id}#orz',\n type: 'oracleAuthZConfig',\n proof: response.proof,\n right: '',\n encrypted: 'false',\n mediaType: 'application/json',\n description: 'Orale AuthZ Config',\n serviceEndpoint: response.serviceEndpoint,\n });\n }\n\n private async createFeesConfig({\n entityDid,\n price,\n denom,\n homeServerUrl,\n accessToken,\n }: {\n entityDid: string;\n price: number;\n denom: Denom;\n homeServerUrl: string;\n accessToken: string;\n }): Promise<LinkedResource> {\n const config = {\n '@context': [\n 'https://schema.org',\n {\n ixo: 'https://w3id.org/ixo/context/v1',\n oracle: {\n '@id': entityDid,\n '@type': '@id',\n },\n },\n ],\n '@type': 'Service',\n '@id': 'oracle:ServiceFeeModel',\n name: 'Pricing',\n description: 'Pricing',\n serviceType: '',\n offers: {\n '@type': 'Offer',\n priceCurrency: denom,\n priceSpecification: {\n '@type': 'PaymentChargeSpecification',\n priceCurrency: denom,\n price: price * 1000, // 1 credit is 1000 uixo\n unitCode: 'MON',\n billingIncrement: 1,\n billingPeriod: 'P1M',\n priceType: 'Subscription',\n maxPrice: price,\n },\n eligibleQuantity: {\n '@type': 'QuantitativeValue',\n value: 1,\n unitCode: 'MON',\n },\n },\n };\n const response = await publicUpload({\n data: config,\n fileName: 'fees',\n homeServerUrl,\n accessToken,\n });\n return ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: '{id}#fee',\n type: 'pricingList',\n proof: response.proof,\n right: '',\n encrypted: 'false',\n mediaType: 'application/json',\n description: 'Pricing List',\n serviceEndpoint: response.serviceEndpoint,\n });\n }\n\n /**\n * Add a controller to an existing entity\n */\n public async addControllerToEntity(entityDid: string, controllerDid: string): Promise<void> {\n const walletAddress = this.wallet.wallet?.address;\n\n if (!this.wallet.signXClient || !this.wallet.wallet || !walletAddress) {\n throw new Error('SignX client or wallet not found');\n }\n\n const addControllerMsg = {\n typeUrl: '/ixo.iid.v1beta1.MsgAddController',\n value: ixo.iid.v1beta1.MsgAddController.fromPartial({\n id: entityDid,\n controllerDid: controllerDid,\n signer: walletAddress,\n }),\n };\n\n log.info(`Sign to add controller ${controllerDid} to entity ${entityDid}`);\n const tx = await this.wallet.signXClient.transact([addControllerMsg], this.wallet.wallet);\n this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(tx));\n await this.wallet.signXClient.pollNextTransaction();\n await this.wallet.signXClient.awaitTransaction();\n log.success(`Controller ${controllerDid} added to entity ${entityDid}`);\n }\n\n private async createOracleConfigFiles({\n oracleName,\n entityDid,\n price,\n oracleAccountAddress,\n homeServerUrl,\n accessToken,\n }: CreateEntityParams['oracleConfig'] & {\n entityDid: string;\n oracleAccountAddress: string;\n homeServerUrl: string;\n accessToken: string;\n }) {\n const walletAddress = this.wallet.wallet?.address;\n\n if (!this.wallet.signXClient || !this.wallet.wallet || !walletAddress) {\n throw new Error('SignX client or wallet not found');\n }\n\n const resources = await Promise.all([\n this.createAuthZConfig({\n oracleName,\n entityDid,\n oracleAccountAddress,\n homeServerUrl,\n accessToken,\n }),\n this.createFeesConfig({\n entityDid,\n price,\n denom:\n this.config.getValue('network') === 'devnet'\n ? 'uixo'\n : 'ibc/6BBE9BD4246F8E04948D5A4EEE7164B2630263B9EBB5E7DC5F0A46C62A2FF97B',\n homeServerUrl,\n accessToken,\n }),\n ]);\n const linkedResourcesMsgs = resources.map((resource) => ({\n typeUrl: '/ixo.iid.v1beta1.MsgAddLinkedResource',\n value: ixo.iid.v1beta1.MsgAddLinkedResource.fromPartial({\n id: entityDid,\n linkedResource: ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: resource.id,\n description: resource.description,\n type: resource.type,\n proof: resource.proof,\n mediaType: resource.mediaType,\n encrypted: resource.encrypted,\n serviceEndpoint: resource.serviceEndpoint,\n }),\n signer: walletAddress,\n }),\n }));\n\n // sign and send the msgs\n log.info('Sign to edit the entity and add the config files');\n const tx = await this.wallet.signXClient.transact(linkedResourcesMsgs, this.wallet.wallet);\n this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(tx));\n await this.wallet.signXClient.pollNextTransaction();\n const response = await this.wallet.signXClient.awaitTransaction();\n return response;\n }\n\n private async createDomainCard({\n profile,\n entityDid,\n homeServerUrl,\n accessToken,\n }: {\n profile: CreateEntityParams['profile'];\n entityDid: string;\n homeServerUrl: string;\n accessToken: string;\n }): Promise<LinkedResource> {\n const validFrom = new Date().toISOString();\n\n const domainCard = {\n '@context': [\n 'https://www.w3.org/ns/credentials/v2',\n 'https://w3id.org/ixo/context/v1',\n {\n schema: 'https://schema.org/',\n ixo: 'https://w3id.org/ixo/vocab/v1',\n prov: 'http://www.w3.org/ns/prov#',\n proj: 'https://linked.data.gov.au/def/project#',\n xsd: 'http://www.w3.org/2001/XMLSchema#',\n id: '@id',\n type: '@type',\n 'ixo:vector': {\n '@container': '@list',\n '@type': 'xsd:double',\n },\n '@protected': true,\n },\n ],\n id: `${entityDid}#dmn`,\n type: ['VerifiableCredential', 'ixo:DomainCard'],\n issuer: {\n id: this.wallet.did,\n },\n validFrom: validFrom,\n credentialSchema: {\n id: 'https://github.com/ixoworld/domainCards/schemas/ixo-domain-card-1.json',\n type: 'JsonSchema',\n },\n credentialSubject: {\n id: entityDid,\n type: ['ixo:oracle'],\n additionalType: ['schema:Organization'],\n name: profile.name,\n alternateName: profile.orgName !== profile.name ? [profile.orgName] : undefined,\n description: profile.description,\n logo: {\n type: 'schema:ImageObject',\n id: profile.logo,\n contentUrl: profile.logo,\n },\n image: [\n {\n type: 'schema:ImageObject',\n id: profile.coverImage,\n contentUrl: profile.coverImage,\n },\n ],\n address: {\n type: 'schema:PostalAddress',\n addressLocality: profile.location,\n },\n ...(profile.url ? { url: profile.url } : {}),\n },\n };\n\n const response = await publicUpload({\n data: domainCard,\n fileName: 'domainCard',\n homeServerUrl,\n accessToken,\n });\n\n return ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: '{id}#dmn',\n type: 'domainCard',\n proof: response.proof,\n right: '',\n encrypted: 'false',\n mediaType: 'application/json',\n description: 'Domain Card',\n serviceEndpoint: response.serviceEndpoint,\n });\n }\n\n private async addProfile({\n orgName,\n name,\n logo,\n coverImage,\n location,\n description,\n homeServerUrl,\n accessToken,\n }: CreateEntityParams['profile'] & { homeServerUrl: string; accessToken: string }) {\n const profileData = {\n '@context': {\n ixo: 'https://w3id.org/ixo/ns/protocol/',\n '@id': '@type',\n type: '@type',\n '@protected': false,\n },\n id: 'ixo:entity#profile',\n type: 'profile',\n orgName,\n name,\n image: coverImage,\n logo,\n brand: orgName,\n location,\n description,\n };\n\n const response = await publicUpload({\n data: profileData,\n fileName: 'profile',\n homeServerUrl,\n accessToken,\n });\n\n return ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: '{id}#pro',\n type: 'Settings',\n description: 'Profile',\n mediaType: 'application/json',\n serviceEndpoint: response.serviceEndpoint,\n proof: response.proof,\n encrypted: 'false',\n right: '',\n });\n }\n\n private addServices(msg: ReturnType<typeof this.buildMsgCreateEntity>, services: Service[]) {\n msg.value.service.push(...services.map((service) => ixo.iid.v1beta1.Service.fromPartial(service)));\n }\n\n private setParentProtocol(msg: ReturnType<typeof this.buildMsgCreateEntity>, parentProtocol: string) {\n msg.value.context.push(\n ...customMessages.iid.createAgentIidContext([{ key: 'class', val: parentProtocol }])\n );\n }\n\n private async submitToDomainIndexer(entityDid: string): Promise<void> {\n const network = (this.config.getValue('network') as NETWORK) ?? 'devnet';\n const indexerUrl = DOMAIN_INDEXER_URL[network];\n\n try {\n const response = await fetch(indexerUrl, {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n did: entityDid,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n log.warn(`Failed to submit to domain indexer: ${response.status} ${errorText}`);\n return;\n }\n\n log.success('Domain card submitted to domain indexer');\n } catch (error) {\n log.warn(`Error submitting to domain indexer: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n public async execute(params: CreateEntityParams): Promise<string> {\n if (!this.wallet.signXClient || !this.wallet.wallet) {\n throw new Error('SignX client not found');\n }\n\n const { matrixHomeServerUrl } = params;\n\n // =================================================================================================\n // 1. REGISTER ORACLE FIRST — we need oracle's credentials for uploads\n // =================================================================================================\n log.info('Creating Oracle Wallet and Matrix Account');\n const pin = await text({\n message: 'Enter a 6-digit PIN to secure your Matrix Vault:',\n placeholder: '123456',\n validate(value) {\n return checkRequiredPin(value);\n },\n });\n if (isCancel(pin)) {\n log.error('User cancelled');\n process.exit(1);\n }\n const registerResult = await registerUserSimplified(\n {\n pin,\n oracleName: params.oracleConfig.oracleName,\n network: this.config.getValue('network') as NETWORK,\n oracleAvatarUrl: params.profile.logo,\n matrixHomeServerUrl,\n },\n async (address) => {\n await this.wallet.sendTokens(address, 250_000); // 250,000 uixo = 0.25 IXO;\n }\n );\n\n // Oracle's credentials for uploading to oracle's Matrix server\n const oracleHomeServerUrl = registerResult.matrixHomeServerUrl;\n const oracleAccessToken = registerResult.matrixAccessToken;\n\n // =================================================================================================\n // 2. UPLOAD PROFILE using oracle's credentials\n // =================================================================================================\n log.info('Adding profile');\n const profileResource = await this.addProfile({\n ...params.profile,\n homeServerUrl: oracleHomeServerUrl,\n accessToken: oracleAccessToken,\n });\n\n // =================================================================================================\n // 3. BUILD AND BROADCAST MsgCreateEntity\n // =================================================================================================\n const msg = this.buildMsgCreateEntity(matrixHomeServerUrl);\n\n // Add profile linked resource\n msg.value.linkedResource.push(profileResource);\n\n // Add services\n log.info('Adding services');\n this.addServices(msg, params.services);\n\n // Add parent protocol\n log.info('Adding parent protocol');\n this.setParentProtocol(msg, params.parentProtocol);\n\n // Add linked accounts\n this.addLinkedAccounts(msg, {\n oracleAccountAddress: registerResult.address,\n });\n\n log.info('Sign this transaction to create the entity');\n const tx = await this.wallet.signXClient.transact([msg], this.wallet.wallet);\n this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(tx));\n await this.wallet.signXClient.pollNextTransaction();\n\n // Wait for transaction completion\n const response = await this.wallet.signXClient.awaitTransaction();\n log.success('Entity created -- wait to attach the required config files');\n\n // upload resources\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const did = utils.common.getValueFromEvents(response as any, 'wasm', 'token_id');\n\n // =================================================================================================\n // 4. CREATE AND ATTACH DOMAIN CARD using oracle's credentials\n // =================================================================================================\n log.info('Creating domain card');\n const domainCardResource = await this.createDomainCard({\n profile: params.profile,\n entityDid: did,\n homeServerUrl: oracleHomeServerUrl,\n accessToken: oracleAccessToken,\n });\n\n // Add domain card to entity\n if (this.wallet.wallet?.address) {\n const addDomainCardMsg = {\n typeUrl: '/ixo.iid.v1beta1.MsgAddLinkedResource',\n value: ixo.iid.v1beta1.MsgAddLinkedResource.fromPartial({\n id: did,\n linkedResource: ixo.iid.v1beta1.LinkedResource.fromPartial({\n id: domainCardResource.id,\n description: domainCardResource.description,\n type: domainCardResource.type,\n proof: domainCardResource.proof,\n mediaType: domainCardResource.mediaType,\n encrypted: domainCardResource.encrypted,\n serviceEndpoint: domainCardResource.serviceEndpoint,\n }),\n signer: this.wallet.wallet.address,\n }),\n };\n log.info('Sign to add domain card to the entity');\n const domainCardTx = await this.wallet.signXClient.transact([addDomainCardMsg], this.wallet.wallet);\n this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(domainCardTx));\n await this.wallet.signXClient.pollNextTransaction();\n await this.wallet.signXClient.awaitTransaction();\n log.success('Domain card added to entity');\n }\n\n // =================================================================================================\n // 5. CREATE AND ATTACH CONFIG FILES using oracle's credentials\n // =================================================================================================\n await this.createOracleConfigFiles({\n oracleName: params.oracleConfig.oracleName,\n price: params.oracleConfig.price,\n oracleAccountAddress: registerResult.address,\n entityDid: did,\n homeServerUrl: oracleHomeServerUrl,\n accessToken: oracleAccessToken,\n });\n log.success('Entity created -- config files attached');\n\n // =================================================================================================\n // 6. LOGOUT ORACLE's Matrix session (no longer needed)\n // =================================================================================================\n await logoutMatrixClient({\n baseUrl: oracleHomeServerUrl,\n accessToken: oracleAccessToken,\n userId: registerResult.matrixUserId,\n deviceId: '',\n });\n\n const s = spinner();\n s.start('Creating Entity Matrix Room...');\n s.stop('Room created -- room joined');\n log.warn('Please save the following information in a secure location as it is not stored:');\n log.info(`ORACLE ACCOUNT DETAILS`);\n\n for (const key in registerResult) {\n log.info(`${key}: ${registerResult[key as keyof SimplifiedRegistrationResult]}`);\n }\n this.config.addValue('registerUserResult', registerResult);\n this.config.addValue('entityDid', did);\n this.config.addValue('oracleMatrixHomeServerUrl', matrixHomeServerUrl);\n\n // Submit to domain indexer\n log.info('Submitting domain card to domain indexer');\n await this.submitToDomainIndexer(did);\n\n return did;\n }\n}\n","import { sha256 } from '@cosmjs/crypto';\nimport { encrypt as eciesEncrypt } from 'eciesjs';\nimport { ClientEvent, createClient, MatrixClient } from 'matrix-js-sdk';\nimport { CryptoApi } from 'matrix-js-sdk/lib/crypto-api';\nimport md5 from 'md5';\n\n// import cons from '@constants/matrix';\n// import { isAuthenticated, secret } from '@utils/secrets';\nimport { cacheSecretStorageKey, clearSecretStorageKeys, getSecretStorageKey } from './secretStorageKeys';\nimport { delay } from './utils';\n\nconst WELL_KNOWN_URI = '/.well-known/matrix/client';\n\n// =================================================================================================\n// AUTH\n// =================================================================================================\ninterface AuthResponse {\n accessToken: string;\n deviceId: string;\n userId: string;\n baseUrl: string;\n}\nexport const mxLogin = async (\n {\n homeServerUrl,\n username,\n password,\n deviceName,\n }: { homeServerUrl: string; username: string; password: string; deviceName: string },\n localMatrix = false\n) => {\n let mxHomeServerUrl = homeServerUrl;\n let mxUsername = username;\n const mxIdMatch = mxUsername.match(/^@(.+):(.+\\..+)$/);\n if (mxIdMatch) {\n mxUsername = mxIdMatch[1] as string;\n mxHomeServerUrl = mxIdMatch[2] as string;\n mxHomeServerUrl = localMatrix ? mxHomeServerUrl : await getBaseUrl(mxHomeServerUrl);\n }\n\n try {\n const client = createTemporaryClient(mxHomeServerUrl);\n const response = await client.login('m.login.password', {\n identifier: {\n type: 'm.id.user',\n user: normalizeUsername(mxUsername),\n },\n password,\n initial_device_display_name: deviceName,\n });\n const data: AuthResponse = {\n accessToken: response.access_token,\n deviceId: response.device_id,\n userId: response.user_id,\n baseUrl: localMatrix ? mxHomeServerUrl : response?.well_known?.['m.homeserver']?.base_url || client.baseUrl,\n };\n return data;\n } catch (error) {\n let msg = (error as any).message;\n if (msg === 'Unknown message') {\n msg = 'Please check your credentials';\n }\n console.error(`mxLogin::`, msg);\n throw new Error(msg);\n }\n};\n\n// =================================================================================================\n// NEW API-BASED REGISTRATION\n// =================================================================================================\n\ninterface PublicKeyResponse {\n publicKey: string;\n fingerprint: string;\n algorithm: string;\n usage: string;\n}\n\ninterface UserCreationChallenge {\n timestamp: string;\n address: string;\n service: string;\n type: string;\n}\n\ninterface UserCreationRequest {\n address: string;\n encryptedPassword: string;\n publicKeyFingerprint: string;\n authnResult?: any;\n secpResult?: {\n signature: string;\n challenge: string;\n };\n}\n\ninterface UserCreationResponse {\n success: boolean;\n matrixUserId: string;\n address: string;\n message: string;\n}\n\n/**\n * Fetch the public key for password encryption from the user creation API\n * @returns Public key information for encryption\n */\nexport async function getPublicKeyForEncryption(roomBotUrl: string): Promise<PublicKeyResponse> {\n const response = await fetch(`${roomBotUrl}/public-key`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error('Failed to fetch public key for encryption');\n }\n\n const data = (await response.json()) as PublicKeyResponse;\n return data;\n}\n\n/**\n * Create a structured challenge for user creation\n * @param address The user's address (without did:ixo: prefix)\n * @returns The challenge object and its base64 representation\n */\nexport function createUserCreationChallenge(address: string): {\n challenge: UserCreationChallenge;\n challengeBase64: string;\n} {\n const challenge: UserCreationChallenge = {\n timestamp: new Date().toISOString(),\n address: address,\n service: 'matrix',\n type: 'create-account',\n };\n\n const challengeBase64 = Buffer.from(JSON.stringify(challenge)).toString('base64');\n\n return { challenge, challengeBase64 };\n}\n\n/**\n * Encrypt password using ECIES with the provided public key\n * @param password The password to encrypt\n * @param publicKey The public key in hex format\n * @returns The encrypted password in hex format\n */\nexport function encryptPasswordWithECIES(password: string, publicKey: string): string {\n const publicKeyBytes = new Uint8Array(Buffer.from(publicKey, 'hex'));\n const passwordBytes = new Uint8Array(Buffer.from(password, 'utf8'));\n const encryptedPassword = eciesEncrypt(publicKeyBytes, passwordBytes);\n return Array.from(encryptedPassword, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Create user account using secp256k1 signature authentication\n * @param address The user's address\n * @param password The matrix password\n * @param signature The secp256k1 signature (base64)\n * @param challenge The challenge that was signed (base64)\n * @returns The user creation response\n */\nexport async function createUserAccountWithSecp(\n address: string,\n password: string,\n signature: string,\n challenge: string,\n homeServerUrl: string,\n roomBotUrl: string\n): Promise<UserCreationResponse> {\n const publicKeyInfo = await getPublicKeyForEncryption(roomBotUrl);\n const encryptedPassword = encryptPasswordWithECIES(password, publicKeyInfo.publicKey);\n\n const request: UserCreationRequest = {\n address,\n encryptedPassword,\n publicKeyFingerprint: publicKeyInfo.fingerprint,\n secpResult: {\n signature,\n challenge,\n },\n };\n\n const response = await fetch(`${roomBotUrl}/user/create`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n const responseText = await response.text();\n let errorMessage = `Failed to create user account (HTTP ${response.status})`;\n try {\n const errorData = JSON.parse(responseText);\n errorMessage = errorData.error || errorData.message || errorData.detail || responseText;\n } catch {\n errorMessage = responseText || errorMessage;\n }\n console.error(`Room bot error [${response.status}]: ${responseText}`);\n throw new Error(errorMessage);\n }\n\n return (await response.json()) as UserCreationResponse;\n}\n\n// =================================================================================================\n// UPDATED REGISTRATION FUNCTIONS\n// =================================================================================================\n\n/**\n * Register matrix account using the new API with secp256k1 signature authentication\n * @param address The user's address\n * @param password The matrix password\n * @param deviceName The device name for the Matrix session\n * @param wallet The secp wallet for signing\n * @param homeServerUrl The Matrix homeserver URL\n * @param roomBotUrl The room bot URL\n * @returns AuthResponse with access token and user details\n */\nexport async function mxRegisterWithSecp(\n address: string,\n password: string,\n deviceName: string,\n wallet: { sign: (message: string) => Promise<Uint8Array> },\n homeServerUrl: string,\n roomBotUrl: string\n): Promise<AuthResponse> {\n try {\n // Create challenge and sign it\n const { challengeBase64 } = createUserCreationChallenge(address);\n const signatureBytes = await wallet.sign(challengeBase64);\n const signature = Buffer.from(signatureBytes).toString('base64');\n\n const userCreationResult = await createUserAccountWithSecp(\n address,\n password,\n signature,\n challengeBase64,\n homeServerUrl,\n roomBotUrl\n );\n\n if (!userCreationResult.success) {\n throw new Error('Failed to create matrix account via API');\n }\n\n const username = generateUsernameFromAddress(address);\n\n const loginResult = await mxLogin({\n homeServerUrl,\n username,\n password,\n deviceName,\n });\n\n return loginResult;\n } catch (error) {\n console.error('mxRegisterWithSecp error:', error);\n throw error;\n }\n}\n\nexport async function checkIsUsernameAvailable({\n homeServerUrl,\n username,\n}: {\n homeServerUrl: string;\n username: string;\n}) {\n const client = createTemporaryClient(homeServerUrl);\n try {\n const isUsernameAvailable = await client.isUsernameAvailable(username);\n return !!isUsernameAvailable;\n } catch (error) {\n return false;\n }\n}\n\n// =================================================================================================\n// CLIENT\n// =================================================================================================\n/**\n * Creates a temporary matrix client, used for matrix login or registration to get access tokens\n * @param homeServerUrl - the home server url to instantiate the matrix client\n * @returns matrix client\n */\nexport function createTemporaryClient(homeServerUrl: string) {\n if (!homeServerUrl) {\n throw new Error('Home server URL is required to instantiate matrix client');\n }\n return createClient({\n baseUrl: homeServerUrl,\n });\n}\n\nexport async function createMatrixClient({\n homeServerUrl,\n accessToken,\n userId,\n deviceId,\n}: {\n homeServerUrl: string;\n accessToken: string;\n userId: string;\n deviceId: string;\n}) {\n console.log('createMatrixClient::', { homeServerUrl, accessToken, userId, deviceId });\n\n if (!homeServerUrl || !accessToken || !userId || !deviceId) {\n throw new Error('Login to Matrix account before trying to instantiate Matrix client.');\n }\n\n // const indexedDBStore = new IndexedDBStore({\n // indexedDB: global.indexedDB,\n // dbName: 'matrix-sync-store',\n // });\n // const legacyCryptoStore = new IndexedDBCryptoStore()\n\n const mxClient = createClient({\n baseUrl: homeServerUrl,\n accessToken,\n userId,\n // store: indexedDBStore,\n // cryptoStore: legacyCryptoStore,\n deviceId,\n timelineSupport: true,\n cryptoCallbacks: {\n getSecretStorageKey: getSecretStorageKey,\n cacheSecretStorageKey: cacheSecretStorageKey,\n },\n verificationMethods: ['m.sas.v1'],\n });\n // await indexedDBStore.startup();\n await mxClient.initRustCrypto({\n useIndexedDB: false,\n });\n // mxClient.setGlobalErrorOnUnknownDevices(false);\n mxClient.setMaxListeners(20);\n // const filter = new Filter(userId);\n // filter.setDefinition({\n // room: {\n // state: {\n // lazy_load_members: true,\n // types: [],\n // },\n // timeline: {\n // types: [],\n // },\n // },\n // // Disable unnecessary features\n // presence: {\n // types: [], // No presence updates needed\n // },\n // account_data: {\n // types: ['m.cross_signing.master'], // No account data needed\n // },\n // });\n await mxClient.startClient({\n lazyLoadMembers: true,\n // initialSyncLimit: 1,\n includeArchivedRooms: false,\n // pollTimeout: 2 * 60 * 1000, // poll every 2 minutes\n // filter: filter,\n });\n await new Promise<void>((resolve, reject) => {\n const sync = {\n NULL: () => {\n console.info('[NULL] state');\n },\n SYNCING: () => {\n void 0;\n },\n PREPARED: () => {\n console.info(`[PREPARED] state: user ${userId}`);\n resolve();\n },\n RECONNECTING: () => {\n console.info('[RECONNECTING] state');\n },\n CATCHUP: () => {\n console.info('[CATCHUP] state');\n },\n ERROR: () => {\n reject(new Error('[ERROR] state: starting matrix client'));\n },\n STOPPED: () => {\n console.info('[STOPPED] state');\n },\n };\n mxClient.on(ClientEvent.Sync, (state) => {\n sync[state]();\n });\n });\n return mxClient;\n}\n\nexport async function logoutMatrixClient({\n mxClient,\n baseUrl,\n accessToken,\n userId,\n deviceId,\n}: {\n mxClient?: MatrixClient;\n baseUrl: string;\n accessToken: string;\n userId: string;\n deviceId: string;\n}) {\n let client = mxClient;\n if (!client) {\n client = createClient({\n baseUrl: baseUrl,\n accessToken,\n userId,\n deviceId,\n });\n }\n if (client) {\n client.stopClient();\n await client.logout().catch(console.error);\n client.clearStores();\n }\n}\n\n// =================================================================================================\n// CROSS SIGNING\n// =================================================================================================\n/**\n * Check if the user has cross-signing account data.\n * @param {MatrixClient} mxClient - The matrix client to check.\n * @returns {boolean} True if the user has cross-signing account data, otherwise false.\n */\nexport function hasCrossSigningAccountData(mxClient: MatrixClient): boolean {\n const masterKeyData = mxClient.getAccountData('m.cross_signing.master');\n console.log('hasCrossSigningAccountData::masterKeyData', masterKeyData);\n return !!masterKeyData;\n}\n\n/**\n * Setup cross signing and secret storage for the current user\n * @param {MatrixClient} mxClient - The matrix client to setup cross signing for\n * @param {string} securityPhrase - the security phrase to use for secret storage\n * @param {string} password - the password for the matrix account\n * @param {boolean} forceReset - if to force reset the cross signing keys (NB, only do if you know what you are doing!!!)\n * @param {boolean} skipBootstrapSS - if to skip bootstrapping secret storage\n * @returns {boolean} True if the cross signing was setup successfully, otherwise false.\n */\nexport async function setupCrossSigning(\n mxClient: MatrixClient,\n {\n securityPhrase,\n password,\n forceReset = false,\n skipBootstrapSecureStorage = false,\n }: { securityPhrase: string; password: string; forceReset?: boolean; skipBootstrapSecureStorage?: boolean }\n): Promise<boolean> {\n if (forceReset) {\n clearSecretStorageKeys();\n }\n\n const mxCrypto = mxClient.getCrypto() as CryptoApi;\n if (!mxCrypto) {\n throw new Error('Failed to setup matrix cross signing - failed to get matrix crypto api');\n }\n if (!skipBootstrapSecureStorage) {\n const recoveryKey = await mxCrypto.createRecoveryKeyFromPassphrase(securityPhrase);\n clearSecretStorageKeys();\n await mxCrypto.bootstrapSecretStorage({\n createSecretStorageKey: async () => recoveryKey!,\n setupNewSecretStorage: forceReset,\n });\n }\n const userId = mxClient.getUserId()!;\n await mxCrypto.bootstrapCrossSigning({\n authUploadDeviceSigningKeys: async function (makeRequest) {\n await makeRequest(getAuthId({ userId, password }));\n },\n setupNewCrossSigning: forceReset,\n });\n await mxCrypto.resetKeyBackup();\n\n await delay(300);\n\n return !!mxClient.getAccountData('m.cross_signing.master');\n}\n\n// =================================================================================================\n// GENERAL\n// =================================================================================================\n/**\n * Generates a username from an address, used for matrix login, generated an account did\n * @param {string} address - the address to generate the username from\n * @returns {string} username\n */\nexport function generateUsernameFromAddress(address: string): string {\n if (!address) {\n throw new Error('Address is required to generate matrix username');\n }\n return 'did-ixo-' + address;\n}\n\n/**\n * Generates a password from a mnemonic, used for matrix login, generated using the first 24 bytes of the base64 encoded md5 hash of the mnemonic\n * @param {string} mnemonic - the mnemonic to generate the password from\n * @returns {string} password\n */\nexport function generatePasswordFromMnemonic(mnemonic: string): string {\n const base64 = Buffer.from(md5(mnemonic.replace(/ /g, ''))).toString('base64');\n return base64.slice(0, 24);\n}\n\n/**\n * Generates a recovery phrase from a mnemonic, used for matrix recovery, generated using the first 32 bytes of the base64 encoded sha256 hash of the mnemonic\n * @param {string} mnemonic - the mnemonic to generate the recovery phrase from\n * @returns {string} recoveryPhrase\n */\nexport function generateRecoveryPhraseFromMnemonic(mnemonic: string): string {\n const hash = sha256(new TextEncoder().encode(mnemonic.replace(/ /g, '')));\n const base64 = Buffer.from(hash).toString('base64');\n return base64.slice(0, 32);\n}\n\n/**\n * Extracts the home server URL from a user ID.\n * @param {string} userId - The user ID to extract the homeserver URL from.\n * @returns {string} The homeserver URL.\n */\nexport function extractHomeServerUrlFromUserId(userId: string): string {\n const parts = userId.split(':');\n if (parts.length < 2) {\n throw new Error('Invalid userId');\n }\n return parts.slice(1).join(':');\n}\n\n/**\n * Generates a recovery phrase from a mnemonic, used for matrix recovery, generated using the first 32 bytes of the base64 encoded sha256 hash of the mnemonic\n * @param {string} mnemonic - the mnemonic to generate the recovery phrase from\n * @returns {string} passphrase\n */\nexport function generatePassphraseFromMnemonic(mnemonic: string): string {\n const hash = sha256(new TextEncoder().encode(mnemonic.replace(/ /g, '')));\n const base64 = Buffer.from(hash).toString('base64');\n return base64.slice(0, 32);\n}\n\n/**\n * Cleans a home server URL by removing protocol and trailing slashes\n * @param {string} homeServer - the homeserver URL to clean\n * @returns {string} cleaned homeserver URL\n */\nexport function cleanMatrixHomeServerUrl(homeServer: string): string {\n return homeServer.replace(/^(https?:\\/\\/)/, '').replace(/\\/$/, '');\n}\n\n/**\n * Generates a room name from an account address, used for matrix user room where user can manage their own data\n * @param {string} address - the address of the user\n * @param {string} postpend - the postpend of the room name (for testing)\n * @returns {string} roomName\n */\nexport function generateUserRoomNameFromAddress(address: string, postpend = ''): string {\n return 'did-ixo-' + address + postpend;\n}\n\n/**\n * Generates a room alias from an account address, used for matrix user room where user can manage their own data\n * @param {string} address - the address of the user\n * @param {string} postpend - the postpend of the room alias (for testing)\n * @returns {string} roomAlias\n */\nexport function generateUserRoomAliasFromAddress(address: string, homeServerUrl: string): string {\n return '#' + generateUserRoomNameFromAddress(address) + ':' + cleanMatrixHomeServerUrl(homeServerUrl);\n}\n\n/**\n * Get the base URL for a given servername.\n * @param servername The servername to get the base URL for.\n * @returns The base URL for the servername.\n */\nexport async function getBaseUrl(servername: string): Promise<string> {\n let protocol = 'https://';\n if (/^https?:\\/\\//.test(servername)) {\n protocol = '';\n }\n const serverDiscoveryUrl = `${protocol}${servername}${WELL_KNOWN_URI}`;\n try {\n const response = await fetch(serverDiscoveryUrl, { method: 'GET' });\n const result = await response.json();\n const baseUrl = (result as { 'm.homeserver': { base_url: string } })['m.homeserver']?.base_url;\n if (baseUrl === undefined) {\n throw new Error();\n }\n return baseUrl;\n } catch (e) {\n return `${protocol}${servername}`;\n }\n}\n\n/**\n * Normalize a username by removing leading '@' and trimming whitespace.\n * @param {string} rawUsername - The raw username to normalize.\n * @returns {string} The normalized username.\n */\nexport function normalizeUsername(rawUsername: string): string {\n const noLeadingAt = rawUsername.indexOf('@') === 0 ? rawUsername.substring(1) : rawUsername;\n return noLeadingAt.trim();\n}\n\n/**\n * Generates the authentication identifier for matrix login\n * @param {string} password - the password for the matrix account\n * @returns {object} authId - the authentication identifier\n */\nexport function getAuthId({ userId, password }: { userId: string; password: string }): {\n type: string;\n password: string;\n identifier: { type: string; user: string };\n} {\n return {\n type: 'm.login.password',\n password,\n identifier: {\n type: 'm.id.user',\n user: userId,\n },\n };\n}\n","const secretStorageKeys = new Map();\n\nexport function storePrivateKey(keyId: string, privateKey: Uint8Array) {\n if (privateKey instanceof Uint8Array === false) {\n throw new Error('Unable to store, privateKey is invalid.');\n }\n\n secretStorageKeys.set(keyId, privateKey);\n}\n\nexport function hasPrivateKey(keyId: string) {\n return secretStorageKeys.get(keyId) instanceof Uint8Array;\n}\n\nexport function getPrivateKey(keyId: string) {\n return secretStorageKeys.get(keyId);\n}\n\nexport function deletePrivateKey(keyId: string) {\n secretStorageKeys.delete(keyId);\n}\n\nexport function clearSecretStorageKeys() {\n secretStorageKeys.clear();\n}\n\nexport async function getSecretStorageKey({ keys }: { keys: any }): Promise<[string, Uint8Array] | null> {\n const keyIds = Object.keys(keys);\n const keyId = keyIds.find(hasPrivateKey);\n console.info('[] getSecretStorageKey', keys, keyIds, keyId);\n\n if (!keyId) {\n return null;\n }\n\n const privateKey = getPrivateKey(keyId);\n\n return [keyId, privateKey];\n}\n\nexport function cacheSecretStorageKey(keyId: string, keyInfo: any, privateKey: Uint8Array) {\n secretStorageKeys.set(keyId, privateKey);\n}\n","import { Bip39, EnglishMnemonic, Secp256k1, sha256, Slip10, Slip10Curve, stringToPath } from '@cosmjs/crypto';\nimport { AccountData, DirectSecp256k1HdWallet, OfflineSigner } from '@cosmjs/proto-signing';\nimport { createQueryClient, createSigningClient, customMessages, ixo, utils } from '@ixo/impactxclient-sdk';\nimport { Service } from '@ixo/impactxclient-sdk/types/codegen/ixo/iid/v1beta1/types';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { createCipheriv, randomBytes } from 'crypto';\nimport { CHAIN_RPC } from '../common';\nimport { decodeGrants, isAllowanceExpired, isAllowanceLimitReached } from './feegrant';\n/**\n * Checks if an iid document (did) exists\n * @param did - The did to check for\n * @returns True if the iid document exists, false otherwise\n */\nexport async function checkIidDocumentExists(did: string, network: NETWORK) {\n if (!network) {\n throw new Error('Network parameter is required but was undefined');\n }\n\n console.log(`🔍 Checking IID document for DID: ${did} on network: ${network}`);\n\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}. Valid networks are: ${Object.keys(CHAIN_RPC).join(', ')}`);\n }\n\n console.log(`🔗 Using RPC URL: ${url}`);\n\n try {\n const queryClient = await createQueryClient(url);\n const iidDocumentResponse = await queryClient.ixo.iid.v1beta1.iidDocument({ id: did });\n if (!iidDocumentResponse?.iidDocument?.id) {\n return false;\n }\n return true;\n } catch (error) {\n if ((error as Error).message?.includes('did document not found') || (error as Error).message?.includes('(22)')) {\n return false;\n }\n console.error('Error checking IID document:', error);\n throw error;\n }\n}\n\n/**\n * Creates an iid document (did)\n * Must be signed by base account mnemonic (not passkey signer)\n * @param did - The did to create iid document for\n * @param offlineSigner - The offline signer to use to create iid document\n */\nexport async function createIidDocument(\n did: string,\n network: NETWORK,\n offlineSigner: OfflineSigner,\n services?: Service[]\n) {\n try {\n const accounts = await offlineSigner.getAccounts();\n const { address, pubkey } = (accounts[0] ?? {}) as AccountData;\n const allowances = await queryAddressAllowances(address, network);\n const feegrantGranter = allowances?.length\n ? decodeGrants(allowances)?.find(\n (allowance) =>\n !!allowance &&\n !isAllowanceExpired(allowance.expiration as number) &&\n !isAllowanceLimitReached(allowance.limit)\n )?.granter\n : undefined;\n const trx = {\n typeUrl: '/ixo.iid.v1beta1.MsgCreateIidDocument',\n value: ixo.iid.v1beta1.MsgCreateIidDocument.fromPartial({\n id: did,\n verifications: customMessages.iid.createIidVerificationMethods({\n did: did,\n pubkey: pubkey,\n address: address,\n controller: did,\n type: 'secp',\n }),\n signer: address,\n controllers: [did],\n ...(services?.length ? { services: services } : {}),\n }),\n };\n // if (!feegrantGranter) {\n // throw new Error('No feegrant granter found');\n // }\n await signAndBroadcastWithMnemonic({\n offlineSigner: offlineSigner,\n messages: [trx],\n feegrantGranter: feegrantGranter as string,\n network,\n });\n } catch (error) {\n console.error(error);\n throw error;\n }\n}\n\nexport async function queryAddressAllowances(address: string, network: NETWORK) {\n try {\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}`);\n }\n const queryClient = await createQueryClient(url);\n const allowancesResponse = await queryClient.cosmos.feegrant.v1beta1.allowances({\n grantee: address,\n });\n return allowancesResponse?.allowances ?? [];\n } catch (error) {\n console.error('queryAddressAllowances::', (error as Error).message);\n return undefined;\n }\n}\n\n/**\n * Signs and broadcasts a transaction with a mnemonic\n * @param offlineSigner - The offline signer\n * @param messages - The messages to sign and broadcast\n * @param memo - The memo for the transaction\n * @param feegrantGranter - The granter for the transaction\n * @returns The deliver tx response\n */\nexport const signAndBroadcastWithMnemonic = async ({\n offlineSigner,\n messages,\n memo = 'Signing with Mnemonic Demo',\n feegrantGranter,\n network,\n}: {\n offlineSigner: OfflineSigner;\n messages: any[];\n memo?: string;\n feegrantGranter: string;\n network: NETWORK;\n}) => {\n const url = CHAIN_RPC[network];\n if (!url) {\n throw new Error(`Invalid network: ${network}`);\n }\n const signingClient = await createSigningClient(url, offlineSigner);\n const accounts = await offlineSigner.getAccounts();\n const { address } = (accounts[0] ?? {}) as AccountData;\n\n const simGas = await signingClient.simulate(address, messages, memo);\n const gasUsed = simGas > 50000 ? simGas : (messages ?? []).length * 500000;\n const gas = gasUsed * 1.7;\n const gasOptions = calculateTrxGasOptions(gas);\n const fee = {\n amount: [\n {\n denom: 'uixo',\n amount: String(Math.round(gasOptions.average)),\n },\n ],\n gas: String(Math.round(gas)),\n granter: feegrantGranter,\n };\n const result = await signingClient.signAndBroadcast(address, messages, fee, memo, undefined);\n const isDeliverTxFailure = !!result.code;\n if (isDeliverTxFailure) {\n throw new Error(\n `Error when broadcasting tx ${result.transactionHash} at height ${result.height}. Code: ${result.code}; Raw log: ${result.rawLog}`\n );\n }\n};\n\nconst calculateTrxGasOptions = (gasUsed: number) => {\n const gasPriceStep = {\n low: 0.02,\n average: 0.035,\n high: 0.045,\n };\n const gas = gasUsed < 0.01 ? 0.01 : gasUsed;\n const gasOptions = {\n low: gas * gasPriceStep.low,\n average: gas * gasPriceStep.average,\n high: gas * gasPriceStep.high,\n };\n\n return gasOptions;\n};\n\nexport const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nexport function encrypt(text: string, password: string) {\n const iv = randomBytes(16);\n\n const cipher = createCipheriv('aes-256-cbc', Buffer.from(password.padEnd(32)), iv);\n let encrypted = cipher.update(text);\n encrypted = Buffer.concat([encrypted, cipher.final()]);\n return iv.toString('hex') + ':' + encrypted.toString('hex');\n}\n\nexport type SecpClient = Awaited<ReturnType<typeof getSecpClient>>;\nexport const getSecpClient = async (mnemonic: string) => {\n const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {\n prefix: 'ixo',\n });\n const account = (await wallet.getAccounts())[0];\n\n // Debug: Derive and verify keys manually for comparison\n const seed = await Bip39.mnemonicToSeed(new EnglishMnemonic(mnemonic));\n const hdPath = stringToPath(\"m/44'/118'/0'/0/0\");\n const slip10Result = Slip10.derivePath(Slip10Curve.Secp256k1, seed, hdPath);\n const privkey = slip10Result.privkey;\n // Derive the compressed public key from the private key\n const keypair = await Secp256k1.makeKeypair(privkey);\n const compressedPubkey = Secp256k1.compressPubkey(keypair.pubkey);\n // Log keys and addresses for comparison\n // console.log({\n // walletPubkey: account!.pubkey ? Buffer.from(account!.pubkey).toString('hex') : 'not available',\n // derivedPubkey: Buffer.from(compressedPubkey).toString('hex'),\n // });\n\n const secpClient = {\n mnemonic,\n did: utils.did.generateSecpDid(account!.address),\n baseAccount: account!,\n\n async getAccounts() {\n return (await wallet.getAccounts()) as AccountData[];\n },\n\n async signDirect(signerAddress: any, signDoc: any) {\n return await wallet.signDirect(signerAddress, signDoc);\n },\n\n /**\n * Sign a message with the secp256k1 private key derived from the mnemonic\n * @param message - The message to sign (usually a challenge string - base64 encoded)\n * @returns The signature as a Uint8Array\n */\n async sign(message: string): Promise<Uint8Array> {\n // Use the wallet's signDirect method to ensure consistent signing\n try {\n // Derive keypair from mnemonic directly\n const seed = await Bip39.mnemonicToSeed(new EnglishMnemonic(mnemonic));\n\n // NOTE: need to do checking here if it produces matched address to signed in one, maybe user is using a different derivation path\n // Use the standard Cosmos HD path (m/44'/118'/0'/0/0)\n const hdPath = stringToPath(\"m/44'/118'/0'/0/0\");\n\n // Derive the private key using SLIP-10\n const { privkey } = Slip10.derivePath(Slip10Curve.Secp256k1, seed, hdPath);\n\n // For the challenge (base64 encoded string), decode to get the original bytes\n const challengeBytes = new Uint8Array(Buffer.from(message, 'base64'));\n\n // Hash the challenge bytes using SHA-256\n const messageHash = sha256(challengeBytes);\n\n // Sign the hash with the derived private key\n const signature = await Secp256k1.createSignature(messageHash, privkey);\n\n // Get the fixed-length signature, which is r (32 bytes) | s (32 bytes) | recovery param (1 byte)\n const fixedLengthSignature = signature.toFixedLength();\n\n // Remove the recovery parameter byte (last byte) to get only r and s\n // This gives us exactly 64 bytes which is what the verification expects\n return fixedLengthSignature.slice(0, 64);\n } catch (error) {\n console.error('Error during signature creation:', error);\n throw error;\n }\n },\n };\n\n return secpClient;\n};\n","import { Coin, DecodeObject } from '@cosmjs/proto-signing';\nimport { createRegistry, utils } from '@ixo/impactxclient-sdk';\nimport { Grant } from '@ixo/impactxclient-sdk/types/codegen/cosmos/feegrant/v1beta1/feegrant';\nimport { Timestamp } from '@ixo/impactxclient-sdk/types/codegen/google/protobuf/timestamp';\n\n/**\n * Converts a timestamp object to a timestamp\n * @param timestamp - The timestamp object to convert\n * @returns The timestamp\n */\nexport function convertTimestampObjectToTimestamp(timestamp: Timestamp): number | undefined {\n try {\n const date = utils.proto.fromTimestamp(timestamp);\n\n return date.getTime();\n } catch (error) {\n return undefined;\n }\n}\n\nexport enum FeegrantTypes {\n BASIC_ALLOWANCE = 'BasicAllowance',\n PERIODIC_ALLOWANCE = 'PeriodicAllowance',\n}\n\nexport const FEEGRANT_TYPES: Record<FeegrantTypes, string> = {\n BasicAllowance: '/cosmos.feegrant.v1beta1.BasicAllowance',\n PeriodicAllowance: '/cosmos.feegrant.v1beta1.PeriodicAllowance',\n};\n\n/**\n * Decodes the grant values from the the user's list of allowances\n * @param grants - The grants to decode\n * @returns The decoded grants\n */\nexport const decodeGrants = (grants: Grant[]) => {\n const registry = createRegistry();\n\n return (grants ?? []).map((grant) => {\n const allowance = grant.allowance as DecodeObject;\n const decodedAllowance = registry.decode(allowance);\n // decodedAllowance.\n switch (allowance.typeUrl) {\n case FEEGRANT_TYPES.BasicAllowance:\n return {\n granter: grant.granter,\n grantee: grant.grantee,\n type: FEEGRANT_TYPES.BasicAllowance,\n expiration: decodedAllowance.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.expiration)\n : null,\n limit: decodedAllowance.spendLimit?.length\n ? decodedAllowance.spendLimit.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : null,\n msgs: [],\n };\n case FEEGRANT_TYPES.PeriodicAllowance:\n return {\n granter: grant.granter,\n grantee: grant.grantee,\n type: FEEGRANT_TYPES.PeriodicAllowance,\n expiration: decodedAllowance.basic?.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.basic.expiration)\n : null,\n limit: decodedAllowance?.periodCanSpend\n ? decodedAllowance?.periodCanSpend?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : decodedAllowance?.basic?.spendLimit?.length\n ? decodedAllowance?.basic?.spendLimit?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : null,\n msgs: [],\n };\n default:\n return {\n type: allowance.typeUrl,\n granter: grant.granter,\n grantee: grant.grantee,\n expiration: decodedAllowance.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.expiration)\n : decodedAllowance.basic?.expiration\n ? convertTimestampObjectToTimestamp(decodedAllowance.basic.expiration)\n : null,\n limit: decodedAllowance.spendLimit?.length\n ? decodedAllowance.spendLimit.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : decodedAllowance?.periodCanSpend\n ? decodedAllowance?.periodCanSpend?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : decodedAllowance?.basic?.spendLimit?.length\n ? decodedAllowance?.basic?.spendLimit?.find((limit: Coin) => limit.denom === 'uixo')?.amount\n : null,\n msgs: decodedAllowance.allowedMessages,\n };\n }\n });\n};\n\n/**\n * Checks if the allowance has expired\n * @param expiration - The expiration of the allowance\n * @returns True if the allowance has expired, false otherwise\n */\nexport const isAllowanceExpired = (expiration: number | Timestamp) => {\n if (expiration === null || expiration === undefined) {\n return false;\n }\n const expirationTimestamp =\n typeof expiration === 'object' ? convertTimestampObjectToTimestamp(expiration) : expiration;\n if (expirationTimestamp === undefined || expirationTimestamp === null) {\n // failed to decode or convert - assume expired\n return true;\n }\n return expirationTimestamp < Date.now();\n};\n\n/**\n * Checks if the allowance limit has been reached\n * @param limit - The limit of the allowance\n * @returns True if the allowance limit has been reached, false otherwise\n */\nexport const isAllowanceLimitReached = (limit: number | string | Coin) => {\n if (limit === null || limit === undefined) {\n return false;\n }\n const limitAmount =\n typeof limit === 'object' ? Number(limit?.amount ?? 0) : typeof limit === 'string' ? Number(limit ?? 0) : limit;\n return limitAmount <= 0.0005;\n};\n","import { ixo, utils } from '@ixo/impactxclient-sdk';\nimport { createMatrixApiClient } from '@ixo/matrixclient-sdk';\n\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { deriveMatrixUrls } from '../common';\nimport {\n checkIsUsernameAvailable,\n createMatrixClient,\n generatePassphraseFromMnemonic,\n generatePasswordFromMnemonic,\n generateUsernameFromAddress,\n generateUserRoomAliasFromAddress,\n hasCrossSigningAccountData,\n mxRegisterWithSecp,\n setupCrossSigning,\n} from './matrix';\nimport { checkIidDocumentExists, createIidDocument, delay, encrypt, getSecpClient } from './utils';\n\nexport interface SimplifiedRegistrationResult {\n address: string;\n did: string;\n mnemonic: string;\n matrixUserId: string;\n matrixRoomId: string;\n matrixMnemonic: string;\n matrixPassword: string;\n matrixAccessToken: string;\n matrixRecoveryPhrase: string;\n matrixHomeServerUrl: string;\n pin: string;\n matrixDeviceName: string;\n}\n\nconst DEVICE_NAME = 'Oracles CLI';\n/**\n * Simplified user registration flow without email verification or passkey authentication\n * Includes: wallet creation, DID creation, Matrix account with secp auth, Matrix room setup, encrypted mnemonic storage\n * @param pin - User PIN for encrypting Matrix mnemonic\n * @param matrixHomeServerUrl - The Matrix homeserver URL to use for registration\n * @returns Registration result with wallet and Matrix account details\n *\n * Note: The returned matrixAccessToken is still valid — the caller is responsible for\n * logging out the oracle's Matrix session after completing any uploads.\n */\nexport async function registerUserSimplified(\n {\n pin,\n oracleName,\n network,\n oracleAvatarUrl,\n matrixHomeServerUrl,\n }: {\n pin: string;\n oracleName: string;\n network: NETWORK;\n oracleAvatarUrl: string;\n matrixHomeServerUrl: string;\n },\n transferTokens: (address: string) => Promise<void>\n): Promise<SimplifiedRegistrationResult> {\n try {\n const { homeServerUrl, roomBotUrl } = deriveMatrixUrls(matrixHomeServerUrl);\n\n // =================================================================================================\n // 1. CREATE WALLET\n // =================================================================================================\n const mnemonic = utils.mnemonic.generateMnemonic();\n const wallet = await getSecpClient(mnemonic);\n const address = wallet.baseAccount.address;\n console.log('✅ Wallet created:', address);\n\n // transfer tokens\n await transferTokens(address);\n\n // =================================================================================================\n // 2. DID CREATION (with {did}#matrix service embedded)\n // =================================================================================================\n const did = utils.did.generateSecpDid(address);\n const didExists = await checkIidDocumentExists(did, network);\n console.log('✅ DID exists:', didExists);\n if (!didExists) {\n console.log('✅ DID does not exist, creating...');\n const matrixService = ixo.iid.v1beta1.Service.fromPartial({\n id: `${did}#matrix`,\n type: 'MatrixHomeServer',\n serviceEndpoint: homeServerUrl,\n });\n await createIidDocument(did, network, wallet, [matrixService]);\n console.log('✅ DID created, waiting 500ms...');\n await delay(500);\n console.log('✅ Checking if DID exists...');\n const didExistsAfterCreation = await checkIidDocumentExists(did, network);\n if (!didExistsAfterCreation) {\n throw new Error('Failed to create DID document');\n }\n }\n console.log('✅ DID created:', did);\n\n // =================================================================================================\n // 3. MATRIX ACCOUNT CREATION\n // =================================================================================================\n const mxMnemonic = utils.mnemonic.generateMnemonic(12);\n const mxUsername = generateUsernameFromAddress(address);\n const mxPassword = generatePasswordFromMnemonic(mxMnemonic);\n const mxPassphrase = generatePassphraseFromMnemonic(mxMnemonic);\n\n // Check if username is available\n const isUsernameAvailable = await checkIsUsernameAvailable({\n homeServerUrl: homeServerUrl,\n username: mxUsername,\n });\n if (!isUsernameAvailable) {\n throw new Error('Matrix account already exists');\n }\n\n // Register using secp256k1 signature (not passkey)\n const account = await mxRegisterWithSecp(address, mxPassword, DEVICE_NAME, wallet, homeServerUrl, roomBotUrl);\n if (!account?.accessToken) {\n throw new Error('Failed to register matrix account');\n }\n console.log('✅ Matrix account created:', account.userId);\n\n // =================================================================================================\n // 4. MATRIX CLIENT SETUP\n // =================================================================================================\n const mxClient = await createMatrixClient({\n homeServerUrl,\n accessToken: account.accessToken,\n userId: account.userId,\n deviceId: account.deviceId,\n });\n\n try {\n await Promise.all([mxClient.setDisplayName(oracleName), mxClient.setAvatarUrl(oracleAvatarUrl)]);\n } catch (error) {\n console.error('Failed to set display name or avatar url:', error);\n }\n\n const matrixApiClient = createMatrixApiClient({\n homeServerUrl: homeServerUrl,\n accessToken: account.accessToken,\n });\n\n // Setup cross signing\n let hasCrossSigning = hasCrossSigningAccountData(mxClient);\n if (!hasCrossSigning) {\n hasCrossSigning = await setupCrossSigning(mxClient, {\n securityPhrase: mxPassphrase,\n password: mxPassword,\n forceReset: true,\n });\n if (!hasCrossSigning) {\n throw new Error('Failed to setup cross signing');\n }\n }\n console.log('✅ Matrix cross-signing setup completed');\n\n // =================================================================================================\n // 5. MATRIX ROOM CREATION/JOIN\n // =================================================================================================\n const mxRoomAlias = generateUserRoomAliasFromAddress(address, account.baseUrl);\n const queryIdResponse = await matrixApiClient.room.v1beta1.queryId(mxRoomAlias).catch(() => undefined);\n let roomId: string = queryIdResponse?.room_id ?? '';\n\n if (!roomId) {\n // Create room via bot\n const response = await fetch(`${roomBotUrl}/room/source`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n did: did,\n userMatrixId: account.userId,\n }),\n });\n if (!response.ok) {\n throw new Error('Failed to create matrix room');\n }\n const data = (await response.json()) as { roomId: string };\n roomId = data.roomId;\n if (!roomId) {\n throw new Error('Failed to create user matrix room');\n }\n }\n\n // Ensure room is joined\n let joinedMembers = await matrixApiClient.room.v1beta1.listJoinedMembers(roomId).catch(() => undefined);\n let joined = !!joinedMembers?.joined?.[account.userId];\n if (!joined) {\n const joinResponse = await matrixApiClient.room.v1beta1.join(roomId);\n if (!joinResponse.room_id) {\n throw new Error('Failed to join matrix room');\n }\n joinedMembers = await matrixApiClient.room.v1beta1.listJoinedMembers(roomId);\n joined = !!joinedMembers?.joined?.[account.userId];\n if (!joined) {\n throw new Error('Failed to join matrix room');\n }\n }\n console.log('✅ Matrix room created/joined:', roomId);\n\n // =================================================================================================\n // 6. ENCRYPT AND STORE MATRIX MNEMONIC\n // =================================================================================================\n const encryptedMnemonic = encrypt(mxMnemonic, pin);\n const storeEncryptedMnemonicResponse = await fetch(\n `${homeServerUrl}/_matrix/client/v3/rooms/${roomId}/state/ixo.room.state.secure/encrypted_mnemonic`,\n {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${account.accessToken as string}`,\n },\n body: JSON.stringify({\n encrypted_mnemonic: encryptedMnemonic,\n }),\n }\n );\n if (!storeEncryptedMnemonicResponse.ok) {\n throw new Error('Failed to store encrypted mnemonic in matrix room');\n }\n await storeEncryptedMnemonicResponse.json();\n console.log('✅ Encrypted Matrix mnemonic stored in room');\n\n // =================================================================================================\n // 7. STOP MATRIX CLIENT (but do NOT logout — access token is needed for subsequent uploads)\n // The caller is responsible for logging out when done with the oracle's credentials.\n // =================================================================================================\n mxClient.stopClient();\n\n // =================================================================================================\n // 8. RETURN REGISTRATION RESULT\n // =================================================================================================\n return {\n address: address,\n did: did,\n mnemonic: mnemonic, // Wallet mnemonic - store securely!\n matrixUserId: account.userId,\n matrixRoomId: roomId,\n matrixMnemonic: mxMnemonic, // Matrix mnemonic - also store securely!\n matrixPassword: mxPassword,\n matrixAccessToken: account.accessToken,\n matrixRecoveryPhrase: mxPassphrase,\n matrixHomeServerUrl: homeServerUrl,\n pin: pin,\n matrixDeviceName: DEVICE_NAME,\n };\n } catch (error) {\n console.error('Simplified registration failed:', error);\n throw error;\n }\n}\n","import { createMatrixApiClient, utils as mxUtils } from '@ixo/matrixclient-sdk';\nimport { UploadContentType } from '@ixo/matrixclient-sdk/types/api/media/v1beta1';\nimport { createCIDFromBase64, jsonToBase64 } from '../createCIDFromBase64';\n\nexport const publicUpload = async ({\n data,\n fileName,\n homeServerUrl,\n accessToken,\n}: {\n data: object;\n fileName: string;\n homeServerUrl: string;\n accessToken: string;\n}) => {\n const matrixAPIClient = createMatrixApiClient({\n homeServerUrl,\n accessToken,\n });\n\n // Create a simple Buffer instead of using File - this works reliably with node-fetch\n const fileContent = JSON.stringify(data);\n const fileBuffer = Buffer.from(fileContent, 'utf8');\n const fullFileName = fileName + '.json';\n const contentType = 'application/ld+json';\n\n // Pass the buffer directly - node-fetch can handle this reliably in all environments\n const response = await matrixAPIClient.media.v1beta1.upload(\n fullFileName,\n contentType as UploadContentType,\n fileBuffer\n );\n const httpUrl = mxUtils.mxc.mxcUrlToHttp(\n homeServerUrl,\n response.content_uri // the mxc url\n );\n\n if (!httpUrl) {\n throw new Error('Failed to upload file to Matrix');\n }\n\n const jsonString = JSON.stringify(data);\n const base64String = jsonToBase64(jsonString);\n const cid = await createCIDFromBase64(base64String);\n\n return {\n encrypted: 'false',\n cid,\n proof: cid,\n serviceEndpoint: httpUrl,\n mxc: response.content_uri,\n };\n};\n","import { CID } from 'multiformats';\nimport { base64 } from 'multiformats/bases/base64';\nimport * as mfsha2 from 'multiformats/hashes/sha2';\n\nexport async function createCIDFromBase64(base64String: string): Promise<string> {\n // Add 'm' prefix if not present\n const multibaseString = base64String.startsWith('m') ? base64String : 'm' + base64String;\n\n // Decode base64 to bytes\n const bytes = base64.decode(multibaseString);\n\n // Create SHA-256 hash of the bytes\n const hash = await mfsha2.sha256.digest(bytes);\n\n // Create CID (using SHA-256 and RAW codec)\n const cid = CID.create(1, 0x55, hash);\n\n return cid.toString();\n}\n\nexport function jsonToBase64(jsonString: string): string {\n const uint8Array = new TextEncoder().encode(jsonString);\n return btoa(String.fromCharCode(...Array.from(uint8Array)));\n}\n","import * as p from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport { registerUserSimplified } from '../utils/account/simplifiedRegistration';\nimport { logoutMatrixClient } from '../utils/account/matrix';\nimport { checkRequiredMatrixUrl, checkRequiredPin, checkRequiredString, MatrixHomeServerUrl, selectNetwork } from '../utils/common';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\n\nexport class CreateUserCommand implements Command {\n name = 'create-user';\n description = 'Create a new user';\n constructor(private wallet: Wallet, private config: RuntimeConfig) {}\n async execute(): Promise<CLIResult> {\n const network = this.config.getValue('network') as NETWORK;\n if (!network) {\n await selectNetwork(this.config);\n }\n\n // Determine default Matrix homeserver URL from wallet or static map\n const defaultMatrixUrl =\n this.wallet.matrixHomeServer ?? MatrixHomeServerUrl[(this.config.getValue('network') as NETWORK) ?? 'devnet'];\n\n const matrixHomeServerUrl = await p.text({\n message: 'Matrix homeserver URL:',\n initialValue: defaultMatrixUrl,\n defaultValue: defaultMatrixUrl,\n validate(value) {\n return checkRequiredMatrixUrl(value);\n },\n });\n if (p.isCancel(matrixHomeServerUrl)) {\n p.log.error('User cancelled');\n process.exit(1);\n }\n\n const pin = await p.text({\n message: 'Enter a 6-digit PIN to secure your Matrix Vault:',\n placeholder: '123456',\n validate(value) {\n return checkRequiredPin(value);\n },\n });\n if (p.isCancel(pin)) {\n p.log.error('User cancelled');\n process.exit(1);\n }\n const oracleName = await p.text({\n message: 'Enter your oracle name',\n initialValue: 'My oracle',\n validate(value) {\n return checkRequiredString(value, 'Oracle name is required');\n },\n });\n if (p.isCancel(oracleName)) {\n p.log.error('User cancelled');\n process.exit(1);\n }\n const user = await registerUserSimplified(\n {\n pin,\n oracleName,\n network: (this.config.getValue('network') as NETWORK) ?? network,\n oracleAvatarUrl: `https://api.dicebear.com/8.x/bottts/svg?seed=${oracleName}`,\n matrixHomeServerUrl,\n },\n async (address) => {\n await this.wallet.sendTokens(address, 150_000); // 150,000 uixo = 0.15 IXO;\n }\n );\n\n // Logout oracle's Matrix session since create-user doesn't need it after\n await logoutMatrixClient({\n baseUrl: user.matrixHomeServerUrl,\n accessToken: user.matrixAccessToken,\n userId: user.matrixUserId,\n deviceId: '',\n });\n\n return { success: true, data: user };\n }\n}\n","import { CLIResult } from '../types';\nimport { Command, CommandRegistry } from './index';\n\nexport class HelpCommand implements Command {\n name = 'help';\n description = 'Show help information and available commands';\n\n constructor(private registry: CommandRegistry) {}\n\n async execute(): Promise<CLIResult> {\n const commands = this.registry.getAll();\n\n const helpText = `\nIXO Oracles CLI - Help\n\nUSAGE:\n oracles-cli [command] [options]\n\nCOMMANDS:\n${commands.map((cmd) => ` ${cmd.name.padEnd(15)} ${cmd.description}`).join('\\n')}\n\nEXAMPLES:\n oracles-cli --init Initialize a new IXO Oracle project\n oracles-cli Launch interactive menu\n oracles-cli help Show this help message\n\nOPTIONS:\n --init Initialize a new project (shortcut)\n --help, -h Show help information\n\nFor more information, visit: https://github.com/ixoworld/ixo-oracles-cli\n`;\n\n return {\n success: true,\n data: helpText,\n };\n }\n}\n","import * as p from '@clack/prompts';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport simpleGit from 'simple-git';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport { createProjectEnvFile } from '../utils/create-project-env-file';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\nimport { CreateEntityCommand } from './create-entity-command';\n\nexport class InitCommand implements Command {\n name = 'init';\n description = 'Initialize Project';\n\n constructor(private readonly config: RuntimeConfig, private readonly wallet: Wallet) {}\n\n private async getProjectInput(): Promise<{ projectPath: string; projectName: string }> {\n // Get the input from user (could be path, name, or both)\n const input = await p.text({\n message: 'What is your project named?',\n placeholder: 'my-ixo-project',\n validate(value) {\n if (!value) {\n return 'Project name is required';\n }\n return undefined;\n },\n });\n\n if (p.isCancel(input)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n // Parse the input to determine if it's a path, name, or both\n const inputStr = String(input);\n let projectPath: string;\n let projectName: string;\n\n // Check if input contains path separators (is a path)\n if (inputStr.includes('/') || inputStr.includes('\\\\')) {\n // Input is a path\n projectPath = inputStr;\n projectName = path.basename(inputStr);\n } else {\n // Input is just a name, create in current directory\n projectName = inputStr;\n projectPath = path.join(process.cwd(), projectName);\n }\n\n // Ensure the project name is valid\n if (!this.isValidProjectName(projectName)) {\n p.note('Invalid project name. Using a valid name instead.', 'Warning');\n projectName = this.sanitizeProjectName(projectName);\n projectPath = path.join(path.dirname(projectPath), projectName);\n }\n\n return { projectPath, projectName };\n }\n\n private isValidProjectName(name: string): boolean {\n // Check if name is valid (no special characters, starts with letter, etc.)\n const validNameRegex = /^[a-zA-Z][a-zA-Z0-9-_]*$/;\n return validNameRegex.test(name) && name.length > 0 && name.length <= 50;\n }\n\n private sanitizeProjectName(name: string): string {\n // Convert invalid characters to valid ones\n return name\n .replace(/[^a-zA-Z0-9-_]/g, '-')\n .replace(/^-+|-+$/g, '') // Remove leading/trailing dashes\n .toLowerCase()\n .substring(0, 50);\n }\n\n private async confirmProjectCreation(projectPath: string, projectName: string): Promise<boolean> {\n const isDirExists = existsSync(projectPath);\n\n if (isDirExists) {\n const overwrite = await p.confirm({\n message: `Directory \"${projectPath}\" already exists. Do you want to overwrite it?`,\n initialValue: false,\n });\n\n if (p.isCancel(overwrite)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n return overwrite;\n }\n\n // Show confirmation for new project\n const confirm = await p.confirm({\n message: `Create IXO project \"${projectName}\" in \"${projectPath}\"?`,\n initialValue: true,\n });\n\n if (p.isCancel(confirm)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n return confirm;\n }\n\n private async selectRepo() {\n const repo = await p.select({\n message: 'Select a template to clone',\n options: [\n {\n value: 'git@github.com:ixoworld/ixo-oracles-boilerplate.git',\n label: 'IXO Oracles (Default)',\n },\n {\n label: 'Custom template',\n value: 'custom',\n },\n ],\n });\n\n if (p.isCancel(repo)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n if (repo === 'custom') {\n const customRepo = await p.text({\n message: 'Enter the custom template URL',\n });\n\n if (p.isCancel(customRepo)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n\n return customRepo;\n }\n\n return repo;\n }\n\n private async cloneRepo(repo: string, projectPath: string, shouldOverwrite: boolean = false) {\n const git = simpleGit();\n const cloneSpinner = p.spinner();\n\n try {\n cloneSpinner.start('Cloning repository...');\n\n // If overwriting, remove the existing directory first\n if (shouldOverwrite && existsSync(projectPath)) {\n const { rmSync } = await import('fs');\n rmSync(projectPath, { recursive: true, force: true });\n }\n\n // Create directory if it doesn't exist\n\n await git.clone(repo, projectPath);\n\n // Clean repo and create new git\n const gitFolder = path.join(projectPath, '.git');\n if (existsSync(gitFolder)) {\n const { rmSync } = await import('fs');\n rmSync(gitFolder, { recursive: true, force: true });\n }\n await simpleGit(projectPath).init();\n\n cloneSpinner.stop('Repository cloned successfully');\n\n p.log.info('Creating Oracle Entity and Matrix Account');\n const command = new CreateEntityCommand(this.wallet, this.config);\n const result = await command.execute();\n if (result.success) {\n p.log.info('Oracle Entity and Matrix Account created successfully');\n } else {\n p.log.error('Failed to create Oracle Entity and Matrix Account');\n }\n\n await createProjectEnvFile(this.config);\n // Show success message with next steps\n p.log.success(\n `\\n✅ IXO project created successfully!\\n\\n` +\n `📁 Location: ${projectPath}\\n` +\n `🚀 Next steps:\\n` +\n ` cd ${path.basename(projectPath)}\\n` +\n ` pnpm install\\n` +\n ` pnpm build \\n` +\n ` cd apps/app\\n` +\n ` pnpm start:dev`\n );\n } catch (error) {\n cloneSpinner.stop('Failed to clone repository');\n throw error;\n }\n }\n\n async execute(): Promise<CLIResult> {\n try {\n // Get project input (path and/or name)\n const { projectPath, projectName } = await this.getProjectInput();\n\n // Confirm project creation\n const shouldProceed = await this.confirmProjectCreation(projectPath, projectName);\n\n if (!shouldProceed) {\n return { success: false, data: 'Project creation cancelled' };\n }\n\n // Store in config\n this.config.addValue('projectPath', projectPath);\n this.config.addValue('projectName', projectName);\n\n // Select repository template\n const repo = await this.selectRepo();\n this.config.addValue('repo', repo);\n\n // Check if we need to overwrite\n const shouldOverwrite = existsSync(projectPath);\n\n // Clone the repository\n await this.cloneRepo(repo, projectPath, shouldOverwrite);\n\n return {\n success: true,\n data: `Project \"${projectName}\" created successfully in \"${projectPath}\"`,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error occurred',\n };\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { mxLogin } from './account/matrix';\nimport { RuntimeConfig } from './runtime-config';\nexport const createProjectEnvFile = async (config: RuntimeConfig) => {\n const oracleMatrixHomeServerUrl = config.getOrThrow('oracleMatrixHomeServerUrl');\n\n const freshMx = await mxLogin({\n homeServerUrl: oracleMatrixHomeServerUrl,\n username: config.getOrThrow('registerUserResult').matrixUserId,\n password: config.getOrThrow('registerUserResult').matrixPassword,\n deviceName: config.getOrThrow('registerUserResult').matrixDeviceName,\n });\n const projectPath = config.getOrThrow('projectPath');\n const envFile = path.join(projectPath, 'apps', 'app', '.env');\n\n console.log('Creating .env file at:', envFile);\n console.log('Project path:', projectPath);\n\n // Ensure the directory exists\n const envDir = path.dirname(envFile);\n if (!fs.existsSync(envDir)) {\n console.log('Creating directory:', envDir);\n fs.mkdirSync(envDir, { recursive: true });\n }\n const envContent = `\nPORT=4000\nORACLE_NAME=${config.getValue('projectName')}\n\n# Matrix\nMATRIX_BASE_URL=${oracleMatrixHomeServerUrl}\nMATRIX_ORACLE_ADMIN_ACCESS_TOKEN=${freshMx.accessToken}\nMATRIX_ORACLE_ADMIN_PASSWORD=${config.getOrThrow('registerUserResult').matrixPassword}\nMATRIX_ORACLE_ADMIN_USER_ID=${config.getOrThrow('registerUserResult').matrixUserId}\nMATRIX_RECOVERY_PHRASE=${config.getOrThrow('registerUserResult').matrixRecoveryPhrase}\n\n# OPENAI\nOPENAI_API_KEY=\n\n# Langfuse\nLANGFUSE_PUBLIC_KEY=\nLANGFUSE_SECRET_KEY=\nLANGFUSE_HOST=https://cloud.langfuse.com\n\nOPEN_ROUTER_API_KEY=\"sk-\"\n\n\n### NOT REQUIRED FOR THE APP BUT SAVE THEM IN SAFE PLACE\n# ORACLE ACCOUNT DETAILS\nORACLE_ADDRESS=${config.getOrThrow('registerUserResult').address}\nORACLE_DID=${config.getOrThrow('registerUserResult').did}\nORACLE_MNEMONIC=${config.getOrThrow('registerUserResult').mnemonic}\nMATRIX_VAULT_PIN=${config.getOrThrow('registerUserResult').pin}\nENTITY_DID=${config.getOrThrow('entityDid')}\n`;\n try {\n fs.writeFileSync(envFile, envContent);\n console.log('✅ .env file created successfully at:', envFile);\n } catch (error) {\n console.error('❌ Failed to create .env file:', error);\n throw error;\n }\n};\n","import { confirm } from '@clack/prompts';\nimport { CLIResult } from '../types';\nimport { Wallet } from '../utils/wallet';\nimport { Command } from './index';\n\nexport class LogoutCommand implements Command {\n name = 'logout';\n description = 'Logout command';\n\n constructor(private wallet: Wallet) {}\n\n async execute(): Promise<CLIResult> {\n const shouldClear = await confirm({\n message: 'Are you sure you want to logout?',\n initialValue: false,\n });\n if (shouldClear) {\n await this.wallet.clearWallet();\n return {\n success: true,\n data: 'Logged out successfully',\n };\n }\n return {\n success: false,\n error: 'Logout cancelled',\n };\n }\n}\n","import { toHex } from '@cosmjs/encoding';\nimport { EncodeObject } from '@cosmjs/proto-signing';\nimport { createRegistry } from '@ixo/impactxclient-sdk';\nimport {\n SignX as IxoSignX,\n SIGN_X_LOGIN_ERROR,\n SIGN_X_LOGIN_SUCCESS,\n SIGN_X_TRANSACT_ERROR,\n SIGN_X_TRANSACT_SUCCESS,\n} from '@ixo/signx-sdk';\nimport { LOGIN_DATA } from '@ixo/signx-sdk/types/types/transact';\nimport qrcode from 'qrcode-terminal';\nimport { WalletProps } from './types';\n\nconst SignXEndpoints = {\n devnet: 'https://signx.devnet.ixo.earth',\n testnet: 'https://signx.testnet.ixo.earth',\n mainnet: 'https://signx.ixo.earth',\n};\n\nexport class SignXClient {\n private readonly signXClient: IxoSignX;\n private _loginData?: LOGIN_DATA;\n public get loginData() {\n return this._loginData;\n }\n\n static loadFromWallet(wallet: WalletProps) {\n return new IxoSignX({\n endpoint: SignXEndpoints[wallet.network],\n sitename: 'IXO Oracles CLI',\n network: wallet.network,\n });\n }\n\n constructor(chainNetwork: keyof typeof SignXEndpoints) {\n this.signXClient = new IxoSignX({\n endpoint: SignXEndpoints[chainNetwork],\n sitename: 'IXO Oracles CLI',\n network: chainNetwork,\n });\n }\n\n async login() {\n const loginData = await this.signXClient.login({ pollingInterval: 2000, matrix: true });\n this._loginData = loginData;\n return loginData;\n }\n\n private displayStyledQRCode(qrCodeData: string | LOGIN_DATA, title: string) {\n const qrCodeStr = typeof qrCodeData === 'string' ? qrCodeData : JSON.stringify(qrCodeData);\n\n // Display title with emoji\n console.log('\\n' + ' '.repeat(5) + '🔐 ' + title);\n console.log(' '.repeat(5) + '📱 Scan with IXO app');\n console.log(' '.repeat(5) + '━'.repeat(30));\n\n // Generate very compact QR code\n qrcode.generate(qrCodeStr, {\n small: true,\n });\n console.log(' '.repeat(5) + '⏳ Waiting...\\n');\n }\n\n public displayQRCode(qrCodeData: string | LOGIN_DATA) {\n this.displayStyledQRCode(qrCodeData, 'Login with SignX');\n }\n\n async awaitLogin() {\n return new Promise<WalletProps>((resolve, reject) => {\n try {\n this.signXClient.on(SIGN_X_LOGIN_SUCCESS, (response: { data: WalletProps }) => {\n if (!response.data) {\n reject(new Error('Login failed'));\n return;\n }\n if (!response.data.matrix) {\n reject(new Error('Matrix login failed'));\n return;\n }\n resolve(response.data); // Resolve the promise with the login success data\n });\n\n this.signXClient.on(SIGN_X_LOGIN_ERROR, (error) => {\n console.log('Login error:', error);\n reject(error); // Reject the promise with the login error\n });\n\n // Use loginRequest data to show QR code to user for scanning by mobile app\n } catch (error) {\n console.error('Error in connecting:', error);\n reject(error); // Reject the promise with any other errors\n }\n });\n }\n\n async transact(messages: readonly EncodeObject[], wallet: WalletProps, memo?: string) {\n const registry = createRegistry();\n\n return this.signXClient.transact({\n address: wallet.address,\n did: wallet.did,\n pubkey: wallet.pubKey,\n timestamp: new Date().toISOString(),\n transactions: [\n {\n sequence: 1,\n txBodyHex: toHex(registry.encodeTxBody({ messages: messages, memo: memo || '' })),\n },\n ],\n });\n }\n\n async awaitTransaction() {\n return new Promise((resolve, reject) => {\n try {\n this.signXClient.on(SIGN_X_TRANSACT_SUCCESS, (result) => {\n resolve(result.data); // Resolve the promise with the login success data\n });\n\n this.signXClient.on(SIGN_X_TRANSACT_ERROR, (error) => {\n reject(error); // Reject the promise with the login error\n });\n // Use loginRequest data to show QR code to user for scanning by mobile app\n } catch (error) {\n console.error('Error in connecting:', error);\n reject(error); // Reject the promise with any other errors\n }\n });\n }\n\n async pollNextTransaction() {\n return this.signXClient.pollNextTransaction();\n }\n\n displayTransactionQRCode(qrCodeData: string) {\n this.displayStyledQRCode(qrCodeData, 'SIGNX TRANSACTION');\n }\n}\n","import { CLIResult } from '../types';\nimport { selectNetwork } from '../utils/common';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { SignXClient } from '../utils/signx/signx';\nimport { Wallet } from '../utils/wallet';\nimport { Command } from './index';\n\nexport class SignXLoginCommand implements Command {\n name = 'signx-login';\n description = 'Login with SignX wallet';\n\n constructor(private wallet: Wallet, private config: RuntimeConfig) {}\n\n async execute(): Promise<CLIResult> {\n try {\n // Select network and create SignX client\n const network = await selectNetwork(this.config);\n const signXClient = new SignXClient(network);\n\n // Start login process\n const loginData = await signXClient.login();\n\n // Display QR code for user to scan\n signXClient.displayQRCode(loginData);\n\n // Wait for login completion\n const loginResult = await signXClient.awaitLogin();\n this.wallet.setWallet(loginResult);\n this.wallet.setSignXClient(signXClient);\n return {\n success: true,\n data: {\n message: 'Successfully logged in with SignX!',\n wallet: {\n address: loginResult.address,\n did: loginResult.did,\n name: loginResult.name,\n },\n },\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? `SignX login failed: ${error.message}` : 'Unknown error',\n };\n }\n }\n}\n","import * as p from '@clack/prompts';\nimport { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { Command } from '.';\nimport { CLIResult } from '../types';\nimport { checkIsEntityDid, selectNetwork } from '../utils/common';\nimport { CreateEntity } from '../utils/entity';\nimport { RuntimeConfig } from '../utils/runtime-config';\nimport { Wallet } from '../utils/wallet';\n\nexport class UpdateEntityCommand implements Command {\n name = 'update-entity';\n description = 'Update an entity (add controllers, etc.)';\n private readonly createEntity: CreateEntity;\n\n constructor(private wallet: Wallet, private config: RuntimeConfig) {\n this.createEntity = new CreateEntity(this.wallet, this.config);\n }\n\n async execute(): Promise<CLIResult> {\n const network = this.config.getValue('network') as NETWORK;\n if (!network) {\n await selectNetwork(this.config);\n }\n\n const results = await p.group(\n {\n entityDid: () =>\n p.text({\n message: 'What is the DID of the entity you want to update?',\n initialValue: this.config.getValue('entityDid')?.toString() ?? '',\n validate(value) {\n return checkIsEntityDid(value);\n },\n }),\n action: () =>\n p.select({\n message: 'What would you like to do?',\n options: [\n {\n value: 'add-controller',\n label: 'Add Controller',\n hint: 'Add a new controller DID to the entity',\n },\n ],\n initialValue: 'add-controller',\n }),\n controllerDid: async ({ results }): Promise<string> => {\n if (results.action !== 'add-controller') {\n throw new Error('Unknown action');\n }\n const did = await p.text({\n message: 'What is the DID of the controller you want to add?',\n validate(value) {\n return checkIsEntityDid(value);\n },\n });\n if (p.isCancel(did)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n return did;\n },\n },\n {\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n try {\n if (results.action === 'add-controller' && typeof results.controllerDid === 'string') {\n const controllerDid = results.controllerDid;\n const entityDid = results.entityDid;\n p.log.info(`Adding controller ${controllerDid} to entity ${entityDid}`);\n await this.createEntity.addControllerToEntity(entityDid, controllerDid);\n p.log.success(`Controller ${controllerDid} successfully added to entity ${entityDid}`);\n return {\n success: true,\n data: `Controller ${controllerDid} added to entity ${entityDid}`,\n };\n }\n\n return {\n success: false,\n error: 'Unknown action',\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n","export class CLIError extends Error {\n constructor(message: string, public code: string = 'CLI_ERROR', public suggestions?: string[]) {\n super(message);\n this.name = 'CLIError';\n }\n}\n\nexport class ConfigError extends CLIError {\n constructor(message: string, suggestions?: string[]) {\n super(message, 'CONFIG_ERROR', suggestions);\n this.name = 'ConfigError';\n }\n}\n\nexport class NetworkError extends CLIError {\n constructor(message: string, suggestions?: string[]) {\n super(message, 'NETWORK_ERROR', suggestions);\n this.name = 'NetworkError';\n }\n}\n\nexport class ValidationError extends CLIError {\n constructor(message: string, suggestions?: string[]) {\n super(message, 'VALIDATION_ERROR', suggestions);\n this.name = 'ValidationError';\n }\n}\n\nexport function handleError(error: unknown): never {\n if (error instanceof CLIError) {\n console.error(`\\n❌ ${error.name}: ${error.message}`);\n if (error.suggestions?.length) {\n console.error('\\nSuggestions:');\n error.suggestions.forEach((suggestion) => console.error(` • ${suggestion}`));\n }\n process.exit(1);\n }\n\n if (error instanceof Error) {\n console.error(`\\n❌ Unexpected Error: ${error.message}`);\n if (error.stack) {\n console.error('\\nStack trace:');\n console.error(error.stack);\n }\n process.exit(1);\n }\n\n console.error('\\n❌ Unknown error occurred' , error);\n process.exit(1);\n}\n","import { NETWORK } from '@ixo/signx-sdk/types/types/transact';\nimport { SimplifiedRegistrationResult } from './account/simplifiedRegistration';\n\ninterface Config {\n authZFile: string;\n feesFile: string;\n projectPath: string;\n projectName: string;\n entityDid: string;\n network: NETWORK;\n repo: string;\n oracleMatrixHomeServerUrl: string;\n registerUserResult: SimplifiedRegistrationResult & {\n matrixDeviceName: string;\n };\n}\n\nexport class RuntimeConfig {\n private config: Partial<Config> = {};\n private static instance: RuntimeConfig;\n private constructor() {}\n\n public static getInstance(): RuntimeConfig {\n if (!RuntimeConfig.instance) {\n RuntimeConfig.instance = new RuntimeConfig();\n }\n return RuntimeConfig.instance;\n }\n\n public addValue<K extends keyof Config>(key: K, value: Config[K]) {\n this.config[key] = value;\n }\n\n public getValue(key: keyof Config) {\n return this.config[key];\n }\n\n public getOrThrow<K extends keyof Config>(key: K): Config[K] {\n const value = this.getValue(key);\n if (!value) {\n throw new Error(`Value ${key} is not set`);\n }\n return value as Config[K];\n }\n\n public getConfig() {\n return this.config;\n }\n\n public deleteValue(key: keyof Config) {\n delete this.config[key];\n }\n}\n","import { log } from '@clack/prompts';\nimport { cosmos } from '@ixo/impactxclient-sdk';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { unlink } from 'fs/promises';\nimport os from 'os';\nimport path from 'path';\nimport { RuntimeConfig } from './runtime-config';\nimport { SignXClient } from './signx/signx';\nimport { WalletProps } from './signx/types';\n\n// Use hidden .wallet.json file in user's home directory\nconst WALLET_PATH = path.join(os.homedir(), '.wallet.json');\n\n// for dev make it here\n// const WALLET_PATH = path.join(__dirname, '.wallet.json');\n\nexport class Wallet {\n public wallet: WalletProps | undefined;\n public signXClient?: SignXClient;\n private config: RuntimeConfig;\n constructor(config: RuntimeConfig) {\n this.config = config;\n this.loadWallet();\n }\n\n public setSignXClient(signXClient: SignXClient) {\n this.signXClient = signXClient;\n }\n\n private loadWallet() {\n if (existsSync(WALLET_PATH)) {\n try {\n const walletData = readFileSync(WALLET_PATH, 'utf8');\n this.wallet = JSON.parse(walletData) as WalletProps;\n\n // Validate that matrix userId is present — required for homeserver derivation\n if (!this.wallet.matrix?.userId || !this.wallet.matrix.userId.includes(':')) {\n log.warning('Wallet is missing valid Matrix credentials. Please re-authenticate via SignX.');\n this.wallet = undefined;\n return;\n }\n\n // Use wallet.network directly from WalletProps (provided by SignX)\n let network = this.wallet.network;\n\n // Fallback: derive network from matrix domain for wallets saved before network field was added\n if (!network) {\n const mxDomain = this.wallet.matrix.userId.split(':')[1];\n const mxDomainToNetwork = {\n 'devmx.ixo.earth': 'devnet',\n 'testmx.ixo.earth': 'testnet',\n 'mx.ixo.earth': 'mainnet',\n } as const;\n network = mxDomainToNetwork[mxDomain as keyof typeof mxDomainToNetwork];\n if (!network) {\n throw new Error(`Cannot determine network from matrix domain: ${mxDomain}`);\n }\n this.wallet.network = network;\n }\n\n this.config.addValue('network', network);\n\n // set signx client\n this.setSignXClient(new SignXClient(network));\n log.success(`Welcome back, ${this.wallet.name}!`);\n log.info(`Network: ${network}`);\n } catch (error) {\n log.warning(`Failed to load wallet file: ${error instanceof Error ? error.message : String(error)}`);\n this.wallet = undefined;\n }\n } else {\n log.warning('No wallet file found');\n }\n }\n\n setWallet(wallet: WalletProps) {\n try {\n this.wallet = wallet;\n\n const walletJson = JSON.stringify(wallet, null, 2);\n writeFileSync(WALLET_PATH, walletJson, 'utf8');\n log.success(`Wallet saved successfully to: ${WALLET_PATH}`);\n } catch (error) {\n log.error(`Failed to save wallet: ${error instanceof Error ? error.message : String(error)}`);\n throw new Error('Failed to save wallet file');\n }\n }\n\n public checkWalletExists() {\n return existsSync(WALLET_PATH) && this.wallet !== undefined;\n }\n\n public async clearWallet() {\n this.wallet = undefined;\n try {\n if (existsSync(WALLET_PATH)) {\n await unlink(WALLET_PATH);\n log.success('Wallet file deleted successfully');\n }\n } catch (error) {\n log.error(`Failed to delete wallet file: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n get did() {\n return this.wallet?.did;\n }\n\n get address() {\n return this.wallet?.address;\n }\n\n get name() {\n return this.wallet?.name;\n }\n\n get pubKey() {\n return this.wallet?.pubKey;\n }\n\n get algo() {\n return this.wallet?.algo;\n }\n\n get matrix() {\n return this.wallet?.matrix;\n }\n\n /**\n * Extracts the Matrix homeserver URL from the user's matrix userId.\n * e.g. @user:devmx.ixo.earth → https://devmx.ixo.earth\n */\n get matrixHomeServer(): string | undefined {\n const userId = this.wallet?.matrix?.userId;\n if (!userId || !userId.includes(':')) return undefined;\n const domain = userId.split(':')[1];\n return `https://${domain}`;\n }\n\n public reloadWallet() {\n this.loadWallet();\n }\n\n async sendTokens(address: string, amount: number) {\n if (!this.address || !this.signXClient || !this.wallet) {\n throw new Error('Wallet not loaded');\n }\n const sendTokensToUserMsg = {\n typeUrl: '/cosmos.bank.v1beta1.MsgSend',\n value: cosmos.bank.v1beta1.MsgSend.fromPartial({\n fromAddress: this.address,\n toAddress: address,\n amount: [\n cosmos.base.v1beta1.Coin.fromPartial({\n amount: amount.toString(),\n denom: 'uixo',\n }),\n ],\n }),\n };\n const tx = await this.signXClient?.transact([sendTokensToUserMsg], this.wallet);\n this.signXClient?.displayTransactionQRCode(JSON.stringify(tx));\n await this.signXClient?.pollNextTransaction();\n const response = await this.signXClient?.awaitTransaction();\n return response;\n }\n}\n"],"mappings":"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","names":["cancel","intro","isCancel","log","outro","select","spinner","process","CommandRegistry","command","name","cmd","p","select","z","selectNetwork","config","network","RELAYER_NODE_DID","MatrixHomeServerUrl","PORTAL_URL","CHAIN_RPC","DOMAIN_INDEXER_URL","checkRequiredString","value","message","result","z","checkIsEntityDid","checkRequiredURL","checkRequiredNumber","checkRequiredPin","v","checkRequiredMatrixUrl","deriveMatrixUrls","homeServerUrl","url","domain","protocol","isCancel","log","spinner","text","customMessages","ixo","utils","sha256","eciesEncrypt","ClientEvent","createClient","md5","secretStorageKeys","hasPrivateKey","keyId","secretStorageKeys","getPrivateKey","clearSecretStorageKeys","secretStorageKeys","getSecretStorageKey","keys","keyIds","keyId","hasPrivateKey","privateKey","getPrivateKey","cacheSecretStorageKey","keyInfo","Bip39","EnglishMnemonic","Secp256k1","sha256","Slip10","Slip10Curve","stringToPath","DirectSecp256k1HdWallet","createQueryClient","createSigningClient","customMessages","ixo","utils","createCipheriv","randomBytes","createRegistry","utils","convertTimestampObjectToTimestamp","timestamp","FEEGRANT_TYPES","decodeGrants","grants","registry","createRegistry","grant","allowance","decodedAllowance","convertTimestampObjectToTimestamp","limit","isAllowanceExpired","expiration","expirationTimestamp","isAllowanceLimitReached","checkIidDocumentExists","did","network","url","CHAIN_RPC","createQueryClient","error","createIidDocument","offlineSigner","services","accounts","address","pubkey","allowances","queryAddressAllowances","feegrantGranter","decodeGrants","allowance","isAllowanceExpired","isAllowanceLimitReached","trx","ixo","customMessages","signAndBroadcastWithMnemonic","messages","memo","signingClient","createSigningClient","simGas","gas","gasOptions","calculateTrxGasOptions","fee","result","gasUsed","gasPriceStep","delay","ms","resolve","encrypt","text","password","iv","randomBytes","cipher","createCipheriv","encrypted","getSecpClient","mnemonic","wallet","DirectSecp256k1HdWallet","account","seed","Bip39","EnglishMnemonic","hdPath","stringToPath","privkey","Slip10","Slip10Curve","keypair","Secp256k1","compressedPubkey","utils","signerAddress","signDoc","message","challengeBytes","messageHash","sha256","WELL_KNOWN_URI","mxLogin","homeServerUrl","username","password","deviceName","localMatrix","mxHomeServerUrl","mxUsername","mxIdMatch","getBaseUrl","client","createTemporaryClient","response","normalizeUsername","error","msg","getPublicKeyForEncryption","roomBotUrl","createUserCreationChallenge","address","challenge","challengeBase64","encryptPasswordWithECIES","publicKey","publicKeyBytes","passwordBytes","encryptedPassword","eciesEncrypt","byte","createUserAccountWithSecp","signature","publicKeyInfo","request","responseText","errorMessage","errorData","mxRegisterWithSecp","wallet","signatureBytes","generateUsernameFromAddress","checkIsUsernameAvailable","createClient","createMatrixClient","accessToken","userId","deviceId","mxClient","getSecretStorageKey","cacheSecretStorageKey","resolve","reject","sync","ClientEvent","state","logoutMatrixClient","baseUrl","hasCrossSigningAccountData","masterKeyData","setupCrossSigning","securityPhrase","forceReset","skipBootstrapSecureStorage","clearSecretStorageKeys","mxCrypto","recoveryKey","makeRequest","getAuthId","delay","generatePasswordFromMnemonic","mnemonic","md5","generatePassphraseFromMnemonic","mnemonic","hash","sha256","cleanMatrixHomeServerUrl","homeServer","generateUserRoomNameFromAddress","address","postpend","generateUserRoomAliasFromAddress","homeServerUrl","getBaseUrl","servername","protocol","serverDiscoveryUrl","WELL_KNOWN_URI","baseUrl","normalizeUsername","rawUsername","getAuthId","userId","password","ixo","utils","createMatrixApiClient","DEVICE_NAME","registerUserSimplified","pin","oracleName","network","oracleAvatarUrl","matrixHomeServerUrl","transferTokens","homeServerUrl","roomBotUrl","deriveMatrixUrls","mnemonic","utils","wallet","getSecpClient","address","did","didExists","checkIidDocumentExists","matrixService","ixo","createIidDocument","delay","mxMnemonic","mxUsername","generateUsernameFromAddress","mxPassword","generatePasswordFromMnemonic","mxPassphrase","generatePassphraseFromMnemonic","checkIsUsernameAvailable","account","mxRegisterWithSecp","mxClient","createMatrixClient","error","matrixApiClient","createMatrixApiClient","hasCrossSigning","hasCrossSigningAccountData","setupCrossSigning","mxRoomAlias","generateUserRoomAliasFromAddress","roomId","response","joinedMembers","joined","encryptedMnemonic","encrypt","storeEncryptedMnemonicResponse","createMatrixApiClient","mxUtils","CID","base64","mfsha2","createCIDFromBase64","base64String","multibaseString","bytes","hash","jsonToBase64","jsonString","uint8Array","publicUpload","data","fileName","homeServerUrl","accessToken","matrixAPIClient","createMatrixApiClient","fileContent","fileBuffer","fullFileName","response","httpUrl","mxUtils","jsonString","base64String","jsonToBase64","cid","createCIDFromBase64","CreateEntity","wallet","config","matrixHomeServerUrl","ixo","customMessages","RELAYER_NODE_DID","utils","msg","oracleAccountAddress","linkedAccounts","account","oracleName","entityDid","homeServerUrl","accessToken","response","publicUpload","price","denom","controllerDid","walletAddress","addControllerMsg","log","tx","linkedResourcesMsgs","resource","profile","validFrom","domainCard","orgName","name","logo","coverImage","location","description","services","service","parentProtocol","network","indexerUrl","DOMAIN_INDEXER_URL","errorText","error","params","pin","text","value","checkRequiredPin","isCancel","registerResult","registerUserSimplified","address","oracleHomeServerUrl","oracleAccessToken","profileResource","did","domainCardResource","addDomainCardMsg","domainCardTx","logoutMatrixClient","s","spinner","key","CreateEntityCommand","wallet","config","selectNetwork","defaultMatrixUrl","MatrixHomeServerUrl","results","value","checkRequiredMatrixUrl","checkRequiredString","checkRequiredNumber","checkRequiredURL","did","CreateEntity","portalUrl","PORTAL_URL","p","CreateUserCommand","wallet","config","network","selectNetwork","defaultMatrixUrl","MatrixHomeServerUrl","matrixHomeServerUrl","value","checkRequiredMatrixUrl","pin","checkRequiredPin","oracleName","checkRequiredString","user","registerUserSimplified","address","logoutMatrixClient","HelpCommand","registry","cmd","existsSync","path","simpleGit","fs","path","createProjectEnvFile","config","oracleMatrixHomeServerUrl","freshMx","mxLogin","projectPath","envFile","path","envDir","fs","envContent","error","InitCommand","config","wallet","input","value","inputStr","projectPath","projectName","path","name","existsSync","overwrite","confirm","repo","customRepo","shouldOverwrite","git","simpleGit","cloneSpinner","rmSync","gitFolder","CreateEntityCommand","createProjectEnvFile","error","confirm","LogoutCommand","wallet","toHex","createRegistry","IxoSignX","SIGN_X_LOGIN_ERROR","SIGN_X_LOGIN_SUCCESS","SIGN_X_TRANSACT_ERROR","SIGN_X_TRANSACT_SUCCESS","qrcode","SignXEndpoints","SignXClient","wallet","chainNetwork","loginData","qrCodeData","title","qrCodeStr","resolve","reject","response","error","messages","memo","registry","result","SignXLoginCommand","wallet","config","network","selectNetwork","signXClient","SignXClient","loginData","loginResult","error","p","UpdateEntityCommand","wallet","config","CreateEntity","selectNetwork","results","value","checkIsEntityDid","did","controllerDid","entityDid","error","CLIError","message","code","suggestions","handleError","error","CLIError","suggestion","RuntimeConfig","_RuntimeConfig","key","value","log","cosmos","existsSync","readFileSync","writeFileSync","unlink","os","path","WALLET_PATH","path","os","Wallet","config","signXClient","existsSync","walletData","readFileSync","log","network","mxDomain","SignXClient","error","wallet","walletJson","writeFileSync","unlink","userId","address","amount","sendTokensToUserMsg","cosmos","tx","CLIManager","CommandRegistry","RuntimeConfig","Wallet","InitCommand","CreateEntityCommand","UpdateEntityCommand","CreateUserCommand","LogoutCommand","HelpCommand","result","login","select","isCancel","cancel","process","SignXLoginCommand","log","commandName","command","s","spinner","intro","action","args","userArgs","error","handleError","outro","cli"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ixo-oracles-cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "CLI tool for creating and managing IXO Oracle projects",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"README.md"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@clack/prompts": "^0.
|
|
39
|
+
"@clack/prompts": "^1.0.1",
|
|
40
40
|
"@cosmjs/crypto": "^0.34.0",
|
|
41
41
|
"@cosmjs/encoding": "^0.34.0",
|
|
42
42
|
"@cosmjs/proto-signing": "^0.34.0",
|
|
43
43
|
"@ixo/impactxclient-sdk": "^2.4.1",
|
|
44
|
-
"@ixo/matrixclient-sdk": "^0.
|
|
44
|
+
"@ixo/matrixclient-sdk": "^1.0.0",
|
|
45
45
|
"@ixo/signx-sdk": "^1.2.0",
|
|
46
46
|
"@matrix-org/matrix-sdk-crypto-wasm": "^15.1.0",
|
|
47
47
|
"eciesjs": "^0.4.15",
|