ixo-oracles-cli 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +11 -11
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{cancel as Re,intro as mr,isCancel as dt,log as X,outro as pr,select as mt,spinner as gr}from"@clack/prompts";import O from"process";var B=class{commands;constructor(){this.commands=new Map}register(e){this.commands.set(e.name,e)}get(e){return this.commands.get(e)}getAll(){return Array.from(this.commands.values())}getCommandOptions(){return this.getAll().map(e=>({value:e.name,label:e.name,hint:e.description}))}};import*as f from"@clack/prompts";import{select as ut}from"@clack/prompts";import{z as V}from"zod";var b=async r=>{let e=await ut({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},Ae={mainnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d",testnet:"did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb",devnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d"},E={devnet:"https://devmx.ixo.earth",testnet:"https://testmx.ixo.earth",mainnet:"https://mx.ixo.earth"},K={devnet:"https://rooms.bot.devmx.ixo.earth",testnet:"https://rooms.bot.testmx.ixo.earth",mainnet:"https://rooms.bot.mx.ixo.earth"};var be={devnet:"https://ixo-portal.vercel.app",testnet:"https://ixo-portal.vercel.app",mainnet:"https://ixo-portal.vercel.app"},U={mainnet:"https://impacthub.ixo.world/rpc/",testnet:"https://testnet.ixo.earth/rpc/",devnet:"https://devnet.ixo.earth/rpc/"},Pe={devnet:"https://domain-indexer.devnet.ixo.earth/index",testnet:"https://domain-indexer.testnet.ixo.earth/index",mainnet:"https://domain-indexer.ixo.earth/index"},C=(r,e="This field is required")=>{let i=V.string().min(1,e).safeParse(r);if(!i.success)return i.error.message},de=r=>{let t=V.string().regex(/^did:ixo:entity:[a-f0-9]{64}$/,"Invalid entity DID").safeParse(r);if(!t.success)return t.error.message},q=(r,e="This url is required or a valid URL")=>{let i=V.url(e).safeParse(r);if(!i.success)return i.error.message},Ie=(r,e="This number is required")=>{let i=V.number().min(1,e).safeParse(r);if(!i.success)return i.error.message};import{isCancel as zt,log as u,spinner as Jt,text as Qt}from"@clack/prompts";import{customMessages as it,ixo as x,utils as ye}from"@ixo/impactxclient-sdk";import{utils as we}from"@ixo/impactxclient-sdk";import{createMatrixApiClient as Bt}from"@ixo/matrixclient-sdk";import{sha256 as Ot}from"@cosmjs/crypto";import{encrypt as Nt}from"eciesjs";import{ClientEvent as kt,createClient as ue}from"matrix-js-sdk";import Ut from"md5";var G=new Map;function ft(r){return G.get(r)instanceof Uint8Array}function ht(r){return G.get(r)}function me(){G.clear()}async function Te({keys:r}){let e=Object.keys(r),t=e.find(ft);if(console.info("[] getSecretStorageKey",r,e,t),!t)return null;let i=ht(t);return[t,i]}function Oe(r,e,t){G.set(r,t)}import{Bip39 as De,EnglishMnemonic as Le,Secp256k1 as pe,sha256 as xt,Slip10 as Me,Slip10Curve as We,stringToPath as Ke}from"@cosmjs/crypto";import{DirectSecp256k1HdWallet as Ct}from"@cosmjs/proto-signing";import{createQueryClient as $e,createSigningClient as vt,customMessages as Rt,ixo as Et,utils as St}from"@ixo/impactxclient-sdk";import{createCipheriv as At,randomBytes as bt}from"crypto";import{createQueryClient as br,createRegistry as wt,utils as yt}from"@ixo/impactxclient-sdk";function $(r){try{return yt.proto.fromTimestamp(r).getTime()}catch{return}}var H={BasicAllowance:"/cosmos.feegrant.v1beta1.BasicAllowance",PeriodicAllowance:"/cosmos.feegrant.v1beta1.PeriodicAllowance"};var Ne=r=>{let e=wt();return(r??[]).map(t=>{let i=t.allowance,n=e.decode(i);switch(i.typeUrl){case H.BasicAllowance:return{granter:t.granter,grantee:t.grantee,type:H.BasicAllowance,expiration:n.expiration?$(n.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};case H.PeriodicAllowance:return{granter:t.granter,grantee:t.grantee,type:H.PeriodicAllowance,expiration:n.basic?.expiration?$(n.basic.expiration):null,limit:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};default:return{type:i.typeUrl,granter:t.granter,grantee:t.grantee,expiration:n.expiration?$(n.expiration):n.basic?.expiration?$(n.basic.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:n.allowedMessages}}})},ke=r=>{if(r==null)return!1;let e=typeof r=="object"?$(r):r;return e==null?!0:e<Date.now()},Ue=r=>r==null?!1:(typeof r=="object"?Number(r?.amount??0):typeof r=="string"?Number(r??0):r)<=5e-4;async function ge(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=U[e];if(!t)throw new Error(`Invalid network: ${e}. Valid networks are: ${Object.keys(U).join(", ")}`);console.log(`\u{1F517} Using RPC URL: ${t}`);try{return!!(await(await $e(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 _e(r,e,t){try{let i=await t.getAccounts(),{address:n,pubkey:o}=i[0]??{},s=await Pt(n,e),a=s?.length?Ne(s)?.find(l=>!!l&&!ke(l.expiration)&&!Ue(l.limit))?.granter:void 0,c={typeUrl:"/ixo.iid.v1beta1.MsgCreateIidDocument",value:Et.iid.v1beta1.MsgCreateIidDocument.fromPartial({id:r,verifications:Rt.iid.createIidVerificationMethods({did:r,pubkey:o,address:n,controller:r,type:"secp"}),signer:n,controllers:[r]})};await It({offlineSigner:t,messages:[c],feegrantGranter:a,network:e})}catch(i){throw console.error(i),i}}async function Pt(r,e){try{let t=U[e];if(!t)throw new Error(`Invalid network: ${e}`);return(await(await $e(t)).cosmos.feegrant.v1beta1.allowances({grantee:r}))?.allowances??[]}catch(t){console.error("queryAddressAllowances::",t.message);return}}var It=async({offlineSigner:r,messages:e,memo:t="Signing with Mnemonic Demo",feegrantGranter:i,network:n})=>{let o=U[n];if(!o)throw new Error(`Invalid network: ${n}`);let s=await vt(o,r),a=await r.getAccounts(),{address:c}=a[0]??{},l=await s.simulate(c,e,t),h=(l>5e4?l:(e??[]).length*5e5)*1.7,I=Tt(h),v={amount:[{denom:"uixo",amount:String(Math.round(I.average))}],gas:String(Math.round(h)),granter:i},R=await s.signAndBroadcast(c,e,v,t,void 0);if(!!R.code)throw new Error(`Error when broadcasting tx ${R.transactionHash} at height ${R.height}. Code: ${R.code}; Raw log: ${R.rawLog}`)},Tt=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}},z=r=>new Promise(e=>setTimeout(e,r));function je(r,e){let t=bt(16),i=At("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 Xe=async r=>{let e=await Ct.fromMnemonic(r,{prefix:"ixo"}),t=(await e.getAccounts())[0],i=await De.mnemonicToSeed(new Le(r)),n=Ke("m/44'/118'/0'/0/0"),s=Me.derivePath(We.Secp256k1,i,n).privkey,a=await pe.makeKeypair(s),c=pe.compressPubkey(a.pubkey);return{mnemonic:r,did:St.did.generateSecpDid(t.address),baseAccount:t,async getAccounts(){return await e.getAccounts()},async signDirect(d,h){return await e.signDirect(d,h)},async sign(d){try{let h=await De.mnemonicToSeed(new Le(r)),I=Ke("m/44'/118'/0'/0/0"),{privkey:v}=Me.derivePath(We.Secp256k1,h,I),R=new Uint8Array(Buffer.from(d,"base64")),se=xt(R);return(await pe.createSignature(se,v)).toFixedLength().slice(0,64)}catch(h){throw console.error("Error during signature creation:",h),h}}}};var Dt="/.well-known/matrix/client",fe=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 jt(o));try{let c=Ve(o),l=await c.login("m.login.password",{identifier:{type:"m.id.user",user:Xt(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 Lt(r){let e=await fetch(`${K[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 Mt(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 Wt(r,e){let t=new Uint8Array(Buffer.from(e,"hex")),i=new Uint8Array(Buffer.from(r,"utf8")),n=Nt(t,i);return Array.from(n,o=>o.toString(16).padStart(2,"0")).join("")}async function Kt(r,e,t,i,n){let o=await Lt(n),s=Wt(e,o.publicKey),a={address:r,encryptedPassword:s,publicKeyFingerprint:o.fingerprint,secpResult:{signature:t,challenge:i}},c=await fetch(`${K[n]}/user/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!c.ok){let l=await c.json();throw new Error(l.error||"Failed to create user account")}return await c.json()}async function Fe(r,e,t,i,n){try{let{challengeBase64:o}=Mt(r),s=await i.sign(o),a=Buffer.from(s).toString("base64");if(!(await Kt(r,e,a,o,n)).success)throw new Error("Failed to create matrix account via API");let l=E[n],d=he(r);return await fe({homeServerUrl:l,username:d,password:e,deviceName:t})}catch(o){throw console.error("mxRegisterWithSecp error:",o),o}}async function Be({homeServerUrl:r,username:e}){let t=Ve(r);try{return!!await t.isUsernameAvailable(e)}catch{return!1}}function Ve(r){if(!r)throw new Error("Home server URL is required to instantiate matrix client");return ue({baseUrl:r})}async function qe({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=ue({baseUrl:r,accessToken:e,userId:t,deviceId:i,timelineSupport:!0,cryptoCallbacks:{getSecretStorageKey:Te,cacheSecretStorageKey:Oe},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(kt.Sync,c=>{a[c]()})}),n}async function Ge({mxClient:r,baseUrl:e,accessToken:t,userId:i,deviceId:n}){let o=r;o||(o=ue({baseUrl:e,accessToken:t,userId:i,deviceId:n})),o&&(o.stopClient(),await o.logout().catch(console.error),o.clearStores())}function He(r){let e=r.getAccountData("m.cross_signing.master");return console.log("hasCrossSigningAccountData::masterKeyData",e),!!e}async function ze(r,{securityPhrase:e,password:t,forceReset:i=!1,skipBootstrapSecureStorage:n=!1}){i&&me();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);me(),await o.bootstrapSecretStorage({createSecretStorageKey:async()=>a,setupNewSecretStorage:i})}let s=r.getUserId();return await o.bootstrapCrossSigning({authUploadDeviceSigningKeys:async function(a){await a(Ft({userId:s,password:t}))},setupNewCrossSigning:i}),await o.resetKeyBackup(),await z(300),!!r.getAccountData("m.cross_signing.master")}function he(r){if(!r)throw new Error("Address is required to generate matrix username");return"did-ixo-"+r}function Je(r){return Buffer.from(Ut(r.replace(/ /g,""))).toString("base64").slice(0,24)}function Qe(r){let e=Ot(new TextEncoder().encode(r.replace(/ /g,"")));return Buffer.from(e).toString("base64").slice(0,32)}function $t(r){return r.replace(/^(https?:\/\/)/,"").replace(/\/$/,"")}function _t(r,e=""){return"did-ixo-"+r+e}function Ye(r,e){return"#"+_t(r)+":"+$t(e)}async function jt(r){let e="https://";/^https?:\/\//.test(r)&&(e="");let t=`${e}${r}${Dt}`;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 Xt(r){return(r.indexOf("@")===0?r.substring(1):r).trim()}function Ft({userId:r,password:e}){return{type:"m.login.password",password:e,identifier:{type:"m.id.user",user:r}}}var Ze="Oracles CLI";async function J({pin:r,oracleName:e,network:t,oracleAvatarUrl:i},n){try{let o=we.mnemonic.generateMnemonic(),s=await Xe(o),a=s.baseAccount.address;console.log("\u2705 Wallet created:",a),await n(a);let c=we.did.generateSecpDid(a),l=await ge(c,t);if(console.log("\u2705 DID exists:",l),!l&&(console.log("\u2705 DID does not exist, creating..."),await _e(c,t,s),console.log("\u2705 DID created, waiting 500ms..."),await z(500),console.log("\u2705 Checking if DID exists..."),!await ge(c,t)))throw new Error("Failed to create DID document");console.log("\u2705 DID created:",c);let d=we.mnemonic.generateMnemonic(12),h=E[t],I=he(a),v=Je(d),R=Qe(d);if(!await Be({homeServerUrl:h,username:I}))throw new Error("Matrix account already exists");let w=await Fe(a,v,Ze,s,t);if(!w?.accessToken)throw new Error("Failed to register matrix account");console.log("\u2705 Matrix account created:",w.userId);let N=await qe({homeServerUrl:h,accessToken:w.accessToken,userId:w.userId,deviceId:w.deviceId});try{await Promise.all([N.setDisplayName(e),N.setAvatarUrl(i)])}catch(k){console.error("Failed to set display name or avatar url:",k)}let F=Bt({homeServerUrl:h,accessToken:w.accessToken}),ae=He(N);if(!ae&&(ae=await ze(N,{securityPhrase:R,password:v,forceReset:!0}),!ae))throw new Error("Failed to setup cross signing");console.log("\u2705 Matrix cross-signing setup completed");let pt=Ye(a,w.baseUrl),S=(await F.room.v1beta1.queryId(pt).catch(()=>{}))?.room_id??"";if(!S){let k=await fetch(`${K[t]}/room/source`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:c,userMatrixId:w.userId})});if(!k.ok)throw new Error("Failed to create matrix room");if(S=(await k.json()).roomId,!S)throw new Error("Failed to create user matrix room")}let ce=await F.room.v1beta1.listJoinedMembers(S).catch(()=>{}),le=!!ce?.joined?.[w.userId];if(!le){if(!(await F.room.v1beta1.join(S)).room_id)throw new Error("Failed to join matrix room");if(ce=await F.room.v1beta1.listJoinedMembers(S),le=!!ce?.joined?.[w.userId],!le)throw new Error("Failed to join matrix room")}console.log("\u2705 Matrix room created/joined:",S);let gt=je(d,r),Se=await fetch(`${h}/_matrix/client/r0/rooms/${S}/state/ixo.room.state.secure/encrypted_mnemonic`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${w.accessToken}`},body:JSON.stringify({encrypted_mnemonic:gt})});if(!Se.ok)throw new Error("Failed to store encrypted mnemonic in matrix room");return await Se.json(),console.log("\u2705 Encrypted Matrix mnemonic stored in room"),await Ge({mxClient:N,baseUrl:h,accessToken:w.accessToken,userId:w.userId,deviceId:w.deviceId}),{address:a,did:c,mnemonic:o,matrixUserId:w.userId,matrixRoomId:S,matrixMnemonic:d,matrixPassword:v,matrixAccessToken:w.accessToken,matrixRecoveryPhrase:R,pin:r,matrixDeviceName:Ze}}catch(o){throw console.error("Simplified registration failed:",o),o}}import{createMatrixApiClient as Gt,utils as Ht}from"@ixo/matrixclient-sdk";import{CID as Vt}from"multiformats";import{base64 as qt}from"multiformats/bases/base64";import*as et from"multiformats/hashes/sha2";async function tt(r){let e=r.startsWith("m")?r:"m"+r,t=qt.decode(e),i=await et.sha256.digest(t);return Vt.create(1,85,i).toString()}function rt(r){let e=new TextEncoder().encode(r);return btoa(String.fromCharCode(...Array.from(e)))}var _=async({data:r,fileName:e,config:t,wallet:i})=>{let n=Gt({homeServerUrl:E[t.getValue("network")??"devnet"],accessToken:i?.matrix?.accessToken??""}),o=JSON.stringify(r),s=Buffer.from(o,"utf8"),a=e+".json",l=await n.media.v1beta1.upload(a,"application/ld+json",s),d=Ht.mxc.mxcUrlToHttp(E[t.getValue("network")??"devnet"],l.content_uri);if(!d)throw new Error("Failed to upload file to Matrix");let h=JSON.stringify(r),I=rt(h),v=await tt(I);return{encrypted:"false",cid:v,proof:v,serviceEndpoint:d,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,this.MsgCreateEntityParams.value.verification=[...it.iid.createIidVerificationMethods({did:e.did,pubkey:new Uint8Array(Buffer.from(e.pubKey)),address:e.address,controller:e.did,type:e.algo==="ed25519"?"ed":"secp"})],this.MsgCreateEntityParams.value.context=[],this.MsgCreateEntityParams.value.controller=[e.did],this.MsgCreateEntityParams.value.ownerAddress=e.address,this.MsgCreateEntityParams.value.ownerDid=e.did,this.MsgCreateEntityParams.value.service.push(x.iid.v1beta1.Service.fromPartial({id:"{id}#matrix",type:"Matrix",serviceEndpoint:"devmx.ixo.earth"})),this.MsgCreateEntityParams.value.relayerNode=Ae[this.config.getValue("network")??"devnet"]}wallet;MsgCreateEntityParams={typeUrl:"/ixo.entity.v1beta1.MsgCreateEntity",value:x.entity.v1beta1.MsgCreateEntity.fromPartial({entityType:"oracle",context:[],entityStatus:0,verification:[],controller:[],ownerAddress:"",ownerDid:"",relayerNode:"",service:[],linkedResource:[],accordedRight:[],linkedEntity:[],linkedClaim:[],startDate:ye.proto.toTimestamp(new Date),endDate:ye.proto.toTimestamp(new Date(Date.now()+100*365*24*60*60*1e3))})};addLinkedAccounts({oracleAccountAddress:e}){if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client or wallet not found");let n=[{devnet:"did:ixo:ixo17w9u5uk4qjyjgeyqfpnp92jwy58faey9vvp3ar",testnet:"did:ixo:ixo14vjrckltpngugp03tcasfgh5qakey9n3sgm6y2",mainnet:"did:ixo:ixo1d39eutxdc0e8mnp0fmzqjdy6aaf26s9hzrk33r"}[this.config.getValue("network")],`did:ixo:${e}`].map(o=>x.iid.v1beta1.LinkedEntity.fromPartial({id:o,type:"agent",relationship:"admin",service:"matrix"}));this.MsgCreateEntityParams.value.linkedEntity=n}async createAuthZConfig({oracleAccountAddress:e,oracleName:t,entityDid:i}){let o=await _({data:{"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":i,"@type":"@id"}}],"@type":"Service","@id":"oracle:OracleAuthorization",name:"OracleAuthorization",description:"OracleAuthorization",serviceType:"OracleClaimAuthorizationService",requiredPermissions:["/ixo.claims.v1beta1.MsgCreateClaimAuthorization"],granteeAddress:e,granterAddress:"",oracleName:t},fileName:"authz",config:this.config,wallet:this.wallet});return x.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#orz",type:"oracleAuthZConfig",proof:o.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Orale AuthZ Config",serviceEndpoint:o.serviceEndpoint})}async createFeesConfig({entityDid:e,price:t,denom:i}){let n={"@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"}}},o=await _({data:n,fileName:"fees",config:this.config,wallet:this.wallet});return x.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#fee",type:"pricingList",proof:o.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Pricing List",serviceEndpoint:o.serviceEndpoint})}async addControllerToEntity(e,t){let i=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!i)throw new Error("SignX client or wallet not found");let n={typeUrl:"/ixo.iid.v1beta1.MsgAddController",value:x.iid.v1beta1.MsgAddController.fromPartial({id:e,controllerDid:t,signer:i})};u.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(),u.success(`Controller ${t} added to entity ${e}`)}async createOracleConfigFiles({oracleName:e,entityDid:t,price:i,oracleAccountAddress:n}){let o=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!o)throw new Error("SignX client or wallet not found");let a=(await Promise.all([this.createAuthZConfig({oracleName:e,entityDid:t,oracleAccountAddress:n}),this.createFeesConfig({entityDid:t,price:i,denom:this.config.getValue("network")==="devnet"?"uixo":"ibc/6BBE9BD4246F8E04948D5A4EEE7164B2630263B9EBB5E7DC5F0A46C62A2FF97B"})])).map(d=>({typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:x.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:t,linkedResource:x.iid.v1beta1.LinkedResource.fromPartial({id:d.id,description:d.description,type:d.type,proof:d.proof,mediaType:d.mediaType,encrypted:d.encrypted,serviceEndpoint:d.serviceEndpoint}),signer:o})}));u.info("Sign to edit the entity and add the config files");let c=await this.wallet.signXClient.transact(a,this.wallet.wallet);return this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(c)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction()}async createDomainCard({profile:e,entityDid:t}){let i=new Date().toISOString(),n={"@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:i,credentialSchema:{id:"https://github.com/ixoworld/domainCards/schemas/ixo-domain-card-1.json",type:"JsonSchema"},credentialSubject:{id:t,type:["ixo:dao"],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}}},o=await _({data:n,fileName:"domainCard",config:this.config,wallet:this.wallet});return x.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#dmn",type:"domainCard",proof:o.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Domain Card",serviceEndpoint:o.serviceEndpoint})}async addProfile({orgName:e,name:t,logo:i,coverImage:n,location:o,description:s}){let c=await _({data:{"@context":{ixo:"https://w3id.org/ixo/ns/protocol/","@id":"@type",type:"@type","@protected":!1},id:"ixo:entity#profile",type:"profile",orgName:e,name:t,image:n,logo:i,brand:e,location:o,description:s},fileName:"profile",config:this.config,wallet:this.wallet}),l={id:"{id}#pro",type:"Settings",description:"Profile",mediaType:"application/json",serviceEndpoint:c.serviceEndpoint,proof:c.proof,encrypted:"false",right:""};this.MsgCreateEntityParams.value.linkedResource.push(x.iid.v1beta1.LinkedResource.fromPartial(l))}addServices(e){this.MsgCreateEntityParams.value.service.push(...e.map(t=>x.iid.v1beta1.Service.fromPartial(t)))}setParentProtocol(e){this.MsgCreateEntityParams.value.context.push(...it.iid.createAgentIidContext([{key:"class",val:e}]))}returnExecutableMsg(){return this.MsgCreateEntityParams}async submitToDomainIndexer(e){let t=this.config.getValue("network")??"devnet",i=Pe[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();u.warn(`Failed to submit to domain indexer: ${n.status} ${o}`);return}u.success("Domain card submitted to domain indexer")}catch(n){u.warn(`Error submitting to domain indexer: ${n instanceof Error?n.message:String(n)}`)}}async execute(e){u.info("Adding profile"),await this.addProfile(e.profile),u.info("Adding services"),this.addServices(e.services),u.info("Adding parent protocol"),this.setParentProtocol(e.parentProtocol);let t=this.returnExecutableMsg();if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client not found");u.info("Creating Oracle Wallet and Matrix Account");let i=await Qt({message:"Enter a PIN to secure your Matrix Vault:",initialValue:"",defaultValue:"",validate(d){return C(d,"PIN is required")}});zt(i)&&(u.error("User cancelled"),process.exit(1));let n=await J({pin:i,oracleName:e.oracleConfig.oracleName,network:this.config.getValue("network"),oracleAvatarUrl:e.profile.logo},async d=>{await this.wallet.sendTokens(d,25e4)});this.addLinkedAccounts({oracleAccountAddress:n.address}),u.info("Sign this transaction to create the entity");let o=await this.wallet.signXClient.transact([t],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(o)),await this.wallet.signXClient.pollNextTransaction();let s=await this.wallet.signXClient.awaitTransaction();u.success("Entity created -- wait to attach the required config files");let a=ye.common.getValueFromEvents(s,"wasm","token_id");u.info("Creating domain card");let c=await this.createDomainCard({profile:e.profile,entityDid:a});if(this.wallet.wallet?.address){let d={typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:x.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:a,linkedResource:x.iid.v1beta1.LinkedResource.fromPartial({id:c.id,description:c.description,type:c.type,proof:c.proof,mediaType:c.mediaType,encrypted:c.encrypted,serviceEndpoint:c.serviceEndpoint}),signer:this.wallet.wallet.address})};u.info("Sign to add domain card to the entity");let h=await this.wallet.signXClient.transact([d],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(h)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),u.success("Domain card added to entity")}await this.createOracleConfigFiles({oracleName:e.oracleConfig.oracleName,price:e.oracleConfig.price,oracleAccountAddress:n.address,entityDid:a}),u.success("Entity created -- config files attached");let l=Jt();l.start("Creating Entity Matrix Room..."),l.stop("Room created -- room joined"),u.warn("Please save the following information in a secure location as it is not stored:"),u.info("ORACLE ACCOUNT DETAILS");for(let d in n)u.info(`${d}: ${n[d]}`);return this.config.addValue("registerUserResult",n),this.config.addValue("entityDid",a),u.info("Submitting domain card to domain indexer"),await this.submitToDomainIndexer(a),a}};var L=class{constructor(e,t){this.wallet=e;this.config=t;this.createEntity=new D(this.wallet,this.config)}name="create-entity";description="Create an entity";createEntity;async execute(){this.config.getValue("network")||await b(this.config);let t=await f.group({oracleName:()=>f.text({message:"What is the name of the oracle?",initialValue:"My oracle",validate(s){return C(s,"Oracle name is required")}}),oraclePrice:()=>f.text({message:"What is the price of the oracle in IXO CREDITS?",initialValue:"100",validate(s){return Ie(parseInt(s),"Oracle price is required and must be a number")}}),profile:()=>f.group({orgName:()=>f.text({message:"What is the name of the organization?",initialValue:"IXO",validate(s){return C(s,"Organization name is required")}}),name:()=>f.text({message:"What is the name of the profile?",initialValue:"My oracle",validate(s){return C(s,"Profile name is required")}}),logo:({results:s})=>f.text({message:"What is the logo of the profile?",initialValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${s?.name??"IXO"}`,defaultValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${s?.name??"IXO"}`,validate(a){return a?q(a,"Logo is required or a valid URL"):`https://api.dicebear.com/8.x/bottts/svg?seed=${s?.name??"IXO"}`}}),coverImage:({results:s})=>f.text({message:"What is the cover image of the profile?",initialValue:s.logo,defaultValue:s.logo,validate(a){return a?q(a,"Cover image is required or a valid URL"):s.logo}}),location:()=>f.text({message:"What is the location of your domain?",initialValue:"New York, NY",validate(s){return C(s,"Location is required")}}),description:()=>f.text({message:"What is the description of the entity (profile)?",initialValue:"We are a company that helps you with daily tasks",validate(s){return C(s,"Description is required")}})}),parentProtocol:()=>f.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:()=>f.text({message:"What is the API URL of the oracle?",initialValue:"http://localhost:4000",validate(s){return q(s,"API URL is required or a valid URL")}})},{onCancel:()=>{f.cancel("Operation cancelled."),process.exit(0)}}),i=await this.createEntity.execute({oracleConfig:{oracleName:t.oracleName,price:parseInt(t.oraclePrice)},profile:{orgName:t.profile.orgName,name:t.profile.name,logo:t.profile.logo,coverImage:t.profile.coverImage,location:t.profile.location,description:t.profile.description},services:[{id:"{id}#api",serviceEndpoint:t.apiUrl,type:"oracleService"},{id:"{id}#ws",serviceEndpoint:t.apiUrl,type:"wsService"}],parentProtocol:t.parentProtocol});f.log.info(`API for the oracle is: ${t.apiUrl} | You can change this after you deploy the oracle`);let o=`${be[this.config.getValue("network")??"devnet"]}/oracle/${i}/overview`;return f.log.info(`Oracle created successfully: ${i}`),f.log.info(`Oracle URL: ${o}`),{success:!0,data:`Entity created successfully: ${i}`}}};import*as A from"@clack/prompts";var Q=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 b(this.config);let t=await A.text({message:"Enter your PIN",initialValue:"",validate(o){return C(o,"PIN is required")}});A.isCancel(t)&&(A.log.error("User cancelled"),process.exit(1));let i=await A.text({message:"Enter your oracle name",initialValue:"My oracle",validate(o){return C(o,"Oracle name is required")}});return A.isCancel(i)&&(A.log.error("User cancelled"),process.exit(1)),{success:!0,data:await J({pin:t,oracleName:i,network:e,oracleAvatarUrl:`https://api.dicebear.com/8.x/bottts/svg?seed=${i}`},async o=>{await this.wallet.sendTokens(o,15e4)})}}};var j=class{constructor(e){this.registry=e}name="help";description="Show help information and available commands";async execute(){return{success:!0,data:`
|
|
2
|
+
import{cancel as be,intro as wr,isCancel as gt,log as K,outro as yr,select as ut,spinner as xr}from"@clack/prompts";import O from"process";var B=class{commands;constructor(){this.commands=new Map}register(e){this.commands.set(e.name,e)}get(e){return this.commands.get(e)}getAll(){return Array.from(this.commands.values())}getCommandOptions(){return this.getAll().map(e=>({value:e.name,label:e.name,hint:e.description}))}};import*as u from"@clack/prompts";import{select as xt}from"@clack/prompts";import{z as k}from"zod";var I=async r=>{let e=await xt({message:"Select network: (default: devnet)",options:[{value:"mainnet",label:"Mainnet"},{value:"testnet",label:"Testnet"},{value:"devnet",label:"Devnet"}],initialValue:"devnet",maxItems:1});return r.addValue("network",e),e},Te={mainnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d",testnet:"did:ixo:entity:3d079ebc0b332aad3305bb4a51c72edb",devnet:"did:ixo:entity:2f22535f8b179a51d77a0e302e68d35d"},V={devnet:"https://devmx.ixo.earth",testnet:"https://testmx.ixo.earth",mainnet:"https://mx.ixo.earth"};var Pe={devnet:"https://ixo-portal.vercel.app",testnet:"https://ixo-portal.vercel.app",mainnet:"https://ixo-portal.vercel.app"},$={mainnet:"https://impacthub.ixo.world/rpc/",testnet:"https://testnet.ixo.earth/rpc/",devnet:"https://devnet.ixo.earth/rpc/"},Ue={devnet:"https://domain-indexer.devnet.ixo.earth/index",testnet:"https://domain-indexer.testnet.ixo.earth/index",mainnet:"https://domain-indexer.ixo.earth/index"},T=(r,e="This field is required")=>{let i=k.string().min(1,e).safeParse(r);if(!i.success)return i.error.message},ge=r=>{let t=k.string().regex(/^did:ixo:entity:[a-f0-9]{32}$/,"Invalid entity DID").safeParse(r);if(!t.success)return t.error.message},q=(r,e="This url is required or a valid URL")=>{let i=k.url(e).safeParse(r);if(!i.success)return i.error.message},Oe=(r,e="This number is required")=>{let i=k.number().min(1,e).safeParse(r);if(!i.success)return i.error.message},H=r=>{let t=k.string().min(1,"PIN is required").refine(i=>/^\d{6}$/.test(i),"PIN must be exactly 6 digits").safeParse(r);if(!t.success)return t.error.issues[0]?.message??"Invalid PIN"},G=r=>{let t=k.string().min(1,"Matrix homeserver URL is required").refine(i=>/^https?:\/\//.test(i),"Must start with http:// or https://").refine(i=>!i.endsWith("/"),"Must not end with a trailing slash").safeParse(r);if(!t.success)return t.error.issues[0]?.message??"Invalid Matrix URL"};function ke(r){let e=new URL(r),t=e.hostname,i=e.protocol;return{homeServerUrl:r,roomBotUrl:`${i}//rooms.bot.${t}`,stateBotUrl:`${i}//state.bot.${t}`,bidsBotUrl:`${i}//bids.bot.${t}`,claimsBotUrl:`${i}//claims.bot.${t}`}}import{isCancel as tr,log as w,spinner as rr,text as ir}from"@clack/prompts";import{customMessages as st,ixo as R,utils as Ce}from"@ixo/impactxclient-sdk";import{sha256 as Lt}from"@cosmjs/crypto";import{encrypt as Mt}from"eciesjs";import{ClientEvent as Wt,createClient as we}from"matrix-js-sdk";import $t from"md5";var z=new Map;function vt(r){return z.get(r)instanceof Uint8Array}function Ct(r){return z.get(r)}function ue(){z.clear()}async function Ne({keys:r}){let e=Object.keys(r),t=e.find(vt);if(console.info("[] getSecretStorageKey",r,e,t),!t)return null;let i=Ct(t);return[t,i]}function De(r,e,t){z.set(r,t)}import{Bip39 as $e,EnglishMnemonic as _e,Secp256k1 as fe,sha256 as Et,Slip10 as Xe,Slip10Curve as je,stringToPath as Ke}from"@cosmjs/crypto";import{DirectSecp256k1HdWallet as bt}from"@cosmjs/proto-signing";import{createQueryClient as Fe,createSigningClient as At,customMessages as It,ixo as Tt,utils as Pt}from"@ixo/impactxclient-sdk";import{createCipheriv as Ut,randomBytes as Ot}from"crypto";import{createRegistry as Rt,utils as St}from"@ixo/impactxclient-sdk";function _(r){try{return St.proto.fromTimestamp(r).getTime()}catch{return}}var J={BasicAllowance:"/cosmos.feegrant.v1beta1.BasicAllowance",PeriodicAllowance:"/cosmos.feegrant.v1beta1.PeriodicAllowance"},Le=r=>{let e=Rt();return(r??[]).map(t=>{let i=t.allowance,n=e.decode(i);switch(i.typeUrl){case J.BasicAllowance:return{granter:t.granter,grantee:t.grantee,type:J.BasicAllowance,expiration:n.expiration?_(n.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};case J.PeriodicAllowance:return{granter:t.granter,grantee:t.grantee,type:J.PeriodicAllowance,expiration:n.basic?.expiration?_(n.basic.expiration):null,limit:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:[]};default:return{type:i.typeUrl,granter:t.granter,grantee:t.grantee,expiration:n.expiration?_(n.expiration):n.basic?.expiration?_(n.basic.expiration):null,limit:n.spendLimit?.length?n.spendLimit.find(o=>o.denom==="uixo")?.amount:n?.periodCanSpend?n?.periodCanSpend?.find(o=>o.denom==="uixo")?.amount:n?.basic?.spendLimit?.length?n?.basic?.spendLimit?.find(o=>o.denom==="uixo")?.amount:null,msgs:n.allowedMessages}}})},Me=r=>{if(r==null)return!1;let e=typeof r=="object"?_(r):r;return e==null?!0:e<Date.now()},We=r=>r==null?!1:(typeof r=="object"?Number(r?.amount??0):typeof r=="string"?Number(r??0):r)<=5e-4;async function he(r,e){if(!e)throw new Error("Network parameter is required but was undefined");console.log(`\u{1F50D} Checking IID document for DID: ${r} on network: ${e}`);let t=$[e];if(!t)throw new Error(`Invalid network: ${e}. Valid networks are: ${Object.keys($).join(", ")}`);console.log(`\u{1F517} Using RPC URL: ${t}`);try{return!!(await(await Fe(t)).ixo.iid.v1beta1.iidDocument({id:r}))?.iidDocument?.id}catch(i){if(i.message?.includes("did document not found")||i.message?.includes("(22)"))return!1;throw console.error("Error checking IID document:",i),i}}async function Be(r,e,t,i){try{let n=await t.getAccounts(),{address:o,pubkey:s}=n[0]??{},a=await kt(o,e),c=a?.length?Le(a)?.find(d=>!!d&&!Me(d.expiration)&&!We(d.limit))?.granter:void 0,l={typeUrl:"/ixo.iid.v1beta1.MsgCreateIidDocument",value:Tt.iid.v1beta1.MsgCreateIidDocument.fromPartial({id:r,verifications:It.iid.createIidVerificationMethods({did:r,pubkey:s,address:o,controller:r,type:"secp"}),signer:o,controllers:[r],...i?.length?{services:i}:{}})};await Nt({offlineSigner:t,messages:[l],feegrantGranter:c,network:e})}catch(n){throw console.error(n),n}}async function kt(r,e){try{let t=$[e];if(!t)throw new Error(`Invalid network: ${e}`);return(await(await Fe(t)).cosmos.feegrant.v1beta1.allowances({grantee:r}))?.allowances??[]}catch(t){console.error("queryAddressAllowances::",t.message);return}}var Nt=async({offlineSigner:r,messages:e,memo:t="Signing with Mnemonic Demo",feegrantGranter:i,network:n})=>{let o=$[n];if(!o)throw new Error(`Invalid network: ${n}`);let s=await At(o,r),a=await r.getAccounts(),{address:c}=a[0]??{},l=await s.simulate(c,e,t),m=(l>5e4?l:(e??[]).length*5e5)*1.7,g=Dt(m),v={amount:[{denom:"uixo",amount:String(Math.round(g.average))}],gas:String(Math.round(m)),granter:i},y=await s.signAndBroadcast(c,e,v,t,void 0);if(!!y.code)throw new Error(`Error when broadcasting tx ${y.transactionHash} at height ${y.height}. Code: ${y.code}; Raw log: ${y.rawLog}`)},Dt=r=>{let e={low:.02,average:.035,high:.045},t=r<.01?.01:r;return{low:t*e.low,average:t*e.average,high:t*e.high}},Q=r=>new Promise(e=>setTimeout(e,r));function Ve(r,e){let t=Ot(16),i=Ut("aes-256-cbc",Buffer.from(e.padEnd(32)),t),n=i.update(r);return n=Buffer.concat([n,i.final()]),t.toString("hex")+":"+n.toString("hex")}var qe=async r=>{let e=await bt.fromMnemonic(r,{prefix:"ixo"}),t=(await e.getAccounts())[0],i=await $e.mnemonicToSeed(new _e(r)),n=Ke("m/44'/118'/0'/0/0"),s=Xe.derivePath(je.Secp256k1,i,n).privkey,a=await fe.makeKeypair(s),c=fe.compressPubkey(a.pubkey);return{mnemonic:r,did:Pt.did.generateSecpDid(t.address),baseAccount:t,async getAccounts(){return await e.getAccounts()},async signDirect(d,m){return await e.signDirect(d,m)},async sign(d){try{let m=await $e.mnemonicToSeed(new _e(r)),g=Ke("m/44'/118'/0'/0/0"),{privkey:v}=Xe.derivePath(je.Secp256k1,m,g),y=new Uint8Array(Buffer.from(d,"base64")),A=Et(y);return(await fe.createSignature(A,v)).toFixedLength().slice(0,64)}catch(m){throw console.error("Error during signature creation:",m),m}}}};var _t="/.well-known/matrix/client",ye=async({homeServerUrl:r,username:e,password:t,deviceName:i},n=!1)=>{let o=r,s=e,a=s.match(/^@(.+):(.+\..+)$/);a&&(s=a[1],o=a[2],o=n?o:await qt(o));try{let c=ze(o),l=await c.login("m.login.password",{identifier:{type:"m.id.user",user:Ht(s)},password:t,initial_device_display_name:i});return{accessToken:l.access_token,deviceId:l.device_id,userId:l.user_id,baseUrl:n?o:l?.well_known?.["m.homeserver"]?.base_url||c.baseUrl}}catch(c){let l=c.message;throw l==="Unknown message"&&(l="Please check your credentials"),console.error("mxLogin::",l),new Error(l)}};async function Xt(r){let e=await fetch(`${r}/public-key`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw new Error("Failed to fetch public key for encryption");return await e.json()}function jt(r){let e={timestamp:new Date().toISOString(),address:r,service:"matrix",type:"create-account"},t=Buffer.from(JSON.stringify(e)).toString("base64");return{challenge:e,challengeBase64:t}}function Kt(r,e){let t=new Uint8Array(Buffer.from(e,"hex")),i=new Uint8Array(Buffer.from(r,"utf8")),n=Mt(t,i);return Array.from(n,o=>o.toString(16).padStart(2,"0")).join("")}async function Ft(r,e,t,i,n,o){let s=await Xt(o),a=Kt(e,s.publicKey),c={address:r,encryptedPassword:a,publicKeyFingerprint:s.fingerprint,secpResult:{signature:t,challenge:i}},l=await fetch(`${o}/user/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let d=await l.text(),m=`Failed to create user account (HTTP ${l.status})`;try{let g=JSON.parse(d);m=g.error||g.message||g.detail||d}catch{m=d||m}throw console.error(`Room bot error [${l.status}]: ${d}`),new Error(m)}return await l.json()}async function He(r,e,t,i,n,o){try{let{challengeBase64:s}=jt(r),a=await i.sign(s),c=Buffer.from(a).toString("base64");if(!(await Ft(r,e,c,s,n,o)).success)throw new Error("Failed to create matrix account via API");let d=xe(r);return await ye({homeServerUrl:n,username:d,password:e,deviceName:t})}catch(s){throw console.error("mxRegisterWithSecp error:",s),s}}async function Ge({homeServerUrl:r,username:e}){let t=ze(r);try{return!!await t.isUsernameAvailable(e)}catch{return!1}}function ze(r){if(!r)throw new Error("Home server URL is required to instantiate matrix client");return we({baseUrl:r})}async function Je({homeServerUrl:r,accessToken:e,userId:t,deviceId:i}){if(console.log("createMatrixClient::",{homeServerUrl:r,accessToken:e,userId:t,deviceId:i}),!r||!e||!t||!i)throw new Error("Login to Matrix account before trying to instantiate Matrix client.");let n=we({baseUrl:r,accessToken:e,userId:t,deviceId:i,timelineSupport:!0,cryptoCallbacks:{getSecretStorageKey:Ne,cacheSecretStorageKey:De},verificationMethods:["m.sas.v1"]});return await n.initRustCrypto({useIndexedDB:!1}),n.setMaxListeners(20),await n.startClient({lazyLoadMembers:!0,includeArchivedRooms:!1}),await new Promise((o,s)=>{let a={NULL:()=>{console.info("[NULL] state")},SYNCING:()=>{},PREPARED:()=>{console.info(`[PREPARED] state: user ${t}`),o()},RECONNECTING:()=>{console.info("[RECONNECTING] state")},CATCHUP:()=>{console.info("[CATCHUP] state")},ERROR:()=>{s(new Error("[ERROR] state: starting matrix client"))},STOPPED:()=>{console.info("[STOPPED] state")}};n.on(Wt.Sync,c=>{a[c]()})}),n}async function Y({mxClient:r,baseUrl:e,accessToken:t,userId:i,deviceId:n}){let o=r;o||(o=we({baseUrl:e,accessToken:t,userId:i,deviceId:n})),o&&(o.stopClient(),await o.logout().catch(console.error),o.clearStores())}function Qe(r){let e=r.getAccountData("m.cross_signing.master");return console.log("hasCrossSigningAccountData::masterKeyData",e),!!e}async function Ye(r,{securityPhrase:e,password:t,forceReset:i=!1,skipBootstrapSecureStorage:n=!1}){i&&ue();let o=r.getCrypto();if(!o)throw new Error("Failed to setup matrix cross signing - failed to get matrix crypto api");if(!n){let a=await o.createRecoveryKeyFromPassphrase(e);ue(),await o.bootstrapSecretStorage({createSecretStorageKey:async()=>a,setupNewSecretStorage:i})}let s=r.getUserId();return await o.bootstrapCrossSigning({authUploadDeviceSigningKeys:async function(a){await a(Gt({userId:s,password:t}))},setupNewCrossSigning:i}),await o.resetKeyBackup(),await Q(300),!!r.getAccountData("m.cross_signing.master")}function xe(r){if(!r)throw new Error("Address is required to generate matrix username");return"did-ixo-"+r}function Ze(r){return Buffer.from($t(r.replace(/ /g,""))).toString("base64").slice(0,24)}function et(r){let e=Lt(new TextEncoder().encode(r.replace(/ /g,"")));return Buffer.from(e).toString("base64").slice(0,32)}function Bt(r){return r.replace(/^(https?:\/\/)/,"").replace(/\/$/,"")}function Vt(r,e=""){return"did-ixo-"+r+e}function tt(r,e){return"#"+Vt(r)+":"+Bt(e)}async function qt(r){let e="https://";/^https?:\/\//.test(r)&&(e="");let t=`${e}${r}${_t}`;try{let o=(await(await fetch(t,{method:"GET"})).json())["m.homeserver"]?.base_url;if(o===void 0)throw new Error;return o}catch{return`${e}${r}`}}function Ht(r){return(r.indexOf("@")===0?r.substring(1):r).trim()}function Gt({userId:r,password:e}){return{type:"m.login.password",password:e,identifier:{type:"m.id.user",user:r}}}import{ixo as zt,utils as ve}from"@ixo/impactxclient-sdk";import{createMatrixApiClient as Jt}from"@ixo/matrixclient-sdk";var rt="Oracles CLI";async function Z({pin:r,oracleName:e,network:t,oracleAvatarUrl:i,matrixHomeServerUrl:n},o){try{let{homeServerUrl:s,roomBotUrl:a}=ke(n),c=ve.mnemonic.generateMnemonic(),l=await qe(c),d=l.baseAccount.address;console.log("\u2705 Wallet created:",d),await o(d);let m=ve.did.generateSecpDid(d),g=await he(m,t);if(console.log("\u2705 DID exists:",g),!g){console.log("\u2705 DID does not exist, creating...");let P=zt.iid.v1beta1.Service.fromPartial({id:`${m}#matrix`,type:"MatrixHomeServer",serviceEndpoint:s});if(await Be(m,t,l,[P]),console.log("\u2705 DID created, waiting 500ms..."),await Q(500),console.log("\u2705 Checking if DID exists..."),!await he(m,t))throw new Error("Failed to create DID document")}console.log("\u2705 DID created:",m);let v=ve.mnemonic.generateMnemonic(12),y=xe(d),A=Ze(v),le=et(v);if(!await Ge({homeServerUrl:s,username:y}))throw new Error("Matrix account already exists");let C=await He(d,A,rt,l,s,a);if(!C?.accessToken)throw new Error("Failed to register matrix account");console.log("\u2705 Matrix account created:",C.userId);let W=await Je({homeServerUrl:s,accessToken:C.accessToken,userId:C.userId,deviceId:C.deviceId});try{await Promise.all([W.setDisplayName(e),W.setAvatarUrl(i)])}catch(P){console.error("Failed to set display name or avatar url:",P)}let F=Jt({homeServerUrl:s,accessToken:C.accessToken}),de=Qe(W);if(!de&&(de=await Ye(W,{securityPhrase:le,password:A,forceReset:!0}),!de))throw new Error("Failed to setup cross signing");console.log("\u2705 Matrix cross-signing setup completed");let ht=tt(d,C.baseUrl),E=(await F.room.v1beta1.queryId(ht).catch(()=>{}))?.room_id??"";if(!E){let P=await fetch(`${a}/room/source`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:m,userMatrixId:C.userId})});if(!P.ok)throw new Error("Failed to create matrix room");if(E=(await P.json()).roomId,!E)throw new Error("Failed to create user matrix room")}let me=await F.room.v1beta1.listJoinedMembers(E).catch(()=>{}),pe=!!me?.joined?.[C.userId];if(!pe){if(!(await F.room.v1beta1.join(E)).room_id)throw new Error("Failed to join matrix room");if(me=await F.room.v1beta1.listJoinedMembers(E),pe=!!me?.joined?.[C.userId],!pe)throw new Error("Failed to join matrix room")}console.log("\u2705 Matrix room created/joined:",E);let wt=Ve(v,r),Ie=await fetch(`${s}/_matrix/client/v3/rooms/${E}/state/ixo.room.state.secure/encrypted_mnemonic`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${C.accessToken}`},body:JSON.stringify({encrypted_mnemonic:wt})});if(!Ie.ok)throw new Error("Failed to store encrypted mnemonic in matrix room");return await Ie.json(),console.log("\u2705 Encrypted Matrix mnemonic stored in room"),W.stopClient(),{address:d,did:m,mnemonic:c,matrixUserId:C.userId,matrixRoomId:E,matrixMnemonic:v,matrixPassword:A,matrixAccessToken:C.accessToken,matrixRecoveryPhrase:le,matrixHomeServerUrl:s,pin:r,matrixDeviceName:rt}}catch(s){throw console.error("Simplified registration failed:",s),s}}import{createMatrixApiClient as Zt,utils as er}from"@ixo/matrixclient-sdk";import{CID as Qt}from"multiformats";import{base64 as Yt}from"multiformats/bases/base64";import*as it from"multiformats/hashes/sha2";async function nt(r){let e=r.startsWith("m")?r:"m"+r,t=Yt.decode(e),i=await it.sha256.digest(t);return Qt.create(1,85,i).toString()}function ot(r){let e=new TextEncoder().encode(r);return btoa(String.fromCharCode(...Array.from(e)))}var X=async({data:r,fileName:e,homeServerUrl:t,accessToken:i})=>{let n=Zt({homeServerUrl:t,accessToken:i}),o=JSON.stringify(r),s=Buffer.from(o,"utf8"),a=e+".json",l=await n.media.v1beta1.upload(a,"application/ld+json",s),d=er.mxc.mxcUrlToHttp(t,l.content_uri);if(!d)throw new Error("Failed to upload file to Matrix");let m=JSON.stringify(r),g=ot(m),v=await nt(g);return{encrypted:"false",cid:v,proof:v,serviceEndpoint:d,mxc:l.content_uri}};var N=class{constructor(e,t){this.config=t;if(!e.did||!e.pubKey||!e.address||!e.algo)throw new Error("Wallet not found");this.wallet=e}wallet;buildMsgCreateEntity(e){return{typeUrl:"/ixo.entity.v1beta1.MsgCreateEntity",value:R.entity.v1beta1.MsgCreateEntity.fromPartial({entityType:"oracle",context:[],entityStatus:0,verification:[...st.iid.createIidVerificationMethods({did:this.wallet.did,pubkey:new Uint8Array(Buffer.from(this.wallet.pubKey)),address:this.wallet.address,controller:this.wallet.did,type:this.wallet.algo==="ed25519"?"ed":"secp"})],controller:[this.wallet.did],ownerAddress:this.wallet.address,ownerDid:this.wallet.did,relayerNode:Te[this.config.getValue("network")??"devnet"],service:[R.iid.v1beta1.Service.fromPartial({id:"{id}#matrix",type:"MatrixHomeServer",serviceEndpoint:e})],linkedResource:[],accordedRight:[],linkedEntity:[],linkedClaim:[],startDate:Ce.proto.toTimestamp(new Date),endDate:Ce.proto.toTimestamp(new Date(Date.now()+31536e8))})}}addLinkedAccounts(e,{oracleAccountAddress:t}){if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client or wallet not found");let o=[{devnet:"did:ixo:ixo17w9u5uk4qjyjgeyqfpnp92jwy58faey9vvp3ar",testnet:"did:ixo:ixo14vjrckltpngugp03tcasfgh5qakey9n3sgm6y2",mainnet:"did:ixo:ixo1d39eutxdc0e8mnp0fmzqjdy6aaf26s9hzrk33r"}[this.config.getValue("network")],`did:ixo:${t}`].map(s=>R.iid.v1beta1.LinkedEntity.fromPartial({id:s,type:"agent",relationship:"admin",service:"matrix"}));e.value.linkedEntity=o}async createAuthZConfig({oracleAccountAddress:e,oracleName:t,entityDid:i,homeServerUrl:n,accessToken:o}){let a=await X({data:{"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":i,"@type":"@id"}}],"@type":"Service","@id":"oracle:OracleAuthorization",name:"OracleAuthorization",description:"OracleAuthorization",serviceType:"OracleClaimAuthorizationService",requiredPermissions:["/ixo.claims.v1beta1.MsgCreateClaimAuthorization"],granteeAddress:e,granterAddress:"",oracleName:t},fileName:"authz",homeServerUrl:n,accessToken:o});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#orz",type:"oracleAuthZConfig",proof:a.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Orale AuthZ Config",serviceEndpoint:a.serviceEndpoint})}async createFeesConfig({entityDid:e,price:t,denom:i,homeServerUrl:n,accessToken:o}){let s={"@context":["https://schema.org",{ixo:"https://w3id.org/ixo/context/v1",oracle:{"@id":e,"@type":"@id"}}],"@type":"Service","@id":"oracle:ServiceFeeModel",name:"Pricing",description:"Pricing",serviceType:"",offers:{"@type":"Offer",priceCurrency:i,priceSpecification:{"@type":"PaymentChargeSpecification",priceCurrency:i,price:t*1e3,unitCode:"MON",billingIncrement:1,billingPeriod:"P1M",priceType:"Subscription",maxPrice:t},eligibleQuantity:{"@type":"QuantitativeValue",value:1,unitCode:"MON"}}},a=await X({data:s,fileName:"fees",homeServerUrl:n,accessToken:o});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#fee",type:"pricingList",proof:a.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Pricing List",serviceEndpoint:a.serviceEndpoint})}async addControllerToEntity(e,t){let i=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!i)throw new Error("SignX client or wallet not found");let n={typeUrl:"/ixo.iid.v1beta1.MsgAddController",value:R.iid.v1beta1.MsgAddController.fromPartial({id:e,controllerDid:t,signer:i})};w.info(`Sign to add controller ${t} to entity ${e}`);let o=await this.wallet.signXClient.transact([n],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(o)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),w.success(`Controller ${t} added to entity ${e}`)}async createOracleConfigFiles({oracleName:e,entityDid:t,price:i,oracleAccountAddress:n,homeServerUrl:o,accessToken:s}){let a=this.wallet.wallet?.address;if(!this.wallet.signXClient||!this.wallet.wallet||!a)throw new Error("SignX client or wallet not found");let l=(await Promise.all([this.createAuthZConfig({oracleName:e,entityDid:t,oracleAccountAddress:n,homeServerUrl:o,accessToken:s}),this.createFeesConfig({entityDid:t,price:i,denom:this.config.getValue("network")==="devnet"?"uixo":"ibc/6BBE9BD4246F8E04948D5A4EEE7164B2630263B9EBB5E7DC5F0A46C62A2FF97B",homeServerUrl:o,accessToken:s})])).map(g=>({typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:R.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:t,linkedResource:R.iid.v1beta1.LinkedResource.fromPartial({id:g.id,description:g.description,type:g.type,proof:g.proof,mediaType:g.mediaType,encrypted:g.encrypted,serviceEndpoint:g.serviceEndpoint}),signer:a})}));w.info("Sign to edit the entity and add the config files");let d=await this.wallet.signXClient.transact(l,this.wallet.wallet);return this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(d)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction()}async createDomainCard({profile:e,entityDid:t,homeServerUrl:i,accessToken:n}){let o=new Date().toISOString(),s={"@context":["https://www.w3.org/ns/credentials/v2","https://w3id.org/ixo/context/v1",{schema:"https://schema.org/",ixo:"https://w3id.org/ixo/vocab/v1",prov:"http://www.w3.org/ns/prov#",proj:"https://linked.data.gov.au/def/project#",xsd:"http://www.w3.org/2001/XMLSchema#",id:"@id",type:"@type","ixo:vector":{"@container":"@list","@type":"xsd:double"},"@protected":!0}],id:`${t}#dmn`,type:["VerifiableCredential","ixo:DomainCard"],issuer:{id:this.wallet.did},validFrom:o,credentialSchema:{id:"https://github.com/ixoworld/domainCards/schemas/ixo-domain-card-1.json",type:"JsonSchema"},credentialSubject:{id:t,type:["ixo:oracle"],additionalType:["schema:Organization"],name:e.name,alternateName:e.orgName!==e.name?[e.orgName]:void 0,description:e.description,logo:{type:"schema:ImageObject",id:e.logo,contentUrl:e.logo},image:[{type:"schema:ImageObject",id:e.coverImage,contentUrl:e.coverImage}],address:{type:"schema:PostalAddress",addressLocality:e.location},...e.url?{url:e.url}:{}}},a=await X({data:s,fileName:"domainCard",homeServerUrl:i,accessToken:n});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#dmn",type:"domainCard",proof:a.proof,right:"",encrypted:"false",mediaType:"application/json",description:"Domain Card",serviceEndpoint:a.serviceEndpoint})}async addProfile({orgName:e,name:t,logo:i,coverImage:n,location:o,description:s,homeServerUrl:a,accessToken:c}){let d=await X({data:{"@context":{ixo:"https://w3id.org/ixo/ns/protocol/","@id":"@type",type:"@type","@protected":!1},id:"ixo:entity#profile",type:"profile",orgName:e,name:t,image:n,logo:i,brand:e,location:o,description:s},fileName:"profile",homeServerUrl:a,accessToken:c});return R.iid.v1beta1.LinkedResource.fromPartial({id:"{id}#pro",type:"Settings",description:"Profile",mediaType:"application/json",serviceEndpoint:d.serviceEndpoint,proof:d.proof,encrypted:"false",right:""})}addServices(e,t){e.value.service.push(...t.map(i=>R.iid.v1beta1.Service.fromPartial(i)))}setParentProtocol(e,t){e.value.context.push(...st.iid.createAgentIidContext([{key:"class",val:t}]))}async submitToDomainIndexer(e){let t=this.config.getValue("network")??"devnet",i=Ue[t];try{let n=await fetch(i,{method:"POST",headers:{accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({did:e})});if(!n.ok){let o=await n.text();w.warn(`Failed to submit to domain indexer: ${n.status} ${o}`);return}w.success("Domain card submitted to domain indexer")}catch(n){w.warn(`Error submitting to domain indexer: ${n instanceof Error?n.message:String(n)}`)}}async execute(e){if(!this.wallet.signXClient||!this.wallet.wallet)throw new Error("SignX client not found");let{matrixHomeServerUrl:t}=e;w.info("Creating Oracle Wallet and Matrix Account");let i=await ir({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(y){return H(y)}});tr(i)&&(w.error("User cancelled"),process.exit(1));let n=await Z({pin:i,oracleName:e.oracleConfig.oracleName,network:this.config.getValue("network"),oracleAvatarUrl:e.profile.logo,matrixHomeServerUrl:t},async y=>{await this.wallet.sendTokens(y,25e4)}),o=n.matrixHomeServerUrl,s=n.matrixAccessToken;w.info("Adding profile");let a=await this.addProfile({...e.profile,homeServerUrl:o,accessToken:s}),c=this.buildMsgCreateEntity(t);c.value.linkedResource.push(a),w.info("Adding services"),this.addServices(c,e.services),w.info("Adding parent protocol"),this.setParentProtocol(c,e.parentProtocol),this.addLinkedAccounts(c,{oracleAccountAddress:n.address}),w.info("Sign this transaction to create the entity");let l=await this.wallet.signXClient.transact([c],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(l)),await this.wallet.signXClient.pollNextTransaction();let d=await this.wallet.signXClient.awaitTransaction();w.success("Entity created -- wait to attach the required config files");let m=Ce.common.getValueFromEvents(d,"wasm","token_id");w.info("Creating domain card");let g=await this.createDomainCard({profile:e.profile,entityDid:m,homeServerUrl:o,accessToken:s});if(this.wallet.wallet?.address){let y={typeUrl:"/ixo.iid.v1beta1.MsgAddLinkedResource",value:R.iid.v1beta1.MsgAddLinkedResource.fromPartial({id:m,linkedResource:R.iid.v1beta1.LinkedResource.fromPartial({id:g.id,description:g.description,type:g.type,proof:g.proof,mediaType:g.mediaType,encrypted:g.encrypted,serviceEndpoint:g.serviceEndpoint}),signer:this.wallet.wallet.address})};w.info("Sign to add domain card to the entity");let A=await this.wallet.signXClient.transact([y],this.wallet.wallet);this.wallet.signXClient.displayTransactionQRCode(JSON.stringify(A)),await this.wallet.signXClient.pollNextTransaction(),await this.wallet.signXClient.awaitTransaction(),w.success("Domain card added to entity")}await this.createOracleConfigFiles({oracleName:e.oracleConfig.oracleName,price:e.oracleConfig.price,oracleAccountAddress:n.address,entityDid:m,homeServerUrl:o,accessToken:s}),w.success("Entity created -- config files attached"),await Y({baseUrl:o,accessToken:s,userId:n.matrixUserId,deviceId:""});let v=rr();v.start("Creating Entity Matrix Room..."),v.stop("Room created -- room joined"),w.warn("Please save the following information in a secure location as it is not stored:"),w.info("ORACLE ACCOUNT DETAILS");for(let y in n)w.info(`${y}: ${n[y]}`);return this.config.addValue("registerUserResult",n),this.config.addValue("entityDid",m),this.config.addValue("oracleMatrixHomeServerUrl",t),w.info("Submitting domain card to domain indexer"),await this.submitToDomainIndexer(m),m}};var D=class{constructor(e,t){this.wallet=e;this.config=t}name="create-entity";description="Create an entity";async execute(){this.config.getValue("network")||await I(this.config);let t=this.wallet.matrixHomeServer??V[this.config.getValue("network")??"devnet"],i=await u.group({matrixHomeServerUrl:()=>u.text({message:"Matrix homeserver URL for the oracle:",initialValue:t,defaultValue:t,validate(c){return G(c)}}),oracleName:()=>u.text({message:"What is the name of the oracle?",initialValue:"My oracle",validate(c){return T(c,"Oracle name is required")}}),oraclePrice:()=>u.text({message:"What is the price of the oracle in IXO CREDITS?",initialValue:"100",validate(c){return Oe(parseInt(c??""),"Oracle price is required and must be a number")}}),profile:()=>u.group({orgName:()=>u.text({message:"What is the name of the organization?",initialValue:"IXO",validate(c){return T(c,"Organization name is required")}}),name:()=>u.text({message:"What is the name of the profile?",initialValue:"My oracle",validate(c){return T(c,"Profile name is required")}}),logo:({results:c})=>u.text({message:"What is the logo of the profile?",initialValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`,defaultValue:`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`,validate(l){return l?q(l,"Logo is required or a valid URL"):`https://api.dicebear.com/8.x/bottts/svg?seed=${c?.name??"IXO"}`}}),coverImage:({results:c})=>u.text({message:"What is the cover image of the profile?",initialValue:c.logo,defaultValue:c.logo,validate(l){return l?q(l,"Cover image is required or a valid URL"):c.logo}}),location:()=>u.text({message:"What is the location of your domain?",initialValue:"New York, NY",validate(c){return T(c,"Location is required")}}),description:()=>u.text({message:"What is the description of the entity (profile)?",initialValue:"We are a company that helps you with daily tasks",validate(c){return T(c,"Description is required")}}),url:()=>u.text({message:"What is the website URL of the oracle? (optional, press Enter to skip)",placeholder:"https://your-oracle-website.com"})}),parentProtocol:()=>u.select({message:"What is the parent protocol of the entity?",options:[{value:"did:ixo:entity:1a76366f16570483cea72b111b27fd78",label:"IXO Oracle Protocol",hint:"default protocol"}],initialValue:"did:ixo:entity:1a76366f16570483cea72b111b27fd78"}),apiUrl:()=>u.text({message:"What is the API URL of the oracle?",initialValue:"http://localhost:4000",validate(c){return q(c,"API URL is required or a valid URL")}})},{onCancel:()=>{u.cancel("Operation cancelled."),process.exit(0)}}),o=await new N(this.wallet,this.config).execute({oracleConfig:{oracleName:i.oracleName,price:parseInt(i.oraclePrice)},profile:{orgName:i.profile.orgName,name:i.profile.name,logo:i.profile.logo,coverImage:i.profile.coverImage,location:i.profile.location,description:i.profile.description,...i.profile.url?{url:i.profile.url}:{}},services:[{id:"{id}#api",serviceEndpoint:i.apiUrl,type:"oracleService"},{id:"{id}#ws",serviceEndpoint:i.apiUrl,type:"wsService"}],parentProtocol:i.parentProtocol,matrixHomeServerUrl:i.matrixHomeServerUrl});u.log.info(`API for the oracle is: ${i.apiUrl} | You can change this after you deploy the oracle`);let a=`${Pe[this.config.getValue("network")??"devnet"]}/oracle/${o}/overview`;return u.log.info(`Oracle created successfully: ${o}`),u.log.info(`Oracle URL: ${a}`),{success:!0,data:`Entity created successfully: ${o}`}}};import*as S from"@clack/prompts";var ee=class{constructor(e,t){this.wallet=e;this.config=t}name="create-user";description="Create a new user";async execute(){let e=this.config.getValue("network");e||await I(this.config);let t=this.wallet.matrixHomeServer??V[this.config.getValue("network")??"devnet"],i=await S.text({message:"Matrix homeserver URL:",initialValue:t,defaultValue:t,validate(a){return G(a)}});S.isCancel(i)&&(S.log.error("User cancelled"),process.exit(1));let n=await S.text({message:"Enter a 6-digit PIN to secure your Matrix Vault:",placeholder:"123456",validate(a){return H(a)}});S.isCancel(n)&&(S.log.error("User cancelled"),process.exit(1));let o=await S.text({message:"Enter your oracle name",initialValue:"My oracle",validate(a){return T(a,"Oracle name is required")}});S.isCancel(o)&&(S.log.error("User cancelled"),process.exit(1));let s=await Z({pin:n,oracleName:o,network:this.config.getValue("network")??e,oracleAvatarUrl:`https://api.dicebear.com/8.x/bottts/svg?seed=${o}`,matrixHomeServerUrl:i},async a=>{await this.wallet.sendTokens(a,15e4)});return await Y({baseUrl:s.matrixHomeServerUrl,accessToken:s.matrixAccessToken,userId:s.matrixUserId,deviceId:""}),{success:!0,data:s}}};var j=class{constructor(e){this.registry=e}name="help";description="Show help information and available commands";async execute(){return{success:!0,data:`
|
|
3
3
|
IXO Oracles CLI - Help
|
|
4
4
|
|
|
5
5
|
USAGE:
|
|
@@ -19,13 +19,13 @@ OPTIONS:
|
|
|
19
19
|
--help, -h Show help information
|
|
20
20
|
|
|
21
21
|
For more information, visit: https://github.com/ixoworld/ixo-oracles-cli
|
|
22
|
-
`}}};import*as
|
|
23
|
-
PORT=4000
|
|
22
|
+
`}}};import*as p from"@clack/prompts";import{existsSync as te}from"fs";import L from"path";import lt from"simple-git";import Re from"fs";import at from"path";var ct=async r=>{let e=r.getOrThrow("oracleMatrixHomeServerUrl"),t=await ye({homeServerUrl:e,username:r.getOrThrow("registerUserResult").matrixUserId,password:r.getOrThrow("registerUserResult").matrixPassword,deviceName:r.getOrThrow("registerUserResult").matrixDeviceName}),i=r.getOrThrow("projectPath"),n=at.join(i,"apps","app",".env");console.log("Creating .env file at:",n),console.log("Project path:",i);let o=at.dirname(n);Re.existsSync(o)||(console.log("Creating directory:",o),Re.mkdirSync(o,{recursive:!0}));let s=`
|
|
23
|
+
PORT=4000
|
|
24
24
|
ORACLE_NAME=${r.getValue("projectName")}
|
|
25
25
|
|
|
26
26
|
# Matrix
|
|
27
|
-
MATRIX_BASE_URL=${
|
|
28
|
-
MATRIX_ORACLE_ADMIN_ACCESS_TOKEN=${
|
|
27
|
+
MATRIX_BASE_URL=${e}
|
|
28
|
+
MATRIX_ORACLE_ADMIN_ACCESS_TOKEN=${t.accessToken}
|
|
29
29
|
MATRIX_ORACLE_ADMIN_PASSWORD=${r.getOrThrow("registerUserResult").matrixPassword}
|
|
30
30
|
MATRIX_ORACLE_ADMIN_USER_ID=${r.getOrThrow("registerUserResult").matrixUserId}
|
|
31
31
|
MATRIX_RECOVERY_PHRASE=${r.getOrThrow("registerUserResult").matrixRecoveryPhrase}
|
|
@@ -48,21 +48,21 @@ ORACLE_DID=${r.getOrThrow("registerUserResult").did}
|
|
|
48
48
|
ORACLE_MNEMONIC=${r.getOrThrow("registerUserResult").mnemonic}
|
|
49
49
|
MATRIX_VAULT_PIN=${r.getOrThrow("registerUserResult").pin}
|
|
50
50
|
ENTITY_DID=${r.getOrThrow("entityDid")}
|
|
51
|
-
`;try{
|
|
51
|
+
`;try{Re.writeFileSync(n,s),console.log("\u2705 .env file created successfully at:",n)}catch(a){throw console.error("\u274C Failed to create .env file:",a),a}};var re=class{constructor(e,t){this.config=e;this.wallet=t}name="init";description="Initialize Project";async getProjectInput(){let e=await p.text({message:"What is your project named?",placeholder:"my-ixo-project",validate(o){if(!o)return"Project name is required"}});p.isCancel(e)&&(p.cancel("Operation cancelled."),process.exit(0));let t=String(e),i,n;return t.includes("/")||t.includes("\\")?(i=t,n=L.basename(t)):(n=t,i=L.join(process.cwd(),n)),this.isValidProjectName(n)||(p.note("Invalid project name. Using a valid name instead.","Warning"),n=this.sanitizeProjectName(n),i=L.join(L.dirname(i),n)),{projectPath:i,projectName:n}}isValidProjectName(e){return/^[a-zA-Z][a-zA-Z0-9-_]*$/.test(e)&&e.length>0&&e.length<=50}sanitizeProjectName(e){return e.replace(/[^a-zA-Z0-9-_]/g,"-").replace(/^-+|-+$/g,"").toLowerCase().substring(0,50)}async confirmProjectCreation(e,t){if(te(e)){let o=await p.confirm({message:`Directory "${e}" already exists. Do you want to overwrite it?`,initialValue:!1});return p.isCancel(o)&&(p.cancel("Operation cancelled."),process.exit(0)),o}let n=await p.confirm({message:`Create IXO project "${t}" in "${e}"?`,initialValue:!0});return p.isCancel(n)&&(p.cancel("Operation cancelled."),process.exit(0)),n}async selectRepo(){let e=await p.select({message:"Select a template to clone",options:[{value:"git@github.com:ixoworld/ixo-oracles-boilerplate.git",label:"IXO Oracles (Default)"},{label:"Custom template",value:"custom"}]});if(p.isCancel(e)&&(p.cancel("Operation cancelled."),process.exit(0)),e==="custom"){let t=await p.text({message:"Enter the custom template URL"});return p.isCancel(t)&&(p.cancel("Operation cancelled."),process.exit(0)),t}return e}async cloneRepo(e,t,i=!1){let n=lt(),o=p.spinner();try{if(o.start("Cloning repository..."),i&&te(t)){let{rmSync:l}=await import("fs");l(t,{recursive:!0,force:!0})}await n.clone(e,t);let s=L.join(t,".git");if(te(s)){let{rmSync:l}=await import("fs");l(s,{recursive:!0,force:!0})}await lt(t).init(),o.stop("Repository cloned successfully"),p.log.info("Creating Oracle Entity and Matrix Account"),(await new D(this.wallet,this.config).execute()).success?p.log.info("Oracle Entity and Matrix Account created successfully"):p.log.error("Failed to create Oracle Entity and Matrix Account"),await ct(this.config),p.log.success(`
|
|
52
52
|
\u2705 IXO project created successfully!
|
|
53
53
|
|
|
54
54
|
\u{1F4C1} Location: ${t}
|
|
55
55
|
\u{1F680} Next steps:
|
|
56
|
-
cd ${
|
|
56
|
+
cd ${L.basename(t)}
|
|
57
57
|
pnpm install
|
|
58
58
|
pnpm build
|
|
59
59
|
cd apps/app
|
|
60
|
-
pnpm start:dev`)}catch(s){throw o.stop("Failed to clone repository"),s}}async execute(){try{let{projectPath:e,projectName:t}=await this.getProjectInput();if(!await this.confirmProjectCreation(e,t))return{success:!1,data:"Project creation cancelled"};this.config.addValue("projectPath",e),this.config.addValue("projectName",t);let n=await this.selectRepo();this.config.addValue("repo",n);let o=
|
|
61
|
-
`+" ".repeat(5)+"\u{1F510} "+t),console.log(" ".repeat(5)+"\u{1F4F1} Scan with IXO app"),console.log(" ".repeat(5)+"\u2501".repeat(30)),
|
|
62
|
-
`)}displayQRCode(e){this.displayStyledQRCode(e,"Login with SignX")}async awaitLogin(){return new Promise((e,t)=>{try{this.signXClient.on(
|
|
60
|
+
pnpm start:dev`)}catch(s){throw o.stop("Failed to clone repository"),s}}async execute(){try{let{projectPath:e,projectName:t}=await this.getProjectInput();if(!await this.confirmProjectCreation(e,t))return{success:!1,data:"Project creation cancelled"};this.config.addValue("projectPath",e),this.config.addValue("projectName",t);let n=await this.selectRepo();this.config.addValue("repo",n);let o=te(e);return await this.cloneRepo(n,e,o),{success:!0,data:`Project "${t}" created successfully in "${e}"`}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Unknown error occurred"}}}};import{confirm as nr}from"@clack/prompts";var ie=class{constructor(e){this.wallet=e}name="logout";description="Logout command";async execute(){return await nr({message:"Are you sure you want to logout?",initialValue:!1})?(await this.wallet.clearWallet(),{success:!0,data:"Logged out successfully"}):{success:!1,error:"Logout cancelled"}}};import{toHex as or}from"@cosmjs/encoding";import{createRegistry as sr}from"@ixo/impactxclient-sdk";import{SignX as dt,SIGN_X_LOGIN_ERROR as ar,SIGN_X_LOGIN_SUCCESS as cr,SIGN_X_TRANSACT_ERROR as lr,SIGN_X_TRANSACT_SUCCESS as dr}from"@ixo/signx-sdk";import mr from"qrcode-terminal";var mt={devnet:"https://signx.devnet.ixo.earth",testnet:"https://signx.testnet.ixo.earth",mainnet:"https://signx.ixo.earth"},M=class{signXClient;_loginData;get loginData(){return this._loginData}static loadFromWallet(e){return new dt({endpoint:mt[e.network],sitename:"IXO Oracles CLI",network:e.network})}constructor(e){this.signXClient=new dt({endpoint:mt[e],sitename:"IXO Oracles CLI",network:e})}async login(){let e=await this.signXClient.login({pollingInterval:2e3,matrix:!0});return this._loginData=e,e}displayStyledQRCode(e,t){let i=typeof e=="string"?e:JSON.stringify(e);console.log(`
|
|
61
|
+
`+" ".repeat(5)+"\u{1F510} "+t),console.log(" ".repeat(5)+"\u{1F4F1} Scan with IXO app"),console.log(" ".repeat(5)+"\u2501".repeat(30)),mr.generate(i,{small:!0}),console.log(" ".repeat(5)+`\u23F3 Waiting...
|
|
62
|
+
`)}displayQRCode(e){this.displayStyledQRCode(e,"Login with SignX")}async awaitLogin(){return new Promise((e,t)=>{try{this.signXClient.on(cr,i=>{if(!i.data){t(new Error("Login failed"));return}if(!i.data.matrix){t(new Error("Matrix login failed"));return}e(i.data)}),this.signXClient.on(ar,i=>{console.log("Login error:",i),t(i)})}catch(i){console.error("Error in connecting:",i),t(i)}})}async transact(e,t,i){let n=sr();return this.signXClient.transact({address:t.address,did:t.did,pubkey:t.pubKey,timestamp:new Date().toISOString(),transactions:[{sequence:1,txBodyHex:or(n.encodeTxBody({messages:e,memo:i||""}))}]})}async awaitTransaction(){return new Promise((e,t)=>{try{this.signXClient.on(dr,i=>{e(i.data)}),this.signXClient.on(lr,i=>{t(i)})}catch(i){console.error("Error in connecting:",i),t(i)}})}async pollNextTransaction(){return this.signXClient.pollNextTransaction()}displayTransactionQRCode(e){this.displayStyledQRCode(e,"SIGNX TRANSACTION")}};var ne=class{constructor(e,t){this.wallet=e;this.config=t}name="signx-login";description="Login with SignX wallet";async execute(){try{let e=await I(this.config),t=new M(e),i=await t.login();t.displayQRCode(i);let n=await t.awaitLogin();return this.wallet.setWallet(n),this.wallet.setSignXClient(t),{success:!0,data:{message:"Successfully logged in with SignX!",wallet:{address:n.address,did:n.did,name:n.name}}}}catch(e){return{success:!1,error:e instanceof Error?`SignX login failed: ${e.message}`:"Unknown error"}}}};import*as x from"@clack/prompts";var oe=class{constructor(e,t){this.wallet=e;this.config=t;this.createEntity=new N(this.wallet,this.config)}name="update-entity";description="Update an entity (add controllers, etc.)";createEntity;async execute(){this.config.getValue("network")||await I(this.config);let t=await x.group({entityDid:()=>x.text({message:"What is the DID of the entity you want to update?",initialValue:this.config.getValue("entityDid")?.toString()??"",validate(i){return ge(i)}}),action:()=>x.select({message:"What would you like to do?",options:[{value:"add-controller",label:"Add Controller",hint:"Add a new controller DID to the entity"}],initialValue:"add-controller"}),controllerDid:async({results:i})=>{if(i.action!=="add-controller")throw new Error("Unknown action");let n=await x.text({message:"What is the DID of the controller you want to add?",validate(o){return ge(o)}});return x.isCancel(n)&&(x.cancel("Operation cancelled."),process.exit(0)),n}},{onCancel:()=>{x.cancel("Operation cancelled."),process.exit(0)}});try{if(t.action==="add-controller"&&typeof t.controllerDid=="string"){let i=t.controllerDid,n=t.entityDid;return x.log.info(`Adding controller ${i} to entity ${n}`),await this.createEntity.addControllerToEntity(n,i),x.log.success(`Controller ${i} successfully added to entity ${n}`),{success:!0,data:`Controller ${i} added to entity ${n}`}}return{success:!1,error:"Unknown action"}}catch(i){return{success:!1,error:i instanceof Error?i.message:String(i)}}}};var Se=class extends Error{constructor(t,i="CLI_ERROR",n){super(t);this.code=i;this.suggestions=n;this.name="CLIError"}};function se(r){r instanceof Se&&(console.error(`
|
|
63
63
|
\u274C ${r.name}: ${r.message}`),r.suggestions?.length&&(console.error(`
|
|
64
64
|
Suggestions:`),r.suggestions.forEach(e=>console.error(` \u2022 ${e}`))),process.exit(1)),r instanceof Error&&(console.error(`
|
|
65
65
|
\u274C Unexpected Error: ${r.message}`),r.stack&&(console.error(`
|
|
66
66
|
Stack trace:`),console.error(r.stack)),process.exit(1)),console.error(`
|
|
67
|
-
\u274C Unknown error occurred`,r),process.exit(1)}var
|
|
67
|
+
\u274C Unknown error occurred`,r),process.exit(1)}var ae=class r{config={};static instance;constructor(){}static getInstance(){return r.instance||(r.instance=new r),r.instance}addValue(e,t){this.config[e]=t}getValue(e){return this.config[e]}getOrThrow(e){let t=this.getValue(e);if(!t)throw new Error(`Value ${e} is not set`);return t}getConfig(){return this.config}deleteValue(e){delete this.config[e]}};import{log as b}from"@clack/prompts";import{cosmos as pt}from"@ixo/impactxclient-sdk";import{existsSync as Ee,readFileSync as pr,writeFileSync as gr}from"fs";import{unlink as ur}from"fs/promises";import fr from"os";import hr from"path";var U=hr.join(fr.homedir(),".wallet.json"),ce=class{wallet;signXClient;config;constructor(e){this.config=e,this.loadWallet()}setSignXClient(e){this.signXClient=e}loadWallet(){if(Ee(U))try{let e=pr(U,"utf8");if(this.wallet=JSON.parse(e),!this.wallet.matrix?.userId||!this.wallet.matrix.userId.includes(":")){b.warning("Wallet is missing valid Matrix credentials. Please re-authenticate via SignX."),this.wallet=void 0;return}let t=this.wallet.network;if(!t){let i=this.wallet.matrix.userId.split(":")[1];if(t={"devmx.ixo.earth":"devnet","testmx.ixo.earth":"testnet","mx.ixo.earth":"mainnet"}[i],!t)throw new Error(`Cannot determine network from matrix domain: ${i}`);this.wallet.network=t}this.config.addValue("network",t),this.setSignXClient(new M(t)),b.success(`Welcome back, ${this.wallet.name}!`),b.info(`Network: ${t}`)}catch(e){b.warning(`Failed to load wallet file: ${e instanceof Error?e.message:String(e)}`),this.wallet=void 0}else b.warning("No wallet file found")}setWallet(e){try{this.wallet=e;let t=JSON.stringify(e,null,2);gr(U,t,"utf8"),b.success(`Wallet saved successfully to: ${U}`)}catch(t){throw b.error(`Failed to save wallet: ${t instanceof Error?t.message:String(t)}`),new Error("Failed to save wallet file")}}checkWalletExists(){return Ee(U)&&this.wallet!==void 0}async clearWallet(){this.wallet=void 0;try{Ee(U)&&(await ur(U),b.success("Wallet file deleted successfully"))}catch(e){b.error(`Failed to delete wallet file: ${e instanceof Error?e.message:String(e)}`)}}get did(){return this.wallet?.did}get address(){return this.wallet?.address}get name(){return this.wallet?.name}get pubKey(){return this.wallet?.pubKey}get algo(){return this.wallet?.algo}get matrix(){return this.wallet?.matrix}get matrixHomeServer(){let e=this.wallet?.matrix?.userId;return!e||!e.includes(":")?void 0:`https://${e.split(":")[1]}`}reloadWallet(){this.loadWallet()}async sendTokens(e,t){if(!this.address||!this.signXClient||!this.wallet)throw new Error("Wallet not loaded");let i={typeUrl:"/cosmos.bank.v1beta1.MsgSend",value:pt.bank.v1beta1.MsgSend.fromPartial({fromAddress:this.address,toAddress:e,amount:[pt.base.v1beta1.Coin.fromPartial({amount:t.toString(),denom:"uixo"})]})},n=await this.signXClient?.transact([i],this.wallet);return this.signXClient?.displayTransactionQRCode(JSON.stringify(n)),await this.signXClient?.pollNextTransaction(),await this.signXClient?.awaitTransaction()}};var Ae=class{registry;config;wallet;constructor(){this.registry=new B,this.config=ae.getInstance(),this.wallet=new ce(this.config)}registerCommands(){this.registry.register(new re(this.config,this.wallet)),this.registry.register(new D(this.wallet,this.config)),this.registry.register(new oe(this.wallet,this.config)),this.registry.register(new ee(this.wallet,this.config)),this.registry.register(new ie(this.wallet)),this.registry.register(new j(this.registry))}async showHelp(){this.wallet.setWallet({address:"0x0000000000000000000000000000000000000000",algo:"secp",did:"did:ixo:entity:1a76366f16570483cea72b111b27fd78",network:"devnet",name:"My oracle",pubKey:"0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",ledgered:!1,matrix:{accessToken:"",userId:"0x0000000000000000000000000000000000000000",address:"",roomId:""}}),this.registerCommands();let t=await new j(this.registry).execute();t.success&&t.data&&console.log(t.data)}async handleAuthentication(){if(!this.wallet.checkWalletExists()){let e=await ut({message:"Login with SignX",options:[{value:"login",label:"Login"},{value:"exit",label:"Exit"}]});switch(gt(e)&&(be("Operation cancelled."),O.exit(0)),String(e)){case"login":{(await new ne(this.wallet,this.config).execute()).success&&K.success("Login successful");return}case"exit":{be("Operation cancelled."),O.exit(0);return}default:throw new Error(`Unknown command: ${e}`)}}}async executeCommand(e){let t=this.registry.get(e);if(!t)throw new Error(`Unknown command: ${e}`);let i=xr();i.start(`Executing ${t.name}...`);let n=await t.execute();i.stop(`${t.name} completed`),n.success?(K.success(`${t.name} completed successfully!`),n.data&&K.info(JSON.stringify(n.data,null,2))):K.error(`${t.name} failed: ${n.error}`)}async interactiveMode(){wr("IXO CLI"),K.warn("Keep your IXO Mobile App open while running the CLI; So u do not interrupt the signX session"),await this.handleAuthentication(),this.registerCommands();let e=await ut({message:`Welcome ${this.wallet.name}, what would you like to do?`,options:[...this.registry.getCommandOptions()],initialValue:"init"});gt(e)&&(be("Operation cancelled."),O.exit(0)),await this.executeCommand(String(e))}async argumentMode(e){let t=e[0];if(!t){await this.interactiveMode();return}if(t==="--init"){await this.handleAuthentication(),this.registerCommands(),await this.executeCommand("init");return}if(t==="--help"||t==="-h"){await this.showHelp();return}await this.handleAuthentication(),this.registerCommands(),await this.executeCommand(t)}async run(e){try{let t=e.slice(2);t.length===0?await this.interactiveMode():await this.argumentMode(t)}catch(t){se(t)}yr("Thanks for using IXO CLI!"),O.exit(0)}};O.on("uncaughtException",se);O.on("unhandledRejection",se);var vr=new Ae;vr.run(O.argv);
|
|
68
68
|
//# sourceMappingURL=cli.js.map
|