diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/canine-docs.iml b/.idea/canine-docs.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/canine-docs.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..bd1f72a
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/developers/jackaljs/intro.md b/docs/developers/jackaljs/intro.md
index 1e49889..c55a18b 100644
--- a/docs/developers/jackaljs/intro.md
+++ b/docs/developers/jackaljs/intro.md
@@ -9,19 +9,32 @@ To get started using Jackal in the browser, you'll need a few things!
### Pre-requesites
-* [Node.js](https://nodejs.org/en/download)
+* [Vue.js](https://vuejs.org/guide/introduction.html) or [React](https://react.dev/learn)
* [Jackal.js](https://www.npmjs.com/package/jackal.js)
-* [Vite](https://vitejs.dev/)
-* [Keplr](https://www.keplr.app/)
+* [Vite](https://vitejs.dev)
+* Chromium-family browser (Chrome, Brave, Edge, etc)
+* [Keplr](https://www.keplr.app) or [Leap](https://www.leapwallet.io/cosmos) wallet extension
### Setting Up
-To get started, make sure you start your project using Vite. If you have an existing React app for example, re-init the project using Vite.
+To get started, make sure you [start your project using Vite](https://vitejs.dev/guide). If you have an existing React app for example, re-init the project using Vite.
+
+Install dependencies:
+```shell
+npm install jackal.js
+npm install -D vite-plugin-node-stdlib-browser
+```
+
+Jackal.js requires Node v20+. The easiest way to manage this is with [NVM](https://github.com/nvm-sh/nvm#installing-and-updating).
+```shell
+nvm use 20
+```
#### Updating Vite Config
```js
// In vite.config.js:
+import { defineConfig } from 'vite'
import nodePolyfills from 'vite-plugin-node-stdlib-browser'
export default defineConfig({
@@ -33,115 +46,216 @@ export default defineConfig({
### Connecting Your Wallet
+Custom chain configurations are required for [Testnet](#testnet-configuration), and for Keplr on [Mainnet](#mainnet-configuration). The following are the correct options to use.
+Jackal.js additionally supports app-level overrides to the chain default settings. This requires some redundancy, but allows for greater flexibility in projects.
+
+#### Wallet Selection
+
+Currently Jackal,js supports Keplr and Leap wallets. Only a single wallet can be used at any time, but you can switch between them as desired.
+
```js
-const chainConfig = { // mainnet chain config
- chainId: 'jackal-1',
- chainName: 'Jackal',
- rpc: 'https://rpc.jackalprotocol.com',
- rest: 'https://api.jackalprotocol.com',
- bip44: {
- coinType: 118
- },
- coinType: 118,
- stakeCurrency: {
+const selectedWallet = 'keplr'
+// OR
+const selectedWallet = 'leap'
+```
+
+#### Testnet Configuration
+
+```js
+const chainConfig = {
+ chainId: 'lupulella-2',
+ chainName: 'Jackal Testnet II',
+ rpc: 'https://testnet-rpc.jackalprotocol.com',
+ rest: 'https://testnet-api.jackalprotocol.com',
+ bip44: {
+ coinType: 118
+ },
+ coinType: 118,
+ stakeCurrency: {
+ coinDenom: 'JKL',
+ coinMinimalDenom: 'ujkl',
+ coinDecimals: 6
+ },
+ bech32Config: {
+ bech32PrefixAccAddr: 'jkl',
+ bech32PrefixAccPub: 'jklpub',
+ bech32PrefixValAddr: 'jklvaloper',
+ bech32PrefixValPub: 'jklvaloperpub',
+ bech32PrefixConsAddr: 'jklvalcons',
+ bech32PrefixConsPub: 'jklvalconspub'
+ },
+ currencies: [
+ {
coinDenom: 'JKL',
coinMinimalDenom: 'ujkl',
coinDecimals: 6
- },
- bech32Config: {
- bech32PrefixAccAddr: 'jkl',
- bech32PrefixAccPub: 'jklpub',
- bech32PrefixValAddr: 'jklvaloper',
- bech32PrefixValPub: 'jklvaloperpub',
- bech32PrefixConsAddr: 'jklvalcons',
- bech32PrefixConsPub: 'jklvalconspub'
- },
- currencies: [
- {
- coinDenom: 'JKL',
- coinMinimalDenom: 'ujkl',
- coinDecimals: 6
+ }
+ ],
+ feeCurrencies: [
+ {
+ coinDenom: 'JKL',
+ coinMinimalDenom: 'ujkl',
+ coinDecimals: 6,
+ gasPriceStep: {
+ low: 0.002,
+ average: 0.002,
+ high: 0.02
}
- ],
- feeCurrencies: [
- {
- coinDenom: 'JKL',
- coinMinimalDenom: 'ujkl',
- coinDecimals: 6,
- gasPriceStep: {
- low: 0.002,
- average: 0.002,
- high: 0.02
- }
- }
- ],
- features: []
+ }
+ ],
+ features: []
}
+```
-const walletConfig = {
- selectedWallet: 'keplr',
+```js
+const appConfig = {
+ signerChain: 'lupulella-2',
+ enabledChains: ['lupulella-2'],
+ queryAddr: 'https://testnet-grpc.jackalprotocol.com',
+ txAddr: 'https://testnet-rpc.jackalprotocol.com'
+}
+```
+
+#### Mainnet Configuration
+
+```js
+const chainConfig = {
+ chainId: 'jackal-1',
+ chainName: 'Jackal Mainnet',
+ rpc: 'https://rpc.jackalprotocol.com',
+ rest: 'https://api.jackalprotocol.com',
+ bip44: {
+ coinType: 118
+ },
+ coinType: 118,
+ stakeCurrency: {
+ coinDenom: 'JKL',
+ coinMinimalDenom: 'ujkl',
+ coinDecimals: 6
+ },
+ bech32Config: {
+ bech32PrefixAccAddr: 'jkl',
+ bech32PrefixAccPub: 'jklpub',
+ bech32PrefixValAddr: 'jklvaloper',
+ bech32PrefixValPub: 'jklvaloperpub',
+ bech32PrefixConsAddr: 'jklvalcons',
+ bech32PrefixConsPub: 'jklvalconspub'
+ },
+ currencies: [
+ {
+ coinDenom: 'JKL',
+ coinMinimalDenom: 'ujkl',
+ coinDecimals: 6
+ }
+ ],
+ feeCurrencies: [
+ {
+ coinDenom: 'JKL',
+ coinMinimalDenom: 'ujkl',
+ coinDecimals: 6,
+ gasPriceStep: {
+ low: 0.002,
+ average: 0.002,
+ high: 0.02
+ }
+ }
+ ],
+ features: []
+}
+```
+
+```js
+const appConfig = {
signerChain: 'jackal-1',
enabledChains: ['jackal-1'],
queryAddr: 'https://grpc.jackalprotocol.com',
- txAddr: 'https://rpc.jackalprotocol.com',
- chainConfig: chainConfig
+ txAddr: 'https://rpc.jackalprotocol.com'
+}
+```
+
+#### Bringing the full config together
+
+```js
+const finalWalletConfig = {
+ selectedWallet,
+ ...appConfig,
+ chainConfig
}
// Hooking up the wallet to your app
-const wallet = await WalletHandler.trackWallet(walletConfig)
+const wallet = await WalletHandler.trackWallet(finalWalletConfig)
+```
+Additionally, a query-only mode for the wallet can get accessed via the following:
+
+```js
+const wallet = await WalletHandler.trackQueryWallet('https://grpc.jackalprotocol.com') // Use the gRPC-web address of your choice
```
### Buying Storage Space
-Every account that wishes to use the Jackal Protocol to store data needs to have a paid account. This means giving the protocol $8/month/tb. We can do this with Jackal.js!
+Every account that wishes to use the Jackal Protocol to store data needs to have a paid storage account.
+This means giving the protocol $8 USD per month per tb. We can do this with Jackal.js!
```js
const storage = await StorageHandler.trackStorage(wallet)
-// (Wallet address, duration in hours (min 720),
-// space in bytes (min 1000000000)
-await storage.buyStorage(WALLET_ADDRESS, 720, 1000000000000)
+// (Wallet address, duration in months (min 1),
+// space in terabytes (min .001)
+
+// 2 TB for 1 year:
+await storage.buyStorage(WALLET_ADDRESS, 12, 2)
```
-### Creating a Folder
+### Creating a Root Folder
```js
const fileIo = await FileIo.trackIo(wallet)
-const listOfFolders = ["folder_name", ...]
-// you can create as many folders as you would like this way
+const listOfRootFolders = ["Home", ...]
+// you can create as many root folders as you would like this way. Home is the dashboard default root directory.
// The first time a user connects, they must init the system
const storage = await StorageHandler.trackStorage(wallet)
const msg = storage.makeStorageInitMsg()
-await fileIo.generateInitialDirs(msg, listOfFolders)
+await fileIo.generateInitialDirs(msg, listOfRootFolders)
-// after the first time, this code can be used instead. this will only create new folders if they don't already exist
-const newFolderCount = await fileIo.verifyFoldersExist(listOfFolders)
+// after the first time, this code can be used instead. this will only create new root folders if they don't already exist
+const newFolderCount = await fileIo.verifyFoldersExist(listOfRootFolders)
```
+### Creating a Child Folder
+
+```js
+const fileIo = await FileIo.trackIo(wallet)
+
+const parentFolderPath = PARENT_FOLDER_NAME // for example Dashboard's root folder path is s/Home
+const parent = await fileIo.downloadFolder(parentFolderPath)
+
+const listOfChildFolders = ["Movies", "Pictures", ...]
+
+await fileIo.createFolders(parent, listOfChildFolders)
+```
### Uploading a File
```js
const fileIo = await FileIo.trackIo(wallet)
-const parentFolderPath = PARENT_FOLDER_NAME // replace this with your own path
-const fileName = FILE_NAME // replace this with your own file name
-
-const handler = await FileUploadHandler.trackFile(FILE_OBJECT, parentFolderPath)
-
+const parentFolderPath = PARENT_FOLDER_NAME // for example Dashboard's root folder path is s/Home
const parent = await fileIo.downloadFolder(parentFolderPath)
-const uploadList = {
- fileName: {
- data: null,
- exists: false,
- handler: handler,
- key: fileName,
- uploadable: await handler.getForUpload()
- }
+const file = FILE_OBJECT // this MUST be an instance of File() that is in the browser memory
+const fileName = file.name
+const handler = await FileUploadHandler.trackFile(file, parentFolderPath)
+
+const uploadList = {}
+uploadList[fileName] = {
+ data: null,
+ exists: false,
+ handler: handler,
+ key: fileName,
+ uploadable: await handler.getForUpload()
}
await fileIo.staggeredUploadFiles(uploadList, parent, {counter: 0, complete: 0})
@@ -152,17 +266,21 @@ await fileIo.staggeredUploadFiles(uploadList, parent, {counter: 0, complete: 0})
```js
const fileIo = await FileIo.trackIo(wallet)
-const file = await fileIo.downloadFile(
- {
- rawPath: FILE_PATH
- owner: OWNER_ADDRESS
- isFolder: false
- },
- {
- track: 0
- }
-)
+/* optional */
+const parentFolderPath = PARENT_FOLDER_NAME // for example Dashboard's root folder path is s/Home
+const parent = await fileIo.downloadFolder(parentFolderPath)
+const childrenFiles = parent.getChildFiles()
+const pathOfFirstChild = parent.getMyChildPath(childrenFiles[0].name)
+/* end optional */
-const fileData = file.receiveBacon()
+const downloadDetails = {
+ rawPath: FILE_PATH, // manual complete file path OR pathOfFirstChild
+ owner: OWNER_ADDRESS, // JKL address of file owner
+ isFolder: false
+}
+
+const fileHanlder = await fileIo.downloadFile(downloadDetails, { track: 0 })
+
+const file = fileHanlder.receiveBacon()
// do what you want with the File object returned by receiveBacon
-```
\ No newline at end of file
+```