qiforge-cli 1.1.1 → 1.2.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 +26 -26
- package/dist/cli.js.map +1 -1
- package/package.json +3 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{cancel as De,intro as br,isCancel as Ct,log as G,outro as Pr,select as Rt,spinner as Nr}from"@clack/prompts";import M from"process";var z=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 w from"@clack/prompts";import{select as bt}from"@clack/prompts";import{z as D}from"zod";var S=async r=>{let e=await bt({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},$e={mainnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d",testnet:"did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb",devnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d"},L={devnet:"https://devmx.ixo.earth",testnet:"https://testmx.ixo.earth",mainnet:"https://mx.ixo.earth"};var We={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/"},B={devnet:"https://domain-indexer.devnet.ixo.earth/index",testnet:"https://domain-indexer.testnet.ixo.earth/index",mainnet:"https://domain-indexer.ixo.earth/index"},j={devnet:"https://devnet-blocksync-graphql.ixo.earth/graphql",testnet:"https://testnet-blocksync-graphql.ixo.earth/graphql",mainnet:"https://blocksync-graphql.ixo.earth/graphql"},ve={devnet:"https://mcp-memory-engine.devnet.ixo.earth/",testnet:"https://memory-engine.testnet.ixo.earth/",mainnet:"https://memory-engine.ixo.earth/"},Ce={devnet:"https://mcp-memory-engine.devnet.ixo.earth/",testnet:"https://mcp-memory-engine.testnet.ixo.earth/",mainnet:"https://mcp-memory-engine.ixo.earth/"},Re={devnet:"https://ai-sandbox-devnet.ixo.earth/mcp",testnet:"https://ai-sandbox-testnet.ixo.earth/mcp",mainnet:"https://ai-sandbox.ixo.earth/mcp"},Ee={devnet:"https://subscriptions-api.ixo-api.workers.dev",testnet:"https://subscriptions-api-testnet.ixo-api.workers.dev/",mainnet:"https://subscriptions-api-mainnet.ixo-api.workers.dev/"},T=(r,e="This field is required")=>{let i=D.string().min(1,e).safeParse(r);if(!i.success)return i.error.message},F=r=>{let t=D.string().regex(/^did:ixo:entity:[a-f0-9]{32}$/,"Invalid entity DID").safeParse(r);if(!t.success)return t.error.message},_=(r,e="This url is required or a valid URL")=>{let i=D.url(e).safeParse(r);if(!i.success)return i.error.message},Xe=(r,e="This number is required")=>{let i=D.number().min(1,e).safeParse(r);if(!i.success)return i.error.message},J=r=>{let t=D.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"},Q=r=>{let t=D.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 lr,log as h,spinner as dr,text as mr}from"@clack/prompts";import{customMessages as ft,ixo as x,utils as Oe}from"@ixo/impactxclient-sdk";import{sha256 as jt}from"@cosmjs/crypto";import{encrypt as Ft}from"eciesjs";import{ClientEvent as Vt,createClient as be}from"matrix-js-sdk";import qt from"md5";var Z=new Map;function Pt(r){return Z.get(r)instanceof Uint8Array}function Nt(r){return Z.get(r)}function Se(){Z.clear()}async function Be({keys:r}){let e=Object.keys(r),t=e.find(Pt);if(console.info("[] getSecretStorageKey",r,e,t),!t)return null;let i=Nt(t);return[t,i]}function je(r,e,t){Z.set(r,t)}import{Bip39 as He,EnglishMnemonic as Ge,Secp256k1 as Ae,sha256 as Ut,Slip10 as Ye,Slip10Curve as ze,stringToPath as Je}from"@cosmjs/crypto";import{DirectSecp256k1HdWallet as kt}from"@cosmjs/proto-signing";import{createQueryClient as Qe,createSigningClient as Mt,customMessages as Dt,ixo as Lt,utils as _t}from"@ixo/impactxclient-sdk";import{createCipheriv as $t,randomBytes as Wt}from"crypto";import{createRegistry as Tt,utils as Ot}from"@ixo/impactxclient-sdk";function V(r){try{return Ot.proto.fromTimestamp(r).getTime()}catch{return}}var ee={BasicAllowance:"/cosmos.feegrant.v1beta1.BasicAllowance",PeriodicAllowance:"/cosmos.feegrant.v1beta1.PeriodicAllowance"},Fe=r=>{let e=Tt();return(r??[]).map(t=>{let i=t.allowance,n=e.decode(i);switch(i.typeUrl){case ee.BasicAllowance:return{granter:t.granter,grantee:t.grantee,type:ee.BasicAllowance,expiration:n.expiration?V(n.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};case ee.PeriodicAllowance:return{granter:t.granter,grantee:t.grantee,type:ee.PeriodicAllowance,expiration:n.basic?.expiration?V(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?V(n.expiration):n.basic?.expiration?V(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}}})},Ve=r=>{if(r==null)return!1;let e=typeof r=="object"?V(r):r;return e==null?!0:e<Date.now()},qe=r=>r==null?!1:(typeof r=="object"?Number(r?.amount??0):typeof r=="string"?Number(r??0):r)<=5e-4;async function Ie(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 Qe(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 Ze(r,e,t,i){try{let n=await t.getAccounts(),{address:o,pubkey:s}=n[0]??{},c=await Xt(o,e),a=c?.length?Fe(c)?.find(d=>!!d&&!Ve(d.expiration)&&!qe(d.limit))?.granter:void 0,l={typeUrl:"/ixo.iid.v1beta1.MsgCreateIidDocument",value:Lt.iid.v1beta1.MsgCreateIidDocument.fromPartial({id:r,verifications:Dt.iid.createIidVerificationMethods({did:r,pubkey:s,address:o,controller:r,type:"secp"}),signer:o,controllers:[r],...i?.length?{services:i}:{}})};await Kt({offlineSigner:t,messages:[l],feegrantGranter:a,network:e})}catch(n){throw console.error(n),n}}async function Xt(r,e){try{let t=N[e];if(!t)throw new Error(`Invalid network: ${e}`);return(await(await Qe(t)).cosmos.feegrant.v1beta1.allowances({grantee:r}))?.allowances??[]}catch(t){console.error("queryAddressAllowances::",t.message);return}}var Kt=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 Mt(o,r),c=await r.getAccounts(),{address:a}=c[0]??{},l=await s.simulate(a,e,t),m=(l>5e4?l:(e??[]).length*5e5)*1.7,p=Bt(m),v={amount:[{denom:"uixo",amount:String(Math.round(p.average))}],gas:String(Math.round(m)),granter:i},y=await s.signAndBroadcast(a,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}`)},Bt=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}},te=r=>new Promise(e=>setTimeout(e,r));function et(r,e){let t=Wt(16),i=$t("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 tt=async r=>{let e=await kt.fromMnemonic(r,{prefix:"ixo"}),t=(await e.getAccounts())[0],i=await He.mnemonicToSeed(new Ge(r)),n=Je("m/44'/118'/0'/0/0"),s=Ye.derivePath(ze.Secp256k1,i,n).privkey,c=await Ae.makeKeypair(s),a=Ae.compressPubkey(c.pubkey);return{mnemonic:r,did:_t.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 He.mnemonicToSeed(new Ge(r)),p=Je("m/44'/118'/0'/0/0"),{privkey:v}=Ye.derivePath(ze.Secp256k1,m,p),y=new Uint8Array(Buffer.from(d,"base64")),P=Ut(y);return(await Ae.createSignature(P,v)).toFixedLength().slice(0,64)}catch(m){throw console.error("Error during signature creation:",m),m}}}};var Ht="/.well-known/matrix/client",Pe=async({homeServerUrl:r,username:e,password:t,deviceName:i},n=!1)=>{let o=r,s=e,c=s.match(/^@(.+):(.+\..+)$/);c&&(s=c[1],o=c[2],o=n?o:await er(o));try{let a=nt(o),l=await a.login("m.login.password",{identifier:{type:"m.id.user",user:tr(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||a.baseUrl}}catch(a){let l=a.message;throw l==="Unknown message"&&(l="Please check your credentials"),console.error("mxLogin::",l),new Error(l)}};async function Gt(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 Yt(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 zt(r,e){let t=new Uint8Array(Buffer.from(e,"hex")),i=new Uint8Array(Buffer.from(r,"utf8")),n=Ft(t,i);return Array.from(n,o=>o.toString(16).padStart(2,"0")).join("")}async function Jt(r,e,t,i,n,o){let s=await Gt(o),c=zt(e,s.publicKey),a={address:r,encryptedPassword:c,publicKeyFingerprint:s.fingerprint,secpResult:{signature:t,challenge:i}},l=await fetch(`${o}/user/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok){let d=await l.text(),m=`Failed to create user account (HTTP ${l.status})`;try{let p=JSON.parse(d);m=p.error||p.message||p.detail||d}catch{m=d||m}throw console.error(`Room bot error [${l.status}]: ${d}`),new Error(m)}return await l.json()}async function rt(r,e,t,i,n,o){try{let{challengeBase64:s}=Yt(r),c=await i.sign(s),a=Buffer.from(c).toString("base64");if(!(await Jt(r,e,a,s,n,o)).success)throw new Error("Failed to create matrix account via API");let d=Ne(r);return await Pe({homeServerUrl:n,username:d,password:e,deviceName:t})}catch(s){throw console.error("mxRegisterWithSecp error:",s),s}}async function it({homeServerUrl:r,username:e}){let t=nt(r);try{return!!await t.isUsernameAvailable(e)}catch{return!1}}function nt(r){if(!r)throw new Error("Home server URL is required to instantiate matrix client");return be({baseUrl:r})}async function ot({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=be({baseUrl:r,accessToken:e,userId:t,deviceId:i,timelineSupport:!0,cryptoCallbacks:{getSecretStorageKey:Be,cacheSecretStorageKey:je},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 c={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(Vt.Sync,a=>{c[a]()})}),n}async function re({mxClient:r,baseUrl:e,accessToken:t,userId:i,deviceId:n}){let o=r;o||(o=be({baseUrl:e,accessToken:t,userId:i,deviceId:n})),o&&(o.stopClient(),await o.logout().catch(console.error),o.clearStores())}function st(r){let e=r.getAccountData("m.cross_signing.master");return console.log("hasCrossSigningAccountData::masterKeyData",e),!!e}async function at(r,{securityPhrase:e,password:t,forceReset:i=!1,skipBootstrapSecureStorage:n=!1}){i&&Se();let o=r.getCrypto();if(!o)throw new Error("Failed to setup matrix cross signing - failed to get matrix crypto api");if(!n){let c=await o.createRecoveryKeyFromPassphrase(e);Se(),await o.bootstrapSecretStorage({createSecretStorageKey:async()=>c,setupNewSecretStorage:i})}let s=r.getUserId();return await o.bootstrapCrossSigning({authUploadDeviceSigningKeys:async function(c){await c(rr({userId:s,password:t}))},setupNewCrossSigning:i}),await o.resetKeyBackup(),await te(300),!!r.getAccountData("m.cross_signing.master")}function Ne(r){if(!r)throw new Error("Address is required to generate matrix username");return"did-ixo-"+r}function ct(r){return Buffer.from(qt(r.replace(/ /g,""))).toString("base64").slice(0,24)}function lt(r){let e=jt(new TextEncoder().encode(r.replace(/ /g,"")));return Buffer.from(e).toString("base64").slice(0,32)}function Qt(r){return r.replace(/^(https?:\/\/)/,"").replace(/\/$/,"")}function Zt(r,e=""){return"did-ixo-"+r+e}function dt(r,e){return"#"+Zt(r)+":"+Qt(e)}async function er(r){let e="https://";/^https?:\/\//.test(r)&&(e="");let t=`${e}${r}${Ht}`;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 tr(r){return(r.indexOf("@")===0?r.substring(1):r).trim()}function rr({userId:r,password:e}){return{type:"m.login.password",password:e,identifier:{type:"m.id.user",user:r}}}import{ixo as ir,utils as Te}from"@ixo/impactxclient-sdk";import{createMatrixApiClient as nr}from"@ixo/matrixclient-sdk";var mt="Oracles CLI";async function ie({pin:r,oracleName:e,network:t,oracleAvatarUrl:i,matrixHomeServerUrl:n},o){try{let{homeServerUrl:s,roomBotUrl:c}=Ke(n),a=Te.mnemonic.generateMnemonic(),l=await tt(a),d=l.baseAccount.address;console.log("\u2705 Wallet created:",d),await o(d);let m=Te.did.generateSecpDid(d),p=await Ie(m,t);if(console.log("\u2705 DID exists:",p),!p){console.log("\u2705 DID does not exist, creating...");let U=ir.iid.v1beta1.Service.fromPartial({id:`${m}#matrix`,type:"MatrixHomeServer",serviceEndpoint:s});if(await Ze(m,t,l,[U]),console.log("\u2705 DID created, waiting 500ms..."),await te(500),console.log("\u2705 Checking if DID exists..."),!await Ie(m,t))throw new Error("Failed to create DID document")}console.log("\u2705 DID created:",m);let v=Te.mnemonic.generateMnemonic(12),y=Ne(d),P=ct(v),he=lt(v);if(!await it({homeServerUrl:s,username:y}))throw new Error("Matrix account already exists");let R=await rt(d,P,mt,l,s,c);if(!R?.accessToken)throw new Error("Failed to register matrix account");console.log("\u2705 Matrix account created:",R.userId);let K=await ot({homeServerUrl:s,accessToken:R.accessToken,userId:R.userId,deviceId:R.deviceId});try{await Promise.all([K.setDisplayName(e),K.setAvatarUrl(i)])}catch(U){console.error("Failed to set display name or avatar url:",U)}let Y=nr({homeServerUrl:s,accessToken:R.accessToken}),we=st(K);if(!we&&(we=await at(K,{securityPhrase:he,password:P,forceReset:!0}),!we))throw new Error("Failed to setup cross signing");console.log("\u2705 Matrix cross-signing setup completed");let St=dt(d,R.baseUrl),A=(await Y.room.v1beta1.queryId(St).catch(()=>{}))?.room_id??"";if(!A){let U=await fetch(`${c}/room/source`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:m,userMatrixId:R.userId})});if(!U.ok)throw new Error("Failed to create matrix room");if(A=(await U.json()).roomId,!A)throw new Error("Failed to create user matrix room")}let ye=await Y.room.v1beta1.listJoinedMembers(A).catch(()=>{}),xe=!!ye?.joined?.[R.userId];if(!xe){if(!(await Y.room.v1beta1.join(A)).room_id)throw new Error("Failed to join matrix room");if(ye=await Y.room.v1beta1.listJoinedMembers(A),xe=!!ye?.joined?.[R.userId],!xe)throw new Error("Failed to join matrix room")}console.log("\u2705 Matrix room created/joined:",A);let At=et(v,r),_e=await fetch(`${s}/_matrix/client/v3/rooms/${A}/state/ixo.room.state.secure/encrypted_mnemonic`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${R.accessToken}`},body:JSON.stringify({encrypted_mnemonic:At})});if(!_e.ok)throw new Error("Failed to store encrypted mnemonic in matrix room");return await _e.json(),console.log("\u2705 Encrypted Matrix mnemonic stored in room"),K.stopClient(),{address:d,did:m,mnemonic:a,matrixUserId:R.userId,matrixRoomId:A,matrixMnemonic:v,matrixPassword:P,matrixAccessToken:R.accessToken,matrixRecoveryPhrase:he,matrixHomeServerUrl:s,pin:r,matrixDeviceName:mt}}catch(s){throw console.error("Simplified registration failed:",s),s}}import{createMatrixApiClient as ar,utils as cr}from"@ixo/matrixclient-sdk";import{CID as or}from"multiformats";import{base64 as sr}from"multiformats/bases/base64";import*as pt from"multiformats/hashes/sha2";async function gt(r){let e=r.startsWith("m")?r:"m"+r,t=sr.decode(e),i=await pt.sha256.digest(t);return or.create(1,85,i).toString()}function ut(r){let e=new TextEncoder().encode(r);return btoa(String.fromCharCode(...Array.from(e)))}var q=async({data:r,fileName:e,homeServerUrl:t,accessToken:i})=>{let n=ar({homeServerUrl:t,accessToken:i}),o=JSON.stringify(r),s=Buffer.from(o,"utf8"),c=e+".json",l=await n.media.v1beta1.upload(c,"application/ld+json",s),d=cr.mxc.mxcUrlToHttp(t,l.content_uri);if(!d)throw new Error("Failed to upload file to Matrix");let m=JSON.stringify(r),p=ut(m),v=await gt(p);return{encrypted:"false",cid:v,proof:v,serviceEndpoint:d,mxc:l.content_uri}};var O=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:x.entity.v1beta1.MsgCreateEntity.fromPartial({entityType:"oracle",context:[],entityStatus:0,verification:[...ft.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:$e[this.config.getValue("network")??"devnet"],service:[x.iid.v1beta1.Service.fromPartial({id:"{id}#matrix",type:"MatrixHomeServer",serviceEndpoint:e})],linkedResource:[],accordedRight:[],linkedEntity:[],linkedClaim:[],startDate:Oe.proto.toTimestamp(new Date),endDate:Oe.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=>x.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 c=await q({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 x.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#orz",type:"oracleAuthZConfig",proof:c.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Orale AuthZ Config",serviceEndpoint:c.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"}}},c=await q({data:s,fileName:"fees",homeServerUrl:n,accessToken:o});return x.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#fee",type:"pricingList",proof:c.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Pricing List",serviceEndpoint:c.serviceEndpoint})}async updateOracleDomain(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.MsgDeleteService",value:x.iid.v1beta1.MsgDeleteService.fromPartial({id:e,serviceId:`${e}#api`,signer:i})},o={typeUrl:"/ixo.iid.v1beta1.MsgDeleteService",value:x.iid.v1beta1.MsgDeleteService.fromPartial({id:e,serviceId:`${e}#ws`,signer:i})},s={typeUrl:"/ixo.iid.v1beta1.MsgAddService",value:x.iid.v1beta1.MsgAddService.fromPartial({id:e,serviceData:x.iid.v1beta1.Service.fromPartial({id:`${e}#api`,type:"oracleService",serviceEndpoint:t}),signer:i})},c={typeUrl:"/ixo.iid.v1beta1.MsgAddService",value:x.iid.v1beta1.MsgAddService.fromPartial({id:e,serviceData:x.iid.v1beta1.Service.fromPartial({id:`${e}#ws`,type:"wsService",serviceEndpoint:t}),signer:i})};h.info(`Sign to update oracle domain for entity ${e}`);let a=await this.wallet.signXClient.transact([n,o,s,c],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(a)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),h.success(`Oracle domain updated to ${t}`)}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:x.iid.v1beta1.MsgAddController.fromPartial({id:e,controllerDid:t,signer:i})};h.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(),h.success(`Controller ${t} added to entity ${e}`)}async createOracleConfigFiles({oracleName:e,entityDid:t,price:i,oracleAccountAddress:n,homeServerUrl:o,accessToken:s}){let c=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!c)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(p=>({typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:x.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:t,linkedResource:x.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:c})}));h.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}:{}}},c=await q({data:s,fileName:"domainCard",homeServerUrl:i,accessToken:n});return x.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#dmn",type:"domainCard",proof:c.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Domain Card",serviceEndpoint:c.serviceEndpoint})}async addProfile({orgName:e,name:t,logo:i,coverImage:n,location:o,description:s,homeServerUrl:c,accessToken:a}){let d=await q({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:c,accessToken:a});return x.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=>x.iid.v1beta1.Service.fromPartial(i)))}setParentProtocol(e,t){e.value.context.push(...ft.iid.createAgentIidContext([{key:"class",val:t}]))}async submitToDomainIndexer(e){let t=this.config.getValue("network")??"devnet",i=B[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();h.warn(`Failed to submit to domain indexer: ${n.status} ${o}`);return}h.success("Domain card submitted to domain indexer")}catch(n){h.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;h.info("Creating Oracle Wallet and Matrix Account");let i=await mr({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(y){return J(y)}});lr(i)&&(h.error("User cancelled"),process.exit(1));let n=await ie({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;h.info("Adding profile");let c=await this.addProfile({...e.profile,homeServerUrl:o,accessToken:s}),a=this.buildMsgCreateEntity(t);a.value.linkedResource.push(c),h.info("Adding services"),this.addServices(a,e.services),h.info("Adding parent protocol"),this.setParentProtocol(a,e.parentProtocol),this.addLinkedAccounts(a,{oracleAccountAddress:n.address}),h.info("Sign this transaction to create the entity");let l=await this.wallet.signXClient.transact([a],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(l)),await this.wallet.signXClient.pollNextTransaction();let d=await this.wallet.signXClient.awaitTransaction();h.success("Entity created -- wait to attach the required config files");let m=Oe.common.getValueFromEvents(d,"wasm","token_id");h.info("Creating domain card");let p=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:x.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:m,linkedResource:x.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:this.wallet.wallet.address})};h.info("Sign to add domain card to the entity");let P=await this.wallet.signXClient.transact([y],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(P)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),h.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}),h.success("Entity created -- config files attached"),await re({baseUrl:o,accessToken:s,userId:n.matrixUserId,deviceId:""});let v=dr();v.start("Creating Entity Matrix Room..."),v.stop("Room created -- room joined"),h.warn("Please save the following information in a secure location as it is not stored:"),h.info("ORACLE ACCOUNT DETAILS");for(let y in n)h.info(`${y}: ${n[y]}`);return this.config.addValue("registerUserResult",n),this.config.addValue("entityDid",m),this.config.addValue("oracleMatrixHomeServerUrl",t),h.info("Submitting domain card to domain indexer"),await this.submitToDomainIndexer(m),m}};var $=class{constructor(e,t){this.wallet=e;this.config=t}name="create-entity";description="Create an entity";async execute(){this.config.getValue("network")||await S(this.config);let t=this.wallet.matrixHomeServer??L[this.config.getValue("network")??"devnet"],i=await w.group({matrixHomeServerUrl:()=>w.text({message:"Matrix homeserver URL for the oracle:",initialValue:t,defaultValue:t,validate(a){return Q(a)}}),oracleName:()=>w.text({message:"What is the name of the oracle?",initialValue:"My oracle",validate(a){return T(a,"Oracle name is required")}}),oraclePrice:()=>w.text({message:"What is the price of the oracle in IXO CREDITS?",initialValue:"100",validate(a){return Xe(parseInt(a??""),"Oracle price is required and must be a number")}}),profile:()=>w.group({orgName:()=>w.text({message:"What is the name of the organization?",initialValue:"IXO",validate(a){return T(a,"Organization name is required")}}),name:()=>w.text({message:"What is the name of the profile?",initialValue:"My oracle",validate(a){return T(a,"Profile name is required")}}),logo:({results:a})=>w.text({message:"What is the logo of the profile?",initialValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${a?.name??"IXO"}`,defaultValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${a?.name??"IXO"}`,validate(l){return l?_(l,"Logo is required or a valid URL"):`https://api.dicebear.com/8.x/bottts/svg?seed=${a?.name??"IXO"}`}}),coverImage:({results:a})=>w.text({message:"What is the cover image of the profile?",initialValue:a.logo,defaultValue:a.logo,validate(l){return l?_(l,"Cover image is required or a valid URL"):a.logo}}),location:()=>w.text({message:"What is the location of your domain?",initialValue:"New York, NY",validate(a){return T(a,"Location is required")}}),description:()=>w.text({message:"What is the description of the entity (profile)?",initialValue:"We are a company that helps you with daily tasks",validate(a){return T(a,"Description is required")}}),url:()=>w.text({message:"What is the website URL of the oracle? (optional, press Enter to skip)",placeholder:"https://your-oracle-website.com"})}),parentProtocol:()=>w.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:()=>w.text({message:"What is the API URL of the oracle?",initialValue:"http://localhost:4000",validate(a){return _(a,"API URL is required or a valid URL")}})},{onCancel:()=>{w.cancel("Operation cancelled."),process.exit(0)}}),o=await new O(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});w.log.info(`API for the oracle is: ${i.apiUrl} | You can change this after you deploy the oracle`);let c=`${We[this.config.getValue("network")??"devnet"]}/oracle/${o}/overview`;return w.log.info(`Oracle created successfully: ${o}`),w.log.info(`Oracle URL: ${c}`),{success:!0,data:`Entity created successfully: ${o}`}}};import*as E from"@clack/prompts";var ne=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 S(this.config);let t=this.wallet.matrixHomeServer??L[this.config.getValue("network")??"devnet"],i=await E.text({message:"Matrix homeserver URL:",initialValue:t,defaultValue:t,validate(c){return Q(c)}});E.isCancel(i)&&(E.log.error("User cancelled"),process.exit(1));let n=await E.text({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(c){return J(c)}});E.isCancel(n)&&(E.log.error("User cancelled"),process.exit(1));let o=await E.text({message:"Enter your oracle name",initialValue:"My oracle",validate(c){return T(c,"Oracle name is required")}});E.isCancel(o)&&(E.log.error("User cancelled"),process.exit(1));let s=await ie({pin:n,oracleName:o,network:this.config.getValue("network")??e,oracleAvatarUrl:`https://api.dicebear.com/8.x/bottts/svg?seed=${o}`,matrixHomeServerUrl:i},async c=>{await this.wallet.sendTokens(c,15e4)});return await re({baseUrl:s.matrixHomeServerUrl,accessToken:s.matrixAccessToken,userId:s.matrixUserId,deviceId:""}),{success:!0,data:s}}};var H=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 Ve,intro as Hr,isCancel as _t,log as Q,outro as Gr,select as Lt,spinner as Yr}from"@clack/prompts";import K from"process";var Z=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 w from"@clack/prompts";import{select as Xt}from"@clack/prompts";import{z as W}from"zod";var S=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},He={mainnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d",testnet:"did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb",devnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d"},X={devnet:"https://devmx.ixo.earth",testnet:"https://testmx.ixo.earth",mainnet:"https://mx.ixo.earth"};var Ge={devnet:"https://ixo-portal.vercel.app",testnet:"https://ixo-portal.vercel.app",mainnet:"https://ixo-portal.vercel.app"},M={mainnet:"https://impacthub.ixo.world/rpc/",testnet:"https://testnet.ixo.earth/rpc/",devnet:"https://devnet.ixo.earth/rpc/"},H={devnet:"https://domain-indexer.devnet.ixo.earth/index",testnet:"https://domain-indexer.testnet.ixo.earth/index",mainnet:"https://domain-indexer.ixo.earth/index"},G={devnet:"https://devnet-blocksync-graphql.ixo.earth/graphql",testnet:"https://testnet-blocksync-graphql.ixo.earth/graphql",mainnet:"https://blocksync-graphql.ixo.earth/graphql"},be={devnet:"https://mcp-memory-engine.devnet.ixo.earth/",testnet:"https://memory-engine.testnet.ixo.earth/",mainnet:"https://memory-engine.ixo.earth/"},Te={devnet:"https://mcp-memory-engine.devnet.ixo.earth/",testnet:"https://mcp-memory-engine.testnet.ixo.earth/",mainnet:"https://mcp-memory-engine.ixo.earth/"},Pe={devnet:"https://ai-sandbox-devnet.ixo.earth/mcp",testnet:"https://ai-sandbox-testnet.ixo.earth/mcp",mainnet:"https://ai-sandbox.ixo.earth/mcp"},ke={devnet:"https://subscriptions-api.ixo-api.workers.dev",testnet:"https://subscriptions-api-testnet.ixo-api.workers.dev/",mainnet:"https://subscriptions-api-mainnet.ixo-api.workers.dev/"},b=(r,e="This field is required")=>{let i=W.string().min(1,e).safeParse(r);if(!i.success)return i.error.message},L=r=>{let t=W.string().regex(/^did:ixo:entity:[a-f0-9]{32}$/,"Invalid entity DID").safeParse(r);if(!t.success)return t.error.message},B=(r,e="This url is required or a valid URL")=>{let i=W.url(e).safeParse(r);if(!i.success)return i.error.message},Ye=(r,e="This number is required")=>{let i=W.number().min(1,e).safeParse(r);if(!i.success)return i.error.message},j=r=>{let t=W.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"},ee=r=>{let t=W.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 Je(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 Pr,log as f,spinner as kr,text as Nr}from"@clack/prompts";import{customMessages as kt,ixo as v,utils as We}from"@ixo/impactxclient-sdk";import{sha256 as ir}from"@cosmjs/crypto";import{encrypt as nr}from"eciesjs";import{ClientEvent as or,createClient as Me}from"matrix-js-sdk";import sr from"md5";var te=new Map;function Bt(r){return te.get(r)instanceof Uint8Array}function jt(r){return te.get(r)}function Ne(){te.clear()}async function ze({keys:r}){let e=Object.keys(r),t=e.find(Bt);if(console.info("[] getSecretStorageKey",r,e,t),!t)return null;let i=jt(t);return[t,i]}function Qe(r,e,t){te.set(r,t)}import{Bip39 as rt,EnglishMnemonic as it,Secp256k1 as Oe,sha256 as qt,Slip10 as nt,Slip10Curve as ot,stringToPath as st}from"@cosmjs/crypto";import{DirectSecp256k1HdWallet as Ht}from"@cosmjs/proto-signing";import{createQueryClient as at,createSigningClient as Gt,customMessages as Yt,ixo as Jt,utils as zt}from"@ixo/impactxclient-sdk";import{createCipheriv as Qt,randomBytes as Zt}from"crypto";import{createRegistry as Vt,utils as Ft}from"@ixo/impactxclient-sdk";function Y(r){try{return Ft.proto.fromTimestamp(r).getTime()}catch{return}}var re={BasicAllowance:"/cosmos.feegrant.v1beta1.BasicAllowance",PeriodicAllowance:"/cosmos.feegrant.v1beta1.PeriodicAllowance"},Ze=r=>{let e=Vt();return(r??[]).map(t=>{let i=t.allowance,n=e.decode(i);switch(i.typeUrl){case re.BasicAllowance:return{granter:t.granter,grantee:t.grantee,type:re.BasicAllowance,expiration:n.expiration?Y(n.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};case re.PeriodicAllowance:return{granter:t.granter,grantee:t.grantee,type:re.PeriodicAllowance,expiration:n.basic?.expiration?Y(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?Y(n.expiration):n.basic?.expiration?Y(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}}})},et=r=>{if(r==null)return!1;let e=typeof r=="object"?Y(r):r;return e==null?!0:e<Date.now()},tt=r=>r==null?!1:(typeof r=="object"?Number(r?.amount??0):typeof r=="string"?Number(r??0):r)<=5e-4;async function Ue(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=M[e];if(!t)throw new Error(`Invalid network: ${e}. Valid networks are: ${Object.keys(M).join(", ")}`);console.log(`\u{1F517} Using RPC URL: ${t}`);try{return!!(await(await at(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 ct(r,e,t,i){try{let n=await t.getAccounts(),{address:o,pubkey:s}=n[0]??{},a=await er(o,e),c=a?.length?Ze(a)?.find(m=>!!m&&!et(m.expiration)&&!tt(m.limit))?.granter:void 0,l={typeUrl:"/ixo.iid.v1beta1.MsgCreateIidDocument",value:Jt.iid.v1beta1.MsgCreateIidDocument.fromPartial({id:r,verifications:Yt.iid.createIidVerificationMethods({did:r,pubkey:s,address:o,controller:r,type:"secp"}),signer:o,controllers:[r],...i?.length?{services:i}:{}})};await tr({offlineSigner:t,messages:[l],feegrantGranter:c,network:e})}catch(n){throw console.error(n),n}}async function er(r,e){try{let t=M[e];if(!t)throw new Error(`Invalid network: ${e}`);return(await(await at(t)).cosmos.feegrant.v1beta1.allowances({grantee:r}))?.allowances??[]}catch(t){console.error("queryAddressAllowances::",t.message);return}}var tr=async({offlineSigner:r,messages:e,memo:t="Signing with Mnemonic Demo",feegrantGranter:i,network:n})=>{let o=M[n];if(!o)throw new Error(`Invalid network: ${n}`);let s=await Gt(o,r),a=await r.getAccounts(),{address:c}=a[0]??{},l=await s.simulate(c,e,t),d=(l>5e4?l:(e??[]).length*5e5)*1.7,p=rr(d),x={amount:[{denom:"uixo",amount:String(Math.round(p.average))}],gas:String(Math.round(d)),granter:i},g=await s.signAndBroadcast(c,e,x,t,void 0);if(!!g.code)throw new Error(`Error when broadcasting tx ${g.transactionHash} at height ${g.height}. Code: ${g.code}; Raw log: ${g.rawLog}`)},rr=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}},ie=r=>new Promise(e=>setTimeout(e,r));function ne(r,e){let t=Zt(16),i=Qt("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 lt=async r=>{let e=await Ht.fromMnemonic(r,{prefix:"ixo"}),t=(await e.getAccounts())[0],i=await rt.mnemonicToSeed(new it(r)),n=st("m/44'/118'/0'/0/0"),s=nt.derivePath(ot.Secp256k1,i,n).privkey,a=await Oe.makeKeypair(s),c=Oe.compressPubkey(a.pubkey);return{mnemonic:r,did:zt.did.generateSecpDid(t.address),baseAccount:t,async getAccounts(){return await e.getAccounts()},async signDirect(m,d){return await e.signDirect(m,d)},async sign(m){try{let d=await rt.mnemonicToSeed(new it(r)),p=st("m/44'/118'/0'/0/0"),{privkey:x}=nt.derivePath(ot.Secp256k1,d,p),g=new Uint8Array(Buffer.from(m,"base64")),I=qt(g);return(await Oe.createSignature(I,x)).toFixedLength().slice(0,64)}catch(d){throw console.error("Error during signature creation:",d),d}}}};var ar="/.well-known/matrix/client",De=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 ur(o));try{let c=pt(o),l=await c.login("m.login.password",{identifier:{type:"m.id.user",user:fr(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 cr(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 lr(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 dr(r,e){let t=new Uint8Array(Buffer.from(e,"hex")),i=new Uint8Array(Buffer.from(r,"utf8")),n=nr(t,i);return Array.from(n,o=>o.toString(16).padStart(2,"0")).join("")}async function mr(r,e,t,i,n,o){let s=await cr(o),a=dr(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 m=await l.text(),d=`Failed to create user account (HTTP ${l.status})`;try{let p=JSON.parse(m);d=p.error||p.message||p.detail||m}catch{d=m||d}throw console.error(`Room bot error [${l.status}]: ${m}`),new Error(d)}return await l.json()}async function dt(r,e,t,i,n,o){try{let{challengeBase64:s}=lr(r),a=await i.sign(s),c=Buffer.from(a).toString("base64");if(!(await mr(r,e,c,s,n,o)).success)throw new Error("Failed to create matrix account via API");let m=_e(r);return await De({homeServerUrl:n,username:m,password:e,deviceName:t})}catch(s){throw console.error("mxRegisterWithSecp error:",s),s}}async function mt({homeServerUrl:r,username:e}){let t=pt(r);try{return!!await t.isUsernameAvailable(e)}catch{return!1}}function pt(r){if(!r)throw new Error("Home server URL is required to instantiate matrix client");return Me({baseUrl:r})}async function gt({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=Me({baseUrl:r,accessToken:e,userId:t,deviceId:i,timelineSupport:!0,cryptoCallbacks:{getSecretStorageKey:ze,cacheSecretStorageKey:Qe},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(or.Sync,c=>{a[c]()})}),n}async function oe({mxClient:r,baseUrl:e,accessToken:t,userId:i,deviceId:n}){let o=r;o||(o=Me({baseUrl:e,accessToken:t,userId:i,deviceId:n})),o&&(o.stopClient(),await o.logout().catch(console.error),o.clearStores())}function ut(r){let e=r.getAccountData("m.cross_signing.master");return console.log("hasCrossSigningAccountData::masterKeyData",e),!!e}async function ft(r,{securityPhrase:e,password:t,forceReset:i=!1,skipBootstrapSecureStorage:n=!1}){i&&Ne();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);Ne(),await o.bootstrapSecretStorage({createSecretStorageKey:async()=>a,setupNewSecretStorage:i})}let s=r.getUserId();return await o.bootstrapCrossSigning({authUploadDeviceSigningKeys:async function(a){await a(hr({userId:s,password:t}))},setupNewCrossSigning:i}),await o.resetKeyBackup(),await ie(300),!!r.getAccountData("m.cross_signing.master")}function _e(r){if(!r)throw new Error("Address is required to generate matrix username");return"did-ixo-"+r}function ht(r){return Buffer.from(sr(r.replace(/ /g,""))).toString("base64").slice(0,24)}function yt(r){let e=ir(new TextEncoder().encode(r.replace(/ /g,"")));return Buffer.from(e).toString("base64").slice(0,32)}function pr(r){return r.replace(/^(https?:\/\/)/,"").replace(/\/$/,"")}function gr(r,e=""){return"did-ixo-"+r+e}function wt(r,e){return"#"+gr(r)+":"+pr(e)}async function ur(r){let e="https://";/^https?:\/\//.test(r)&&(e="");let t=`${e}${r}${ar}`;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 fr(r){return(r.indexOf("@")===0?r.substring(1):r).trim()}function hr({userId:r,password:e}){return{type:"m.login.password",password:e,identifier:{type:"m.id.user",user:r}}}import{ixo as yr,utils as Le}from"@ixo/impactxclient-sdk";import{createMatrixApiClient as wr}from"@ixo/matrixclient-sdk";var xt="Oracles CLI";async function se({pin:r,oracleName:e,network:t,oracleAvatarUrl:i,matrixHomeServerUrl:n},o){try{let{homeServerUrl:s,roomBotUrl:a}=Je(n),c=Le.mnemonic.generateMnemonic(),l=await lt(c),m=l.baseAccount.address;console.log("\u2705 Wallet created:",m),await o(m);let d=Le.did.generateSecpDid(m),p=await Ue(d,t);if(console.log("\u2705 DID exists:",p),!p){console.log("\u2705 DID does not exist, creating...");let _=yr.iid.v1beta1.Service.fromPartial({id:`${d}#matrix`,type:"MatrixHomeServer",serviceEndpoint:s});if(await ct(d,t,l,[_]),console.log("\u2705 DID created, waiting 500ms..."),await ie(500),console.log("\u2705 Checking if DID exists..."),!await Ue(d,t))throw new Error("Failed to create DID document")}console.log("\u2705 DID created:",d);let x=Le.mnemonic.generateMnemonic(12),g=_e(m),I=ht(x),O=yt(x);if(!await mt({homeServerUrl:s,username:g}))throw new Error("Matrix account already exists");let R=await dt(m,I,xt,l,s,a);if(!R?.accessToken)throw new Error("Failed to register matrix account");console.log("\u2705 Matrix account created:",R.userId);let U=await gt({homeServerUrl:s,accessToken:R.accessToken,userId:R.userId,deviceId:R.deviceId});try{await Promise.all([U.setDisplayName(e),U.setAvatarUrl(i)])}catch(_){console.error("Failed to set display name or avatar url:",_)}let T=wr({homeServerUrl:s,accessToken:R.accessToken}),Ie=ut(U);if(!Ie&&(Ie=await ft(U,{securityPhrase:O,password:I,forceReset:!0}),!Ie))throw new Error("Failed to setup cross signing");console.log("\u2705 Matrix cross-signing setup completed");let $t=wt(m,R.baseUrl),P=(await T.room.v1beta1.queryId($t).catch(()=>{}))?.room_id??"";if(!P){let _=await fetch(`${a}/room/source`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:d,userMatrixId:R.userId})});if(!_.ok)throw new Error("Failed to create matrix room");if(P=(await _.json()).roomId,!P)throw new Error("Failed to create user matrix room")}let Se=await T.room.v1beta1.listJoinedMembers(P).catch(()=>{}),Ae=!!Se?.joined?.[R.userId];if(!Ae){if(!(await T.room.v1beta1.join(P)).room_id)throw new Error("Failed to join matrix room");if(Se=await T.room.v1beta1.listJoinedMembers(P),Ae=!!Se?.joined?.[R.userId],!Ae)throw new Error("Failed to join matrix room")}console.log("\u2705 Matrix room created/joined:",P);let Kt=ne(x,r),qe=await fetch(`${s}/_matrix/client/v3/rooms/${P}/state/ixo.room.state.secure/encrypted_mnemonic`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${R.accessToken}`},body:JSON.stringify({encrypted_mnemonic:Kt})});if(!qe.ok)throw new Error("Failed to store encrypted mnemonic in matrix room");return await qe.json(),console.log("\u2705 Encrypted Matrix mnemonic stored in room"),U.stopClient(),{address:m,did:d,mnemonic:c,matrixUserId:R.userId,matrixRoomId:P,matrixMnemonic:x,matrixPassword:I,matrixAccessToken:R.accessToken,matrixRecoveryPhrase:O,matrixHomeServerUrl:s,pin:r,matrixDeviceName:xt}}catch(s){throw console.error("Simplified registration failed:",s),s}}import{ixo as $e}from"@ixo/impactxclient-sdk";import xr from"bs58";import{randomUUID as Ct}from"crypto";import{exportJWK as vt,generateKeyPair as vr}from"jose";var Rt="ixo.room.encryption_key.index",Et="p256_encryption",Cr="ixo.room.encryption_key";function Rr(r){let e=Buffer.from(r.x,"base64url"),t=Buffer.from(r.y,"base64url"),i=new Uint8Array(33);return i[0]=(t[t.length-1]&1)===0?2:3,i.set(e,1),i}function Er(r){let e=new Uint8Array(2+r.length);return e[0]=128,e[1]=36,e.set(r,2),"z"+xr.encode(e)}async function Ke(r,e,t){let i=await fetch(`${t}/_matrix/client/v3/rooms/${encodeURIComponent(r)}/state/${Rt}/${Et}`,{headers:{Authorization:`Bearer ${e}`}});if(i.status===404)return null;if(!i.ok)throw new Error(`Failed to read encryption key index (status ${i.status}): ${await i.text()}`);return await i.json()}async function Ir(r,e,t,i){let n=`enc_key_${Ct()}`,o=await fetch(`${t}/_matrix/client/v3/rooms/${encodeURIComponent(r)}/send/${Cr}/${n}`,{method:"PUT",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({encrypted_private_key:i})});if(!o.ok)throw new Error(`Failed to store encryption key timeline event: ${o.statusText}`);let s=await o.json();if(!s?.event_id)throw new Error("No event_id returned from timeline event send");return s.event_id}async function It(r,e,t,i){let n=await fetch(`${t}/_matrix/client/v3/rooms/${encodeURIComponent(r)}/state/${Rt}/${Et}`,{method:"PUT",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(i)});if(!n.ok)throw new Error(`Failed to write encryption key state index: ${n.statusText}`)}function St(r){let e=r.indexOf(":");if(e===-1||!r.startsWith("!"))throw new Error(`Invalid Matrix room ID format: ${r}. Expected !roomId:server (e.g. !abc123:devmx.ixo.earth)`);return`https://${r.slice(e+1)}`}async function At(r,e,t){let i=await Ke(r,e,t);return i?.keys?Object.values(i.keys).some(n=>n.active):!1}async function ae(r){let{roomId:e,accessToken:t,homeServerUrl:i,pin:n,oracleEntityDid:o}=r,s=await Ke(e,t,i);if(s?.keys){let U=Object.entries(s.keys).find(([,T])=>!T.active&&T.publicKeyMultibase);if(U){let[,T]=U;return{publicKeyMultibase:T.publicKeyMultibase,verificationMethodId:T.didVerificationMethodId}}}let a=Ct(),{privateKey:c,publicKey:l}=await vr("ECDH-ES",{crv:"P-256",extractable:!0}),m=await vt(c);m.alg="ECDH-ES+A256KW";let d=await vt(l);d.alg="ECDH-ES+A256KW";let p=ne(JSON.stringify(m),n),x=await Ir(e,t,i,p),g=Rr(d),I=Er(g),O=`${o}#p256-enc-1`,Ee={eventId:x,didVerificationMethodId:O,algorithm:"ECDH-ES+A256KW",curve:"P-256",createdAt:new Date().toISOString(),active:!1,publicKeyMultibase:I},R={keys:{...s?.keys??{},[a]:Ee}};return await It(e,t,i,R),{publicKeyMultibase:I,verificationMethodId:O}}async function ce(r){let{roomId:e,accessToken:t,homeServerUrl:i,verificationMethodId:n}=r,o=await Ke(e,t,i);if(!o?.keys)throw new Error("No encryption key index found \u2014 cannot activate");let s=!1;for(let a of Object.values(o.keys))a.didVerificationMethodId===n&&(a.active=!0,s=!0);if(!s)throw new Error(`No key entry found for verification method ${n}`);await It(e,t,i,o)}function le(r){return{typeUrl:"/ixo.iid.v1beta1.MsgAddVerification",value:$e.iid.v1beta1.MsgAddVerification.fromPartial({id:r.oracleEntityDid,verification:$e.iid.v1beta1.Verification.fromPartial({relationships:["keyAgreement"],method:$e.iid.v1beta1.VerificationMethod.fromPartial({id:r.verificationMethodId,type:"Multikey",controller:r.oracleEntityDid,publicKeyMultibase:r.publicKeyMultibase})}),signer:r.signerAddress})}}import{createMatrixApiClient as br,utils as Tr}from"@ixo/matrixclient-sdk";import{CID as Sr}from"multiformats";import{base64 as Ar}from"multiformats/bases/base64";import*as bt from"multiformats/hashes/sha2";async function Tt(r){let e=r.startsWith("m")?r:"m"+r,t=Ar.decode(e),i=await bt.sha256.digest(t);return Sr.create(1,85,i).toString()}function Pt(r){let e=new TextEncoder().encode(r);return btoa(String.fromCharCode(...Array.from(e)))}var J=async({data:r,fileName:e,homeServerUrl:t,accessToken:i})=>{let n=br({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),m=Tr.mxc.mxcUrlToHttp(t,l.content_uri);if(!m)throw new Error("Failed to upload file to Matrix");let d=JSON.stringify(r),p=Pt(d),x=await Tt(p);return{encrypted:"false",cid:x,proof:x,serviceEndpoint:m,mxc:l.content_uri}};var D=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:v.entity.v1beta1.MsgCreateEntity.fromPartial({entityType:"oracle",context:[],entityStatus:0,verification:[...kt.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:He[this.config.getValue("network")??"devnet"],service:[v.iid.v1beta1.Service.fromPartial({id:"{id}#matrix",type:"MatrixHomeServer",serviceEndpoint:e})],linkedResource:[],accordedRight:[],linkedEntity:[],linkedClaim:[],startDate:We.proto.toTimestamp(new Date),endDate:We.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=>v.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 J({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 v.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 J({data:s,fileName:"fees",homeServerUrl:n,accessToken:o});return v.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 updateOracleDomain(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.MsgDeleteService",value:v.iid.v1beta1.MsgDeleteService.fromPartial({id:e,serviceId:`${e}#api`,signer:i})},o={typeUrl:"/ixo.iid.v1beta1.MsgDeleteService",value:v.iid.v1beta1.MsgDeleteService.fromPartial({id:e,serviceId:`${e}#ws`,signer:i})},s={typeUrl:"/ixo.iid.v1beta1.MsgAddService",value:v.iid.v1beta1.MsgAddService.fromPartial({id:e,serviceData:v.iid.v1beta1.Service.fromPartial({id:`${e}#api`,type:"oracleService",serviceEndpoint:t}),signer:i})},a={typeUrl:"/ixo.iid.v1beta1.MsgAddService",value:v.iid.v1beta1.MsgAddService.fromPartial({id:e,serviceData:v.iid.v1beta1.Service.fromPartial({id:`${e}#ws`,type:"wsService",serviceEndpoint:t}),signer:i})};f.info(`Sign to update oracle domain for entity ${e}`);let c=await this.wallet.signXClient.transact([n,o,s,a],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(c)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),f.success(`Oracle domain updated to ${t}`)}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:v.iid.v1beta1.MsgAddController.fromPartial({id:e,controllerDid:t,signer:i})};f.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(),f.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(p=>({typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:v.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:t,linkedResource:v.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:a})}));f.info("Sign to edit the entity and add the config files");let m=await this.wallet.signXClient.transact(l,this.wallet.wallet);return this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(m)),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 J({data:s,fileName:"domainCard",homeServerUrl:i,accessToken:n});return v.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 m=await J({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 v.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#pro",type:"Settings",description:"Profile",mediaType:"application/json",serviceEndpoint:m.serviceEndpoint,proof:m.proof,encrypted:"false",right:""})}addServices(e,t){e.value.service.push(...t.map(i=>v.iid.v1beta1.Service.fromPartial(i)))}setParentProtocol(e,t){e.value.context.push(...kt.iid.createAgentIidContext([{key:"class",val:t}]))}async submitToDomainIndexer(e){let t=this.config.getValue("network")??"devnet",i=H[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();f.warn(`Failed to submit to domain indexer: ${n.status} ${o}`);return}f.success("Domain card submitted to domain indexer")}catch(n){f.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;f.info("Creating Oracle Wallet and Matrix Account");let i=await Nr({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(g){return j(g)}});Pr(i)&&(f.error("User cancelled"),process.exit(1));let n=await se({pin:i,oracleName:e.oracleConfig.oracleName,network:this.config.getValue("network"),oracleAvatarUrl:e.profile.logo,matrixHomeServerUrl:t},async g=>{await this.wallet.sendTokens(g,25e4)}),o=n.matrixHomeServerUrl,s=n.matrixAccessToken;f.info("Adding profile");let a=await this.addProfile({...e.profile,homeServerUrl:o,accessToken:s}),c=this.buildMsgCreateEntity(t);c.value.linkedResource.push(a),f.info("Adding services"),this.addServices(c,e.services),f.info("Adding parent protocol"),this.setParentProtocol(c,e.parentProtocol),this.addLinkedAccounts(c,{oracleAccountAddress:n.address}),f.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 m=await this.wallet.signXClient.awaitTransaction();f.success("Entity created -- wait to attach the required config files");let d=We.common.getValueFromEvents(m,"wasm","token_id");f.info("Creating domain card");let p=await this.createDomainCard({profile:e.profile,entityDid:d,homeServerUrl:o,accessToken:s});if(this.wallet.wallet?.address){let g={typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:v.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:d,linkedResource:v.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:this.wallet.wallet.address})};f.info("Sign to add domain card to the entity");let I=await this.wallet.signXClient.transact([g],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(I)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),f.success("Domain card added to entity")}await this.createOracleConfigFiles({oracleName:e.oracleConfig.oracleName,price:e.oracleConfig.price,oracleAccountAddress:n.address,entityDid:d,homeServerUrl:o,accessToken:s}),f.success("Entity created -- config files attached"),f.info("Setting up P-256 encryption key for secrets management");try{let g=await ae({roomId:n.matrixRoomId,accessToken:s,homeServerUrl:o,pin:i,oracleEntityDid:d}),I=le({oracleEntityDid:d,verificationMethodId:g.verificationMethodId,publicKeyMultibase:g.publicKeyMultibase,signerAddress:this.wallet.wallet.address});f.info("Sign to add P-256 encryption key (keyAgreement) to the entity");let O=await this.wallet.signXClient.transact([I],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(O)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),await ce({roomId:n.matrixRoomId,accessToken:s,homeServerUrl:o,verificationMethodId:g.verificationMethodId}),f.success("P-256 encryption key published to entity DID")}catch(g){f.warn(`Failed to setup encryption key: ${g instanceof Error?g.message:String(g)}`),f.warn("You can set it up later using: oracles-cli setup-encryption-key")}await oe({baseUrl:o,accessToken:s,userId:n.matrixUserId,deviceId:""});let x=kr();x.start("Creating Entity Matrix Room..."),x.stop("Room created -- room joined"),f.warn("Please save the following information in a secure location as it is not stored:"),f.info("ORACLE ACCOUNT DETAILS");for(let g in n)f.info(`${g}: ${n[g]}`);return this.config.addValue("registerUserResult",n),this.config.addValue("entityDid",d),this.config.addValue("oracleMatrixHomeServerUrl",t),f.info("Submitting domain card to domain indexer"),await this.submitToDomainIndexer(d),d}};var V=class{constructor(e,t){this.wallet=e;this.config=t}name="create-entity";description="Create an entity";async execute(){this.config.getValue("network")||await S(this.config);let t=this.wallet.matrixHomeServer??X[this.config.getValue("network")??"devnet"],i=await w.group({matrixHomeServerUrl:()=>w.text({message:"Matrix homeserver URL for the oracle:",initialValue:t,defaultValue:t,validate(c){return ee(c)}}),oracleName:()=>w.text({message:"What is the name of the oracle?",initialValue:"My oracle",validate(c){return b(c,"Oracle name is required")}}),oraclePrice:()=>w.text({message:"What is the price of the oracle in IXO CREDITS?",initialValue:"100",validate(c){return Ye(parseInt(c??""),"Oracle price is required and must be a number")}}),profile:()=>w.group({orgName:()=>w.text({message:"What is the name of the organization?",initialValue:"IXO",validate(c){return b(c,"Organization name is required")}}),name:()=>w.text({message:"What is the name of the profile?",initialValue:"My oracle",validate(c){return b(c,"Profile name is required")}}),logo:({results:c})=>w.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?B(l,"Logo is required or a valid URL"):`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`}}),coverImage:({results:c})=>w.text({message:"What is the cover image of the profile?",initialValue:c.logo,defaultValue:c.logo,validate(l){return l?B(l,"Cover image is required or a valid URL"):c.logo}}),location:()=>w.text({message:"What is the location of your domain?",initialValue:"New York, NY",validate(c){return b(c,"Location is required")}}),description:()=>w.text({message:"What is the description of the entity (profile)?",initialValue:"We are a company that helps you with daily tasks",validate(c){return b(c,"Description is required")}}),url:()=>w.text({message:"What is the website URL of the oracle? (optional, press Enter to skip)",placeholder:"https://your-oracle-website.com"})}),parentProtocol:()=>w.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:()=>w.text({message:"What is the API URL of the oracle?",initialValue:"http://localhost:4000",validate(c){return B(c,"API URL is required or a valid URL")}})},{onCancel:()=>{w.cancel("Operation cancelled."),process.exit(0)}}),o=await new D(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});w.log.info(`API for the oracle is: ${i.apiUrl} | You can change this after you deploy the oracle`);let a=`${Ge[this.config.getValue("network")??"devnet"]}/oracle/${o}/overview`;return w.log.info(`Oracle created successfully: ${o}`),w.log.info(`Oracle URL: ${a}`),{success:!0,data:`Entity created successfully: ${o}`}}};import*as A from"@clack/prompts";var de=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 S(this.config);let t=this.wallet.matrixHomeServer??X[this.config.getValue("network")??"devnet"],i=await A.text({message:"Matrix homeserver URL:",initialValue:t,defaultValue:t,validate(a){return ee(a)}});A.isCancel(i)&&(A.log.error("User cancelled"),process.exit(1));let n=await A.text({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(a){return j(a)}});A.isCancel(n)&&(A.log.error("User cancelled"),process.exit(1));let o=await A.text({message:"Enter your oracle name",initialValue:"My oracle",validate(a){return b(a,"Oracle name is required")}});A.isCancel(o)&&(A.log.error("User cancelled"),process.exit(1));let s=await se({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 oe({baseUrl:s.matrixHomeServerUrl,accessToken:s.matrixAccessToken,userId:s.matrixUserId,deviceId:""}),{success:!0,data:s}}};var z=class{constructor(e){this.registry=e}name="help";description="Show help information and available commands";async execute(){return{success:!0,data:`
|
|
3
3
|
QiForge CLI - Help
|
|
4
4
|
|
|
5
5
|
USAGE:
|
|
@@ -19,15 +19,15 @@ OPTIONS:
|
|
|
19
19
|
--help, -h Show help information
|
|
20
20
|
|
|
21
21
|
For more information, visit: https://www.npmjs.com/package/qiforge-cli
|
|
22
|
-
`}}};import*as
|
|
22
|
+
`}}};import*as u from"@clack/prompts";import{existsSync as ge}from"fs";import F from"path";import Ot from"simple-git";import pe from"fs";import me from"path";function Or(r,e){return`
|
|
23
23
|
PORT=4000
|
|
24
24
|
ORACLE_NAME=${e.oracleName}
|
|
25
25
|
|
|
26
26
|
# Network
|
|
27
27
|
NETWORK=${r}
|
|
28
|
-
RPC_URL=${
|
|
29
|
-
BLOCKSYNC_GRAPHQL_URL=${
|
|
30
|
-
BLOCKSYNC_URI=${
|
|
28
|
+
RPC_URL=${M[r]}
|
|
29
|
+
BLOCKSYNC_GRAPHQL_URL=${G[r]}
|
|
30
|
+
BLOCKSYNC_URI=${G[r]}
|
|
31
31
|
|
|
32
32
|
# Matrix
|
|
33
33
|
MATRIX_BASE_URL=${e.matrixBaseUrl}
|
|
@@ -51,13 +51,13 @@ OPENAI_API_KEY=
|
|
|
51
51
|
OPEN_ROUTER_API_KEY=
|
|
52
52
|
|
|
53
53
|
# External Services (configure these for your deployment)
|
|
54
|
-
MEMORY_MCP_URL=${
|
|
55
|
-
MEMORY_ENGINE_URL=${
|
|
54
|
+
MEMORY_MCP_URL=${Te[r]}
|
|
55
|
+
MEMORY_ENGINE_URL=${be[r]}
|
|
56
56
|
|
|
57
57
|
# FIRECRWAL -> check the docs https://docs.firecrawl.dev/mcp-server
|
|
58
58
|
FIRECRAWL_MCP_URL=
|
|
59
|
-
DOMAIN_INDEXER_URL=${
|
|
60
|
-
SANDBOX_MCP_URL=${
|
|
59
|
+
DOMAIN_INDEXER_URL=${H[r]}
|
|
60
|
+
SANDBOX_MCP_URL=${Pe[r]}
|
|
61
61
|
|
|
62
62
|
# Observability (optional)
|
|
63
63
|
LANGSMITH_TRACING=true
|
|
@@ -68,24 +68,24 @@ LANGSMITH_PROJECT="${e.oracleName}_${r}"
|
|
|
68
68
|
|
|
69
69
|
DISABLE_CREDITS=true
|
|
70
70
|
CORS_ORIGIN=*
|
|
71
|
-
SUBSCRIPTION_URL=${
|
|
71
|
+
SUBSCRIPTION_URL=${ke[r]}
|
|
72
72
|
|
|
73
73
|
### BACKUP \u2014 save these securely (values above are already set)
|
|
74
74
|
# ORACLE_ADDRESS=${e.oracleAddress}
|
|
75
75
|
# ORACLE_DID=${e.oracleDid}
|
|
76
|
-
`}function
|
|
76
|
+
`}function Ur(r,e){return`# To fill in the blank values, run: qiforge-cli create-entity (select ${r})
|
|
77
77
|
|
|
78
78
|
PORT=4000
|
|
79
79
|
ORACLE_NAME=${e}
|
|
80
80
|
|
|
81
81
|
# Network
|
|
82
82
|
NETWORK=${r}
|
|
83
|
-
RPC_URL=${
|
|
84
|
-
BLOCKSYNC_GRAPHQL_URL=${
|
|
85
|
-
BLOCKSYNC_URI=${
|
|
83
|
+
RPC_URL=${M[r]}
|
|
84
|
+
BLOCKSYNC_GRAPHQL_URL=${G[r]}
|
|
85
|
+
BLOCKSYNC_URI=${G[r]}
|
|
86
86
|
|
|
87
87
|
# Matrix
|
|
88
|
-
MATRIX_BASE_URL=${
|
|
88
|
+
MATRIX_BASE_URL=${X[r]}
|
|
89
89
|
MATRIX_ORACLE_ADMIN_ACCESS_TOKEN=
|
|
90
90
|
MATRIX_ORACLE_ADMIN_PASSWORD=
|
|
91
91
|
MATRIX_ORACLE_ADMIN_USER_ID=
|
|
@@ -106,13 +106,13 @@ OPENAI_API_KEY=
|
|
|
106
106
|
OPEN_ROUTER_API_KEY=
|
|
107
107
|
|
|
108
108
|
# External Services (configure these for your deployment)
|
|
109
|
-
MEMORY_MCP_URL=${
|
|
110
|
-
MEMORY_ENGINE_URL=${
|
|
109
|
+
MEMORY_MCP_URL=${Te[r]}
|
|
110
|
+
MEMORY_ENGINE_URL=${be[r]}
|
|
111
111
|
|
|
112
112
|
# FIRECRWAL -> check the docs https://docs.firecrawl.dev/mcp-server
|
|
113
113
|
FIRECRAWL_MCP_URL=
|
|
114
|
-
DOMAIN_INDEXER_URL=${
|
|
115
|
-
SANDBOX_MCP_URL=${
|
|
114
|
+
DOMAIN_INDEXER_URL=${H[r]}
|
|
115
|
+
SANDBOX_MCP_URL=${Pe[r]}
|
|
116
116
|
|
|
117
117
|
# Observability (optional)
|
|
118
118
|
LANGSMITH_TRACING=true
|
|
@@ -124,22 +124,22 @@ LANGSMITH_PROJECT="${e}_${r}"
|
|
|
124
124
|
# Features (optional)
|
|
125
125
|
# DISABLE_CREDITS=false
|
|
126
126
|
# CORS_ORIGIN=*
|
|
127
|
-
# SUBSCRIPTION_URL=${
|
|
128
|
-
`}function
|
|
127
|
+
# SUBSCRIPTION_URL=${ke[r]}
|
|
128
|
+
`}function Xe(r,e){try{pe.writeFileSync(r,e),console.log("\u2705 env file created successfully at:",r)}catch(t){throw console.error("\u274C Failed to create env file:",r,t),t}}var Nt=async r=>{let e=r.getOrThrow("oracleMatrixHomeServerUrl"),t=r.getOrThrow("network"),i=r.getOrThrow("registerUserResult"),n=await De({homeServerUrl:e,username:i.matrixUserId,password:i.matrixPassword,deviceName:i.matrixDeviceName}),o=r.getOrThrow("projectPath"),s=me.join(o,"apps","app");console.log("Creating env files in:",s),pe.existsSync(s)||(console.log("Creating directory:",s),pe.mkdirSync(s,{recursive:!0}));let a=r.getValue("projectName")??"",c=Or(t,{oracleName:a,network:t,matrixBaseUrl:e,matrixAccessToken:n.accessToken,matrixPassword:i.matrixPassword,matrixUserId:i.matrixUserId,matrixRecoveryPhrase:i.matrixRecoveryPhrase,matrixPin:i.pin,matrixRoomId:i.matrixRoomId,mnemonic:i.mnemonic,entityDid:r.getOrThrow("entityDid"),oracleAddress:i.address,oracleDid:i.did}),l=`.env.${t}`;Xe(me.join(s,l),c),Xe(me.join(s,".env"),c);let m=[{net:"devnet",filename:".env.devnet"},{net:"testnet",filename:".env.testnet"},{net:"mainnet",filename:".env.mainnet"}];for(let{net:d,filename:p}of m){if(d===t)continue;let x=me.join(s,p);if(pe.existsSync(x))continue;let g=Ur(d,a);Xe(x,g)}};var ue=class{constructor(e,t){this.config=e;this.wallet=t}name="init";description="Initialize Project";async getProjectInput(){let e=await u.text({message:"What is your project named?",placeholder:"my-ixo-project",validate(o){if(!o)return"Project name is required"}});u.isCancel(e)&&(u.cancel("Operation cancelled."),process.exit(0));let t=String(e),i,n;return t.includes("/")||t.includes("\\")?(i=t,n=F.basename(t)):(n=t,i=F.join(process.cwd(),n)),this.isValidProjectName(n)||(u.note("Invalid project name. Using a valid name instead.","Warning"),n=this.sanitizeProjectName(n),i=F.join(F.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(ge(e)){let o=await u.confirm({message:`Directory "${e}" already exists. Do you want to overwrite it?`,initialValue:!1});return u.isCancel(o)&&(u.cancel("Operation cancelled."),process.exit(0)),o}let n=await u.confirm({message:`Create IXO project "${t}" in "${e}"?`,initialValue:!0});return u.isCancel(n)&&(u.cancel("Operation cancelled."),process.exit(0)),n}async selectRepo(){let e=await u.select({message:"Select a template to clone",options:[{value:"git@github.com:ixoworld/qiforge.git",label:"IXO Oracles (Default)"},{label:"Custom template",value:"custom"}]});if(u.isCancel(e)&&(u.cancel("Operation cancelled."),process.exit(0)),e==="custom"){let t=await u.text({message:"Enter the custom template URL"});return u.isCancel(t)&&(u.cancel("Operation cancelled."),process.exit(0)),t}return e}async cloneRepo(e,t,i=!1){let n=Ot(),o=u.spinner();try{if(o.start("Cloning repository..."),i&&ge(t)){let{rmSync:l}=await import("fs");l(t,{recursive:!0,force:!0})}await n.clone(e,t);let s=F.join(t,".git");if(ge(s)){let{rmSync:l}=await import("fs");l(s,{recursive:!0,force:!0})}await Ot(t).init(),o.stop("Repository cloned successfully"),u.log.info("Creating Oracle Entity and Matrix Account"),(await new V(this.wallet,this.config).execute()).success?u.log.info("Oracle Entity and Matrix Account created successfully"):u.log.error("Failed to create Oracle Entity and Matrix Account"),await Nt(this.config),u.log.success(`
|
|
129
129
|
\u2705 IXO project created successfully!
|
|
130
130
|
|
|
131
131
|
\u{1F4C1} Location: ${t}
|
|
132
132
|
\u{1F680} Next steps:
|
|
133
|
-
cd ${
|
|
133
|
+
cd ${F.basename(t)}
|
|
134
134
|
pnpm install
|
|
135
135
|
pnpm build
|
|
136
136
|
cd apps/app
|
|
137
|
-
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=
|
|
138
|
-
`+" ".repeat(5)+"\u{1F510} "+t),console.log(" ".repeat(5)+"\u{1F4F1} Scan with IXO app"),console.log(" ".repeat(5)+"\u2501".repeat(30)),
|
|
139
|
-
`)}displayQRCode(e){this.displayStyledQRCode(e,"Login with SignX")}async awaitLogin(){return new Promise((e,t)=>{try{this.signXClient.on(
|
|
137
|
+
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=ge(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 Mr}from"@clack/prompts";var fe=class{constructor(e){this.wallet=e}name="logout";description="Logout command";async execute(){return await Mr({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*as C from"@clack/prompts";var he=class{constructor(e,t){this.wallet=e;this.config=t}name="setup-encryption-key";description="Setup P-256 encryption key for an existing oracle (keyAgreement)";async execute(){this.config.getValue("network")||await S(this.config);let t=await C.group({entityDid:()=>C.text({message:"Oracle entity DID (ORACLE_ENTITY_DID from .env):",initialValue:this.config.getValue("entityDid")?.toString()??"",validate(n){return L(n)}}),matrixRoomId:()=>C.text({message:"Oracle Matrix room ID (MATRIX_ACCOUNT_ROOM_ID from .env):",placeholder:"!abc123:devmx.ixo.earth",validate(n){return!n||!n.startsWith("!")||!n.includes(":")?"Matrix room ID must be in format !roomId:server (e.g. !abc123:devmx.ixo.earth)":b(n,"Matrix room ID is required")}}),matrixAccessToken:()=>C.password({message:"Oracle Matrix access token (MATRIX_ORACLE_ADMIN_ACCESS_TOKEN from .env):",validate(n){return b(n,"Matrix access token is required")}}),pin:()=>C.password({message:"Oracle PIN (MATRIX_VALUE_PIN from .env):",validate(n){return j(n)}})},{onCancel:()=>{C.cancel("Operation cancelled."),process.exit(0)}}),i=St(t.matrixRoomId);try{if(!this.wallet.signXClient||!this.wallet.wallet?.address)throw new Error("Wallet/SignX client not available. Please login first.");if(C.log.info("Checking for existing encryption key..."),await At(t.matrixRoomId,t.matrixAccessToken,i))return C.log.info("Encryption key already exists for this oracle. No action needed."),{success:!0,data:"Encryption key already exists"};C.log.info("Preparing P-256 encryption keypair...");let o=await ae({roomId:t.matrixRoomId,accessToken:t.matrixAccessToken,homeServerUrl:i,pin:t.pin,oracleEntityDid:t.entityDid});C.log.success("Encryption key prepared in Matrix room");let s=le({oracleEntityDid:t.entityDid,verificationMethodId:o.verificationMethodId,publicKeyMultibase:o.publicKeyMultibase,signerAddress:this.wallet.wallet.address});C.log.info("Sign to add P-256 encryption key (keyAgreement) to the entity");let a=await this.wallet.signXClient.transact([s],this.wallet.wallet);return this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(a)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),await ce({roomId:t.matrixRoomId,accessToken:t.matrixAccessToken,homeServerUrl:i,verificationMethodId:o.verificationMethodId}),C.log.success(`P-256 encryption key published to entity DID: ${t.entityDid}`),C.log.info(`Verification method ID: ${o.verificationMethodId}`),{success:!0,data:`Encryption key setup complete for ${t.entityDid}`}}catch(n){return{success:!1,error:n instanceof Error?n.message:String(n)}}}};import{toHex as Dr}from"@cosmjs/encoding";import{createRegistry as _r}from"@ixo/impactxclient-sdk";import{SignX as Ut,SIGN_X_LOGIN_ERROR as Lr,SIGN_X_LOGIN_SUCCESS as $r,SIGN_X_TRANSACT_ERROR as Kr,SIGN_X_TRANSACT_SUCCESS as Wr}from"@ixo/signx-sdk";import Xr from"qrcode-terminal";var Mt={devnet:"https://signx.devnet.ixo.earth",testnet:"https://signx.testnet.ixo.earth",mainnet:"https://signx.ixo.earth"},q=class{signXClient;_loginData;get loginData(){return this._loginData}static loadFromWallet(e){return new Ut({endpoint:Mt[e.network],sitename:"QiForge CLI",network:e.network})}constructor(e){this.signXClient=new Ut({endpoint:Mt[e],sitename:"QiForge 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(`
|
|
138
|
+
`+" ".repeat(5)+"\u{1F510} "+t),console.log(" ".repeat(5)+"\u{1F4F1} Scan with IXO app"),console.log(" ".repeat(5)+"\u2501".repeat(30)),Xr.generate(i,{small:!0}),console.log(" ".repeat(5)+`\u23F3 Waiting...
|
|
139
|
+
`)}displayQRCode(e){this.displayStyledQRCode(e,"Login with SignX")}async awaitLogin(){return new Promise((e,t)=>{try{this.signXClient.on($r,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(Lr,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=_r();return this.signXClient.transact({address:t.address,did:t.did,pubkey:t.pubKey,timestamp:new Date().toISOString(),transactions:[{sequence:1,txBodyHex:Dr(n.encodeTxBody({messages:e,memo:i||""}))}]})}async awaitTransaction(){return new Promise((e,t)=>{try{this.signXClient.on(Wr,i=>{e(i.data)}),this.signXClient.on(Kr,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 ye=class{constructor(e,t){this.wallet=e;this.config=t}name="signx-login";description="Login with SignX wallet";async execute(){try{let e=await S(this.config),t=new q(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 k from"@clack/prompts";var we=class{constructor(e,t){this.wallet=e;this.config=t}name="update-oracle-api-url";description="Update the oracle API domain (default is localhost)";async execute(){this.config.getValue("network")||await S(this.config);let t=await k.group({entityDid:()=>k.text({message:"What is the DID of the entity you want to update?",initialValue:this.config.getValue("entityDid")?.toString()??"",validate(i){return L(i)}}),apiUrl:()=>k.text({message:"What is the new API URL (domain) for the oracle?",initialValue:"http://localhost:4000",validate(i){return B(i,"API URL is required and must be a valid URL")}})},{onCancel:()=>{k.cancel("Operation cancelled."),process.exit(0)}});try{let i=new D(this.wallet,this.config);return k.log.info(`Updating oracle domain for entity ${t.entityDid} to ${t.apiUrl}`),await i.updateOracleDomain(t.entityDid,t.apiUrl),{success:!0,data:`Oracle domain updated to ${t.apiUrl} for entity ${t.entityDid}`}}catch(i){return{success:!1,error:i instanceof Error?i.message:String(i)}}}};import*as E from"@clack/prompts";var xe=class{constructor(e,t){this.wallet=e;this.config=t;this.createEntity=new D(this.wallet,this.config)}name="update-entity";description="Update an entity (add controllers, etc.)";createEntity;async execute(){this.config.getValue("network")||await S(this.config);let t=await E.group({entityDid:()=>E.text({message:"What is the DID of the entity you want to update?",initialValue:this.config.getValue("entityDid")?.toString()??"",validate(i){return L(i)}}),action:()=>E.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 E.text({message:"What is the DID of the controller you want to add?",validate(o){return L(o)}});return E.isCancel(n)&&(E.cancel("Operation cancelled."),process.exit(0)),n}},{onCancel:()=>{E.cancel("Operation cancelled."),process.exit(0)}});try{if(t.action==="add-controller"&&typeof t.controllerDid=="string"){let i=t.controllerDid,n=t.entityDid;return E.log.info(`Adding controller ${i} to entity ${n}`),await this.createEntity.addControllerToEntity(n,i),E.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 Be=class extends Error{constructor(t,i="CLI_ERROR",n){super(t);this.code=i;this.suggestions=n;this.name="CLIError"}};function ve(r){r instanceof Be&&(console.error(`
|
|
140
140
|
\u274C ${r.name}: ${r.message}`),r.suggestions?.length&&(console.error(`
|
|
141
141
|
Suggestions:`),r.suggestions.forEach(e=>console.error(` \u2022 ${e}`))),process.exit(1)),r instanceof Error&&(console.error(`
|
|
142
142
|
\u274C Unexpected Error: ${r.message}`),r.stack&&(console.error(`
|
|
143
143
|
Stack trace:`),console.error(r.stack)),process.exit(1)),console.error(`
|
|
144
|
-
\u274C Unknown error occurred`,r),process.exit(1)}var
|
|
144
|
+
\u274C Unknown error occurred`,r),process.exit(1)}var Ce=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 N}from"@clack/prompts";import{cosmos as Dt}from"@ixo/impactxclient-sdk";import{existsSync as je,readFileSync as Br,writeFileSync as jr}from"fs";import{unlink as Vr}from"fs/promises";import Fr from"os";import qr from"path";var $=qr.join(Fr.homedir(),".wallet.json"),Re=class{wallet;signXClient;config;constructor(e){this.config=e,this.loadWallet()}setSignXClient(e){this.signXClient=e}loadWallet(){if(je($))try{let e=Br($,"utf8");if(this.wallet=JSON.parse(e),!this.wallet.matrix?.userId||!this.wallet.matrix.userId.includes(":")){N.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 q(t)),N.success(`Welcome back, ${this.wallet.name}!`),N.info(`Network: ${t}`)}catch(e){N.warning(`Failed to load wallet file: ${e instanceof Error?e.message:String(e)}`),this.wallet=void 0}else N.warning("No wallet file found")}setWallet(e){try{this.wallet=e;let t=JSON.stringify(e,null,2);jr($,t,"utf8"),N.success(`Wallet saved successfully to: ${$}`)}catch(t){throw N.error(`Failed to save wallet: ${t instanceof Error?t.message:String(t)}`),new Error("Failed to save wallet file")}}checkWalletExists(){return je($)&&this.wallet!==void 0}async clearWallet(){this.wallet=void 0;try{je($)&&(await Vr($),N.success("Wallet file deleted successfully"))}catch(e){N.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:Dt.bank.v1beta1.MsgSend.fromPartial({fromAddress:this.address,toAddress:e,amount:[Dt.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 Fe=class{registry;config;wallet;constructor(){this.registry=new Z,this.config=Ce.getInstance(),this.wallet=new Re(this.config)}registerCommands(){this.registry.register(new ue(this.config,this.wallet)),this.registry.register(new V(this.wallet,this.config)),this.registry.register(new xe(this.wallet,this.config)),this.registry.register(new we(this.wallet,this.config)),this.registry.register(new he(this.wallet,this.config)),this.registry.register(new de(this.wallet,this.config)),this.registry.register(new fe(this.wallet)),this.registry.register(new z(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 z(this.registry).execute();t.success&&t.data&&console.log(t.data)}async handleAuthentication(){if(!this.wallet.checkWalletExists()){let e=await Lt({message:"Login with SignX",options:[{value:"login",label:"Login"},{value:"exit",label:"Exit"}]});switch(_t(e)&&(Ve("Operation cancelled."),K.exit(0)),String(e)){case"login":{(await new ye(this.wallet,this.config).execute()).success&&Q.success("Login successful");return}case"exit":{Ve("Operation cancelled."),K.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=Yr();i.start(`Executing ${t.name}...`);let n=await t.execute();i.stop(`${t.name} completed`),n.success?(Q.success(`${t.name} completed successfully!`),n.data&&Q.info(JSON.stringify(n.data,null,2))):Q.error(`${t.name} failed: ${n.error}`)}async interactiveMode(){Hr("IXO CLI"),Q.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 Lt({message:`Welcome ${this.wallet.name}, what would you like to do?`,options:[...this.registry.getCommandOptions()],initialValue:"init"});_t(e)&&(Ve("Operation cancelled."),K.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){ve(t)}Gr("Thanks for using IXO CLI!"),K.exit(0)}};K.on("uncaughtException",ve);K.on("unhandledRejection",ve);var Jr=new Fe;Jr.run(K.argv);
|
|
145
145
|
//# sourceMappingURL=cli.js.map
|