@tuwaio/satellite-evm 0.3.1 → 0.3.3
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/README.md +2 -2
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +14 -14
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ You create the adapter by passing your `wagmiConfig` to the `satelliteEVMAdapter
|
|
|
77
77
|
import { satelliteEVMAdapter } from '@tuwaio/satellite-evm';
|
|
78
78
|
import { wagmiConfig } from './your-wagmi-config'; // Import your configured wagmiConfig
|
|
79
79
|
|
|
80
|
-
export const evmAdapter = satelliteEVMAdapter(wagmiConfig);
|
|
80
|
+
export const evmAdapter = satelliteEVMAdapter(wagmiConfig, appEVMChains);
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
### Integrating with Satellite Connect Provider
|
|
@@ -139,7 +139,7 @@ function SatelliteSiweProvider({ children }: { children: ReactNode }) {
|
|
|
139
139
|
return (
|
|
140
140
|
<SatelliteConnectProvider
|
|
141
141
|
// Create the adapter, passing signInWithSiwe if SIWE is enabled
|
|
142
|
-
adapter={satelliteEVMAdapter(wagmiConfig, siweEnabled ? signInWithSiwe : undefined)}
|
|
142
|
+
adapter={satelliteEVMAdapter(wagmiConfig, appEVMChains, siweEnabled ? signInWithSiwe : undefined)}
|
|
143
143
|
autoConnect={true}
|
|
144
144
|
>
|
|
145
145
|
{/* Pass SIWE state to watcher for handling disconnections on SIWE rejection */}
|
package/dist/index.d.mts
CHANGED
|
@@ -23,6 +23,7 @@ interface EVMConnection extends BaseConnector {
|
|
|
23
23
|
* It uses wagmi as the underlying library for connector connections and chain interactions.
|
|
24
24
|
*
|
|
25
25
|
* @param config - Wagmi configuration object containing chain and connector settings
|
|
26
|
+
* @param chains - The list of chains to use for ENS client creation and other interactions
|
|
26
27
|
* @param signInWithSiwe - Optional function for signing in with SIWE
|
|
27
28
|
* @returns A configured SatelliteAdapter instance for EVM chains
|
|
28
29
|
* @throws Error if config is not provided
|
|
@@ -34,10 +35,11 @@ interface EVMConnection extends BaseConnector {
|
|
|
34
35
|
* connectors: [injected()]
|
|
35
36
|
* });
|
|
36
37
|
*
|
|
37
|
-
* const
|
|
38
|
+
* const chains = [mainnet, polygon];
|
|
39
|
+
* const evmAdapter = satelliteEVMAdapter(config, chains);
|
|
38
40
|
* ```
|
|
39
41
|
*/
|
|
40
|
-
declare function satelliteEVMAdapter(config: Config, signInWithSiwe?: () => Promise<void>): SatelliteAdapter<ConnectorEVM, EVMConnection>;
|
|
42
|
+
declare function satelliteEVMAdapter(config: Config, chains: readonly [Chain, ...Chain[]], signInWithSiwe?: () => Promise<void>): SatelliteAdapter<ConnectorEVM, EVMConnection>;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* Configuration parameters for impersonated wallet connector
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ interface EVMConnection extends BaseConnector {
|
|
|
23
23
|
* It uses wagmi as the underlying library for connector connections and chain interactions.
|
|
24
24
|
*
|
|
25
25
|
* @param config - Wagmi configuration object containing chain and connector settings
|
|
26
|
+
* @param chains - The list of chains to use for ENS client creation and other interactions
|
|
26
27
|
* @param signInWithSiwe - Optional function for signing in with SIWE
|
|
27
28
|
* @returns A configured SatelliteAdapter instance for EVM chains
|
|
28
29
|
* @throws Error if config is not provided
|
|
@@ -34,10 +35,11 @@ interface EVMConnection extends BaseConnector {
|
|
|
34
35
|
* connectors: [injected()]
|
|
35
36
|
* });
|
|
36
37
|
*
|
|
37
|
-
* const
|
|
38
|
+
* const chains = [mainnet, polygon];
|
|
39
|
+
* const evmAdapter = satelliteEVMAdapter(config, chains);
|
|
38
40
|
* ```
|
|
39
41
|
*/
|
|
40
|
-
declare function satelliteEVMAdapter(config: Config, signInWithSiwe?: () => Promise<void>): SatelliteAdapter<ConnectorEVM, EVMConnection>;
|
|
42
|
+
declare function satelliteEVMAdapter(config: Config, chains: readonly [Chain, ...Chain[]], signInWithSiwe?: () => Promise<void>): SatelliteAdapter<ConnectorEVM, EVMConnection>;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* Configuration parameters for impersonated wallet connector
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitEvm=require('@tuwaio/orbit-evm'),core=require('@wagmi/core'),viem=require('viem'),chains=require('viem/chains'),utils=require('viem/utils');var g=new Map;async function b({config:
|
|
1
|
+
'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitEvm=require('@tuwaio/orbit-evm'),core=require('@wagmi/core'),viem=require('viem'),chains=require('viem/chains'),utils=require('viem/utils');var g=new Map;async function b({config:a,address:o,chainId:s,chains:e}){if(g.has(o))return g.get(o);if(orbitEvm.createViemClient(s,e)){let n=!!await core.getBytecode(a,{address:o});return g.set(o,n),n}else return false}function Ce(a,o,s){if(!a)throw new Error("Satellite EVM adapter requires a wagmi config object.");return {key:orbitCore.OrbitAdapter.EVM,connect:async({connectorType:e,chainId:t})=>{let n=core.getConnectors(a).find(c=>orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.EVM,orbitCore.formatConnectorName(c.name))===e);if(!n)throw new Error("Cannot find connector with this wallet type");try{await core.connect(a,{connector:n,chainId:t}),s&&!orbitCore.isSafeApp&&orbitCore.formatConnectorName(n.name)!=="porto"&&orbitCore.formatConnectorName(n.name)!=="geminiwallet"&&orbitCore.formatConnectorName(n.name)!=="impersonatedwallet"&&await s();let c=core.getConnection(a);return {connectorType:e,address:c.address??viem.zeroAddress,chainId:c.chainId??chains.mainnet.id,rpcURL:c.chain?.rpcUrls.default.http[0]??chains.mainnet.rpcUrls.default.http[0],isConnected:c.isConnected,isContractAddress:!1,icon:n?.icon?.trim(),connector:n}}catch(c){throw new Error(c instanceof Error?c.message:String(c),{cause:c})}},disconnect:async e=>{if(e&&e.isConnected)await core.disconnect(a,{connector:e?.connector});else {let t=core.getConnectors(a);await Promise.allSettled(t.map(async r=>{await core.disconnect(a,{connector:r});}));}},getConnectors:()=>{let e=core.getConnectors(a);return {adapter:orbitCore.OrbitAdapter.EVM,connectors:e.map(t=>t)}},checkAndSwitchNetwork:async e=>await orbitEvm.checkAndSwitchChain(Number(e),a),getBalance:async(e,t)=>{let r=await core.getBalance(a,{address:e,chainId:Number(t)});return {value:viem.formatUnits(r.value,r.decimals),symbol:r.symbol}},getExplorerUrl:e=>{let{chain:t}=core.getConnection(a),r=t?.blockExplorers?.default.url;return e?`${r}/${e}`:r},getName:e=>orbitEvm.getName(e,o),getAvatar:e=>orbitEvm.getAvatar(e,o),getAddress:e=>orbitEvm.getAddress(e,o),checkIsContractAddress:async({address:e,chainId:t})=>{let r=core.getChains(a);return await b({config:a,address:e,chainId:t,chains:r})},getSafeConnectorChainId:async()=>{let t=core.getConnectors(a).find(r=>r.name==="Safe");if(t)return await t.getChainId()},switchConnection:async e=>{let r=core.getConnectors(a).find(n=>orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.EVM,orbitCore.formatConnectorName(n.name))===e);if(!r)throw new Error(`Cannot find connector with type: ${e}`);try{await core.switchConnection(a,{connector:r});}catch(n){throw new Error(`Failed to switch to connector ${e}: ${n instanceof Error?n.message:String(n)}`,{cause:n})}}}}S.type="impersonated";function S(a){let o=a.features??{},s=false,e,t;return core.createConnector(r=>({id:"impersonated",name:"Impersonated Connector",type:S.type,async setup(){e=r.chains[0].id;},async connect({chainId:n}={}){if(o.connectError)throw typeof o.connectError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to connect.")):o.connectError;let{request:c}=await this.getProvider(),d=await c({method:"eth_requestAccounts"}),h=await this.getChainId();return n&&h!==n&&(h=(await this.switchChain({chainId:n})).id),s=true,{accounts:d,chainId:h}},async disconnect(){s=false,t=void 0;},async getAccounts(){if(!s)throw new Error("Not connected connector");let{request:n}=await this.getProvider();return (await n({method:"eth_accounts"})).map(viem.getAddress)},async getChainId(){let{request:n}=await this.getProvider(),c=await n({method:"eth_chainId"});return viem.fromHex(c,"number")},async isAuthorized(){return s?!!(await this.getAccounts()).length:false},async switchChain({chainId:n}){let c=r.chains.find(h=>h.id===n);if(!c)throw new viem.SwitchChainError(new core.ChainNotConfiguredError);let{request:d}=await this.getProvider();return await d({method:"wallet_switchEthereumChain",params:[{chainId:viem.numberToHex(n)}]}),c},onAccountsChanged(n){n.length===0?this.onDisconnect():r.emitter.emit("change",{accounts:n.map(viem.getAddress)});},onChainChanged(n){let c=Number(n);r.emitter.emit("change",{chainId:c});},async onDisconnect(){r.emitter.emit("disconnect"),s=false,t=void 0;},async getProvider({chainId:n}={}){t=orbitCore.impersonatedHelpers?.getImpersonated()?[orbitCore.impersonatedHelpers.getImpersonated()||viem.zeroAddress]:void 0;let d=(r.chains.find(i=>i.id===n)??r.chains[0]).rpcUrls.default.http[0];return viem.custom({request:async({method:i,params:p})=>{if(i==="eth_chainId")return viem.numberToHex(e);if(i==="eth_requestAccounts")return t;if(i==="eth_signTypedData_v4"&&o.signTypedDataError)throw typeof o.signTypedDataError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to sign typed data.")):o.signTypedDataError;if(i==="wallet_switchEthereumChain"){if(o.switchChainError)throw typeof o.switchChainError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to switch chain.")):o.switchChainError;e=viem.fromHex(p[0].chainId,"number"),this.onChainChanged(e.toString());return}if(i==="personal_sign"){if(o.signMessageError)throw typeof o.signMessageError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to sign message.")):o.signMessageError;i="eth_sign",p=[p[1],p[0]];}let m={method:i,params:p},{error:u,result:y}=await utils.rpc.http(d,{body:m});if(u)throw new viem.RpcRequestError({body:m,error:u,url:d});return y}})({retryCount:1})}}))}var Ie={allowedDomains:[/gnosis-safe.io$/,/app.safe.global$/,/metissafe.tech$/],debug:false};var Ve=a=>a.reduce((o,s)=>{let e=s.id;return o[e]=viem.http(),o},{});function We(a,o){let{wagmiConfig:s,siwe:e}=a,{activeConnection:t,disconnect:r,connectionError:n,updateActiveConnection:c}=o,d=()=>{e?.enabled&&!e?.isSignedIn&&e?.isRejected&&t&&r(t.connectorType);},h=p=>{if(t&&orbitCore.getAdapterFromConnectorType(t.connectorType)!==orbitCore.OrbitAdapter.EVM)return;if(p.length===0){t&&r(t.connectorType);return}let m=core.getConnection(s);if(t&&orbitCore.getAdapterFromConnectorType(t.connectorType)!==orbitCore.OrbitAdapter.EVM||!m||n)return;let u=m.connector,k={connectorType:u?`${orbitCore.OrbitAdapter.EVM}:${orbitCore.formatConnectorName(u.name)}`:t?.connectorType,address:m.address,chainId:m.chainId,rpcURL:m?.chain?.rpcUrls.default.http[0],isConnected:true};c(k);};return d(),core.watchConnections(s,{onChange:h})}exports.checkIsWalletAddressContract=b;exports.createDefaultTransports=Ve;exports.createEVMConnectionsWatcher=We;exports.impersonated=S;exports.safeSdkOptions=Ie;exports.satelliteEVMAdapter=Ce;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {OrbitAdapter,getConnectorTypeFromName,formatConnectorName,isSafeApp,impersonatedHelpers,getAdapterFromConnectorType}from'@tuwaio/orbit-core';import {createViemClient,getAddress,getAvatar,getName,checkAndSwitchChain}from'@tuwaio/orbit-evm';import {getBytecode,getConnectors,switchConnection,getChains,getConnection,getBalance,disconnect,connect,createConnector,ChainNotConfiguredError,watchConnections}from'@wagmi/core';import {formatUnits,zeroAddress,custom,numberToHex,UserRejectedRequestError,fromHex,RpcRequestError,getAddress as getAddress$1,SwitchChainError,http}from'viem';import {mainnet}from'viem/chains';import {rpc}from'viem/utils';var g=new Map;async function b({config:
|
|
1
|
+
import {OrbitAdapter,getConnectorTypeFromName,formatConnectorName,isSafeApp,impersonatedHelpers,getAdapterFromConnectorType}from'@tuwaio/orbit-core';import {createViemClient,getAddress,getAvatar,getName,checkAndSwitchChain}from'@tuwaio/orbit-evm';import {getBytecode,getConnectors,switchConnection,getChains,getConnection,getBalance,disconnect,connect,createConnector,ChainNotConfiguredError,watchConnections}from'@wagmi/core';import {formatUnits,zeroAddress,custom,numberToHex,UserRejectedRequestError,fromHex,RpcRequestError,getAddress as getAddress$1,SwitchChainError,http}from'viem';import {mainnet}from'viem/chains';import {rpc}from'viem/utils';var g=new Map;async function b({config:a,address:o,chainId:s,chains:e}){if(g.has(o))return g.get(o);if(createViemClient(s,e)){let n=!!await getBytecode(a,{address:o});return g.set(o,n),n}else return false}function Ce(a,o,s){if(!a)throw new Error("Satellite EVM adapter requires a wagmi config object.");return {key:OrbitAdapter.EVM,connect:async({connectorType:e,chainId:t})=>{let n=getConnectors(a).find(c=>getConnectorTypeFromName(OrbitAdapter.EVM,formatConnectorName(c.name))===e);if(!n)throw new Error("Cannot find connector with this wallet type");try{await connect(a,{connector:n,chainId:t}),s&&!isSafeApp&&formatConnectorName(n.name)!=="porto"&&formatConnectorName(n.name)!=="geminiwallet"&&formatConnectorName(n.name)!=="impersonatedwallet"&&await s();let c=getConnection(a);return {connectorType:e,address:c.address??zeroAddress,chainId:c.chainId??mainnet.id,rpcURL:c.chain?.rpcUrls.default.http[0]??mainnet.rpcUrls.default.http[0],isConnected:c.isConnected,isContractAddress:!1,icon:n?.icon?.trim(),connector:n}}catch(c){throw new Error(c instanceof Error?c.message:String(c),{cause:c})}},disconnect:async e=>{if(e&&e.isConnected)await disconnect(a,{connector:e?.connector});else {let t=getConnectors(a);await Promise.allSettled(t.map(async r=>{await disconnect(a,{connector:r});}));}},getConnectors:()=>{let e=getConnectors(a);return {adapter:OrbitAdapter.EVM,connectors:e.map(t=>t)}},checkAndSwitchNetwork:async e=>await checkAndSwitchChain(Number(e),a),getBalance:async(e,t)=>{let r=await getBalance(a,{address:e,chainId:Number(t)});return {value:formatUnits(r.value,r.decimals),symbol:r.symbol}},getExplorerUrl:e=>{let{chain:t}=getConnection(a),r=t?.blockExplorers?.default.url;return e?`${r}/${e}`:r},getName:e=>getName(e,o),getAvatar:e=>getAvatar(e,o),getAddress:e=>getAddress(e,o),checkIsContractAddress:async({address:e,chainId:t})=>{let r=getChains(a);return await b({config:a,address:e,chainId:t,chains:r})},getSafeConnectorChainId:async()=>{let t=getConnectors(a).find(r=>r.name==="Safe");if(t)return await t.getChainId()},switchConnection:async e=>{let r=getConnectors(a).find(n=>getConnectorTypeFromName(OrbitAdapter.EVM,formatConnectorName(n.name))===e);if(!r)throw new Error(`Cannot find connector with type: ${e}`);try{await switchConnection(a,{connector:r});}catch(n){throw new Error(`Failed to switch to connector ${e}: ${n instanceof Error?n.message:String(n)}`,{cause:n})}}}}S.type="impersonated";function S(a){let o=a.features??{},s=false,e,t;return createConnector(r=>({id:"impersonated",name:"Impersonated Connector",type:S.type,async setup(){e=r.chains[0].id;},async connect({chainId:n}={}){if(o.connectError)throw typeof o.connectError=="boolean"?new UserRejectedRequestError(new Error("Failed to connect.")):o.connectError;let{request:c}=await this.getProvider(),d=await c({method:"eth_requestAccounts"}),h=await this.getChainId();return n&&h!==n&&(h=(await this.switchChain({chainId:n})).id),s=true,{accounts:d,chainId:h}},async disconnect(){s=false,t=void 0;},async getAccounts(){if(!s)throw new Error("Not connected connector");let{request:n}=await this.getProvider();return (await n({method:"eth_accounts"})).map(getAddress$1)},async getChainId(){let{request:n}=await this.getProvider(),c=await n({method:"eth_chainId"});return fromHex(c,"number")},async isAuthorized(){return s?!!(await this.getAccounts()).length:false},async switchChain({chainId:n}){let c=r.chains.find(h=>h.id===n);if(!c)throw new SwitchChainError(new ChainNotConfiguredError);let{request:d}=await this.getProvider();return await d({method:"wallet_switchEthereumChain",params:[{chainId:numberToHex(n)}]}),c},onAccountsChanged(n){n.length===0?this.onDisconnect():r.emitter.emit("change",{accounts:n.map(getAddress$1)});},onChainChanged(n){let c=Number(n);r.emitter.emit("change",{chainId:c});},async onDisconnect(){r.emitter.emit("disconnect"),s=false,t=void 0;},async getProvider({chainId:n}={}){t=impersonatedHelpers?.getImpersonated()?[impersonatedHelpers.getImpersonated()||zeroAddress]:void 0;let d=(r.chains.find(i=>i.id===n)??r.chains[0]).rpcUrls.default.http[0];return custom({request:async({method:i,params:p})=>{if(i==="eth_chainId")return numberToHex(e);if(i==="eth_requestAccounts")return t;if(i==="eth_signTypedData_v4"&&o.signTypedDataError)throw typeof o.signTypedDataError=="boolean"?new UserRejectedRequestError(new Error("Failed to sign typed data.")):o.signTypedDataError;if(i==="wallet_switchEthereumChain"){if(o.switchChainError)throw typeof o.switchChainError=="boolean"?new UserRejectedRequestError(new Error("Failed to switch chain.")):o.switchChainError;e=fromHex(p[0].chainId,"number"),this.onChainChanged(e.toString());return}if(i==="personal_sign"){if(o.signMessageError)throw typeof o.signMessageError=="boolean"?new UserRejectedRequestError(new Error("Failed to sign message.")):o.signMessageError;i="eth_sign",p=[p[1],p[0]];}let m={method:i,params:p},{error:u,result:y}=await rpc.http(d,{body:m});if(u)throw new RpcRequestError({body:m,error:u,url:d});return y}})({retryCount:1})}}))}var Ie={allowedDomains:[/gnosis-safe.io$/,/app.safe.global$/,/metissafe.tech$/],debug:false};var Ve=a=>a.reduce((o,s)=>{let e=s.id;return o[e]=http(),o},{});function We(a,o){let{wagmiConfig:s,siwe:e}=a,{activeConnection:t,disconnect:r,connectionError:n,updateActiveConnection:c}=o,d=()=>{e?.enabled&&!e?.isSignedIn&&e?.isRejected&&t&&r(t.connectorType);},h=p=>{if(t&&getAdapterFromConnectorType(t.connectorType)!==OrbitAdapter.EVM)return;if(p.length===0){t&&r(t.connectorType);return}let m=getConnection(s);if(t&&getAdapterFromConnectorType(t.connectorType)!==OrbitAdapter.EVM||!m||n)return;let u=m.connector,k={connectorType:u?`${OrbitAdapter.EVM}:${formatConnectorName(u.name)}`:t?.connectorType,address:m.address,chainId:m.chainId,rpcURL:m?.chain?.rpcUrls.default.http[0],isConnected:true};c(k);};return d(),watchConnections(s,{onChange:h})}export{b as checkIsWalletAddressContract,Ve as createDefaultTransports,We as createEVMConnectionsWatcher,S as impersonated,Ie as safeSdkOptions,Ce as satelliteEVMAdapter};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuwaio/satellite-evm",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Oleksandr Tkach",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -43,22 +43,22 @@
|
|
|
43
43
|
"immer": "11.x.x",
|
|
44
44
|
"zustand": "5.x.x",
|
|
45
45
|
"viem": "2.x.x",
|
|
46
|
-
"@tuwaio/orbit-core": ">=0.2.
|
|
47
|
-
"@tuwaio/orbit-evm": ">=0.2.
|
|
48
|
-
"@tuwaio/satellite-core": ">=0.3"
|
|
46
|
+
"@tuwaio/orbit-core": ">=0.2.8",
|
|
47
|
+
"@tuwaio/orbit-evm": ">=0.2.11",
|
|
48
|
+
"@tuwaio/satellite-core": ">=0.3.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@wagmi/core": "^3.4.
|
|
52
|
-
"@tuwaio/orbit-core": "^0.2.
|
|
53
|
-
"@tuwaio/orbit-evm": "^0.2.
|
|
54
|
-
"immer": "^11.1.
|
|
55
|
-
"jsdom": "^
|
|
51
|
+
"@wagmi/core": "^3.4.9",
|
|
52
|
+
"@tuwaio/orbit-core": "^0.2.8",
|
|
53
|
+
"@tuwaio/orbit-evm": "^0.2.12",
|
|
54
|
+
"immer": "^11.1.8",
|
|
55
|
+
"jsdom": "^29.1.1",
|
|
56
56
|
"tsup": "^8.5.1",
|
|
57
|
-
"typescript": "^
|
|
58
|
-
"viem": "^2.
|
|
59
|
-
"vitest": "^4.
|
|
60
|
-
"zustand": "^5.0.
|
|
61
|
-
"@tuwaio/satellite-core": "^0.3.
|
|
57
|
+
"typescript": "^6.0.3",
|
|
58
|
+
"viem": "^2.48.11",
|
|
59
|
+
"vitest": "^4.1.5",
|
|
60
|
+
"zustand": "^5.0.13",
|
|
61
|
+
"@tuwaio/satellite-core": "^0.3.3"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"start": "tsup src/index.ts --watch",
|