Your storage allowance automatically refills every 6 weeks. Your computer must be online with your wallet unlocked to complete the refill. If Sia fails to refill the allowance by the end of the lock-in period, your data may be lost.
*contract fees are non-refundable. They will be subtracted from the allowance that you set.
Allocated Funds
-
+
Number of Hosts
Contract Period
diff --git a/htdocs/js/index.js b/htdocs/js/index.js
index a22c616..3c66a7a 100644
--- a/htdocs/js/index.js
+++ b/htdocs/js/index.js
@@ -175,6 +175,9 @@
window.appActions.setRenterSettings(allowance, cb);
}
+ function _calculateEstimatedStorage(funds) {
+ return window.appActions.calculateEstimatedStorage(funds)
+ }
return {
createWallet: _createWallet,
mountDrive: _mountDrive,
@@ -183,7 +186,8 @@
unlockWallet: _unlockWallet,
unmountDrive: _unmountDrive,
shutdown: _shutdown,
- setRenterSettings: _setRenterSettings
+ setRenterSettings: _setRenterSettings,
+ calculateEstimatedStorage: _calculateEstimatedStorage
};
})();
@@ -269,8 +273,15 @@
function handleRenterEditSettings() {
setMainWindow('renter_settings_window');
+ const estStorage = document.getElementById('ID_RenterCalcStorage');
+ const funds = document.getElementById('ID_RenterSetFunds');
+ funds.oninput = () => {
+ estStorage.innerText = AppActions.calculateEstimatedStorage(funds.value);
+ };
+
const defaultsButton = document.getElementById('ID_RenterSettingsDefaults');
defaultsButton.onclick = ()=> {
+ funds.oninput = null;
const settings = UiState.defaultRenterSettings();
if (getValue('ID_RenterSetFunds') === '0') {
setValue('ID_RenterSetFunds', settings.Funds);
@@ -282,6 +293,7 @@
const cancelButton = document.getElementById('ID_RenterSettingsCancel');
cancelButton.onclick = ()=> {
+ funds.oninput = null;
saveButton.onclick = null;
cancelButton.onclick = null;
defaultsButton.onclick = null;
@@ -290,6 +302,7 @@
const saveButton = document.getElementById('ID_RenterSettingsOK');
saveButton.onclick = ()=> {
+ funds.oninput = null;
saveButton.onclick = null;
cancelButton.onclick = null;
defaultsButton.onclick = null;
diff --git a/include/siadrive_api/siaapi.h b/include/siadrive_api/siaapi.h
index b56387c..ea84bc5 100644
--- a/include/siadrive_api/siaapi.h
+++ b/include/siadrive_api/siaapi.h
@@ -176,6 +176,7 @@ public:
void Refresh(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig);
public:
+ CSiaError<_SiaApiErrorCode> CalculateEstimatedStorage(const SiaCurrency& funds, SiaCurrency& resultGb) const;
CSiaError<_SiaApiErrorCode> DownloadFile(const SString& siaPath, const SString& location) const;
CSiaError<_SiaApiErrorCode> FileExists(const SString& siaPath, bool& exists) const;
_SiaRenterAllowance GetAllowance() const;
@@ -205,6 +206,52 @@ public:
void Refresh(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig);
};
+ class SIADRIVE_EXPORTABLE _CSiaHost :
+ public virtual CSiaBase
+ {
+ friend CSiaApi;
+
+ private:
+ explicit _CSiaHost(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig, const json& hostJson);
+
+ public:
+ virtual ~_CSiaHost();
+
+ //Properties
+ Property(bool, AcceptingContracts, public, private)
+ Property(std::uint64_t, MaxDownloadBatchSize, public, private)
+ Property(std::uint64_t, MaxDuration, public, private)
+ Property(std::uint64_t, MaxReviseBatchSize, public, private)
+ Property(SString, NetAddress, public, private)
+ Property(std::uint64_t, RemainingStorage, public, private)
+ Property(std::uint64_t, SectorSize, public, private)
+ Property(std::uint64_t, TotalStorage, public, private)
+ Property(SString, UnlockHash, public, private)
+ Property(std::uint64_t, WindowSize, public, private)
+ Property(std::pair, PublicKey, public, private)
+ };
+
+ class SIADRIVE_EXPORTABLE _CSiaHostDb :
+ public virtual CSiaBase
+ {
+ friend CSiaApi;
+
+ private:
+ explicit _CSiaHostDb(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig);
+
+ public:
+ virtual ~_CSiaHostDb();
+
+ private:
+ std::shared_ptr>> _activeHosts;
+
+ private:
+ void Refresh(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig);
+
+ public:
+ std::shared_ptr>> GetActiveHosts() const;
+ };
+
public:
explicit CSiaApi(const SiaHostConfig& hostConfig, CSiaDriveConfig* siaDriveConfig);
@@ -217,7 +264,8 @@ private:
CSiaDriveConfig* _siaDriveConfig;
std::shared_ptr<_CSiaWallet> _wallet;
std::shared_ptr<_CSiaRenter> _renter;
- std::shared_ptr<_CSiaConsensus> _consensus;
+ std::shared_ptr<_CSiaConsensus> _consensus;
+ std::shared_ptr<_CSiaHostDb> _hostDb;
std::unique_ptr _refreshThread;
private:
@@ -229,7 +277,8 @@ public:
public:
std::shared_ptr<_CSiaWallet> GetWallet() const;
std::shared_ptr<_CSiaRenter> GetRenter() const;
- std::shared_ptr<_CSiaConsensus> GetConsensus() const;
+ std::shared_ptr<_CSiaConsensus> GetConsensus() const;
+ std::shared_ptr<_CSiaHostDb> GetHostDb() const;
SString GetServerVersion() const;
SiaHostConfig GetHostConfig() const;
};
@@ -241,9 +290,15 @@ typedef CSiaApi::_CSiaWallet CSiaWallet;
typedef CSiaApi::_CSiaRenter CSiaRenter;
typedef CSiaRenter::_SiaRenterAllowance SiaRenterAllowance;
typedef CSiaApi::_CSiaConsensus CSiaConsensus;
+typedef CSiaApi::_CSiaHostDb CSiaHostDb;
+typedef CSiaApi::_CSiaHost CSiaHost;
+typedef std::shared_ptr CSiaHostDbPtr;
typedef std::shared_ptr CSiaWalletPtr;
typedef std::shared_ptr CSiaRenterPtr;
typedef std::shared_ptr CSiaConsensusPtr;
+typedef std::shared_ptr CSiaHostPtr;
+typedef std::vector CSiaHostCollection;
+typedef std::shared_ptr CSiaHostCollectionPtr;
typedef CSiaApi::_CSiaFile CSiaFile;
typedef std::shared_ptr CSiaFilePtr;
typedef std::vector CSiaFileCollection;
diff --git a/include/siadrive_api/siacommon.h b/include/siadrive_api/siacommon.h
index 4fc624e..172d106 100644
--- a/include/siadrive_api/siacommon.h
+++ b/include/siadrive_api/siacommon.h
@@ -30,8 +30,8 @@
#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
// Windows 8.1 or above supported
- #define WINVER _WIN32_WINNT_WINBLUE
- #define _WIN32_WINNT _WIN32_WINNT_WINBLUE
+ #define WINVER _WIN32_WINNT_WIN7
+ #define _WIN32_WINNT _WIN32_WINNT_WIN7
#define _WINSOCKAPI_
#include
#include
@@ -68,6 +68,8 @@ using json = nlohmann::json;
#define NS_END(c) NS_END##c()
+#define COMMA ,
+
NS_BEGIN(Sia)
NS_BEGIN(Api)
@@ -87,7 +89,7 @@ typedef ttmath::Big<1, 30> SiaCurrency;
const std::uint8_t SIA_BLOCK_TIME_MINS = 10;
const std::uint32_t MINUTES_PER_MONTH = (730 * 60);
const std::uint32_t SIA_BLOCKS_PER_MONTH = MINUTES_PER_MONTH / SIA_BLOCK_TIME_MINS;
-const std::uint32_t SIA_DEFAULT_HOST_COUNT = 50;
+const std::uint32_t SIA_DEFAULT_HOST_COUNT = 24;
const std::uint32_t SIA_DEFAULT_RENEW_WINDOW = ((1440 / SIA_BLOCK_TIME_MINS) * 14);
const SiaCurrency SIA_DEFAULT_MINIMUM_FUNDS = 4000;
const std::uint32_t SIA_DEFAULT_CONTRACT_LENGTH = SIA_BLOCKS_PER_MONTH * 3;
@@ -131,7 +133,7 @@ public:
public:
Property(T, Code, public, private)
- Property(SString, Reason, public, private)
+ Property(SString, Reason, public, private)
public:
operator bool() { return GetCode() == T::Success; }
@@ -189,41 +191,16 @@ inline static SString SiaCurrencyToGB(const SiaCurrency& value)
return value.ToWString(conv);
}
-class IHost
+inline static Hastings SiaCurrencyToHastings(const SiaCurrency& currency)
{
-public:
- IHost() {}
- virtual ~IHost() {}
+ ttmath::Parser parser;
+ parser.Parse(currency.ToString() + " * (10 ^ 24)");
-public:
- virtual Hastings GetStoragePrice() const = 0;
- virtual Hastings GetDownloadPrice() const = 0;
- virtual Hastings GetUploadPrice() const = 0;
-};
-
-template
-inline static R CalculateAveragePrice(const std::vector& v, std::function PriceGetter)
-{
- R result = v.size() ? std::accumulate(std::next(v.begin()), v.end(), PriceGetter(v[0]), [&](const R& a, const T& b) {
- return a + PriceGetter(b);
- }).Div(v.size()) : 0;
-
- return result;
-}
-
-inline static Hastings CalculateAverageHostPrice(const std::vector& hosts)
-{
- return CalculateAveragePrice(hosts, [](const IHost& host)->Hastings { return host.GetStoragePrice(); });
-}
-
-inline static Hastings CalculateAverageDownloadPrice(const std::vector& hosts)
-{
- return CalculateAveragePrice(hosts, [](const IHost& host)->Hastings { return host.GetDownloadPrice(); });
-}
-
-inline static Hastings CalculateAverageUploadPrice(const std::vector& hosts)
-{
- return CalculateAveragePrice(hosts, [](const IHost& host)->Hastings { return host.GetUploadPrice(); });
+ ttmath::Conv conv;
+ conv.scient_from = 256;
+ conv.base = 10;
+ conv.round = 0;
+ return parser.stack[0].value.ToString(conv);
}
BOOL SIADRIVE_EXPORTABLE RetryAction(std::function func, std::uint16_t retryCount, const DWORD& retryDelay);
diff --git a/src/siadrive_api/siaapi.cpp b/src/siadrive_api/siaapi.cpp
index 331ef66..e144d3e 100644
--- a/src/siadrive_api/siaapi.cpp
+++ b/src/siadrive_api/siaapi.cpp
@@ -11,6 +11,7 @@ CSiaApi::CSiaApi(const SiaHostConfig& hostConfig, CSiaDriveConfig* siaDriveConfi
_wallet(new CSiaWallet(_siaCurl, siaDriveConfig)),
_renter(new CSiaRenter(_siaCurl, siaDriveConfig)),
_consensus(new CSiaConsensus(_siaCurl, siaDriveConfig)),
+ _hostDb(new CSiaHostDb(_siaCurl, siaDriveConfig)),
_refreshThread(new CAutoThread(_siaCurl, _siaDriveConfig, [this] (const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) { this->Refresh(siaCurl, siaDriveConfig); }))
{
_refreshThread->StartAutoThread();
@@ -28,6 +29,7 @@ void CSiaApi::Refresh(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig)
this->_wallet->Refresh(siaCurl, siaDriveConfig);
this->_consensus->Refresh(siaCurl, siaDriveConfig);
this->_renter->Refresh(siaCurl, siaDriveConfig);
+ this->_hostDb->Refresh(siaCurl, siaDriveConfig);
}
SString CSiaApi::FormatToSiaPath(SString path)
@@ -72,6 +74,11 @@ CSiaConsensusPtr CSiaApi::GetConsensus() const
return _consensus;
}
+CSiaHostDbPtr CSiaApi::GetHostDb() const
+{
+ return _hostDb;
+}
+
SiaHostConfig CSiaApi::GetHostConfig() const
{
return _hostConfig;
diff --git a/src/siadrive_api/siahost.cpp b/src/siadrive_api/siahost.cpp
new file mode 100644
index 0000000..c0fe707
--- /dev/null
+++ b/src/siadrive_api/siahost.cpp
@@ -0,0 +1,82 @@
+#include
+
+using namespace Sia::Api;
+/*
+{
+ // true if the host is accepting new contracts.
+ "acceptingcontracts": true,
+
+ // Maximum number of bytes that the host will allow to be requested by a
+ // single download request.
+ "maxdownloadbatchsize" : 17825792,
+
+ // Maximum duration in blocks that a host will allow for a file contract.
+ // The host commits to keeping files for the full duration under the
+ // threat of facing a large penalty for losing or dropping data before
+ // the duration is complete. The storage proof window of an incoming file
+ // contract must end before the current height + maxduration.
+ //
+ // There is a block approximately every 10 minutes.
+ // e.g. 1 day = 144 blocks
+ "maxduration": 25920,
+
+ // Maximum size in bytes of a single batch of file contract
+ // revisions. Larger batch sizes allow for higher throughput as there is
+ // significant communication overhead associated with performing a batch
+ // upload.
+ "maxrevisebatchsize": 17825792,
+
+ // Remote address of the host. It can be an IPv4, IPv6, or hostname,
+ // along with the port. IPv6 addresses are enclosed in square brackets.
+ "netaddress" : "123.456.789.0:9982",
+
+ // Unused storage capacity the host claims it has, in bytes.
+ "remainingstorage" : 35000000000,
+
+ // Smallest amount of data in bytes that can be uploaded or downloaded to
+ // or from the host.
+ "sectorsize" : 4194304,
+
+ // Total amount of storage capacity the host claims it has, in bytes.
+ "totalstorage" : 35000000000,
+
+ // Address at which the host can be paid when forming file contracts.
+ "unlockhash" : "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab",
+
+ // A storage proof window is the number of blocks that the host has to
+ // get a storage proof onto the blockchain. The window size is the
+ // minimum size of window that the host will accept in a file contract.
+ "windowsize" : 144,
+
+ // Public key used to identify and verify hosts.
+ "publickey" : {
+ // Algorithm used for signing and verification. Typically "ed25519".
+ "algorithm": "ed25519",
+
+ // Key used to verify signed host messages.
+ "key" : "RW50cm9weSBpc24ndCB3aGF0IGl0IHVzZWQgdG8gYmU="
+ }
+}
+*/
+
+CSiaApi::_CSiaHost::_CSiaHost(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig, const json& hostJson) :
+ CSiaBase(siaCurl, siaDriveConfig),
+ _AcceptingContracts(hostJson["acceptingcontracts"].get()),
+ _MaxDownloadBatchSize(hostJson["maxdownloadbatchsize"].get()),
+ _MaxDuration(hostJson["maxduration"].get()),
+ _MaxReviseBatchSize(hostJson["maxrevisebatchsize"].get()),
+ _NetAddress(hostJson["netaddress"].get()),
+ _RemainingStorage(hostJson["remainingstorage"].get()),
+ _SectorSize(hostJson["sectorsize"].get()),
+ _TotalStorage(hostJson["totalstorage"].get()),
+ _UnlockHash(hostJson["unlockhash"].get()),
+ _WindowSize(hostJson["windowsize"].get()),
+ _PublicKey({hostJson["publickey"]["algorithm"].get(), hostJson["publickey"]["key"].get()})
+{
+
+}
+
+CSiaApi::_CSiaHost::~_CSiaHost()
+{
+
+}
diff --git a/src/siadrive_api/siahostdb.cpp b/src/siadrive_api/siahostdb.cpp
new file mode 100644
index 0000000..81076d3
--- /dev/null
+++ b/src/siadrive_api/siahostdb.cpp
@@ -0,0 +1,33 @@
+#include
+
+using namespace Sia::Api;
+
+CSiaApi::_CSiaHostDb::_CSiaHostDb(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) :
+ CSiaBase(siaCurl, siaDriveConfig)
+{
+}
+
+CSiaApi::_CSiaHostDb::~_CSiaHostDb()
+{
+}
+
+void CSiaApi::_CSiaHostDb::Refresh(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig)
+{
+ CSiaHostCollectionPtr hostCollection(new CSiaHostCollection());
+ json result;
+ if (ApiSuccess(siaCurl.Get(L"/hostdb/active", result)))
+ {
+ auto hosts = result["hosts"];
+ for (const auto& host : hosts)
+ {
+ CSiaHostPtr hostPtr(new CSiaHost(siaCurl, siaDriveConfig, host));
+ hostCollection->push_back(hostPtr);
+ }
+ }
+ _activeHosts = hostCollection;
+}
+
+CSiaHostCollectionPtr CSiaApi::_CSiaHostDb::GetActiveHosts() const
+{
+ return _activeHosts;
+}
\ No newline at end of file
diff --git a/src/siadrive_api/siarenter.cpp b/src/siadrive_api/siarenter.cpp
index af5b384..d332fbc 100644
--- a/src/siadrive_api/siarenter.cpp
+++ b/src/siadrive_api/siarenter.cpp
@@ -223,5 +223,27 @@ SiaApiError CSiaApi::_CSiaRenter::SetAllowance(const SiaRenterAllowance& renterA
ret = { SiaApiErrorCode::RequestError, cerror.GetReason() };
}
+ return ret;
+}
+
+SiaApiError CSiaApi::_CSiaRenter::CalculateEstimatedStorage(const SiaCurrency& funds, SiaCurrency& resultGb) const
+{
+ SiaApiError ret;
+ json result;
+ SiaCurlError cerror = GetSiaCurl().Get(L"/renter/prices", {}, result);
+ if (ApiSuccess(cerror))
+ {
+ ret = { SiaApiErrorCode::RequestError, cerror.GetReason() };
+ }
+ else
+ {
+ Hastings fundsHastings = SiaCurrencyToHastings(funds);
+ ttmath::Parser parser;
+ parser.Parse(fundsHastings.ToString() + " / " + result["storageterabytemonth"].get() + " * 1000000000000");
+ resultGb = parser.stack[0].value;
+ }
+
+ //const estimate = new BigNumber(SiaAPI.siacoinsToHastings(action.funds)).dividedBy(response.storageterabytemonth).times(1e12)
+
return ret;
}
\ No newline at end of file