@etherna/docker 1.7.1 → 1.7.2

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/index.cjs CHANGED
@@ -2,9 +2,9 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.
2
2
  `:`
3
3
  `)+n,i=r+1,r=e.indexOf(`
4
4
  `,i)}while(r!==-1);return a+=e.slice(i),a}const{stdout:le,stderr:ue}=oe,de=Symbol(`GENERATOR`),T=Symbol(`STYLER`),E=Symbol(`IS_EMPTY`),fe=[`ansi`,`ansi`,`ansi256`,`ansi16m`],D=Object.create(null),pe=(e,t={})=>{if(t.level&&!(Number.isInteger(t.level)&&t.level>=0&&t.level<=3))throw Error("The `level` option should be an integer from 0 to 3");let n=le?le.level:0;e.level=t.level===void 0?n:t.level},me=e=>{let t=(...e)=>e.join(` `);return pe(t,e),Object.setPrototypeOf(t,O.prototype),t};function O(e){return me(e)}Object.setPrototypeOf(O.prototype,Function.prototype);for(let[e,t]of Object.entries(x))D[e]={get(){let n=k(this,_e(t.open,t.close,this[T]),this[E]);return Object.defineProperty(this,e,{value:n}),n}};D.visible={get(){let e=k(this,this[T],!0);return Object.defineProperty(this,"visible",{value:e}),e}};const he=(e,t,n,...r)=>e===`rgb`?t===`ansi16m`?x[n].ansi16m(...r):t===`ansi256`?x[n].ansi256(x.rgbToAnsi256(...r)):x[n].ansi(x.rgbToAnsi(...r)):e===`hex`?he(`rgb`,t,n,...x.hexToRgb(...r)):x[n][e](...r);for(let e of[`rgb`,`hex`,`ansi256`]){D[e]={get(){let{level:t}=this;return function(...n){let r=_e(he(e,fe[t],`color`,...n),x.color.close,this[T]);return k(this,r,this[E])}}};let t=`bg`+e[0].toUpperCase()+e.slice(1);D[t]={get(){let{level:t}=this;return function(...n){let r=_e(he(e,fe[t],`bgColor`,...n),x.bgColor.close,this[T]);return k(this,r,this[E])}}}}const ge=Object.defineProperties(()=>{},{...D,level:{enumerable:!0,get(){return this[de].level},set(e){this[de].level=e}}}),_e=(e,t,n)=>{let r,i;return n===void 0?(r=e,i=t):(r=n.openAll+e,i=t+n.closeAll),{open:e,close:t,openAll:r,closeAll:i,parent:n}},k=(e,t,n)=>{let r=(...e)=>ve(r,e.length===1?``+e[0]:e.join(` `));return Object.setPrototypeOf(r,ge),r[de]=e,r[T]=t,r[E]=n,r},ve=(e,t)=>{if(e.level<=0||!t)return e[E]?``:t;let n=e[T];if(n===void 0)return t;let{openAll:r,closeAll:i}=n;if(t.includes(`\x1B`))for(;n!==void 0;)t=se(t,n.close,n.open),n=n.parent;let a=t.indexOf(`
5
- `);return a!==-1&&(t=ce(t,i,r,a)),r+t+i};Object.defineProperties(O.prototype,D);const A=O();O({level:ue?ue.level:0});const ye={"bee-blockchain":{code:`bee-blockchain`,service:`bee`,dependencies:[],onFailure:`stop`},"bee-nodes":{code:`bee-nodes`,service:`bee`,dependencies:[`bee-blockchain`],onFailure:`stop`},shkeeper:{code:`shkeeper`,service:`shkeeper`,dependencies:[],onFailure:`stop`},mongo:{code:`mongo`,service:`mongo`,dependencies:[],onFailure:`stop`},sso:{code:`sso`,service:`sso`,dependencies:[`mongo`],onFailure:`stop`},index:{code:`index`,service:`index`,dependencies:[`mongo`],onFailure:`stop`},beehive:{code:`beehive`,service:`beehive`,dependencies:[`mongo`],onFailure:`stop`},gateway:{code:`gateway`,service:`gateway`,dependencies:[`mongo`,`sso`],onFailure:`stop`},credit:{code:`credit`,service:`credit`,dependencies:[`mongo`,`sso`,`shkeeper`],onFailure:`stop`},elastic:{code:`elastic`,service:`elastic`,dependencies:[],onFailure:`stop`}},be=[`blockchain`,`bee`,`beehive`,`credit`,`elastic`,`gateway`,`index`,`mongo`,`shkeeper`,`sso`];be.filter(e=>e!==`shkeeper`);var j=class extends Error{constructor(e){super(e),this.name=`DependencyTreeValidationError`}};function xe(e){return e instanceof Error?e:Error(String(e))}function Se(e,t){let n=new Set;for(let r=0;r<t.length;r++){let i=t[r];if(i.status!==`started`&&i.status!==`skipped`)if(i.status===`failed`)n.add(i.code);else{let t=i.blockedBy;if(t&&t.length>0)for(let e of t)n.add(e);else n.add(e[r])}}return[...n]}function Ce(e){let t=new Set;for(let n of e){if(t.has(n.code))throw new j(`Duplicate service code "${String(n.code)}".`);t.add(n.code)}for(let n of e){let e=n.dependencies??[];for(let r of e){if(r===n.code)throw new j(`Service "${String(n.code)}" cannot depend on itself.`);if(!t.has(r))throw new j(`Service "${String(n.code)}" depends on unknown service "${String(r)}".`)}}let n=new Set,r=new Set,i=new Map(e.map(e=>[e.code,e]));function a(e){if(r.has(e))return;if(n.has(e))throw new j(`Dependency cycle detected involving service "${String(e)}".`);n.add(e);let t=i.get(e);if(t){for(let e of t.dependencies??[])a(e);n.delete(e),r.add(e)}}for(let t of e)a(t.code)}function we(e,t){Ce(e);let n=new Map(e.map(e=>[e.code,e])),r=new Map;function i(e){let a=r.get(e);if(a)return a;let o=n.get(e);if(!o)throw new j(`Unknown service code "${String(e)}".`);let s=(async()=>{let n=o.dependencies??[],r=await Promise.all(n.map(e=>i(e)));if(r.some(e=>e.status!==`started`&&e.status!==`skipped`))return{code:e,status:`blocked`,blockedBy:Se(n,r)};if(o.enabled===!1)return{code:e,status:`skipped`};let a=o.onFailure??`stop`;try{if(o.beforeStartup&&await o.beforeStartup(),!await o.startupCallback()){let n=Error(`Service startup returned false`);return a===`log`&&t.logError(String(e),n.message),{code:e,status:`failed`,error:n}}return{code:e,status:`started`}}catch(n){let r=xe(n);return a===`log`&&t.logError(String(e),r.message),{code:e,status:`failed`,error:r}}})();return r.set(e,s),s}return{start:async()=>{let t=await Promise.all(e.map(e=>i(e.code)));return{shouldStop:t.some(e=>e.status===`failed`&&(n.get(e.code)?.onFailure??`stop`)===`stop`),services:t}}}}const Te=`/usr/local/share/ca-certificates`,Ee={"etherna-sso":`sso`,"etherna-index":`index`,"etherna-credit":`credit`,"etherna-gateway":`gateway`,"etherna-beehive":`beehive`};function M(e){return`http://${e}.localhost:1355`}function De(e){return e.trim().replace(/\/+$/,``)}function Oe(){return[`proxy`,`start`,`-p`,`1355`,`--no-tls`]}function ke(){return[`proxy`,`stop`]}function Ae(e,t,n=!1){let r=[`alias`,e,String(t)];return n&&r.push(`--force`),r}function je(e){return[`alias`,`--remove`,e]}async function N(e){return new Promise((t,n)=>{let r=(0,d.spawn)(`portless`,e,{stdio:[`ignore`,`pipe`,`pipe`]}),i=``,a=``;r.stdout?.on(`data`,e=>{i+=String(e)}),r.stderr?.on(`data`,e=>{a+=String(e)}),r.on(`error`,n),r.on(`exit`,e=>{t({code:e??1,stderr:a,stdout:i})})})}async function Me(){try{return(await N([`--version`])).code===0}catch{return!1}}async function Ne(){let e=await N(Oe());if(e.code===0)return{startedByUs:!0};let t=`${e.stderr}\n${e.stdout}`;if(/already|in use|running|listen/i.test(t))return{startedByUs:!1};throw Error(`portless proxy start failed (exit ${e.code}): ${t.trim()||`(no output)`}`)}function Pe(e){if(typeof e==`number`&&Number.isFinite(e))return e;let t=String(e).trim();if(t===``)throw Error(`Port value is empty`);let n=Number.parseInt(t,10);if(!Number.isFinite(n))throw Error(`Invalid port: ${String(e)}`);return n}async function Fe(e,t){let n=Pe(t),r=await N(Ae(e,n,!0));if(r.code!==0){let t=`${r.stderr}\n${r.stdout}`;throw Error(`portless alias ${e} ${n} failed: ${t.trim()}`)}}async function Ie(e){for(let t of e)await N(je(t))}async function Le(){await N(ke())}const Re=1633,ze=1634,P=9545,Be=4020,Ve=`0xCEeE442a149784faa65C35e328CCd64d874F9a02`,He=[`POSTAGE_PRICE`],Ue=32650,F=`shkeeper`;function We(e){let{mode:t,portless:n,appPort:r,portlessAppPublicUrl:i}=e,a=t===`http`?32610:42610,o=t===`http`?32620:42620,s=t===`http`?32630:42630,c=t===`http`?32640:42640,l=`mongodb://localhost:27017`,u=L(t,a),d=L(t,o),f=L(t,s),p=L(t,c),m=L(t,12610),h=`http://localhost:${Re}`,g=n&&i?De(i):Ke(t,r,n,`app`),_={ASPNETCORE_ENVIRONMENT:`Development`,"Elastic:Urls:0":`http://localhost:9200`,...t===`https`?{ASPNETCORE_Kestrel__Certificates__Default__Path:`${Te}/etherna.pfx`,ASPNETCORE_Kestrel__Certificates__Default__Password:``}:{}};return{app:{port:r},shkeeper:{port:Ue},"shkeeper-core":{DEV_MODE:`1`,BTC_WALLET:`disabled`,LTC_WALLET:`disabled`,DOGE_WALLET:`disabled`,ETH_WALLET:`enabled`,ETH_USERNAME:`shkeeper`,ETH_PASSWORD:`shkeeper`,ETHEREUM_API_SERVER_HOST:`localhost`,ETHEREUM_SERVER_PORT:`6000`,SHKEEPER_BACKEND_KEY:F,SHKEEPER_BTC_BACKEND_KEY:F},"ethereum-shkeeper":{FULLNODE_URL:`http://localhost:${P}`,FULLNODE_TIMEOUT:`60`,CURRENT_ETH_NETWORK:`custom`,WEB3_ENABLE_POA_MIDDLEWARE:`1`,BLOCK_SCANNER_MAX_CATCHUP_BLOCKS:`64`,ETH_USERNAME:`shkeeper`,ETH_PASSWORD:`shkeeper`,SHKEEPER_BACKEND_KEY:F,SHKEEPER_HOST:`localhost:${Ue}`,REDIS_HOST:`localhost`,SQLALCHEMY_DATABASE_URI:`mariadb+pymysql://root:shkeeper@localhost:3306/ethereum-shkeeper?charset=utf8mb4`,LAST_BLOCK_LOCKED:`FALSE`},elastic:{"discovery.type":`single-node`,"xpack.security.enabled":`false`,ES_JAVA_OPTS:`-Xms512m -Xmx512m`},"etherna-mongodb":{},"etherna-sso":{..._,ASPNETCORE_URLS:u,"IdServer:SsoServer:BaseUrl":u,"IdServer:SsoServer:AllowUnsafeConnection":`true`,"IdServer:Clients:EthernaCredit:BaseUrl":f,"IdServer:Clients:EthernaGateway:BaseUrls:0":p,"IdServer:Clients:EthernaIndex:BaseUrl":d,"IdServer:Clients:EthernaDapp:BaseUrl":g,"DbSeed:Clients:0:RedirectUris:0":`${g}/callback`,"DbSeed:Clients:0:PostLogoutRedirectUris:0":g,"DbSeed:Clients:0:AllowedCorsOrigins:0":g,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSSODataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaSSOHangfireDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`,"ConnectionStrings:SSOServerDb":`${l}/ethernaSSODev`},"etherna-index":{..._,ASPNETCORE_URLS:d,"Swarm:GatewayUrl":p,"SsoServer:BaseUrl":u,"SsoServer:AllowUnsafeConnection":`true`,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSharedDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaIndexHangfireDev`,"ConnectionStrings:IndexDb":`${l}/ethernaIndexDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`},"etherna-credit":{..._,ASPNETCORE_URLS:f,"SsoServer:BaseUrl":u,"SsoServer:AllowUnsafeConnection":`true`,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSharedDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaCreditHangfireDev`,"ConnectionStrings:CreditDb":`${l}/ethernaCreditDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`,DisableHttpsRedirection:`true`,"Payments:ShKeeper:Url":`http://localhost:${Ue}`,"Payments:ShKeeper:ApiKey":F,"Payments:ShKeeper:CustomCallbackBaseUrl":f},"etherna-gateway":{..._,ASPNETCORE_URLS:p,"ForwardedHeaders:KnownNetworks:0":`0.0.0.0/0`,"SsoServer:BaseUrl":u,"SsoServer:Clients:Credit:BaseUrl":f,"SsoServer:Clients:Credit:Secret":`ethernaGatewayCreditClientSecret`,"SsoServer:Clients:Webapp:Secret":`ethernaGatewayWebappClientSecret`,"SsoServer:AllowUnsafeConnection":`true`,"Bee:CachedUrl":m,"Bee:DirectUrl":m,"Features:GarbageCollectPins":`false`,ForwardedAllowedHosts:`*`,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSharedDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaGatewayHangfireDev`,"ConnectionStrings:GatewayDb":`${l}/ethernaGatewayDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`},"etherna-beehive":{..._,ASPNETCORE_URLS:m,"SeedDb:BeeNodes:0:Hostname":`localhost`,"ConnectionStrings:DataProtectionDb":`${l}/beehiveDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/beehiveHangfireDev`,"ConnectionStrings:BeehiveDb":`${l}/beehiveDev`,"SeedDb:BeeNodes:0:ConnectionString":h,"SeedDb:BeeNodes:0:EnableBatchCreation":`true`},"etherna-blockchain":{BLOCKCHAIN_PORT:P,NETWORK_ID:Be},"etherna-bee":{POSTAGE_PRICE:`24000`,BEE_WARMUP_TIME:`10s`,BEE_DEBUG_API_ENABLE:`true`,BEE_VERBOSITY:`4`,BEE_SWAP_ENABLE:`true`,BEE_MAINNET:`false`,BEE_SWAP_ENDPOINT:`http://etherna-blockchain:${P}`,BEE_BLOCKCHAIN_RPC_ENDPOINT:`http://etherna-blockchain:${P}`,BEE_PASSWORD:`password`,BEE_SWAP_FACTORY_ADDRESS:`0xCfEB869F69431e42cdB54A4F4f105C19C080A601`,BEE_POSTAGE_STAMP_ADDRESS:`0x254dffcd3277C0b1660F6d42EFbB754edaBAbC2B`,BEE_PRICE_ORACLE_ADDRESS:`0x5b1869D9A4C187F2EAa108f3062412ecf0526b24`,BEE_REDISTRIBUTION_ADDRESS:`0x9561C133DD8580860B6b7E504bC5Aa500f0f06a7`,BEE_STAKING_ADDRESS:`0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb`,BEE_POSTAGE_STAMP_START_BLOCK:`1`,BEE_NETWORK_ID:Be,BEE_FULL_NODE:`true`,BEE_PORT:Re,BEE_P2P_PORT:ze,BEE_API_ADDR:`0.0.0.0:${Re}`,BEE_P2P_ADDR:`0.0.0.0:${ze}`,BEE_CORS_ALLOWED_ORIGINS:`*`,BEE_ALLOW_PRIVATE_CIDRS:`true`,BEE_BOOTNODE_MODE:``,BEE_BOOTNODE:``}}}function Ge(e){return{mode:e,portless:!1,appPort:e===`http`?5173:5371}}function I(e){let t=e.split(`;`)[0]?.trim()??``;try{let e=new URL(t);return e.port?e.port:e.protocol===`https:`?`443`:`80`}catch{return t.split(`:`)[2]??`80`}}function L(e,t){return`${e}://localhost:${t}`}function Ke(e,t,n,r){return n?M(r):L(e,t)}const R=(e,t)=>We(t)[e]??null;function qe(e){let t=new Set(He);return Object.fromEntries(Object.entries(e).filter(([e])=>!t.has(e)))}const Je=`ETHERNA_DETACHED`;function Ye(e){if(typeof e.detached==`boolean`)return e.detached;let t=process.env[Je]?.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}const Xe=[`elastic`,`mongo`,`bee`,`sso`,`index`,`gateway`,`credit`,`beehive`,`shkeeper`];function Ze(e){return typeof e==`object`&&e?e.enabled!==!1:e!==!1}function Qe(e){return e===!0?!0:typeof e==`object`&&e?e.enabled!==!1:!1}function $e(e){let t={};for(let n of Xe)t[n]=n===`shkeeper`?Qe(e[n]):Ze(e[n]);t.blockchain=t.bee;let n={enabled:t,detached:Ye(e),portless:e.portless??!1,mode:e.mode??`http`,installSignalHandlers:e.installSignalHandlers??!0};return e.appPort!==void 0&&(n.appPort=e.appPort),n}function et(e){return new Promise(t=>setTimeout(t,e))}async function tt(e){let t=e?.containerName??`shkeeper`,n=e?.sqlitePath??`/shkeeper.io/instance/shkeeper.sqlite`,r=e?.maxAttempts??120,i=e?.intervalMs??1e3;for(let e=0;e<r;e++){let a=await nt(t,n,`SELECT apikey FROM wallet WHERE apikey IS NOT NULL AND TRIM(COALESCE(apikey, '')) != '' LIMIT 1`);if(a)return a;e<r-1&&await et(i)}return null}function nt(e,t,n){return new Promise(r=>{let i=(0,d.spawn)(`docker`,[`exec`,e,`sqlite3`,t,n]),a=``;i.stdout?.on(`data`,e=>{a+=typeof e==`string`?e:e.toString(`utf8`)}),i.on(`error`,()=>{r(null)}),i.on(`close`,e=>{if(e!==0){r(null);return}let t=a.trim();r(t.length>0?t:null)})})}function rt(e){let t=typeof process<`u`?process.env?.[e]:void 0;if(t!==void 0)return t;try{let t={}.env?.[e];return typeof t==`string`?t:void 0}catch{return}}function z(...e){return p.default.resolve(`node_modules/.vite`,...e)}function it(...e){let t=z(...e);return process.platform===`win32`?t.replace(/\\/g,`/`):t}function B(e,t,n,r){if(r?.portlessUrl){let i=`${r.portlessUrl.replace(/\/$/,``)}/`,a=`${t}://localhost:${n}/`;console.log(` ${A.green(`➜`)} ${A.bold(e)}: ${A.cyan(i)} ${A.gray(`(${a})`)}`);return}let i=`${t}://localhost:${A.bold.cyanBright(n)}/`;console.log(` ${A.green(`➜`)} ${A.bold(e)}: ${A.cyan(i)}`)}function at(e){console.log(` ${A.gray(`➜`)} ${A.bold(e)}: ${A.yellow(`Downloading image...`)}`)}function V(e,t){console.log(` ${A.red(`x`)} ${A.bold(e)}: ${A.red(t)}`)}async function ot(e,t,n){let r=(0,d.spawn)(e,t,n);return new Promise((e,t)=>{r.on(`error`,e=>{t(e)}),r.on(`exit`,()=>{e()})})}async function st(e){let t=await fetch(`${e}/addresses`);if(!t.ok)throw Error(`Failed to fetch addresses from ${e}: ${t.statusText}`);let n=await t.json(),r=Array.isArray(n.underlay)?n.underlay:[];if(r.length===0)return await new Promise(e=>setTimeout(e,500)),st(e);let i=r.find(e=>!e.includes(`127.0.0.1`));if(!i)throw Error(`No valid underlay address found in response from ${e}`);return i}const ct=`etherna-`;function H(e){return e.startsWith(ct)?e:`${ct}${e}`}const lt=`https://docs.docker.com/get-docker/`,ut=3e4;function U(e,t){(0,d.spawn)(e,t,{detached:!0,stdio:`ignore`}).unref()}function dt(){return new Promise(e=>{let t=(0,d.spawn)(`docker`,[`info`],{stdio:`ignore`});t.on(`error`,()=>e(!1)),t.on(`exit`,t=>e(t===0))})}function ft(){return new Promise(e=>{let t=(0,d.spawn)(`docker`,[`--version`],{stdio:`ignore`});t.on(`error`,()=>e(!1)),t.on(`exit`,t=>e(t===0))})}function pt(){let{platform:e}=process;if(e===`darwin`){U(`open`,[`-a`,`Docker`]);return}if(e===`win32`){let e=`C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe`;if(f.default.existsSync(e)){U(e,[]);return}U(`cmd`,[`/c`,`start`,``,`Docker Desktop`]);return}e===`linux`&&U(`systemctl`,[`--user`,`start`,`docker-desktop`])}function mt(e){return new Promise(t=>setTimeout(t,e))}async function ht(){if(await ft()||(console.error(` ${A.red(`x`)} ${A.bold(`docker`)}: ${A.red(`Docker is not installed or not on your PATH.`)}`),console.error(` Install Docker and try again: ${A.cyan.underline(lt)}`),process.exit(1)),await dt())return;console.log(` ${A.yellow(`➜`)} ${A.bold(`docker`)}: ${A.yellow(`Docker daemon is not running. Starting it…`)}`),pt();let e=Date.now()+ut;for(;Date.now()<e;)if(await mt(2e3),await dt()){console.log(` ${A.green(`➜`)} ${A.bold(`docker`)}: ${A.green(`Docker is ready.`)}`);return}console.error(` ${A.red(`x`)} ${A.bold(`docker`)}: ${A.red(`Docker did not become ready within ${ut/1e3}s. Start Docker manually and run the dev server again.`)}`),console.error(` Install or troubleshoot: ${A.cyan.underline(lt)}`),process.exit(1)}async function W({containerName:e,imageName:t,args:n=[],cmd:r=[],detached:i=!1}){let a=H(e);if(!i)await gt(a)&&await _t(a);else{if(await vt(a))return null;await gt(a)&&await yt(a)}let o=[`run`,`--rm`,`--name`,a,...n,t,...r],s=i?(0,d.spawn)(`docker`,[...o],{detached:!0,stdio:[`ignore`,`pipe`,`pipe`]}):(0,d.spawn)(`docker`,[...o]);return s.stdout?.on(`data`,e=>{let t=String(e);/Pulling from/gm.test(t)&&at(a),/Error response from daemon/gm.test(t)&&V(a,t)}),i&&s.unref(),s}async function gt(e){let t=(0,d.spawn)(`docker`,[`ps`,`-a`,`--filter`,`name=${H(e)}`]);return(await new Promise(e=>{let n=``;t.stdout?.on(`data`,e=>{n+=String(e)}),t.on(`close`,()=>{e(n)})})).split(`
6
- `).length>1}async function _t(e){let t=(0,d.spawn)(`docker`,[`stop`,H(e)]);await new Promise(e=>{t.on(`close`,()=>{e()})})}async function vt(e){return new Promise(t=>{let n=(0,d.spawn)(`docker`,[`inspect`,`-f`,`{{.State.Running}}`,H(e)],{stdio:[`ignore`,`pipe`,`ignore`]}),r=``;n.stdout?.on(`data`,e=>{r+=String(e)}),n.on(`error`,()=>t(!1)),n.on(`close`,e=>{if(e!==0){t(!1);return}t(r.trim().toLowerCase()===`true`)})})}async function yt(e){await new Promise(t=>{let n=(0,d.spawn)(`docker`,[`rm`,`-f`,H(e)],{stdio:`ignore`});n.on(`error`,()=>t()),n.on(`close`,()=>t())})}async function G(e){let t=(0,d.spawn)(`docker`,[`volume`,`create`,e]);await new Promise(e=>{t.on(`close`,()=>{e()})})}async function bt(e){let t=(0,d.spawn)(`docker`,[`network`,`create`,e]);await new Promise(e=>{t.on(`close`,()=>{e()})})}const xt={blockchain:[`etherna-blockchain`],bee:[`etherna-blockchain`,`etherna-bee`,`etherna-bee_worker_1`],beehive:[`etherna-beehive`],credit:[`etherna-credit`],elastic:[`etherna-elastic`],gateway:[`etherna-gateway`],index:[`etherna-index`],mongo:[`etherna-mongodb`],shkeeper:[`ethereum-shkeeper-mariadb`,`ethereum-shkeeper-redis`,`ethereum-shkeeper`,`ethereum-tasks`,`shkeeper`],sso:[`etherna-sso`]};function St(e){return xt[e]}async function Ct(e){let t=[...new Set(e.flatMap(St))];await Promise.all(t.map(e=>_t(e)))}async function wt(e){await Ct(Object.keys(e).filter(t=>e[t]))}async function Tt(e){await ot(`docker`,[`exec`,e,`update-ca-certificates`]).catch(t=>{console.error(A.red(`‼️ Error trusting certificate in container '${e}': ${t.message}`))})}async function K(e,t,n,r){let i,a=new Promise(e=>{i=e}),o,{mode:s}=e.serviceCtx,c={...R(t,e.serviceCtx)??{},...r},l=c.ASPNETCORE_URLS.split(`;`)[0]?.split(`:`)[2]??`80`,u=Ee[t],d=e.serviceCtx.portless&&u?M(u):void 0,f=await W({containerName:t,imageName:n,args:[...Object.entries(c).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),...s===`https`?[`--mount`,`type=bind,source=${it(`.ssl`)},target=${Te}/`]:[],`--network`,`host`],detached:e.detached});if(!f)return B(t,s,l,{portlessUrl:d}),null;e.pushSpawn(f);let p=async e=>{o=void 0;let n=String(e);/Now listening on: https?:\/\/(localhost|\[::\]):\d+/gm.test(n)&&(s===`https`&&await Tt(t),B(t,s,l,{portlessUrl:d}),i?.());let r=[/Current db does not support change stream/gm,/is only supported on replica sets./gm,/Failed to process the job/gm],a=[/\[(ERR|FTL)\]/gm,/"LogLevel"\s*:\s*"(Error|Critical)"/gm,/\b(fail|crit):/gm,/<(2|3)>/gm].some(e=>e.test(n)),c=/\[(INF|WRN|DBG|VRB)\]/gm.test(n);a&&!c&&/Exception:.+/gm.test(n)&&!r.some(e=>e.test(n))?(V(t,n),i?.()):o=n};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),i?.()}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(t,o||`Container closed with code ${e}`),i?.(),f.kill()}),await a,f}function Et(e){return new Promise(t=>setTimeout(t,e))}async function q(e,t,n){let r=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({jsonrpc:`2.0`,id:1,method:t,params:n})});if(!r.ok)throw Error(`RPC ${t} failed: ${r.status} ${r.statusText}`);let i=await r.json();if(i.error?.message)throw Error(`RPC ${t} error: ${i.error.message}`);return i.result}async function J(e,t){return(await q(e,`web3_sha3`,[`0x`+Buffer.from(t,`utf-8`).toString(`hex`)])).slice(0,10)}function Dt(e){if(e<0n)throw Error(`Cannot encode negative uint param: ${e}`);return e.toString(16).padStart(64,`0`)}function Ot(e){let t=e.toLowerCase().startsWith(`0x`)?e.slice(2):e;if(t.length!==40)throw Error(`Invalid address (expected 20 bytes / 40 hex chars): ${e}`);return t.toLowerCase().padStart(64,`0`)}function kt(e){let t=e.startsWith(`0x`)?e.slice(2):e;if(t.length!==64)throw Error(`Invalid bytes32 (expected 32 bytes / 64 hex chars): ${e}`);return t.toLowerCase()}function Y(e){let t=e.startsWith(`0x`)?e.slice(2):e;return t.length===0?0n:BigInt(`0x`+t)}async function At(e,t,n,r=500){let i=Date.now()+n;for(;Date.now()<i;){let n=await q(e,`eth_getTransactionReceipt`,[t]);if(n?.status)return{status:n.status,blockNumber:n.blockNumber};await Et(r)}throw Error(`Transaction ${t} was not mined within ${n}ms`)}async function jt(e,t){return await q(e,`eth_getCode`,[t,`latest`]).then(e=>e??`0x`)}async function Mt(e){let t=await q(e,`eth_blockNumber`,[]);return Number.parseInt(t??`0x0`,16)}function Nt(e){return e!==`0x`&&e.length>2}async function Pt(e,t,n=`pending`){return Y(await q(e,`eth_getTransactionCount`,[t,n]))}async function Ft(e){return Y(await q(e,`eth_gasPrice`,[]))}function X(e){let t=e.startsWith(`0x`)?e.slice(2):e,n=t.length%2==0?t:`0`+t;return Uint8Array.from(Buffer.from(n,`hex`))}function Z(e){return Buffer.from(e).toString(`hex`)}function Q(e){if(e<0n)throw Error(`Cannot encode negative bigint: ${e}`);if(e===0n)return new Uint8Array;let t=e.toString(16);return t.length%2!=0&&(t=`0`+t),X(t)}function It(...e){let t=e.reduce((e,t)=>e+t.length,0),n=new Uint8Array(t),r=0;for(let t of e)n.set(t,r),r+=t.length;return n}function Lt(e,t){if(e<56)return Uint8Array.of(t+e);let n=Q(BigInt(e));return It(Uint8Array.of(t+55+n.length),n)}function Rt(e){if(e instanceof Uint8Array)return e.length===1&&e[0]<128?e:It(Lt(e.length,128),e);let t=It(...e.map(Rt));return It(Lt(t.length,192),t)}function zt(e){let t=X(e);if(t.length!==32)throw Error(`Invalid private key length: expected 32 bytes, got ${t.length}`);return`0x`+Z((0,h.keccak_256)(m.secp256k1.getPublicKey(t,!1).slice(1)).slice(-20))}function Bt(e,t){if(!e.to.startsWith(`0x`)||e.to.length!==42)throw Error(`Invalid 'to' address: ${e.to}`);let n=[Q(e.nonce),Q(e.gasPrice),Q(e.gasLimit),X(e.to),Q(e.value),X(e.data)],r=(0,h.keccak_256)(Rt([...n,Q(e.chainId),new Uint8Array,new Uint8Array])),i=X(t),a=m.secp256k1.sign(r,i,{format:`recovered`,lowS:!0,prehash:!1}),o=a[0],s=Y(Z(a.subarray(1,33))),c=Y(Z(a.subarray(33,65))),l=BigInt(o)+35n+e.chainId*2n,u=Rt([...n,Q(l),Q(s),Q(c)]);return{rawTx:`0x`+Z(u),hash:`0x`+Z((0,h.keccak_256)(u))}}async function Vt(e,t,n,r){let i=zt(t),[a,o,s]=await Promise.all([q(e,`eth_chainId`,[]),Pt(e,i,`pending`),Ft(e)]),{rawTx:c,hash:l}=Bt({chainId:Y(a),nonce:o,gasPrice:s===0n?1n:s,gasLimit:n.gasLimit,to:n.to,value:n.value??0n,data:n.data},t);await q(e,`eth_sendRawTransaction`,[c]);let u=await At(e,l,r.timeoutMs,r.pollMs);if(u.status!==`0x1`)throw Error(r.onRevert?.(l)??`Transaction ${l} reverted (status ${u.status}).`);return l}const Ht=`etherna_bee_network`,Ut=[`BEE_SWAP_FACTORY_ADDRESS`,`BEE_POSTAGE_STAMP_ADDRESS`,`BEE_PRICE_ORACLE_ADDRESS`,`BEE_REDISTRIBUTION_ADDRESS`,`BEE_STAKING_ADDRESS`],Wt=3e4,Gt=2e5;let Kt=!1,qt,Jt=Promise.resolve();function Yt(){Kt=!0,Jt=new Promise(e=>{qt=e})}function $(){Kt&&(Kt=!1,qt?.(),qt=void 0)}function Xt(){return Kt}function Zt(){return Jt}function Qt(e){return new Promise(t=>setTimeout(t,e))}async function $t({rpcUrl:e,postageStampAddress:t,ownerPrivateKey:n,desiredPrice:r}){let i=`etherna-bee`,a=(1n<<64n)-1n;if(r<0n||r>a)throw Error(`POSTAGE_PRICE ${r} is out of range for uint64 (0..${a}).`);let[o,s,c,l,u]=await Promise.all([J(e,`lastPrice()`),J(e,`setPrice(uint256)`),J(e,`hasRole(bytes32,address)`),J(e,`grantRole(bytes32,address)`),J(e,`PRICE_ORACLE_ROLE()`)]),d=async()=>Y(await q(e,`eth_call`,[{to:t,data:o},`latest`])),f=await d();if(f===r)return;let p=zt(n),m=await q(e,`eth_call`,[{to:t,data:u},`latest`]);if(!m||m===`0x`)throw Error(`PostageStamp.PRICE_ORACLE_ROLE() returned no data; ${t} may not be a PostageStamp contract.`);let h=kt(m),g=Ot(p);if(Y(await q(e,`eth_call`,[{to:t,data:c+h+g},`latest`]))===0n){console.log(` ${A.yellow(`➜`)} ${A.bold(i)}: granting PRICE_ORACLE_ROLE on PostageStamp to ${A.gray(p)}`);let r=await Vt(e,n,{to:t,data:l+h+g,gasLimit:BigInt(Gt)},{timeoutMs:Wt,pollMs:500,onRevert:e=>`PostageStamp.grantRole(PRICE_ORACLE_ROLE, ${p}) reverted (tx ${e}). The owner likely lacks DEFAULT_ADMIN_ROLE on PostageStamp ${t}.`});console.log(` ${A.gray(` granted (tx ${r})`)}`)}console.log(` ${A.yellow(`➜`)} ${A.bold(i)}: updating postage price ${A.gray(String(f))} → ${A.cyan(String(r))} PLUR`);let _=await Vt(e,n,{to:t,data:s+Dt(r),gasLimit:BigInt(Gt)},{timeoutMs:Wt,pollMs:500,onRevert:e=>`PostageStamp.setPrice(${r}) reverted (tx ${e}). The owner ${p} may lack PRICE_ORACLE_ROLE on PostageStamp ${t}.`}),v=await d();if(v!==r)throw Error(`PostageStamp.setPrice(${r}) succeeded (tx ${_}) but PostageStamp.lastPrice is ${v}.`);console.log(` ${A.green(`➜`)} ${A.bold(i)}: postage price set to ${A.cyan(String(r))} PLUR ${A.gray(`(tx ${_})`)}`)}function en(e){return Error([`Detected a stale or corrupted local blockchain state: Bee contracts are still missing even though the chain has already advanced.`,`Fix it by stopping the dev server, removing the persisted blockchain volume, and starting again:`,`1. Stop the dev server`,`2. Run: docker volume rm ${e}`,`3. Run: pnpm dev`].join(`
7
- `))}async function tn(e,t,n){let r=Date.now()+3e4,i=null;for(;Date.now()<r;){let[r,a]=await Promise.all([Mt(e).catch(()=>null),Promise.all(t.map(t=>jt(e,t).catch(()=>null)))]);if(r!=null&&a.every(e=>e!=null)){if(i===null&&(i=r),a.every(e=>Nt(e)))return;if(r>=10||r-i>=2)throw en(n)}await Qt(1e3)}throw Error(`Bee contracts were not deployed before the startup timeout elapsed. If this keeps happening, stop the dev server, run \`docker volume rm ${n}\`, and start again.`)}async function nn(e){let t=e.serviceCtx,n=e.getServiceEnv(`bee`),r=`etherna-blockchain`,i=`etherna_blockchain-volume`,a=e.detached,o=qe({...R(r,t)??{},...n}),s=Number(o.BLOCKCHAIN_PORT);if(a&&await vt(r))return B(r,`http`,String(s)),null;Yt(),await bt(Ht),await G(i);let c,l,u,d=new Promise((e,t)=>{l=e,u=t}),p=!1,m=!1;f.default.existsSync(z(`.ethereum`))||f.default.mkdirSync(z(`.ethereum`),{recursive:!0,mode:511}),f.default.existsSync(z(`.ethereum`,`password`))||f.default.writeFileSync(z(`.ethereum`,`password`),`toTheSun`,{encoding:`utf-8`,mode:420});let h=qe({...R(r,t)??{},...n}),g={...R(`etherna-bee`,t)??{},...n},_=Number(h.BLOCKCHAIN_PORT),v=Ut.map(e=>String(g[e])),y=await W({containerName:r,imageName:`fairdatasociety/fdp-play-blockchain:latest`,args:[...Object.entries(h).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--network`,Ht,`-p`,`${_}:${_}`,`-p`,`${_+1}:${_+1}`,`--mount`,`type=volume,source=${i},target=/root/.ethereum`,`--mount`,`type=bind,source=${it(`.ethereum`)},target=/root/extra`],detached:a,cmd:[`--allow-insecure-unlock`,`--unlock=${Ve}`,`--password=/root/extra/password`,`--mine`,`--miner.etherbase=${Ve}`,`--http`,`--http.api="debug,web3,eth,txpool,net,personal"`,`--http.corsdomain=*`,`--http.port=${_}`,`--http.addr=0.0.0.0`,`--http.vhosts=*`,`--ws`,`--ws.api="debug,web3,eth,txpool,net,personal"`,`--ws.port=${_+1}`,`--ws.origins=*`,`--maxpeers=0`,`--networkid=${h.NETWORK_ID}`,`--authrpc.vhosts=*`,`--authrpc.addr=0.0.0.0`]});if(!y)return $(),B(r,`http`,String(_)),null;e.pushSpawn(y);let b=e=>{c=void 0;let t=String(e);!p&&/HTTP server started/gm.test(t)&&(p=!0,tn(`http://127.0.0.1:${_}`,v,i).then(()=>{m=!0,$(),l?.()}).catch(e=>{m=!0,$();let t=e instanceof Error?e.message:String(e);V(r,t),_t(r).finally(()=>{u?.(e)})})),/Error:.+/gm.test(t)?(V(r,t),l?.()):c=t};return y.stdout?.on(`data`,b),y.stdout?.on(`error`,e=>{$(),V(r,`FATAL: `+e.message),l?.()}),y.stderr?.on(`data`,b),y.on(`close`,e=>{$(),m||(V(r,c||`Container closed with code ${e}`),l?.()),y.kill()}),await d,y}async function rn(e){let t=e.serviceCtx,n=e.getServiceEnv(`bee`),r=`etherna-bee`,i=await an(e,r),a=await st(`http://localhost:${R(`etherna-bee`,t)?.BEE_PORT??`1633`}`),[o]=await Promise.all([an(e,r,1,a)]);try{let e={...R(`etherna-bee`,t)??{},...n};await $t({rpcUrl:`http://127.0.0.1:${{...R(`etherna-blockchain`,t)??{},...n}.BLOCKCHAIN_PORT}`,postageStampAddress:String(e.BEE_POSTAGE_STAMP_ADDRESS),ownerPrivateKey:`0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d`,desiredPrice:BigInt(String(e.POSTAGE_PRICE??`24000`))})}catch(e){V(r,`Failed to sync postage price: ${e instanceof Error?e.message:String(e)}`)}return[i,o]}async function an(e,t,n,r){let i=e.serviceCtx,a=e.getServiceEnv(`bee`),o=n?`etherna_bee_worker_${n}-volume`:`etherna_bee-volume`;await G(o);let s,c,l=new Promise(e=>{c=e}),{mode:u}=i,d=qe({...R(t,i)??{},...a});n?(delete d.BEE_BOOTNODE_MODE,d.BEE_BOOTNODE=r):(delete d.BEE_BOOTNODE,d.BEE_BOOTNODE_MODE=`false`),n&&(t=`${t}_worker_${n}`);let f=await W({containerName:t,imageName:n?`fairdatasociety/fdp-play-worker-${n}`:`fairdatasociety/fdp-play-queen:latest`,args:[...Object.entries(d).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${o},target=/home/bee/.bee`,`--network`,Ht,`-p`,`${n?parseInt(d.BEE_PORT??`1633`)+n*1e4:d.BEE_PORT}:${d.BEE_PORT}`,`-p`,`${n?parseInt(d.BEE_P2P_PORT??`1634`)+n*1e4:d.BEE_P2P_PORT}:${d.BEE_P2P_PORT}`],cmd:[`start`],detached:e.detached});if(!f){if(!n){let e=i.portless?M(`bee`):void 0;B(t,u,String(d.BEE_PORT??`1633`),{portlessUrl:e})}return null}e.pushSpawn(f);let p=e=>{s=void 0;let r=String(e);if(/"address"="\[::\]:\d+"/gm.test(r)){if(!n){let e=i.portless?M(`bee`):void 0;B(t,u,String(d.BEE_PORT??`1633`),{portlessUrl:e})}c?.()}let a=[/"logger"="node\/storageincentives"/gm],o=r.split(`
5
+ `);return a!==-1&&(t=ce(t,i,r,a)),r+t+i};Object.defineProperties(O.prototype,D);const A=O();O({level:ue?ue.level:0});const ye={"bee-blockchain":{code:`bee-blockchain`,service:`bee`,dependencies:[],onFailure:`stop`},"bee-nodes":{code:`bee-nodes`,service:`bee`,dependencies:[`bee-blockchain`],onFailure:`stop`},shkeeper:{code:`shkeeper`,service:`shkeeper`,dependencies:[],onFailure:`stop`},mongo:{code:`mongo`,service:`mongo`,dependencies:[],onFailure:`stop`},sso:{code:`sso`,service:`sso`,dependencies:[`mongo`],onFailure:`stop`},index:{code:`index`,service:`index`,dependencies:[`mongo`],onFailure:`stop`},beehive:{code:`beehive`,service:`beehive`,dependencies:[`mongo`],onFailure:`stop`},gateway:{code:`gateway`,service:`gateway`,dependencies:[`mongo`,`sso`],onFailure:`stop`},credit:{code:`credit`,service:`credit`,dependencies:[`mongo`,`sso`,`shkeeper`],onFailure:`stop`},elastic:{code:`elastic`,service:`elastic`,dependencies:[],onFailure:`stop`}},be=[`blockchain`,`bee`,`beehive`,`credit`,`elastic`,`gateway`,`index`,`mongo`,`shkeeper`,`sso`];be.filter(e=>e!==`shkeeper`);var j=class extends Error{constructor(e){super(e),this.name=`DependencyTreeValidationError`}};function xe(e){return e instanceof Error?e:Error(String(e))}function Se(e,t){let n=new Set;for(let r=0;r<t.length;r++){let i=t[r];if(i.status!==`started`&&i.status!==`skipped`)if(i.status===`failed`)n.add(i.code);else{let t=i.blockedBy;if(t&&t.length>0)for(let e of t)n.add(e);else n.add(e[r])}}return[...n]}function Ce(e){let t=new Set;for(let n of e){if(t.has(n.code))throw new j(`Duplicate service code "${String(n.code)}".`);t.add(n.code)}for(let n of e){let e=n.dependencies??[];for(let r of e){if(r===n.code)throw new j(`Service "${String(n.code)}" cannot depend on itself.`);if(!t.has(r))throw new j(`Service "${String(n.code)}" depends on unknown service "${String(r)}".`)}}let n=new Set,r=new Set,i=new Map(e.map(e=>[e.code,e]));function a(e){if(r.has(e))return;if(n.has(e))throw new j(`Dependency cycle detected involving service "${String(e)}".`);n.add(e);let t=i.get(e);if(t){for(let e of t.dependencies??[])a(e);n.delete(e),r.add(e)}}for(let t of e)a(t.code)}function we(e,t){Ce(e);let n=new Map(e.map(e=>[e.code,e])),r=new Map;function i(e){let a=r.get(e);if(a)return a;let o=n.get(e);if(!o)throw new j(`Unknown service code "${String(e)}".`);let s=(async()=>{let n=o.dependencies??[],r=await Promise.all(n.map(e=>i(e)));if(r.some(e=>e.status!==`started`&&e.status!==`skipped`))return{code:e,status:`blocked`,blockedBy:Se(n,r)};if(o.enabled===!1)return{code:e,status:`skipped`};let a=o.onFailure??`stop`;try{if(o.beforeStartup&&await o.beforeStartup(),!await o.startupCallback()){let n=Error(`Service startup returned false`);return a===`log`&&t.logError(String(e),n.message),{code:e,status:`failed`,error:n}}return{code:e,status:`started`}}catch(n){let r=xe(n);return a===`log`&&t.logError(String(e),r.message),{code:e,status:`failed`,error:r}}})();return r.set(e,s),s}return{start:async()=>{let t=await Promise.all(e.map(e=>i(e.code)));return{shouldStop:t.some(e=>e.status===`failed`&&(n.get(e.code)?.onFailure??`stop`)===`stop`),services:t}}}}const Te=`/usr/local/share/ca-certificates`,Ee={"etherna-sso":`sso`,"etherna-index":`index`,"etherna-credit":`credit`,"etherna-gateway":`gateway`,"etherna-beehive":`beehive`};function M(e){return`http://${e}.localhost`}function De(e){return e.trim().replace(/\/+$/,``)}function Oe(){return[`proxy`,`start`,`--no-tls`,`--unprivileged`]}function ke(e=process.env){return{...e,PORTLESS_UNPRIVILEGED:`1`}}function Ae(){return[`proxy`,`stop`]}function je(e,t,n=!1){let r=[`alias`,e,String(t)];return n&&r.push(`--force`),r}function Me(e){return[`alias`,`--remove`,e]}async function N(e){return new Promise((t,n)=>{let r=(0,d.spawn)(`portless`,e,{stdio:[`ignore`,`pipe`,`pipe`],env:ke()}),i=``,a=``;r.stdout?.on(`data`,e=>{i+=String(e)}),r.stderr?.on(`data`,e=>{a+=String(e)}),r.on(`error`,n),r.on(`exit`,e=>{t({code:e??1,stderr:a,stdout:i})})})}async function Ne(){try{return(await N([`--version`])).code===0}catch{return!1}}async function Pe(){let e=await N(Oe());if(e.code===0)return{startedByUs:!0};let t=`${e.stderr}\n${e.stdout}`;if(/already|in use|running|listen/i.test(t))return{startedByUs:!1};throw Error(`portless proxy start failed (exit ${e.code}): ${t.trim()||`(no output)`}`)}function Fe(e){if(typeof e==`number`&&Number.isFinite(e))return e;let t=String(e).trim();if(t===``)throw Error(`Port value is empty`);let n=Number.parseInt(t,10);if(!Number.isFinite(n))throw Error(`Invalid port: ${String(e)}`);return n}async function Ie(e,t){let n=Fe(t),r=await N(je(e,n,!0));if(r.code!==0){let t=`${r.stderr}\n${r.stdout}`;throw Error(`portless alias ${e} ${n} failed: ${t.trim()}`)}}async function Le(e){for(let t of e)await N(Me(t))}async function Re(){await N(Ae())}const ze=1633,Be=1634,P=9545,Ve=4020,He=`0xCEeE442a149784faa65C35e328CCd64d874F9a02`,Ue=[`POSTAGE_PRICE`],We=32650,F=`shkeeper`;function Ge(e){let{mode:t,portless:n,appPort:r,portlessAppPublicUrl:i}=e,a=t===`http`?32610:42610,o=t===`http`?32620:42620,s=t===`http`?32630:42630,c=t===`http`?32640:42640,l=`mongodb://localhost:27017`,u=L(t,a),d=L(t,o),f=L(t,s),p=L(t,c),m=L(t,12610),h=`http://localhost:${ze}`,g=n&&i?De(i):qe(t,r,n,`app`),_={ASPNETCORE_ENVIRONMENT:`Development`,"Elastic:Urls:0":`http://localhost:9200`,...t===`https`?{ASPNETCORE_Kestrel__Certificates__Default__Path:`${Te}/etherna.pfx`,ASPNETCORE_Kestrel__Certificates__Default__Password:``}:{}};return{app:{port:r},shkeeper:{port:We},"shkeeper-core":{DEV_MODE:`1`,BTC_WALLET:`disabled`,LTC_WALLET:`disabled`,DOGE_WALLET:`disabled`,ETH_WALLET:`enabled`,ETH_USERNAME:`shkeeper`,ETH_PASSWORD:`shkeeper`,ETHEREUM_API_SERVER_HOST:`localhost`,ETHEREUM_SERVER_PORT:`6000`,SHKEEPER_BACKEND_KEY:F,SHKEEPER_BTC_BACKEND_KEY:F},"ethereum-shkeeper":{FULLNODE_URL:`http://localhost:${P}`,FULLNODE_TIMEOUT:`60`,CURRENT_ETH_NETWORK:`custom`,WEB3_ENABLE_POA_MIDDLEWARE:`1`,BLOCK_SCANNER_MAX_CATCHUP_BLOCKS:`64`,ETH_USERNAME:`shkeeper`,ETH_PASSWORD:`shkeeper`,SHKEEPER_BACKEND_KEY:F,SHKEEPER_HOST:`localhost:${We}`,REDIS_HOST:`localhost`,SQLALCHEMY_DATABASE_URI:`mariadb+pymysql://root:shkeeper@localhost:3306/ethereum-shkeeper?charset=utf8mb4`,LAST_BLOCK_LOCKED:`FALSE`},elastic:{"discovery.type":`single-node`,"xpack.security.enabled":`false`,ES_JAVA_OPTS:`-Xms512m -Xmx512m`},"etherna-mongodb":{},"etherna-sso":{..._,ASPNETCORE_URLS:u,"IdServer:SsoServer:BaseUrl":u,"IdServer:SsoServer:AllowUnsafeConnection":`true`,"IdServer:Clients:EthernaCredit:BaseUrl":f,"IdServer:Clients:EthernaGateway:BaseUrls:0":p,"IdServer:Clients:EthernaIndex:BaseUrl":d,"IdServer:Clients:EthernaDapp:BaseUrl":g,"DbSeed:Clients:0:RedirectUris:0":`${g}/callback`,"DbSeed:Clients:0:PostLogoutRedirectUris:0":g,"DbSeed:Clients:0:AllowedCorsOrigins:0":g,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSSODataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaSSOHangfireDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`,"ConnectionStrings:SSOServerDb":`${l}/ethernaSSODev`},"etherna-index":{..._,ASPNETCORE_URLS:d,"Swarm:GatewayUrl":p,"SsoServer:BaseUrl":u,"SsoServer:AllowUnsafeConnection":`true`,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSharedDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaIndexHangfireDev`,"ConnectionStrings:IndexDb":`${l}/ethernaIndexDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`},"etherna-credit":{..._,ASPNETCORE_URLS:f,"SsoServer:BaseUrl":u,"SsoServer:AllowUnsafeConnection":`true`,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSharedDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaCreditHangfireDev`,"ConnectionStrings:CreditDb":`${l}/ethernaCreditDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`,DisableHttpsRedirection:`true`,"Payments:ShKeeper:Url":`http://localhost:${We}`,"Payments:ShKeeper:ApiKey":F,"Payments:ShKeeper:CustomCallbackBaseUrl":f},"etherna-gateway":{..._,ASPNETCORE_URLS:p,"ForwardedHeaders:KnownNetworks:0":`0.0.0.0/0`,"SsoServer:BaseUrl":u,"SsoServer:Clients:Credit:BaseUrl":f,"SsoServer:Clients:Credit:Secret":`ethernaGatewayCreditClientSecret`,"SsoServer:Clients:Webapp:Secret":`ethernaGatewayWebappClientSecret`,"SsoServer:AllowUnsafeConnection":`true`,"Bee:CachedUrl":m,"Bee:DirectUrl":m,"Features:GarbageCollectPins":`false`,ForwardedAllowedHosts:`*`,"ConnectionStrings:DataProtectionDb":`${l}/ethernaSharedDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/ethernaGatewayHangfireDev`,"ConnectionStrings:GatewayDb":`${l}/ethernaGatewayDev`,"ConnectionStrings:ServiceSharedDb":`${l}/ethernaServiceSharedDev`},"etherna-beehive":{..._,ASPNETCORE_URLS:m,"SeedDb:BeeNodes:0:Hostname":`localhost`,"ConnectionStrings:DataProtectionDb":`${l}/beehiveDataProtectionDev`,"ConnectionStrings:HangfireDb":`${l}/beehiveHangfireDev`,"ConnectionStrings:BeehiveDb":`${l}/beehiveDev`,"SeedDb:BeeNodes:0:ConnectionString":h,"SeedDb:BeeNodes:0:EnableBatchCreation":`true`},"etherna-blockchain":{BLOCKCHAIN_PORT:P,NETWORK_ID:Ve},"etherna-bee":{POSTAGE_PRICE:`24000`,BEE_WARMUP_TIME:`10s`,BEE_DEBUG_API_ENABLE:`true`,BEE_VERBOSITY:`4`,BEE_SWAP_ENABLE:`true`,BEE_MAINNET:`false`,BEE_SWAP_ENDPOINT:`http://etherna-blockchain:${P}`,BEE_BLOCKCHAIN_RPC_ENDPOINT:`http://etherna-blockchain:${P}`,BEE_PASSWORD:`password`,BEE_SWAP_FACTORY_ADDRESS:`0xCfEB869F69431e42cdB54A4F4f105C19C080A601`,BEE_POSTAGE_STAMP_ADDRESS:`0x254dffcd3277C0b1660F6d42EFbB754edaBAbC2B`,BEE_PRICE_ORACLE_ADDRESS:`0x5b1869D9A4C187F2EAa108f3062412ecf0526b24`,BEE_REDISTRIBUTION_ADDRESS:`0x9561C133DD8580860B6b7E504bC5Aa500f0f06a7`,BEE_STAKING_ADDRESS:`0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb`,BEE_POSTAGE_STAMP_START_BLOCK:`1`,BEE_NETWORK_ID:Ve,BEE_FULL_NODE:`true`,BEE_PORT:ze,BEE_P2P_PORT:Be,BEE_API_ADDR:`0.0.0.0:${ze}`,BEE_P2P_ADDR:`0.0.0.0:${Be}`,BEE_CORS_ALLOWED_ORIGINS:`*`,BEE_ALLOW_PRIVATE_CIDRS:`true`,BEE_BOOTNODE_MODE:``,BEE_BOOTNODE:``}}}function Ke(e){return{mode:e,portless:!1,appPort:e===`http`?5173:5371}}function I(e){let t=e.split(`;`)[0]?.trim()??``;try{let e=new URL(t);return e.port?e.port:e.protocol===`https:`?`443`:`80`}catch{return t.split(`:`)[2]??`80`}}function L(e,t){return`${e}://localhost:${t}`}function qe(e,t,n,r){return n?M(r):L(e,t)}const R=(e,t)=>Ge(t)[e]??null;function Je(e){let t=new Set(Ue);return Object.fromEntries(Object.entries(e).filter(([e])=>!t.has(e)))}const Ye=`ETHERNA_DETACHED`;function Xe(e){if(typeof e.detached==`boolean`)return e.detached;let t=process.env[Ye]?.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}const Ze=[`elastic`,`mongo`,`bee`,`sso`,`index`,`gateway`,`credit`,`beehive`,`shkeeper`];function Qe(e){return typeof e==`object`&&e?e.enabled!==!1:e!==!1}function $e(e){return e===!0?!0:typeof e==`object`&&e?e.enabled!==!1:!1}function et(e){let t={};for(let n of Ze)t[n]=n===`shkeeper`?$e(e[n]):Qe(e[n]);t.blockchain=t.bee;let n={enabled:t,detached:Xe(e),portless:e.portless??!1,mode:e.mode??`http`,installSignalHandlers:e.installSignalHandlers??!0};return e.appPort!==void 0&&(n.appPort=e.appPort),n}function tt(e){return new Promise(t=>setTimeout(t,e))}async function nt(e){let t=e?.containerName??`shkeeper`,n=e?.sqlitePath??`/shkeeper.io/instance/shkeeper.sqlite`,r=e?.maxAttempts??120,i=e?.intervalMs??1e3;for(let e=0;e<r;e++){let a=await rt(t,n,`SELECT apikey FROM wallet WHERE apikey IS NOT NULL AND TRIM(COALESCE(apikey, '')) != '' LIMIT 1`);if(a)return a;e<r-1&&await tt(i)}return null}function rt(e,t,n){return new Promise(r=>{let i=(0,d.spawn)(`docker`,[`exec`,e,`sqlite3`,t,n]),a=``;i.stdout?.on(`data`,e=>{a+=typeof e==`string`?e:e.toString(`utf8`)}),i.on(`error`,()=>{r(null)}),i.on(`close`,e=>{if(e!==0){r(null);return}let t=a.trim();r(t.length>0?t:null)})})}function it(e){let t=typeof process<`u`?process.env?.[e]:void 0;if(t!==void 0)return t;try{let t={}.env?.[e];return typeof t==`string`?t:void 0}catch{return}}function z(...e){return p.default.resolve(`node_modules/.vite`,...e)}function at(...e){let t=z(...e);return process.platform===`win32`?t.replace(/\\/g,`/`):t}function B(e,t,n,r){if(r?.portlessUrl){let i=`${r.portlessUrl.replace(/\/$/,``)}/`,a=`${t}://localhost:${n}/`;console.log(` ${A.green(`➜`)} ${A.bold(e)}: ${A.cyan(i)} ${A.gray(`(${a})`)}`);return}let i=`${t}://localhost:${A.bold.cyanBright(n)}/`;console.log(` ${A.green(`➜`)} ${A.bold(e)}: ${A.cyan(i)}`)}function ot(e){console.log(` ${A.gray(`➜`)} ${A.bold(e)}: ${A.yellow(`Downloading image...`)}`)}function V(e,t){console.log(` ${A.red(`x`)} ${A.bold(e)}: ${A.red(t)}`)}async function st(e,t,n){let r=(0,d.spawn)(e,t,n);return new Promise((e,t)=>{r.on(`error`,e=>{t(e)}),r.on(`exit`,()=>{e()})})}async function ct(e){let t=await fetch(`${e}/addresses`);if(!t.ok)throw Error(`Failed to fetch addresses from ${e}: ${t.statusText}`);let n=await t.json(),r=Array.isArray(n.underlay)?n.underlay:[];if(r.length===0)return await new Promise(e=>setTimeout(e,500)),ct(e);let i=r.find(e=>!e.includes(`127.0.0.1`));if(!i)throw Error(`No valid underlay address found in response from ${e}`);return i}const lt=`etherna-`;function H(e){return e.startsWith(lt)?e:`${lt}${e}`}const ut=`https://docs.docker.com/get-docker/`,dt=3e4;function U(e,t){(0,d.spawn)(e,t,{detached:!0,stdio:`ignore`}).unref()}function ft(){return new Promise(e=>{let t=(0,d.spawn)(`docker`,[`info`],{stdio:`ignore`});t.on(`error`,()=>e(!1)),t.on(`exit`,t=>e(t===0))})}function pt(){return new Promise(e=>{let t=(0,d.spawn)(`docker`,[`--version`],{stdio:`ignore`});t.on(`error`,()=>e(!1)),t.on(`exit`,t=>e(t===0))})}function mt(){let{platform:e}=process;if(e===`darwin`){U(`open`,[`-a`,`Docker`]);return}if(e===`win32`){let e=`C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe`;if(f.default.existsSync(e)){U(e,[]);return}U(`cmd`,[`/c`,`start`,``,`Docker Desktop`]);return}e===`linux`&&U(`systemctl`,[`--user`,`start`,`docker-desktop`])}function ht(e){return new Promise(t=>setTimeout(t,e))}async function gt(){if(await pt()||(console.error(` ${A.red(`x`)} ${A.bold(`docker`)}: ${A.red(`Docker is not installed or not on your PATH.`)}`),console.error(` Install Docker and try again: ${A.cyan.underline(ut)}`),process.exit(1)),await ft())return;console.log(` ${A.yellow(`➜`)} ${A.bold(`docker`)}: ${A.yellow(`Docker daemon is not running. Starting it…`)}`),mt();let e=Date.now()+dt;for(;Date.now()<e;)if(await ht(2e3),await ft()){console.log(` ${A.green(`➜`)} ${A.bold(`docker`)}: ${A.green(`Docker is ready.`)}`);return}console.error(` ${A.red(`x`)} ${A.bold(`docker`)}: ${A.red(`Docker did not become ready within ${dt/1e3}s. Start Docker manually and run the dev server again.`)}`),console.error(` Install or troubleshoot: ${A.cyan.underline(ut)}`),process.exit(1)}async function W({containerName:e,imageName:t,args:n=[],cmd:r=[],detached:i=!1}){let a=H(e);if(!i)await _t(a)&&await vt(a);else{if(await yt(a))return null;await _t(a)&&await bt(a)}let o=[`run`,`--rm`,`--name`,a,...n,t,...r],s=i?(0,d.spawn)(`docker`,[...o],{detached:!0,stdio:[`ignore`,`pipe`,`pipe`]}):(0,d.spawn)(`docker`,[...o]);return s.stdout?.on(`data`,e=>{let t=String(e);/Pulling from/gm.test(t)&&ot(a),/Error response from daemon/gm.test(t)&&V(a,t)}),i&&s.unref(),s}async function _t(e){let t=(0,d.spawn)(`docker`,[`ps`,`-a`,`--filter`,`name=${H(e)}`]);return(await new Promise(e=>{let n=``;t.stdout?.on(`data`,e=>{n+=String(e)}),t.on(`close`,()=>{e(n)})})).split(`
6
+ `).length>1}async function vt(e){let t=(0,d.spawn)(`docker`,[`stop`,H(e)]);await new Promise(e=>{t.on(`close`,()=>{e()})})}async function yt(e){return new Promise(t=>{let n=(0,d.spawn)(`docker`,[`inspect`,`-f`,`{{.State.Running}}`,H(e)],{stdio:[`ignore`,`pipe`,`ignore`]}),r=``;n.stdout?.on(`data`,e=>{r+=String(e)}),n.on(`error`,()=>t(!1)),n.on(`close`,e=>{if(e!==0){t(!1);return}t(r.trim().toLowerCase()===`true`)})})}async function bt(e){await new Promise(t=>{let n=(0,d.spawn)(`docker`,[`rm`,`-f`,H(e)],{stdio:`ignore`});n.on(`error`,()=>t()),n.on(`close`,()=>t())})}async function G(e){let t=(0,d.spawn)(`docker`,[`volume`,`create`,e]);await new Promise(e=>{t.on(`close`,()=>{e()})})}async function xt(e){let t=(0,d.spawn)(`docker`,[`network`,`create`,e]);await new Promise(e=>{t.on(`close`,()=>{e()})})}const St={blockchain:[`etherna-blockchain`],bee:[`etherna-blockchain`,`etherna-bee`,`etherna-bee_worker_1`],beehive:[`etherna-beehive`],credit:[`etherna-credit`],elastic:[`etherna-elastic`],gateway:[`etherna-gateway`],index:[`etherna-index`],mongo:[`etherna-mongodb`],shkeeper:[`ethereum-shkeeper-mariadb`,`ethereum-shkeeper-redis`,`ethereum-shkeeper`,`ethereum-tasks`,`shkeeper`],sso:[`etherna-sso`]};function Ct(e){return St[e]}async function wt(e){let t=[...new Set(e.flatMap(Ct))];await Promise.all(t.map(e=>vt(e)))}async function Tt(e){await wt(Object.keys(e).filter(t=>e[t]))}async function Et(e){await st(`docker`,[`exec`,e,`update-ca-certificates`]).catch(t=>{console.error(A.red(`‼️ Error trusting certificate in container '${e}': ${t.message}`))})}async function K(e,t,n,r){let i,a=new Promise(e=>{i=e}),o,{mode:s}=e.serviceCtx,c={...R(t,e.serviceCtx)??{},...r},l=c.ASPNETCORE_URLS.split(`;`)[0]?.split(`:`)[2]??`80`,u=Ee[t],d=e.serviceCtx.portless&&u?M(u):void 0,f=await W({containerName:t,imageName:n,args:[...Object.entries(c).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),...s===`https`?[`--mount`,`type=bind,source=${at(`.ssl`)},target=${Te}/`]:[],`--network`,`host`],detached:e.detached});if(!f)return B(t,s,l,{portlessUrl:d}),null;e.pushSpawn(f);let p=async e=>{o=void 0;let n=String(e);/Now listening on: https?:\/\/(localhost|\[::\]):\d+/gm.test(n)&&(s===`https`&&await Et(t),B(t,s,l,{portlessUrl:d}),i?.());let r=[/Current db does not support change stream/gm,/is only supported on replica sets./gm,/Failed to process the job/gm],a=[/\[(ERR|FTL)\]/gm,/"LogLevel"\s*:\s*"(Error|Critical)"/gm,/\b(fail|crit):/gm,/<(2|3)>/gm].some(e=>e.test(n)),c=/\[(INF|WRN|DBG|VRB)\]/gm.test(n);a&&!c&&/Exception:.+/gm.test(n)&&!r.some(e=>e.test(n))?(V(t,n),i?.()):o=n};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),i?.()}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(t,o||`Container closed with code ${e}`),i?.(),f.kill()}),await a,f}function Dt(e){return new Promise(t=>setTimeout(t,e))}async function q(e,t,n){let r=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({jsonrpc:`2.0`,id:1,method:t,params:n})});if(!r.ok)throw Error(`RPC ${t} failed: ${r.status} ${r.statusText}`);let i=await r.json();if(i.error?.message)throw Error(`RPC ${t} error: ${i.error.message}`);return i.result}async function J(e,t){return(await q(e,`web3_sha3`,[`0x`+Buffer.from(t,`utf-8`).toString(`hex`)])).slice(0,10)}function Ot(e){if(e<0n)throw Error(`Cannot encode negative uint param: ${e}`);return e.toString(16).padStart(64,`0`)}function kt(e){let t=e.toLowerCase().startsWith(`0x`)?e.slice(2):e;if(t.length!==40)throw Error(`Invalid address (expected 20 bytes / 40 hex chars): ${e}`);return t.toLowerCase().padStart(64,`0`)}function At(e){let t=e.startsWith(`0x`)?e.slice(2):e;if(t.length!==64)throw Error(`Invalid bytes32 (expected 32 bytes / 64 hex chars): ${e}`);return t.toLowerCase()}function Y(e){let t=e.startsWith(`0x`)?e.slice(2):e;return t.length===0?0n:BigInt(`0x`+t)}async function jt(e,t,n,r=500){let i=Date.now()+n;for(;Date.now()<i;){let n=await q(e,`eth_getTransactionReceipt`,[t]);if(n?.status)return{status:n.status,blockNumber:n.blockNumber};await Dt(r)}throw Error(`Transaction ${t} was not mined within ${n}ms`)}async function Mt(e,t){return await q(e,`eth_getCode`,[t,`latest`]).then(e=>e??`0x`)}async function Nt(e){let t=await q(e,`eth_blockNumber`,[]);return Number.parseInt(t??`0x0`,16)}function Pt(e){return e!==`0x`&&e.length>2}async function Ft(e,t,n=`pending`){return Y(await q(e,`eth_getTransactionCount`,[t,n]))}async function It(e){return Y(await q(e,`eth_gasPrice`,[]))}function X(e){let t=e.startsWith(`0x`)?e.slice(2):e,n=t.length%2==0?t:`0`+t;return Uint8Array.from(Buffer.from(n,`hex`))}function Z(e){return Buffer.from(e).toString(`hex`)}function Q(e){if(e<0n)throw Error(`Cannot encode negative bigint: ${e}`);if(e===0n)return new Uint8Array;let t=e.toString(16);return t.length%2!=0&&(t=`0`+t),X(t)}function Lt(...e){let t=e.reduce((e,t)=>e+t.length,0),n=new Uint8Array(t),r=0;for(let t of e)n.set(t,r),r+=t.length;return n}function Rt(e,t){if(e<56)return Uint8Array.of(t+e);let n=Q(BigInt(e));return Lt(Uint8Array.of(t+55+n.length),n)}function zt(e){if(e instanceof Uint8Array)return e.length===1&&e[0]<128?e:Lt(Rt(e.length,128),e);let t=Lt(...e.map(zt));return Lt(Rt(t.length,192),t)}function Bt(e){let t=X(e);if(t.length!==32)throw Error(`Invalid private key length: expected 32 bytes, got ${t.length}`);return`0x`+Z((0,h.keccak_256)(m.secp256k1.getPublicKey(t,!1).slice(1)).slice(-20))}function Vt(e,t){if(!e.to.startsWith(`0x`)||e.to.length!==42)throw Error(`Invalid 'to' address: ${e.to}`);let n=[Q(e.nonce),Q(e.gasPrice),Q(e.gasLimit),X(e.to),Q(e.value),X(e.data)],r=(0,h.keccak_256)(zt([...n,Q(e.chainId),new Uint8Array,new Uint8Array])),i=X(t),a=m.secp256k1.sign(r,i,{format:`recovered`,lowS:!0,prehash:!1}),o=a[0],s=Y(Z(a.subarray(1,33))),c=Y(Z(a.subarray(33,65))),l=BigInt(o)+35n+e.chainId*2n,u=zt([...n,Q(l),Q(s),Q(c)]);return{rawTx:`0x`+Z(u),hash:`0x`+Z((0,h.keccak_256)(u))}}async function Ht(e,t,n,r){let i=Bt(t),[a,o,s]=await Promise.all([q(e,`eth_chainId`,[]),Ft(e,i,`pending`),It(e)]),{rawTx:c,hash:l}=Vt({chainId:Y(a),nonce:o,gasPrice:s===0n?1n:s,gasLimit:n.gasLimit,to:n.to,value:n.value??0n,data:n.data},t);await q(e,`eth_sendRawTransaction`,[c]);let u=await jt(e,l,r.timeoutMs,r.pollMs);if(u.status!==`0x1`)throw Error(r.onRevert?.(l)??`Transaction ${l} reverted (status ${u.status}).`);return l}const Ut=`etherna_bee_network`,Wt=[`BEE_SWAP_FACTORY_ADDRESS`,`BEE_POSTAGE_STAMP_ADDRESS`,`BEE_PRICE_ORACLE_ADDRESS`,`BEE_REDISTRIBUTION_ADDRESS`,`BEE_STAKING_ADDRESS`],Gt=3e4,Kt=2e5;let qt=!1,Jt,Yt=Promise.resolve();function Xt(){qt=!0,Yt=new Promise(e=>{Jt=e})}function $(){qt&&(qt=!1,Jt?.(),Jt=void 0)}function Zt(){return qt}function Qt(){return Yt}function $t(e){return new Promise(t=>setTimeout(t,e))}async function en({rpcUrl:e,postageStampAddress:t,ownerPrivateKey:n,desiredPrice:r}){let i=`etherna-bee`,a=(1n<<64n)-1n;if(r<0n||r>a)throw Error(`POSTAGE_PRICE ${r} is out of range for uint64 (0..${a}).`);let[o,s,c,l,u]=await Promise.all([J(e,`lastPrice()`),J(e,`setPrice(uint256)`),J(e,`hasRole(bytes32,address)`),J(e,`grantRole(bytes32,address)`),J(e,`PRICE_ORACLE_ROLE()`)]),d=async()=>Y(await q(e,`eth_call`,[{to:t,data:o},`latest`])),f=await d();if(f===r)return;let p=Bt(n),m=await q(e,`eth_call`,[{to:t,data:u},`latest`]);if(!m||m===`0x`)throw Error(`PostageStamp.PRICE_ORACLE_ROLE() returned no data; ${t} may not be a PostageStamp contract.`);let h=At(m),g=kt(p);if(Y(await q(e,`eth_call`,[{to:t,data:c+h+g},`latest`]))===0n){console.log(` ${A.yellow(`➜`)} ${A.bold(i)}: granting PRICE_ORACLE_ROLE on PostageStamp to ${A.gray(p)}`);let r=await Ht(e,n,{to:t,data:l+h+g,gasLimit:BigInt(Kt)},{timeoutMs:Gt,pollMs:500,onRevert:e=>`PostageStamp.grantRole(PRICE_ORACLE_ROLE, ${p}) reverted (tx ${e}). The owner likely lacks DEFAULT_ADMIN_ROLE on PostageStamp ${t}.`});console.log(` ${A.gray(` granted (tx ${r})`)}`)}console.log(` ${A.yellow(`➜`)} ${A.bold(i)}: updating postage price ${A.gray(String(f))} → ${A.cyan(String(r))} PLUR`);let _=await Ht(e,n,{to:t,data:s+Ot(r),gasLimit:BigInt(Kt)},{timeoutMs:Gt,pollMs:500,onRevert:e=>`PostageStamp.setPrice(${r}) reverted (tx ${e}). The owner ${p} may lack PRICE_ORACLE_ROLE on PostageStamp ${t}.`}),v=await d();if(v!==r)throw Error(`PostageStamp.setPrice(${r}) succeeded (tx ${_}) but PostageStamp.lastPrice is ${v}.`);console.log(` ${A.green(`➜`)} ${A.bold(i)}: postage price set to ${A.cyan(String(r))} PLUR ${A.gray(`(tx ${_})`)}`)}function tn(e){return Error([`Detected a stale or corrupted local blockchain state: Bee contracts are still missing even though the chain has already advanced.`,`Fix it by stopping the dev server, removing the persisted blockchain volume, and starting again:`,`1. Stop the dev server`,`2. Run: docker volume rm ${e}`,`3. Run: pnpm dev`].join(`
7
+ `))}async function nn(e,t,n){let r=Date.now()+3e4,i=null;for(;Date.now()<r;){let[r,a]=await Promise.all([Nt(e).catch(()=>null),Promise.all(t.map(t=>Mt(e,t).catch(()=>null)))]);if(r!=null&&a.every(e=>e!=null)){if(i===null&&(i=r),a.every(e=>Pt(e)))return;if(r>=10||r-i>=2)throw tn(n)}await $t(1e3)}throw Error(`Bee contracts were not deployed before the startup timeout elapsed. If this keeps happening, stop the dev server, run \`docker volume rm ${n}\`, and start again.`)}async function rn(e){let t=e.serviceCtx,n=e.getServiceEnv(`bee`),r=`etherna-blockchain`,i=`etherna_blockchain-volume`,a=e.detached,o=Je({...R(r,t)??{},...n}),s=Number(o.BLOCKCHAIN_PORT);if(a&&await yt(r))return B(r,`http`,String(s)),null;Xt(),await xt(Ut),await G(i);let c,l,u,d=new Promise((e,t)=>{l=e,u=t}),p=!1,m=!1;f.default.existsSync(z(`.ethereum`))||f.default.mkdirSync(z(`.ethereum`),{recursive:!0,mode:511}),f.default.existsSync(z(`.ethereum`,`password`))||f.default.writeFileSync(z(`.ethereum`,`password`),`toTheSun`,{encoding:`utf-8`,mode:420});let h=Je({...R(r,t)??{},...n}),g={...R(`etherna-bee`,t)??{},...n},_=Number(h.BLOCKCHAIN_PORT),v=Wt.map(e=>String(g[e])),y=await W({containerName:r,imageName:`fairdatasociety/fdp-play-blockchain:latest`,args:[...Object.entries(h).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--network`,Ut,`-p`,`${_}:${_}`,`-p`,`${_+1}:${_+1}`,`--mount`,`type=volume,source=${i},target=/root/.ethereum`,`--mount`,`type=bind,source=${at(`.ethereum`)},target=/root/extra`],detached:a,cmd:[`--allow-insecure-unlock`,`--unlock=${He}`,`--password=/root/extra/password`,`--mine`,`--miner.etherbase=${He}`,`--http`,`--http.api="debug,web3,eth,txpool,net,personal"`,`--http.corsdomain=*`,`--http.port=${_}`,`--http.addr=0.0.0.0`,`--http.vhosts=*`,`--ws`,`--ws.api="debug,web3,eth,txpool,net,personal"`,`--ws.port=${_+1}`,`--ws.origins=*`,`--maxpeers=0`,`--networkid=${h.NETWORK_ID}`,`--authrpc.vhosts=*`,`--authrpc.addr=0.0.0.0`]});if(!y)return $(),B(r,`http`,String(_)),null;e.pushSpawn(y);let b=e=>{c=void 0;let t=String(e);!p&&/HTTP server started/gm.test(t)&&(p=!0,nn(`http://127.0.0.1:${_}`,v,i).then(()=>{m=!0,$(),l?.()}).catch(e=>{m=!0,$();let t=e instanceof Error?e.message:String(e);V(r,t),vt(r).finally(()=>{u?.(e)})})),/Error:.+/gm.test(t)?(V(r,t),l?.()):c=t};return y.stdout?.on(`data`,b),y.stdout?.on(`error`,e=>{$(),V(r,`FATAL: `+e.message),l?.()}),y.stderr?.on(`data`,b),y.on(`close`,e=>{$(),m||(V(r,c||`Container closed with code ${e}`),l?.()),y.kill()}),await d,y}async function an(e){let t=e.serviceCtx,n=e.getServiceEnv(`bee`),r=`etherna-bee`,i=await on(e,r),a=await ct(`http://localhost:${R(`etherna-bee`,t)?.BEE_PORT??`1633`}`),[o]=await Promise.all([on(e,r,1,a)]);try{let e={...R(`etherna-bee`,t)??{},...n};await en({rpcUrl:`http://127.0.0.1:${{...R(`etherna-blockchain`,t)??{},...n}.BLOCKCHAIN_PORT}`,postageStampAddress:String(e.BEE_POSTAGE_STAMP_ADDRESS),ownerPrivateKey:`0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d`,desiredPrice:BigInt(String(e.POSTAGE_PRICE??`24000`))})}catch(e){V(r,`Failed to sync postage price: ${e instanceof Error?e.message:String(e)}`)}return[i,o]}async function on(e,t,n,r){let i=e.serviceCtx,a=e.getServiceEnv(`bee`),o=n?`etherna_bee_worker_${n}-volume`:`etherna_bee-volume`;await G(o);let s,c,l=new Promise(e=>{c=e}),{mode:u}=i,d=Je({...R(t,i)??{},...a});n?(delete d.BEE_BOOTNODE_MODE,d.BEE_BOOTNODE=r):(delete d.BEE_BOOTNODE,d.BEE_BOOTNODE_MODE=`false`),n&&(t=`${t}_worker_${n}`);let f=await W({containerName:t,imageName:n?`fairdatasociety/fdp-play-worker-${n}`:`fairdatasociety/fdp-play-queen:latest`,args:[...Object.entries(d).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${o},target=/home/bee/.bee`,`--network`,Ut,`-p`,`${n?parseInt(d.BEE_PORT??`1633`)+n*1e4:d.BEE_PORT}:${d.BEE_PORT}`,`-p`,`${n?parseInt(d.BEE_P2P_PORT??`1634`)+n*1e4:d.BEE_P2P_PORT}:${d.BEE_P2P_PORT}`],cmd:[`start`],detached:e.detached});if(!f){if(!n){let e=i.portless?M(`bee`):void 0;B(t,u,String(d.BEE_PORT??`1633`),{portlessUrl:e})}return null}e.pushSpawn(f);let p=e=>{s=void 0;let r=String(e);if(/"address"="\[::\]:\d+"/gm.test(r)){if(!n){let e=i.portless?M(`bee`):void 0;B(t,u,String(d.BEE_PORT??`1633`),{portlessUrl:e})}c?.()}let a=[/"logger"="node\/storageincentives"/gm],o=r.split(`
8
8
  `).filter(e=>/"level"="(error|critical)"/.test(e)).join(`
9
- `);o&&!a.some(e=>e.test(r))&&(V(t,o),c?.(),s=o)};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),c?.()}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(t,s||`Container closed with code ${e}`),c?.(),f.kill()}),await l,f}function on(e){return{detached:e.detached??!1,serviceCtx:e.serviceCtx,getServiceEnv:e.getServiceEnv??(e=>({})),pushSpawn:e.pushSpawn??(()=>{}),isShutdownRequested:e.isShutdownRequested??(()=>!1),getShkeeperConfig:e.getShkeeperConfig??(()=>({})),getShkeeperBuild:e.getShkeeperBuild??(()=>({}))}}async function sn(e){let t=`elastic`,n=`etherna_${t}-data-volume`;await G(n);let r,i=new Promise(e=>{r=e}),a={...R(t,e.serviceCtx)??{},...e.getServiceEnv(`elastic`)},o=await W({containerName:t,imageName:`elasticsearch:7.17.24`,args:[...Object.entries(a).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${n},target=/usr/share/elasticsearch/data`,`--network`,`host`,`--memory=512m`],cmd:[],detached:e.detached});if(!o)return B(t,`http`,`9200`),null;e.pushSpawn(o);let s=e=>{let n=String(e);/"message": "started"/gm.test(n)&&(B(t,`http`,`9200`),r?.())};return o.stdout?.on(`data`,s),o.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),r?.()}),o.stderr?.on(`data`,s),o.on(`close`,e=>{V(t,`Container closed with code ${e}`),r?.(),o.kill()}),await i,o}async function cn(e){let t=`etherna-mongodb`,n=`etherna_${t}-db-volume`,r=`etherna_${t}-configdb-volume`;await Promise.all([G(n),G(r)]);let i,a=new Promise(e=>{i=e}),o={...R(t,e.serviceCtx)??{},...e.getServiceEnv(`mongo`)},s=await W({containerName:t,imageName:`mongo:latest`,args:[...Object.entries(o).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${n},target=/data/db`,`--mount`,`type=volume,source=${r},target=/data/configdb`,`--network`,`host`],cmd:[],detached:e.detached});if(!s)return B(t,`mongodb`,`27017`),null;e.pushSpawn(s);let c=e=>{let n=String(e);/mongod startup complete/gm.test(n)&&(B(t,`mongodb`,`27017`),i?.())};return s.stdout?.on(`data`,c),s.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),i?.()}),s.stderr?.on(`data`,c),s.on(`close`,e=>{V(t,`Container closed with code ${e}`),i?.(),s.kill()}),await a,s}const ln=`vsyshost/shkeeper:2.5.12`,un=`vsyshost/ethereum-shkeeper:1.2.3`,dn=`etherna`;function fn(e){let t=e.lastIndexOf(`:`);return t===-1||e.slice(t+1).includes(`/`)?{repository:e,tag:`latest`}:{repository:e.slice(0,t),tag:e.slice(t+1)}}function pn(e){let{tag:t}=fn(ln);return e?`${dn}/shkeeper:${t}`:ln}function mn(e){let{tag:t}=fn(un);return e?`${dn}/ethereum-shkeeper:${t}`:un}async function hn(e){let t=(0,d.spawn)(`docker`,[`image`,`inspect`,e]);return await new Promise(e=>{t.on(`close`,t=>{e(t===0)}),t.on(`error`,()=>{e(!1)})})}async function gn(e,t){let n=(0,d.spawn)(e,t);await new Promise((r,i)=>{n.on(`close`,n=>{if(n===0){r();return}i(Error(`Command failed: ${e} ${t.join(` `)}`))}),n.on(`error`,i)})}function _n(e,t){return z(e,`${t.replace(/[^a-z0-9._-]+/gi,`-`)}-${Date.now()}`)}async function vn(e,t,n){let r=_n(t,n);f.default.mkdirSync(r,{recursive:!0});let i=p.default.join(r,`clone`);return await gn(`git`,[`clone`,`--depth`,`1`,`--branch`,n,`https://github.com/${e}.git`,i]),{cleanupPath:r,contextPath:i,dockerfilePath:p.default.join(i,`Dockerfile`)}}async function yn(e){let{logLabel:t,imageName:n,sourceRepo:r,workspacePrefix:i,gitRef:a}=e;if(await hn(n))return;console.log(` ${A.yellow(`➜`)} ${A.bold(t)}: ${A.yellow(`Building Docker image from GitHub (${r}@${a}) (first run may take a while)…`)}`);let o=await vn(r,i,a),s=(0,d.spawn)(`docker`,[`build`,`-t`,n,`-f`,o.dockerfilePath,o.contextPath]);try{await new Promise((e,t)=>{s.on(`close`,r=>{if(r===0){e();return}t(Error(`Failed to build local Docker image ${n}`))}),s.on(`error`,t)})}catch(e){throw V(t,`Failed to build Docker image (${n}).`),o.cleanupPath?Error(`Failed to build local Docker image ${n}. Inspect cloned source at ${o.contextPath}`,{cause:e}):e}console.log(` ${A.yellow(`➜`)} ${A.bold(t)}: ${A.yellow(`Finished building Docker image.`)}`),o.cleanupPath&&f.default.rmSync(o.cleanupPath,{force:!0,recursive:!0})}function bn(e){let t=e?.trim();return t&&t.length>0?t:`main`}async function xn(e,t){await yn({logLabel:`shkeeper`,imageName:pn(e),sourceRepo:e??`vsys-host/shkeeper.io`,workspacePrefix:`.shkeeper-build`,gitRef:e?bn(t):fn(ln).tag})}async function Sn(e,t){e&&await yn({logLabel:`ethereum-shkeeper`,imageName:mn(e),sourceRepo:e,workspacePrefix:`.ethereum-shkeeper-build`,gitRef:bn(t)})}const Cn=`etherna_shkeeper_network`;async function wn({context:e,envs:t,build:n,networkName:r,detached:i=!1}){let a=`shkeeper`,o=`etherna_shkeeper-instance-volume`;await G(o);let s,c,l=new Promise((e,t)=>{s=e,c=t}),u,d=!1,f={...R(`shkeeper-core`,e)??{},...t},p=String(R(`shkeeper`,e)?.port??`32650`),m=r===`host`,h=m?p:`5000`,g=await W({containerName:a,imageName:n.imageName,args:[...Object.entries(f).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${o},target=/shkeeper.io/instance`,`--network`,r,...m?[]:[`-p`,`${p}:5000`]],...m?{cmd:[`bash`,`-c`,`gunicorn --access-logfile=- --workers=1 --threads=16 --timeout=600 --bind=0.0.0.0:${p} 'shkeeper:create_app()'`]}:{},detached:i});if(!g)return B(a,`http`,p),s?.(),null;let _=e=>{u=void 0;let t=String(e);RegExp(`Listening at: http://.+:${h}`,`gm`).test(t)?(d=!0,B(a,`http`,p),s?.()):u=t};return g.stdout?.on(`data`,_),g.stdout?.on(`error`,e=>{V(a,`FATAL: `+e.message),d||c?.(e)}),g.stderr?.on(`data`,_),g.on(`close`,e=>{V(a,u||`Container closed with code ${e}`),d||c?.(Error(`Container closed with code ${e}`)),g.kill()}),await l,g}async function Tn({context:e,envs:t,networkName:n,imageName:r,detached:i=!1}){let a=`ethereum-shkeeper`,o,s,c=new Promise((e,t)=>{o=e,s=t}),l,u=!1,d={...R(`ethereum-shkeeper`,e)??{},...t},f=await W({containerName:a,imageName:r,args:[...Object.entries(d).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--network`,n],cmd:[`bash`,`-c`,`sleep 30 && gunicorn --access-logfile=- --workers=1 --threads=16 --timeout=600 --bind=0.0.0.0:6000 run:server`],detached:i});if(!f)return o?.(),null;let p=e=>{l=void 0;let t=String(e);/Listening at: http:\/\/.+:6000/gm.test(t)?(u=!0,o?.()):l=t};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(a,`FATAL: `+e.message),u||s?.(e)}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(a,l||`Container closed with code ${e}`),u||s?.(Error(`Container closed with code ${e}`)),f.kill()}),await c,f}async function En(e=Cn,t){let n=`ethereum-shkeeper-mariadb`,r=`etherna_shkeeper-mariadb-volume`;await G(r);let i,a,o=new Promise((e,t)=>{i=e,a=t}),s,c=!1,l=await W({containerName:n,imageName:`mariadb:10.9.3`,args:[`-e`,`MARIADB_ROOT_PASSWORD=shkeeper`,`-e`,`MARIADB_DATABASE=ethereum-shkeeper`,`--mount`,`type=volume,source=${r},target=/var/lib/mysql`,`--network`,e],detached:!!t?.detached});if(!l)return i?.(),null;let u=e=>{s=void 0;let t=String(e);/ready for connections/gim.test(t)?(c=!0,i?.()):s=t};return l.stdout?.on(`data`,u),l.stdout?.on(`error`,e=>{V(n,`FATAL: `+e.message),c||a?.(e)}),l.stderr?.on(`data`,u),l.on(`close`,e=>{V(n,s||`Container closed with code ${e}`),c||a?.(Error(`Container closed with code ${e}`)),l.kill()}),await o,l}async function Dn(e=Cn,t){let n=`ethereum-shkeeper-redis`,r=`etherna_shkeeper-redis-volume`;await G(r);let i,a,o=new Promise((e,t)=>{i=e,a=t}),s,c=!1,l=await W({containerName:n,imageName:`redis:7`,args:[`--mount`,`type=volume,source=${r},target=/data`,`--network`,e],detached:!!t?.detached});if(!l)return i?.(),null;let u=e=>{s=void 0;let t=String(e);/Ready to accept connections/gm.test(t)?(c=!0,i?.()):s=t};return l.stdout?.on(`data`,u),l.stdout?.on(`error`,e=>{V(n,`FATAL: `+e.message),c||a?.(e)}),l.stderr?.on(`data`,u),l.on(`close`,e=>{V(n,s||`Container closed with code ${e}`),c||a?.(Error(`Container closed with code ${e}`)),l.kill()}),await o,l}async function On({context:e,envs:t,networkName:n,imageName:r,detached:i=!1}){let a=`ethereum-tasks`,o,s,c=new Promise((e,t)=>{o=e,s=t}),l,u=!1,d={...R(`ethereum-shkeeper`,e)??{},...t,C_FORCE_ROOT:`1`},f=await W({containerName:a,imageName:r,args:[...Object.entries(d).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--network`,n],cmd:[`bash`,`-c`,`sleep 30 && celery -A celery_worker.celery worker --loglevel=info -B`],detached:i});if(!f)return o?.(),null;let p=e=>{l=void 0;let t=String(e);/ready\./gim.test(t)?(u=!0,o?.()):l=t};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(a,`FATAL: `+e.message),u||s?.(e)}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(a,l||`Container closed with code ${e}`),u||s?.(Error(`Container closed with code ${e}`)),f.kill()}),await c,f}async function kn(e){let t=e.serviceCtx,n=e.detached,r=e.getShkeeperConfig(),i=e.getShkeeperBuild(),a={imageName:pn(i.githubRepo)},o=r.ethereum?.githubRepo?.trim()||void 0,s=r.ethereum?.githubBranch?.trim()||void 0,c=`host`,l=[];try{await xn(i.githubRepo,i.githubBranch),await Sn(o,s);let u=mn(o),[d,f]=await Promise.all([En(c,{detached:n}),Dn(c,{detached:n})]);l.push(d,f);let[p,m]=await Promise.all([Tn({context:t,envs:r.ethereum?.env,networkName:c,imageName:u,detached:n}),On({context:t,envs:r.ethereum?.env,networkName:c,imageName:u,detached:n})]);l.push(p,m);let h=await wn({context:t,envs:r.env,build:a,networkName:c,detached:n});return l.push(h),e.pushSpawn(...l),l}catch(e){for(let e of l)e?.kill();throw e}}function An(e){let t=e.detached,n=[],r=!1,i=[],a=!1,o=!1,s=e.isBlockchainBootstrapInProgress??(()=>!1),c=e.waitForBlockchainBootstrapToSettle??(()=>Promise.resolve()),l=e.onBlockchainShutdownWait??(()=>{}),u=e.addPortlessAlias??(async()=>{}),d=e.removePortlessAliases??(async()=>{}),f=e.stopPortlessProxy??(async()=>{}),p=e.exitProcess??(e=>process.exit(e)),m=()=>t,h=(...e)=>{n.push(...e)},g=()=>{for(let e of n)e.kill()},_=e=>{r=e},v=async(e,t)=>{await u(e,t),i.push(e)},y=async()=>{t||(i.length>0&&(await d([...i]),i.length=0),r&&await f(),r=!1)},b=async n=>{a=!0;let r=n?.force??!1;o&&!r||(o=!0,!r&&s()&&(l(),await c()),t||await e.stopContainersForEnabled(e.enabledServices),await y(),(n?.killTrackedSpawns??!t)&&g(),n?.exitProcess&&p(0))};return{isShutdownRequested:()=>a,pushSpawn:h,killSpawns:g,getDetached:m,setPortlessProxyStartedByUs:_,recordPortlessAlias:v,cleanupPortless:y,shutdown:b,installSignalHandlers:()=>{process.on(`SIGINT`,()=>{process.stdin.resume(),(async()=>{await b({exitProcess:!0,force:a})})()}),process.on(`SIGTERM`,()=>{(async()=>{await b({force:a})})()})}}}async function jn(e){let t=Array.isArray(e)?e:[e];for(let e of t)if(!be.includes(e))throw TypeError(`Unknown Etherna service "${String(e)}". Valid services: ${be.join(`, `)}.`);await Ct(t)}function Mn(e){return typeof e==`object`&&e?e.env??{}:{}}function Nn(e){return e===!0?{}:typeof e==`object`&&e?e:{}}async function Pn(e={}){let t=$e(e);await ht();let n=rt(`PORTLESS_URL`)?.trim(),r=t.appPort??Ge(t.mode).appPort,i={mode:t.mode,portless:t.portless,appPort:r,...t.portless&&n?{portlessAppPublicUrl:De(n)}:{}},a=An({detached:t.detached,enabledServices:t.enabled,stopContainersForEnabled:wt,addPortlessAlias:(e,t)=>Fe(e,t),removePortlessAliases:e=>Ie(e),stopPortlessProxy:Le,isBlockchainBootstrapInProgress:Xt,waitForBlockchainBootstrapToSettle:Zt,onBlockchainShutdownWait:()=>{console.log(A.yellow(` ➜ ${A.bold(`etherna-blockchain`)}: Shutdown requested during blockchain initialization. Waiting for a safe shutdown point. Press Ctrl+C again to force exit.`))}});e.installSignalHandlers!==!1&&a.installSignalHandlers(),t.portless&&await Fn(a,i,n);let o=t.portless?We(i):void 0,s=t=>Mn(e[t]),c=on({detached:t.detached,serviceCtx:i,getServiceEnv:s,pushSpawn:(...e)=>{a.pushSpawn(...e.filter(e=>e!=null))},isShutdownRequested:()=>a.isShutdownRequested(),getShkeeperConfig:()=>Nn(e.shkeeper),getShkeeperBuild:()=>{let t=Nn(e.shkeeper).build;return{githubRepo:t?.githubRepo?.trim()||void 0,githubBranch:t?.githubBranch?.trim()||void 0}}}),l=async e=>{try{return await e(),!a.isShutdownRequested()}catch(e){if(a.isShutdownRequested())return!1;throw e}},u=async()=>{let e=s(`credit`);if(t.enabled.shkeeper){let t=await tt();t&&(e={...e,"Payments:ShKeeper:ApiKey":t})}await K(c,`etherna-credit`,`etherna/etherna-credit:latest`,e)},d={"bee-blockchain":()=>l(()=>nn(c)),"bee-nodes":()=>l(()=>rn(c)),shkeeper:()=>l(()=>kn(c)),mongo:()=>l(()=>cn(c)),sso:()=>l(()=>K(c,`etherna-sso`,`etherna/etherna-sso:latest`,s(`sso`))),index:()=>l(()=>K(c,`etherna-index`,`etherna/etherna-index:latest`,s(`index`))),beehive:()=>l(()=>K(c,`etherna-beehive`,`etherna/beehive:latest`,s(`beehive`))),gateway:()=>l(()=>K(c,`etherna-gateway`,`etherna/etherna-gateway:latest`,s(`gateway`))),credit:()=>l(u),elastic:()=>l(()=>sn(c))},f=t.portless?{"bee-blockchain":async()=>{let e=R(`etherna-bee`,i)??{};await a.recordPortlessAlias(`bee`,{...e,...s(`bee`)}.BEE_PORT??1633)},shkeeper:async()=>{await a.recordPortlessAlias(`shkeeper`,R(`shkeeper`,i).port)},sso:async()=>{await a.recordPortlessAlias(`sso`,I(String(o?.[`etherna-sso`].ASPNETCORE_URLS)))},index:async()=>{await a.recordPortlessAlias(`index`,I(String(o?.[`etherna-index`].ASPNETCORE_URLS)))},beehive:async()=>{await a.recordPortlessAlias(`beehive`,I(String(o?.[`etherna-beehive`].ASPNETCORE_URLS)))},gateway:async()=>{await a.recordPortlessAlias(`gateway`,I(String(o?.[`etherna-gateway`].ASPNETCORE_URLS)))},credit:async()=>{await a.recordPortlessAlias(`credit`,I(String(o?.[`etherna-credit`].ASPNETCORE_URLS)))}}:{};return(await we(Object.keys(ye).map(e=>{let n=ye[e],r=f[e];return{code:e,dependencies:n.dependencies,enabled:t.enabled[n.service],onFailure:n.onFailure,startupCallback:d[e],...r?{beforeStartup:r}:{}}}),{logError:V}).start()).shouldStop&&!a.isShutdownRequested()&&(await wt(t.enabled),await a.shutdown({killTrackedSpawns:!0})),{shutdown:e=>a.shutdown(e)}}async function Fn(e,t,n){await Me()||(console.error(A.red(` portless: CLI not found. Install globally (recommended): npm install -g portless`)),process.exit(1));try{let{startedByUs:t}=await Ne();e.setPortlessProxyStartedByUs(t)}catch(e){console.error(A.red(` portless: failed to start proxy: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}if(!n)try{await e.recordPortlessAlias(`app`,t.appPort)}catch(t){console.error(A.red(` portless: failed to register aliases: ${t instanceof Error?t.message:String(t)}`)),await e.cleanupPortless(),process.exit(1)}let r=n!=null&&n!==``?`${De(n)}/`:`${M(`app`)}/`;console.log(A.green(` ➜ ${A.bold(`app (portless)`)}: ${A.cyan(r)}`))}exports.ETHERNA_DETACHED_ENV=Je,exports.resolveDetachedMode=Ye,exports.start=Pn,exports.stop=jn;
9
+ `);o&&!a.some(e=>e.test(r))&&(V(t,o),c?.(),s=o)};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),c?.()}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(t,s||`Container closed with code ${e}`),c?.(),f.kill()}),await l,f}function sn(e){return{detached:e.detached??!1,serviceCtx:e.serviceCtx,getServiceEnv:e.getServiceEnv??(e=>({})),pushSpawn:e.pushSpawn??(()=>{}),isShutdownRequested:e.isShutdownRequested??(()=>!1),getShkeeperConfig:e.getShkeeperConfig??(()=>({})),getShkeeperBuild:e.getShkeeperBuild??(()=>({}))}}async function cn(e){let t=`elastic`,n=`etherna_${t}-data-volume`;await G(n);let r,i=new Promise(e=>{r=e}),a={...R(t,e.serviceCtx)??{},...e.getServiceEnv(`elastic`)},o=await W({containerName:t,imageName:`elasticsearch:7.17.24`,args:[...Object.entries(a).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${n},target=/usr/share/elasticsearch/data`,`--network`,`host`,`--memory=512m`],cmd:[],detached:e.detached});if(!o)return B(t,`http`,`9200`),null;e.pushSpawn(o);let s=e=>{let n=String(e);/"message": "started"/gm.test(n)&&(B(t,`http`,`9200`),r?.())};return o.stdout?.on(`data`,s),o.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),r?.()}),o.stderr?.on(`data`,s),o.on(`close`,e=>{V(t,`Container closed with code ${e}`),r?.(),o.kill()}),await i,o}async function ln(e){let t=`etherna-mongodb`,n=`etherna_${t}-db-volume`,r=`etherna_${t}-configdb-volume`;await Promise.all([G(n),G(r)]);let i,a=new Promise(e=>{i=e}),o={...R(t,e.serviceCtx)??{},...e.getServiceEnv(`mongo`)},s=await W({containerName:t,imageName:`mongo:latest`,args:[...Object.entries(o).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${n},target=/data/db`,`--mount`,`type=volume,source=${r},target=/data/configdb`,`--network`,`host`],cmd:[],detached:e.detached});if(!s)return B(t,`mongodb`,`27017`),null;e.pushSpawn(s);let c=e=>{let n=String(e);/mongod startup complete/gm.test(n)&&(B(t,`mongodb`,`27017`),i?.())};return s.stdout?.on(`data`,c),s.stdout?.on(`error`,e=>{V(t,`FATAL: `+e.message),i?.()}),s.stderr?.on(`data`,c),s.on(`close`,e=>{V(t,`Container closed with code ${e}`),i?.(),s.kill()}),await a,s}const un=`vsyshost/shkeeper:2.5.12`,dn=`vsyshost/ethereum-shkeeper:1.2.3`,fn=`etherna`;function pn(e){let t=e.lastIndexOf(`:`);return t===-1||e.slice(t+1).includes(`/`)?{repository:e,tag:`latest`}:{repository:e.slice(0,t),tag:e.slice(t+1)}}function mn(e){let{tag:t}=pn(un);return e?`${fn}/shkeeper:${t}`:un}function hn(e){let{tag:t}=pn(dn);return e?`${fn}/ethereum-shkeeper:${t}`:dn}async function gn(e){let t=(0,d.spawn)(`docker`,[`image`,`inspect`,e]);return await new Promise(e=>{t.on(`close`,t=>{e(t===0)}),t.on(`error`,()=>{e(!1)})})}async function _n(e,t){let n=(0,d.spawn)(e,t);await new Promise((r,i)=>{n.on(`close`,n=>{if(n===0){r();return}i(Error(`Command failed: ${e} ${t.join(` `)}`))}),n.on(`error`,i)})}function vn(e,t){return z(e,`${t.replace(/[^a-z0-9._-]+/gi,`-`)}-${Date.now()}`)}async function yn(e,t,n){let r=vn(t,n);f.default.mkdirSync(r,{recursive:!0});let i=p.default.join(r,`clone`);return await _n(`git`,[`clone`,`--depth`,`1`,`--branch`,n,`https://github.com/${e}.git`,i]),{cleanupPath:r,contextPath:i,dockerfilePath:p.default.join(i,`Dockerfile`)}}async function bn(e){let{logLabel:t,imageName:n,sourceRepo:r,workspacePrefix:i,gitRef:a}=e;if(await gn(n))return;console.log(` ${A.yellow(`➜`)} ${A.bold(t)}: ${A.yellow(`Building Docker image from GitHub (${r}@${a}) (first run may take a while)…`)}`);let o=await yn(r,i,a),s=(0,d.spawn)(`docker`,[`build`,`-t`,n,`-f`,o.dockerfilePath,o.contextPath]);try{await new Promise((e,t)=>{s.on(`close`,r=>{if(r===0){e();return}t(Error(`Failed to build local Docker image ${n}`))}),s.on(`error`,t)})}catch(e){throw V(t,`Failed to build Docker image (${n}).`),o.cleanupPath?Error(`Failed to build local Docker image ${n}. Inspect cloned source at ${o.contextPath}`,{cause:e}):e}console.log(` ${A.yellow(`➜`)} ${A.bold(t)}: ${A.yellow(`Finished building Docker image.`)}`),o.cleanupPath&&f.default.rmSync(o.cleanupPath,{force:!0,recursive:!0})}function xn(e){let t=e?.trim();return t&&t.length>0?t:`main`}async function Sn(e,t){await bn({logLabel:`shkeeper`,imageName:mn(e),sourceRepo:e??`vsys-host/shkeeper.io`,workspacePrefix:`.shkeeper-build`,gitRef:e?xn(t):pn(un).tag})}async function Cn(e,t){e&&await bn({logLabel:`ethereum-shkeeper`,imageName:hn(e),sourceRepo:e,workspacePrefix:`.ethereum-shkeeper-build`,gitRef:xn(t)})}const wn=`etherna_shkeeper_network`;async function Tn({context:e,envs:t,build:n,networkName:r,detached:i=!1}){let a=`shkeeper`,o=`etherna_shkeeper-instance-volume`;await G(o);let s,c,l=new Promise((e,t)=>{s=e,c=t}),u,d=!1,f={...R(`shkeeper-core`,e)??{},...t},p=String(R(`shkeeper`,e)?.port??`32650`),m=r===`host`,h=m?p:`5000`,g=await W({containerName:a,imageName:n.imageName,args:[...Object.entries(f).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--mount`,`type=volume,source=${o},target=/shkeeper.io/instance`,`--network`,r,...m?[]:[`-p`,`${p}:5000`]],...m?{cmd:[`bash`,`-c`,`gunicorn --access-logfile=- --workers=1 --threads=16 --timeout=600 --bind=0.0.0.0:${p} 'shkeeper:create_app()'`]}:{},detached:i});if(!g)return B(a,`http`,p),s?.(),null;let _=e=>{u=void 0;let t=String(e);RegExp(`Listening at: http://.+:${h}`,`gm`).test(t)?(d=!0,B(a,`http`,p),s?.()):u=t};return g.stdout?.on(`data`,_),g.stdout?.on(`error`,e=>{V(a,`FATAL: `+e.message),d||c?.(e)}),g.stderr?.on(`data`,_),g.on(`close`,e=>{V(a,u||`Container closed with code ${e}`),d||c?.(Error(`Container closed with code ${e}`)),g.kill()}),await l,g}async function En({context:e,envs:t,networkName:n,imageName:r,detached:i=!1}){let a=`ethereum-shkeeper`,o,s,c=new Promise((e,t)=>{o=e,s=t}),l,u=!1,d={...R(`ethereum-shkeeper`,e)??{},...t},f=await W({containerName:a,imageName:r,args:[...Object.entries(d).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--network`,n],cmd:[`bash`,`-c`,`sleep 30 && gunicorn --access-logfile=- --workers=1 --threads=16 --timeout=600 --bind=0.0.0.0:6000 run:server`],detached:i});if(!f)return o?.(),null;let p=e=>{l=void 0;let t=String(e);/Listening at: http:\/\/.+:6000/gm.test(t)?(u=!0,o?.()):l=t};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(a,`FATAL: `+e.message),u||s?.(e)}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(a,l||`Container closed with code ${e}`),u||s?.(Error(`Container closed with code ${e}`)),f.kill()}),await c,f}async function Dn(e=wn,t){let n=`ethereum-shkeeper-mariadb`,r=`etherna_shkeeper-mariadb-volume`;await G(r);let i,a,o=new Promise((e,t)=>{i=e,a=t}),s,c=!1,l=await W({containerName:n,imageName:`mariadb:10.9.3`,args:[`-e`,`MARIADB_ROOT_PASSWORD=shkeeper`,`-e`,`MARIADB_DATABASE=ethereum-shkeeper`,`--mount`,`type=volume,source=${r},target=/var/lib/mysql`,`--network`,e],detached:!!t?.detached});if(!l)return i?.(),null;let u=e=>{s=void 0;let t=String(e);/ready for connections/gim.test(t)?(c=!0,i?.()):s=t};return l.stdout?.on(`data`,u),l.stdout?.on(`error`,e=>{V(n,`FATAL: `+e.message),c||a?.(e)}),l.stderr?.on(`data`,u),l.on(`close`,e=>{V(n,s||`Container closed with code ${e}`),c||a?.(Error(`Container closed with code ${e}`)),l.kill()}),await o,l}async function On(e=wn,t){let n=`ethereum-shkeeper-redis`,r=`etherna_shkeeper-redis-volume`;await G(r);let i,a,o=new Promise((e,t)=>{i=e,a=t}),s,c=!1,l=await W({containerName:n,imageName:`redis:7`,args:[`--mount`,`type=volume,source=${r},target=/data`,`--network`,e],detached:!!t?.detached});if(!l)return i?.(),null;let u=e=>{s=void 0;let t=String(e);/Ready to accept connections/gm.test(t)?(c=!0,i?.()):s=t};return l.stdout?.on(`data`,u),l.stdout?.on(`error`,e=>{V(n,`FATAL: `+e.message),c||a?.(e)}),l.stderr?.on(`data`,u),l.on(`close`,e=>{V(n,s||`Container closed with code ${e}`),c||a?.(Error(`Container closed with code ${e}`)),l.kill()}),await o,l}async function kn({context:e,envs:t,networkName:n,imageName:r,detached:i=!1}){let a=`ethereum-tasks`,o,s,c=new Promise((e,t)=>{o=e,s=t}),l,u=!1,d={...R(`ethereum-shkeeper`,e)??{},...t,C_FORCE_ROOT:`1`},f=await W({containerName:a,imageName:r,args:[...Object.entries(d).flatMap(([e,t])=>[`-e`,`${e}=${String(t)}`]),`--network`,n],cmd:[`bash`,`-c`,`sleep 30 && celery -A celery_worker.celery worker --loglevel=info -B`],detached:i});if(!f)return o?.(),null;let p=e=>{l=void 0;let t=String(e);/ready\./gim.test(t)?(u=!0,o?.()):l=t};return f.stdout?.on(`data`,p),f.stdout?.on(`error`,e=>{V(a,`FATAL: `+e.message),u||s?.(e)}),f.stderr?.on(`data`,p),f.on(`close`,e=>{V(a,l||`Container closed with code ${e}`),u||s?.(Error(`Container closed with code ${e}`)),f.kill()}),await c,f}async function An(e){let t=e.serviceCtx,n=e.detached,r=e.getShkeeperConfig(),i=e.getShkeeperBuild(),a={imageName:mn(i.githubRepo)},o=r.ethereum?.githubRepo?.trim()||void 0,s=r.ethereum?.githubBranch?.trim()||void 0,c=`host`,l=[];try{await Sn(i.githubRepo,i.githubBranch),await Cn(o,s);let u=hn(o),[d,f]=await Promise.all([Dn(c,{detached:n}),On(c,{detached:n})]);l.push(d,f);let[p,m]=await Promise.all([En({context:t,envs:r.ethereum?.env,networkName:c,imageName:u,detached:n}),kn({context:t,envs:r.ethereum?.env,networkName:c,imageName:u,detached:n})]);l.push(p,m);let h=await Tn({context:t,envs:r.env,build:a,networkName:c,detached:n});return l.push(h),e.pushSpawn(...l),l}catch(e){for(let e of l)e?.kill();throw e}}function jn(e){let t=e.detached,n=[],r=!1,i=[],a=!1,o=!1,s=e.isBlockchainBootstrapInProgress??(()=>!1),c=e.waitForBlockchainBootstrapToSettle??(()=>Promise.resolve()),l=e.onBlockchainShutdownWait??(()=>{}),u=e.addPortlessAlias??(async()=>{}),d=e.removePortlessAliases??(async()=>{}),f=e.stopPortlessProxy??(async()=>{}),p=e.exitProcess??(e=>process.exit(e)),m=()=>t,h=(...e)=>{n.push(...e)},g=()=>{for(let e of n)e.kill()},_=e=>{r=e},v=async(e,t)=>{await u(e,t),i.push(e)},y=async()=>{t||(i.length>0&&(await d([...i]),i.length=0),r&&await f(),r=!1)},b=async n=>{a=!0;let r=n?.force??!1;o&&!r||(o=!0,!r&&s()&&(l(),await c()),t||await e.stopContainersForEnabled(e.enabledServices),await y(),(n?.killTrackedSpawns??!t)&&g(),n?.exitProcess&&p(0))};return{isShutdownRequested:()=>a,pushSpawn:h,killSpawns:g,getDetached:m,setPortlessProxyStartedByUs:_,recordPortlessAlias:v,cleanupPortless:y,shutdown:b,installSignalHandlers:()=>{process.on(`SIGINT`,()=>{process.stdin.resume(),(async()=>{await b({exitProcess:!0,force:a})})()}),process.on(`SIGTERM`,()=>{(async()=>{await b({force:a})})()})}}}async function Mn(e){let t=Array.isArray(e)?e:[e];for(let e of t)if(!be.includes(e))throw TypeError(`Unknown Etherna service "${String(e)}". Valid services: ${be.join(`, `)}.`);await wt(t)}function Nn(e){return typeof e==`object`&&e?e.env??{}:{}}function Pn(e){return e===!0?{}:typeof e==`object`&&e?e:{}}async function Fn(e={}){let t=et(e);await gt();let n=it(`PORTLESS_URL`)?.trim(),r=t.appPort??Ke(t.mode).appPort,i={mode:t.mode,portless:t.portless,appPort:r,...t.portless&&n?{portlessAppPublicUrl:De(n)}:{}},a=jn({detached:t.detached,enabledServices:t.enabled,stopContainersForEnabled:Tt,addPortlessAlias:(e,t)=>Ie(e,t),removePortlessAliases:e=>Le(e),stopPortlessProxy:Re,isBlockchainBootstrapInProgress:Zt,waitForBlockchainBootstrapToSettle:Qt,onBlockchainShutdownWait:()=>{console.log(A.yellow(` ➜ ${A.bold(`etherna-blockchain`)}: Shutdown requested during blockchain initialization. Waiting for a safe shutdown point. Press Ctrl+C again to force exit.`))}});e.installSignalHandlers!==!1&&a.installSignalHandlers(),t.portless&&await In(a,i,n);let o=t.portless?Ge(i):void 0,s=t=>Nn(e[t]),c=sn({detached:t.detached,serviceCtx:i,getServiceEnv:s,pushSpawn:(...e)=>{a.pushSpawn(...e.filter(e=>e!=null))},isShutdownRequested:()=>a.isShutdownRequested(),getShkeeperConfig:()=>Pn(e.shkeeper),getShkeeperBuild:()=>{let t=Pn(e.shkeeper).build;return{githubRepo:t?.githubRepo?.trim()||void 0,githubBranch:t?.githubBranch?.trim()||void 0}}}),l=async e=>{try{return await e(),!a.isShutdownRequested()}catch(e){if(a.isShutdownRequested())return!1;throw e}},u=async()=>{let e=s(`credit`);if(t.enabled.shkeeper){let t=await nt();t&&(e={...e,"Payments:ShKeeper:ApiKey":t})}await K(c,`etherna-credit`,`etherna/etherna-credit:latest`,e)},d={"bee-blockchain":()=>l(()=>rn(c)),"bee-nodes":()=>l(()=>an(c)),shkeeper:()=>l(()=>An(c)),mongo:()=>l(()=>ln(c)),sso:()=>l(()=>K(c,`etherna-sso`,`etherna/etherna-sso:latest`,s(`sso`))),index:()=>l(()=>K(c,`etherna-index`,`etherna/etherna-index:latest`,s(`index`))),beehive:()=>l(()=>K(c,`etherna-beehive`,`etherna/beehive:latest`,s(`beehive`))),gateway:()=>l(()=>K(c,`etherna-gateway`,`etherna/etherna-gateway:latest`,s(`gateway`))),credit:()=>l(u),elastic:()=>l(()=>cn(c))},f=t.portless?{"bee-blockchain":async()=>{let e=R(`etherna-bee`,i)??{};await a.recordPortlessAlias(`bee`,{...e,...s(`bee`)}.BEE_PORT??1633)},shkeeper:async()=>{await a.recordPortlessAlias(`shkeeper`,R(`shkeeper`,i).port)},sso:async()=>{await a.recordPortlessAlias(`sso`,I(String(o?.[`etherna-sso`].ASPNETCORE_URLS)))},index:async()=>{await a.recordPortlessAlias(`index`,I(String(o?.[`etherna-index`].ASPNETCORE_URLS)))},beehive:async()=>{await a.recordPortlessAlias(`beehive`,I(String(o?.[`etherna-beehive`].ASPNETCORE_URLS)))},gateway:async()=>{await a.recordPortlessAlias(`gateway`,I(String(o?.[`etherna-gateway`].ASPNETCORE_URLS)))},credit:async()=>{await a.recordPortlessAlias(`credit`,I(String(o?.[`etherna-credit`].ASPNETCORE_URLS)))}}:{};return(await we(Object.keys(ye).map(e=>{let n=ye[e],r=f[e];return{code:e,dependencies:n.dependencies,enabled:t.enabled[n.service],onFailure:n.onFailure,startupCallback:d[e],...r?{beforeStartup:r}:{}}}),{logError:V}).start()).shouldStop&&!a.isShutdownRequested()&&(await Tt(t.enabled),await a.shutdown({killTrackedSpawns:!0})),{shutdown:e=>a.shutdown(e)}}async function In(e,t,n){await Ne()||(console.error(A.red(` portless: CLI not found. Install globally (recommended): npm install -g portless`)),process.exit(1));try{let{startedByUs:t}=await Pe();e.setPortlessProxyStartedByUs(t)}catch(e){console.error(A.red(` portless: failed to start proxy: ${e instanceof Error?e.message:String(e)}`)),process.exit(1)}if(!n)try{await e.recordPortlessAlias(`app`,t.appPort)}catch(t){console.error(A.red(` portless: failed to register aliases: ${t instanceof Error?t.message:String(t)}`)),await e.cleanupPortless(),process.exit(1)}let r=n!=null&&n!==``?`${De(n)}/`:`${M(`app`)}/`;console.log(A.green(` ➜ ${A.bold(`app (portless)`)}: ${A.cyan(r)}`))}exports.ETHERNA_DETACHED_ENV=Ye,exports.resolveDetachedMode=Xe,exports.start=Fn,exports.stop=Mn;
10
10
  //# sourceMappingURL=index.cjs.map