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 +```